xref: /aosp_15_r20/external/pdfium/core/fxge/win32/cgdi_printer_driver.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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