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

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

Issue 2197553002: Fix CGdiPrinterDriver::DrawDeviceText() to draw multiple characters. (Closed) Base URL: https://pdfium.googlesource.com/pdfium@master
Patch Set: Fix kerning Created 4 years, 4 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 | « no previous file | no next file » | 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/fxcrt/include/fx_system.h" 7 #include "core/fxcrt/include/fx_system.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
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 const CFX_Matrix* pObject2Device, 202 const CFX_Matrix* pObject2Device,
203 FX_FLOAT font_size, 203 FX_FLOAT font_size,
204 uint32_t color) { 204 uint32_t color) {
205 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) 205 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
206 if (!g_pdfium_print_text_with_gdi) 206 if (!g_pdfium_print_text_with_gdi)
207 return FALSE; 207 return FALSE;
208 208
209 if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) 209 if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont())
210 return FALSE; 210 return FALSE;
211 211
212 // Scale factor used to minimize the kerning problems caused by rounding
213 // errors below. Value choosen based on the title of https://crbug.com/18383
214 const double kScaleFactor = 10;
215
212 // Font 216 // Font
213 // 217 //
214 // Note that |pFont| has the actual font to render with embedded within, but 218 // Note that |pFont| has the actual font to render with embedded within, but
215 // but unfortunately AddFontMemResourceEx() does not seem to cooperate. 219 // but unfortunately AddFontMemResourceEx() does not seem to cooperate.
216 // Loading font data to memory seems to work, but then enumerating the fonts 220 // Loading font data to memory seems to work, but then enumerating the fonts
217 // fails to find it. This requires more investigation. In the meanwhile, 221 // fails to find it. This requires more investigation. In the meanwhile,
218 // assume the printing is happening on the machine that generated the PDF, so 222 // assume the printing is happening on the machine that generated the PDF, so
219 // the embedded font, if not a web font, is available through GDI anyway. 223 // the embedded font, if not a web font, is available through GDI anyway.
220 // TODO(thestig): Figure out why AddFontMemResourceEx() does not work. 224 // TODO(thestig): Figure out why AddFontMemResourceEx() does not work.
221 // Generalize this method to work for all PDFs with embedded fonts. 225 // Generalize this method to work for all PDFs with embedded fonts.
222 // In sandboxed environments, font loading may not work at all, so this may be 226 // In sandboxed environments, font loading may not work at all, so this may be
223 // the best possible effort. 227 // the best possible effort.
224 LOGFONT lf = {}; 228 LOGFONT lf = {};
225 lf.lfHeight = -font_size; 229 lf.lfHeight = -font_size * kScaleFactor;
226 lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL; 230 lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL;
227 lf.lfItalic = pFont->IsItalic(); 231 lf.lfItalic = pFont->IsItalic();
228 lf.lfCharSet = DEFAULT_CHARSET; 232 lf.lfCharSet = DEFAULT_CHARSET;
229 233
230 const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode(); 234 const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode();
231 int iNameLen = std::min(wsName.GetLength(), LF_FACESIZE - 1); 235 int iNameLen = std::min(wsName.GetLength(), LF_FACESIZE - 1);
232 memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * iNameLen); 236 memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * iNameLen);
233 lf.lfFaceName[iNameLen] = 0; 237 lf.lfFaceName[iNameLen] = 0;
234 238
235 HFONT hFont = CreateFontIndirect(&lf); 239 HFONT hFont = CreateFontIndirect(&lf);
(...skipping 23 matching lines...) Expand all
259 // If the selected font is not the requested font, then bail out. This can 263 // If the selected font is not the requested font, then bail out. This can
260 // happen with web fonts, for example. 264 // happen with web fonts, for example.
261 wchar_t* wsSelectedName = reinterpret_cast<wchar_t*>( 265 wchar_t* wsSelectedName = reinterpret_cast<wchar_t*>(
262 buf.data() + reinterpret_cast<size_t>(pTextMetric->otmpFaceName)); 266 buf.data() + reinterpret_cast<size_t>(pTextMetric->otmpFaceName));
263 if (wsName != wsSelectedName) 267 if (wsName != wsSelectedName)
264 return FALSE; 268 return FALSE;
265 269
266 // Transforms 270 // Transforms
267 SetGraphicsMode(m_hDC, GM_ADVANCED); 271 SetGraphicsMode(m_hDC, GM_ADVANCED);
268 XFORM xform; 272 XFORM xform;
269 xform.eM11 = pObject2Device->GetA(); 273 xform.eM11 = pObject2Device->GetA() / kScaleFactor;
270 xform.eM12 = pObject2Device->GetB(); 274 xform.eM12 = pObject2Device->GetB() / kScaleFactor;
271 xform.eM21 = -pObject2Device->GetC(); 275 xform.eM21 = -pObject2Device->GetC() / kScaleFactor;
272 xform.eM22 = -pObject2Device->GetD(); 276 xform.eM22 = -pObject2Device->GetD() / kScaleFactor;
273 xform.eDx = pObject2Device->GetE(); 277 xform.eDx = pObject2Device->GetE();
274 xform.eDy = pObject2Device->GetF(); 278 xform.eDy = pObject2Device->GetF();
275 ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY); 279 ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY);
276 280
277 // Color 281 // Color
278 int iUnusedAlpha; 282 int iUnusedAlpha;
279 FX_COLORREF rgb; 283 FX_COLORREF rgb;
280 ArgbDecode(color, iUnusedAlpha, rgb); 284 ArgbDecode(color, iUnusedAlpha, rgb);
281 SetTextColor(m_hDC, rgb); 285 SetTextColor(m_hDC, rgb);
282 SetBkMode(m_hDC, TRANSPARENT); 286 SetBkMode(m_hDC, TRANSPARENT);
283 287
284 // Text 288 // Text
285 CFX_WideString wsText; 289 CFX_WideString wsText;
290 std::vector<INT> spacing(nChars);
291 FX_FLOAT fPreviousOriginX = 0;
286 for (int i = 0; i < nChars; ++i) { 292 for (int i = 0; i < nChars; ++i) {
287 // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary 293 // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary
288 // values from PDFs. 294 // values from PDFs.
289 const FXTEXT_CHARPOS& charpos = pCharPos[i]; 295 const FXTEXT_CHARPOS& charpos = pCharPos[i];
290 ASSERT(charpos.m_OriginX == 0);
291 ASSERT(charpos.m_OriginY == 0);
292 ASSERT(charpos.m_AdjustMatrix[0] == 0); 296 ASSERT(charpos.m_AdjustMatrix[0] == 0);
293 ASSERT(charpos.m_AdjustMatrix[1] == 0); 297 ASSERT(charpos.m_AdjustMatrix[1] == 0);
294 ASSERT(charpos.m_AdjustMatrix[2] == 0); 298 ASSERT(charpos.m_AdjustMatrix[2] == 0);
295 ASSERT(charpos.m_AdjustMatrix[3] == 0); 299 ASSERT(charpos.m_AdjustMatrix[3] == 0);
300 ASSERT(charpos.m_OriginY == 0);
301
302 // Round the spacing to the nearest integer, but keep track of the rounding
303 // error for calculating the next spacing value.
304 FX_FLOAT fOriginX = charpos.m_OriginX * kScaleFactor;
305 FX_FLOAT fPixelSpacing = fOriginX - fPreviousOriginX;
306 spacing[i] = FXSYS_round(fPixelSpacing);
307 fPreviousOriginX = fOriginX - (fPixelSpacing - spacing[i]);
308
296 wsText += charpos.m_GlyphIndex; 309 wsText += charpos.m_GlyphIndex;
297 } 310 }
298 311
299 // Draw 312 // Draw
300 SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE); 313 SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE);
301 if (ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), nChars, 314 if (ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), nChars,
302 nullptr)) { 315 nChars > 1 ? &spacing[1] : nullptr)) {
303 return TRUE; 316 return TRUE;
304 } 317 }
305 318
306 // Give up and fail if there is no way to get the font to try again. 319 // Give up and fail if there is no way to get the font to try again.
307 if (!g_pdfium_typeface_accessible_func) 320 if (!g_pdfium_typeface_accessible_func)
308 return FALSE; 321 return FALSE;
309 322
310 // Try to get the font and draw again. 323 // Try to get the font and draw again.
311 g_pdfium_typeface_accessible_func(&lf, wsText.c_str(), nChars); 324 g_pdfium_typeface_accessible_func(&lf, wsText.c_str(), nChars);
312 return ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), 325 return ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(),
313 nChars, nullptr); 326 nChars, nChars > 1 ? &spacing[1] : nullptr);
314 #else 327 #else
315 return FALSE; 328 return FALSE;
316 #endif 329 #endif
317 } 330 }
318 331
319 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ 332 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698