Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: core/fxge/win32/fx_win32_print.cpp

Issue 2113563003: Implement CGdiPrinterDriver::DrawDeviceText(). (Closed) Base URL: https://pdfium.googlesource.com/pdfium@master
Patch Set: rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fxge/include/fx_ge_win32.h ('k') | core/fxge/win32/win32_int.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include "core/fxge/include/fx_ge.h" 7 #include "core/fxge/include/fx_ge.h"
8 8
9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ 9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
10 10
11 #include <windows.h> 11 #include <windows.h>
12 12
13 #include <algorithm>
14
13 #include "core/fxge/dib/dib_int.h" 15 #include "core/fxge/dib/dib_int.h"
14 #include "core/fxge/ge/fx_text_int.h" 16 #include "core/fxge/ge/fx_text_int.h"
15 #include "core/fxge/include/fx_freetype.h" 17 #include "core/fxge/include/fx_freetype.h"
16 #include "core/fxge/include/fx_ge_win32.h" 18 #include "core/fxge/include/fx_ge_win32.h"
17 #include "core/fxge/win32/win32_int.h" 19 #include "core/fxge/win32/win32_int.h"
18 20
21 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
22 namespace {
23
24 class ScopedState {
25 public:
26 ScopedState(HDC hDC, HFONT hFont) : m_hDC(hDC) {
27 m_iState = SaveDC(m_hDC);
28 m_hFont = SelectObject(m_hDC, hFont);
29 }
30
31 ~ScopedState() {
32 HGDIOBJ hFont = SelectObject(m_hDC, m_hFont);
33 DeleteObject(hFont);
34 RestoreDC(m_hDC, m_iState);
35 }
36
37 private:
38 HDC m_hDC;
39 HGDIOBJ m_hFont;
40 int m_iState;
41
42 ScopedState(const ScopedState&) = delete;
43 void operator=(const ScopedState&) = delete;
44 };
45
46 } // namespace
47
48 bool g_pdfium_print_text_with_gdi = false;
49
50 PDFiumEnsureTypefaceCharactersAccessible g_pdfium_typeface_accessible_func =
51 nullptr;
52 #endif
53
19 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) 54 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC)
20 : CGdiDeviceDriver(hDC, FXDC_PRINTER), 55 : CGdiDeviceDriver(hDC, FXDC_PRINTER),
21 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), 56 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)),
22 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {} 57 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {}
23 58
24 CGdiPrinterDriver::~CGdiPrinterDriver() {} 59 CGdiPrinterDriver::~CGdiPrinterDriver() {}
25 60
26 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { 61 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const {
27 if (caps_id == FXDC_HORZ_SIZE) 62 if (caps_id == FXDC_HORZ_SIZE)
28 return m_HorzSize; 63 return m_HorzSize;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) { 174 FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) {
140 FX_BOOL bFlipX = pMatrix->a < 0; 175 FX_BOOL bFlipX = pMatrix->a < 0;
141 FX_BOOL bFlipY = pMatrix->d > 0; 176 FX_BOOL bFlipY = pMatrix->d > 0;
142 return StretchDIBits(pSource, color, 177 return StretchDIBits(pSource, color,
143 bFlipX ? full_rect.right : full_rect.left, 178 bFlipX ? full_rect.right : full_rect.left,
144 bFlipY ? full_rect.bottom : full_rect.top, 179 bFlipY ? full_rect.bottom : full_rect.top,
145 bFlipX ? -full_rect.Width() : full_rect.Width(), 180 bFlipX ? -full_rect.Width() : full_rect.Width(),
146 bFlipY ? -full_rect.Height() : full_rect.Height(), 181 bFlipY ? -full_rect.Height() : full_rect.Height(),
147 nullptr, 0, blend_type); 182 nullptr, 0, blend_type);
148 } 183 }
149 if (FXSYS_fabs(pMatrix->a) < 0.5f && FXSYS_fabs(pMatrix->d) < 0.5f) { 184 if (FXSYS_fabs(pMatrix->a) >= 0.5f || FXSYS_fabs(pMatrix->d) >= 0.5f)
150 std::unique_ptr<CFX_DIBitmap> pTransformed( 185 return FALSE;
151 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); 186
152 if (!pTransformed) 187 std::unique_ptr<CFX_DIBitmap> pTransformed(
188 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0));
189 if (!pTransformed)
190 return FALSE;
191
192 return StretchDIBits(pTransformed.get(), color, full_rect.left, full_rect.top,
193 full_rect.Width(), full_rect.Height(), nullptr, 0,
194 blend_type);
195 }
196
197 FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars,
198 const FXTEXT_CHARPOS* pCharPos,
199 CFX_Font* pFont,
200 CFX_FontCache* pCache,
201 const CFX_Matrix* pObject2Device,
202 FX_FLOAT font_size,
203 uint32_t color) {
204 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
205 if (!g_pdfium_print_text_with_gdi)
206 return FALSE;
207
208 if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont())
209 return FALSE;
210
211 // Font
212 //
213 // Note that |pFont| has the actual font to render with embedded within, but
214 // but unfortunately AddFontMemResourceEx() does not seem to cooperate.
215 // Loading font data to memory seems to work, but then enumerating the fonts
216 // fails to find it. This requires more investigation. In the meanwhile,
217 // assume the printing is happening on the machine that generated the PDF, so
218 // the embedded font, if not a web font, is available through GDI anyway.
219 // TODO(thestig): Figure out why AddFontMemResourceEx() does not work.
220 // Generalize this method to work for all PDFs with embedded fonts.
221 // In sandboxed environments, font loading may not work at all, so this may be
222 // the best possible effort.
223 LOGFONT lf = {};
224 lf.lfHeight = -font_size;
225 lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL;
226 lf.lfItalic = pFont->IsItalic();
227 lf.lfCharSet = DEFAULT_CHARSET;
228
229 const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode();
230 int iNameLen = std::min(wsName.GetLength(), LF_FACESIZE - 1);
231 memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * iNameLen);
232 lf.lfFaceName[iNameLen] = 0;
233
234 HFONT hFont = CreateFontIndirect(&lf);
235 if (!hFont)
236 return FALSE;
237
238 ScopedState state(m_hDC, hFont);
239 size_t nTextMetricSize = GetOutlineTextMetrics(m_hDC, 0, nullptr);
240 if (nTextMetricSize == 0) {
241 // Give up and fail if there is no way to get the font to try again.
242 if (!g_pdfium_typeface_accessible_func)
153 return FALSE; 243 return FALSE;
154 244
155 return StretchDIBits(pTransformed.get(), color, full_rect.left, 245 // Try to get the font. Any letter will do.
156 full_rect.top, full_rect.Width(), full_rect.Height(), 246 g_pdfium_typeface_accessible_func(&lf, L"A", 1);
157 nullptr, 0, blend_type); 247 nTextMetricSize = GetOutlineTextMetrics(m_hDC, 0, nullptr);
248 if (nTextMetricSize == 0)
249 return FALSE;
158 } 250 }
251
252 std::vector<BYTE> buf(nTextMetricSize);
253 OUTLINETEXTMETRIC* pTextMetric =
254 reinterpret_cast<OUTLINETEXTMETRIC*>(buf.data());
255 if (GetOutlineTextMetrics(m_hDC, nTextMetricSize, pTextMetric) == 0)
256 return FALSE;
257
258 // If the selected font is not the requested font, then bail out. This can
259 // happen with web fonts, for example.
260 wchar_t* wsSelectedName = reinterpret_cast<wchar_t*>(
261 buf.data() + reinterpret_cast<size_t>(pTextMetric->otmpFaceName));
262 if (wsName != wsSelectedName)
263 return FALSE;
264
265 // Transforms
266 SetGraphicsMode(m_hDC, GM_ADVANCED);
267 XFORM xform;
268 xform.eM11 = pObject2Device->GetA();
269 xform.eM12 = pObject2Device->GetB();
270 xform.eM21 = -pObject2Device->GetC();
271 xform.eM22 = -pObject2Device->GetD();
272 xform.eDx = pObject2Device->GetE();
273 xform.eDy = pObject2Device->GetF();
274 ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY);
275
276 // Color
277 int iUnusedAlpha;
278 FX_COLORREF rgb;
279 ArgbDecode(color, iUnusedAlpha, rgb);
280 SetTextColor(m_hDC, rgb);
281 SetBkMode(m_hDC, TRANSPARENT);
282
283 // Text
284 CFX_WideString wsText;
285 for (int i = 0; i < nChars; ++i) {
286 // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary
287 // values from PDFs.
288 const FXTEXT_CHARPOS& charpos = pCharPos[i];
289 ASSERT(charpos.m_OriginX == 0);
290 ASSERT(charpos.m_OriginY == 0);
291 ASSERT(charpos.m_AdjustMatrix[0] == 0);
292 ASSERT(charpos.m_AdjustMatrix[1] == 0);
293 ASSERT(charpos.m_AdjustMatrix[2] == 0);
294 ASSERT(charpos.m_AdjustMatrix[3] == 0);
295 wsText += charpos.m_GlyphIndex;
296 }
297
298 // Draw
299 SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE);
300 if (ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), nChars,
301 nullptr)) {
302 return TRUE;
303 }
304
305 // Give up and fail if there is no way to get the font to try again.
306 if (!g_pdfium_typeface_accessible_func)
307 return FALSE;
308
309 // Try to get the font and draw again.
310 g_pdfium_typeface_accessible_func(&lf, wsText.c_str(), nChars);
311 return ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(),
312 nChars, nullptr);
313 #else
159 return FALSE; 314 return FALSE;
315 #endif
160 } 316 }
161 317
162 #endif 318 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
OLDNEW
« no previous file with comments | « core/fxge/include/fx_ge_win32.h ('k') | core/fxge/win32/win32_int.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698