• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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/cps_printer_driver.h"
8 
9 #include <stdint.h>
10 
11 #include <sstream>
12 #include <utility>
13 
14 #include "core/fxcrt/check.h"
15 #include "core/fxcrt/compiler_specific.h"
16 #include "core/fxcrt/data_vector.h"
17 #include "core/fxcrt/fx_system.h"
18 #include "core/fxcrt/notreached.h"
19 #include "core/fxcrt/retain_ptr.h"
20 #include "core/fxge/agg/cfx_agg_imagerenderer.h"
21 #include "core/fxge/cfx_fillrenderoptions.h"
22 #include "core/fxge/cfx_path.h"
23 #include "core/fxge/dib/cfx_dibbase.h"
24 #include "core/fxge/dib/cfx_dibitmap.h"
25 #include "core/fxge/win32/cpsoutput.h"
26 
27 namespace {
28 
RenderingLevelFromWindowsPrintMode(WindowsPrintMode mode)29 CFX_PSRenderer::RenderingLevel RenderingLevelFromWindowsPrintMode(
30     WindowsPrintMode mode) {
31   switch (mode) {
32     case WindowsPrintMode::kPostScript2:
33     case WindowsPrintMode::kPostScript2PassThrough:
34       return CFX_PSRenderer::RenderingLevel::kLevel2;
35     case WindowsPrintMode::kPostScript3:
36     case WindowsPrintMode::kPostScript3PassThrough:
37       return CFX_PSRenderer::RenderingLevel::kLevel3;
38     case WindowsPrintMode::kPostScript3Type42:
39     case WindowsPrintMode::kPostScript3Type42PassThrough:
40       return CFX_PSRenderer::RenderingLevel::kLevel3Type42;
41     default:
42       // |mode| should be PostScript.
43       NOTREACHED_NORETURN();
44   }
45 }
46 
47 }  // namespace
48 
CPSPrinterDriver(HDC hDC,WindowsPrintMode mode,CFX_PSFontTracker * ps_font_tracker,const EncoderIface * encoder_iface)49 CPSPrinterDriver::CPSPrinterDriver(HDC hDC,
50                                    WindowsPrintMode mode,
51                                    CFX_PSFontTracker* ps_font_tracker,
52                                    const EncoderIface* encoder_iface)
53     : m_hDC(hDC), m_PSRenderer(ps_font_tracker, encoder_iface) {
54   CFX_PSRenderer::RenderingLevel level =
55       RenderingLevelFromWindowsPrintMode(mode);
56   CPSOutput::OutputMode output_mode =
57       (mode == WindowsPrintMode::kPostScript2 ||
58        mode == WindowsPrintMode::kPostScript3 ||
59        mode == WindowsPrintMode::kPostScript3Type42)
60           ? CPSOutput::OutputMode::kGdiComment
61           : CPSOutput::OutputMode::kExtEscape;
62 
63   m_HorzSize = ::GetDeviceCaps(m_hDC, HORZSIZE);
64   m_VertSize = ::GetDeviceCaps(m_hDC, VERTSIZE);
65   m_Width = ::GetDeviceCaps(m_hDC, HORZRES);
66   m_Height = ::GetDeviceCaps(m_hDC, VERTRES);
67   m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
68 
69   m_PSRenderer.Init(pdfium::MakeRetain<CPSOutput>(m_hDC, output_mode), level,
70                     m_Width, m_Height);
71   HRGN hRgn = ::CreateRectRgn(0, 0, 1, 1);
72   if (::GetClipRgn(m_hDC, hRgn) == 1) {
73     DWORD dwCount = ::GetRegionData(hRgn, 0, nullptr);
74     if (dwCount) {
75       DataVector<uint8_t> buffer(dwCount);
76       RGNDATA* pData = reinterpret_cast<RGNDATA*>(buffer.data());
77       if (::GetRegionData(hRgn, dwCount, pData)) {
78         CFX_Path path;
79         for (uint32_t i = 0; i < pData->rdh.nCount; i++) {
80           RECT* pRect = UNSAFE_TODO(
81               reinterpret_cast<RECT*>(pData->Buffer + pData->rdh.nRgnSize * i));
82           path.AppendRect(static_cast<float>(pRect->left),
83                           static_cast<float>(pRect->bottom),
84                           static_cast<float>(pRect->right),
85                           static_cast<float>(pRect->top));
86         }
87         m_PSRenderer.SetClip_PathFill(path, nullptr,
88                                       CFX_FillRenderOptions::WindingOptions());
89       }
90     }
91   }
92   ::DeleteObject(hRgn);
93 }
94 
95 CPSPrinterDriver::~CPSPrinterDriver() = default;
96 
GetDeviceType() const97 DeviceType CPSPrinterDriver::GetDeviceType() const {
98   return DeviceType::kPrinter;
99 }
100 
GetDeviceCaps(int caps_id) const101 int CPSPrinterDriver::GetDeviceCaps(int caps_id) const {
102   switch (caps_id) {
103     case FXDC_PIXEL_WIDTH:
104       return m_Width;
105     case FXDC_PIXEL_HEIGHT:
106       return m_Height;
107     case FXDC_BITS_PIXEL:
108       return m_nBitsPerPixel;
109     case FXDC_RENDER_CAPS:
110       return 0;
111     case FXDC_HORZ_SIZE:
112       return m_HorzSize;
113     case FXDC_VERT_SIZE:
114       return m_VertSize;
115     default:
116       NOTREACHED_NORETURN();
117   }
118 }
119 
SaveState()120 void CPSPrinterDriver::SaveState() {
121   m_PSRenderer.SaveState();
122 }
123 
RestoreState(bool bKeepSaved)124 void CPSPrinterDriver::RestoreState(bool bKeepSaved) {
125   m_PSRenderer.RestoreState(bKeepSaved);
126 }
127 
SetClip_PathFill(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_FillRenderOptions & fill_options)128 bool CPSPrinterDriver::SetClip_PathFill(
129     const CFX_Path& path,
130     const CFX_Matrix* pObject2Device,
131     const CFX_FillRenderOptions& fill_options) {
132   m_PSRenderer.SetClip_PathFill(path, pObject2Device, fill_options);
133   return true;
134 }
135 
SetClip_PathStroke(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)136 bool CPSPrinterDriver::SetClip_PathStroke(
137     const CFX_Path& path,
138     const CFX_Matrix* pObject2Device,
139     const CFX_GraphStateData* pGraphState) {
140   m_PSRenderer.SetClip_PathStroke(path, pObject2Device, pGraphState);
141   return true;
142 }
143 
DrawPath(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,FX_ARGB fill_color,FX_ARGB stroke_color,const CFX_FillRenderOptions & fill_options)144 bool CPSPrinterDriver::DrawPath(const CFX_Path& path,
145                                 const CFX_Matrix* pObject2Device,
146                                 const CFX_GraphStateData* pGraphState,
147                                 FX_ARGB fill_color,
148                                 FX_ARGB stroke_color,
149                                 const CFX_FillRenderOptions& fill_options) {
150   return m_PSRenderer.DrawPath(path, pObject2Device, pGraphState, fill_color,
151                                stroke_color, fill_options);
152 }
153 
GetClipBox() const154 FX_RECT CPSPrinterDriver::GetClipBox() const {
155   return m_PSRenderer.GetClipBox();
156 }
157 
SetDIBits(RetainPtr<const CFX_DIBBase> bitmap,uint32_t color,const FX_RECT & src_rect,int left,int top,BlendMode blend_type)158 bool CPSPrinterDriver::SetDIBits(RetainPtr<const CFX_DIBBase> bitmap,
159                                  uint32_t color,
160                                  const FX_RECT& src_rect,
161                                  int left,
162                                  int top,
163                                  BlendMode blend_type) {
164   if (blend_type != BlendMode::kNormal)
165     return false;
166   return m_PSRenderer.SetDIBits(std::move(bitmap), color, left, top);
167 }
168 
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)169 bool CPSPrinterDriver::StretchDIBits(RetainPtr<const CFX_DIBBase> bitmap,
170                                      uint32_t color,
171                                      int dest_left,
172                                      int dest_top,
173                                      int dest_width,
174                                      int dest_height,
175                                      const FX_RECT* pClipRect,
176                                      const FXDIB_ResampleOptions& options,
177                                      BlendMode blend_type) {
178   return blend_type == BlendMode::kNormal &&
179          m_PSRenderer.StretchDIBits(std::move(bitmap), color, dest_left,
180                                     dest_top, dest_width, dest_height, options);
181 }
182 
StartDIBits(RetainPtr<const CFX_DIBBase> bitmap,float alpha,uint32_t color,const CFX_Matrix & matrix,const FXDIB_ResampleOptions & options,BlendMode blend_type)183 RenderDeviceDriverIface::StartResult CPSPrinterDriver::StartDIBits(
184     RetainPtr<const CFX_DIBBase> bitmap,
185     float alpha,
186     uint32_t color,
187     const CFX_Matrix& matrix,
188     const FXDIB_ResampleOptions& options,
189     BlendMode blend_type) {
190   if (blend_type != BlendMode::kNormal || alpha != 1.0f) {
191     return {Result::kNotSupported, nullptr};
192   }
193 
194   bool success =
195       m_PSRenderer.DrawDIBits(std::move(bitmap), color, matrix, options);
196   return {success ? Result::kSuccess : Result::kFailure, nullptr};
197 }
198 
DrawDeviceText(pdfium::span<const TextCharPos> pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t color,const CFX_TextRenderOptions &)199 bool CPSPrinterDriver::DrawDeviceText(
200     pdfium::span<const TextCharPos> pCharPos,
201     CFX_Font* pFont,
202     const CFX_Matrix& mtObject2Device,
203     float font_size,
204     uint32_t color,
205     const CFX_TextRenderOptions& /*options*/) {
206   return m_PSRenderer.DrawText(pCharPos.size(), pCharPos.data(), pFont,
207                                mtObject2Device, font_size, color);
208 }
209 
MultiplyAlpha(float alpha)210 bool CPSPrinterDriver::MultiplyAlpha(float alpha) {
211   // PostScript doesn't support transparency. All callers are using
212   // `CFX_DIBitmap`-backed raster devices anyway.
213   NOTREACHED_NORETURN();
214 }
215 
MultiplyAlphaMask(RetainPtr<const CFX_DIBitmap> mask)216 bool CPSPrinterDriver::MultiplyAlphaMask(RetainPtr<const CFX_DIBitmap> mask) {
217   // PostScript doesn't support transparency. All callers are using
218   // `CFX_DIBitmap`-backed raster devices anyway.
219   NOTREACHED_NORETURN();
220 }
221