summaryrefslogtreecommitdiffstats
path: root/printing
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 05:29:07 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 05:29:07 +0000
commit38bba4f8e2f93dd789c3483a3f0c153ca5809793 (patch)
tree18ec7bd6d8cf84dd7492b1f986f210621a79db00 /printing
parent31548a10135c11ff689074896237d2b7a404959c (diff)
downloadchromium_src-38bba4f8e2f93dd789c3483a3f0c153ca5809793.zip
chromium_src-38bba4f8e2f93dd789c3483a3f0c153ca5809793.tar.gz
chromium_src-38bba4f8e2f93dd789c3483a3f0c153ca5809793.tar.bz2
Changes made to the printing logic to allow plugins to participate in the browser's print workflow. These changes mainly involve allowing the plugin to specify
whether it wants the browser to use overlays and also changes to the EMF code on Windows to decompress JPEGs/PNGs in the metafile. The related webkit change is https://bugs.webkit.org/show_bug.cgi?id=35550 BUG=None TEST=Test printing with new Pepper plugins that support custom printing. Review URL: http://codereview.chromium.org/745001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41400 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing')
-rw-r--r--printing/emf_win.cc85
-rw-r--r--printing/print_settings.cc14
-rw-r--r--printing/print_settings.h5
-rw-r--r--printing/printed_document.cc3
-rw-r--r--printing/printing_context.h4
5 files changed, 105 insertions, 6 deletions
diff --git a/printing/emf_win.cc b/printing/emf_win.cc
index f69d4fa..62cc4a0 100644
--- a/printing/emf_win.cc
+++ b/printing/emf_win.cc
@@ -4,11 +4,29 @@
#include "printing/emf_win.h"
+#include "app/gfx/codec/jpeg_codec.h"
+#include "app/gfx/codec/png_codec.h"
+#include "app/gfx/gdi_util.h"
#include "base/gfx/rect.h"
+#include "base/histogram.h"
#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace printing {
+bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits,
+ int size) {
+ BOOL supported = FALSE;
+ if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape),
+ reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) {
+ ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits),
+ sizeof(supported), reinterpret_cast<LPSTR>(&supported));
+ }
+ return !!supported;
+}
+
Emf::Emf() : emf_(NULL), hdc_(NULL) {
}
@@ -65,7 +83,6 @@ bool Emf::SafePlayback(HDC context) const {
NOTREACHED();
return false;
}
-
return EnumEnhMetaFile(context,
emf_,
&Emf::SafePlaybackProc,
@@ -209,9 +226,75 @@ bool Emf::Record::SafePlayback(const XFORM* base_matrix) const {
// I also use this opportunity to skip over eventual EMR_SETLAYOUT record that
// could remain.
//
+ // Another tweak we make is for JPEGs/PNGs in calls to StretchDIBits.
+ // (Our Pepper plugin code uses a JPEG). If the printer does not support
+ // JPEGs/PNGs natively we decompress the JPEG/PNG and then set it to the
+ // device.
+ // TODO(sanjeevr): We should also add JPEG/PNG support for SetSIBitsToDevice
+ //
// Note: I should probably care about view ports and clipping, eventually.
bool res;
switch (record()->iType) {
+ case EMR_STRETCHDIBITS: {
+ const EMRSTRETCHDIBITS * sdib_record =
+ reinterpret_cast<const EMRSTRETCHDIBITS*>(record());
+ const BYTE* record_start = reinterpret_cast<const BYTE *>(record());
+ const BITMAPINFOHEADER *bmih =
+ reinterpret_cast<const BITMAPINFOHEADER *>(record_start +
+ sdib_record->offBmiSrc);
+ const BYTE* bits = record_start + sdib_record->offBitsSrc;
+ bool play_normally = true;
+ res = false;
+ HDC hdc = context_->hdc;
+ scoped_ptr<SkBitmap> bitmap;
+ if (bmih->biCompression == BI_JPEG) {
+ if (!DIBFormatNativelySupported(hdc, CHECKJPEGFORMAT, bits,
+ bmih->biSizeImage)) {
+ play_normally = false;
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bitmap.reset(gfx::JPEGCodec::Decode(bits, bmih->biSizeImage));
+ UMA_HISTOGRAM_TIMES("Printing.JPEGDecompressTime",
+ base::TimeTicks::Now() - start_time);
+ }
+ } else if (bmih->biCompression == BI_PNG) {
+ if (!DIBFormatNativelySupported(hdc, CHECKPNGFORMAT, bits,
+ bmih->biSizeImage)) {
+ play_normally = false;
+ bitmap.reset(new SkBitmap());
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ gfx::PNGCodec::Decode(bits, bmih->biSizeImage, bitmap.get());
+ UMA_HISTOGRAM_TIMES("Printing.PNGDecompressTime",
+ base::TimeTicks::Now() - start_time);
+ }
+ }
+ if (!play_normally) {
+ DCHECK(bitmap.get());
+ if (bitmap.get()) {
+ SkAutoLockPixels lock(*bitmap.get());
+ DCHECK_EQ(bitmap->getConfig(), SkBitmap::kARGB_8888_Config);
+ const uint32_t* pixels =
+ static_cast<const uint32_t*>(bitmap->getPixels());
+ if (pixels == NULL) {
+ NOTREACHED();
+ return false;
+ }
+ BITMAPINFOHEADER bmi = {0};
+ gfx::CreateBitmapHeader(bitmap->width(), bitmap->height(), &bmi);
+ res = (0 != StretchDIBits(hdc, sdib_record->xDest, sdib_record->yDest,
+ sdib_record->cxDest,
+ sdib_record->cyDest, sdib_record->xSrc,
+ sdib_record->ySrc,
+ sdib_record->cxSrc, sdib_record->cySrc,
+ pixels,
+ reinterpret_cast<const BITMAPINFO *>(&bmi),
+ sdib_record->iUsageSrc,
+ sdib_record->dwRop));
+ }
+ } else {
+ res = Play();
+ }
+ break;
+ }
case EMR_SETWORLDTRANSFORM: {
DCHECK_EQ(record()->nSize, sizeof(DWORD) * 2 + sizeof(XFORM));
const XFORM* xform = reinterpret_cast<const XFORM*>(record()->dParm);
diff --git a/printing/print_settings.cc b/printing/print_settings.cc
index 4764952..77c4049 100644
--- a/printing/print_settings.cc
+++ b/printing/print_settings.cc
@@ -19,6 +19,7 @@ PrintSettings::PrintSettings()
max_shrink(2.0),
desired_dpi(72),
selection_only(false),
+ use_overlays(true),
dpi_(0),
landscape_(false) {
}
@@ -120,16 +121,19 @@ void PrintSettings::SetPrinterPrintableArea(
gfx::Size const& physical_size_pixels,
gfx::Rect const& printable_area_pixels) {
- // Hard-code text_height = 0.5cm = ~1/5 of inch.
- int header_footer_text_height = ConvertUnit(500, kHundrethsMMPerInch, dpi_);
-
+ int header_footer_text_height = 0;
+ int margin_printer_units = 0;
+ if (use_overlays) {
+ // Hard-code text_height = 0.5cm = ~1/5 of inch.
+ header_footer_text_height = ConvertUnit(500, kHundrethsMMPerInch, dpi_);
+ // Default margins 1.0cm = ~2/5 of an inch.
+ margin_printer_units = ConvertUnit(1000, kHundrethsMMPerInch, dpi_);
+ }
// Start by setting the user configuration
page_setup_pixels_.Init(physical_size_pixels,
printable_area_pixels,
header_footer_text_height);
- // Default margins 1.0cm = ~2/5 of an inch.
- int margin_printer_units = ConvertUnit(1000, kHundrethsMMPerInch, dpi_);
// Apply default margins (not user configurable just yet).
// Since the font height is half the margin we put the header and footers at
diff --git a/printing/print_settings.h b/printing/print_settings.h
index dd90007f..b5bb723 100644
--- a/printing/print_settings.h
+++ b/printing/print_settings.h
@@ -85,6 +85,11 @@ class PrintSettings {
// Indicates if the user only wants to print the current selection.
bool selection_only;
+ // Indicates whether we should use browser-controlled page overlays
+ // (header, footer, margins etc). If it is false, the overlays are
+ // controlled by the renderer.
+ bool use_overlays;
+
// Cookie generator. It is used to initialize PrintedDocument with its
// associated PrintSettings, to be sure that each generated PrintedPage is
// correctly associated with its corresponding PrintedDocument.
diff --git a/printing/printed_document.cc b/printing/printed_document.cc
index 5f5f53c..7857859 100644
--- a/printing/printed_document.cc
+++ b/printing/printed_document.cc
@@ -180,6 +180,9 @@ void PrintedDocument::PrintHeaderFooter(gfx::NativeDrawingContext context,
PageOverlays::VerticalPosition y,
const gfx::Font& font) const {
const PrintSettings& settings = immutable_.settings_;
+ if (!settings.use_overlays) {
+ return;
+ }
const std::wstring& line = settings.overlays.GetOverlay(x, y);
if (line.empty()) {
return;
diff --git a/printing/printing_context.h b/printing/printing_context.h
index 29c9478..a931c8b 100644
--- a/printing/printing_context.h
+++ b/printing/printing_context.h
@@ -54,6 +54,10 @@ class PrintingContext {
// default device settings.
Result UseDefaultSettings();
+ void SetUseOverlays(bool use_overlays) {
+ settings_.use_overlays = use_overlays;
+ }
+
// Initializes with predefined settings.
Result InitWithSettings(const PrintSettings& settings);