1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxge/win32/cgdi_printer_driver.h"
8
9 #include <math.h>
10 #include <windows.h>
11
12 #include <algorithm>
13 #include <memory>
14
15 #include "core/fxcrt/fx_memory.h"
16 #include "core/fxcrt/fx_system.h"
17 #include "core/fxcrt/retain_ptr.h"
18 #include "core/fxge/cfx_font.h"
19 #include "core/fxge/cfx_windowsrenderdevice.h"
20 #include "core/fxge/dib/cfx_dibbase.h"
21 #include "core/fxge/dib/cfx_dibitmap.h"
22 #include "core/fxge/render_defines.h"
23 #include "core/fxge/text_char_pos.h"
24 #include "third_party/base/check.h"
25 #include "third_party/base/check_op.h"
26
CGdiPrinterDriver(HDC hDC)27 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC)
28 : CGdiDeviceDriver(hDC, DeviceType::kPrinter),
29 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)),
30 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {}
31
32 CGdiPrinterDriver::~CGdiPrinterDriver() = default;
33
GetDeviceCaps(int caps_id) const34 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const {
35 if (caps_id == FXDC_HORZ_SIZE)
36 return m_HorzSize;
37 if (caps_id == FXDC_VERT_SIZE)
38 return m_VertSize;
39 return CGdiDeviceDriver::GetDeviceCaps(caps_id);
40 }
41
SetDIBits(const RetainPtr<CFX_DIBBase> & pSource,uint32_t color,const FX_RECT & src_rect,int left,int top,BlendMode blend_type)42 bool CGdiPrinterDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pSource,
43 uint32_t color,
44 const FX_RECT& src_rect,
45 int left,
46 int top,
47 BlendMode blend_type) {
48 if (pSource->IsMaskFormat()) {
49 FX_RECT clip_rect(left, top, left + src_rect.Width(),
50 top + src_rect.Height());
51 return StretchDIBits(pSource, color, left - src_rect.left,
52 top - src_rect.top, pSource->GetWidth(),
53 pSource->GetHeight(), &clip_rect,
54 FXDIB_ResampleOptions(), BlendMode::kNormal);
55 }
56 DCHECK(pSource);
57 DCHECK(!pSource->IsMaskFormat());
58 DCHECK_EQ(blend_type, BlendMode::kNormal);
59 if (pSource->IsAlphaFormat())
60 return false;
61
62 return GDI_SetDIBits(pSource, src_rect, left, top);
63 }
64
StretchDIBits(const RetainPtr<CFX_DIBBase> & pSource,uint32_t color,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,const FXDIB_ResampleOptions & options,BlendMode blend_type)65 bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
66 uint32_t color,
67 int dest_left,
68 int dest_top,
69 int dest_width,
70 int dest_height,
71 const FX_RECT* pClipRect,
72 const FXDIB_ResampleOptions& options,
73 BlendMode blend_type) {
74 if (pSource->IsMaskFormat()) {
75 int alpha = FXARGB_A(color);
76 if (pSource->GetBPP() != 1 || alpha != 255)
77 return false;
78
79 if (dest_width < 0 || dest_height < 0) {
80 RetainPtr<CFX_DIBBase> pFlipped =
81 pSource->FlipImage(dest_width < 0, dest_height < 0);
82 if (!pFlipped)
83 return false;
84
85 if (dest_width < 0)
86 dest_left += dest_width;
87 if (dest_height < 0)
88 dest_top += dest_height;
89
90 return GDI_StretchBitMask(pFlipped, dest_left, dest_top, abs(dest_width),
91 abs(dest_height), color);
92 }
93
94 return GDI_StretchBitMask(pSource, dest_left, dest_top, dest_width,
95 dest_height, color);
96 }
97
98 if (pSource->IsAlphaFormat())
99 return false;
100
101 if (dest_width < 0 || dest_height < 0) {
102 RetainPtr<CFX_DIBBase> pFlipped =
103 pSource->FlipImage(dest_width < 0, dest_height < 0);
104 if (!pFlipped)
105 return false;
106
107 if (dest_width < 0)
108 dest_left += dest_width;
109 if (dest_height < 0)
110 dest_top += dest_height;
111
112 return GDI_StretchDIBits(pFlipped, dest_left, dest_top, abs(dest_width),
113 abs(dest_height), options);
114 }
115
116 return GDI_StretchDIBits(pSource, dest_left, dest_top, dest_width,
117 dest_height, options);
118 }
119
StartDIBits(const RetainPtr<CFX_DIBBase> & pSource,int bitmap_alpha,uint32_t color,const CFX_Matrix & matrix,const FXDIB_ResampleOptions & options,std::unique_ptr<CFX_ImageRenderer> * handle,BlendMode blend_type)120 bool CGdiPrinterDriver::StartDIBits(const RetainPtr<CFX_DIBBase>& pSource,
121 int bitmap_alpha,
122 uint32_t color,
123 const CFX_Matrix& matrix,
124 const FXDIB_ResampleOptions& options,
125 std::unique_ptr<CFX_ImageRenderer>* handle,
126 BlendMode blend_type) {
127 if (bitmap_alpha < 255 || pSource->IsAlphaFormat() ||
128 (pSource->IsMaskFormat() && (pSource->GetBPP() != 1))) {
129 return false;
130 }
131 CFX_FloatRect unit_rect = matrix.GetUnitRect();
132 FX_RECT full_rect = unit_rect.GetOuterRect();
133 if (fabs(matrix.b) < 0.5f && matrix.a != 0 && fabs(matrix.c) < 0.5f &&
134 matrix.d != 0) {
135 bool bFlipX = matrix.a < 0;
136 bool bFlipY = matrix.d > 0;
137 return StretchDIBits(pSource, color,
138 bFlipX ? full_rect.right : full_rect.left,
139 bFlipY ? full_rect.bottom : full_rect.top,
140 bFlipX ? -full_rect.Width() : full_rect.Width(),
141 bFlipY ? -full_rect.Height() : full_rect.Height(),
142 nullptr, FXDIB_ResampleOptions(), blend_type);
143 }
144 if (fabs(matrix.a) >= 0.5f || fabs(matrix.d) >= 0.5f)
145 return false;
146
147 RetainPtr<CFX_DIBBase> pTransformed =
148 pSource->SwapXY(matrix.c > 0, matrix.b < 0);
149 if (!pTransformed)
150 return false;
151
152 return StretchDIBits(pTransformed, color, full_rect.left, full_rect.top,
153 full_rect.Width(), full_rect.Height(), nullptr,
154 FXDIB_ResampleOptions(), blend_type);
155 }
156
DrawDeviceText(pdfium::span<const TextCharPos> pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t color,const CFX_TextRenderOptions &)157 bool CGdiPrinterDriver::DrawDeviceText(
158 pdfium::span<const TextCharPos> pCharPos,
159 CFX_Font* pFont,
160 const CFX_Matrix& mtObject2Device,
161 float font_size,
162 uint32_t color,
163 const CFX_TextRenderOptions& /*options*/) {
164 return false;
165 }
166