summaryrefslogtreecommitdiffstats
path: root/printing/emf_win.cc
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/emf_win.cc
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/emf_win.cc')
-rw-r--r--printing/emf_win.cc85
1 files changed, 84 insertions, 1 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);