OLD | NEW |
---|---|
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" | 10 #include "base/win/scoped_gdi_object.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 switch (record->iType) { | 47 switch (record->iType) { |
48 case EMR_ALPHABLEND: { | 48 case EMR_ALPHABLEND: { |
49 *result = true; | 49 *result = true; |
50 return 0; | 50 return 0; |
51 break; | 51 break; |
52 } | 52 } |
53 } | 53 } |
54 return 1; | 54 return 1; |
55 } | 55 } |
56 | 56 |
57 int CALLBACK RasterizeAlphaBlendProc(HDC metafile_dc, | |
58 HANDLETABLE* handle_table, | |
59 const ENHMETARECORD *record, | |
60 int num_objects, | |
61 LPARAM data) { | |
62 HDC bitmap_dc = *reinterpret_cast<HDC*>(data); | |
63 // Play this command to the bitmap DC. | |
64 ::PlayEnhMetaFileRecord(bitmap_dc, handle_table, record, num_objects); | |
65 switch (record->iType) { | |
66 case EMR_ALPHABLEND: { | |
67 const EMRALPHABLEND* alpha_blend = | |
68 reinterpret_cast<const EMRALPHABLEND*>(record); | |
69 // Don't modify transformation here. | |
70 // Old implementation did reset transformations for DC to identity matrix. | |
71 // That was not correct and cause some bugs, like unexpected cropping. | |
72 // EMRALPHABLEND is rendered into bitmap and metafile contexts with | |
73 // current transformation. If we don't touch them here BitBlt will copy | |
74 // same areas. | |
75 ::BitBlt(metafile_dc, | |
76 alpha_blend->xDest, | |
77 alpha_blend->yDest, | |
78 alpha_blend->cxDest, | |
79 alpha_blend->cyDest, | |
80 bitmap_dc, | |
81 alpha_blend->xDest, | |
82 alpha_blend->yDest, | |
83 SRCCOPY); | |
84 break; | |
85 } | |
86 case EMR_CREATEBRUSHINDIRECT: | |
87 case EMR_CREATECOLORSPACE: | |
88 case EMR_CREATECOLORSPACEW: | |
89 case EMR_CREATEDIBPATTERNBRUSHPT: | |
90 case EMR_CREATEMONOBRUSH: | |
91 case EMR_CREATEPALETTE: | |
92 case EMR_CREATEPEN: | |
93 case EMR_DELETECOLORSPACE: | |
94 case EMR_DELETEOBJECT: | |
95 case EMR_EXTCREATEFONTINDIRECTW: | |
96 // Play object creation command only once. | |
97 break; | |
98 | |
99 default: | |
100 // Play this command to the metafile DC. | |
101 ::PlayEnhMetaFileRecord(metafile_dc, handle_table, record, num_objects); | |
102 break; | |
103 } | |
104 return 1; // Continue enumeration | |
105 } | |
106 | |
107 // Bitmapt for rasterization. | |
108 class RasterBitmap { | |
109 public: | |
110 explicit RasterBitmap(const gfx::Size& raster_size) | |
111 : saved_object_(NULL) { | |
112 context_.Set(::CreateCompatibleDC(NULL)); | |
113 if (!context_) { | |
114 NOTREACHED() << "Bitmap DC creation failed"; | |
115 return; | |
116 } | |
117 ::SetGraphicsMode(context_, GM_ADVANCED); | |
118 void* bits = NULL; | |
119 gfx::Rect bitmap_rect(raster_size); | |
120 gfx::CreateBitmapHeader(raster_size.width(), raster_size.height(), | |
121 &header_.bmiHeader); | |
122 bitmap_.Set(::CreateDIBSection(context_, &header_, DIB_RGB_COLORS, &bits, | |
123 NULL, 0)); | |
124 if (!bitmap_) | |
125 NOTREACHED() << "Raster bitmap creation for printing failed"; | |
126 | |
127 saved_object_ = ::SelectObject(context_, bitmap_); | |
128 ::FillRect(context_, &bitmap_rect.ToRECT(), | |
Timur Iskhodzhanov
2013/03/28 03:49:39
FYI taking an address of a temporary object is not
| |
129 static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH))); | |
130 | |
131 } | |
132 | |
133 ~RasterBitmap() { | |
134 ::SelectObject(context_, saved_object_); | |
135 } | |
136 | |
137 HDC context() const { | |
138 return context_; | |
139 } | |
140 | |
141 base::win::ScopedCreateDC context_; | |
142 BITMAPINFO header_; | |
143 base::win::ScopedBitmap bitmap_; | |
144 HGDIOBJ saved_object_; | |
145 | |
146 private: | |
147 DISALLOW_COPY_AND_ASSIGN(RasterBitmap); | |
148 }; | |
149 | |
150 | |
151 | |
57 } // namespace | 152 } // namespace |
58 | 153 |
59 namespace printing { | 154 namespace printing { |
60 | 155 |
61 bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits, | 156 bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits, |
62 int size) { | 157 int size) { |
63 BOOL supported = FALSE; | 158 BOOL supported = FALSE; |
64 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), | 159 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), |
65 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) { | 160 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) { |
66 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits), | 161 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits), |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
509 gfx::Size page_size(page_bounds.size()); | 604 gfx::Size page_size(page_bounds.size()); |
510 if (page_size.GetArea() <= 0) { | 605 if (page_size.GetArea() <= 0) { |
511 NOTREACHED() << "Metafile is empty"; | 606 NOTREACHED() << "Metafile is empty"; |
512 page_bounds = gfx::Rect(1, 1); | 607 page_bounds = gfx::Rect(1, 1); |
513 } | 608 } |
514 | 609 |
515 float scale = sqrt(float(raster_area_in_pixels) / page_size.GetArea()); | 610 float scale = sqrt(float(raster_area_in_pixels) / page_size.GetArea()); |
516 page_size.set_width(std::max<int>(1, page_size.width() * scale)); | 611 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)); | 612 page_size.set_height(std::max<int>(1, page_size.height() * scale)); |
518 | 613 |
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 | 614 |
534 base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap); | 615 RasterBitmap bitmap(page_size); |
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 | 616 |
539 gfx::Rect bitmap_rect(page_size); | 617 gfx::Rect bitmap_rect(page_size); |
540 Playback(bitmap_dc, &bitmap_rect.ToRECT()); | 618 Playback(bitmap.context(), &bitmap_rect.ToRECT()); |
541 | 619 |
542 scoped_ptr<Emf> result(new Emf); | 620 scoped_ptr<Emf> result(new Emf); |
543 result->Init(); | 621 result->Init(); |
544 HDC hdc = result->context(); | 622 HDC hdc = result->context(); |
545 DCHECK(hdc); | 623 DCHECK(hdc); |
546 skia::InitializeDC(hdc); | 624 skia::InitializeDC(hdc); |
547 | 625 |
548 // Params are ignored. | 626 // Params are ignored. |
549 result->StartPage(page_bounds.size(), page_bounds, 1); | 627 result->StartPage(page_bounds.size(), page_bounds, 1); |
550 | 628 |
551 ::ModifyWorldTransform(hdc, NULL, MWT_IDENTITY); | 629 ::ModifyWorldTransform(hdc, NULL, MWT_IDENTITY); |
552 XFORM xform = { | 630 XFORM xform = { |
553 float(page_bounds.width()) / bitmap_rect.width(), 0, | 631 float(page_bounds.width()) / bitmap_rect.width(), 0, |
554 0, float(page_bounds.height()) / bitmap_rect.height(), | 632 0, float(page_bounds.height()) / bitmap_rect.height(), |
555 page_bounds.x(), | 633 page_bounds.x(), |
556 page_bounds.y(), | 634 page_bounds.y(), |
557 }; | 635 }; |
558 ::SetWorldTransform(hdc, &xform); | 636 ::SetWorldTransform(hdc, &xform); |
559 ::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(), | 637 ::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(), |
560 bitmap_dc, bitmap_rect.x(), bitmap_rect.y(), SRCCOPY); | 638 bitmap.context(), bitmap_rect.x(), bitmap_rect.y(), SRCCOPY); |
561 | 639 |
562 result->FinishPage(); | 640 result->FinishPage(); |
563 result->FinishDocument(); | 641 result->FinishDocument(); |
564 | 642 |
565 return result.release(); | 643 return result.release(); |
566 } | 644 } |
567 | 645 |
646 Emf* Emf::RasterizeAlphaBlend() const { | |
647 gfx::Rect page_bounds = GetPageBounds(1); | |
648 if (page_bounds.size().GetArea() <= 0) { | |
649 NOTREACHED() << "Metafile is empty"; | |
650 page_bounds = gfx::Rect(1, 1); | |
651 } | |
652 | |
653 RasterBitmap bitmap(page_bounds.size()); | |
654 | |
655 // Map metafile page_bounds.x(), page_bounds.y() to bitmap 0, 0. | |
656 XFORM xform = { 1, 0, 0, 1, -page_bounds.x(), -page_bounds.y()}; | |
657 ::SetWorldTransform(bitmap.context(), &xform); | |
658 | |
659 scoped_ptr<Emf> result(new Emf); | |
660 result->Init(); | |
661 HDC hdc = result->context(); | |
662 DCHECK(hdc); | |
663 skia::InitializeDC(hdc); | |
664 | |
665 HDC bitmap_dc = bitmap.context(); | |
666 ::EnumEnhMetaFile(hdc, emf(), &RasterizeAlphaBlendProc, &bitmap_dc, | |
667 &page_bounds.ToRECT()); | |
668 | |
669 result->FinishDocument(); | |
670 | |
671 return result.release(); | |
672 } | |
673 | |
674 | |
568 } // namespace printing | 675 } // namespace printing |
OLD | NEW |