Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: printing/emf_win.cc

Issue 10836330: Rasterize page before printing. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « printing/emf_win.h ('k') | printing/emf_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "printing/emf_win.h" 5 #include "printing/emf_win.h"
6 6
7 #include "base/file_path.h" 7 #include "base/file_path.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/win/scoped_gdi_object.h"
11 #include "base/win/scoped_hdc.h"
12 #include "base/win/scoped_select_object.h"
10 #include "skia/ext/vector_platform_device_emf_win.h" 13 #include "skia/ext/vector_platform_device_emf_win.h"
11 #include "third_party/skia/include/core/SkBitmap.h" 14 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "ui/gfx/codec/jpeg_codec.h" 15 #include "ui/gfx/codec/jpeg_codec.h"
13 #include "ui/gfx/codec/png_codec.h" 16 #include "ui/gfx/codec/png_codec.h"
14 #include "ui/gfx/gdi_util.h" 17 #include "ui/gfx/gdi_util.h"
15 #include "ui/gfx/rect.h" 18 #include "ui/gfx/rect.h"
16 #include "ui/gfx/size.h" 19 #include "ui/gfx/size.h"
17 20
18 namespace { 21 namespace {
22
19 const int kCustomGdiCommentSignature = 0xdeadbabe; 23 const int kCustomGdiCommentSignature = 0xdeadbabe;
20 struct PageBreakRecord { 24 struct PageBreakRecord {
21 int signature; 25 int signature;
22 enum PageBreakType { 26 enum PageBreakType {
23 START_PAGE, 27 START_PAGE,
24 END_PAGE, 28 END_PAGE,
25 } type; 29 } type;
26 explicit PageBreakRecord(PageBreakType type_in) 30 explicit PageBreakRecord(PageBreakType type_in)
27 : signature(kCustomGdiCommentSignature), type(type_in) { 31 : signature(kCustomGdiCommentSignature), type(type_in) {
28 } 32 }
29 bool IsValid() const { 33 bool IsValid() const {
30 return (signature == kCustomGdiCommentSignature) && 34 return (signature == kCustomGdiCommentSignature) &&
31 (type >= START_PAGE) && (type <= END_PAGE); 35 (type >= START_PAGE) && (type <= END_PAGE);
32 } 36 }
33 }; 37 };
38
39 int CALLBACK IsAlphaBlendUsedEnumProc(HDC,
40 HANDLETABLE*,
41 const ENHMETARECORD *record,
42 int,
43 LPARAM data) {
44 bool* result = reinterpret_cast<bool*>(data);
45 if (!result)
46 return 0;
47 switch (record->iType) {
48 case EMR_ALPHABLEND: {
49 *result = true;
50 return 0;
51 break;
52 }
53 }
54 return 1;
34 } 55 }
35 56
57 } // namespace
58
36 namespace printing { 59 namespace printing {
37 60
38 bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits, 61 bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits,
39 int size) { 62 int size) {
40 BOOL supported = FALSE; 63 BOOL supported = FALSE;
41 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), 64 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape),
42 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) { 65 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) {
43 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits), 66 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits),
44 sizeof(supported), reinterpret_cast<LPSTR>(&supported)); 67 sizeof(supported), reinterpret_cast<LPSTR>(&supported));
45 } 68 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 } 142 }
120 143
121 gfx::Rect Emf::GetPageBounds(unsigned int page_number) const { 144 gfx::Rect Emf::GetPageBounds(unsigned int page_number) const {
122 DCHECK(emf_ && !hdc_); 145 DCHECK(emf_ && !hdc_);
123 DCHECK_EQ(1U, page_number); 146 DCHECK_EQ(1U, page_number);
124 ENHMETAHEADER header; 147 ENHMETAHEADER header;
125 if (GetEnhMetaFileHeader(emf_, sizeof(header), &header) != sizeof(header)) { 148 if (GetEnhMetaFileHeader(emf_, sizeof(header), &header) != sizeof(header)) {
126 NOTREACHED(); 149 NOTREACHED();
127 return gfx::Rect(); 150 return gfx::Rect();
128 } 151 }
129 if (header.rclBounds.left == 0 && 152 // Add 1 to right and bottom because it's inclusive rectangle.
130 header.rclBounds.top == 0 && 153 // See ENHMETAHEADER.
131 header.rclBounds.right == -1 &&
132 header.rclBounds.bottom == -1) {
133 // A freshly created EMF buffer that has no drawing operation has invalid
134 // bounds. Instead of having an (0,0) size, it has a (-1,-1) size. Detect
135 // this special case and returns an empty Rect instead of an invalid one.
136 return gfx::Rect();
137 }
138 return gfx::Rect(header.rclBounds.left, 154 return gfx::Rect(header.rclBounds.left,
139 header.rclBounds.top, 155 header.rclBounds.top,
140 header.rclBounds.right - header.rclBounds.left, 156 header.rclBounds.right - header.rclBounds.left + 1,
141 header.rclBounds.bottom - header.rclBounds.top); 157 header.rclBounds.bottom - header.rclBounds.top + 1);
142 } 158 }
143 159
144 uint32 Emf::GetDataSize() const { 160 uint32 Emf::GetDataSize() const {
145 DCHECK(emf_ && !hdc_); 161 DCHECK(emf_ && !hdc_);
146 return GetEnhMetaFileBits(emf_, 0, NULL); 162 return GetEnhMetaFileBits(emf_, 0, NULL);
147 } 163 }
148 164
149 bool Emf::GetData(void* buffer, uint32 size) const { 165 bool Emf::GetData(void* buffer, uint32 size) const {
150 DCHECK(emf_ && !hdc_); 166 DCHECK(emf_ && !hdc_);
151 DCHECK(buffer && size); 167 DCHECK(buffer && size);
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 emf.context_.hdc = hdc; 487 emf.context_.hdc = hdc;
472 } else { 488 } else {
473 DCHECK_EQ(emf.context_.handle_table, handle_table); 489 DCHECK_EQ(emf.context_.handle_table, handle_table);
474 DCHECK_EQ(emf.context_.objects_count, objects_count); 490 DCHECK_EQ(emf.context_.objects_count, objects_count);
475 DCHECK_EQ(emf.context_.hdc, hdc); 491 DCHECK_EQ(emf.context_.hdc, hdc);
476 } 492 }
477 emf.items_.push_back(Record(record)); 493 emf.items_.push_back(Record(record));
478 return 1; 494 return 1;
479 } 495 }
480 496
497 bool Emf::IsAlphaBlendUsed() const {
498 bool result = false;
499 ::EnumEnhMetaFile(NULL,
500 emf(),
501 &IsAlphaBlendUsedEnumProc,
502 &result,
503 NULL);
504 return result;
505 }
506
507 Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
508 gfx::Rect page_bounds = GetPageBounds(1);
509 gfx::Size page_size(page_bounds.size());
510 if (page_size.GetArea() <= 0) {
511 NOTREACHED() << "Metafile is empty";
512 page_bounds = gfx::Rect(1, 1);
513 }
514
515 float scale = sqrt(float(raster_area_in_pixels) / page_size.GetArea());
516 page_size.set_width(std::max<int>(1, page_size.width() * scale));
517 page_size.set_height(std::max<int>(1, page_size.height() * scale));
518
519 base::win::ScopedCreateDC bitmap_dc(::CreateCompatibleDC(NULL));
520 if (!bitmap_dc) {
521 NOTREACHED() << "Bitmap DC creation failed";
522 return NULL;
523 }
524 ::SetGraphicsMode(bitmap_dc, GM_ADVANCED);
525 void* bits = NULL;
526 BITMAPINFO hdr;
527 gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
528 &hdr.bmiHeader);
529 base::win::ScopedBitmap hbitmap(CreateDIBSection(
530 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
531 if (!hbitmap)
532 NOTREACHED() << "Raster bitmap creation for printing failed";
533
534 base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap);
535 RECT rect = { 0, 0, page_size.width(), page_size.height() };
536 HBRUSH white_brush = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
537 FillRect(bitmap_dc, &rect, white_brush);
538
539 gfx::Rect bitmap_rect(page_size);
540 Playback(bitmap_dc, &bitmap_rect.ToRECT());
541
542 scoped_ptr<Emf> result(new Emf);
543 result->Init();
544 HDC hdc = result->context();
545 DCHECK(hdc);
546 skia::InitializeDC(hdc);
547
548 // Params are ignored.
549 result->StartPage(page_bounds.size(), page_bounds, 1);
550
551 ::ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
552 XFORM xform = {
553 float(page_bounds.width()) / bitmap_rect.width(), 0,
554 0, float(page_bounds.height()) / bitmap_rect.height(),
555 page_bounds.x(),
556 page_bounds.y(),
557 };
558 ::SetWorldTransform(hdc, &xform);
559 ::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(),
560 bitmap_dc, bitmap_rect.x(), bitmap_rect.y(), SRCCOPY);
561
562 result->FinishPage();
563 result->FinishDocument();
564
565 return result.release();
566 }
567
481 } // namespace printing 568 } // namespace printing
OLDNEW
« no previous file with comments | « printing/emf_win.h ('k') | printing/emf_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698