SkFontHost_FreeType.cpp revision 62107f3888bc9011c404be4597b89e70c0987afe
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "SkAdvancedTypefaceMetrics.h" 10#include "SkBitmap.h" 11#include "SkCanvas.h" 12#include "SkColorPriv.h" 13#include "SkDescriptor.h" 14#include "SkFDot6.h" 15#include "SkFloatingPoint.h" 16#include "SkFontHost.h" 17#include "SkFontHost_FreeType_common.h" 18#include "SkGlyph.h" 19#include "SkMask.h" 20#include "SkMaskGamma.h" 21#include "SkMatrix22.h" 22#include "SkOTUtils.h" 23#include "SkOnce.h" 24#include "SkScalerContext.h" 25#include "SkStream.h" 26#include "SkString.h" 27#include "SkTemplates.h" 28#include "SkThread.h" 29 30#if defined(SK_CAN_USE_DLOPEN) 31#include <dlfcn.h> 32#endif 33#include <ft2build.h> 34#include FT_FREETYPE_H 35#include FT_OUTLINE_H 36#include FT_SIZES_H 37#include FT_TRUETYPE_TABLES_H 38#include FT_TYPE1_TABLES_H 39#include FT_BITMAP_H 40// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 41#include FT_SYNTHESIS_H 42#include FT_XFREE86_H 43#ifdef FT_LCD_FILTER_H 44#include FT_LCD_FILTER_H 45#endif 46 47// Defined in FreeType 2.3.8 and later. 48// This is a silly build time check, we would need a runtime check if we really cared. 49#ifdef FT_ADVANCES_H 50#include FT_ADVANCES_H 51#endif 52 53#if 0 54// Also include the files by name for build tools which require this. 55#include <freetype/freetype.h> 56#include <freetype/ftoutln.h> 57#include <freetype/ftsizes.h> 58#include <freetype/tttables.h> 59#include <freetype/ftadvanc.h> 60#include <freetype/ftlcdfil.h> 61#include <freetype/ftbitmap.h> 62#include <freetype/ftsynth.h> 63#endif 64 65// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 66// were introduced in FreeType 2.5.0. 67// The following may be removed once FreeType 2.5.0 is required to build. 68#ifndef FT_LOAD_COLOR 69# define FT_LOAD_COLOR ( 1L << 20 ) 70# define FT_PIXEL_MODE_BGRA 7 71#endif 72 73// FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR 74// were introduced in FreeType 2.5.1 75// The following may be removed once FreeType 2.5.1 is required to build. 76#ifndef FT_HAS_COLOR 77# define FT_HAS_COLOR(face) false 78#endif 79 80//#define ENABLE_GLYPH_SPEW // for tracing calls 81//#define DUMP_STRIKE_CREATION 82 83//#define SK_GAMMA_APPLY_TO_A8 84 85using namespace skia_advanced_typeface_metrics_utils; 86 87static bool isLCD(const SkScalerContext::Rec& rec) { 88 switch (rec.fMaskFormat) { 89 case SkMask::kLCD16_Format: 90 case SkMask::kLCD32_Format: 91 return true; 92 default: 93 return false; 94 } 95} 96 97////////////////////////////////////////////////////////////////////////// 98 99struct SkFaceRec; 100 101SK_DECLARE_STATIC_MUTEX(gFTMutex); 102static int gFTCount; 103static FT_Library gFTLibrary; 104static SkFaceRec* gFaceRecHead; 105static bool gLCDSupportValid; // true iff |gLCDSupport| has been set. 106static bool gLCDSupport; // true iff LCD is supported by the runtime. 107static int gLCDExtra; // number of extra pixels for filtering. 108 109///////////////////////////////////////////////////////////////////////// 110 111// FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. 112// The following platforms provide FreeType of at least 2.4.0. 113// Ubuntu >= 11.04 (previous deprecated April 2013) 114// Debian >= 6.0 (good) 115// OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2) 116// Fedora >= 14 (good) 117// Android >= Gingerbread (good) 118typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*); 119 120// Caller must lock gFTMutex before calling this function. 121static bool InitFreetype() { 122 FT_Error err = FT_Init_FreeType(&gFTLibrary); 123 if (err) { 124 return false; 125 } 126 127 // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs. 128#ifdef FT_LCD_FILTER_H 129 // Use default { 0x10, 0x40, 0x70, 0x40, 0x10 }, as it adds up to 0x110, simulating ink spread. 130 // SetLcdFilter must be called before SetLcdFilterWeights. 131 err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); 132 if (0 == err) { 133 gLCDSupport = true; 134 gLCDExtra = 2; //Using a filter adds one full pixel to each side. 135 136#ifdef SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER 137 // This also adds to 0x110 simulating ink spread, but provides better results than default. 138 static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x56, 0x43, 0x1A, }; 139 140#if defined(SK_FONTHOST_FREETYPE_RUNTIME_VERSION) && \ 141 SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400 142 err = FT_Library_SetLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights); 143#elif defined(SK_CAN_USE_DLOPEN) && SK_CAN_USE_DLOPEN == 1 144 //The FreeType library is already loaded, so symbols are available in process. 145 void* self = dlopen(NULL, RTLD_LAZY); 146 if (NULL != self) { 147 FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights; 148 //The following cast is non-standard, but safe for POSIX. 149 *reinterpret_cast<void**>(&setLcdFilterWeights) = dlsym(self, "FT_Library_SetLcdFilterWeights"); 150 dlclose(self); 151 152 if (NULL != setLcdFilterWeights) { 153 err = setLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights); 154 } 155 } 156#endif 157#endif 158 } 159#else 160 gLCDSupport = false; 161#endif 162 gLCDSupportValid = true; 163 164 return true; 165} 166 167// Called while holding gFTMutex. 168static void determine_lcd_support(bool* lcdSupported) { 169 if (!gLCDSupportValid) { 170 // This will determine LCD support as a side effect. 171 InitFreetype(); 172 FT_Done_FreeType(gFTLibrary); 173 } 174 SkASSERT(gLCDSupportValid); 175 *lcdSupported = gLCDSupport; 176} 177 178// Lazy, once, wrapper to ask the FreeType Library if it can support LCD text 179static bool is_lcd_supported() { 180 static bool lcdSupported = false; 181 SkOnce(&gLCDSupportValid, &gFTMutex, determine_lcd_support, &lcdSupported); 182 return lcdSupported; 183} 184 185class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { 186public: 187 SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); 188 virtual ~SkScalerContext_FreeType(); 189 190 bool success() const { 191 return fFaceRec != NULL && 192 fFTSize != NULL && 193 fFace != NULL; 194 } 195 196protected: 197 virtual unsigned generateGlyphCount() SK_OVERRIDE; 198 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 199 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 200 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 201 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 202 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 203 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 204 SkPaint::FontMetrics* my) SK_OVERRIDE; 205 virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; 206 207private: 208 SkFaceRec* fFaceRec; 209 FT_Face fFace; // reference to shared face in gFaceRecHead 210 FT_Size fFTSize; // our own copy 211 FT_Int fStrikeIndex; 212 SkFixed fScaleX, fScaleY; 213 FT_Matrix fMatrix22; 214 uint32_t fLoadGlyphFlags; 215 bool fDoLinearMetrics; 216 bool fLCDIsVert; 217 218 // Need scalar versions for generateFontMetrics 219 SkVector fScale; 220 SkMatrix fMatrix22Scalar; 221 222 FT_Error setupSize(); 223 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 224 bool snapToPixelBoundary = false); 225 bool getCBoxForLetter(char letter, FT_BBox* bbox); 226 // Caller must lock gFTMutex before calling this function. 227 void updateGlyphIfLCD(SkGlyph* glyph); 228 // Caller must lock gFTMutex before calling this function. 229 // update FreeType2 glyph slot with glyph emboldened 230 void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph); 231}; 232 233/////////////////////////////////////////////////////////////////////////// 234/////////////////////////////////////////////////////////////////////////// 235 236struct SkFaceRec { 237 SkFaceRec* fNext; 238 FT_Face fFace; 239 FT_StreamRec fFTStream; 240 SkStream* fSkStream; 241 uint32_t fRefCnt; 242 uint32_t fFontID; 243 244 // assumes ownership of the stream, will call unref() when its done 245 SkFaceRec(SkStream* strm, uint32_t fontID); 246 ~SkFaceRec() { 247 fSkStream->unref(); 248 } 249}; 250 251extern "C" { 252 static unsigned long sk_stream_read(FT_Stream stream, 253 unsigned long offset, 254 unsigned char* buffer, 255 unsigned long count ) { 256 SkStream* str = (SkStream*)stream->descriptor.pointer; 257 258 if (count) { 259 if (!str->rewind()) { 260 return 0; 261 } else { 262 unsigned long ret; 263 if (offset) { 264 ret = str->read(NULL, offset); 265 if (ret != offset) { 266 return 0; 267 } 268 } 269 ret = str->read(buffer, count); 270 if (ret != count) { 271 return 0; 272 } 273 count = ret; 274 } 275 } 276 return count; 277 } 278 279 static void sk_stream_close(FT_Stream) {} 280} 281 282SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) 283 : fNext(NULL), fSkStream(strm), fRefCnt(1), fFontID(fontID) { 284// SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); 285 286 sk_bzero(&fFTStream, sizeof(fFTStream)); 287 fFTStream.size = fSkStream->getLength(); 288 fFTStream.descriptor.pointer = fSkStream; 289 fFTStream.read = sk_stream_read; 290 fFTStream.close = sk_stream_close; 291} 292 293// Will return 0 on failure 294// Caller must lock gFTMutex before calling this function. 295static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { 296 const SkFontID fontID = typeface->uniqueID(); 297 SkFaceRec* rec = gFaceRecHead; 298 while (rec) { 299 if (rec->fFontID == fontID) { 300 SkASSERT(rec->fFace); 301 rec->fRefCnt += 1; 302 return rec; 303 } 304 rec = rec->fNext; 305 } 306 307 int face_index; 308 SkStream* strm = typeface->openStream(&face_index); 309 if (NULL == strm) { 310 return NULL; 311 } 312 313 // this passes ownership of strm to the rec 314 rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); 315 316 FT_Open_Args args; 317 memset(&args, 0, sizeof(args)); 318 const void* memoryBase = strm->getMemoryBase(); 319 320 if (NULL != memoryBase) { 321//printf("mmap(%s)\n", keyString.c_str()); 322 args.flags = FT_OPEN_MEMORY; 323 args.memory_base = (const FT_Byte*)memoryBase; 324 args.memory_size = strm->getLength(); 325 } else { 326//printf("fopen(%s)\n", keyString.c_str()); 327 args.flags = FT_OPEN_STREAM; 328 args.stream = &rec->fFTStream; 329 } 330 331 FT_Error err = FT_Open_Face(gFTLibrary, &args, face_index, &rec->fFace); 332 if (err) { // bad filename, try the default font 333 fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); 334 SkDELETE(rec); 335 return NULL; 336 } else { 337 SkASSERT(rec->fFace); 338 //fprintf(stderr, "Opened font '%s'\n", filename.c_str()); 339 rec->fNext = gFaceRecHead; 340 gFaceRecHead = rec; 341 return rec; 342 } 343} 344 345// Caller must lock gFTMutex before calling this function. 346static void unref_ft_face(FT_Face face) { 347 SkFaceRec* rec = gFaceRecHead; 348 SkFaceRec* prev = NULL; 349 while (rec) { 350 SkFaceRec* next = rec->fNext; 351 if (rec->fFace == face) { 352 if (--rec->fRefCnt == 0) { 353 if (prev) { 354 prev->fNext = next; 355 } else { 356 gFaceRecHead = next; 357 } 358 FT_Done_Face(face); 359 SkDELETE(rec); 360 } 361 return; 362 } 363 prev = rec; 364 rec = next; 365 } 366 SkDEBUGFAIL("shouldn't get here, face not in list"); 367} 368 369class AutoFTAccess { 370public: 371 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { 372 gFTMutex.acquire(); 373 if (1 == ++gFTCount) { 374 if (!InitFreetype()) { 375 sk_throw(); 376 } 377 } 378 fRec = ref_ft_face(tf); 379 if (fRec) { 380 fFace = fRec->fFace; 381 } 382 } 383 384 ~AutoFTAccess() { 385 if (fFace) { 386 unref_ft_face(fFace); 387 } 388 if (0 == --gFTCount) { 389 FT_Done_FreeType(gFTLibrary); 390 } 391 gFTMutex.release(); 392 } 393 394 SkFaceRec* rec() { return fRec; } 395 FT_Face face() { return fFace; } 396 397private: 398 SkFaceRec* fRec; 399 FT_Face fFace; 400}; 401 402/////////////////////////////////////////////////////////////////////////// 403 404// Work around for old versions of freetype. 405static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count, 406 FT_Int32 loadFlags, FT_Fixed* advances) { 407#ifdef FT_ADVANCES_H 408 return FT_Get_Advances(face, start, count, loadFlags, advances); 409#else 410 if (!face || start >= face->num_glyphs || 411 start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) { 412 return 6; // "Invalid argument." 413 } 414 if (count == 0) 415 return 0; 416 417 for (int i = 0; i < count; i++) { 418 FT_Error err = FT_Load_Glyph(face, start + i, FT_LOAD_NO_SCALE); 419 if (err) 420 return err; 421 advances[i] = face->glyph->advance.x; 422 } 423 424 return 0; 425#endif 426} 427 428static bool canEmbed(FT_Face face) { 429#ifdef FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 430 FT_UShort fsType = FT_Get_FSType_Flags(face); 431 return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 432 FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0; 433#else 434 // No embedding is 0x2 and bitmap embedding only is 0x200. 435 TT_OS2* os2_table; 436 if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 437 return (os2_table->fsType & 0x202) == 0; 438 } 439 return false; // We tried, fail safe. 440#endif 441} 442 443static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { 444 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); 445 if (!glyph_id) 446 return false; 447 if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0) 448 return false; 449 FT_Outline_Get_CBox(&face->glyph->outline, bbox); 450 return true; 451} 452 453static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { 454 FT_Fixed advance = 0; 455 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { 456 return false; 457 } 458 SkASSERT(data); 459 *data = advance; 460 return true; 461} 462 463static void populate_glyph_to_unicode(FT_Face& face, 464 SkTDArray<SkUnichar>* glyphToUnicode) { 465 // Check and see if we have Unicode cmaps. 466 for (int i = 0; i < face->num_charmaps; ++i) { 467 // CMaps known to support Unicode: 468 // Platform ID Encoding ID Name 469 // ----------- ----------- ----------------------------------- 470 // 0 0,1 Apple Unicode 471 // 0 3 Apple Unicode 2.0 (preferred) 472 // 3 1 Microsoft Unicode UCS-2 473 // 3 10 Microsoft Unicode UCS-4 (preferred) 474 // 475 // See Apple TrueType Reference Manual 476 // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html 477 // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html#ID 478 // Microsoft OpenType Specification 479 // http://www.microsoft.com/typography/otspec/cmap.htm 480 481 FT_UShort platformId = face->charmaps[i]->platform_id; 482 FT_UShort encodingId = face->charmaps[i]->encoding_id; 483 484 if (platformId != 0 && platformId != 3) { 485 continue; 486 } 487 if (platformId == 3 && encodingId != 1 && encodingId != 10) { 488 continue; 489 } 490 bool preferredMap = ((platformId == 3 && encodingId == 10) || 491 (platformId == 0 && encodingId == 3)); 492 493 FT_Set_Charmap(face, face->charmaps[i]); 494 if (glyphToUnicode->isEmpty()) { 495 glyphToUnicode->setCount(face->num_glyphs); 496 memset(glyphToUnicode->begin(), 0, 497 sizeof(SkUnichar) * face->num_glyphs); 498 } 499 500 // Iterate through each cmap entry. 501 FT_UInt glyphIndex; 502 for (SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 503 glyphIndex != 0; 504 charCode = FT_Get_Next_Char(face, charCode, &glyphIndex)) { 505 if (charCode && 506 ((*glyphToUnicode)[glyphIndex] == 0 || preferredMap)) { 507 (*glyphToUnicode)[glyphIndex] = charCode; 508 } 509 } 510 } 511} 512 513SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( 514 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 515 const uint32_t* glyphIDs, 516 uint32_t glyphIDsCount) const { 517#if defined(SK_BUILD_FOR_MAC) 518 return NULL; 519#else 520 AutoFTAccess fta(this); 521 FT_Face face = fta.face(); 522 if (!face) { 523 return NULL; 524 } 525 526 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 527 info->fFontName.set(FT_Get_Postscript_Name(face)); 528 info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face); 529 info->fLastGlyphID = face->num_glyphs - 1; 530 info->fEmSize = 1000; 531 532 bool cid = false; 533 const char* fontType = FT_Get_X11_Font_Format(face); 534 if (strcmp(fontType, "Type 1") == 0) { 535 info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 536 } else if (strcmp(fontType, "CID Type 1") == 0) { 537 info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 538 cid = true; 539 } else if (strcmp(fontType, "CFF") == 0) { 540 info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 541 } else if (strcmp(fontType, "TrueType") == 0) { 542 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 543 cid = true; 544 TT_Header* ttHeader; 545 if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, 546 ft_sfnt_head)) != NULL) { 547 info->fEmSize = ttHeader->Units_Per_EM; 548 } 549 } else { 550 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 551 } 552 553 info->fStyle = 0; 554 if (FT_IS_FIXED_WIDTH(face)) 555 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 556 if (face->style_flags & FT_STYLE_FLAG_ITALIC) 557 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 558 559 PS_FontInfoRec ps_info; 560 TT_Postscript* tt_info; 561 if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { 562 info->fItalicAngle = ps_info.italic_angle; 563 } else if ((tt_info = 564 (TT_Postscript*)FT_Get_Sfnt_Table(face, 565 ft_sfnt_post)) != NULL) { 566 info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle); 567 } else { 568 info->fItalicAngle = 0; 569 } 570 571 info->fAscent = face->ascender; 572 info->fDescent = face->descender; 573 574 // Figure out a good guess for StemV - Min width of i, I, !, 1. 575 // This probably isn't very good with an italic font. 576 int16_t min_width = SHRT_MAX; 577 info->fStemV = 0; 578 char stem_chars[] = {'i', 'I', '!', '1'}; 579 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 580 FT_BBox bbox; 581 if (GetLetterCBox(face, stem_chars[i], &bbox)) { 582 int16_t width = bbox.xMax - bbox.xMin; 583 if (width > 0 && width < min_width) { 584 min_width = width; 585 info->fStemV = min_width; 586 } 587 } 588 } 589 590 TT_PCLT* pclt_info; 591 TT_OS2* os2_table; 592 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { 593 info->fCapHeight = pclt_info->CapHeight; 594 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 595 if (serif_style >= 2 && serif_style <= 6) 596 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 597 else if (serif_style >= 9 && serif_style <= 12) 598 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 599 } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) && 600 // sCapHeight is available only when version 2 or later. 601 os2_table->version != 0xFFFF && 602 os2_table->version >= 2) { 603 info->fCapHeight = os2_table->sCapHeight; 604 } else { 605 // Figure out a good guess for CapHeight: average the height of M and X. 606 FT_BBox m_bbox, x_bbox; 607 bool got_m, got_x; 608 got_m = GetLetterCBox(face, 'M', &m_bbox); 609 got_x = GetLetterCBox(face, 'X', &x_bbox); 610 if (got_m && got_x) { 611 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 612 x_bbox.yMin) / 2; 613 } else if (got_m && !got_x) { 614 info->fCapHeight = m_bbox.yMax - m_bbox.yMin; 615 } else if (!got_m && got_x) { 616 info->fCapHeight = x_bbox.yMax - x_bbox.yMin; 617 } else { 618 // Last resort, use the ascent. 619 info->fCapHeight = info->fAscent; 620 } 621 } 622 623 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 624 face->bbox.xMax, face->bbox.yMin); 625 626 if (!canEmbed(face) || !FT_IS_SCALABLE(face) || 627 info->fType == SkAdvancedTypefaceMetrics::kOther_Font) { 628 perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo; 629 } 630 631 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 632 if (FT_IS_FIXED_WIDTH(face)) { 633 appendRange(&info->fGlyphWidths, 0); 634 int16_t advance = face->max_advance_width; 635 info->fGlyphWidths->fAdvance.append(1, &advance); 636 finishRange(info->fGlyphWidths.get(), 0, 637 SkAdvancedTypefaceMetrics::WidthRange::kDefault); 638 } else if (!cid) { 639 appendRange(&info->fGlyphWidths, 0); 640 // So as to not blow out the stack, get advances in batches. 641 for (int gID = 0; gID < face->num_glyphs; gID += 128) { 642 FT_Fixed advances[128]; 643 int advanceCount = 128; 644 if (gID + advanceCount > face->num_glyphs) 645 advanceCount = face->num_glyphs - gID; 646 getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE, 647 advances); 648 for (int i = 0; i < advanceCount; i++) { 649 int16_t advance = advances[i]; 650 info->fGlyphWidths->fAdvance.append(1, &advance); 651 } 652 } 653 finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1, 654 SkAdvancedTypefaceMetrics::WidthRange::kRange); 655 } else { 656 info->fGlyphWidths.reset( 657 getAdvanceData(face, 658 face->num_glyphs, 659 glyphIDs, 660 glyphIDsCount, 661 &getWidthAdvance)); 662 } 663 } 664 665 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo && 666 FT_HAS_VERTICAL(face)) { 667 SkASSERT(false); // Not implemented yet. 668 } 669 670 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo && 671 info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 672 // Postscript fonts may contain more than 255 glyphs, so we end up 673 // using multiple font descriptions with a glyph ordering. Record 674 // the name of each glyph. 675 info->fGlyphNames.reset( 676 new SkAutoTArray<SkString>(face->num_glyphs)); 677 for (int gID = 0; gID < face->num_glyphs; gID++) { 678 char glyphName[128]; // PS limit for names is 127 bytes. 679 FT_Get_Glyph_Name(face, gID, glyphName, 128); 680 info->fGlyphNames->get()[gID].set(glyphName); 681 } 682 } 683 684 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo && 685 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 686 face->num_charmaps) { 687 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 688 } 689 690 if (!canEmbed(face)) 691 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 692 693 return info; 694#endif 695} 696 697/////////////////////////////////////////////////////////////////////////// 698 699static bool bothZero(SkScalar a, SkScalar b) { 700 return 0 == a && 0 == b; 701} 702 703// returns false if there is any non-90-rotation or skew 704static bool isAxisAligned(const SkScalerContext::Rec& rec) { 705 return 0 == rec.fPreSkewX && 706 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 707 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 708} 709 710SkScalerContext* SkTypeface_FreeType::onCreateScalerContext( 711 const SkDescriptor* desc) const { 712 SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, 713 (const_cast<SkTypeface_FreeType*>(this), 714 desc)); 715 if (!c->success()) { 716 SkDELETE(c); 717 c = NULL; 718 } 719 return c; 720} 721 722void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { 723 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 724 //Cap the requested size as larger sizes give bogus values. 725 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. 726 if (rec->fTextSize > SkIntToScalar(1 << 14)) { 727 rec->fTextSize = SkIntToScalar(1 << 14); 728 } 729 730 if (!is_lcd_supported() && isLCD(*rec)) { 731 // If the runtime Freetype library doesn't support LCD mode, we disable 732 // it here. 733 rec->fMaskFormat = SkMask::kA8_Format; 734 } 735 736 SkPaint::Hinting h = rec->getHinting(); 737 if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { 738 // collapse full->normal hinting if we're not doing LCD 739 h = SkPaint::kNormal_Hinting; 740 } 741 if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag)) { 742 if (SkPaint::kNo_Hinting != h) { 743 h = SkPaint::kSlight_Hinting; 744 } 745 } 746 747 // rotated text looks bad with hinting, so we disable it as needed 748 if (!isAxisAligned(*rec)) { 749 h = SkPaint::kNo_Hinting; 750 } 751 rec->setHinting(h); 752 753#ifndef SK_GAMMA_APPLY_TO_A8 754 if (!isLCD(*rec)) { 755 rec->ignorePreBlend(); 756 } 757#endif 758} 759 760int SkTypeface_FreeType::onGetUPEM() const { 761 AutoFTAccess fta(this); 762 FT_Face face = fta.face(); 763 return face ? face->units_per_EM : 0; 764} 765 766bool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[], 767 int count, int32_t adjustments[]) const { 768 AutoFTAccess fta(this); 769 FT_Face face = fta.face(); 770 if (!face || !FT_HAS_KERNING(face)) { 771 return false; 772 } 773 774 for (int i = 0; i < count - 1; ++i) { 775 FT_Vector delta; 776 FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 777 FT_KERNING_UNSCALED, &delta); 778 if (err) { 779 return false; 780 } 781 adjustments[i] = delta.x; 782 } 783 return true; 784} 785 786static FT_Int chooseBitmapStrike(FT_Face face, SkFixed scaleY) { 787 // early out if face is bad 788 if (face == NULL) { 789 SkDEBUGF(("chooseBitmapStrike aborted due to NULL face\n")); 790 return -1; 791 } 792 // determine target ppem 793 FT_Pos targetPPEM = SkFixedToFDot6(scaleY); 794 // find a bitmap strike equal to or just larger than the requested size 795 FT_Int chosenStrikeIndex = -1; 796 FT_Pos chosenPPEM = 0; 797 for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) { 798 FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem; 799 if (thisPPEM == targetPPEM) { 800 // exact match - our search stops here 801 chosenPPEM = thisPPEM; 802 chosenStrikeIndex = strikeIndex; 803 break; 804 } else if (chosenPPEM < targetPPEM) { 805 // attempt to increase chosenPPEM 806 if (thisPPEM > chosenPPEM) { 807 chosenPPEM = thisPPEM; 808 chosenStrikeIndex = strikeIndex; 809 } 810 } else { 811 // attempt to decrease chosenPPEM, but not below targetPPEM 812 if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) { 813 chosenPPEM = thisPPEM; 814 chosenStrikeIndex = strikeIndex; 815 } 816 } 817 } 818 if (chosenStrikeIndex != -1) { 819 // use the chosen strike 820 FT_Error err = FT_Select_Size(face, chosenStrikeIndex); 821 if (err != 0) { 822 SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_name, 823 chosenStrikeIndex, err)); 824 chosenStrikeIndex = -1; 825 } 826 } 827 return chosenStrikeIndex; 828} 829 830SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, 831 const SkDescriptor* desc) 832 : SkScalerContext_FreeType_Base(typeface, desc) { 833 SkAutoMutexAcquire ac(gFTMutex); 834 835 if (gFTCount == 0) { 836 if (!InitFreetype()) { 837 sk_throw(); 838 } 839 } 840 ++gFTCount; 841 842 // load the font file 843 fStrikeIndex = -1; 844 fFTSize = NULL; 845 fFace = NULL; 846 fFaceRec = ref_ft_face(typeface); 847 if (NULL == fFaceRec) { 848 return; 849 } 850 fFace = fFaceRec->fFace; 851 852 // A is the total matrix. 853 SkMatrix A; 854 fRec.getSingleMatrix(&A); 855 856 SkScalar sx = A.getScaleX(); 857 SkScalar sy = A.getScaleY(); 858 fMatrix22Scalar.reset(); 859 860 // In GDI, the hinter is aware of the current transformation 861 // (the transform is in some sense applied before/with the hinting). 862 // The bytecode can then test if it is rotated or stretched and decide 863 // to apply instructions or not. 864 // 865 // FreeType, however, always does the transformation strictly after hinting. 866 // It just sets 'rotated' and 'stretched' to false and only applies the 867 // size before hinting. 868 // 869 // Also, FreeType respects the head::flags::IntegerScaling flag, 870 // (although this is patched out on most major distros) 871 // so it is critical to get the size correct on the request. 872 // 873 // This also gets us the actual closest size on bitmap fonts as well. 874 if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) { 875 // h is where A maps the horizontal baseline. 876 SkPoint h = SkPoint::Make(SK_Scalar1, 0); 877 A.mapPoints(&h, 1); 878 879 // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). 880 SkMatrix G; 881 SkComputeGivensRotation(h, &G); 882 883 // GA is the matrix A with rotation removed. 884 SkMatrix GA(G); 885 GA.preConcat(A); 886 887 sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX)); 888 sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); 889 890 // sA is the total matrix A without the text scale. 891 SkMatrix sA(A); 892 sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size 893 894 fMatrix22Scalar.setScaleX(sA.getScaleX()); 895 fMatrix22Scalar.setSkewX(-sA.getSkewX()); 896 fMatrix22Scalar.setSkewY(-sA.getSkewY()); 897 fMatrix22Scalar.setScaleY(sA.getScaleY()); 898 } 899 fScale.set(sx, sy); 900 fScaleX = SkScalarToFixed(sx); 901 fScaleY = SkScalarToFixed(sy); 902 fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 903 fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX()); 904 fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY()); 905 fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 906 907 fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 908 909 // compute the flags we send to Load_Glyph 910 bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag); 911 { 912 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 913 914 if (SkMask::kBW_Format == fRec.fMaskFormat) { 915 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 916 loadFlags = FT_LOAD_TARGET_MONO; 917 if (fRec.getHinting() == SkPaint::kNo_Hinting) { 918 loadFlags = FT_LOAD_NO_HINTING; 919 linearMetrics = true; 920 } 921 } else { 922 switch (fRec.getHinting()) { 923 case SkPaint::kNo_Hinting: 924 loadFlags = FT_LOAD_NO_HINTING; 925 linearMetrics = true; 926 break; 927 case SkPaint::kSlight_Hinting: 928 loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 929 break; 930 case SkPaint::kNormal_Hinting: 931 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 932 loadFlags = FT_LOAD_FORCE_AUTOHINT; 933 } 934 break; 935 case SkPaint::kFull_Hinting: 936 if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 937 loadFlags = FT_LOAD_FORCE_AUTOHINT; 938 break; 939 } 940 loadFlags = FT_LOAD_TARGET_NORMAL; 941 if (isLCD(fRec)) { 942 if (fLCDIsVert) { 943 loadFlags = FT_LOAD_TARGET_LCD_V; 944 } else { 945 loadFlags = FT_LOAD_TARGET_LCD; 946 } 947 } 948 break; 949 default: 950 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 951 break; 952 } 953 } 954 955 if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 956 loadFlags |= FT_LOAD_NO_BITMAP; 957 } 958 959 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 960 // advances, as fontconfig and cairo do. 961 // See http://code.google.com/p/skia/issues/detail?id=222. 962 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 963 964 // Use vertical layout if requested. 965 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 966 loadFlags |= FT_LOAD_VERTICAL_LAYOUT; 967 } 968 969 loadFlags |= FT_LOAD_COLOR; 970 971 fLoadGlyphFlags = loadFlags; 972 } 973 974 FT_Error err = FT_New_Size(fFace, &fFTSize); 975 if (err != 0) { 976 SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_name)); 977 fFace = NULL; 978 return; 979 } 980 err = FT_Activate_Size(fFTSize); 981 if (err != 0) { 982 SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, fScaleX, fScaleY, 983 err)); 984 fFTSize = NULL; 985 return; 986 } 987 988 if (FT_IS_SCALABLE(fFace)) { 989 err = FT_Set_Char_Size(fFace, SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY), 72, 72); 990 if (err != 0) { 991 SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", 992 fFace, fScaleX, fScaleY, err)); 993 fFace = NULL; 994 return; 995 } 996 FT_Set_Transform(fFace, &fMatrix22, NULL); 997 } else if (FT_HAS_FIXED_SIZES(fFace)) { 998 fStrikeIndex = chooseBitmapStrike(fFace, fScaleY); 999 if (fStrikeIndex == -1) { 1000 SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", 1001 fFace->family_name, SkFixedToScalar(fScaleY))); 1002 } else { 1003 // FreeType does no provide linear metrics for bitmap fonts. 1004 linearMetrics = false; 1005 1006 // FreeType documentation says: 1007 // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. 1008 // Bitmap-only fonts ignore this flag. 1009 // 1010 // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. 1011 // Force this flag off for bitmap only fonts. 1012 fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; 1013 } 1014 } else { 1015 SkDEBUGF(("unknown kind of font \"%s\" size %f?\n", 1016 fFace->family_name, SkFixedToScalar(fScaleY))); 1017 } 1018 1019 fDoLinearMetrics = linearMetrics; 1020} 1021 1022SkScalerContext_FreeType::~SkScalerContext_FreeType() { 1023 SkAutoMutexAcquire ac(gFTMutex); 1024 1025 if (fFTSize != NULL) { 1026 FT_Done_Size(fFTSize); 1027 } 1028 1029 if (fFace != NULL) { 1030 unref_ft_face(fFace); 1031 } 1032 if (--gFTCount == 0) { 1033 FT_Done_FreeType(gFTLibrary); 1034 SkDEBUGCODE(gFTLibrary = NULL;) 1035 } 1036} 1037 1038/* We call this before each use of the fFace, since we may be sharing 1039 this face with other context (at different sizes). 1040*/ 1041FT_Error SkScalerContext_FreeType::setupSize() { 1042 FT_Error err = FT_Activate_Size(fFTSize); 1043 if (err != 0) { 1044 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 1045 fFaceRec->fFontID, fScaleX, fScaleY, err)); 1046 fFTSize = NULL; 1047 return err; 1048 } 1049 1050 // seems we need to reset this every time (not sure why, but without it 1051 // I get random italics from some other fFTSize) 1052 FT_Set_Transform(fFace, &fMatrix22, NULL); 1053 return 0; 1054} 1055 1056unsigned SkScalerContext_FreeType::generateGlyphCount() { 1057 return fFace->num_glyphs; 1058} 1059 1060uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 1061 return SkToU16(FT_Get_Char_Index( fFace, uni )); 1062} 1063 1064SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 1065 // iterate through each cmap entry, looking for matching glyph indices 1066 FT_UInt glyphIndex; 1067 SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 1068 1069 while (glyphIndex != 0) { 1070 if (glyphIndex == glyph) { 1071 return charCode; 1072 } 1073 charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 1074 } 1075 1076 return 0; 1077} 1078 1079void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 1080#ifdef FT_ADVANCES_H 1081 /* unhinted and light hinted text have linearly scaled advances 1082 * which are very cheap to compute with some font formats... 1083 */ 1084 if (fDoLinearMetrics) { 1085 SkAutoMutexAcquire ac(gFTMutex); 1086 1087 if (this->setupSize()) { 1088 glyph->zeroMetrics(); 1089 return; 1090 } 1091 1092 FT_Error error; 1093 FT_Fixed advance; 1094 1095 error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount), 1096 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 1097 &advance ); 1098 if (0 == error) { 1099 glyph->fRsbDelta = 0; 1100 glyph->fLsbDelta = 0; 1101 glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, advance); 1102 glyph->fAdvanceY = - SkFixedMul(fMatrix22.yx, advance); 1103 return; 1104 } 1105 } 1106#endif /* FT_ADVANCES_H */ 1107 /* otherwise, we need to load/hint the glyph, which is slower */ 1108 this->generateMetrics(glyph); 1109 return; 1110} 1111 1112void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 1113 FT_BBox* bbox, 1114 bool snapToPixelBoundary) { 1115 1116 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1117 1118 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1119 int dx = SkFixedToFDot6(glyph->getSubXFixed()); 1120 int dy = SkFixedToFDot6(glyph->getSubYFixed()); 1121 // negate dy since freetype-y-goes-up and skia-y-goes-down 1122 bbox->xMin += dx; 1123 bbox->yMin -= dy; 1124 bbox->xMax += dx; 1125 bbox->yMax -= dy; 1126 } 1127 1128 // outset the box to integral boundaries 1129 if (snapToPixelBoundary) { 1130 bbox->xMin &= ~63; 1131 bbox->yMin &= ~63; 1132 bbox->xMax = (bbox->xMax + 63) & ~63; 1133 bbox->yMax = (bbox->yMax + 63) & ~63; 1134 } 1135 1136 // Must come after snapToPixelBoundary so that the width and height are 1137 // consistent. Otherwise asserts will fire later on when generating the 1138 // glyph image. 1139 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1140 FT_Vector vector; 1141 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1142 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1143 FT_Vector_Transform(&vector, &fMatrix22); 1144 bbox->xMin += vector.x; 1145 bbox->xMax += vector.x; 1146 bbox->yMin += vector.y; 1147 bbox->yMax += vector.y; 1148 } 1149} 1150 1151bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { 1152 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); 1153 if (!glyph_id) 1154 return false; 1155 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) 1156 return false; 1157 emboldenIfNeeded(fFace, fFace->glyph); 1158 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1159 return true; 1160} 1161 1162void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1163 if (isLCD(fRec)) { 1164 if (fLCDIsVert) { 1165 glyph->fHeight += gLCDExtra; 1166 glyph->fTop -= gLCDExtra >> 1; 1167 } else { 1168 glyph->fWidth += gLCDExtra; 1169 glyph->fLeft -= gLCDExtra >> 1; 1170 } 1171 } 1172} 1173 1174inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { 1175 glyph.fWidth *= scale; 1176 glyph.fHeight *= scale; 1177 glyph.fTop *= scale; 1178 glyph.fLeft *= scale; 1179 1180 SkFixed fixedScale = SkScalarToFixed(scale); 1181 glyph.fAdvanceX = SkFixedMul(glyph.fAdvanceX, fixedScale); 1182 glyph.fAdvanceY = SkFixedMul(glyph.fAdvanceY, fixedScale); 1183} 1184 1185void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1186 SkAutoMutexAcquire ac(gFTMutex); 1187 1188 glyph->fRsbDelta = 0; 1189 glyph->fLsbDelta = 0; 1190 1191 FT_Error err; 1192 1193 if (this->setupSize()) { 1194 goto ERROR; 1195 } 1196 1197 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags ); 1198 if (err != 0) { 1199#if 0 1200 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%x) returned 0x%x\n", 1201 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err)); 1202#endif 1203 ERROR: 1204 glyph->zeroMetrics(); 1205 return; 1206 } 1207 emboldenIfNeeded(fFace, fFace->glyph); 1208 1209 switch ( fFace->glyph->format ) { 1210 case FT_GLYPH_FORMAT_OUTLINE: 1211 if (0 == fFace->glyph->outline.n_contours) { 1212 glyph->fWidth = 0; 1213 glyph->fHeight = 0; 1214 glyph->fTop = 0; 1215 glyph->fLeft = 0; 1216 } else { 1217 FT_BBox bbox; 1218 getBBoxForCurrentGlyph(glyph, &bbox, true); 1219 1220 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); 1221 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); 1222 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); 1223 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); 1224 1225 updateGlyphIfLCD(glyph); 1226 } 1227 break; 1228 1229 case FT_GLYPH_FORMAT_BITMAP: 1230 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1231 FT_Vector vector; 1232 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1233 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1234 FT_Vector_Transform(&vector, &fMatrix22); 1235 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 1236 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 1237 } 1238 1239 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { 1240 glyph->fMaskFormat = SkMask::kARGB32_Format; 1241 } 1242 1243 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 1244 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 1245 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 1246 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 1247 break; 1248 1249 default: 1250 SkDEBUGFAIL("unknown glyph format"); 1251 goto ERROR; 1252 } 1253 1254 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1255 if (fDoLinearMetrics) { 1256 glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance); 1257 glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance); 1258 } else { 1259 glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x); 1260 glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y); 1261 } 1262 } else { 1263 if (fDoLinearMetrics) { 1264 glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance); 1265 glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance); 1266 } else { 1267 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); 1268 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); 1269 1270 if (fRec.fFlags & kDevKernText_Flag) { 1271 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1272 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1273 } 1274 } 1275 } 1276 1277 if (fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && fScaleY && fFace->size->metrics.y_ppem) { 1278 // NOTE: both dimensions are scaled by y_ppem. this is WAI. 1279 scaleGlyphMetrics(*glyph, SkScalarDiv(SkFixedToScalar(fScaleY), 1280 SkIntToScalar(fFace->size->metrics.y_ppem))); 1281 } 1282 1283#ifdef ENABLE_GLYPH_SPEW 1284 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); 1285 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth)); 1286#endif 1287} 1288 1289 1290void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1291 SkAutoMutexAcquire ac(gFTMutex); 1292 1293 FT_Error err; 1294 1295 if (this->setupSize()) { 1296 goto ERROR; 1297 } 1298 1299 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags); 1300 if (err != 0) { 1301 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", 1302 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err)); 1303 ERROR: 1304 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 1305 return; 1306 } 1307 1308 emboldenIfNeeded(fFace, fFace->glyph); 1309 generateGlyphImage(fFace, glyph); 1310} 1311 1312 1313void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, 1314 SkPath* path) { 1315 SkAutoMutexAcquire ac(gFTMutex); 1316 1317 SkASSERT(&glyph && path); 1318 1319 if (this->setupSize()) { 1320 path->reset(); 1321 return; 1322 } 1323 1324 uint32_t flags = fLoadGlyphFlags; 1325 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 1326 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 1327 1328 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags); 1329 1330 if (err != 0) { 1331 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1332 glyph.getGlyphID(fBaseGlyphCount), flags, err)); 1333 path->reset(); 1334 return; 1335 } 1336 emboldenIfNeeded(fFace, fFace->glyph); 1337 1338 generateGlyphPath(fFace, path); 1339 1340 // The path's origin from FreeType is always the horizontal layout origin. 1341 // Offset the path so that it is relative to the vertical origin if needed. 1342 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1343 FT_Vector vector; 1344 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1345 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1346 FT_Vector_Transform(&vector, &fMatrix22); 1347 path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); 1348 } 1349} 1350 1351void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 1352 SkPaint::FontMetrics* my) { 1353 if (NULL == mx && NULL == my) { 1354 return; 1355 } 1356 1357 SkAutoMutexAcquire ac(gFTMutex); 1358 1359 if (this->setupSize()) { 1360 ERROR: 1361 if (mx) { 1362 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); 1363 } 1364 if (my) { 1365 sk_bzero(my, sizeof(SkPaint::FontMetrics)); 1366 } 1367 return; 1368 } 1369 1370 FT_Face face = fFace; 1371 SkScalar scaleX = fScale.x(); 1372 SkScalar scaleY = fScale.y(); 1373 SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY; 1374 SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY; 1375 1376 // fetch units/EM from "head" table if needed (ie for bitmap fonts) 1377 SkScalar upem = SkIntToScalar(face->units_per_EM); 1378 if (!upem) { 1379 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1380 if (ttHeader) { 1381 upem = SkIntToScalar(ttHeader->Units_Per_EM); 1382 } 1383 } 1384 1385 // use the os/2 table as a source of reasonable defaults. 1386 SkScalar x_height = 0.0f; 1387 SkScalar avgCharWidth = 0.0f; 1388 SkScalar cap_height = 0.0f; 1389 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1390 if (os2) { 1391 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; 1392 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; 1393 if (os2->version != 0xFFFF && os2->version >= 2) { 1394 cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem; 1395 } 1396 } 1397 1398 // pull from format-specific metrics as needed 1399 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; 1400 SkScalar underlineThickness, underlinePosition; 1401 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font 1402 ascent = -SkIntToScalar(face->ascender) / upem; 1403 descent = -SkIntToScalar(face->descender) / upem; 1404 leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem; 1405 xmin = SkIntToScalar(face->bbox.xMin) / upem; 1406 xmax = SkIntToScalar(face->bbox.xMax) / upem; 1407 ymin = -SkIntToScalar(face->bbox.yMin) / upem; 1408 ymax = -SkIntToScalar(face->bbox.yMax) / upem; 1409 underlineThickness = SkIntToScalar(face->underline_thickness) / upem; 1410#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX 1411 underlinePosition = -SkIntToScalar(face->underline_position) / upem; 1412#else 1413 underlinePosition = -SkIntToScalar(face->underline_position + 1414 face->underline_thickness / 2) / upem; 1415#endif 1416 1417 if(mx) { 1418 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1419 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1420 } 1421 if(my){ 1422 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1423 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1424 } 1425 // we may be able to synthesize x_height and cap_height from outline 1426 if (!x_height) { 1427 FT_BBox bbox; 1428 if (getCBoxForLetter('x', &bbox)) { 1429 x_height = SkIntToScalar(bbox.yMax) / 64.0f; 1430 } 1431 } 1432 if (!cap_height) { 1433 FT_BBox bbox; 1434 if (getCBoxForLetter('H', &bbox)) { 1435 cap_height = SkIntToScalar(bbox.yMax) / 64.0f; 1436 } 1437 } 1438 } else if (fStrikeIndex != -1) { // bitmap strike metrics 1439 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); 1440 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); 1441 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); 1442 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f); 1443 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) 1444 + ascent - descent; 1445 xmin = 0.0f; 1446 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; 1447 ymin = descent + leading; 1448 ymax = ascent - descent; 1449 underlineThickness = 0; 1450 underlinePosition = 0; 1451 1452 if(mx) { 1453 mx->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1454 mx->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1455 } 1456 if(my){ 1457 my->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1458 my->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1459 } 1460 } else { 1461 goto ERROR; 1462 } 1463 1464 // synthesize elements that were not provided by the os/2 table or format-specific metrics 1465 if (!x_height) { 1466 x_height = -ascent; 1467 } 1468 if (!avgCharWidth) { 1469 avgCharWidth = xmax - xmin; 1470 } 1471 if (!cap_height) { 1472 cap_height = -ascent; 1473 } 1474 1475 // disallow negative linespacing 1476 if (leading < 0.0f) { 1477 leading = 0.0f; 1478 } 1479 1480 if (mx) { 1481 mx->fTop = ymax * mxy; 1482 mx->fAscent = ascent * mxy; 1483 mx->fDescent = descent * mxy; 1484 mx->fBottom = ymin * mxy; 1485 mx->fLeading = leading * mxy; 1486 mx->fAvgCharWidth = avgCharWidth * mxy; 1487 mx->fXMin = xmin; 1488 mx->fXMax = xmax; 1489 mx->fXHeight = x_height; 1490 mx->fCapHeight = cap_height; 1491#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX 1492 mx->fUnderlineThickness = underlineThickness; 1493 mx->fUnderlinePosition = underlinePosition; 1494#else 1495 mx->fUnderlineThickness = underlineThickness * mxy; 1496 mx->fUnderlinePosition = underlinePosition * mxy; 1497#endif 1498 } 1499 if (my) { 1500 my->fTop = ymax * myy; 1501 my->fAscent = ascent * myy; 1502 my->fDescent = descent * myy; 1503 my->fBottom = ymin * myy; 1504 my->fLeading = leading * myy; 1505 my->fAvgCharWidth = avgCharWidth * myy; 1506 my->fXMin = xmin; 1507 my->fXMax = xmax; 1508 my->fXHeight = x_height; 1509 my->fCapHeight = cap_height; 1510#ifdef SK_IGNORE_UNDERLINE_POSITION_FIX 1511 my->fUnderlineThickness = underlineThickness; 1512 my->fUnderlinePosition = underlinePosition; 1513#else 1514 my->fUnderlineThickness = underlineThickness * myy; 1515 my->fUnderlinePosition = underlinePosition * myy; 1516#endif 1517 } 1518} 1519 1520/////////////////////////////////////////////////////////////////////////////// 1521 1522// hand-tuned value to reduce outline embolden strength 1523#ifndef SK_OUTLINE_EMBOLDEN_DIVISOR 1524 #ifdef SK_BUILD_FOR_ANDROID 1525 #define SK_OUTLINE_EMBOLDEN_DIVISOR 34 1526 #else 1527 #define SK_OUTLINE_EMBOLDEN_DIVISOR 24 1528 #endif 1529#endif 1530 1531/////////////////////////////////////////////////////////////////////////////// 1532 1533void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph) 1534{ 1535 // check to see if the embolden bit is set 1536 if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) { 1537 return; 1538 } 1539 1540#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) 1541 // Android doesn't want to embolden a font that is already bold. 1542 if ((fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1543 return; 1544 } 1545#endif 1546 1547 switch (glyph->format) { 1548 case FT_GLYPH_FORMAT_OUTLINE: 1549 FT_Pos strength; 1550 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) 1551 / SK_OUTLINE_EMBOLDEN_DIVISOR; 1552 FT_Outline_Embolden(&glyph->outline, strength); 1553 break; 1554 case FT_GLYPH_FORMAT_BITMAP: 1555 FT_GlyphSlot_Own_Bitmap(glyph); 1556 FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0); 1557 break; 1558 default: 1559 SkDEBUGFAIL("unknown glyph format"); 1560 } 1561} 1562 1563/////////////////////////////////////////////////////////////////////////////// 1564 1565#include "SkUtils.h" 1566 1567static SkUnichar next_utf8(const void** chars) { 1568 return SkUTF8_NextUnichar((const char**)chars); 1569} 1570 1571static SkUnichar next_utf16(const void** chars) { 1572 return SkUTF16_NextUnichar((const uint16_t**)chars); 1573} 1574 1575static SkUnichar next_utf32(const void** chars) { 1576 const SkUnichar** uniChars = (const SkUnichar**)chars; 1577 SkUnichar uni = **uniChars; 1578 *uniChars += 1; 1579 return uni; 1580} 1581 1582typedef SkUnichar (*EncodingProc)(const void**); 1583 1584static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 1585 static const EncodingProc gProcs[] = { 1586 next_utf8, next_utf16, next_utf32 1587 }; 1588 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 1589 return gProcs[enc]; 1590} 1591 1592int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, 1593 uint16_t glyphs[], int glyphCount) const { 1594 AutoFTAccess fta(this); 1595 FT_Face face = fta.face(); 1596 if (!face) { 1597 if (glyphs) { 1598 sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); 1599 } 1600 return 0; 1601 } 1602 1603 EncodingProc next_uni_proc = find_encoding_proc(encoding); 1604 1605 if (NULL == glyphs) { 1606 for (int i = 0; i < glyphCount; ++i) { 1607 if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { 1608 return i; 1609 } 1610 } 1611 return glyphCount; 1612 } else { 1613 int first = glyphCount; 1614 for (int i = 0; i < glyphCount; ++i) { 1615 unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); 1616 glyphs[i] = SkToU16(id); 1617 if (0 == id && i < first) { 1618 first = i; 1619 } 1620 } 1621 return first; 1622 } 1623} 1624 1625int SkTypeface_FreeType::onCountGlyphs() const { 1626 // we cache this value, using -1 as a sentinel for "not computed" 1627 if (fGlyphCount < 0) { 1628 AutoFTAccess fta(this); 1629 FT_Face face = fta.face(); 1630 // if the face failed, we still assign a non-negative value 1631 fGlyphCount = face ? face->num_glyphs : 0; 1632 } 1633 return fGlyphCount; 1634} 1635 1636SkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const { 1637 SkTypeface::LocalizedStrings* nameIter = 1638 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1639 if (NULL == nameIter) { 1640 SkString familyName; 1641 this->getFamilyName(&familyName); 1642 SkString language("und"); //undetermined 1643 nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 1644 } 1645 return nameIter; 1646} 1647 1648int SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const { 1649 AutoFTAccess fta(this); 1650 FT_Face face = fta.face(); 1651 1652 FT_ULong tableCount = 0; 1653 FT_Error error; 1654 1655 // When 'tag' is NULL, returns number of tables in 'length'. 1656 error = FT_Sfnt_Table_Info(face, 0, NULL, &tableCount); 1657 if (error) { 1658 return 0; 1659 } 1660 1661 if (tags) { 1662 for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) { 1663 FT_ULong tableTag; 1664 FT_ULong tablelength; 1665 error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength); 1666 if (error) { 1667 return 0; 1668 } 1669 tags[tableIndex] = static_cast<SkFontTableTag>(tableTag); 1670 } 1671 } 1672 return tableCount; 1673} 1674 1675size_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset, 1676 size_t length, void* data) const 1677{ 1678 AutoFTAccess fta(this); 1679 FT_Face face = fta.face(); 1680 1681 FT_ULong tableLength = 0; 1682 FT_Error error; 1683 1684 // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored. 1685 error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &tableLength); 1686 if (error) { 1687 return 0; 1688 } 1689 1690 if (offset > tableLength) { 1691 return 0; 1692 } 1693 FT_ULong size = SkTMin((FT_ULong)length, tableLength - (FT_ULong)offset); 1694 if (NULL != data) { 1695 error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size); 1696 if (error) { 1697 return 0; 1698 } 1699 } 1700 1701 return size; 1702} 1703 1704/////////////////////////////////////////////////////////////////////////////// 1705/////////////////////////////////////////////////////////////////////////////// 1706 1707/* Export this so that other parts of our FonttHost port can make use of our 1708 ability to extract the name+style from a stream, using FreeType's api. 1709*/ 1710bool find_name_and_attributes(SkStream* stream, SkString* name, 1711 SkTypeface::Style* style, bool* isFixedPitch) { 1712 FT_Library library; 1713 if (FT_Init_FreeType(&library)) { 1714 return false; 1715 } 1716 1717 FT_Open_Args args; 1718 memset(&args, 0, sizeof(args)); 1719 1720 const void* memoryBase = stream->getMemoryBase(); 1721 FT_StreamRec streamRec; 1722 1723 if (NULL != memoryBase) { 1724 args.flags = FT_OPEN_MEMORY; 1725 args.memory_base = (const FT_Byte*)memoryBase; 1726 args.memory_size = stream->getLength(); 1727 } else { 1728 memset(&streamRec, 0, sizeof(streamRec)); 1729 streamRec.size = stream->getLength(); 1730 streamRec.descriptor.pointer = stream; 1731 streamRec.read = sk_stream_read; 1732 streamRec.close = sk_stream_close; 1733 1734 args.flags = FT_OPEN_STREAM; 1735 args.stream = &streamRec; 1736 } 1737 1738 FT_Face face; 1739 if (FT_Open_Face(library, &args, 0, &face)) { 1740 FT_Done_FreeType(library); 1741 return false; 1742 } 1743 1744 int tempStyle = SkTypeface::kNormal; 1745 if (face->style_flags & FT_STYLE_FLAG_BOLD) { 1746 tempStyle |= SkTypeface::kBold; 1747 } 1748 if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 1749 tempStyle |= SkTypeface::kItalic; 1750 } 1751 1752 if (name) { 1753 name->set(face->family_name); 1754 } 1755 if (style) { 1756 *style = (SkTypeface::Style) tempStyle; 1757 } 1758 if (isFixedPitch) { 1759 *isFixedPitch = FT_IS_FIXED_WIDTH(face); 1760 } 1761 1762 FT_Done_Face(face); 1763 FT_Done_FreeType(library); 1764 return true; 1765} 1766