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