0

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:
vitalybuka@chromium.org
2012-10-13 04:50:06 +00:00
parent 8339379dbd
commit 64f5f92073
3 changed files with 140 additions and 26 deletions
chrome/browser/printing
printing

@ -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);