| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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_ |
| OLD | NEW |