• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <utility>
15 
16 #include "core/fxcrt/check.h"
17 #include "core/fxcrt/check_op.h"
18 #include "core/fxcrt/fx_memory.h"
19 #include "core/fxcrt/fx_system.h"
20 #include "core/fxcrt/retain_ptr.h"
21 #include "core/fxge/agg/cfx_agg_imagerenderer.h"
22 #include "core/fxge/cfx_font.h"
23 #include "core/fxge/cfx_windowsrenderdevice.h"
24 #include "core/fxge/dib/cfx_dibbase.h"
25 #include "core/fxge/dib/cfx_dibitmap.h"
26 #include "core/fxge/render_defines.h"
27 #include "core/fxge/text_char_pos.h"
28 
CGdiPrinterDriver(HDC hDC)29 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC)
30     : CGdiDeviceDriver(hDC, DeviceType::kPrinter),
31       m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)),
32       m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {}
33 
34 CGdiPrinterDriver::~CGdiPrinterDriver() = default;
35 
GetDeviceCaps(int caps_id) const36 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const {
37   if (caps_id == FXDC_HORZ_SIZE)
38     return m_HorzSize;
39   if (caps_id == FXDC_VERT_SIZE)
40     return m_VertSize;
41   return CGdiDeviceDriver::GetDeviceCaps(caps_id);
42 }
43 
SetDIBits(RetainPtr<const CFX_DIBBase> bitmap,uint32_t color,const FX_RECT & src_rect,int left,int top,BlendMode blend_type)44 bool CGdiPrinterDriver::SetDIBits(RetainPtr<const CFX_DIBBase> bitmap,
45                                   uint32_t color,
46                                   const FX_RECT& src_rect,
47                                   int left,
48                                   int top,
49                                   BlendMode blend_type) {
50   if (bitmap->IsMaskFormat()) {
51     FX_RECT clip_rect(left, top, left + src_rect.Width(),
52                       top + src_rect.Height());
53     int dest_width = bitmap->GetWidth();
54     int dest_height = bitmap->GetHeight();
55     return StretchDIBits(std::move(bitmap), color, left - src_rect.left,
56                          top - src_rect.top, dest_width, dest_height,
57                          &clip_rect, FXDIB_ResampleOptions(),
58                          BlendMode::kNormal);
59   }
60 
61   DCHECK_EQ(blend_type, BlendMode::kNormal);
62   if (bitmap->IsAlphaFormat()) {
63     return false;
64   }
65 
66   return GDI_SetDIBits(std::move(bitmap), src_rect, left, top);
67 }
68 
StretchDIBits(RetainPtr<const CFX_DIBBase> bitmap,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)69 bool CGdiPrinterDriver::StretchDIBits(RetainPtr<const CFX_DIBBase> bitmap,
70                                       uint32_t color,
71                                       int dest_left,
72                                       int dest_top,
73                                       int dest_width,
74                                       int dest_height,
75                                       const FX_RECT* pClipRect,
76                                       const FXDIB_ResampleOptions& options,
77                                       BlendMode blend_type) {
78   if (bitmap->IsMaskFormat()) {
79     int alpha = FXARGB_A(color);
80     if (bitmap->GetBPP() != 1 || alpha != 255) {
81       return false;
82     }
83 
84     if (dest_width < 0 || dest_height < 0) {
85       bitmap = bitmap->FlipImage(dest_width < 0, dest_height < 0);
86       if (!bitmap) {
87         return false;
88       }
89 
90       if (dest_width < 0)
91         dest_left += dest_width;
92       if (dest_height < 0)
93         dest_top += dest_height;
94 
95       dest_width = abs(dest_width);
96       dest_height = abs(dest_height);
97     }
98 
99     return GDI_StretchBitMask(std::move(bitmap), dest_left, dest_top,
100                               dest_width, dest_height, color);
101   }
102 
103   if (bitmap->IsAlphaFormat()) {
104     return false;
105   }
106 
107   if (dest_width < 0 || dest_height < 0) {
108     bitmap = bitmap->FlipImage(dest_width < 0, dest_height < 0);
109     if (!bitmap) {
110       return false;
111     }
112 
113     if (dest_width < 0)
114       dest_left += dest_width;
115     if (dest_height < 0)
116       dest_top += dest_height;
117 
118     dest_width = abs(dest_width);
119     dest_height = abs(dest_height);
120   }
121 
122   return GDI_StretchDIBits(std::move(bitmap), dest_left, dest_top, dest_width,
123                            dest_height, options);
124 }
125 
StartDIBits(RetainPtr<const CFX_DIBBase> bitmap,float alpha,uint32_t color,const CFX_Matrix & matrix,const FXDIB_ResampleOptions & options,BlendMode blend_type)126 RenderDeviceDriverIface::StartResult CGdiPrinterDriver::StartDIBits(
127     RetainPtr<const CFX_DIBBase> bitmap,
128     float alpha,
129     uint32_t color,
130     const CFX_Matrix& matrix,
131     const FXDIB_ResampleOptions& options,
132     BlendMode blend_type) {
133   if (alpha != 1.0f || bitmap->IsAlphaFormat() ||
134       (bitmap->IsMaskFormat() && (bitmap->GetBPP() != 1))) {
135     return {Result::kNotSupported, nullptr};
136   }
137   CFX_FloatRect unit_rect = matrix.GetUnitRect();
138   FX_RECT full_rect = unit_rect.GetOuterRect();
139   if (fabs(matrix.b) < 0.5f && matrix.a != 0 && fabs(matrix.c) < 0.5f &&
140       matrix.d != 0) {
141     bool bFlipX = matrix.a < 0;
142     bool bFlipY = matrix.d > 0;
143     bool success = StretchDIBits(
144         std::move(bitmap), color, bFlipX ? full_rect.right : full_rect.left,
145         bFlipY ? full_rect.bottom : full_rect.top,
146         bFlipX ? -full_rect.Width() : full_rect.Width(),
147         bFlipY ? -full_rect.Height() : full_rect.Height(), nullptr,
148         FXDIB_ResampleOptions(), blend_type);
149     return {success ? Result::kSuccess : Result::kFailure, nullptr};
150   }
151   if (fabs(matrix.a) >= 0.5f || fabs(matrix.d) >= 0.5f) {
152     return {Result::kNotSupported, nullptr};
153   }
154 
155   const bool flip_x = matrix.c > 0;
156   const bool flip_y = matrix.b < 0;
157   bitmap = bitmap->SwapXY(flip_x, flip_y);
158   if (!bitmap) {
159     return {Result::kFailure, nullptr};
160   }
161 
162   bool success =
163       StretchDIBits(std::move(bitmap), color, full_rect.left, full_rect.top,
164                     full_rect.Width(), full_rect.Height(), nullptr,
165                     FXDIB_ResampleOptions(), blend_type);
166   return {success ? Result::kSuccess : Result::kFailure, nullptr};
167 }
168 
DrawDeviceText(pdfium::span<const TextCharPos> pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t color,const CFX_TextRenderOptions &)169 bool CGdiPrinterDriver::DrawDeviceText(
170     pdfium::span<const TextCharPos> pCharPos,
171     CFX_Font* pFont,
172     const CFX_Matrix& mtObject2Device,
173     float font_size,
174     uint32_t color,
175     const CFX_TextRenderOptions& /*options*/) {
176   return false;
177 }
178