1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fxge/cfx_font.h" 8 9 #include <algorithm> 10 #include <limits> 11 #include <memory> 12 #include <utility> 13 #include <vector> 14 15 #include "core/fpdfapi/font/cpdf_font.h" 16 #include "core/fxcrt/fx_codepage.h" 17 #include "core/fxcrt/fx_stream.h" 18 #include "core/fxge/cfx_facecache.h" 19 #include "core/fxge/cfx_fontcache.h" 20 #include "core/fxge/cfx_fontmgr.h" 21 #include "core/fxge/cfx_gemodule.h" 22 #include "core/fxge/cfx_pathdata.h" 23 #include "core/fxge/cfx_substfont.h" 24 #include "core/fxge/fx_freetype.h" 25 #include "third_party/base/ptr_util.h" 26 27 #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em) 28 29 namespace { 30 31 constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000; 32 constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000; 33 34 struct OUTLINE_PARAMS { 35 CFX_PathData* m_pPath; 36 int m_CurX; 37 int m_CurY; 38 float m_CoordUnit; 39 }; 40 41 #ifdef PDF_ENABLE_XFA 42 43 unsigned long FTStreamRead(FXFT_Stream stream, 44 unsigned long offset, 45 unsigned char* buffer, 46 unsigned long count) { 47 if (count == 0) 48 return 0; 49 50 IFX_SeekableReadStream* pFile = 51 static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer); 52 return pFile && pFile->ReadBlock(buffer, offset, count) ? count : 0; 53 } 54 55 void FTStreamClose(FXFT_Stream stream) {} 56 57 bool LoadFileImp(FXFT_Library library, 58 FXFT_Face* Face, 59 const RetainPtr<IFX_SeekableReadStream>& pFile, 60 int32_t faceIndex, 61 std::unique_ptr<FXFT_StreamRec>* stream) { 62 auto stream1 = pdfium::MakeUnique<FXFT_StreamRec>(); 63 stream1->base = nullptr; 64 stream1->size = static_cast<unsigned long>(pFile->GetSize()); 65 stream1->pos = 0; 66 stream1->descriptor.pointer = static_cast<void*>(pFile.Get()); 67 stream1->close = FTStreamClose; 68 stream1->read = FTStreamRead; 69 FXFT_Open_Args args; 70 args.flags = FT_OPEN_STREAM; 71 args.stream = stream1.get(); 72 if (FXFT_Open_Face(library, &args, faceIndex, Face)) 73 return false; 74 if (stream) 75 *stream = std::move(stream1); 76 return true; 77 } 78 #endif // PDF_ENABLE_XFA 79 80 FXFT_Face FT_LoadFont(const uint8_t* pData, int size) { 81 return CFX_GEModule::Get()->GetFontMgr()->GetFixedFace(pData, size, 0); 82 } 83 84 void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { 85 std::vector<FX_PATHPOINT>& points = param->m_pPath->GetPoints(); 86 size_t size = points.size(); 87 88 if (size >= 2 && points[size - 2].IsTypeAndOpen(FXPT_TYPE::MoveTo) && 89 points[size - 2].m_Point == points[size - 1].m_Point) { 90 size -= 2; 91 } 92 if (size >= 4 && points[size - 4].IsTypeAndOpen(FXPT_TYPE::MoveTo) && 93 points[size - 3].IsTypeAndOpen(FXPT_TYPE::BezierTo) && 94 points[size - 3].m_Point == points[size - 4].m_Point && 95 points[size - 2].m_Point == points[size - 4].m_Point && 96 points[size - 1].m_Point == points[size - 4].m_Point) { 97 size -= 4; 98 } 99 points.resize(size); 100 } 101 102 int Outline_MoveTo(const FXFT_Vector* to, void* user) { 103 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user); 104 105 Outline_CheckEmptyContour(param); 106 107 param->m_pPath->ClosePath(); 108 param->m_pPath->AppendPoint( 109 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), 110 FXPT_TYPE::MoveTo, false); 111 112 param->m_CurX = to->x; 113 param->m_CurY = to->y; 114 return 0; 115 } 116 117 int Outline_LineTo(const FXFT_Vector* to, void* user) { 118 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user); 119 120 param->m_pPath->AppendPoint( 121 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), 122 FXPT_TYPE::LineTo, false); 123 124 param->m_CurX = to->x; 125 param->m_CurY = to->y; 126 return 0; 127 } 128 129 int Outline_ConicTo(const FXFT_Vector* control, 130 const FXFT_Vector* to, 131 void* user) { 132 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user); 133 134 param->m_pPath->AppendPoint( 135 CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / 136 param->m_CoordUnit, 137 (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / 138 param->m_CoordUnit), 139 FXPT_TYPE::BezierTo, false); 140 141 param->m_pPath->AppendPoint( 142 CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit, 143 (control->y + (to->y - control->y) / 3) / param->m_CoordUnit), 144 FXPT_TYPE::BezierTo, false); 145 146 param->m_pPath->AppendPoint( 147 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), 148 FXPT_TYPE::BezierTo, false); 149 150 param->m_CurX = to->x; 151 param->m_CurY = to->y; 152 return 0; 153 } 154 155 int Outline_CubicTo(const FXFT_Vector* control1, 156 const FXFT_Vector* control2, 157 const FXFT_Vector* to, 158 void* user) { 159 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user); 160 161 param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit, 162 control1->y / param->m_CoordUnit), 163 FXPT_TYPE::BezierTo, false); 164 165 param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit, 166 control2->y / param->m_CoordUnit), 167 FXPT_TYPE::BezierTo, false); 168 169 param->m_pPath->AppendPoint( 170 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), 171 FXPT_TYPE::BezierTo, false); 172 173 param->m_CurX = to->x; 174 param->m_CurY = to->y; 175 return 0; 176 } 177 178 } // namespace 179 180 const char CFX_Font::s_AngleSkew[] = { 181 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 182 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, 183 }; 184 185 const uint8_t CFX_Font::s_WeightPow[] = { 186 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 187 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, 188 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 189 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 190 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, 191 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 192 }; 193 194 const uint8_t CFX_Font::s_WeightPow_11[] = { 195 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, 196 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, 197 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 198 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, 199 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 200 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 201 }; 202 203 const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = { 204 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, 205 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, 206 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 207 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 208 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 209 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 210 }; 211 212 CFX_Font::CFX_Font() 213 : 214 m_Face(nullptr), 215 m_FaceCache(nullptr), 216 m_pFontData(nullptr), 217 m_pGsubData(nullptr), 218 m_dwSize(0), 219 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 220 m_pPlatformFont(nullptr), 221 #endif 222 m_bEmbedded(false), 223 m_bVertical(false) { 224 } 225 226 #ifdef PDF_ENABLE_XFA 227 void CFX_Font::SetFace(FXFT_Face face) { 228 ClearFaceCache(); 229 m_Face = face; 230 } 231 232 void CFX_Font::SetSubstFont(std::unique_ptr<CFX_SubstFont> subst) { 233 m_pSubstFont = std::move(subst); 234 } 235 #endif // PDF_ENABLE_XFA 236 237 CFX_Font::~CFX_Font() { 238 if (m_Face) { 239 #ifndef PDF_ENABLE_XFA 240 if (FXFT_Get_Face_External_Stream(m_Face)) { 241 FXFT_Clear_Face_External_Stream(m_Face); 242 } 243 #endif // PDF_ENABLE_XFA 244 DeleteFace(); 245 } 246 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 247 ReleasePlatformResource(); 248 #endif 249 } 250 251 void CFX_Font::DeleteFace() { 252 ClearFaceCache(); 253 if (m_bEmbedded) 254 FXFT_Done_Face(m_Face); 255 else 256 CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); 257 m_Face = nullptr; 258 } 259 260 void CFX_Font::LoadSubst(const ByteString& face_name, 261 bool bTrueType, 262 uint32_t flags, 263 int weight, 264 int italic_angle, 265 int CharsetCP, 266 bool bVertical) { 267 m_bEmbedded = false; 268 m_bVertical = bVertical; 269 m_pSubstFont = pdfium::MakeUnique<CFX_SubstFont>(); 270 m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont( 271 face_name, bTrueType, flags, weight, italic_angle, CharsetCP, 272 m_pSubstFont.get()); 273 if (m_Face) { 274 m_pFontData = FXFT_Get_Face_Stream_Base(m_Face); 275 m_dwSize = FXFT_Get_Face_Stream_Size(m_Face); 276 } 277 } 278 279 #ifdef PDF_ENABLE_XFA 280 bool CFX_Font::LoadFile(const RetainPtr<IFX_SeekableReadStream>& pFile, 281 int nFaceIndex) { 282 m_bEmbedded = false; 283 284 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); 285 pFontMgr->InitFTLibrary(); 286 287 FXFT_Library library = pFontMgr->GetFTLibrary(); 288 std::unique_ptr<FXFT_StreamRec> stream; 289 if (!LoadFileImp(library, &m_Face, pFile, nFaceIndex, &stream)) 290 return false; 291 292 m_pOwnedStream = std::move(stream); 293 FXFT_Set_Pixel_Sizes(m_Face, 0, 64); 294 return true; 295 } 296 #endif // PDF_ENABLE_XFA 297 298 int CFX_Font::GetGlyphWidth(uint32_t glyph_index) { 299 if (!m_Face) 300 return 0; 301 if (m_pSubstFont && m_pSubstFont->m_bFlagMM) 302 AdjustMMParams(glyph_index, 0, 0); 303 int err = FXFT_Load_Glyph( 304 m_Face, glyph_index, 305 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 306 if (err) 307 return 0; 308 309 int horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face); 310 if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt) 311 return 0; 312 313 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), horiAdvance); 314 } 315 316 bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) { 317 std::vector<uint8_t> temp(data, data + size); 318 m_pFontDataAllocation.swap(temp); 319 m_Face = FT_LoadFont(m_pFontDataAllocation.data(), size); 320 m_pFontData = m_pFontDataAllocation.data(); 321 m_bEmbedded = true; 322 m_dwSize = size; 323 return !!m_Face; 324 } 325 326 bool CFX_Font::IsTTFont() const { 327 return m_Face && FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; 328 } 329 330 int CFX_Font::GetAscent() const { 331 if (!m_Face) 332 return 0; 333 334 int ascender = FXFT_Get_Face_Ascender(m_Face); 335 if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt) 336 return 0; 337 338 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), ascender); 339 } 340 341 int CFX_Font::GetDescent() const { 342 if (!m_Face) 343 return 0; 344 345 int descender = FXFT_Get_Face_Descender(m_Face); 346 if (descender < kThousandthMinInt || descender > kThousandthMaxInt) 347 return 0; 348 349 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), descender); 350 } 351 352 bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { 353 if (!m_Face) 354 return false; 355 356 if (FXFT_Is_Face_Tricky(m_Face)) { 357 int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); 358 if (error) 359 return false; 360 361 error = FXFT_Load_Glyph(m_Face, glyph_index, 362 FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 363 if (error) 364 return false; 365 366 FXFT_BBox cbox; 367 FT_Glyph glyph; 368 error = FXFT_Get_Glyph(m_Face->glyph, &glyph); 369 if (error) 370 return false; 371 372 FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); 373 int pixel_size_x = m_Face->size->metrics.x_ppem, 374 pixel_size_y = m_Face->size->metrics.y_ppem; 375 if (pixel_size_x == 0 || pixel_size_y == 0) { 376 bbox.left = cbox.xMin; 377 bbox.right = cbox.xMax; 378 bbox.top = cbox.yMax; 379 bbox.bottom = cbox.yMin; 380 } else { 381 bbox.left = cbox.xMin * 1000 / pixel_size_x; 382 bbox.right = cbox.xMax * 1000 / pixel_size_x; 383 bbox.top = cbox.yMax * 1000 / pixel_size_y; 384 bbox.bottom = cbox.yMin * 1000 / pixel_size_y; 385 } 386 bbox.top = std::min(bbox.top, 387 static_cast<int32_t>(FXFT_Get_Face_Ascender(m_Face))); 388 bbox.bottom = std::max( 389 bbox.bottom, static_cast<int32_t>(FXFT_Get_Face_Descender(m_Face))); 390 FT_Done_Glyph(glyph); 391 return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; 392 } 393 if (FXFT_Load_Glyph( 394 m_Face, glyph_index, 395 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) { 396 return false; 397 } 398 int em = FXFT_Get_Face_UnitsPerEM(m_Face); 399 if (em == 0) { 400 bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face); 401 bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face); 402 bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face); 403 bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face); 404 } else { 405 bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em; 406 bbox.top = 407 (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * 408 1000 / em; 409 bbox.right = 410 (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * 411 1000 / em; 412 bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em; 413 } 414 return true; 415 } 416 417 bool CFX_Font::IsItalic() const { 418 if (!m_Face) 419 return false; 420 if (FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC) 421 return true; 422 423 ByteString str(FXFT_Get_Face_Style_Name(m_Face)); 424 str.MakeLower(); 425 return str.Contains("italic"); 426 } 427 428 bool CFX_Font::IsBold() const { 429 return m_Face && FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; 430 } 431 432 bool CFX_Font::IsFixedWidth() const { 433 return m_Face && FXFT_Is_Face_fixedwidth(m_Face) != 0; 434 } 435 436 ByteString CFX_Font::GetPsName() const { 437 if (!m_Face) 438 return ByteString(); 439 440 ByteString psName = FXFT_Get_Postscript_Name(m_Face); 441 if (psName.IsEmpty()) 442 psName = "Untitled"; 443 return psName; 444 } 445 446 ByteString CFX_Font::GetFamilyName() const { 447 if (!m_Face && !m_pSubstFont) 448 return ByteString(); 449 if (m_Face) 450 return ByteString(FXFT_Get_Face_Family_Name(m_Face)); 451 452 return m_pSubstFont->m_Family; 453 } 454 455 ByteString CFX_Font::GetFaceName() const { 456 if (!m_Face && !m_pSubstFont) 457 return ByteString(); 458 if (m_Face) { 459 ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face)); 460 ByteString facename = GetFamilyName(); 461 if (facename.IsEmpty()) 462 facename = "Untitled"; 463 if (!style.IsEmpty() && style != "Regular") 464 facename += " " + style; 465 return facename; 466 } 467 return m_pSubstFont->m_Family; 468 } 469 470 bool CFX_Font::GetBBox(FX_RECT& bbox) { 471 if (!m_Face) 472 return false; 473 474 int em = FXFT_Get_Face_UnitsPerEM(m_Face); 475 if (em == 0) { 476 bbox.left = FXFT_Get_Face_xMin(m_Face); 477 bbox.bottom = FXFT_Get_Face_yMax(m_Face); 478 bbox.top = FXFT_Get_Face_yMin(m_Face); 479 bbox.right = FXFT_Get_Face_xMax(m_Face); 480 } else { 481 bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em; 482 bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em; 483 bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em; 484 bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em; 485 } 486 return true; 487 } 488 489 CFX_FaceCache* CFX_Font::GetFaceCache() const { 490 if (!m_FaceCache) 491 m_FaceCache = CFX_GEModule::Get()->GetFontCache()->GetCachedFace(this); 492 return m_FaceCache.Get(); 493 } 494 495 void CFX_Font::ClearFaceCache() { 496 if (!m_FaceCache) 497 return; 498 499 m_FaceCache = nullptr; 500 CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this); 501 } 502 503 void CFX_Font::AdjustMMParams(int glyph_index, 504 int dest_width, 505 int weight) const { 506 FXFT_MM_Var pMasters = nullptr; 507 FXFT_Get_MM_Var(m_Face, &pMasters); 508 if (!pMasters) 509 return; 510 511 long coords[2]; 512 if (weight == 0) 513 coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; 514 else 515 coords[0] = weight; 516 517 if (dest_width == 0) { 518 coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 519 } else { 520 int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 521 int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 522 coords[1] = min_param; 523 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 524 FXFT_Load_Glyph(m_Face, glyph_index, 525 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 526 int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / 527 FXFT_Get_Face_UnitsPerEM(m_Face); 528 coords[1] = max_param; 529 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 530 FXFT_Load_Glyph(m_Face, glyph_index, 531 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 532 int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / 533 FXFT_Get_Face_UnitsPerEM(m_Face); 534 if (max_width == min_width) { 535 FXFT_Free(m_Face, pMasters); 536 return; 537 } 538 int param = min_param + (max_param - min_param) * (dest_width - min_width) / 539 (max_width - min_width); 540 coords[1] = param; 541 } 542 FXFT_Free(m_Face, pMasters); 543 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 544 } 545 546 CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index, 547 int dest_width) const { 548 if (!m_Face) 549 return nullptr; 550 FXFT_Set_Pixel_Sizes(m_Face, 0, 64); 551 FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; 552 if (m_pSubstFont) { 553 if (m_pSubstFont->m_ItalicAngle) { 554 int skew = m_pSubstFont->m_ItalicAngle; 555 // |skew| is nonpositive so |-skew| is used as the index. We need to make 556 // sure |skew| != INT_MIN since -INT_MIN is undefined. 557 if (skew <= 0 && skew != std::numeric_limits<int>::min() && 558 static_cast<size_t>(-skew) < kAngleSkewArraySize) { 559 skew = -s_AngleSkew[-skew]; 560 } else { 561 skew = -58; 562 } 563 if (m_bVertical) 564 ft_matrix.yx += ft_matrix.yy * skew / 100; 565 else 566 ft_matrix.xy -= ft_matrix.xx * skew / 100; 567 } 568 if (m_pSubstFont->m_bFlagMM) 569 AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); 570 } 571 ScopedFontTransform scoped_transform(m_Face, &ft_matrix); 572 int load_flags = FXFT_LOAD_NO_BITMAP; 573 if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) 574 load_flags |= FT_LOAD_NO_HINTING; 575 if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags)) 576 return nullptr; 577 if (m_pSubstFont && !m_pSubstFont->m_bFlagMM && 578 m_pSubstFont->m_Weight > 400) { 579 uint32_t index = (m_pSubstFont->m_Weight - 400) / 10; 580 index = std::min(index, static_cast<uint32_t>(kWeightPowArraySize - 1)); 581 int level = 0; 582 if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) 583 level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; 584 else 585 level = s_WeightPow[index] * 2; 586 FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); 587 } 588 589 FXFT_Outline_Funcs funcs; 590 funcs.move_to = Outline_MoveTo; 591 funcs.line_to = Outline_LineTo; 592 funcs.conic_to = Outline_ConicTo; 593 funcs.cubic_to = Outline_CubicTo; 594 funcs.shift = 0; 595 funcs.delta = 0; 596 597 OUTLINE_PARAMS params; 598 auto pPath = pdfium::MakeUnique<CFX_PathData>(); 599 params.m_pPath = pPath.get(); 600 params.m_CurX = params.m_CurY = 0; 601 params.m_CoordUnit = 64 * 64.0; 602 603 FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); 604 if (pPath->GetPoints().empty()) 605 return nullptr; 606 607 Outline_CheckEmptyContour(¶ms); 608 pPath->ClosePath(); 609 610 return pPath.release(); 611 } 612 613 const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index, 614 bool bFontStyle, 615 const CFX_Matrix* pMatrix, 616 int dest_width, 617 int anti_alias, 618 int& text_flags) const { 619 return GetFaceCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle, pMatrix, 620 dest_width, anti_alias, text_flags); 621 } 622 623 const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index, 624 int dest_width) const { 625 return GetFaceCache()->LoadGlyphPath(this, glyph_index, dest_width); 626 } 627 628 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ 629 CFX_TypeFace* CFX_Font::GetDeviceCache() const { 630 return GetFaceCache()->GetDeviceCache(this); 631 } 632 #endif 633