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