summaryrefslogtreecommitdiffstats
path: root/printing/emf_win.cc
diff options
context:
space:
mode:
authorvitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-22 00:10:07 +0000
committervitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-22 00:10:07 +0000
commit60d77bde7e6aac08a05b00ce2b82f94144934965 (patch)
treee259f3205b1017c549b87e08497ad4172f990bdd /printing/emf_win.cc
parentf26c77082295b9fc277cd7a5eb75cdf0edee1bbb (diff)
downloadchromium_src-60d77bde7e6aac08a05b00ce2b82f94144934965.zip
chromium_src-60d77bde7e6aac08a05b00ce2b82f94144934965.tar.gz
chromium_src-60d77bde7e6aac08a05b00ce2b82f94144934965.tar.bz2
Some printers has issue with metafiles produces from PDF so added switch and about:flag as workaround for affected users.
Rasterisation is implemented and RasterizeMetafile function. It replace metafile with new one where content is only bitmap created by playback of original metafile. FlattenTransparency replaced with full rasterisation. Fixed rectangle returned by Emf::GetPageBounds. Removed SkDevice::AlphaBlendUsed(). Removed return value from PrintWebViewHelper::RenderPage on windows. BUG=133527 Review URL: https://chromiumcodereview.appspot.com/10836330 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152681 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing/emf_win.cc')
-rw-r--r--printing/emf_win.cc109
1 files changed, 98 insertions, 11 deletions
diff --git a/printing/emf_win.cc b/printing/emf_win.cc
index 3634cbd..a5d4c02 100644
--- a/printing/emf_win.cc
+++ b/printing/emf_win.cc
@@ -7,6 +7,9 @@
#include "base/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_gdi_object.h"
+#include "base/win/scoped_hdc.h"
+#include "base/win/scoped_select_object.h"
#include "skia/ext/vector_platform_device_emf_win.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
@@ -16,6 +19,7 @@
#include "ui/gfx/size.h"
namespace {
+
const int kCustomGdiCommentSignature = 0xdeadbabe;
struct PageBreakRecord {
int signature;
@@ -31,8 +35,27 @@ struct PageBreakRecord {
(type >= START_PAGE) && (type <= END_PAGE);
}
};
+
+int CALLBACK IsAlphaBlendUsedEnumProc(HDC,
+ HANDLETABLE*,
+ const ENHMETARECORD *record,
+ int,
+ LPARAM data) {
+ bool* result = reinterpret_cast<bool*>(data);
+ if (!result)
+ return 0;
+ switch (record->iType) {
+ case EMR_ALPHABLEND: {
+ *result = true;
+ return 0;
+ break;
+ }
+ }
+ return 1;
}
+} // namespace
+
namespace printing {
bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits,
@@ -126,19 +149,12 @@ gfx::Rect Emf::GetPageBounds(unsigned int page_number) const {
NOTREACHED();
return gfx::Rect();
}
- if (header.rclBounds.left == 0 &&
- header.rclBounds.top == 0 &&
- header.rclBounds.right == -1 &&
- header.rclBounds.bottom == -1) {
- // A freshly created EMF buffer that has no drawing operation has invalid
- // bounds. Instead of having an (0,0) size, it has a (-1,-1) size. Detect
- // this special case and returns an empty Rect instead of an invalid one.
- return gfx::Rect();
- }
+ // Add 1 to right and bottom because it's inclusive rectangle.
+ // See ENHMETAHEADER.
return gfx::Rect(header.rclBounds.left,
header.rclBounds.top,
- header.rclBounds.right - header.rclBounds.left,
- header.rclBounds.bottom - header.rclBounds.top);
+ header.rclBounds.right - header.rclBounds.left + 1,
+ header.rclBounds.bottom - header.rclBounds.top + 1);
}
uint32 Emf::GetDataSize() const {
@@ -478,4 +494,75 @@ int CALLBACK Emf::Enumerator::EnhMetaFileProc(HDC hdc,
return 1;
}
+bool Emf::IsAlphaBlendUsed() const {
+ bool result = false;
+ ::EnumEnhMetaFile(NULL,
+ emf(),
+ &IsAlphaBlendUsedEnumProc,
+ &result,
+ NULL);
+ return result;
+}
+
+Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
+ gfx::Rect page_bounds = GetPageBounds(1);
+ gfx::Size page_size(page_bounds.size());
+ if (page_size.GetArea() <= 0) {
+ NOTREACHED() << "Metafile is empty";
+ page_bounds = gfx::Rect(1, 1);
+ }
+
+ float scale = sqrt(float(raster_area_in_pixels) / page_size.GetArea());
+ 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);
+
+ gfx::Rect bitmap_rect(page_size);
+ Playback(bitmap_dc, &bitmap_rect.ToRECT());
+
+ scoped_ptr<Emf> result(new Emf);
+ result->Init();
+ HDC hdc = result->context();
+ DCHECK(hdc);
+ skia::InitializeDC(hdc);
+
+ // Params are ignored.
+ result->StartPage(page_bounds.size(), page_bounds, 1);
+
+ ::ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
+ XFORM xform = {
+ float(page_bounds.width()) / bitmap_rect.width(), 0,
+ 0, float(page_bounds.height()) / bitmap_rect.height(),
+ page_bounds.x(),
+ page_bounds.y(),
+ };
+ ::SetWorldTransform(hdc, &xform);
+ ::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(),
+ bitmap_dc, bitmap_rect.x(), bitmap_rect.y(), SRCCOPY);
+
+ result->FinishPage();
+ result->FinishDocument();
+
+ return result.release();
+}
+
} // namespace printing