xref: /aosp_15_r20/external/pdfium/core/fxge/win32/ctext_only_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 #include "core/fxge/win32/ctext_only_printer_driver.h"
6 
7 #include <limits.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <algorithm>
13 
14 #include "core/fxcrt/fx_string.h"
15 #include "core/fxcrt/fx_system.h"
16 #include "core/fxge/cfx_font.h"
17 #include "core/fxge/text_char_pos.h"
18 #include "third_party/base/check_op.h"
19 #include "third_party/base/notreached.h"
20 
CTextOnlyPrinterDriver(HDC hDC)21 CTextOnlyPrinterDriver::CTextOnlyPrinterDriver(HDC hDC)
22     : m_hDC(hDC),
23       m_Width(INT_MAX),
24       m_Height(INT_MAX),
25       m_HorzSize(INT_MAX),
26       m_VertSize(INT_MAX),
27       m_OriginY(0.0f),
28       m_SetOrigin(false) {
29   m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
30 }
31 
32 CTextOnlyPrinterDriver::~CTextOnlyPrinterDriver() = default;
33 
GetDeviceType() const34 DeviceType CTextOnlyPrinterDriver::GetDeviceType() const {
35   return DeviceType::kPrinter;
36 }
37 
GetDeviceCaps(int caps_id) const38 int CTextOnlyPrinterDriver::GetDeviceCaps(int caps_id) const {
39   switch (caps_id) {
40     case FXDC_PIXEL_WIDTH:
41       return m_Width;
42     case FXDC_PIXEL_HEIGHT:
43       return m_Height;
44     case FXDC_BITS_PIXEL:
45       return m_nBitsPerPixel;
46     case FXDC_RENDER_CAPS:
47       return 0;
48     case FXDC_HORZ_SIZE:
49       return m_HorzSize;
50     case FXDC_VERT_SIZE:
51       return m_VertSize;
52     default:
53       NOTREACHED();
54       return 0;
55   }
56 }
57 
SaveState()58 void CTextOnlyPrinterDriver::SaveState() {}
59 
RestoreState(bool bKeepSaved)60 void CTextOnlyPrinterDriver::RestoreState(bool bKeepSaved) {}
61 
SetClip_PathFill(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_FillRenderOptions & fill_options)62 bool CTextOnlyPrinterDriver::SetClip_PathFill(
63     const CFX_Path& path,
64     const CFX_Matrix* pObject2Device,
65     const CFX_FillRenderOptions& fill_options) {
66   return true;
67 }
68 
SetClip_PathStroke(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)69 bool CTextOnlyPrinterDriver::SetClip_PathStroke(
70     const CFX_Path& path,
71     const CFX_Matrix* pObject2Device,
72     const CFX_GraphStateData* pGraphState) {
73   return false;
74 }
75 
DrawPath(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,const CFX_FillRenderOptions & fill_options,BlendMode blend_type)76 bool CTextOnlyPrinterDriver::DrawPath(const CFX_Path& path,
77                                       const CFX_Matrix* pObject2Device,
78                                       const CFX_GraphStateData* pGraphState,
79                                       uint32_t fill_color,
80                                       uint32_t stroke_color,
81                                       const CFX_FillRenderOptions& fill_options,
82                                       BlendMode blend_type) {
83   return false;
84 }
85 
SetDIBits(const RetainPtr<CFX_DIBBase> & pBitmap,uint32_t color,const FX_RECT & src_rect,int left,int top,BlendMode blend_type)86 bool CTextOnlyPrinterDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pBitmap,
87                                        uint32_t color,
88                                        const FX_RECT& src_rect,
89                                        int left,
90                                        int top,
91                                        BlendMode blend_type) {
92   return false;
93 }
94 
GetClipBox(FX_RECT * pRect)95 bool CTextOnlyPrinterDriver::GetClipBox(FX_RECT* pRect) {
96   pRect->left = 0;
97   pRect->right = m_Width;
98   pRect->top = 0;
99   pRect->bottom = m_Height;
100   return true;
101 }
102 
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)103 bool CTextOnlyPrinterDriver::StretchDIBits(
104     const RetainPtr<CFX_DIBBase>& pBitmap,
105     uint32_t color,
106     int dest_left,
107     int dest_top,
108     int dest_width,
109     int dest_height,
110     const FX_RECT* pClipRect,
111     const FXDIB_ResampleOptions& options,
112     BlendMode blend_type) {
113   return false;
114 }
115 
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)116 bool CTextOnlyPrinterDriver::StartDIBits(
117     const RetainPtr<CFX_DIBBase>& pBitmap,
118     int bitmap_alpha,
119     uint32_t color,
120     const CFX_Matrix& matrix,
121     const FXDIB_ResampleOptions& options,
122     std::unique_ptr<CFX_ImageRenderer>* handle,
123     BlendMode blend_type) {
124   return false;
125 }
126 
DrawDeviceText(pdfium::span<const TextCharPos> pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t color,const CFX_TextRenderOptions &)127 bool CTextOnlyPrinterDriver::DrawDeviceText(
128     pdfium::span<const TextCharPos> pCharPos,
129     CFX_Font* pFont,
130     const CFX_Matrix& mtObject2Device,
131     float font_size,
132     uint32_t color,
133     const CFX_TextRenderOptions& /*options*/) {
134   if (g_pdfium_print_mode != WindowsPrintMode::kTextOnly)
135     return false;
136   if (pCharPos.empty() || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont())
137     return false;
138 
139   // Scale factor used to minimize the kerning problems caused by rounding
140   // errors below. Value chosen based on the title of https://crbug.com/18383
141   const double kScaleFactor = 10;
142 
143   // Detect new lines and add clrf characters (since this is Windows only).
144   // These characters are removed by SkPDF, but the new line information is
145   // preserved in the text location. clrf characters seem to be ignored by
146   // label printers that use this driver.
147   WideString wsText;
148   size_t len = pCharPos.size();
149   float fOffsetY = mtObject2Device.f * kScaleFactor;
150   if (m_SetOrigin && FXSYS_roundf(m_OriginY) != FXSYS_roundf(fOffsetY)) {
151     wsText += L"\r\n";
152     len += 2;
153   }
154   wsText.Reserve(len);
155   m_OriginY = fOffsetY;
156   m_SetOrigin = true;
157 
158   // Text
159   for (const auto& charpos : pCharPos) {
160     // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary
161     // values from PDFs.
162     DCHECK_EQ(charpos.m_AdjustMatrix[0], 0);
163     DCHECK_EQ(charpos.m_AdjustMatrix[1], 0);
164     DCHECK_EQ(charpos.m_AdjustMatrix[2], 0);
165     DCHECK_EQ(charpos.m_AdjustMatrix[3], 0);
166     DCHECK_EQ(charpos.m_Origin.y, 0);
167     wsText += charpos.m_Unicode;
168   }
169   ByteString text = wsText.ToDefANSI();
170   auto text_span = text.span();
171   while (!text_span.empty()) {
172     uint8_t buffer[1026];
173     size_t send_len = std::min<size_t>(text_span.size(), 1024);
174     *(reinterpret_cast<uint16_t*>(buffer)) = static_cast<uint16_t>(send_len);
175     memcpy(buffer + 2, text_span.data(), send_len);
176     ::GdiComment(m_hDC, static_cast<UINT>(send_len + 2), buffer);
177     text_span = text_span.subspan(send_len);
178   }
179   return true;
180 }
181 
MultiplyAlpha(float alpha)182 bool CTextOnlyPrinterDriver::MultiplyAlpha(float alpha) {
183   // Not needed. All callers are using `CFX_DIBitmap`-backed raster devices
184   // anyway.
185   NOTREACHED();
186   return false;
187 }
188 
MultiplyAlpha(const RetainPtr<CFX_DIBBase> & mask)189 bool CTextOnlyPrinterDriver::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& mask) {
190   // Not needed. All callers are using `CFX_DIBitmap`-backed raster devices
191   // anyway.
192   NOTREACHED();
193   return false;
194 }
195