1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkAdvancedTypefaceMetrics.h" 9 #include "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkColorData.h" 12 #include "SkDescriptor.h" 13 #include "SkFDot6.h" 14 #include "SkFontDescriptor.h" 15 #include "SkFontHost_FreeType_common.h" 16 #include "SkGlyph.h" 17 #include "SkMakeUnique.h" 18 #include "SkMask.h" 19 #include "SkMaskGamma.h" 20 #include "SkMatrix22.h" 21 #include "SkMalloc.h" 22 #include "SkMutex.h" 23 #include "SkOTUtils.h" 24 #include "SkPath.h" 25 #include "SkScalerContext.h" 26 #include "SkStream.h" 27 #include "SkString.h" 28 #include "SkTemplates.h" 29 #include <memory> 30 31 #include <ft2build.h> 32 #include FT_ADVANCES_H 33 #include FT_BITMAP_H 34 #include FT_FREETYPE_H 35 #include FT_LCD_FILTER_H 36 #include FT_MODULE_H 37 #include FT_MULTIPLE_MASTERS_H 38 #include FT_OUTLINE_H 39 #include FT_SIZES_H 40 #include FT_SYSTEM_H 41 #include FT_TRUETYPE_TABLES_H 42 #include FT_TYPE1_TABLES_H 43 #include FT_XFREE86_H 44 45 // SK_FREETYPE_MINIMUM_RUNTIME_VERSION 0x<major><minor><patch><flags> 46 // Flag SK_FREETYPE_DLOPEN: also try dlopen to get newer features. 47 #define SK_FREETYPE_DLOPEN (0x1) 48 #ifndef SK_FREETYPE_MINIMUM_RUNTIME_VERSION 49 # if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) || defined (SK_BUILD_FOR_GOOGLE3) 50 # define SK_FREETYPE_MINIMUM_RUNTIME_VERSION (((FREETYPE_MAJOR) << 24) | ((FREETYPE_MINOR) << 16) | ((FREETYPE_PATCH) << 8)) 51 # else 52 # define SK_FREETYPE_MINIMUM_RUNTIME_VERSION ((2 << 24) | (3 << 16) | (11 << 8) | (SK_FREETYPE_DLOPEN)) 53 # endif 54 #endif 55 #if SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 56 # include <dlfcn.h> 57 #endif 58 59 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 60 // were introduced in FreeType 2.5.0. 61 // The following may be removed once FreeType 2.5.0 is required to build. 62 #ifndef FT_LOAD_COLOR 63 # define FT_LOAD_COLOR ( 1L << 20 ) 64 # define FT_PIXEL_MODE_BGRA 7 65 #endif 66 67 // FT_LOAD_BITMAP_METRICS_ONLY was introduced in FreeType 2.7.1 68 // The following may be removed once FreeType 2.7.1 is required to build. 69 #ifndef FT_LOAD_BITMAP_METRICS_ONLY 70 # define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) 71 #endif 72 73 //#define ENABLE_GLYPH_SPEW // for tracing calls 74 //#define DUMP_STRIKE_CREATION 75 //#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION 76 //#define SK_GAMMA_APPLY_TO_A8 77 78 static bool isLCD(const SkScalerContextRec& rec) { 79 return SkMask::kLCD16_Format == rec.fMaskFormat; 80 } 81 82 ////////////////////////////////////////////////////////////////////////// 83 84 extern "C" { 85 static void* sk_ft_alloc(FT_Memory, long size) { 86 return sk_malloc_throw(size); 87 } 88 static void sk_ft_free(FT_Memory, void* block) { 89 sk_free(block); 90 } 91 static void* sk_ft_realloc(FT_Memory, long cur_size, long new_size, void* block) { 92 return sk_realloc_throw(block, new_size); 93 } 94 }; 95 FT_MemoryRec_ gFTMemory = { nullptr, sk_ft_alloc, sk_ft_free, sk_ft_realloc }; 96 97 class FreeTypeLibrary : SkNoncopyable { 98 public: 99 FreeTypeLibrary() 100 : fGetVarDesignCoordinates(nullptr) 101 , fLibrary(nullptr) 102 , fIsLCDSupported(false) 103 , fLCDExtra(0) 104 { 105 if (FT_New_Library(&gFTMemory, &fLibrary)) { 106 return; 107 } 108 FT_Add_Default_Modules(fLibrary); 109 110 // When using dlsym 111 // *(void**)(&procPtr) = dlsym(self, "proc"); 112 // is non-standard, but safe for POSIX. Cannot write 113 // *reinterpret_cast<void**>(&procPtr) = dlsym(self, "proc"); 114 // because clang has not implemented DR573. See http://clang.llvm.org/cxx_dr_status.html . 115 116 FT_Int major, minor, patch; 117 FT_Library_Version(fLibrary, &major, &minor, &patch); 118 119 #if SK_FREETYPE_MINIMUM_RUNTIME_VERSION >= 0x02070100 120 fGetVarDesignCoordinates = FT_Get_Var_Design_Coordinates; 121 #elif SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 122 if (major > 2 || ((major == 2 && minor > 7) || (major == 2 && minor == 7 && patch >= 0))) { 123 //The FreeType library is already loaded, so symbols are available in process. 124 void* self = dlopen(nullptr, RTLD_LAZY); 125 if (self) { 126 *(void**)(&fGetVarDesignCoordinates) = dlsym(self, "FT_Get_Var_Design_Coordinates"); 127 dlclose(self); 128 } 129 } 130 #endif 131 132 #if SK_FREETYPE_MINIMUM_RUNTIME_VERSION >= 0x02070200 133 FT_Set_Default_Properties(fLibrary); 134 #elif SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 135 if (major > 2 || ((major == 2 && minor > 7) || (major == 2 && minor == 7 && patch >= 1))) { 136 //The FreeType library is already loaded, so symbols are available in process. 137 void* self = dlopen(nullptr, RTLD_LAZY); 138 if (self) { 139 FT_Set_Default_PropertiesProc setDefaultProperties; 140 *(void**)(&setDefaultProperties) = dlsym(self, "FT_Set_Default_Properties"); 141 dlclose(self); 142 143 if (setDefaultProperties) { 144 setDefaultProperties(fLibrary); 145 } 146 } 147 } 148 #endif 149 150 // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs. 151 // The default has changed over time, so this doesn't mean the same thing to all users. 152 if (FT_Library_SetLcdFilter(fLibrary, FT_LCD_FILTER_DEFAULT) == 0) { 153 fIsLCDSupported = true; 154 fLCDExtra = 2; //Using a filter adds one full pixel to each side. 155 } 156 } 157 ~FreeTypeLibrary() { 158 if (fLibrary) { 159 FT_Done_Library(fLibrary); 160 } 161 } 162 163 FT_Library library() { return fLibrary; } 164 bool isLCDSupported() { return fIsLCDSupported; } 165 int lcdExtra() { return fLCDExtra; } 166 167 // FT_Get_{MM,Var}_{Blend,Design}_Coordinates were added in FreeType 2.7.1. 168 // Prior to this there was no way to get the coordinates out of the FT_Face. 169 // This wasn't too bad because you needed to specify them anyway, and the clamp was provided. 170 // However, this doesn't work when face_index specifies named variations as introduced in 2.6.1. 171 using FT_Get_Var_Blend_CoordinatesProc = FT_Error (*)(FT_Face, FT_UInt, FT_Fixed*); 172 FT_Get_Var_Blend_CoordinatesProc fGetVarDesignCoordinates; 173 174 private: 175 FT_Library fLibrary; 176 bool fIsLCDSupported; 177 int fLCDExtra; 178 179 // FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. 180 // The following platforms provide FreeType of at least 2.4.0. 181 // Ubuntu >= 11.04 (previous deprecated April 2013) 182 // Debian >= 6.0 (good) 183 // OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2) 184 // Fedora >= 14 (good) 185 // Android >= Gingerbread (good) 186 // RHEL >= 7 (6 has 2.3.11, EOL Nov 2020, Phase 3 May 2017) 187 using FT_Library_SetLcdFilterWeightsProc = FT_Error (*)(FT_Library, unsigned char*); 188 189 // FreeType added the ability to read global properties in 2.7.0. After 2.7.1 a means for users 190 // of FT_New_Library to request these global properties to be read was added. 191 using FT_Set_Default_PropertiesProc = void (*)(FT_Library); 192 }; 193 194 struct SkFaceRec; 195 196 SK_DECLARE_STATIC_MUTEX(gFTMutex); 197 static FreeTypeLibrary* gFTLibrary; 198 static SkFaceRec* gFaceRecHead; 199 200 // Private to ref_ft_library and unref_ft_library 201 static int gFTCount; 202 203 // Caller must lock gFTMutex before calling this function. 204 static bool ref_ft_library() { 205 gFTMutex.assertHeld(); 206 SkASSERT(gFTCount >= 0); 207 208 if (0 == gFTCount) { 209 SkASSERT(nullptr == gFTLibrary); 210 gFTLibrary = new FreeTypeLibrary; 211 } 212 ++gFTCount; 213 return gFTLibrary->library(); 214 } 215 216 // Caller must lock gFTMutex before calling this function. 217 static void unref_ft_library() { 218 gFTMutex.assertHeld(); 219 SkASSERT(gFTCount > 0); 220 221 --gFTCount; 222 if (0 == gFTCount) { 223 SkASSERT(nullptr == gFaceRecHead); 224 SkASSERT(nullptr != gFTLibrary); 225 delete gFTLibrary; 226 SkDEBUGCODE(gFTLibrary = nullptr;) 227 } 228 } 229 230 /////////////////////////////////////////////////////////////////////////// 231 232 struct SkFaceRec { 233 SkFaceRec* fNext; 234 std::unique_ptr<FT_FaceRec, SkFunctionWrapper<FT_Error, FT_FaceRec, FT_Done_Face>> fFace; 235 FT_StreamRec fFTStream; 236 std::unique_ptr<SkStreamAsset> fSkStream; 237 uint32_t fRefCnt; 238 uint32_t fFontID; 239 240 // FreeType prior to 2.7.1 does not implement retreiving variation design metrics. 241 // Cache the variation design metrics used to create the font if the user specifies them. 242 SkAutoSTMalloc<4, SkFixed> fAxes; 243 int fAxesCount; 244 245 // FreeType from 2.6.1 (14d6b5d7) until 2.7.0 (ee3f36f6b38) uses font_index for both font index 246 // and named variation index on input, but masks the named variation index part on output. 247 // Manually keep track of when a named variation is requested for 2.6.1 until 2.7.1. 248 bool fNamedVariationSpecified; 249 250 SkFaceRec(std::unique_ptr<SkStreamAsset> stream, uint32_t fontID); 251 }; 252 253 extern "C" { 254 static unsigned long sk_ft_stream_io(FT_Stream ftStream, 255 unsigned long offset, 256 unsigned char* buffer, 257 unsigned long count) 258 { 259 SkStreamAsset* stream = static_cast<SkStreamAsset*>(ftStream->descriptor.pointer); 260 261 if (count) { 262 if (!stream->seek(offset)) { 263 return 0; 264 } 265 count = stream->read(buffer, count); 266 } 267 return count; 268 } 269 270 static void sk_ft_stream_close(FT_Stream) {} 271 } 272 273 SkFaceRec::SkFaceRec(std::unique_ptr<SkStreamAsset> stream, uint32_t fontID) 274 : fNext(nullptr), fSkStream(std::move(stream)), fRefCnt(1), fFontID(fontID) 275 , fAxesCount(0), fNamedVariationSpecified(false) 276 { 277 sk_bzero(&fFTStream, sizeof(fFTStream)); 278 fFTStream.size = fSkStream->getLength(); 279 fFTStream.descriptor.pointer = fSkStream.get(); 280 fFTStream.read = sk_ft_stream_io; 281 fFTStream.close = sk_ft_stream_close; 282 } 283 284 static void ft_face_setup_axes(SkFaceRec* rec, const SkFontData& data) { 285 if (!(rec->fFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { 286 return; 287 } 288 289 // If a named variation is requested, don't overwrite the named variation's position. 290 if (data.getIndex() > 0xFFFF) { 291 rec->fNamedVariationSpecified = true; 292 return; 293 } 294 295 SkDEBUGCODE( 296 FT_MM_Var* variations = nullptr; 297 if (FT_Get_MM_Var(rec->fFace.get(), &variations)) { 298 SkDEBUGF(("INFO: font %s claims variations, but none found.\n", 299 rec->fFace->family_name)); 300 return; 301 } 302 SkAutoFree autoFreeVariations(variations); 303 304 if (static_cast<FT_UInt>(data.getAxisCount()) != variations->num_axis) { 305 SkDEBUGF(("INFO: font %s has %d variations, but %d were specified.\n", 306 rec->fFace->family_name, variations->num_axis, data.getAxisCount())); 307 return; 308 } 309 ) 310 311 SkAutoSTMalloc<4, FT_Fixed> coords(data.getAxisCount()); 312 for (int i = 0; i < data.getAxisCount(); ++i) { 313 coords[i] = data.getAxis()[i]; 314 } 315 if (FT_Set_Var_Design_Coordinates(rec->fFace.get(), data.getAxisCount(), coords.get())) { 316 SkDEBUGF(("INFO: font %s has variations, but specified variations could not be set.\n", 317 rec->fFace->family_name)); 318 return; 319 } 320 321 rec->fAxesCount = data.getAxisCount(); 322 rec->fAxes.reset(rec->fAxesCount); 323 for (int i = 0; i < rec->fAxesCount; ++i) { 324 rec->fAxes[i] = data.getAxis()[i]; 325 } 326 } 327 328 // Will return nullptr on failure 329 // Caller must lock gFTMutex before calling this function. 330 static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { 331 gFTMutex.assertHeld(); 332 333 const SkFontID fontID = typeface->uniqueID(); 334 SkFaceRec* cachedRec = gFaceRecHead; 335 while (cachedRec) { 336 if (cachedRec->fFontID == fontID) { 337 SkASSERT(cachedRec->fFace); 338 cachedRec->fRefCnt += 1; 339 return cachedRec; 340 } 341 cachedRec = cachedRec->fNext; 342 } 343 344 std::unique_ptr<SkFontData> data = typeface->makeFontData(); 345 if (nullptr == data || !data->hasStream()) { 346 return nullptr; 347 } 348 349 std::unique_ptr<SkFaceRec> rec(new SkFaceRec(data->detachStream(), fontID)); 350 351 FT_Open_Args args; 352 memset(&args, 0, sizeof(args)); 353 const void* memoryBase = rec->fSkStream->getMemoryBase(); 354 if (memoryBase) { 355 args.flags = FT_OPEN_MEMORY; 356 args.memory_base = (const FT_Byte*)memoryBase; 357 args.memory_size = rec->fSkStream->getLength(); 358 } else { 359 args.flags = FT_OPEN_STREAM; 360 args.stream = &rec->fFTStream; 361 } 362 363 { 364 FT_Face rawFace; 365 FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, data->getIndex(), &rawFace); 366 if (err) { 367 SK_TRACEFTR(err, "unable to open font '%x'", fontID); 368 return nullptr; 369 } 370 rec->fFace.reset(rawFace); 371 } 372 SkASSERT(rec->fFace); 373 374 ft_face_setup_axes(rec.get(), *data); 375 376 // FreeType will set the charmap to the "most unicode" cmap if it exists. 377 // If there are no unicode cmaps, the charmap is set to nullptr. 378 // However, "symbol" cmaps should also be considered "fallback unicode" cmaps 379 // because they are effectively private use area only (even if they aren't). 380 // This is the last on the fallback list at 381 // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html 382 if (!rec->fFace->charmap) { 383 FT_Select_Charmap(rec->fFace.get(), FT_ENCODING_MS_SYMBOL); 384 } 385 386 rec->fNext = gFaceRecHead; 387 gFaceRecHead = rec.get(); 388 return rec.release(); 389 } 390 391 // Caller must lock gFTMutex before calling this function. 392 // Marked extern because vc++ does not support internal linkage template parameters. 393 extern /*static*/ void unref_ft_face(SkFaceRec* faceRec) { 394 gFTMutex.assertHeld(); 395 396 SkFaceRec* rec = gFaceRecHead; 397 SkFaceRec* prev = nullptr; 398 while (rec) { 399 SkFaceRec* next = rec->fNext; 400 if (rec->fFace == faceRec->fFace) { 401 if (--rec->fRefCnt == 0) { 402 if (prev) { 403 prev->fNext = next; 404 } else { 405 gFaceRecHead = next; 406 } 407 delete rec; 408 } 409 return; 410 } 411 prev = rec; 412 rec = next; 413 } 414 SkDEBUGFAIL("shouldn't get here, face not in list"); 415 } 416 417 class AutoFTAccess { 418 public: 419 AutoFTAccess(const SkTypeface* tf) : fFaceRec(nullptr) { 420 gFTMutex.acquire(); 421 SkASSERT_RELEASE(ref_ft_library()); 422 fFaceRec = ref_ft_face(tf); 423 } 424 425 ~AutoFTAccess() { 426 if (fFaceRec) { 427 unref_ft_face(fFaceRec); 428 } 429 unref_ft_library(); 430 gFTMutex.release(); 431 } 432 433 FT_Face face() { return fFaceRec ? fFaceRec->fFace.get() : nullptr; } 434 int getAxesCount() { return fFaceRec ? fFaceRec->fAxesCount : 0; } 435 SkFixed* getAxes() { return fFaceRec ? fFaceRec->fAxes.get() : nullptr; } 436 bool isNamedVariationSpecified() { 437 return fFaceRec ? fFaceRec->fNamedVariationSpecified : false; 438 } 439 440 private: 441 SkFaceRec* fFaceRec; 442 }; 443 444 /////////////////////////////////////////////////////////////////////////// 445 446 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { 447 public: 448 SkScalerContext_FreeType(sk_sp<SkTypeface>, 449 const SkScalerContextEffects&, 450 const SkDescriptor* desc); 451 ~SkScalerContext_FreeType() override; 452 453 bool success() const { 454 return fFTSize != nullptr && fFace != nullptr; 455 } 456 457 protected: 458 unsigned generateGlyphCount() override; 459 uint16_t generateCharToGlyph(SkUnichar uni) override; 460 void generateAdvance(SkGlyph* glyph) override; 461 void generateMetrics(SkGlyph* glyph) override; 462 void generateImage(const SkGlyph& glyph) override; 463 void generatePath(SkGlyphID glyphID, SkPath* path) override; 464 void generateFontMetrics(SkPaint::FontMetrics*) override; 465 SkUnichar generateGlyphToChar(uint16_t glyph) override; 466 467 private: 468 using UnrefFTFace = SkFunctionWrapper<void, SkFaceRec, unref_ft_face>; 469 std::unique_ptr<SkFaceRec, UnrefFTFace> fFaceRec; 470 471 FT_Face fFace; // Borrowed face from gFaceRecHead. 472 FT_Size fFTSize; // The size on the fFace for this scaler. 473 FT_Int fStrikeIndex; 474 475 /** The rest of the matrix after FreeType handles the size. 476 * With outline font rasterization this is handled by FreeType with FT_Set_Transform. 477 * With bitmap only fonts this matrix must be applied to scale the bitmap. 478 */ 479 SkMatrix fMatrix22Scalar; 480 /** Same as fMatrix22Scalar, but in FreeType units and space. */ 481 FT_Matrix fMatrix22; 482 /** The actual size requested. */ 483 SkVector fScale; 484 485 uint32_t fLoadGlyphFlags; 486 bool fDoLinearMetrics; 487 bool fLCDIsVert; 488 489 FT_Error setupSize(); 490 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 491 bool snapToPixelBoundary = false); 492 bool getCBoxForLetter(char letter, FT_BBox* bbox); 493 // Caller must lock gFTMutex before calling this function. 494 void updateGlyphIfLCD(SkGlyph* glyph); 495 // Caller must lock gFTMutex before calling this function. 496 // update FreeType2 glyph slot with glyph emboldened 497 void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid); 498 bool shouldSubpixelBitmap(const SkGlyph&, const SkMatrix&); 499 }; 500 501 /////////////////////////////////////////////////////////////////////////// 502 503 static bool canEmbed(FT_Face face) { 504 FT_UShort fsType = FT_Get_FSType_Flags(face); 505 return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 506 FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0; 507 } 508 509 static bool canSubset(FT_Face face) { 510 FT_UShort fsType = FT_Get_FSType_Flags(face); 511 return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0; 512 } 513 514 static void populate_glyph_to_unicode(FT_Face& face, SkTDArray<SkUnichar>* glyphToUnicode) { 515 FT_Long numGlyphs = face->num_glyphs; 516 glyphToUnicode->setCount(SkToInt(numGlyphs)); 517 sk_bzero(glyphToUnicode->begin(), sizeof((*glyphToUnicode)[0]) * numGlyphs); 518 519 FT_UInt glyphIndex; 520 SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 521 while (glyphIndex) { 522 SkASSERT(glyphIndex < SkToUInt(numGlyphs)); 523 // Use the first character that maps to this glyphID. https://crbug.com/359065 524 if (0 == (*glyphToUnicode)[glyphIndex]) { 525 (*glyphToUnicode)[glyphIndex] = charCode; 526 } 527 charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); 528 } 529 } 530 531 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMetrics() const { 532 AutoFTAccess fta(this); 533 FT_Face face = fta.face(); 534 if (!face) { 535 return nullptr; 536 } 537 538 std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); 539 info->fFontName.set(FT_Get_Postscript_Name(face)); 540 541 if (FT_HAS_MULTIPLE_MASTERS(face)) { 542 info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag; 543 } 544 if (!canEmbed(face)) { 545 info->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag; 546 } 547 if (!canSubset(face)) { 548 info->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag; 549 } 550 551 const char* fontType = FT_Get_X11_Font_Format(face); 552 if (strcmp(fontType, "Type 1") == 0) { 553 info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 554 } else if (strcmp(fontType, "CID Type 1") == 0) { 555 info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 556 } else if (strcmp(fontType, "CFF") == 0) { 557 info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 558 } else if (strcmp(fontType, "TrueType") == 0) { 559 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 560 } else { 561 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 562 } 563 564 info->fStyle = (SkAdvancedTypefaceMetrics::StyleFlags)0; 565 if (FT_IS_FIXED_WIDTH(face)) { 566 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 567 } 568 if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 569 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 570 } 571 572 PS_FontInfoRec psFontInfo; 573 TT_Postscript* postTable; 574 if (FT_Get_PS_Font_Info(face, &psFontInfo) == 0) { 575 info->fItalicAngle = psFontInfo.italic_angle; 576 } else if ((postTable = (TT_Postscript*)FT_Get_Sfnt_Table(face, ft_sfnt_post)) != nullptr) { 577 info->fItalicAngle = SkFixedFloorToInt(postTable->italicAngle); 578 } else { 579 info->fItalicAngle = 0; 580 } 581 582 info->fAscent = face->ascender; 583 info->fDescent = face->descender; 584 585 TT_PCLT* pcltTable; 586 TT_OS2* os2Table; 587 if ((pcltTable = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr) { 588 info->fCapHeight = pcltTable->CapHeight; 589 uint8_t serif_style = pcltTable->SerifStyle & 0x3F; 590 if (2 <= serif_style && serif_style <= 6) { 591 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 592 } else if (9 <= serif_style && serif_style <= 12) { 593 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 594 } 595 } else if (((os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nullptr) && 596 // sCapHeight is available only when version 2 or later. 597 os2Table->version != 0xFFFF && 598 os2Table->version >= 2) 599 { 600 info->fCapHeight = os2Table->sCapHeight; 601 } 602 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 603 face->bbox.xMax, face->bbox.yMin); 604 605 bool perGlyphInfo = FT_IS_SCALABLE(face); 606 607 if (perGlyphInfo && info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 608 // Postscript fonts may contain more than 255 glyphs, so we end up 609 // using multiple font descriptions with a glyph ordering. Record 610 // the name of each glyph. 611 info->fGlyphNames.reset(face->num_glyphs); 612 for (int gID = 0; gID < face->num_glyphs; gID++) { 613 char glyphName[128]; // PS limit for names is 127 bytes. 614 FT_Get_Glyph_Name(face, gID, glyphName, 128); 615 info->fGlyphNames[gID].set(glyphName); 616 } 617 } 618 619 if (perGlyphInfo && 620 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 621 face->num_charmaps) 622 { 623 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 624 } 625 626 return info; 627 } 628 629 /////////////////////////////////////////////////////////////////////////// 630 631 static bool bothZero(SkScalar a, SkScalar b) { 632 return 0 == a && 0 == b; 633 } 634 635 // returns false if there is any non-90-rotation or skew 636 static bool isAxisAligned(const SkScalerContextRec& rec) { 637 return 0 == rec.fPreSkewX && 638 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 639 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 640 } 641 642 SkScalerContext* SkTypeface_FreeType::onCreateScalerContext(const SkScalerContextEffects& effects, 643 const SkDescriptor* desc) const { 644 auto c = skstd::make_unique<SkScalerContext_FreeType>( 645 sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc); 646 if (!c->success()) { 647 return nullptr; 648 } 649 return c.release(); 650 } 651 652 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { 653 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 654 //Cap the requested size as larger sizes give bogus values. 655 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. 656 //Note that this also currently only protects against large text size requests, 657 //the total matrix is not taken into account here. 658 if (rec->fTextSize > SkIntToScalar(1 << 14)) { 659 rec->fTextSize = SkIntToScalar(1 << 14); 660 } 661 662 if (isLCD(*rec)) { 663 // TODO: re-work so that FreeType is set-up and selected by the SkFontMgr. 664 SkAutoMutexAcquire ama(gFTMutex); 665 ref_ft_library(); 666 if (!gFTLibrary->isLCDSupported()) { 667 // If the runtime Freetype library doesn't support LCD, disable it here. 668 rec->fMaskFormat = SkMask::kA8_Format; 669 } 670 unref_ft_library(); 671 } 672 673 SkPaint::Hinting h = rec->getHinting(); 674 if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { 675 // collapse full->normal hinting if we're not doing LCD 676 h = SkPaint::kNormal_Hinting; 677 } 678 679 // rotated text looks bad with hinting, so we disable it as needed 680 if (!isAxisAligned(*rec)) { 681 h = SkPaint::kNo_Hinting; 682 } 683 rec->setHinting(h); 684 685 #ifndef SK_GAMMA_APPLY_TO_A8 686 if (!isLCD(*rec)) { 687 // SRGBTODO: Is this correct? Do we want contrast boost? 688 rec->ignorePreBlend(); 689 } 690 #endif 691 } 692 693 int SkTypeface_FreeType::onGetUPEM() const { 694 AutoFTAccess fta(this); 695 FT_Face face = fta.face(); 696 return face ? face->units_per_EM : 0; 697 } 698 699 bool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[], 700 int count, int32_t adjustments[]) const { 701 AutoFTAccess fta(this); 702 FT_Face face = fta.face(); 703 if (!face || !FT_HAS_KERNING(face)) { 704 return false; 705 } 706 707 for (int i = 0; i < count - 1; ++i) { 708 FT_Vector delta; 709 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 710 FT_KERNING_UNSCALED, &delta); 711 if (err) { 712 return false; 713 } 714 adjustments[i] = delta.x; 715 } 716 return true; 717 } 718 719 /** Returns the bitmap strike equal to or just larger than the requested size. */ 720 static FT_Int chooseBitmapStrike(FT_Face face, FT_F26Dot6 scaleY) { 721 if (face == nullptr) { 722 SkDEBUGF(("chooseBitmapStrike aborted due to nullptr face.\n")); 723 return -1; 724 } 725 726 FT_Pos requestedPPEM = scaleY; // FT_Bitmap_Size::y_ppem is in 26.6 format. 727 FT_Int chosenStrikeIndex = -1; 728 FT_Pos chosenPPEM = 0; 729 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) { 730 FT_Pos strikePPEM = face->available_sizes[strikeIndex].y_ppem; 731 if (strikePPEM == requestedPPEM) { 732 // exact match - our search stops here 733 return strikeIndex; 734 } else if (chosenPPEM < requestedPPEM) { 735 // attempt to increase chosenPPEM 736 if (chosenPPEM < strikePPEM) { 737 chosenPPEM = strikePPEM; 738 chosenStrikeIndex = strikeIndex; 739 } 740 } else { 741 // attempt to decrease chosenPPEM, but not below requestedPPEM 742 if (requestedPPEM < strikePPEM && strikePPEM < chosenPPEM) { 743 chosenPPEM = strikePPEM; 744 chosenStrikeIndex = strikeIndex; 745 } 746 } 747 } 748 return chosenStrikeIndex; 749 } 750 751 SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface, 752 const SkScalerContextEffects& effects, 753 const SkDescriptor* desc) 754 : SkScalerContext_FreeType_Base(std::move(typeface), effects, desc) 755 , fFace(nullptr) 756 , fFTSize(nullptr) 757 , fStrikeIndex(-1) 758 { 759 SkAutoMutexAcquire ac(gFTMutex); 760 SkASSERT_RELEASE(ref_ft_library()); 761 762 fFaceRec.reset(ref_ft_face(this->getTypeface())); 763 764 // load the font file 765 if (nullptr == fFaceRec) { 766 SkDEBUGF(("Could not create FT_Face.\n")); 767 return; 768 } 769 770 fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMatrix22Scalar); 771 772 FT_F26Dot6 scaleX = SkScalarToFDot6(fScale.fX); 773 FT_F26Dot6 scaleY = SkScalarToFDot6(fScale.fY); 774 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 775 fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX()); 776 fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY()); 777 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 778 779 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 780 781 // compute the flags we send to Load_Glyph 782 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag); 783 { 784 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 785 786 if (SkMask::kBW_Format == fRec.fMaskFormat) { 787 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 788 loadFlags = FT_LOAD_TARGET_MONO; 789 if (fRec.getHinting() == SkPaint::kNo_Hinting) { 790 loadFlags = FT_LOAD_NO_HINTING; 791 linearMetrics = true; 792 } 793 } else { 794 switch (fRec.getHinting()) { 795 case SkPaint::kNo_Hinting: 796 loadFlags = FT_LOAD_NO_HINTING; 797 linearMetrics = true; 798 break; 799 case SkPaint::kSlight_Hinting: 800 loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 801 break; 802 case SkPaint::kNormal_Hinting: 803 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 804 loadFlags = FT_LOAD_FORCE_AUTOHINT; 805 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 806 } else { 807 loadFlags = FT_LOAD_NO_AUTOHINT; 808 #endif 809 } 810 break; 811 case SkPaint::kFull_Hinting: 812 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 813 loadFlags = FT_LOAD_FORCE_AUTOHINT; 814 break; 815 } 816 loadFlags = FT_LOAD_TARGET_NORMAL; 817 if (isLCD(fRec)) { 818 if (fLCDIsVert) { 819 loadFlags = FT_LOAD_TARGET_LCD_V; 820 } else { 821 loadFlags = FT_LOAD_TARGET_LCD; 822 } 823 } 824 break; 825 default: 826 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 827 break; 828 } 829 } 830 831 if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 832 loadFlags |= FT_LOAD_NO_BITMAP; 833 } 834 835 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 836 // advances, as fontconfig and cairo do. 837 // See http://code.google.com/p/skia/issues/detail?id=222. 838 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 839 840 // Use vertical layout if requested. 841 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 842 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; 843 } 844 845 loadFlags |= FT_LOAD_COLOR; 846 847 fLoadGlyphFlags = loadFlags; 848 } 849 850 using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Size>, FT_Done_Size>; 851 std::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([this]() -> FT_Size { 852 FT_Size size; 853 FT_Error err = FT_New_Size(fFaceRec->fFace.get(), &size); 854 if (err != 0) { 855 SK_TRACEFTR(err, "FT_New_Size(%s) failed.", fFaceRec->fFace->family_name); 856 return nullptr; 857 } 858 return size; 859 }()); 860 if (nullptr == ftSize) { 861 SkDEBUGF(("Could not create FT_Size.\n")); 862 return; 863 } 864 865 FT_Error err = FT_Activate_Size(ftSize.get()); 866 if (err != 0) { 867 SK_TRACEFTR(err, "FT_Activate_Size(%s) failed.", fFaceRec->fFace->family_name); 868 return; 869 } 870 871 if (FT_IS_SCALABLE(fFaceRec->fFace)) { 872 err = FT_Set_Char_Size(fFaceRec->fFace.get(), scaleX, scaleY, 72, 72); 873 if (err != 0) { 874 SK_TRACEFTR(err, "FT_Set_CharSize(%s, %f, %f) failed.", 875 fFaceRec->fFace->family_name, fScale.fX, fScale.fY); 876 return; 877 } 878 } else if (FT_HAS_FIXED_SIZES(fFaceRec->fFace)) { 879 fStrikeIndex = chooseBitmapStrike(fFaceRec->fFace.get(), scaleY); 880 if (fStrikeIndex == -1) { 881 SkDEBUGF(("No glyphs for font \"%s\" size %f.\n", 882 fFaceRec->fFace->family_name, fScale.fY)); 883 return; 884 } 885 886 err = FT_Select_Size(fFaceRec->fFace.get(), fStrikeIndex); 887 if (err != 0) { 888 SK_TRACEFTR(err, "FT_Select_Size(%s, %d) failed.", 889 fFaceRec->fFace->family_name, fStrikeIndex); 890 fStrikeIndex = -1; 891 return; 892 } 893 894 // A non-ideal size was picked, so recompute the matrix. 895 // This adjusts for the difference between FT_Set_Char_Size and FT_Select_Size. 896 fMatrix22Scalar.preScale(fScale.x() / fFaceRec->fFace->size->metrics.x_ppem, 897 fScale.y() / fFaceRec->fFace->size->metrics.y_ppem); 898 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 899 fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX()); 900 fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY()); 901 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 902 903 // FreeType does not provide linear metrics for bitmap fonts. 904 linearMetrics = false; 905 906 // FreeType documentation says: 907 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. 908 // Bitmap-only fonts ignore this flag. 909 // 910 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. 911 // Force this flag off for bitmap only fonts. 912 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; 913 } else { 914 SkDEBUGF(("Unknown kind of font \"%s\" size %f.\n", fFaceRec->fFace->family_name, fScale.fY)); 915 return; 916 } 917 918 fFTSize = ftSize.release(); 919 fFace = fFaceRec->fFace.get(); 920 fDoLinearMetrics = linearMetrics; 921 } 922 923 SkScalerContext_FreeType::~SkScalerContext_FreeType() { 924 SkAutoMutexAcquire ac(gFTMutex); 925 926 if (fFTSize != nullptr) { 927 FT_Done_Size(fFTSize); 928 } 929 930 fFaceRec = nullptr; 931 932 unref_ft_library(); 933 } 934 935 /* We call this before each use of the fFace, since we may be sharing 936 this face with other context (at different sizes). 937 */ 938 FT_Error SkScalerContext_FreeType::setupSize() { 939 gFTMutex.assertHeld(); 940 FT_Error err = FT_Activate_Size(fFTSize); 941 if (err != 0) { 942 return err; 943 } 944 FT_Set_Transform(fFace, &fMatrix22, nullptr); 945 return 0; 946 } 947 948 unsigned SkScalerContext_FreeType::generateGlyphCount() { 949 return fFace->num_glyphs; 950 } 951 952 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 953 SkAutoMutexAcquire ac(gFTMutex); 954 return SkToU16(FT_Get_Char_Index( fFace, uni )); 955 } 956 957 SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 958 SkAutoMutexAcquire ac(gFTMutex); 959 // iterate through each cmap entry, looking for matching glyph indices 960 FT_UInt glyphIndex; 961 SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 962 963 while (glyphIndex != 0) { 964 if (glyphIndex == glyph) { 965 return charCode; 966 } 967 charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 968 } 969 970 return 0; 971 } 972 973 static SkScalar SkFT_FixedToScalar(FT_Fixed x) { 974 return SkFixedToScalar(x); 975 } 976 977 void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 978 /* unhinted and light hinted text have linearly scaled advances 979 * which are very cheap to compute with some font formats... 980 */ 981 if (fDoLinearMetrics) { 982 SkAutoMutexAcquire ac(gFTMutex); 983 984 if (this->setupSize()) { 985 glyph->zeroMetrics(); 986 return; 987 } 988 989 FT_Error error; 990 FT_Fixed advance; 991 992 error = FT_Get_Advance( fFace, glyph->getGlyphID(), 993 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 994 &advance ); 995 if (0 == error) { 996 glyph->fRsbDelta = 0; 997 glyph->fLsbDelta = 0; 998 const SkScalar advanceScalar = SkFT_FixedToScalar(advance); 999 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar); 1000 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar); 1001 return; 1002 } 1003 } 1004 1005 /* otherwise, we need to load/hint the glyph, which is slower */ 1006 this->generateMetrics(glyph); 1007 return; 1008 } 1009 1010 void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 1011 FT_BBox* bbox, 1012 bool snapToPixelBoundary) { 1013 1014 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1015 1016 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1017 int dx = SkFixedToFDot6(glyph->getSubXFixed()); 1018 int dy = SkFixedToFDot6(glyph->getSubYFixed()); 1019 // negate dy since freetype-y-goes-up and skia-y-goes-down 1020 bbox->xMin += dx; 1021 bbox->yMin -= dy; 1022 bbox->xMax += dx; 1023 bbox->yMax -= dy; 1024 } 1025 1026 // outset the box to integral boundaries 1027 if (snapToPixelBoundary) { 1028 bbox->xMin &= ~63; 1029 bbox->yMin &= ~63; 1030 bbox->xMax = (bbox->xMax + 63) & ~63; 1031 bbox->yMax = (bbox->yMax + 63) & ~63; 1032 } 1033 1034 // Must come after snapToPixelBoundary so that the width and height are 1035 // consistent. Otherwise asserts will fire later on when generating the 1036 // glyph image. 1037 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1038 FT_Vector vector; 1039 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1040 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1041 FT_Vector_Transform(&vector, &fMatrix22); 1042 bbox->xMin += vector.x; 1043 bbox->xMax += vector.x; 1044 bbox->yMin += vector.y; 1045 bbox->yMax += vector.y; 1046 } 1047 } 1048 1049 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { 1050 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); 1051 if (!glyph_id) { 1052 return false; 1053 } 1054 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) { 1055 return false; 1056 } 1057 emboldenIfNeeded(fFace, fFace->glyph, SkTo<SkGlyphID>(glyph_id)); 1058 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1059 return true; 1060 } 1061 1062 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1063 if (isLCD(fRec)) { 1064 if (fLCDIsVert) { 1065 glyph->fHeight += gFTLibrary->lcdExtra(); 1066 glyph->fTop -= gFTLibrary->lcdExtra() >> 1; 1067 } else { 1068 glyph->fWidth += gFTLibrary->lcdExtra(); 1069 glyph->fLeft -= gFTLibrary->lcdExtra() >> 1; 1070 } 1071 } 1072 } 1073 1074 bool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const SkMatrix& matrix) { 1075 // If subpixel rendering of a bitmap *can* be done. 1076 bool mechanism = fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && 1077 fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag && 1078 (glyph.getSubXFixed() || glyph.getSubYFixed()); 1079 1080 // If subpixel rendering of a bitmap *should* be done. 1081 // 1. If the face is not scalable then always allow subpixel rendering. 1082 // Otherwise, if the font has an 8ppem strike 7 will subpixel render but 8 won't. 1083 // 2. If the matrix is already not identity the bitmap will already be resampled, 1084 // so resampling slightly differently shouldn't make much difference. 1085 bool policy = !FT_IS_SCALABLE(fFace) || !matrix.isIdentity(); 1086 1087 return mechanism && policy; 1088 } 1089 1090 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1091 SkAutoMutexAcquire ac(gFTMutex); 1092 1093 glyph->fRsbDelta = 0; 1094 glyph->fLsbDelta = 0; 1095 1096 FT_Error err; 1097 1098 if (this->setupSize()) { 1099 glyph->zeroMetrics(); 1100 return; 1101 } 1102 1103 err = FT_Load_Glyph( fFace, glyph->getGlyphID(), 1104 fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY ); 1105 if (err != 0) { 1106 glyph->zeroMetrics(); 1107 return; 1108 } 1109 emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID()); 1110 1111 switch ( fFace->glyph->format ) { 1112 case FT_GLYPH_FORMAT_OUTLINE: 1113 if (0 == fFace->glyph->outline.n_contours) { 1114 glyph->fWidth = 0; 1115 glyph->fHeight = 0; 1116 glyph->fTop = 0; 1117 glyph->fLeft = 0; 1118 } else { 1119 FT_BBox bbox; 1120 getBBoxForCurrentGlyph(glyph, &bbox, true); 1121 1122 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); 1123 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); 1124 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); 1125 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); 1126 1127 updateGlyphIfLCD(glyph); 1128 } 1129 break; 1130 1131 case FT_GLYPH_FORMAT_BITMAP: 1132 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1133 FT_Vector vector; 1134 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1135 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1136 FT_Vector_Transform(&vector, &fMatrix22); 1137 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 1138 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 1139 } 1140 1141 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { 1142 glyph->fMaskFormat = SkMask::kARGB32_Format; 1143 } 1144 1145 { 1146 SkRect rect = SkRect::MakeXYWH(SkIntToScalar(fFace->glyph->bitmap_left), 1147 -SkIntToScalar(fFace->glyph->bitmap_top), 1148 SkIntToScalar(fFace->glyph->bitmap.width), 1149 SkIntToScalar(fFace->glyph->bitmap.rows)); 1150 fMatrix22Scalar.mapRect(&rect); 1151 if (this->shouldSubpixelBitmap(*glyph, fMatrix22Scalar)) { 1152 rect.offset(SkFixedToScalar(glyph->getSubXFixed()), 1153 SkFixedToScalar(glyph->getSubYFixed())); 1154 } 1155 SkIRect irect = rect.roundOut(); 1156 glyph->fWidth = SkToU16(irect.width()); 1157 glyph->fHeight = SkToU16(irect.height()); 1158 glyph->fTop = SkToS16(irect.top()); 1159 glyph->fLeft = SkToS16(irect.left()); 1160 } 1161 break; 1162 1163 default: 1164 SkDEBUGFAIL("unknown glyph format"); 1165 glyph->zeroMetrics(); 1166 return; 1167 } 1168 1169 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1170 if (fDoLinearMetrics) { 1171 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearVertAdvance); 1172 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * advanceScalar); 1173 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * advanceScalar); 1174 } else { 1175 glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x); 1176 glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y); 1177 } 1178 } else { 1179 if (fDoLinearMetrics) { 1180 const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearHoriAdvance); 1181 glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar); 1182 glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar); 1183 } else { 1184 glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x); 1185 glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y); 1186 1187 if (fRec.fFlags & kDevKernText_Flag) { 1188 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1189 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1190 } 1191 } 1192 } 1193 1194 #ifdef ENABLE_GLYPH_SPEW 1195 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadGlyphFlags, glyph->fWidth)); 1196 #endif 1197 } 1198 1199 static void clear_glyph_image(const SkGlyph& glyph) { 1200 sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight); 1201 } 1202 1203 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1204 SkAutoMutexAcquire ac(gFTMutex); 1205 1206 if (this->setupSize()) { 1207 clear_glyph_image(glyph); 1208 return; 1209 } 1210 1211 FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags); 1212 if (err != 0) { 1213 SK_TRACEFTR(err, "SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d " 1214 "width:%d height:%d rb:%d flags:%d) failed.", 1215 glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), 1216 fLoadGlyphFlags); 1217 clear_glyph_image(glyph); 1218 return; 1219 } 1220 1221 emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID()); 1222 SkMatrix* bitmapMatrix = &fMatrix22Scalar; 1223 SkMatrix subpixelBitmapMatrix; 1224 if (this->shouldSubpixelBitmap(glyph, *bitmapMatrix)) { 1225 subpixelBitmapMatrix = fMatrix22Scalar; 1226 subpixelBitmapMatrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()), 1227 SkFixedToScalar(glyph.getSubYFixed())); 1228 bitmapMatrix = &subpixelBitmapMatrix; 1229 } 1230 generateGlyphImage(fFace, glyph, *bitmapMatrix); 1231 } 1232 1233 1234 void SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) { 1235 SkAutoMutexAcquire ac(gFTMutex); 1236 1237 SkASSERT(path); 1238 1239 if (this->setupSize()) { 1240 path->reset(); 1241 return; 1242 } 1243 1244 uint32_t flags = fLoadGlyphFlags; 1245 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 1246 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 1247 1248 FT_Error err = FT_Load_Glyph(fFace, glyphID, flags); 1249 1250 if (err != 0) { 1251 SK_TRACEFTR(err, "SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d " 1252 "flags:%d) failed.", glyphID, flags); 1253 path->reset(); 1254 return; 1255 } 1256 emboldenIfNeeded(fFace, fFace->glyph, glyphID); 1257 1258 generateGlyphPath(fFace, path); 1259 1260 // The path's origin from FreeType is always the horizontal layout origin. 1261 // Offset the path so that it is relative to the vertical origin if needed. 1262 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1263 FT_Vector vector; 1264 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1265 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1266 FT_Vector_Transform(&vector, &fMatrix22); 1267 path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); 1268 } 1269 } 1270 1271 void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics) { 1272 if (nullptr == metrics) { 1273 return; 1274 } 1275 1276 SkAutoMutexAcquire ac(gFTMutex); 1277 1278 if (this->setupSize()) { 1279 sk_bzero(metrics, sizeof(*metrics)); 1280 return; 1281 } 1282 1283 FT_Face face = fFace; 1284 metrics->fFlags = 0; 1285 1286 // fetch units/EM from "head" table if needed (ie for bitmap fonts) 1287 SkScalar upem = SkIntToScalar(face->units_per_EM); 1288 if (!upem) { 1289 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1290 if (ttHeader) { 1291 upem = SkIntToScalar(ttHeader->Units_Per_EM); 1292 } 1293 } 1294 1295 // use the os/2 table as a source of reasonable defaults. 1296 SkScalar x_height = 0.0f; 1297 SkScalar avgCharWidth = 0.0f; 1298 SkScalar cap_height = 0.0f; 1299 SkScalar strikeoutThickness = 0.0f, strikeoutPosition = 0.0f; 1300 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1301 if (os2) { 1302 x_height = SkIntToScalar(os2->sxHeight) / upem * fScale.y(); 1303 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; 1304 strikeoutThickness = SkIntToScalar(os2->yStrikeoutSize) / upem; 1305 strikeoutPosition = -SkIntToScalar(os2->yStrikeoutPosition) / upem; 1306 metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutThicknessIsValid_Flag; 1307 metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutPositionIsValid_Flag; 1308 if (os2->version != 0xFFFF && os2->version >= 2) { 1309 cap_height = SkIntToScalar(os2->sCapHeight) / upem * fScale.y(); 1310 } 1311 } 1312 1313 // pull from format-specific metrics as needed 1314 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; 1315 SkScalar underlineThickness, underlinePosition; 1316 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font 1317 // FreeType will always use HHEA metrics if they're not zero. 1318 // It completely ignores the OS/2 fsSelection::UseTypoMetrics bit. 1319 // It also ignores the VDMX tables, which are also of interest here 1320 // (and override everything else when they apply). 1321 static const int kUseTypoMetricsMask = (1 << 7); 1322 if (os2 && os2->version != 0xFFFF && (os2->fsSelection & kUseTypoMetricsMask)) { 1323 ascent = -SkIntToScalar(os2->sTypoAscender) / upem; 1324 descent = -SkIntToScalar(os2->sTypoDescender) / upem; 1325 leading = SkIntToScalar(os2->sTypoLineGap) / upem; 1326 } else { 1327 ascent = -SkIntToScalar(face->ascender) / upem; 1328 descent = -SkIntToScalar(face->descender) / upem; 1329 leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem; 1330 } 1331 xmin = SkIntToScalar(face->bbox.xMin) / upem; 1332 xmax = SkIntToScalar(face->bbox.xMax) / upem; 1333 ymin = -SkIntToScalar(face->bbox.yMin) / upem; 1334 ymax = -SkIntToScalar(face->bbox.yMax) / upem; 1335 underlineThickness = SkIntToScalar(face->underline_thickness) / upem; 1336 underlinePosition = -SkIntToScalar(face->underline_position + 1337 face->underline_thickness / 2) / upem; 1338 1339 metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 1340 metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1341 1342 // we may be able to synthesize x_height and cap_height from outline 1343 if (!x_height) { 1344 FT_BBox bbox; 1345 if (getCBoxForLetter('x', &bbox)) { 1346 x_height = SkIntToScalar(bbox.yMax) / 64.0f; 1347 } 1348 } 1349 if (!cap_height) { 1350 FT_BBox bbox; 1351 if (getCBoxForLetter('H', &bbox)) { 1352 cap_height = SkIntToScalar(bbox.yMax) / 64.0f; 1353 } 1354 } 1355 } else if (fStrikeIndex != -1) { // bitmap strike metrics 1356 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); 1357 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); 1358 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); 1359 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f); 1360 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) + ascent - descent; 1361 xmin = 0.0f; 1362 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; 1363 ymin = descent; 1364 ymax = ascent; 1365 underlineThickness = 0; 1366 underlinePosition = 0; 1367 metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 1368 metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1369 1370 TT_Postscript* post = (TT_Postscript*) FT_Get_Sfnt_Table(face, ft_sfnt_post); 1371 if (post) { 1372 underlineThickness = SkIntToScalar(post->underlineThickness) / upem; 1373 underlinePosition = -SkIntToScalar(post->underlinePosition) / upem; 1374 metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 1375 metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1376 } 1377 } else { 1378 sk_bzero(metrics, sizeof(*metrics)); 1379 return; 1380 } 1381 1382 // synthesize elements that were not provided by the os/2 table or format-specific metrics 1383 if (!x_height) { 1384 x_height = -ascent * fScale.y(); 1385 } 1386 if (!avgCharWidth) { 1387 avgCharWidth = xmax - xmin; 1388 } 1389 if (!cap_height) { 1390 cap_height = -ascent * fScale.y(); 1391 } 1392 1393 // disallow negative linespacing 1394 if (leading < 0.0f) { 1395 leading = 0.0f; 1396 } 1397 1398 metrics->fTop = ymax * fScale.y(); 1399 metrics->fAscent = ascent * fScale.y(); 1400 metrics->fDescent = descent * fScale.y(); 1401 metrics->fBottom = ymin * fScale.y(); 1402 metrics->fLeading = leading * fScale.y(); 1403 metrics->fAvgCharWidth = avgCharWidth * fScale.y(); 1404 metrics->fXMin = xmin * fScale.y(); 1405 metrics->fXMax = xmax * fScale.y(); 1406 metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin; 1407 metrics->fXHeight = x_height; 1408 metrics->fCapHeight = cap_height; 1409 metrics->fUnderlineThickness = underlineThickness * fScale.y(); 1410 metrics->fUnderlinePosition = underlinePosition * fScale.y(); 1411 metrics->fStrikeoutThickness = strikeoutThickness * fScale.y(); 1412 metrics->fStrikeoutPosition = strikeoutPosition * fScale.y(); 1413 } 1414 1415 /////////////////////////////////////////////////////////////////////////////// 1416 1417 // hand-tuned value to reduce outline embolden strength 1418 #ifndef SK_OUTLINE_EMBOLDEN_DIVISOR 1419 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 1420 #define SK_OUTLINE_EMBOLDEN_DIVISOR 34 1421 #else 1422 #define SK_OUTLINE_EMBOLDEN_DIVISOR 24 1423 #endif 1424 #endif 1425 1426 /////////////////////////////////////////////////////////////////////////////// 1427 1428 void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid) { 1429 // check to see if the embolden bit is set 1430 if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) { 1431 return; 1432 } 1433 1434 switch (glyph->format) { 1435 case FT_GLYPH_FORMAT_OUTLINE: 1436 FT_Pos strength; 1437 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) 1438 / SK_OUTLINE_EMBOLDEN_DIVISOR; 1439 FT_Outline_Embolden(&glyph->outline, strength); 1440 break; 1441 case FT_GLYPH_FORMAT_BITMAP: 1442 if (!fFace->glyph->bitmap.buffer) { 1443 FT_Load_Glyph(fFace, gid, fLoadGlyphFlags); 1444 } 1445 FT_GlyphSlot_Own_Bitmap(glyph); 1446 FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0); 1447 break; 1448 default: 1449 SkDEBUGFAIL("unknown glyph format"); 1450 } 1451 } 1452 1453 /////////////////////////////////////////////////////////////////////////////// 1454 1455 #include "SkUtils.h" 1456 1457 static SkUnichar next_utf8(const void** chars) { 1458 return SkUTF8_NextUnichar((const char**)chars); 1459 } 1460 1461 static SkUnichar next_utf16(const void** chars) { 1462 return SkUTF16_NextUnichar((const uint16_t**)chars); 1463 } 1464 1465 static SkUnichar next_utf32(const void** chars) { 1466 const SkUnichar** uniChars = (const SkUnichar**)chars; 1467 SkUnichar uni = **uniChars; 1468 *uniChars += 1; 1469 return uni; 1470 } 1471 1472 typedef SkUnichar (*EncodingProc)(const void**); 1473 1474 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 1475 static const EncodingProc gProcs[] = { 1476 next_utf8, next_utf16, next_utf32 1477 }; 1478 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 1479 return gProcs[enc]; 1480 } 1481 1482 int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, 1483 uint16_t glyphs[], int glyphCount) const 1484 { 1485 AutoFTAccess fta(this); 1486 FT_Face face = fta.face(); 1487 if (!face) { 1488 if (glyphs) { 1489 sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); 1490 } 1491 return 0; 1492 } 1493 1494 EncodingProc next_uni_proc = find_encoding_proc(encoding); 1495 1496 if (nullptr == glyphs) { 1497 for (int i = 0; i < glyphCount; ++i) { 1498 if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { 1499 return i; 1500 } 1501 } 1502 return glyphCount; 1503 } else { 1504 int first = glyphCount; 1505 for (int i = 0; i < glyphCount; ++i) { 1506 unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); 1507 glyphs[i] = SkToU16(id); 1508 if (0 == id && i < first) { 1509 first = i; 1510 } 1511 } 1512 return first; 1513 } 1514 } 1515 1516 int SkTypeface_FreeType::onCountGlyphs() const { 1517 AutoFTAccess fta(this); 1518 FT_Face face = fta.face(); 1519 return face ? face->num_glyphs : 0; 1520 } 1521 1522 SkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const { 1523 SkTypeface::LocalizedStrings* nameIter = 1524 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1525 if (nullptr == nameIter) { 1526 SkString familyName; 1527 this->getFamilyName(&familyName); 1528 SkString language("und"); //undetermined 1529 nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 1530 } 1531 return nameIter; 1532 } 1533 1534 int SkTypeface_FreeType::onGetVariationDesignPosition( 1535 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const 1536 { 1537 AutoFTAccess fta(this); 1538 FT_Face face = fta.face(); 1539 1540 if (!face || !(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { 1541 return 0; 1542 } 1543 1544 FT_MM_Var* variations = nullptr; 1545 if (FT_Get_MM_Var(face, &variations)) { 1546 return 0; 1547 } 1548 SkAutoFree autoFreeVariations(variations); 1549 1550 if (!coordinates || coordinateCount < SkToInt(variations->num_axis)) { 1551 return variations->num_axis; 1552 } 1553 1554 SkAutoSTMalloc<4, FT_Fixed> coords(variations->num_axis); 1555 // FT_Get_{MM,Var}_{Blend,Design}_Coordinates were added in FreeType 2.7.1. 1556 if (gFTLibrary->fGetVarDesignCoordinates && 1557 !gFTLibrary->fGetVarDesignCoordinates(face, variations->num_axis, coords.get())) 1558 { 1559 for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1560 coordinates[i].axis = variations->axis[i].tag; 1561 coordinates[i].value = SkFixedToScalar(coords[i]); 1562 } 1563 } else if (static_cast<FT_UInt>(fta.getAxesCount()) == variations->num_axis) { 1564 for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1565 coordinates[i].axis = variations->axis[i].tag; 1566 coordinates[i].value = SkFixedToScalar(fta.getAxes()[i]); 1567 } 1568 } else if (fta.isNamedVariationSpecified()) { 1569 // The font has axes, they cannot be retrieved, and some named axis was specified. 1570 return -1; 1571 } else { 1572 // The font has axes, they cannot be retrieved, but no named instance was specified. 1573 return 0; 1574 } 1575 1576 return variations->num_axis; 1577 } 1578 1579 int SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const { 1580 AutoFTAccess fta(this); 1581 FT_Face face = fta.face(); 1582 1583 FT_ULong tableCount = 0; 1584 FT_Error error; 1585 1586 // When 'tag' is nullptr, returns number of tables in 'length'. 1587 error = FT_Sfnt_Table_Info(face, 0, nullptr, &tableCount); 1588 if (error) { 1589 return 0; 1590 } 1591 1592 if (tags) { 1593 for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) { 1594 FT_ULong tableTag; 1595 FT_ULong tablelength; 1596 error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength); 1597 if (error) { 1598 return 0; 1599 } 1600 tags[tableIndex] = static_cast<SkFontTableTag>(tableTag); 1601 } 1602 } 1603 return tableCount; 1604 } 1605 1606 size_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset, 1607 size_t length, void* data) const 1608 { 1609 AutoFTAccess fta(this); 1610 FT_Face face = fta.face(); 1611 1612 FT_ULong tableLength = 0; 1613 FT_Error error; 1614 1615 // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored. 1616 error = FT_Load_Sfnt_Table(face, tag, 0, nullptr, &tableLength); 1617 if (error) { 1618 return 0; 1619 } 1620 1621 if (offset > tableLength) { 1622 return 0; 1623 } 1624 FT_ULong size = SkTMin((FT_ULong)length, tableLength - (FT_ULong)offset); 1625 if (data) { 1626 error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size); 1627 if (error) { 1628 return 0; 1629 } 1630 } 1631 1632 return size; 1633 } 1634 1635 /////////////////////////////////////////////////////////////////////////////// 1636 /////////////////////////////////////////////////////////////////////////////// 1637 1638 SkTypeface_FreeType::Scanner::Scanner() : fLibrary(nullptr) { 1639 if (FT_New_Library(&gFTMemory, &fLibrary)) { 1640 return; 1641 } 1642 FT_Add_Default_Modules(fLibrary); 1643 } 1644 SkTypeface_FreeType::Scanner::~Scanner() { 1645 if (fLibrary) { 1646 FT_Done_Library(fLibrary); 1647 } 1648 } 1649 1650 FT_Face SkTypeface_FreeType::Scanner::openFace(SkStreamAsset* stream, int ttcIndex, 1651 FT_Stream ftStream) const 1652 { 1653 if (fLibrary == nullptr) { 1654 return nullptr; 1655 } 1656 1657 FT_Open_Args args; 1658 memset(&args, 0, sizeof(args)); 1659 1660 const void* memoryBase = stream->getMemoryBase(); 1661 1662 if (memoryBase) { 1663 args.flags = FT_OPEN_MEMORY; 1664 args.memory_base = (const FT_Byte*)memoryBase; 1665 args.memory_size = stream->getLength(); 1666 } else { 1667 memset(ftStream, 0, sizeof(*ftStream)); 1668 ftStream->size = stream->getLength(); 1669 ftStream->descriptor.pointer = stream; 1670 ftStream->read = sk_ft_stream_io; 1671 ftStream->close = sk_ft_stream_close; 1672 1673 args.flags = FT_OPEN_STREAM; 1674 args.stream = ftStream; 1675 } 1676 1677 FT_Face face; 1678 if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) { 1679 return nullptr; 1680 } 1681 return face; 1682 } 1683 1684 bool SkTypeface_FreeType::Scanner::recognizedFont(SkStreamAsset* stream, int* numFaces) const { 1685 SkAutoMutexAcquire libraryLock(fLibraryMutex); 1686 1687 FT_StreamRec streamRec; 1688 FT_Face face = this->openFace(stream, -1, &streamRec); 1689 if (nullptr == face) { 1690 return false; 1691 } 1692 1693 *numFaces = face->num_faces; 1694 1695 FT_Done_Face(face); 1696 return true; 1697 } 1698 1699 #include "SkTSearch.h" 1700 bool SkTypeface_FreeType::Scanner::scanFont( 1701 SkStreamAsset* stream, int ttcIndex, 1702 SkString* name, SkFontStyle* style, bool* isFixedPitch, AxisDefinitions* axes) const 1703 { 1704 SkAutoMutexAcquire libraryLock(fLibraryMutex); 1705 1706 FT_StreamRec streamRec; 1707 FT_Face face = this->openFace(stream, ttcIndex, &streamRec); 1708 if (nullptr == face) { 1709 return false; 1710 } 1711 1712 int weight = SkFontStyle::kNormal_Weight; 1713 int width = SkFontStyle::kNormal_Width; 1714 SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant; 1715 if (face->style_flags & FT_STYLE_FLAG_BOLD) { 1716 weight = SkFontStyle::kBold_Weight; 1717 } 1718 if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 1719 slant = SkFontStyle::kItalic_Slant; 1720 } 1721 1722 PS_FontInfoRec psFontInfo; 1723 TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face, ft_sfnt_os2)); 1724 if (os2 && os2->version != 0xffff) { 1725 weight = os2->usWeightClass; 1726 width = os2->usWidthClass; 1727 1728 // OS/2::fsSelection bit 9 indicates oblique. 1729 if (SkToBool(os2->fsSelection & (1u << 9))) { 1730 slant = SkFontStyle::kOblique_Slant; 1731 } 1732 } else if (0 == FT_Get_PS_Font_Info(face, &psFontInfo) && psFontInfo.weight) { 1733 static const struct { 1734 char const * const name; 1735 int const weight; 1736 } commonWeights [] = { 1737 // There are probably more common names, but these are known to exist. 1738 { "all", SkFontStyle::kNormal_Weight }, // Multiple Masters usually default to normal. 1739 { "black", SkFontStyle::kBlack_Weight }, 1740 { "bold", SkFontStyle::kBold_Weight }, 1741 { "book", (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight)/2 }, 1742 { "demi", SkFontStyle::kSemiBold_Weight }, 1743 { "demibold", SkFontStyle::kSemiBold_Weight }, 1744 { "extra", SkFontStyle::kExtraBold_Weight }, 1745 { "extrabold", SkFontStyle::kExtraBold_Weight }, 1746 { "extralight", SkFontStyle::kExtraLight_Weight }, 1747 { "hairline", SkFontStyle::kThin_Weight }, 1748 { "heavy", SkFontStyle::kBlack_Weight }, 1749 { "light", SkFontStyle::kLight_Weight }, 1750 { "medium", SkFontStyle::kMedium_Weight }, 1751 { "normal", SkFontStyle::kNormal_Weight }, 1752 { "plain", SkFontStyle::kNormal_Weight }, 1753 { "regular", SkFontStyle::kNormal_Weight }, 1754 { "roman", SkFontStyle::kNormal_Weight }, 1755 { "semibold", SkFontStyle::kSemiBold_Weight }, 1756 { "standard", SkFontStyle::kNormal_Weight }, 1757 { "thin", SkFontStyle::kThin_Weight }, 1758 { "ultra", SkFontStyle::kExtraBold_Weight }, 1759 { "ultrablack", SkFontStyle::kExtraBlack_Weight }, 1760 { "ultrabold", SkFontStyle::kExtraBold_Weight }, 1761 { "ultraheavy", SkFontStyle::kExtraBlack_Weight }, 1762 { "ultralight", SkFontStyle::kExtraLight_Weight }, 1763 }; 1764 int const index = SkStrLCSearch(&commonWeights[0].name, SK_ARRAY_COUNT(commonWeights), 1765 psFontInfo.weight, sizeof(commonWeights[0])); 1766 if (index >= 0) { 1767 weight = commonWeights[index].weight; 1768 } else { 1769 SkDEBUGF(("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight)); 1770 } 1771 } 1772 1773 if (name) { 1774 name->set(face->family_name); 1775 } 1776 if (style) { 1777 *style = SkFontStyle(weight, width, slant); 1778 } 1779 if (isFixedPitch) { 1780 *isFixedPitch = FT_IS_FIXED_WIDTH(face); 1781 } 1782 1783 if (axes && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { 1784 FT_MM_Var* variations = nullptr; 1785 FT_Error err = FT_Get_MM_Var(face, &variations); 1786 if (err) { 1787 SkDEBUGF(("INFO: font %s claims to have variations, but none found.\n", 1788 face->family_name)); 1789 return false; 1790 } 1791 SkAutoFree autoFreeVariations(variations); 1792 1793 axes->reset(variations->num_axis); 1794 for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1795 const FT_Var_Axis& ftAxis = variations->axis[i]; 1796 (*axes)[i].fTag = ftAxis.tag; 1797 (*axes)[i].fMinimum = ftAxis.minimum; 1798 (*axes)[i].fDefault = ftAxis.def; 1799 (*axes)[i].fMaximum = ftAxis.maximum; 1800 } 1801 } 1802 1803 FT_Done_Face(face); 1804 return true; 1805 } 1806 1807 /*static*/ void SkTypeface_FreeType::Scanner::computeAxisValues( 1808 AxisDefinitions axisDefinitions, 1809 const SkFontArguments::VariationPosition position, 1810 SkFixed* axisValues, 1811 const SkString& name) 1812 { 1813 for (int i = 0; i < axisDefinitions.count(); ++i) { 1814 const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i]; 1815 const SkScalar axisMin = SkFixedToScalar(axisDefinition.fMinimum); 1816 const SkScalar axisMax = SkFixedToScalar(axisDefinition.fMaximum); 1817 axisValues[i] = axisDefinition.fDefault; 1818 // The position may be over specified. If there are multiple values for a given axis, 1819 // use the last one since that's what css-fonts-4 requires. 1820 for (int j = position.coordinateCount; j --> 0;) { 1821 const auto& coordinate = position.coordinates[j]; 1822 if (axisDefinition.fTag == coordinate.axis) { 1823 const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax); 1824 if (coordinate.value != axisValue) { 1825 SkDEBUGF(("Requested font axis value out of range: " 1826 "%s '%c%c%c%c' %f; pinned to %f.\n", 1827 name.c_str(), 1828 (axisDefinition.fTag >> 24) & 0xFF, 1829 (axisDefinition.fTag >> 16) & 0xFF, 1830 (axisDefinition.fTag >> 8) & 0xFF, 1831 (axisDefinition.fTag ) & 0xFF, 1832 SkScalarToDouble(coordinate.value), 1833 SkScalarToDouble(axisValue))); 1834 } 1835 axisValues[i] = SkScalarToFixed(axisValue); 1836 break; 1837 } 1838 } 1839 // TODO: warn on defaulted axis? 1840 } 1841 1842 SkDEBUGCODE( 1843 // Check for axis specified, but not matched in font. 1844 for (int i = 0; i < position.coordinateCount; ++i) { 1845 SkFourByteTag skTag = position.coordinates[i].axis; 1846 bool found = false; 1847 for (int j = 0; j < axisDefinitions.count(); ++j) { 1848 if (skTag == axisDefinitions[j].fTag) { 1849 found = true; 1850 break; 1851 } 1852 } 1853 if (!found) { 1854 SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", 1855 name.c_str(), 1856 (skTag >> 24) & 0xFF, 1857 (skTag >> 16) & 0xFF, 1858 (skTag >> 8) & 0xFF, 1859 (skTag) & 0xFF)); 1860 } 1861 } 1862 ) 1863 } 1864