Restored partial rasterization for AlphaBlend.
Fixed incorect transformation in RasterizeAlphaBlendProc. BUG=152204 Review URL: https://chromiumcodereview.appspot.com/11078018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161713 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -260,12 +260,9 @@ void PrintViewManager::OnDidPrintPage(
|
||||
#if defined(OS_WIN)
|
||||
bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize);
|
||||
const CommandLine* cmdline = CommandLine::ForCurrentProcess();
|
||||
if (big_emf ||
|
||||
(cmdline && cmdline->HasSwitch(switches::kPrintRaster)) ||
|
||||
(!print_job_->settings().supports_alpha_blend() &&
|
||||
metafile->IsAlphaBlendUsed())) {
|
||||
int raster_size = std::min(params.page_size.GetArea(),
|
||||
kMaxRasterSizeInPixels);
|
||||
int raster_size = std::min(params.page_size.GetArea(),
|
||||
kMaxRasterSizeInPixels);
|
||||
if (big_emf || (cmdline && cmdline->HasSwitch(switches::kPrintRaster))) {
|
||||
scoped_ptr<NativeMetafile> raster_metafile(
|
||||
metafile->RasterizeMetafile(raster_size));
|
||||
if (raster_metafile.get()) {
|
||||
@ -277,6 +274,12 @@ void PrintViewManager::OnDidPrintPage(
|
||||
web_contents()->Stop();
|
||||
return;
|
||||
}
|
||||
} else if (!print_job_->settings().supports_alpha_blend() &&
|
||||
metafile->IsAlphaBlendUsed()) {
|
||||
scoped_ptr<NativeMetafile> raster_metafile(
|
||||
metafile->RasterizeAlphaBlend());
|
||||
if (raster_metafile.get())
|
||||
metafile.swap(raster_metafile);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -54,6 +54,101 @@ int CALLBACK IsAlphaBlendUsedEnumProc(HDC,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CALLBACK RasterizeAlphaBlendProc(HDC metafile_dc,
|
||||
HANDLETABLE* handle_table,
|
||||
const ENHMETARECORD *record,
|
||||
int num_objects,
|
||||
LPARAM data) {
|
||||
HDC bitmap_dc = *reinterpret_cast<HDC*>(data);
|
||||
// Play this command to the bitmap DC.
|
||||
::PlayEnhMetaFileRecord(bitmap_dc, handle_table, record, num_objects);
|
||||
switch (record->iType) {
|
||||
case EMR_ALPHABLEND: {
|
||||
const EMRALPHABLEND* alpha_blend =
|
||||
reinterpret_cast<const EMRALPHABLEND*>(record);
|
||||
// Don't modify transformation here.
|
||||
// Old implementation did reset transformations for DC to identity matrix.
|
||||
// That was not correct and cause some bugs, like unexpected cropping.
|
||||
// EMRALPHABLEND is rendered into bitmap and metafile contexts with
|
||||
// current transformation. If we don't touch them here BitBlt will copy
|
||||
// same areas.
|
||||
::BitBlt(metafile_dc,
|
||||
alpha_blend->xDest,
|
||||
alpha_blend->yDest,
|
||||
alpha_blend->cxDest,
|
||||
alpha_blend->cyDest,
|
||||
bitmap_dc,
|
||||
alpha_blend->xDest,
|
||||
alpha_blend->yDest,
|
||||
SRCCOPY);
|
||||
break;
|
||||
}
|
||||
case EMR_CREATEBRUSHINDIRECT:
|
||||
case EMR_CREATECOLORSPACE:
|
||||
case EMR_CREATECOLORSPACEW:
|
||||
case EMR_CREATEDIBPATTERNBRUSHPT:
|
||||
case EMR_CREATEMONOBRUSH:
|
||||
case EMR_CREATEPALETTE:
|
||||
case EMR_CREATEPEN:
|
||||
case EMR_DELETECOLORSPACE:
|
||||
case EMR_DELETEOBJECT:
|
||||
case EMR_EXTCREATEFONTINDIRECTW:
|
||||
// Play object creation command only once.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Play this command to the metafile DC.
|
||||
::PlayEnhMetaFileRecord(metafile_dc, handle_table, record, num_objects);
|
||||
break;
|
||||
}
|
||||
return 1; // Continue enumeration
|
||||
}
|
||||
|
||||
// Bitmapt for rasterization.
|
||||
class RasterBitmap {
|
||||
public:
|
||||
explicit RasterBitmap(const gfx::Size& raster_size)
|
||||
: saved_object_(NULL) {
|
||||
context_.Set(::CreateCompatibleDC(NULL));
|
||||
if (!context_) {
|
||||
NOTREACHED() << "Bitmap DC creation failed";
|
||||
return;
|
||||
}
|
||||
::SetGraphicsMode(context_, GM_ADVANCED);
|
||||
void* bits = NULL;
|
||||
gfx::Rect bitmap_rect(raster_size);
|
||||
gfx::CreateBitmapHeader(raster_size.width(), raster_size.height(),
|
||||
&header_.bmiHeader);
|
||||
bitmap_.Set(::CreateDIBSection(context_, &header_, DIB_RGB_COLORS, &bits,
|
||||
NULL, 0));
|
||||
if (!bitmap_)
|
||||
NOTREACHED() << "Raster bitmap creation for printing failed";
|
||||
|
||||
saved_object_ = ::SelectObject(context_, bitmap_);
|
||||
::FillRect(context_, &bitmap_rect.ToRECT(),
|
||||
static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)));
|
||||
|
||||
}
|
||||
|
||||
~RasterBitmap() {
|
||||
::SelectObject(context_, saved_object_);
|
||||
}
|
||||
|
||||
HDC context() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
base::win::ScopedCreateDC context_;
|
||||
BITMAPINFO header_;
|
||||
base::win::ScopedBitmap bitmap_;
|
||||
HGDIOBJ saved_object_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RasterBitmap);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace printing {
|
||||
@ -516,28 +611,11 @@ Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
|
||||
page_size.set_width(std::max<int>(1, page_size.width() * scale));
|
||||
page_size.set_height(std::max<int>(1, page_size.height() * scale));
|
||||
|
||||
base::win::ScopedCreateDC bitmap_dc(::CreateCompatibleDC(NULL));
|
||||
if (!bitmap_dc) {
|
||||
NOTREACHED() << "Bitmap DC creation failed";
|
||||
return NULL;
|
||||
}
|
||||
::SetGraphicsMode(bitmap_dc, GM_ADVANCED);
|
||||
void* bits = NULL;
|
||||
BITMAPINFO hdr;
|
||||
gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
|
||||
&hdr.bmiHeader);
|
||||
base::win::ScopedBitmap hbitmap(CreateDIBSection(
|
||||
bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
|
||||
if (!hbitmap)
|
||||
NOTREACHED() << "Raster bitmap creation for printing failed";
|
||||
|
||||
base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap);
|
||||
RECT rect = { 0, 0, page_size.width(), page_size.height() };
|
||||
HBRUSH white_brush = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
|
||||
FillRect(bitmap_dc, &rect, white_brush);
|
||||
RasterBitmap bitmap(page_size);
|
||||
|
||||
gfx::Rect bitmap_rect(page_size);
|
||||
Playback(bitmap_dc, &bitmap_rect.ToRECT());
|
||||
Playback(bitmap.context(), &bitmap_rect.ToRECT());
|
||||
|
||||
scoped_ptr<Emf> result(new Emf);
|
||||
result->Init();
|
||||
@ -557,7 +635,7 @@ Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
|
||||
};
|
||||
::SetWorldTransform(hdc, &xform);
|
||||
::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(),
|
||||
bitmap_dc, bitmap_rect.x(), bitmap_rect.y(), SRCCOPY);
|
||||
bitmap.context(), bitmap_rect.x(), bitmap_rect.y(), SRCCOPY);
|
||||
|
||||
result->FinishPage();
|
||||
result->FinishDocument();
|
||||
@ -565,4 +643,33 @@ Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
|
||||
return result.release();
|
||||
}
|
||||
|
||||
Emf* Emf::RasterizeAlphaBlend() const {
|
||||
gfx::Rect page_bounds = GetPageBounds(1);
|
||||
if (page_bounds.size().GetArea() <= 0) {
|
||||
NOTREACHED() << "Metafile is empty";
|
||||
page_bounds = gfx::Rect(1, 1);
|
||||
}
|
||||
|
||||
RasterBitmap bitmap(page_bounds.size());
|
||||
|
||||
// Map metafile page_bounds.x(), page_bounds.y() to bitmap 0, 0.
|
||||
XFORM xform = { 1, 0, 0, 1, -page_bounds.x(), -page_bounds.y()};
|
||||
::SetWorldTransform(bitmap.context(), &xform);
|
||||
|
||||
scoped_ptr<Emf> result(new Emf);
|
||||
result->Init();
|
||||
HDC hdc = result->context();
|
||||
DCHECK(hdc);
|
||||
skia::InitializeDC(hdc);
|
||||
|
||||
HDC bitmap_dc = bitmap.context();
|
||||
::EnumEnhMetaFile(hdc, emf(), &RasterizeAlphaBlendProc, &bitmap_dc,
|
||||
&page_bounds.ToRECT());
|
||||
|
||||
result->FinishDocument();
|
||||
|
||||
return result.release();
|
||||
}
|
||||
|
||||
|
||||
} // namespace printing
|
||||
|
@ -98,6 +98,10 @@ class PRINTING_EXPORT Emf : public Metafile {
|
||||
// metafile. Returns NULL if fails.
|
||||
Emf* RasterizeMetafile(int raster_area_in_pixels) const;
|
||||
|
||||
// Returns new metafile where AlphaBlend replaced by bitmaps. Returns NULL
|
||||
// if fails.
|
||||
Emf* RasterizeAlphaBlend() const;
|
||||
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(EmfTest, DC);
|
||||
FRIEND_TEST_ALL_PREFIXES(EmfPrintingTest, PageBreak);
|
||||
|
Reference in New Issue
Block a user