summaryrefslogtreecommitdiffstats
path: root/printing
diff options
context:
space:
mode:
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);