summaryrefslogtreecommitdiffstats
path: root/chrome
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 /chrome
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 'chrome')
-rw-r--r--chrome/app/generated_resources.grd8
-rw-r--r--chrome/browser/about_flags.cc9
-rw-r--r--chrome/browser/printing/print_view_manager.cc43
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/renderer/print_web_view_helper.h20
-rw-r--r--chrome/renderer/print_web_view_helper_win.cc141
7 files changed, 65 insertions, 160 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 518ea05..9908de4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5361,6 +5361,14 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_FLAGS_PRINT_SETTING_RESET_DESCRIPTION" desc="Description for flag to reset the last printer and settings on browser restart.">
Reset the last used printer on restart. With this enabled, the OS default printer will become the current printer for print preview on each browser start.
</message>
+ <if expr="is_win">
+ <message name="IDS_FLAGS_PRINT_RASTER_NAME" desc="Name of 'Print raster' flag.">
+ Print raster
+ </message>
+ <message name="IDS_FLAGS_PRINT_RASTER_DESCRIPTION" desc="Description for 'Print raster' flag.">
+ Rasterise page before printing. Slower, but may help to resolve issues with some printers
+ </message>
+ </if>
<message name="IDS_FLAGS_CRXLESS_WEB_APPS_NAME" desc="Title of the CRX-less web apps lab">
CRX-less Web Apps
</message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 51ef078..956b8ca 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -223,6 +223,15 @@ const Experiment kExperiments[] = {
kOsAll,
SINGLE_VALUE_TYPE(switches::kPrintSettingsReset)
},
+#if defined(OS_WIN)
+ {
+ "print-raster",
+ IDS_FLAGS_PRINT_RASTER_NAME,
+ IDS_FLAGS_PRINT_RASTER_DESCRIPTION,
+ kOsWin,
+ SINGLE_VALUE_TYPE(switches::kPrintRaster)
+ },
+#endif // OS_WIN
{
"crxless-web-apps",
IDS_FLAGS_CRXLESS_WEB_APPS_NAME,
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 001f656..abbdc1f 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -7,6 +7,7 @@
#include <map>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
@@ -24,6 +25,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -52,6 +54,9 @@ typedef std::map<content::RenderProcessHost*, base::Closure>
static base::LazyInstance<ScriptedPrintPreviewClosureMap>
g_scripted_print_preview_closure_map = LAZY_INSTANCE_INITIALIZER;
+// Limits memory usage by raster to 64 MiB.
+const int kMaxRasterSizeInPixels = 16*1024*1024;
+
} // namespace
namespace printing {
@@ -221,18 +226,6 @@ void PrintViewManager::OnDidPrintPage(
return;
}
-#if defined(OS_WIN)
- // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
- // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
- // MB, it can fail to print and not send an error message.
- if (params.data_size && params.data_size >= 350*1024*1024) {
- NOTREACHED() << "size:" << params.data_size;
- TerminatePrintJob(true);
- web_contents()->Stop();
- return;
- }
-#endif
-
#if defined(OS_WIN) || defined(OS_MACOSX)
const bool metafile_must_be_valid = true;
#elif defined(OS_POSIX)
@@ -249,7 +242,7 @@ void PrintViewManager::OnDidPrintPage(
}
}
- scoped_ptr<Metafile> metafile(new NativeMetafile);
+ scoped_ptr<NativeMetafile> metafile(new NativeMetafile);
if (metafile_must_be_valid) {
if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
NOTREACHED() << "Invalid metafile header";
@@ -258,6 +251,30 @@ 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);
+ scoped_ptr<NativeMetafile> raster_metafile(
+ metafile->RasterizeMetafile(raster_size));
+ if (raster_metafile.get()) {
+ metafile.swap(raster_metafile);
+ } else if (big_emf) {
+ // Don't fall back to emf here.
+ NOTREACHED() << "size:" << params.data_size;
+ TerminatePrintJob(true);
+ web_contents()->Stop();
+ return;
+ }
+ }
+
+#endif
+
// Update the rendered document. It will send notifications to the listener.
document->SetPage(params.page_number,
metafile.release(),
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index a069a09..49e2643 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1082,6 +1082,9 @@ const char kPrerenderModeSwitchValueEnabled[] = "enabled";
// prefetch_only: No prerendering, but enables prefetching.
const char kPrerenderModeSwitchValuePrefetchOnly[] = "prefetch_only";
+// Enable conversion from vector to raster for any page.
+const char kPrintRaster[] = "print-raster";
+
// Disable saving the printer and settings between sessions.
const char kPrintSettingsReset[] = "print-settings-reset";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 8fb9953..7d45b2a 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -437,6 +437,7 @@ extern const char kUseMockKeychain[];
extern const char kDisableDesktopShortcuts[];
extern const char kEnableSyncCredentialCaching[];
extern const char kForceImmersive[];
+extern const char kPrintRaster[];
extern const char kRelaunchShortcut[];
extern const char kWaitForHandle[];
#endif
diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h
index c76bf33..1180a5d 100644
--- a/chrome/renderer/print_web_view_helper.h
+++ b/chrome/renderer/print_web_view_helper.h
@@ -269,18 +269,14 @@ class PrintWebViewHelper
// Platform specific helper function for rendering page(s) to |metafile|.
#if defined(OS_WIN)
- // Because of mixed support for alpha channels on printers, this method may
- // need to create a new metafile. The result may be either the passed
- // |metafile| or a new one. In either case, the caller owns both |metafile|
- // and the result.
- printing::Metafile* RenderPage(const PrintMsg_Print_Params& params,
- int page_number,
- WebKit::WebFrame* frame,
- bool is_preview,
- printing::Metafile* metafile,
- double* scale_factor,
- gfx::Size* page_size_in_dpi,
- gfx::Rect* content_area_in_dpi);
+ void RenderPage(const PrintMsg_Print_Params& params,
+ int page_number,
+ WebKit::WebFrame* frame,
+ bool is_preview,
+ printing::Metafile* metafile,
+ double* scale_factor,
+ gfx::Size* page_size_in_dpi,
+ gfx::Rect* content_area_in_dpi);
#elif defined(OS_MACOSX)
void RenderPage(const PrintMsg_Print_Params& params, int page_number,
WebKit::WebFrame* frame, bool is_preview,
diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc
index d3e6576..d827678 100644
--- a/chrome/renderer/print_web_view_helper_win.cc
+++ b/chrome/renderer/print_web_view_helper_win.cc
@@ -32,117 +32,6 @@ using printing::kPointsPerInch;
using printing::Metafile;
using WebKit::WebFrame;
-namespace {
-
-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);
- switch (record->iType) {
- case 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);
- 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(dc, handle_table, record, num_objects);
- break;
- }
- return 1; // Continue enumeration
-}
-
-Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) {
- // Currently, we handle alpha blend transparency for a single page.
- // Therefore, expecting a metafile with page count 1.
- DCHECK_EQ(1U, metafile->GetPageCount());
-
- // Close the device context to retrieve the compiled metafile.
- if (!metafile->FinishDocument())
- NOTREACHED();
-
- // Page used alpha blend, but printer doesn't support it. Rewrite the
- // metafile and flatten out the transparency.
- base::win::ScopedGetDC screen_dc(NULL);
- base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(screen_dc));
- if (!bitmap_dc)
- NOTREACHED() << "Bitmap DC creation failed";
- 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 whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
- FillRect(bitmap_dc, &rect, whiteBrush);
-
- Metafile* metafile2(new printing::NativeMetafile);
- metafile2->Init();
- HDC hdc = metafile2->context();
- DCHECK(hdc);
- skia::InitializeDC(hdc);
-
- RECT metafile_bounds = metafile->GetPageBounds(1).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);
- return metafile2;
-}
-
-} // namespace
-
void PrintWebViewHelper::PrintPageInternal(
const PrintMsg_PrintPage_Params& params,
const gfx::Size& canvas_size,
@@ -166,9 +55,8 @@ void PrintWebViewHelper::PrintPageInternal(
gfx::Rect content_area_in_dpi;
// Render page for printing.
- metafile.reset(RenderPage(params.params, page_number, frame, false,
- metafile.get(), &actual_shrink, &page_size_in_dpi,
- &content_area_in_dpi));
+ RenderPage(params.params, page_number, frame, false, metafile.get(),
+ &actual_shrink, &page_size_in_dpi, &content_area_in_dpi);
// Close the device context to retrieve the compiled metafile.
if (!metafile->FinishDocument())
@@ -210,11 +98,8 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) {
}
base::TimeTicks begin_time = base::TimeTicks::Now();
- printing::Metafile* render_page_result =
- RenderPage(print_params, page_number, print_preview_context_.frame(),
- true, initial_render_metafile, &actual_shrink, NULL, NULL);
- // In the preview flow, RenderPage will never return a new metafile.
- DCHECK_EQ(render_page_result, initial_render_metafile);
+ RenderPage(print_params, page_number, print_preview_context_.frame(), true,
+ initial_render_metafile, &actual_shrink, NULL, NULL);
print_preview_context_.RenderedPreviewPage(
base::TimeTicks::Now() - begin_time);
@@ -229,7 +114,7 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) {
return PreviewPageRendered(page_number, draft_metafile.get());
}
-Metafile* PrintWebViewHelper::RenderPage(
+void PrintWebViewHelper::RenderPage(
const PrintMsg_Print_Params& params, int page_number, WebFrame* frame,
bool is_preview, Metafile* metafile, double* actual_shrink,
gfx::Size* page_size_in_dpi, gfx::Rect* content_area_in_dpi) {
@@ -319,27 +204,13 @@ Metafile* PrintWebViewHelper::RenderPage(
bool result = metafile->FinishPage();
DCHECK(result);
-
- if (!params.supports_alpha_blend) {
- // PreviewMetafile (PDF) supports alpha blend, so we only hit this case
- // for NativeMetafile.
- DCHECK(!is_preview);
- skia::PlatformDevice* platform_device = skia::GetPlatformDevice(device);
- if (platform_device && platform_device->AlphaBlendUsed()) {
- return FlattenTransparency(metafile, page_size);
- }
- }
- return metafile;
}
bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle) {
uint32 buf_size = metafile->GetDataSize();
base::SharedMemory shared_buf;
- // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
- // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
- // MB, it can fail to print and not send an error message.
- if (buf_size >= 350*1024*1024) {
+ if (buf_size >= printing::kMetafileMaxSize) {
NOTREACHED() << "Buffer too large: " << buf_size;
return false;
}