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 10 #include "SkBitmap.h" 11 #include "SkCanvas.h" 12 #include "SkColorPriv.h" 13 #include "SkDescriptor.h" 14 #include "SkFDot6.h" 15 #include "SkFontHost.h" 16 #include "SkMask.h" 17 #include "SkAdvancedTypefaceMetrics.h" 18 #include "SkScalerContext.h" 19 #include "SkStream.h" 20 #include "SkString.h" 21 #include "SkTemplates.h" 22 #include "SkThread.h" 23 24 #include <ft2build.h> 25 #include FT_FREETYPE_H 26 #include FT_OUTLINE_H 27 #include FT_SIZES_H 28 #include FT_TRUETYPE_TABLES_H 29 #include FT_TYPE1_TABLES_H 30 #include FT_BITMAP_H 31 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 32 #include FT_SYNTHESIS_H 33 #include FT_XFREE86_H 34 #ifdef FT_LCD_FILTER_H 35 #include FT_LCD_FILTER_H 36 #endif 37 38 #ifdef FT_ADVANCES_H 39 #include FT_ADVANCES_H 40 #endif 41 42 #if 0 43 // Also include the files by name for build tools which require this. 44 #include <freetype/freetype.h> 45 #include <freetype/ftoutln.h> 46 #include <freetype/ftsizes.h> 47 #include <freetype/tttables.h> 48 #include <freetype/ftadvanc.h> 49 #include <freetype/ftlcdfil.h> 50 #include <freetype/ftbitmap.h> 51 #include <freetype/ftsynth.h> 52 #endif 53 54 //#define ENABLE_GLYPH_SPEW // for tracing calls 55 //#define DUMP_STRIKE_CREATION 56 57 //#define SK_GAMMA_APPLY_TO_A8 58 59 #ifndef SK_GAMMA_CONTRAST 60 #define SK_GAMMA_CONTRAST 0x66 61 #endif 62 #ifndef SK_GAMMA_EXPONENT 63 #define SK_GAMMA_EXPONENT 2.2 64 #endif 65 66 // hand-tuned value to reduce outline embolden strength 67 #ifndef SK_OUTLINE_EMBOLDEN_DIVISOR 68 #ifdef SK_BUILD_FOR_ANDROID 69 #define SK_OUTLINE_EMBOLDEN_DIVISOR 34 70 #else 71 #define SK_OUTLINE_EMBOLDEN_DIVISOR 24 72 #endif 73 #endif 74 75 76 #ifdef SK_DEBUG 77 #define SkASSERT_CONTINUE(pred) \ 78 do { \ 79 if (!(pred)) \ 80 SkDebugf("file %s:%d: assert failed '" #pred "'\n", __FILE__, __LINE__); \ 81 } while (false) 82 #else 83 #define SkASSERT_CONTINUE(pred) 84 #endif 85 86 using namespace skia_advanced_typeface_metrics_utils; 87 88 static bool isLCD(const SkScalerContext::Rec& rec) { 89 switch (rec.fMaskFormat) { 90 case SkMask::kLCD16_Format: 91 case SkMask::kLCD32_Format: 92 return true; 93 default: 94 return false; 95 } 96 } 97 98 ////////////////////////////////////////////////////////////////////////// 99 100 struct SkFaceRec; 101 102 SK_DECLARE_STATIC_MUTEX(gFTMutex); 103 static int gFTCount; 104 static FT_Library gFTLibrary; 105 static SkFaceRec* gFaceRecHead; 106 static bool gLCDSupportValid; // true iff |gLCDSupport| has been set. 107 static bool gLCDSupport; // true iff LCD is supported by the runtime. 108 static int gLCDExtra; // number of extra pixels for filtering. 109 110 static const uint8_t* gGammaTables[2]; 111 112 ///////////////////////////////////////////////////////////////////////// 113 114 // See http://freetype.sourceforge.net/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden 115 // This value was chosen by eyeballing the result in Firefox and trying to match it. 116 static const FT_Pos kBitmapEmboldenStrength = 1 << 6; 117 118 // convert from Skia's fixed (16.16) to FreeType's fixed (26.6) representation 119 static inline int FixedToDot6(SkFixed x) { return x >> 10; } 120 // convert from FreeType's fixed (26.6) to Skia's fixed (16.16) representation 121 static inline SkFixed Dot6ToFixed(int x) { return x << 10; } 122 123 static bool 124 InitFreetype() { 125 FT_Error err = FT_Init_FreeType(&gFTLibrary); 126 if (err) { 127 return false; 128 } 129 130 // Setup LCD filtering. This reduces colour fringes for LCD rendered 131 // glyphs. 132 #ifdef FT_LCD_FILTER_H 133 // err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); 134 err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_LIGHT); 135 gLCDSupport = err == 0; 136 if (gLCDSupport) { 137 gLCDExtra = 2; //DEFAULT and LIGHT add one pixel to each side. 138 } 139 #else 140 gLCDSupport = false; 141 #endif 142 gLCDSupportValid = true; 143 144 return true; 145 } 146 147 class SkScalerContext_FreeType : public SkScalerContext { 148 public: 149 SkScalerContext_FreeType(const SkDescriptor* desc); 150 virtual ~SkScalerContext_FreeType(); 151 152 bool success() const { 153 return fFaceRec != NULL && 154 fFTSize != NULL && 155 fFace != NULL; 156 } 157 158 protected: 159 virtual unsigned generateGlyphCount(); 160 virtual uint16_t generateCharToGlyph(SkUnichar uni); 161 virtual void generateAdvance(SkGlyph* glyph); 162 virtual void generateMetrics(SkGlyph* glyph); 163 virtual void generateImage(const SkGlyph& glyph); 164 virtual void generatePath(const SkGlyph& glyph, SkPath* path); 165 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 166 SkPaint::FontMetrics* my); 167 virtual SkUnichar generateGlyphToChar(uint16_t glyph); 168 169 private: 170 SkFaceRec* fFaceRec; 171 FT_Face fFace; // reference to shared face in gFaceRecHead 172 FT_Size fFTSize; // our own copy 173 SkFixed fScaleX, fScaleY; 174 FT_Matrix fMatrix22; 175 uint32_t fLoadGlyphFlags; 176 bool fDoLinearMetrics; 177 178 FT_Error setupSize(); 179 void emboldenOutline(FT_Outline* outline); 180 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 181 bool snapToPixelBoundary = false); 182 void updateGlyphIfLCD(SkGlyph* glyph); 183 }; 184 185 /////////////////////////////////////////////////////////////////////////// 186 /////////////////////////////////////////////////////////////////////////// 187 188 #include "SkStream.h" 189 190 struct SkFaceRec { 191 SkFaceRec* fNext; 192 FT_Face fFace; 193 FT_StreamRec fFTStream; 194 SkStream* fSkStream; 195 uint32_t fRefCnt; 196 uint32_t fFontID; 197 198 // assumes ownership of the stream, will call unref() when its done 199 SkFaceRec(SkStream* strm, uint32_t fontID); 200 ~SkFaceRec() { 201 fSkStream->unref(); 202 } 203 }; 204 205 extern "C" { 206 static unsigned long sk_stream_read(FT_Stream stream, 207 unsigned long offset, 208 unsigned char* buffer, 209 unsigned long count ) { 210 SkStream* str = (SkStream*)stream->descriptor.pointer; 211 212 if (count) { 213 if (!str->rewind()) { 214 return 0; 215 } else { 216 unsigned long ret; 217 if (offset) { 218 ret = str->read(NULL, offset); 219 if (ret != offset) { 220 return 0; 221 } 222 } 223 ret = str->read(buffer, count); 224 if (ret != count) { 225 return 0; 226 } 227 count = ret; 228 } 229 } 230 return count; 231 } 232 233 static void sk_stream_close( FT_Stream stream) {} 234 } 235 236 SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) 237 : fSkStream(strm), fFontID(fontID) { 238 // SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); 239 240 sk_bzero(&fFTStream, sizeof(fFTStream)); 241 fFTStream.size = fSkStream->getLength(); 242 fFTStream.descriptor.pointer = fSkStream; 243 fFTStream.read = sk_stream_read; 244 fFTStream.close = sk_stream_close; 245 } 246 247 // Will return 0 on failure 248 static SkFaceRec* ref_ft_face(uint32_t fontID) { 249 SkFaceRec* rec = gFaceRecHead; 250 while (rec) { 251 if (rec->fFontID == fontID) { 252 SkASSERT(rec->fFace); 253 rec->fRefCnt += 1; 254 return rec; 255 } 256 rec = rec->fNext; 257 } 258 259 SkStream* strm = SkFontHost::OpenStream(fontID); 260 if (NULL == strm) { 261 SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID)); 262 return 0; 263 } 264 265 // this passes ownership of strm to the rec 266 rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); 267 268 FT_Open_Args args; 269 memset(&args, 0, sizeof(args)); 270 const void* memoryBase = strm->getMemoryBase(); 271 272 if (NULL != memoryBase) { 273 //printf("mmap(%s)\n", keyString.c_str()); 274 args.flags = FT_OPEN_MEMORY; 275 args.memory_base = (const FT_Byte*)memoryBase; 276 args.memory_size = strm->getLength(); 277 } else { 278 //printf("fopen(%s)\n", keyString.c_str()); 279 args.flags = FT_OPEN_STREAM; 280 args.stream = &rec->fFTStream; 281 } 282 283 int face_index; 284 int length = SkFontHost::GetFileName(fontID, NULL, 0, &face_index); 285 FT_Error err = FT_Open_Face(gFTLibrary, &args, length ? face_index : 0, 286 &rec->fFace); 287 288 if (err) { // bad filename, try the default font 289 fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); 290 SkDELETE(rec); 291 return 0; 292 } else { 293 SkASSERT(rec->fFace); 294 //fprintf(stderr, "Opened font '%s'\n", filename.c_str()); 295 rec->fNext = gFaceRecHead; 296 gFaceRecHead = rec; 297 rec->fRefCnt = 1; 298 return rec; 299 } 300 } 301 302 static void unref_ft_face(FT_Face face) { 303 SkFaceRec* rec = gFaceRecHead; 304 SkFaceRec* prev = NULL; 305 while (rec) { 306 SkFaceRec* next = rec->fNext; 307 if (rec->fFace == face) { 308 if (--rec->fRefCnt == 0) { 309 if (prev) { 310 prev->fNext = next; 311 } else { 312 gFaceRecHead = next; 313 } 314 FT_Done_Face(face); 315 SkDELETE(rec); 316 } 317 return; 318 } 319 prev = rec; 320 rec = next; 321 } 322 SkDEBUGFAIL("shouldn't get here, face not in list"); 323 } 324 325 /////////////////////////////////////////////////////////////////////////// 326 327 // Work around for old versions of freetype. 328 static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count, 329 FT_Int32 loadFlags, FT_Fixed* advances) { 330 #ifdef FT_ADVANCES_H 331 return FT_Get_Advances(face, start, count, loadFlags, advances); 332 #else 333 if (!face || start >= face->num_glyphs || 334 start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) { 335 return 6; // "Invalid argument." 336 } 337 if (count == 0) 338 return 0; 339 340 for (int i = 0; i < count; i++) { 341 FT_Error err = FT_Load_Glyph(face, start + i, FT_LOAD_NO_SCALE); 342 if (err) 343 return err; 344 advances[i] = face->glyph->advance.x; 345 } 346 347 return 0; 348 #endif 349 } 350 351 static bool canEmbed(FT_Face face) { 352 #ifdef FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 353 FT_UShort fsType = FT_Get_FSType_Flags(face); 354 return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 355 FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0; 356 #else 357 // No embedding is 0x2 and bitmap embedding only is 0x200. 358 TT_OS2* os2_table; 359 if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 360 return (os2_table->fsType & 0x202) == 0; 361 } 362 return false; // We tried, fail safe. 363 #endif 364 } 365 366 static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { 367 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); 368 if (!glyph_id) 369 return false; 370 FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE); 371 FT_Outline_Get_CBox(&face->glyph->outline, bbox); 372 return true; 373 } 374 375 static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { 376 FT_Fixed advance = 0; 377 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { 378 return false; 379 } 380 SkASSERT(data); 381 *data = advance; 382 return true; 383 } 384 385 static void populate_glyph_to_unicode(FT_Face& face, 386 SkTDArray<SkUnichar>* glyphToUnicode) { 387 // Check and see if we have Unicode cmaps. 388 for (int i = 0; i < face->num_charmaps; ++i) { 389 // CMaps known to support Unicode: 390 // Platform ID Encoding ID Name 391 // ----------- ----------- ----------------------------------- 392 // 0 0,1 Apple Unicode 393 // 0 3 Apple Unicode 2.0 (preferred) 394 // 3 1 Microsoft Unicode UCS-2 395 // 3 10 Microsoft Unicode UCS-4 (preferred) 396 // 397 // See Apple TrueType Reference Manual 398 // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html 399 // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html#ID 400 // Microsoft OpenType Specification 401 // http://www.microsoft.com/typography/otspec/cmap.htm 402 403 FT_UShort platformId = face->charmaps[i]->platform_id; 404 FT_UShort encodingId = face->charmaps[i]->encoding_id; 405 406 if (platformId != 0 && platformId != 3) { 407 continue; 408 } 409 if (platformId == 3 && encodingId != 1 && encodingId != 10) { 410 continue; 411 } 412 bool preferredMap = ((platformId == 3 && encodingId == 10) || 413 (platformId == 0 && encodingId == 3)); 414 415 FT_Set_Charmap(face, face->charmaps[i]); 416 if (glyphToUnicode->isEmpty()) { 417 glyphToUnicode->setCount(face->num_glyphs); 418 memset(glyphToUnicode->begin(), 0, 419 sizeof(SkUnichar) * face->num_glyphs); 420 } 421 422 // Iterate through each cmap entry. 423 FT_UInt glyphIndex; 424 for (SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 425 glyphIndex != 0; 426 charCode = FT_Get_Next_Char(face, charCode, &glyphIndex)) { 427 if (charCode && 428 ((*glyphToUnicode)[glyphIndex] == 0 || preferredMap)) { 429 (*glyphToUnicode)[glyphIndex] = charCode; 430 } 431 } 432 } 433 } 434 435 // static 436 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( 437 uint32_t fontID, 438 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 439 const uint32_t* glyphIDs, 440 uint32_t glyphIDsCount) { 441 #if defined(SK_BUILD_FOR_MAC) 442 return NULL; 443 #else 444 SkAutoMutexAcquire ac(gFTMutex); 445 FT_Library libInit = NULL; 446 if (gFTCount == 0) { 447 if (!InitFreetype()) 448 sk_throw(); 449 libInit = gFTLibrary; 450 } 451 SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); 452 SkFaceRec* rec = ref_ft_face(fontID); 453 if (NULL == rec) 454 return NULL; 455 FT_Face face = rec->fFace; 456 457 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 458 info->fFontName.set(FT_Get_Postscript_Name(face)); 459 info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face); 460 info->fLastGlyphID = face->num_glyphs - 1; 461 info->fEmSize = 1000; 462 463 bool cid = false; 464 const char* fontType = FT_Get_X11_Font_Format(face); 465 if (strcmp(fontType, "Type 1") == 0) { 466 info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 467 } else if (strcmp(fontType, "CID Type 1") == 0) { 468 info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 469 cid = true; 470 } else if (strcmp(fontType, "CFF") == 0) { 471 info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 472 } else if (strcmp(fontType, "TrueType") == 0) { 473 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 474 cid = true; 475 TT_Header* ttHeader; 476 if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, 477 ft_sfnt_head)) != NULL) { 478 info->fEmSize = ttHeader->Units_Per_EM; 479 } 480 } 481 482 info->fStyle = 0; 483 if (FT_IS_FIXED_WIDTH(face)) 484 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 485 if (face->style_flags & FT_STYLE_FLAG_ITALIC) 486 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 487 // We should set either Symbolic or Nonsymbolic; Nonsymbolic if the font's 488 // character set is a subset of 'Adobe standard Latin.' 489 info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style; 490 491 PS_FontInfoRec ps_info; 492 TT_Postscript* tt_info; 493 if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { 494 info->fItalicAngle = ps_info.italic_angle; 495 } else if ((tt_info = 496 (TT_Postscript*)FT_Get_Sfnt_Table(face, 497 ft_sfnt_post)) != NULL) { 498 info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle); 499 } else { 500 info->fItalicAngle = 0; 501 } 502 503 info->fAscent = face->ascender; 504 info->fDescent = face->descender; 505 506 // Figure out a good guess for StemV - Min width of i, I, !, 1. 507 // This probably isn't very good with an italic font. 508 int16_t min_width = SHRT_MAX; 509 info->fStemV = 0; 510 char stem_chars[] = {'i', 'I', '!', '1'}; 511 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 512 FT_BBox bbox; 513 if (GetLetterCBox(face, stem_chars[i], &bbox)) { 514 int16_t width = bbox.xMax - bbox.xMin; 515 if (width > 0 && width < min_width) { 516 min_width = width; 517 info->fStemV = min_width; 518 } 519 } 520 } 521 522 TT_PCLT* pclt_info; 523 TT_OS2* os2_table; 524 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { 525 info->fCapHeight = pclt_info->CapHeight; 526 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 527 if (serif_style >= 2 && serif_style <= 6) 528 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 529 else if (serif_style >= 9 && serif_style <= 12) 530 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 531 } else if ((os2_table = 532 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 533 info->fCapHeight = os2_table->sCapHeight; 534 } else { 535 // Figure out a good guess for CapHeight: average the height of M and X. 536 FT_BBox m_bbox, x_bbox; 537 bool got_m, got_x; 538 got_m = GetLetterCBox(face, 'M', &m_bbox); 539 got_x = GetLetterCBox(face, 'X', &x_bbox); 540 if (got_m && got_x) { 541 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 542 x_bbox.yMin) / 2; 543 } else if (got_m && !got_x) { 544 info->fCapHeight = m_bbox.yMax - m_bbox.yMin; 545 } else if (!got_m && got_x) { 546 info->fCapHeight = x_bbox.yMax - x_bbox.yMin; 547 } 548 } 549 550 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 551 face->bbox.xMax, face->bbox.yMin); 552 553 if (!canEmbed(face) || !FT_IS_SCALABLE(face) || 554 info->fType == SkAdvancedTypefaceMetrics::kOther_Font) { 555 perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo; 556 } 557 558 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 559 if (FT_IS_FIXED_WIDTH(face)) { 560 appendRange(&info->fGlyphWidths, 0); 561 int16_t advance = face->max_advance_width; 562 info->fGlyphWidths->fAdvance.append(1, &advance); 563 finishRange(info->fGlyphWidths.get(), 0, 564 SkAdvancedTypefaceMetrics::WidthRange::kDefault); 565 } else if (!cid) { 566 appendRange(&info->fGlyphWidths, 0); 567 // So as to not blow out the stack, get advances in batches. 568 for (int gID = 0; gID < face->num_glyphs; gID += 128) { 569 FT_Fixed advances[128]; 570 int advanceCount = 128; 571 if (gID + advanceCount > face->num_glyphs) 572 advanceCount = face->num_glyphs - gID + 1; 573 getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE, 574 advances); 575 for (int i = 0; i < advanceCount; i++) { 576 int16_t advance = advances[gID + i]; 577 info->fGlyphWidths->fAdvance.append(1, &advance); 578 } 579 } 580 finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1, 581 SkAdvancedTypefaceMetrics::WidthRange::kRange); 582 } else { 583 info->fGlyphWidths.reset( 584 getAdvanceData(face, 585 face->num_glyphs, 586 glyphIDs, 587 glyphIDsCount, 588 &getWidthAdvance)); 589 } 590 } 591 592 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo && 593 FT_HAS_VERTICAL(face)) { 594 SkASSERT(false); // Not implemented yet. 595 } 596 597 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo && 598 info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 599 // Postscript fonts may contain more than 255 glyphs, so we end up 600 // using multiple font descriptions with a glyph ordering. Record 601 // the name of each glyph. 602 info->fGlyphNames.reset( 603 new SkAutoTArray<SkString>(face->num_glyphs)); 604 for (int gID = 0; gID < face->num_glyphs; gID++) { 605 char glyphName[128]; // PS limit for names is 127 bytes. 606 FT_Get_Glyph_Name(face, gID, glyphName, 128); 607 info->fGlyphNames->get()[gID].set(glyphName); 608 } 609 } 610 611 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo && 612 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 613 face->num_charmaps) { 614 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 615 } 616 617 if (!canEmbed(face)) 618 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 619 620 unref_ft_face(face); 621 return info; 622 #endif 623 } 624 625 /////////////////////////////////////////////////////////////////////////// 626 627 #define BLACK_LUMINANCE_LIMIT 0x40 628 #define WHITE_LUMINANCE_LIMIT 0xA0 629 630 static bool bothZero(SkScalar a, SkScalar b) { 631 return 0 == a && 0 == b; 632 } 633 634 // returns false if there is any non-90-rotation or skew 635 static bool isAxisAligned(const SkScalerContext::Rec& rec) { 636 return 0 == rec.fPreSkewX && 637 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 638 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 639 } 640 641 void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { 642 if (!gLCDSupportValid) { 643 InitFreetype(); 644 FT_Done_FreeType(gFTLibrary); 645 } 646 647 if (!gLCDSupport && isLCD(*rec)) { 648 // If the runtime Freetype library doesn't support LCD mode, we disable 649 // it here. 650 rec->fMaskFormat = SkMask::kA8_Format; 651 } 652 653 SkPaint::Hinting h = rec->getHinting(); 654 if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { 655 // collapse full->normal hinting if we're not doing LCD 656 h = SkPaint::kNormal_Hinting; 657 } 658 if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag) || isLCD(*rec)) { 659 if (SkPaint::kNo_Hinting != h) { 660 h = SkPaint::kSlight_Hinting; 661 } 662 } 663 664 #ifndef SK_IGNORE_ROTATED_FREETYPE_FIX 665 // rotated text looks bad with hinting, so we disable it as needed 666 if (!isAxisAligned(*rec)) { 667 h = SkPaint::kNo_Hinting; 668 } 669 #endif 670 rec->setHinting(h); 671 672 #ifndef SK_USE_COLOR_LUMINANCE 673 // for compatibility at the moment, discretize luminance to 3 settings 674 // black, white, gray. This helps with fontcache utilization, since we 675 // won't create multiple entries that in the end map to the same results. 676 { 677 unsigned lum = rec->getLuminanceByte(); 678 if (gGammaTables[0] || gGammaTables[1]) { 679 if (lum <= BLACK_LUMINANCE_LIMIT) { 680 lum = 0; 681 } else if (lum >= WHITE_LUMINANCE_LIMIT) { 682 lum = SkScalerContext::kLuminance_Max; 683 } else { 684 lum = SkScalerContext::kLuminance_Max >> 1; 685 } 686 } else { 687 lum = 0; // no gamma correct, so use 0 since SkPaint uses that 688 // when measuring text w/o regard for luminance 689 } 690 rec->setLuminanceBits(lum); 691 } 692 #endif 693 } 694 695 #ifdef SK_BUILD_FOR_ANDROID 696 uint32_t SkFontHost::GetUnitsPerEm(SkFontID fontID) { 697 SkAutoMutexAcquire ac(gFTMutex); 698 SkFaceRec *rec = ref_ft_face(fontID); 699 uint16_t unitsPerEm = 0; 700 701 if (rec != NULL && rec->fFace != NULL) { 702 unitsPerEm = rec->fFace->units_per_EM; 703 unref_ft_face(rec->fFace); 704 } 705 706 return (uint32_t)unitsPerEm; 707 } 708 #endif 709 710 SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc) 711 : SkScalerContext(desc) { 712 SkAutoMutexAcquire ac(gFTMutex); 713 714 if (gFTCount == 0) { 715 if (!InitFreetype()) { 716 sk_throw(); 717 } 718 SkFontHost::GetGammaTables(gGammaTables); 719 } 720 ++gFTCount; 721 722 // load the font file 723 fFTSize = NULL; 724 fFace = NULL; 725 fFaceRec = ref_ft_face(fRec.fFontID); 726 if (NULL == fFaceRec) { 727 return; 728 } 729 fFace = fFaceRec->fFace; 730 731 // compute our factors from the record 732 733 SkMatrix m; 734 735 fRec.getSingleMatrix(&m); 736 737 #ifdef DUMP_STRIKE_CREATION 738 SkString keyString; 739 SkFontHost::GetDescriptorKeyString(desc, &keyString); 740 printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize), 741 SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX), 742 SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]), 743 SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]), 744 fRec.getHinting(), fRec.fMaskFormat, keyString.c_str()); 745 #endif 746 747 // now compute our scale factors 748 SkScalar sx = m.getScaleX(); 749 SkScalar sy = m.getScaleY(); 750 751 if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) { 752 // sort of give up on hinting 753 sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX())); 754 sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy)); 755 sx = sy = SkScalarAve(sx, sy); 756 757 SkScalar inv = SkScalarInvert(sx); 758 759 // flip the skew elements to go from our Y-down system to FreeType's 760 fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv)); 761 fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv)); 762 fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv)); 763 fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv)); 764 } else { 765 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; 766 fMatrix22.xy = fMatrix22.yx = 0; 767 } 768 769 fScaleX = SkScalarToFixed(sx); 770 fScaleY = SkScalarToFixed(sy); 771 772 // compute the flags we send to Load_Glyph 773 { 774 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 775 bool linearMetrics = false; 776 777 if (SkMask::kBW_Format == fRec.fMaskFormat) { 778 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 779 loadFlags = FT_LOAD_TARGET_MONO; 780 if (fRec.getHinting() == SkPaint::kNo_Hinting) { 781 loadFlags = FT_LOAD_NO_HINTING; 782 linearMetrics = true; 783 } 784 } else { 785 switch (fRec.getHinting()) { 786 case SkPaint::kNo_Hinting: 787 loadFlags = FT_LOAD_NO_HINTING; 788 linearMetrics = true; 789 break; 790 case SkPaint::kSlight_Hinting: 791 loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 792 linearMetrics = true; 793 break; 794 case SkPaint::kNormal_Hinting: 795 if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) 796 loadFlags = FT_LOAD_FORCE_AUTOHINT; 797 else 798 loadFlags = FT_LOAD_NO_AUTOHINT; 799 break; 800 case SkPaint::kFull_Hinting: 801 if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) { 802 loadFlags = FT_LOAD_FORCE_AUTOHINT; 803 break; 804 } 805 loadFlags = FT_LOAD_TARGET_NORMAL; 806 if (isLCD(fRec)) { 807 if (fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag) { 808 loadFlags = FT_LOAD_TARGET_LCD_V; 809 } else { 810 loadFlags = FT_LOAD_TARGET_LCD; 811 } 812 } 813 break; 814 default: 815 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 816 break; 817 } 818 } 819 820 if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 821 loadFlags |= FT_LOAD_NO_BITMAP; 822 } 823 824 // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 825 // advances, as fontconfig and cairo do. 826 // See http://code.google.com/p/skia/issues/detail?id=222. 827 loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 828 829 fLoadGlyphFlags = loadFlags; 830 fDoLinearMetrics = linearMetrics; 831 } 832 833 // now create the FT_Size 834 835 { 836 FT_Error err; 837 838 err = FT_New_Size(fFace, &fFTSize); 839 if (err != 0) { 840 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n", 841 fFaceRec->fFontID, fScaleX, fScaleY, err)); 842 fFace = NULL; 843 return; 844 } 845 846 err = FT_Activate_Size(fFTSize); 847 if (err != 0) { 848 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 849 fFaceRec->fFontID, fScaleX, fScaleY, err)); 850 fFTSize = NULL; 851 } 852 853 err = FT_Set_Char_Size( fFace, 854 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY), 855 72, 72); 856 if (err != 0) { 857 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 858 fFaceRec->fFontID, fScaleX, fScaleY, err)); 859 fFace = NULL; 860 return; 861 } 862 863 FT_Set_Transform( fFace, &fMatrix22, NULL); 864 } 865 } 866 867 SkScalerContext_FreeType::~SkScalerContext_FreeType() { 868 if (fFTSize != NULL) { 869 FT_Done_Size(fFTSize); 870 } 871 872 SkAutoMutexAcquire ac(gFTMutex); 873 874 if (fFace != NULL) { 875 unref_ft_face(fFace); 876 } 877 if (--gFTCount == 0) { 878 // SkDEBUGF(("FT_Done_FreeType\n")); 879 FT_Done_FreeType(gFTLibrary); 880 SkDEBUGCODE(gFTLibrary = NULL;) 881 } 882 } 883 884 /* We call this before each use of the fFace, since we may be sharing 885 this face with other context (at different sizes). 886 */ 887 FT_Error SkScalerContext_FreeType::setupSize() { 888 FT_Error err = FT_Activate_Size(fFTSize); 889 890 if (err != 0) { 891 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 892 fFaceRec->fFontID, fScaleX, fScaleY, err)); 893 fFTSize = NULL; 894 } else { 895 // seems we need to reset this every time (not sure why, but without it 896 // I get random italics from some other fFTSize) 897 FT_Set_Transform( fFace, &fMatrix22, NULL); 898 } 899 return err; 900 } 901 902 void SkScalerContext_FreeType::emboldenOutline(FT_Outline* outline) { 903 FT_Pos strength; 904 strength = FT_MulFix(fFace->units_per_EM, fFace->size->metrics.y_scale) 905 / SK_OUTLINE_EMBOLDEN_DIVISOR; 906 FT_Outline_Embolden(outline, strength); 907 } 908 909 unsigned SkScalerContext_FreeType::generateGlyphCount() { 910 return fFace->num_glyphs; 911 } 912 913 uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 914 return SkToU16(FT_Get_Char_Index( fFace, uni )); 915 } 916 917 SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 918 // iterate through each cmap entry, looking for matching glyph indices 919 FT_UInt glyphIndex; 920 SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 921 922 while (glyphIndex != 0) { 923 if (glyphIndex == glyph) { 924 return charCode; 925 } 926 charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 927 } 928 929 return 0; 930 } 931 932 static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { 933 switch (format) { 934 case SkMask::kBW_Format: 935 return FT_PIXEL_MODE_MONO; 936 case SkMask::kA8_Format: 937 default: 938 return FT_PIXEL_MODE_GRAY; 939 } 940 } 941 942 void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 943 #ifdef FT_ADVANCES_H 944 /* unhinted and light hinted text have linearly scaled advances 945 * which are very cheap to compute with some font formats... 946 */ 947 if (fDoLinearMetrics) { 948 SkAutoMutexAcquire ac(gFTMutex); 949 950 if (this->setupSize()) { 951 glyph->zeroMetrics(); 952 return; 953 } 954 955 FT_Error error; 956 FT_Fixed advance; 957 958 error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount), 959 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 960 &advance ); 961 if (0 == error) { 962 glyph->fRsbDelta = 0; 963 glyph->fLsbDelta = 0; 964 glyph->fAdvanceX = advance; // advance *2/3; //DEBUG 965 glyph->fAdvanceY = 0; 966 return; 967 } 968 } 969 #endif /* FT_ADVANCES_H */ 970 /* otherwise, we need to load/hint the glyph, which is slower */ 971 this->generateMetrics(glyph); 972 return; 973 } 974 975 void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 976 FT_BBox* bbox, 977 bool snapToPixelBoundary) { 978 979 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 980 981 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 982 int dx = FixedToDot6(glyph->getSubXFixed()); 983 int dy = FixedToDot6(glyph->getSubYFixed()); 984 // negate dy since freetype-y-goes-up and skia-y-goes-down 985 bbox->xMin += dx; 986 bbox->yMin -= dy; 987 bbox->xMax += dx; 988 bbox->yMax -= dy; 989 } 990 991 // outset the box to integral boundaries 992 if (snapToPixelBoundary) { 993 bbox->xMin &= ~63; 994 bbox->yMin &= ~63; 995 bbox->xMax = (bbox->xMax + 63) & ~63; 996 bbox->yMax = (bbox->yMax + 63) & ~63; 997 } 998 } 999 1000 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1001 if (isLCD(fRec)) { 1002 glyph->fWidth += gLCDExtra; 1003 glyph->fLeft -= gLCDExtra >> 1; 1004 } 1005 } 1006 1007 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1008 SkAutoMutexAcquire ac(gFTMutex); 1009 1010 glyph->fRsbDelta = 0; 1011 glyph->fLsbDelta = 0; 1012 1013 FT_Error err; 1014 1015 if (this->setupSize()) { 1016 goto ERROR; 1017 } 1018 1019 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags ); 1020 if (err != 0) { 1021 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1022 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err)); 1023 ERROR: 1024 glyph->zeroMetrics(); 1025 return; 1026 } 1027 1028 SkFixed vLeft, vTop; 1029 1030 switch ( fFace->glyph->format ) { 1031 case FT_GLYPH_FORMAT_OUTLINE: { 1032 FT_BBox bbox; 1033 1034 if (0 == fFace->glyph->outline.n_contours) { 1035 glyph->fWidth = 0; 1036 glyph->fHeight = 0; 1037 glyph->fTop = 0; 1038 glyph->fLeft = 0; 1039 break; 1040 } 1041 1042 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1043 emboldenOutline(&fFace->glyph->outline); 1044 } 1045 1046 getBBoxForCurrentGlyph(glyph, &bbox, true); 1047 1048 glyph->fWidth = SkToU16((bbox.xMax - bbox.xMin) >> 6); 1049 glyph->fHeight = SkToU16((bbox.yMax - bbox.yMin) >> 6); 1050 glyph->fTop = -SkToS16(bbox.yMax >> 6); 1051 glyph->fLeft = SkToS16(bbox.xMin >> 6); 1052 1053 if ((fRec.fFlags & SkScalerContext::kVertical_Flag)) { 1054 vLeft = Dot6ToFixed(bbox.xMin); 1055 vTop = Dot6ToFixed(bbox.yMax); 1056 } 1057 1058 updateGlyphIfLCD(glyph); 1059 1060 break; 1061 } 1062 1063 case FT_GLYPH_FORMAT_BITMAP: 1064 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1065 FT_GlyphSlot_Own_Bitmap(fFace->glyph); 1066 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0); 1067 } 1068 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 1069 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 1070 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 1071 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 1072 break; 1073 1074 default: 1075 SkDEBUGFAIL("unknown glyph format"); 1076 goto ERROR; 1077 } 1078 1079 if ((fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) == 0) { 1080 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); 1081 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); 1082 if (fRec.fFlags & kDevKernText_Flag) { 1083 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1084 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1085 } 1086 } else { 1087 glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance); 1088 glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance); 1089 } 1090 1091 if ((fRec.fFlags & SkScalerContext::kVertical_Flag) 1092 && fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { 1093 1094 //TODO: do we need to specially handle SubpixelPositioning and Kerning? 1095 1096 FT_Matrix identityMatrix; 1097 identityMatrix.xx = identityMatrix.yy = SK_Fixed1; 1098 identityMatrix.xy = identityMatrix.yx = 0; 1099 1100 // if the matrix is not the identity matrix then we need to re-load the 1101 // glyph with the identity matrix to get the necessary bounding box 1102 if (memcmp(&fMatrix22, &identityMatrix, sizeof(FT_Matrix)) != 0) { 1103 1104 FT_Set_Transform(fFace, &identityMatrix, NULL); 1105 1106 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags ); 1107 if (err != 0) { 1108 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1109 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err)); 1110 goto ERROR; 1111 } 1112 1113 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1114 emboldenOutline(&fFace->glyph->outline); 1115 } 1116 } 1117 1118 // bounding box of the unskewed and unscaled glyph 1119 FT_BBox bbox; 1120 getBBoxForCurrentGlyph(glyph, &bbox); 1121 1122 // compute the vertical gap above and below the glyph if the glyph were 1123 // centered within the linearVertAdvance 1124 SkFixed vGap = (fFace->glyph->linearVertAdvance - Dot6ToFixed(bbox.yMax - bbox.yMin)) / 2; 1125 1126 // the origin point of the glyph when rendered vertically 1127 FT_Vector vOrigin; 1128 vOrigin.x = fFace->glyph->linearHoriAdvance / 2; 1129 vOrigin.y = vGap + Dot6ToFixed(bbox.yMax); 1130 1131 // transform the vertical origin based on the matrix of the actual glyph 1132 FT_Vector_Transform(&vOrigin, &fMatrix22); 1133 1134 // compute a new offset vector for the glyph by subtracting the vertical 1135 // origin from the original horizontal offset vector 1136 glyph->fLeft = SkFixedRoundToInt(vLeft - vOrigin.x); 1137 glyph->fTop = -SkFixedRoundToInt(vTop - vOrigin.y); 1138 1139 updateGlyphIfLCD(glyph); 1140 1141 // use the vertical advance values computed by freetype 1142 glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance); 1143 glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance); 1144 } 1145 1146 1147 #ifdef ENABLE_GLYPH_SPEW 1148 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); 1149 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth)); 1150 #endif 1151 } 1152 1153 /////////////////////////////////////////////////////////////////////////////// 1154 1155 static int apply_contrast(int srca, int contrast) { 1156 return srca + (((255 - srca) * contrast * srca) / (255*255)); 1157 } 1158 1159 static void build_power_table(uint8_t table[], float ee) { 1160 for (int i = 0; i < 256; i++) { 1161 float x = i / 255.f; 1162 x = powf(x, ee); 1163 int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255)); 1164 table[i] = SkToU8(xx); 1165 } 1166 } 1167 1168 static void build_gamma_table(uint8_t table[256], int src, int dst) { 1169 static bool gInit; 1170 static uint8_t powTable[256], invPowTable[256]; 1171 if (!gInit) { 1172 const float g = SK_GAMMA_EXPONENT; 1173 build_power_table(powTable, g); 1174 build_power_table(invPowTable, 1/g); 1175 gInit = true; 1176 } 1177 1178 const int linSrc = powTable[src]; 1179 const int linDst = powTable[dst]; 1180 // have our contrast value taper off to 0 as the src luminance becomes white 1181 const int contrast = SK_GAMMA_CONTRAST * (255 - linSrc) / 255; 1182 1183 for (int i = 0; i < 256; ++i) { 1184 int srca = apply_contrast(i, contrast); 1185 SkASSERT((unsigned)srca <= 255); 1186 int dsta = 255 - srca; 1187 1188 //Calculate the output we want. 1189 int linOut = (linSrc * srca + dsta * linDst) / 255; 1190 SkASSERT((unsigned)linOut <= 255); 1191 int out = invPowTable[linOut]; 1192 1193 //Undo what the blit blend will do. 1194 int result = ((255 * out) - (255 * dst)) / (src - dst); 1195 SkASSERT((unsigned)result <= 255); 1196 1197 table[i] = result; 1198 } 1199 } 1200 1201 static const uint8_t* getGammaTable(U8CPU luminance) { 1202 static uint8_t gGammaTables[4][256]; 1203 static bool gInited; 1204 if (!gInited) { 1205 build_gamma_table(gGammaTables[0], 0x00, 0xFF); 1206 build_gamma_table(gGammaTables[1], 0x66, 0x99); 1207 build_gamma_table(gGammaTables[2], 0x99, 0x66); 1208 build_gamma_table(gGammaTables[3], 0xFF, 0x00); 1209 1210 gInited = true; 1211 } 1212 SkASSERT(0 == (luminance >> 8)); 1213 return gGammaTables[luminance >> 6]; 1214 } 1215 1216 #ifndef SK_USE_COLOR_LUMINANCE 1217 static const uint8_t* getIdentityTable() { 1218 static bool gOnce; 1219 static uint8_t gIdentityTable[256]; 1220 if (!gOnce) { 1221 for (int i = 0; i < 256; ++i) { 1222 gIdentityTable[i] = i; 1223 } 1224 gOnce = true; 1225 } 1226 return gIdentityTable; 1227 } 1228 #endif 1229 1230 static uint16_t packTriple(unsigned r, unsigned g, unsigned b) { 1231 return SkPackRGB16(r >> 3, g >> 2, b >> 3); 1232 } 1233 1234 static uint16_t grayToRGB16(U8CPU gray) { 1235 SkASSERT(gray <= 255); 1236 return SkPackRGB16(gray >> 3, gray >> 2, gray >> 3); 1237 } 1238 1239 static int bittst(const uint8_t data[], int bitOffset) { 1240 SkASSERT(bitOffset >= 0); 1241 int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); 1242 return lowBit & 1; 1243 } 1244 1245 static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap, 1246 int lcdIsBGR, const uint8_t* tableR, 1247 const uint8_t* tableG, const uint8_t* tableB) { 1248 SkASSERT(glyph.fHeight == bitmap.rows); 1249 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); 1250 const size_t dstRB = glyph.rowBytes(); 1251 const int width = glyph.fWidth; 1252 const uint8_t* src = bitmap.buffer; 1253 1254 switch (bitmap.pixel_mode) { 1255 case FT_PIXEL_MODE_MONO: { 1256 for (int y = 0; y < glyph.fHeight; ++y) { 1257 for (int x = 0; x < width; ++x) { 1258 dst[x] = -bittst(src, x); 1259 } 1260 dst = (uint16_t*)((char*)dst + dstRB); 1261 src += bitmap.pitch; 1262 } 1263 } break; 1264 case FT_PIXEL_MODE_GRAY: { 1265 for (int y = 0; y < glyph.fHeight; ++y) { 1266 for (int x = 0; x < width; ++x) { 1267 dst[x] = grayToRGB16(src[x]); 1268 } 1269 dst = (uint16_t*)((char*)dst + dstRB); 1270 src += bitmap.pitch; 1271 } 1272 } break; 1273 default: { 1274 SkASSERT(glyph.fWidth * 3 == bitmap.width); 1275 for (int y = 0; y < glyph.fHeight; y++) { 1276 const uint8_t* triple = src; 1277 if (lcdIsBGR) { 1278 for (int x = 0; x < width; x++) { 1279 dst[x] = packTriple(tableR[triple[2]], 1280 tableG[triple[1]], 1281 tableB[triple[0]]); 1282 triple += 3; 1283 } 1284 } else { 1285 for (int x = 0; x < width; x++) { 1286 dst[x] = packTriple(tableR[triple[0]], 1287 tableG[triple[1]], 1288 tableB[triple[2]]); 1289 triple += 3; 1290 } 1291 } 1292 src += bitmap.pitch; 1293 dst = (uint16_t*)((char*)dst + dstRB); 1294 } 1295 } break; 1296 } 1297 } 1298 1299 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1300 SkAutoMutexAcquire ac(gFTMutex); 1301 1302 FT_Error err; 1303 1304 if (this->setupSize()) { 1305 goto ERROR; 1306 } 1307 1308 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags); 1309 if (err != 0) { 1310 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", 1311 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err)); 1312 ERROR: 1313 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 1314 return; 1315 } 1316 1317 #ifdef SK_USE_COLOR_LUMINANCE 1318 SkColor lumColor = fRec.getLuminanceColor(); 1319 const uint8_t* tableR = getGammaTable(SkColorGetR(lumColor)); 1320 const uint8_t* tableG = getGammaTable(SkColorGetG(lumColor)); 1321 const uint8_t* tableB = getGammaTable(SkColorGetB(lumColor)); 1322 #else 1323 unsigned lum = fRec.getLuminanceByte(); 1324 const uint8_t* tableR; 1325 const uint8_t* tableG; 1326 const uint8_t* tableB; 1327 1328 bool isWhite = lum >= WHITE_LUMINANCE_LIMIT; 1329 bool isBlack = lum <= BLACK_LUMINANCE_LIMIT; 1330 if ((gGammaTables[0] || gGammaTables[1]) && (isBlack || isWhite)) { 1331 tableR = tableG = tableB = gGammaTables[isBlack ? 0 : 1]; 1332 } else { 1333 tableR = tableG = tableB = getIdentityTable(); 1334 } 1335 #endif 1336 1337 switch ( fFace->glyph->format ) { 1338 case FT_GLYPH_FORMAT_OUTLINE: { 1339 FT_Outline* outline = &fFace->glyph->outline; 1340 FT_BBox bbox; 1341 FT_Bitmap target; 1342 1343 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1344 emboldenOutline(outline); 1345 } 1346 1347 int dx = 0, dy = 0; 1348 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1349 dx = glyph.getSubXFixed() >> 10; 1350 dy = glyph.getSubYFixed() >> 10; 1351 // negate dy since freetype-y-goes-up and skia-y-goes-down 1352 dy = -dy; 1353 } 1354 FT_Outline_Get_CBox(outline, &bbox); 1355 /* 1356 what we really want to do for subpixel is 1357 offset(dx, dy) 1358 compute_bounds 1359 offset(bbox & !63) 1360 but that is two calls to offset, so we do the following, which 1361 achieves the same thing with only one offset call. 1362 */ 1363 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), 1364 dy - ((bbox.yMin + dy) & ~63)); 1365 1366 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 1367 FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD); 1368 copyFT2LCD16(glyph, fFace->glyph->bitmap, 1369 fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag, 1370 tableR, tableG, tableB); 1371 } else { 1372 target.width = glyph.fWidth; 1373 target.rows = glyph.fHeight; 1374 target.pitch = glyph.rowBytes(); 1375 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); 1376 target.pixel_mode = compute_pixel_mode( 1377 (SkMask::Format)fRec.fMaskFormat); 1378 target.num_grays = 256; 1379 1380 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 1381 FT_Outline_Get_Bitmap(gFTLibrary, outline, &target); 1382 } 1383 } break; 1384 1385 case FT_GLYPH_FORMAT_BITMAP: { 1386 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1387 FT_GlyphSlot_Own_Bitmap(fFace->glyph); 1388 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0); 1389 } 1390 SkASSERT_CONTINUE(glyph.fWidth == fFace->glyph->bitmap.width); 1391 SkASSERT_CONTINUE(glyph.fHeight == fFace->glyph->bitmap.rows); 1392 SkASSERT_CONTINUE(glyph.fTop == -fFace->glyph->bitmap_top); 1393 SkASSERT_CONTINUE(glyph.fLeft == fFace->glyph->bitmap_left); 1394 1395 const uint8_t* src = (const uint8_t*)fFace->glyph->bitmap.buffer; 1396 uint8_t* dst = (uint8_t*)glyph.fImage; 1397 1398 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY || 1399 (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && 1400 glyph.fMaskFormat == SkMask::kBW_Format)) { 1401 unsigned srcRowBytes = fFace->glyph->bitmap.pitch; 1402 unsigned dstRowBytes = glyph.rowBytes(); 1403 unsigned minRowBytes = SkMin32(srcRowBytes, dstRowBytes); 1404 unsigned extraRowBytes = dstRowBytes - minRowBytes; 1405 1406 for (int y = fFace->glyph->bitmap.rows - 1; y >= 0; --y) { 1407 memcpy(dst, src, minRowBytes); 1408 memset(dst + minRowBytes, 0, extraRowBytes); 1409 src += srcRowBytes; 1410 dst += dstRowBytes; 1411 } 1412 } else if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && 1413 glyph.fMaskFormat == SkMask::kA8_Format) { 1414 for (int y = 0; y < fFace->glyph->bitmap.rows; ++y) { 1415 uint8_t byte = 0; 1416 int bits = 0; 1417 const uint8_t* src_row = src; 1418 uint8_t* dst_row = dst; 1419 1420 for (int x = 0; x < fFace->glyph->bitmap.width; ++x) { 1421 if (!bits) { 1422 byte = *src_row++; 1423 bits = 8; 1424 } 1425 1426 *dst_row++ = byte & 0x80 ? 0xff : 0; 1427 bits--; 1428 byte <<= 1; 1429 } 1430 1431 src += fFace->glyph->bitmap.pitch; 1432 dst += glyph.rowBytes(); 1433 } 1434 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 1435 copyFT2LCD16(glyph, fFace->glyph->bitmap, 1436 fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag, 1437 tableR, tableG, tableB); 1438 } else { 1439 SkDEBUGFAIL("unknown glyph bitmap transform needed"); 1440 } 1441 } break; 1442 1443 default: 1444 SkDEBUGFAIL("unknown glyph format"); 1445 goto ERROR; 1446 } 1447 1448 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, 1449 // it is optional 1450 #if defined(SK_GAMMA_APPLY_TO_A8) || !defined(SK_USE_COLOR_LUMINANCE) 1451 if (SkMask::kA8_Format == glyph.fMaskFormat) { 1452 SkASSERT(tableR == tableG && tableR == tableB); 1453 const uint8_t* table = tableR; 1454 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 1455 unsigned rowBytes = glyph.rowBytes(); 1456 1457 for (int y = glyph.fHeight - 1; y >= 0; --y) { 1458 for (int x = glyph.fWidth - 1; x >= 0; --x) { 1459 dst[x] = table[dst[x]]; 1460 } 1461 dst += rowBytes; 1462 } 1463 } 1464 #endif 1465 } 1466 1467 /////////////////////////////////////////////////////////////////////////////// 1468 1469 #define ft2sk(x) SkFixedToScalar((x) << 10) 1470 1471 #if FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2 1472 #define CONST_PARAM const 1473 #else // older freetype doesn't use const here 1474 #define CONST_PARAM 1475 #endif 1476 1477 static int move_proc(CONST_PARAM FT_Vector* pt, void* ctx) { 1478 SkPath* path = (SkPath*)ctx; 1479 path->close(); // to close the previous contour (if any) 1480 path->moveTo(ft2sk(pt->x), -ft2sk(pt->y)); 1481 return 0; 1482 } 1483 1484 static int line_proc(CONST_PARAM FT_Vector* pt, void* ctx) { 1485 SkPath* path = (SkPath*)ctx; 1486 path->lineTo(ft2sk(pt->x), -ft2sk(pt->y)); 1487 return 0; 1488 } 1489 1490 static int quad_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1, 1491 void* ctx) { 1492 SkPath* path = (SkPath*)ctx; 1493 path->quadTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), -ft2sk(pt1->y)); 1494 return 0; 1495 } 1496 1497 static int cubic_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1, 1498 CONST_PARAM FT_Vector* pt2, void* ctx) { 1499 SkPath* path = (SkPath*)ctx; 1500 path->cubicTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), 1501 -ft2sk(pt1->y), ft2sk(pt2->x), -ft2sk(pt2->y)); 1502 return 0; 1503 } 1504 1505 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, 1506 SkPath* path) { 1507 SkAutoMutexAcquire ac(gFTMutex); 1508 1509 SkASSERT(&glyph && path); 1510 1511 if (this->setupSize()) { 1512 path->reset(); 1513 return; 1514 } 1515 1516 uint32_t flags = fLoadGlyphFlags; 1517 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 1518 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 1519 1520 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags); 1521 1522 if (err != 0) { 1523 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1524 glyph.getGlyphID(fBaseGlyphCount), flags, err)); 1525 path->reset(); 1526 return; 1527 } 1528 1529 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1530 emboldenOutline(&fFace->glyph->outline); 1531 } 1532 1533 FT_Outline_Funcs funcs; 1534 1535 funcs.move_to = move_proc; 1536 funcs.line_to = line_proc; 1537 funcs.conic_to = quad_proc; 1538 funcs.cubic_to = cubic_proc; 1539 funcs.shift = 0; 1540 funcs.delta = 0; 1541 1542 err = FT_Outline_Decompose(&fFace->glyph->outline, &funcs, path); 1543 1544 if (err != 0) { 1545 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1546 glyph.getGlyphID(fBaseGlyphCount), flags, err)); 1547 path->reset(); 1548 return; 1549 } 1550 1551 path->close(); 1552 } 1553 1554 void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 1555 SkPaint::FontMetrics* my) { 1556 if (NULL == mx && NULL == my) { 1557 return; 1558 } 1559 1560 SkAutoMutexAcquire ac(gFTMutex); 1561 1562 if (this->setupSize()) { 1563 ERROR: 1564 if (mx) { 1565 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); 1566 } 1567 if (my) { 1568 sk_bzero(my, sizeof(SkPaint::FontMetrics)); 1569 } 1570 return; 1571 } 1572 1573 FT_Face face = fFace; 1574 int upem = face->units_per_EM; 1575 if (upem <= 0) { 1576 goto ERROR; 1577 } 1578 1579 SkPoint pts[6]; 1580 SkFixed ys[6]; 1581 SkFixed scaleY = fScaleY; 1582 SkFixed mxy = fMatrix22.xy; 1583 SkFixed myy = fMatrix22.yy; 1584 SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem; 1585 SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem; 1586 1587 int leading = face->height - (face->ascender + -face->descender); 1588 if (leading < 0) { 1589 leading = 0; 1590 } 1591 1592 // Try to get the OS/2 table from the font. This contains the specific 1593 // average font width metrics which Windows uses. 1594 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1595 1596 ys[0] = -face->bbox.yMax; 1597 ys[1] = -face->ascender; 1598 ys[2] = -face->descender; 1599 ys[3] = -face->bbox.yMin; 1600 ys[4] = leading; 1601 ys[5] = os2 ? os2->xAvgCharWidth : 0; 1602 1603 SkScalar x_height; 1604 if (os2 && os2->sxHeight) { 1605 x_height = SkFixedToScalar(SkMulDiv(fScaleX, os2->sxHeight, upem)); 1606 } else { 1607 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); 1608 if (x_glyph) { 1609 FT_BBox bbox; 1610 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); 1611 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { 1612 emboldenOutline(&fFace->glyph->outline); 1613 } 1614 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); 1615 x_height = SkFixedToScalar(SkFDot6ToFixed(bbox.yMax)); 1616 } else { 1617 x_height = 0; 1618 } 1619 } 1620 1621 // convert upem-y values into scalar points 1622 for (int i = 0; i < 6; i++) { 1623 SkFixed y = SkMulDiv(scaleY, ys[i], upem); 1624 SkFixed x = SkFixedMul(mxy, y); 1625 y = SkFixedMul(myy, y); 1626 pts[i].set(SkFixedToScalar(x), SkFixedToScalar(y)); 1627 } 1628 1629 if (mx) { 1630 mx->fTop = pts[0].fX; 1631 mx->fAscent = pts[1].fX; 1632 mx->fDescent = pts[2].fX; 1633 mx->fBottom = pts[3].fX; 1634 mx->fLeading = pts[4].fX; 1635 mx->fAvgCharWidth = pts[5].fX; 1636 mx->fXMin = xmin; 1637 mx->fXMax = xmax; 1638 mx->fXHeight = x_height; 1639 } 1640 if (my) { 1641 my->fTop = pts[0].fY; 1642 my->fAscent = pts[1].fY; 1643 my->fDescent = pts[2].fY; 1644 my->fBottom = pts[3].fY; 1645 my->fLeading = pts[4].fY; 1646 my->fAvgCharWidth = pts[5].fY; 1647 my->fXMin = xmin; 1648 my->fXMax = xmax; 1649 my->fXHeight = x_height; 1650 } 1651 } 1652 1653 //////////////////////////////////////////////////////////////////////// 1654 //////////////////////////////////////////////////////////////////////// 1655 1656 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { 1657 SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, (desc)); 1658 if (!c->success()) { 1659 SkDELETE(c); 1660 c = NULL; 1661 } 1662 return c; 1663 } 1664 1665 /////////////////////////////////////////////////////////////////////////////// 1666 1667 /* Export this so that other parts of our FonttHost port can make use of our 1668 ability to extract the name+style from a stream, using FreeType's api. 1669 */ 1670 bool find_name_and_attributes(SkStream* stream, SkString* name, 1671 SkTypeface::Style* style, bool* isFixedWidth) { 1672 FT_Library library; 1673 if (FT_Init_FreeType(&library)) { 1674 return false; 1675 } 1676 1677 FT_Open_Args args; 1678 memset(&args, 0, sizeof(args)); 1679 1680 const void* memoryBase = stream->getMemoryBase(); 1681 FT_StreamRec streamRec; 1682 1683 if (NULL != memoryBase) { 1684 args.flags = FT_OPEN_MEMORY; 1685 args.memory_base = (const FT_Byte*)memoryBase; 1686 args.memory_size = stream->getLength(); 1687 } else { 1688 memset(&streamRec, 0, sizeof(streamRec)); 1689 streamRec.size = stream->read(NULL, 0); 1690 streamRec.descriptor.pointer = stream; 1691 streamRec.read = sk_stream_read; 1692 streamRec.close = sk_stream_close; 1693 1694 args.flags = FT_OPEN_STREAM; 1695 args.stream = &streamRec; 1696 } 1697 1698 FT_Face face; 1699 if (FT_Open_Face(library, &args, 0, &face)) { 1700 FT_Done_FreeType(library); 1701 return false; 1702 } 1703 1704 int tempStyle = SkTypeface::kNormal; 1705 if (face->style_flags & FT_STYLE_FLAG_BOLD) { 1706 tempStyle |= SkTypeface::kBold; 1707 } 1708 if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 1709 tempStyle |= SkTypeface::kItalic; 1710 } 1711 1712 if (name) { 1713 name->set(face->family_name); 1714 } 1715 if (style) { 1716 *style = (SkTypeface::Style) tempStyle; 1717 } 1718 if (isFixedWidth) { 1719 *isFixedWidth = FT_IS_FIXED_WIDTH(face); 1720 } 1721 1722 FT_Done_Face(face); 1723 FT_Done_FreeType(library); 1724 return true; 1725 } 1726