summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/render_message_filter.cc1
-rw-r--r--chrome/common/render_messages_params.cc13
-rw-r--r--chrome/common/render_messages_params.h5
-rw-r--r--chrome/renderer/print_web_view_helper_win.cc102
-rw-r--r--printing/emf_win.cc2
-rw-r--r--printing/print_settings.cc4
-rw-r--r--printing/print_settings.h7
-rw-r--r--printing/print_settings_initializer_win.cc3
-rw-r--r--skia/ext/vector_platform_device_win.cc5
-rw-r--r--skia/ext/vector_platform_device_win.h4
10 files changed, 134 insertions, 12 deletions
diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc
index 73af165..a0696b5 100644
--- a/chrome/browser/renderer_host/render_message_filter.cc
+++ b/chrome/browser/renderer_host/render_message_filter.cc
@@ -162,6 +162,7 @@ void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
// Always use an invalid cookie.
params->document_cookie = 0;
params->selection_only = settings.selection_only;
+ params->supports_alpha_blend = settings.supports_alpha_blend();
}
class ClearCacheCompletion : public net::CompletionCallback {
diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc
index 7fab193..a05266c 100644
--- a/chrome/common/render_messages_params.cc
+++ b/chrome/common/render_messages_params.cc
@@ -81,7 +81,8 @@ ViewMsg_Print_Params::ViewMsg_Print_Params()
max_shrink(0),
desired_dpi(0),
document_cookie(0),
- selection_only(false) {
+ selection_only(false),
+ supports_alpha_blend(true) {
}
ViewMsg_Print_Params::~ViewMsg_Print_Params() {
@@ -96,13 +97,15 @@ bool ViewMsg_Print_Params::Equals(const ViewMsg_Print_Params& rhs) const {
min_shrink == rhs.min_shrink &&
max_shrink == rhs.max_shrink &&
desired_dpi == rhs.desired_dpi &&
- selection_only == rhs.selection_only;
+ selection_only == rhs.selection_only &&
+ supports_alpha_blend == rhs.supports_alpha_blend;
}
bool ViewMsg_Print_Params::IsEmpty() const {
return !document_cookie && !desired_dpi && !max_shrink && !min_shrink &&
!dpi && printable_size.IsEmpty() && !selection_only &&
- page_size.IsEmpty() && !margin_top && !margin_left;
+ page_size.IsEmpty() && !margin_top && !margin_left &&
+ !supports_alpha_blend;
}
ViewMsg_PrintPage_Params::ViewMsg_PrintPage_Params()
@@ -952,6 +955,7 @@ void ParamTraits<ViewMsg_Print_Params>::Write(Message* m, const param_type& p) {
WriteParam(m, p.desired_dpi);
WriteParam(m, p.document_cookie);
WriteParam(m, p.selection_only);
+ WriteParam(m, p.supports_alpha_blend);
}
bool ParamTraits<ViewMsg_Print_Params>::Read(const Message* m,
@@ -966,7 +970,8 @@ bool ParamTraits<ViewMsg_Print_Params>::Read(const Message* m,
ReadParam(m, iter, &p->max_shrink) &&
ReadParam(m, iter, &p->desired_dpi) &&
ReadParam(m, iter, &p->document_cookie) &&
- ReadParam(m, iter, &p->selection_only);
+ ReadParam(m, iter, &p->selection_only) &&
+ ReadParam(m, iter, &p->supports_alpha_blend);
}
void ParamTraits<ViewMsg_Print_Params>::Log(const param_type& p,
diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h
index 97817d2..0523fdf 100644
--- a/chrome/common/render_messages_params.h
+++ b/chrome/common/render_messages_params.h
@@ -520,6 +520,9 @@ struct ViewMsg_Print_Params {
// Should only print currently selected text.
bool selection_only;
+ // Does the printer support alpha blending?
+ bool supports_alpha_blend;
+
// Warning: do not compare document_cookie.
bool Equals(const ViewMsg_Print_Params& rhs) const;
@@ -552,7 +555,7 @@ struct ViewMsg_PrintPages_Params {
std::vector<int> pages;
};
-//Parameters to describe a rendered document.
+// Parameters to describe a rendered document.
struct ViewHostMsg_DidPreviewDocument_Params {
ViewHostMsg_DidPreviewDocument_Params();
~ViewHostMsg_DidPreviewDocument_Params();
diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc
index bd1e595..22c6e00 100644
--- a/chrome/renderer/print_web_view_helper_win.cc
+++ b/chrome/renderer/print_web_view_helper_win.cc
@@ -8,11 +8,13 @@
#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
#include "chrome/renderer/render_view.h"
+#include "gfx/gdi_util.h"
#include "gfx/size.h"
#include "grit/generated_resources.h"
#include "printing/native_metafile.h"
#include "printing/units.h"
#include "skia/ext/vector_canvas.h"
+#include "skia/ext/vector_platform_device.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
using printing::ConvertUnitDouble;
@@ -20,6 +22,46 @@ using printing::kPointsPerInch;
using WebKit::WebFrame;
using WebKit::WebString;
+int CALLBACK EnhMetaFileProc(HDC 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);
+ if (record->iType == EMR_ALPHABLEND) {
+ const EMRALPHABLEND* emr_alpha_blend =
+ reinterpret_cast<const EMRALPHABLEND*>(record);
+ XFORM bitmap_dc_transform, metafile_dc_transform;
+ XFORM identity = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
+ // Temporarily set the world transforms of both DC's to identity.
+ GetWorldTransform(dc, &metafile_dc_transform);
+ SetWorldTransform(dc, &identity);
+ GetWorldTransform(*bitmap_dc, &bitmap_dc_transform);
+ SetWorldTransform(*bitmap_dc, &identity);
+ const RECTL& rect = emr_alpha_blend->rclBounds;
+ // Since the printer does not support alpha blend, copy the alpha blended
+ // region from our (software-rendered) bitmap DC to the metafile DC.
+ BitBlt(dc,
+ rect.left,
+ rect.top,
+ rect.right - rect.left + 1,
+ rect.bottom - rect.top + 1,
+ *bitmap_dc,
+ rect.left,
+ rect.top,
+ SRCCOPY);
+ // Restore the world transforms of both DC's.
+ SetWorldTransform(dc, &metafile_dc_transform);
+ SetWorldTransform(*bitmap_dc, &bitmap_dc_transform);
+ } else {
+ // Play this command to the metafile DC.
+ PlayEnhMetaFileRecord(dc, handle_table, record, num_objects);
+ }
+ return 1; // Continue enumeration
+}
+
void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
WebFrame* frame) {
@@ -64,8 +106,8 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
// Mix of Skia and GDI based.
skia::PlatformCanvas canvas(size_x, size_y, true);
- canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
- float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
+ canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
+ float webkit_shrink = frame->printPage(params.page_number, &canvas);
if (shrink <= 0 || webkit_shrink <= 0) {
NOTREACHED() << "Printing page " << params.page_number << " failed.";
} else {
@@ -105,9 +147,59 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
if (!metafile.CloseDc()) {
NOTREACHED() << "metafile failed";
}
+ printing::NativeMetafile* mf = &metafile;
+ printing::NativeMetafile metafile2;
+
+ skia::VectorPlatformDevice* platform_device =
+ static_cast<skia::VectorPlatformDevice*>(canvas.getDevice());
+ if (platform_device->alpha_blend_used() &&
+ !params.params.supports_alpha_blend) {
+ // Page used alpha blend, but printer doesn't support it. Rewrite the
+ // metafile and flatten out the transparency.
+ HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL));
+ if (!bitmap_dc) {
+ NOTREACHED() << "Bitmap DC creation failed";
+ }
+ SetGraphicsMode(bitmap_dc, GM_ADVANCED);
+ void* bits = NULL;
+ BITMAPINFO hdr;
+ gfx::CreateBitmapHeader(size_x, size_y, &hdr.bmiHeader);
+ HBITMAP hbitmap = CreateDIBSection(
+ bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0);
+ if (!hbitmap) {
+ NOTREACHED() << "Raster bitmap creation for printing failed";
+ }
+
+ HGDIOBJ old_bitmap = SelectObject(bitmap_dc, hbitmap);
+ RECT rect = {0, 0, size_x, size_y };
+ HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
+ FillRect(bitmap_dc, &rect, whiteBrush);
+
+ metafile2.CreateDc(NULL, NULL);
+ HDC hdc = metafile2.hdc();
+ DCHECK(hdc);
+ skia::PlatformDevice::InitializeDC(hdc);
+
+ RECT metafile_bounds = metafile.GetBounds().ToRECT();
+ // Process the old metafile, placing all non-AlphaBlend calls into the
+ // new metafile, and copying the results of all the AlphaBlend calls
+ // from the bitmap DC.
+ EnumEnhMetaFile(hdc,
+ metafile.emf(),
+ EnhMetaFileProc,
+ &bitmap_dc,
+ &metafile_bounds);
+
+ SelectObject(bitmap_dc, old_bitmap);
+
+ if (!metafile2.CloseDc()) {
+ NOTREACHED() << "metafile failed";
+ }
+ mf = &metafile2;
+ }
// Get the size of the compiled metafile.
- uint32 buf_size = metafile.GetDataSize();
+ uint32 buf_size = mf->GetDataSize();
DCHECK_GT(buf_size, 128u);
ViewHostMsg_DidPrintPage_Params page_params;
page_params.data_size = 0;
@@ -144,7 +236,7 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
// Allocate a shared memory buffer to hold the generated metafile data.
if (shared_buf.CreateAndMapAnonymous(buf_size)) {
// Copy the bits into shared memory.
- if (metafile.GetData(shared_buf.memory(), buf_size)) {
+ if (mf->GetData(shared_buf.memory(), buf_size)) {
page_params.metafile_data_handle = shared_buf.handle();
page_params.data_size = buf_size;
} else {
@@ -157,7 +249,7 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
} else {
NOTREACHED() << "Buffer too large: " << buf_size;
}
- metafile.CloseEmf();
+ mf->CloseEmf();
if (Send(new ViewHostMsg_DuplicateSection(
routing_id(),
page_params.metafile_data_handle,
diff --git a/printing/emf_win.cc b/printing/emf_win.cc
index 9629bb2..5de962b 100644
--- a/printing/emf_win.cc
+++ b/printing/emf_win.cc
@@ -396,6 +396,8 @@ bool Emf::Record::SafePlayback(const XFORM* base_matrix) const {
} else {
res = Play();
}
+ } else {
+ res = true;
}
break;
}
diff --git a/printing/print_settings.cc b/printing/print_settings.cc
index cf8c50a..3f0f842 100644
--- a/printing/print_settings.cc
+++ b/printing/print_settings.cc
@@ -19,7 +19,8 @@ PrintSettings::PrintSettings()
selection_only(false),
use_overlays(true),
dpi_(0),
- landscape_(false) {
+ landscape_(false),
+ supports_alpha_blend_(true) {
}
PrintSettings::~PrintSettings() {
@@ -36,6 +37,7 @@ void PrintSettings::Clear() {
page_setup_device_units_.Clear();
dpi_ = 0;
landscape_ = false;
+ supports_alpha_blend_ = true;
}
void PrintSettings::SetPrinterPrintableArea(
diff --git a/printing/print_settings.h b/printing/print_settings.h
index bc9cbaf..298fcd2 100644
--- a/printing/print_settings.h
+++ b/printing/print_settings.h
@@ -42,6 +42,10 @@ class PrintSettings {
const std::wstring& device_name() const { return device_name_; }
void set_dpi(int dpi) { dpi_ = dpi; }
int dpi() const { return dpi_; }
+ void set_supports_alpha_blend(bool supports_alpha_blend) {
+ supports_alpha_blend_ = supports_alpha_blend;
+ }
+ bool supports_alpha_blend() const { return supports_alpha_blend_; }
const PageSetup& page_setup_device_units() const {
return page_setup_device_units_;
}
@@ -108,6 +112,9 @@ class PrintSettings {
// Is the orientation landscape or portrait.
bool landscape_;
+
+ // True if this printer supports AlphaBlend.
+ bool supports_alpha_blend_;
};
} // namespace printing
diff --git a/printing/print_settings_initializer_win.cc b/printing/print_settings_initializer_win.cc
index f840f4d..065a8db 100644
--- a/printing/print_settings_initializer_win.cc
+++ b/printing/print_settings_initializer_win.cc
@@ -29,6 +29,9 @@ void PrintSettingsInitializerWin::InitPrintSettings(
int dpi = GetDeviceCaps(hdc, LOGPIXELSX);
print_settings->set_dpi(dpi);
+ const int kAlphaCaps = SB_CONST_ALPHA | SB_PIXEL_ALPHA;
+ print_settings->set_supports_alpha_blend(
+ (GetDeviceCaps(hdc, SHADEBLENDCAPS) & kAlphaCaps) == kAlphaCaps);
// No printer device is known to advertise different dpi in X and Y axis; even
// the fax device using the 200x100 dpi setting. It's ought to break so many
// applications that it's not even needed to care about. WebKit doesn't
diff --git a/skia/ext/vector_platform_device_win.cc b/skia/ext/vector_platform_device_win.cc
index 31ac722..6ec4e39 100644
--- a/skia/ext/vector_platform_device_win.cc
+++ b/skia/ext/vector_platform_device_win.cc
@@ -104,7 +104,8 @@ VectorPlatformDevice::VectorPlatformDevice(HDC dc, const SkBitmap& bitmap)
: PlatformDevice(bitmap),
hdc_(dc),
previous_brush_(NULL),
- previous_pen_(NULL) {
+ previous_pen_(NULL),
+ alpha_blend_used_(false) {
transform_.reset();
}
@@ -698,6 +699,8 @@ void VectorPlatformDevice::InternalDrawBitmap(const SkBitmap& bitmap,
result = SetStretchBltMode(dc, previous_mode);
SkASSERT(result);
+ alpha_blend_used_ = true;
+
::SelectObject(bitmap_dc, static_cast<HBITMAP>(old_bitmap));
DeleteObject(hbitmap);
DeleteDC(bitmap_dc);
diff --git a/skia/ext/vector_platform_device_win.h b/skia/ext/vector_platform_device_win.h
index 2a5057e..3050a90 100644
--- a/skia/ext/vector_platform_device_win.h
+++ b/skia/ext/vector_platform_device_win.h
@@ -81,6 +81,7 @@ class VectorPlatformDevice : public PlatformDevice {
virtual bool IsVectorial() { return true; }
void LoadClipRegion();
+ bool alpha_blend_used() const { return alpha_blend_used_; }
private:
// Applies the SkPaint's painting properties in the current GDI context, if
@@ -129,6 +130,9 @@ class VectorPlatformDevice : public PlatformDevice {
// Previously selected pen before the current drawing.
HGDIOBJ previous_pen_;
+ // True if AlphaBlend() was called during this print.
+ bool alpha_blend_used_;
+
// Copy & assign are not supported.
VectorPlatformDevice(const VectorPlatformDevice&);
const VectorPlatformDevice& operator=(const VectorPlatformDevice&);