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