SkFontHost_FreeType.cpp revision 618ef5ee3bc1fae284c766597fd518faabf7373d
1/* libs/graphics/ports/SkFontHost_FreeType.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkBitmap.h" 19#include "SkCanvas.h" 20#include "SkColorPriv.h" 21#include "SkDescriptor.h" 22#include "SkFDot6.h" 23#include "SkFontHost.h" 24#include "SkMask.h" 25#include "SkPDFTypefaceInfo.h" 26#include "SkScalerContext.h" 27#include "SkStream.h" 28#include "SkString.h" 29#include "SkTemplates.h" 30#include "SkThread.h" 31 32#include <ft2build.h> 33#include FT_FREETYPE_H 34#include FT_OUTLINE_H 35#include FT_SIZES_H 36#include FT_TRUETYPE_TABLES_H 37#include FT_TYPE1_TABLES_H 38#include FT_BITMAP_H 39// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 40#include FT_SYNTHESIS_H 41#include FT_XFREE86_H 42 43#if defined(SK_SUPPORT_LCDTEXT) 44#include FT_LCD_FILTER_H 45#endif 46 47#ifdef FT_ADVANCES_H 48#include FT_ADVANCES_H 49#endif 50 51#if 0 52// Also include the files by name for build tools which require this. 53#include <freetype/freetype.h> 54#include <freetype/ftoutln.h> 55#include <freetype/ftsizes.h> 56#include <freetype/tttables.h> 57#include <freetype/ftadvanc.h> 58#include <freetype/ftlcdfil.h> 59#include <freetype/ftbitmap.h> 60#include <freetype/ftsynth.h> 61#endif 62 63//#define ENABLE_GLYPH_SPEW // for tracing calls 64//#define DUMP_STRIKE_CREATION 65 66#ifdef SK_DEBUG 67 #define SkASSERT_CONTINUE(pred) \ 68 do { \ 69 if (!(pred)) \ 70 SkDebugf("file %s:%d: assert failed '" #pred "'\n", __FILE__, __LINE__); \ 71 } while (false) 72#else 73 #define SkASSERT_CONTINUE(pred) 74#endif 75 76////////////////////////////////////////////////////////////////////////// 77 78struct SkFaceRec; 79 80static SkMutex gFTMutex; 81static int gFTCount; 82static FT_Library gFTLibrary; 83static SkFaceRec* gFaceRecHead; 84static bool gLCDSupportValid; // true iff |gLCDSupport| has been set. 85static bool gLCDSupport; // true iff LCD is supported by the runtime. 86 87///////////////////////////////////////////////////////////////////////// 88 89// See http://freetype.sourceforge.net/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden 90// This value was chosen by eyeballing the result in Firefox and trying to match it. 91static const FT_Pos kBitmapEmboldenStrength = 1 << 6; 92 93static bool 94InitFreetype() { 95 FT_Error err = FT_Init_FreeType(&gFTLibrary); 96 if (err) 97 return false; 98 99#if defined(SK_SUPPORT_LCDTEXT) 100 // Setup LCD filtering. This reduces colour fringes for LCD rendered 101 // glyphs. 102 err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); 103 gLCDSupport = err == 0; 104#endif 105 gLCDSupportValid = true; 106 107 return true; 108} 109 110class SkScalerContext_FreeType : public SkScalerContext { 111public: 112 SkScalerContext_FreeType(const SkDescriptor* desc); 113 virtual ~SkScalerContext_FreeType(); 114 115 bool success() const { 116 return fFaceRec != NULL && 117 fFTSize != NULL && 118 fFace != NULL; 119 } 120 121protected: 122 virtual unsigned generateGlyphCount() const; 123 virtual uint16_t generateCharToGlyph(SkUnichar uni); 124 virtual void generateAdvance(SkGlyph* glyph); 125 virtual void generateMetrics(SkGlyph* glyph); 126 virtual void generateImage(const SkGlyph& glyph); 127 virtual void generatePath(const SkGlyph& glyph, SkPath* path); 128 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 129 SkPaint::FontMetrics* my); 130 virtual SkUnichar generateGlyphToChar(uint16_t glyph); 131 132private: 133 SkFaceRec* fFaceRec; 134 FT_Face fFace; // reference to shared face in gFaceRecHead 135 FT_Size fFTSize; // our own copy 136 SkFixed fScaleX, fScaleY; 137 FT_Matrix fMatrix22; 138 uint32_t fLoadGlyphFlags; 139 140 FT_Error setupSize(); 141 void emboldenOutline(FT_Outline* outline); 142}; 143 144/////////////////////////////////////////////////////////////////////////// 145/////////////////////////////////////////////////////////////////////////// 146 147#include "SkStream.h" 148 149struct SkFaceRec { 150 SkFaceRec* fNext; 151 FT_Face fFace; 152 FT_StreamRec fFTStream; 153 SkStream* fSkStream; 154 uint32_t fRefCnt; 155 uint32_t fFontID; 156 157 // assumes ownership of the stream, will call unref() when its done 158 SkFaceRec(SkStream* strm, uint32_t fontID); 159 ~SkFaceRec() { 160 fSkStream->unref(); 161 } 162}; 163 164extern "C" { 165 static unsigned long sk_stream_read(FT_Stream stream, 166 unsigned long offset, 167 unsigned char* buffer, 168 unsigned long count ) { 169 SkStream* str = (SkStream*)stream->descriptor.pointer; 170 171 if (count) { 172 if (!str->rewind()) { 173 return 0; 174 } else { 175 unsigned long ret; 176 if (offset) { 177 ret = str->read(NULL, offset); 178 if (ret != offset) { 179 return 0; 180 } 181 } 182 ret = str->read(buffer, count); 183 if (ret != count) { 184 return 0; 185 } 186 count = ret; 187 } 188 } 189 return count; 190 } 191 192 static void sk_stream_close( FT_Stream stream) {} 193} 194 195SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) 196 : fSkStream(strm), fFontID(fontID) { 197// SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); 198 199 sk_bzero(&fFTStream, sizeof(fFTStream)); 200 fFTStream.size = fSkStream->getLength(); 201 fFTStream.descriptor.pointer = fSkStream; 202 fFTStream.read = sk_stream_read; 203 fFTStream.close = sk_stream_close; 204} 205 206// Will return 0 on failure 207static SkFaceRec* ref_ft_face(uint32_t fontID) { 208 SkFaceRec* rec = gFaceRecHead; 209 while (rec) { 210 if (rec->fFontID == fontID) { 211 SkASSERT(rec->fFace); 212 rec->fRefCnt += 1; 213 return rec; 214 } 215 rec = rec->fNext; 216 } 217 218 SkStream* strm = SkFontHost::OpenStream(fontID); 219 if (NULL == strm) { 220 SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID)); 221 return 0; 222 } 223 224 // this passes ownership of strm to the rec 225 rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); 226 227 FT_Open_Args args; 228 memset(&args, 0, sizeof(args)); 229 const void* memoryBase = strm->getMemoryBase(); 230 231 if (NULL != memoryBase) { 232//printf("mmap(%s)\n", keyString.c_str()); 233 args.flags = FT_OPEN_MEMORY; 234 args.memory_base = (const FT_Byte*)memoryBase; 235 args.memory_size = strm->getLength(); 236 } else { 237//printf("fopen(%s)\n", keyString.c_str()); 238 args.flags = FT_OPEN_STREAM; 239 args.stream = &rec->fFTStream; 240 } 241 242 int face_index; 243 int length = SkFontHost::GetFileName(fontID, NULL, 0, &face_index); 244 FT_Error err = FT_Open_Face(gFTLibrary, &args, length ? face_index : 0, 245 &rec->fFace); 246 247 if (err) { // bad filename, try the default font 248 fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); 249 SkDELETE(rec); 250 return 0; 251 } else { 252 SkASSERT(rec->fFace); 253 //fprintf(stderr, "Opened font '%s'\n", filename.c_str()); 254 rec->fNext = gFaceRecHead; 255 gFaceRecHead = rec; 256 rec->fRefCnt = 1; 257 return rec; 258 } 259} 260 261static void unref_ft_face(FT_Face face) { 262 SkFaceRec* rec = gFaceRecHead; 263 SkFaceRec* prev = NULL; 264 while (rec) { 265 SkFaceRec* next = rec->fNext; 266 if (rec->fFace == face) { 267 if (--rec->fRefCnt == 0) { 268 if (prev) { 269 prev->fNext = next; 270 } else { 271 gFaceRecHead = next; 272 } 273 FT_Done_Face(face); 274 SkDELETE(rec); 275 } 276 return; 277 } 278 prev = rec; 279 rec = next; 280 } 281 SkASSERT("shouldn't get here, face not in list"); 282} 283 284/////////////////////////////////////////////////////////////////////////// 285 286#ifdef SK_SUPPORT_PDF 287static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { 288 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); 289 if (!glyph_id) 290 return false; 291 FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE); 292 FT_Outline_Get_CBox(&face->glyph->outline, bbox); 293 return true; 294} 295 296int getWidthAdvance(FT_Face face, int gId, int scaleDivisor) { 297 FT_Fixed unscaledAdvance = 0; 298 SkAssertResult(FT_Get_Advance(face, gId, FT_LOAD_NO_SCALE, 299 &unscaledAdvance) == 0); 300 return unscaledAdvance * 1000 / scaleDivisor; 301} 302 303template <typename Data> 304void resetRange(SkPDFTypefaceInfo::AdvanceMetric<Data>* range, int startId) { 305 range->fStartId = startId; 306 range->fAdvance.setCount(0); 307} 308 309template <typename Data> 310SkPDFTypefaceInfo::AdvanceMetric<Data>* appendRange( 311 SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> >* nextSlot, 312 int startId) { 313 nextSlot->reset(new SkPDFTypefaceInfo::AdvanceMetric<Data>); 314 resetRange(nextSlot->get(), startId); 315 return nextSlot->get(); 316} 317 318template <typename Data> 319void finishRange( 320 SkPDFTypefaceInfo::AdvanceMetric<Data>* range, 321 int endId, 322 typename SkPDFTypefaceInfo::AdvanceMetric<Data>::MetricType type) { 323 range->fEndId = endId; 324 range->fType = type; 325 int newLength; 326 if (type == SkPDFTypefaceInfo::AdvanceMetric<Data>::kRange) 327 newLength = endId - range->fStartId + 1; 328 else 329 newLength = 1; 330 SkASSERT(range->fAdvance.count() >= newLength); 331 range->fAdvance.setCount(newLength); 332} 333 334template <typename Data> 335SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData( 336 FT_Face face, 337 int scaleDivisor, 338 Data (*getAdvance)(FT_Face face, int gId, int scaleDivisor)) { 339 // Assuming that an ASCII representation of a width or a glyph id is, 340 // on average, 3 characters long gives the following cut offs for 341 // using different range types: 342 // When currently in a range 343 // - Removing 4 0's is a win 344 // - Removing 5 repeats is a win 345 // When not currently in a range 346 // - Removing 1 0 is a win 347 // - Removing 3 repeats is a win 348 349 SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> > result; 350 SkPDFTypefaceInfo::AdvanceMetric<Data>* curRange; 351 curRange = appendRange(&result, 0); 352 int lastAdvance = INT_MIN; 353 int repeats = 0; 354 for (FT_UInt gId = 0; gId < face->num_glyphs; gId++) { 355 int advance = getAdvance(face, gId, scaleDivisor); 356 if (advance == lastAdvance) { 357 repeats++; 358 } else if (curRange->fAdvance.count() == repeats + 1) { 359 if (lastAdvance == 0 && repeats >= 0) { 360 resetRange(curRange, gId); 361 } else if (repeats >= 2) { 362 finishRange(curRange, gId - 1, 363 SkPDFTypefaceInfo::WidthRange::kRun); 364 curRange = appendRange(&curRange->fNext, gId); 365 } 366 repeats = 0; 367 } else { 368 if (lastAdvance == 0 && repeats >= 3) { 369 finishRange(curRange, gId - repeats - 2, 370 SkPDFTypefaceInfo::WidthRange::kRange); 371 curRange = appendRange(&curRange->fNext, gId); 372 } else if (repeats >= 4) { 373 finishRange(curRange, gId - repeats - 2, 374 SkPDFTypefaceInfo::WidthRange::kRange); 375 curRange = appendRange(&curRange->fNext, gId - repeats - 1); 376 curRange->fAdvance.append(1, &lastAdvance); 377 finishRange(curRange, gId - 1, 378 SkPDFTypefaceInfo::WidthRange::kRun); 379 curRange = appendRange(&curRange->fNext, gId); 380 } 381 repeats = 0; 382 } 383 curRange->fAdvance.append(1, &advance); 384 lastAdvance = advance; 385 } 386 finishRange(curRange, face->num_glyphs - 1, 387 SkPDFTypefaceInfo::WidthRange::kRange); 388 return result.release(); 389} 390 391// static 392SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) { 393 SkAutoMutexAcquire ac(gFTMutex); 394 FT_Library libInit = NULL; 395 if (gFTCount == 0) { 396 if (!InitFreetype()) 397 sk_throw(); 398 libInit = gFTLibrary; 399 } 400 SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); 401 SkFaceRec* rec = ref_ft_face(fontID); 402 if (NULL == rec) 403 return NULL; 404 FT_Face face = rec->fFace; 405 406 SkPDFTypefaceInfo* info = new SkPDFTypefaceInfo; 407 info->fMultiMaster = false; 408 bool cid = false; 409 int scaleDivisor = 1000; 410 const char* fontType = FT_Get_X11_Font_Format(face); 411 if (FT_Get_FSType_Flags(face) & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 412 FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) { 413 info->fType = SkPDFTypefaceInfo::kNotEmbeddable_Font; 414 } else if (FT_HAS_MULTIPLE_MASTERS(face)) { 415 // PDF requires that embedded MM fonts be reduced to a simple font. 416 info->fType = SkPDFTypefaceInfo::kOther_Font; 417 } else if (strcmp(fontType, "Type 1") == 0) { 418 info->fType = SkPDFTypefaceInfo::kType1_Font; 419 } else if (strcmp(fontType, "CID Type 1") == 0) { 420 info->fType = SkPDFTypefaceInfo::kType1CID_Font; 421 cid = true; 422 } else if (strcmp(fontType, "CFF") == 0) { 423 info->fType = SkPDFTypefaceInfo::kCFF_Font; 424 } else if (strcmp(fontType, "TrueType") == 0) { 425 info->fType = SkPDFTypefaceInfo::kTrueType_Font; 426 cid = true; 427 TT_Header* ttHeader; 428 if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, 429 ft_sfnt_head)) != NULL) { 430 scaleDivisor = ttHeader->Units_Per_EM; 431 } 432 } 433 info->fFontName.set(FT_Get_Postscript_Name(face)); 434 SkASSERT(FT_IS_CID_KEYED(face) == 435 (info->fType == SkPDFTypefaceInfo::kType1CID_Font)); 436 437 if (info->fType == SkPDFTypefaceInfo::kOther_Font || 438 info->fType == SkPDFTypefaceInfo::kNotEmbeddable_Font || 439 !FT_IS_SCALABLE(face)) { 440 unref_ft_face(face); 441 return info; 442 } 443 444 info->fLastGlyphID = face->num_glyphs - 1; 445 446 SkASSERT(!FT_HAS_VERTICAL(face)); 447 448 if (FT_IS_FIXED_WIDTH(face)) { 449 appendRange(&info->fGlyphWidths, 0); 450 int advance = face->max_advance_width * 1000 / scaleDivisor; 451 info->fGlyphWidths->fAdvance.append(1, &advance); 452 finishRange(info->fGlyphWidths.get(), 0, 453 SkPDFTypefaceInfo::WidthRange::kDefault); 454 } else if(!cid) { 455 appendRange(&info->fGlyphWidths, 0); 456 // So as to not blow out the stack, get advances in batches. 457 for (int gIDStart = 0; gIDStart < face->num_glyphs; gIDStart += 128) { 458 FT_Fixed advances[128]; 459 int advanceCount = 128; 460 if (gIDStart + advanceCount > face->num_glyphs) 461 advanceCount = face->num_glyphs - gIDStart + 1; 462 FT_Get_Advances(face, gIDStart, advanceCount, FT_LOAD_NO_SCALE, 463 advances); 464 for (int i = 0; i < advanceCount; i++) { 465 int advance = advances[gIDStart + i]; 466 info->fGlyphWidths->fAdvance.append(1, &advance); 467 } 468 } 469 finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1, 470 SkPDFTypefaceInfo::WidthRange::kRange); 471 } else { 472 // For CID keyed fonts, an identity pdf-cmap is used, so we iterate and 473 // report on glyph ids, not character ids (tt-cmap indices). 474 info->fGlyphWidths.reset(getAdvanceData(face, scaleDivisor, 475 &getWidthAdvance)); 476 } 477 478 if (info->fType == SkPDFTypefaceInfo::kType1_Font) { 479 // Postscript fonts may contain more than 255 glyphs, so we end up 480 // using multiple font descriptions with a glyph ordering. Record 481 // the name of each glyph. 482 info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs)); 483 for (FT_UInt gID = 0; gID < face->num_glyphs; gID++) { 484 char glyphName[128]; // Postscript limit for names is 127 bytes. 485 FT_Get_Glyph_Name(face, gID, glyphName, 128); 486 info->fGlyphNames->get()[gID].set(glyphName); 487 } 488 } 489 490 info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin * 1000 / scaleDivisor, 491 face->bbox.yMax * 1000 / scaleDivisor, 492 face->bbox.xMax * 1000 / scaleDivisor, 493 face->bbox.yMin * 1000 / scaleDivisor); 494 info->fStyle = 0; 495 if (FT_IS_FIXED_WIDTH(face)) 496 info->fStyle |= SkPDFTypefaceInfo::kFixedPitch_Style; 497 if (face->style_flags & FT_STYLE_FLAG_ITALIC) 498 info->fStyle |= SkPDFTypefaceInfo::kItalic_Style; 499 // We should set either Symbolic or Nonsymbolic; Nonsymbolic if the font's 500 // character set is a subset of 'Adobe standard Latin.' 501 info->fStyle |= SkPDFTypefaceInfo::kSymbolic_Style; 502 503 TT_PCLT* pclt_info; 504 TT_OS2* os2_table; 505 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { 506 info->fCapHeight = pclt_info->CapHeight; 507 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 508 if (serif_style >= 2 && serif_style <= 6) 509 info->fStyle |= SkPDFTypefaceInfo::kSerif_Style; 510 else if (serif_style >= 9 && serif_style <= 12) 511 info->fStyle |= SkPDFTypefaceInfo::kScript_Style; 512 } else if ((os2_table = 513 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 514 info->fCapHeight = os2_table->sCapHeight; 515 } else { 516 // Figure out a good guess for CapHeight: average the height of M and X. 517 FT_BBox m_bbox, x_bbox; 518 bool got_m, got_x; 519 got_m = GetLetterCBox(face, 'M', &m_bbox); 520 got_x = GetLetterCBox(face, 'X', &x_bbox); 521 if (got_m && got_x) { 522 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 523 x_bbox.yMin) / 2; 524 } else if (got_m && !got_x) { 525 info->fCapHeight = m_bbox.yMax - m_bbox.yMin; 526 } else if (!got_m && got_x) { 527 info->fCapHeight = x_bbox.yMax - x_bbox.yMin; 528 } 529 } 530 info->fCapHeight = info->fCapHeight * 1000 / scaleDivisor; 531 532 // Figure out a good guess for StemV - Min width of i, I, !, 1. 533 // This probably isn't very good with an italic font. 534 int min_width = INT_MAX; 535 char stem_chars[] = {'i', 'I', '!', '1'}; 536 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 537 FT_BBox bbox; 538 if (GetLetterCBox(face, stem_chars[i], &bbox)) { 539 int width = bbox.xMax - bbox.xMin; 540 if (width > 0 && width < min_width) { 541 min_width = width; 542 info->fStemV = min_width * 1000 / scaleDivisor; 543 } 544 } 545 } 546 547 PS_FontInfoRec ps_info; 548 TT_Postscript* tt_info; 549 if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { 550 info->fItalicAngle = ps_info.italic_angle; 551 } else if ((tt_info = 552 (TT_Postscript*)FT_Get_Sfnt_Table(face, 553 ft_sfnt_post)) != NULL) { 554 info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle); 555 } else { 556 info->fItalicAngle = 0; 557 } 558 559 info->fAscent = face->ascender * 1000 / scaleDivisor; 560 info->fDescent = face->descender * 1000 / scaleDivisor; 561 562 unref_ft_face(face); 563 return info; 564} 565#else 566SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) { 567 SkDebugf("--- GetPDFTypefaceInfo unimplemented\n"); 568 return NULL; 569} 570#endif 571 572/////////////////////////////////////////////////////////////////////////// 573 574void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { 575 if (!gLCDSupportValid) { 576 InitFreetype(); 577 FT_Done_FreeType(gFTLibrary); 578 } 579 580 if (!gLCDSupport && rec->isLCD()) { 581 // If the runtime Freetype library doesn't support LCD mode, we disable 582 // it here. 583 rec->fMaskFormat = SkMask::kA8_Format; 584 } 585 586 SkPaint::Hinting h = rec->getHinting(); 587 if (SkPaint::kFull_Hinting == h && !rec->isLCD()) { 588 // collapse full->normal hinting if we're not doing LCD 589 h = SkPaint::kNormal_Hinting; 590 } else if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag) && 591 SkPaint::kNo_Hinting != h) { 592 // to do subpixel, we must have at most slight hinting 593 h = SkPaint::kSlight_Hinting; 594 } 595 rec->setHinting(h); 596} 597 598SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc) 599 : SkScalerContext(desc) { 600 SkAutoMutexAcquire ac(gFTMutex); 601 602 if (gFTCount == 0) { 603 if (!InitFreetype()) { 604 sk_throw(); 605 } 606 } 607 ++gFTCount; 608 609 // load the font file 610 fFTSize = NULL; 611 fFace = NULL; 612 fFaceRec = ref_ft_face(fRec.fFontID); 613 if (NULL == fFaceRec) { 614 return; 615 } 616 fFace = fFaceRec->fFace; 617 618 // compute our factors from the record 619 620 SkMatrix m; 621 622 fRec.getSingleMatrix(&m); 623 624#ifdef DUMP_STRIKE_CREATION 625 SkString keyString; 626 SkFontHost::GetDescriptorKeyString(desc, &keyString); 627 printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize), 628 SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX), 629 SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]), 630 SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]), 631 fRec.getHinting(), fRec.fMaskFormat, keyString.c_str()); 632#endif 633 634 // now compute our scale factors 635 SkScalar sx = m.getScaleX(); 636 SkScalar sy = m.getScaleY(); 637 638 if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) { 639 // sort of give up on hinting 640 sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX())); 641 sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy)); 642 sx = sy = SkScalarAve(sx, sy); 643 644 SkScalar inv = SkScalarInvert(sx); 645 646 // flip the skew elements to go from our Y-down system to FreeType's 647 fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv)); 648 fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv)); 649 fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv)); 650 fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv)); 651 } else { 652 fMatrix22.xx = fMatrix22.yy = SK_Fixed1; 653 fMatrix22.xy = fMatrix22.yx = 0; 654 } 655 656 fScaleX = SkScalarToFixed(sx); 657 fScaleY = SkScalarToFixed(sy); 658 659 // compute the flags we send to Load_Glyph 660 { 661 FT_Int32 loadFlags = FT_LOAD_DEFAULT; 662 663 if (SkMask::kBW_Format == fRec.fMaskFormat) { 664 // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 665 loadFlags = FT_LOAD_TARGET_MONO; 666 if (fRec.getHinting() == SkPaint::kNo_Hinting) 667 loadFlags = FT_LOAD_NO_HINTING; 668 } else { 669 switch (fRec.getHinting()) { 670 case SkPaint::kNo_Hinting: 671 loadFlags = FT_LOAD_NO_HINTING; 672 break; 673 case SkPaint::kSlight_Hinting: 674 loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 675 break; 676 case SkPaint::kNormal_Hinting: 677 if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) 678 loadFlags = FT_LOAD_FORCE_AUTOHINT; 679 else 680 loadFlags = FT_LOAD_NO_AUTOHINT; 681 break; 682 case SkPaint::kFull_Hinting: 683 if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) { 684 loadFlags = FT_LOAD_FORCE_AUTOHINT; 685 break; 686 } 687 loadFlags = FT_LOAD_TARGET_NORMAL; 688 if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat) 689 loadFlags = FT_LOAD_TARGET_LCD; 690 else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat) 691 loadFlags = FT_LOAD_TARGET_LCD_V; 692 break; 693 default: 694 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 695 break; 696 } 697 } 698 699 if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) 700 loadFlags |= FT_LOAD_NO_BITMAP; 701 702 fLoadGlyphFlags = loadFlags; 703 } 704 705 // now create the FT_Size 706 707 { 708 FT_Error err; 709 710 err = FT_New_Size(fFace, &fFTSize); 711 if (err != 0) { 712 SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n", 713 fFaceRec->fFontID, fScaleX, fScaleY, err)); 714 fFace = NULL; 715 return; 716 } 717 718 err = FT_Activate_Size(fFTSize); 719 if (err != 0) { 720 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 721 fFaceRec->fFontID, fScaleX, fScaleY, err)); 722 fFTSize = NULL; 723 } 724 725 err = FT_Set_Char_Size( fFace, 726 SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY), 727 72, 72); 728 if (err != 0) { 729 SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 730 fFaceRec->fFontID, fScaleX, fScaleY, err)); 731 fFace = NULL; 732 return; 733 } 734 735 FT_Set_Transform( fFace, &fMatrix22, NULL); 736 } 737} 738 739SkScalerContext_FreeType::~SkScalerContext_FreeType() { 740 if (fFTSize != NULL) { 741 FT_Done_Size(fFTSize); 742 } 743 744 SkAutoMutexAcquire ac(gFTMutex); 745 746 if (fFace != NULL) { 747 unref_ft_face(fFace); 748 } 749 if (--gFTCount == 0) { 750// SkDEBUGF(("FT_Done_FreeType\n")); 751 FT_Done_FreeType(gFTLibrary); 752 SkDEBUGCODE(gFTLibrary = NULL;) 753 } 754} 755 756/* We call this before each use of the fFace, since we may be sharing 757 this face with other context (at different sizes). 758*/ 759FT_Error SkScalerContext_FreeType::setupSize() { 760 /* In the off-chance that a font has been removed, we want to error out 761 right away, so call resolve just to be sure. 762 763 TODO: perhaps we can skip this, by walking the global font cache and 764 killing all of the contexts when we know that a given fontID is going 765 away... 766 */ 767 if (!SkFontHost::ValidFontID(fRec.fFontID)) { 768 return (FT_Error)-1; 769 } 770 771 FT_Error err = FT_Activate_Size(fFTSize); 772 773 if (err != 0) { 774 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 775 fFaceRec->fFontID, fScaleX, fScaleY, err)); 776 fFTSize = NULL; 777 } else { 778 // seems we need to reset this every time (not sure why, but without it 779 // I get random italics from some other fFTSize) 780 FT_Set_Transform( fFace, &fMatrix22, NULL); 781 } 782 return err; 783} 784 785void SkScalerContext_FreeType::emboldenOutline(FT_Outline* outline) { 786 FT_Pos strength; 787 strength = FT_MulFix(fFace->units_per_EM, fFace->size->metrics.y_scale) 788 / 24; 789 FT_Outline_Embolden(outline, strength); 790} 791 792unsigned SkScalerContext_FreeType::generateGlyphCount() const { 793 return fFace->num_glyphs; 794} 795 796uint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 797 return SkToU16(FT_Get_Char_Index( fFace, uni )); 798} 799 800SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 801 // iterate through each cmap entry, looking for matching glyph indices 802 FT_UInt glyphIndex; 803 SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 804 805 while (glyphIndex != 0) { 806 if (glyphIndex == glyph) { 807 return charCode; 808 } 809 charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 810 } 811 812 return 0; 813} 814 815static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { 816 switch (format) { 817 case SkMask::kHorizontalLCD_Format: 818 case SkMask::kVerticalLCD_Format: 819 SkASSERT(!"An LCD format should never be passed here"); 820 return FT_PIXEL_MODE_GRAY; 821 case SkMask::kBW_Format: 822 return FT_PIXEL_MODE_MONO; 823 case SkMask::kA8_Format: 824 default: 825 return FT_PIXEL_MODE_GRAY; 826 } 827} 828 829void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 830#ifdef FT_ADVANCES_H 831 /* unhinted and light hinted text have linearly scaled advances 832 * which are very cheap to compute with some font formats... 833 */ 834 { 835 SkAutoMutexAcquire ac(gFTMutex); 836 837 if (this->setupSize()) { 838 glyph->zeroMetrics(); 839 return; 840 } 841 842 FT_Error error; 843 FT_Fixed advance; 844 845 error = FT_Get_Advance( fFace, glyph->getGlyphID(fBaseGlyphCount), 846 fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 847 &advance ); 848 if (0 == error) { 849 glyph->fRsbDelta = 0; 850 glyph->fLsbDelta = 0; 851 glyph->fAdvanceX = advance; // advance *2/3; //DEBUG 852 glyph->fAdvanceY = 0; 853 return; 854 } 855 } 856#endif /* FT_ADVANCES_H */ 857 /* otherwise, we need to load/hint the glyph, which is slower */ 858 this->generateMetrics(glyph); 859 return; 860} 861 862void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 863 SkAutoMutexAcquire ac(gFTMutex); 864 865 glyph->fRsbDelta = 0; 866 glyph->fLsbDelta = 0; 867 868 FT_Error err; 869 870 if (this->setupSize()) { 871 goto ERROR; 872 } 873 874 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags ); 875 if (err != 0) { 876 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 877 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err)); 878 ERROR: 879 glyph->zeroMetrics(); 880 return; 881 } 882 883 switch ( fFace->glyph->format ) { 884 case FT_GLYPH_FORMAT_OUTLINE: 885 FT_BBox bbox; 886 887 if (fRec.fFlags & kEmbolden_Flag) { 888 emboldenOutline(&fFace->glyph->outline); 889 } 890 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); 891 892 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 893 int dx = glyph->getSubXFixed() >> 10; 894 int dy = glyph->getSubYFixed() >> 10; 895 // negate dy since freetype-y-goes-up and skia-y-goes-down 896 bbox.xMin += dx; 897 bbox.yMin -= dy; 898 bbox.xMax += dx; 899 bbox.yMax -= dy; 900 } 901 902 bbox.xMin &= ~63; 903 bbox.yMin &= ~63; 904 bbox.xMax = (bbox.xMax + 63) & ~63; 905 bbox.yMax = (bbox.yMax + 63) & ~63; 906 907 glyph->fWidth = SkToU16((bbox.xMax - bbox.xMin) >> 6); 908 glyph->fHeight = SkToU16((bbox.yMax - bbox.yMin) >> 6); 909 glyph->fTop = -SkToS16(bbox.yMax >> 6); 910 glyph->fLeft = SkToS16(bbox.xMin >> 6); 911 break; 912 913 case FT_GLYPH_FORMAT_BITMAP: 914 if (fRec.fFlags & kEmbolden_Flag) { 915 FT_GlyphSlot_Own_Bitmap(fFace->glyph); 916 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0); 917 } 918 glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 919 glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 920 glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 921 glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 922 break; 923 924 default: 925 SkASSERT(!"unknown glyph format"); 926 goto ERROR; 927 } 928 929 if ((fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) == 0) { 930 glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); 931 glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); 932 if (fRec.fFlags & kDevKernText_Flag) { 933 glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 934 glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 935 } 936 } else { 937 glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance); 938 glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance); 939 } 940 941#ifdef ENABLE_GLYPH_SPEW 942 SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); 943 SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth)); 944#endif 945} 946 947#if defined(SK_SUPPORT_LCDTEXT) 948namespace skia_freetype_support { 949// extern functions from SkFontHost_FreeType_Subpixel 950extern void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source); 951extern void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& source); 952} 953 954using namespace skia_freetype_support; 955#endif 956 957void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 958 SkAutoMutexAcquire ac(gFTMutex); 959 960 FT_Error err; 961 962 if (this->setupSize()) { 963 goto ERROR; 964 } 965 966 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags); 967 if (err != 0) { 968 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", 969 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err)); 970 ERROR: 971 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 972 return; 973 } 974 975 const bool lcdRenderMode = fRec.fMaskFormat == SkMask::kHorizontalLCD_Format || 976 fRec.fMaskFormat == SkMask::kVerticalLCD_Format; 977 978 switch ( fFace->glyph->format ) { 979 case FT_GLYPH_FORMAT_OUTLINE: { 980 FT_Outline* outline = &fFace->glyph->outline; 981 FT_BBox bbox; 982 FT_Bitmap target; 983 984 if (fRec.fFlags & kEmbolden_Flag) { 985 emboldenOutline(outline); 986 } 987 988 int dx = 0, dy = 0; 989 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 990 dx = glyph.getSubXFixed() >> 10; 991 dy = glyph.getSubYFixed() >> 10; 992 // negate dy since freetype-y-goes-up and skia-y-goes-down 993 dy = -dy; 994 } 995 FT_Outline_Get_CBox(outline, &bbox); 996 /* 997 what we really want to do for subpixel is 998 offset(dx, dy) 999 compute_bounds 1000 offset(bbox & !63) 1001 but that is two calls to offset, so we do the following, which 1002 achieves the same thing with only one offset call. 1003 */ 1004 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), 1005 dy - ((bbox.yMin + dy) & ~63)); 1006 1007#if defined(SK_SUPPORT_LCDTEXT) 1008 if (lcdRenderMode) { 1009 // FT_Outline_Get_Bitmap cannot render LCD glyphs. In this case 1010 // we have to call FT_Render_Glyph and memcpy the image out. 1011 const bool isVertical = fRec.fMaskFormat == SkMask::kVerticalLCD_Format; 1012 FT_Render_Mode mode = isVertical ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD; 1013 FT_Render_Glyph(fFace->glyph, mode); 1014 1015 if (isVertical) 1016 CopyFreetypeBitmapToVerticalLCDMask(glyph, fFace->glyph->bitmap); 1017 else 1018 CopyFreetypeBitmapToLCDMask(glyph, fFace->glyph->bitmap); 1019 1020 break; 1021 } 1022#endif 1023 1024 target.width = glyph.fWidth; 1025 target.rows = glyph.fHeight; 1026 target.pitch = glyph.rowBytes(); 1027 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); 1028 target.pixel_mode = compute_pixel_mode( 1029 (SkMask::Format)fRec.fMaskFormat); 1030 target.num_grays = 256; 1031 1032 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 1033 FT_Outline_Get_Bitmap(gFTLibrary, outline, &target); 1034 } break; 1035 1036 case FT_GLYPH_FORMAT_BITMAP: { 1037 if (fRec.fFlags & kEmbolden_Flag) { 1038 FT_GlyphSlot_Own_Bitmap(fFace->glyph); 1039 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0); 1040 } 1041 SkASSERT_CONTINUE(glyph.fWidth == fFace->glyph->bitmap.width); 1042 SkASSERT_CONTINUE(glyph.fHeight == fFace->glyph->bitmap.rows); 1043 SkASSERT_CONTINUE(glyph.fTop == -fFace->glyph->bitmap_top); 1044 SkASSERT_CONTINUE(glyph.fLeft == fFace->glyph->bitmap_left); 1045 1046 const uint8_t* src = (const uint8_t*)fFace->glyph->bitmap.buffer; 1047 uint8_t* dst = (uint8_t*)glyph.fImage; 1048 1049 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY || 1050 (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && 1051 glyph.fMaskFormat == SkMask::kBW_Format)) { 1052 unsigned srcRowBytes = fFace->glyph->bitmap.pitch; 1053 unsigned dstRowBytes = glyph.rowBytes(); 1054 unsigned minRowBytes = SkMin32(srcRowBytes, dstRowBytes); 1055 unsigned extraRowBytes = dstRowBytes - minRowBytes; 1056 1057 for (int y = fFace->glyph->bitmap.rows - 1; y >= 0; --y) { 1058 memcpy(dst, src, minRowBytes); 1059 memset(dst + minRowBytes, 0, extraRowBytes); 1060 src += srcRowBytes; 1061 dst += dstRowBytes; 1062 } 1063 } else if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && 1064 (glyph.fMaskFormat == SkMask::kA8_Format || 1065 glyph.fMaskFormat == SkMask::kHorizontalLCD_Format || 1066 glyph.fMaskFormat == SkMask::kVerticalLCD_Format)) { 1067 for (int y = 0; y < fFace->glyph->bitmap.rows; ++y) { 1068 uint8_t byte = 0; 1069 int bits = 0; 1070 const uint8_t* src_row = src; 1071 uint8_t* dst_row = dst; 1072 1073 for (int x = 0; x < fFace->glyph->bitmap.width; ++x) { 1074 if (!bits) { 1075 byte = *src_row++; 1076 bits = 8; 1077 } 1078 1079 *dst_row++ = byte & 0x80 ? 0xff : 0; 1080 bits--; 1081 byte <<= 1; 1082 } 1083 1084 src += fFace->glyph->bitmap.pitch; 1085 dst += glyph.rowBytes(); 1086 } 1087 } else { 1088 SkASSERT(!"unknown glyph bitmap transform needed"); 1089 } 1090 1091 if (lcdRenderMode) 1092 glyph.expandA8ToLCD(); 1093 1094 } break; 1095 1096 default: 1097 SkASSERT(!"unknown glyph format"); 1098 goto ERROR; 1099 } 1100} 1101 1102/////////////////////////////////////////////////////////////////////////////// 1103 1104#define ft2sk(x) SkFixedToScalar((x) << 10) 1105 1106#if FREETYPE_MAJOR >= 2 && FREETYPE_MINOR >= 2 1107 #define CONST_PARAM const 1108#else // older freetype doesn't use const here 1109 #define CONST_PARAM 1110#endif 1111 1112static int move_proc(CONST_PARAM FT_Vector* pt, void* ctx) { 1113 SkPath* path = (SkPath*)ctx; 1114 path->close(); // to close the previous contour (if any) 1115 path->moveTo(ft2sk(pt->x), -ft2sk(pt->y)); 1116 return 0; 1117} 1118 1119static int line_proc(CONST_PARAM FT_Vector* pt, void* ctx) { 1120 SkPath* path = (SkPath*)ctx; 1121 path->lineTo(ft2sk(pt->x), -ft2sk(pt->y)); 1122 return 0; 1123} 1124 1125static int quad_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1, 1126 void* ctx) { 1127 SkPath* path = (SkPath*)ctx; 1128 path->quadTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), -ft2sk(pt1->y)); 1129 return 0; 1130} 1131 1132static int cubic_proc(CONST_PARAM FT_Vector* pt0, CONST_PARAM FT_Vector* pt1, 1133 CONST_PARAM FT_Vector* pt2, void* ctx) { 1134 SkPath* path = (SkPath*)ctx; 1135 path->cubicTo(ft2sk(pt0->x), -ft2sk(pt0->y), ft2sk(pt1->x), 1136 -ft2sk(pt1->y), ft2sk(pt2->x), -ft2sk(pt2->y)); 1137 return 0; 1138} 1139 1140void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, 1141 SkPath* path) { 1142 SkAutoMutexAcquire ac(gFTMutex); 1143 1144 SkASSERT(&glyph && path); 1145 1146 if (this->setupSize()) { 1147 path->reset(); 1148 return; 1149 } 1150 1151 uint32_t flags = fLoadGlyphFlags; 1152 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 1153 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 1154 1155 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags); 1156 1157 if (err != 0) { 1158 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1159 glyph.getGlyphID(fBaseGlyphCount), flags, err)); 1160 path->reset(); 1161 return; 1162 } 1163 1164 if (fRec.fFlags & kEmbolden_Flag) { 1165 emboldenOutline(&fFace->glyph->outline); 1166 } 1167 1168 FT_Outline_Funcs funcs; 1169 1170 funcs.move_to = move_proc; 1171 funcs.line_to = line_proc; 1172 funcs.conic_to = quad_proc; 1173 funcs.cubic_to = cubic_proc; 1174 funcs.shift = 0; 1175 funcs.delta = 0; 1176 1177 err = FT_Outline_Decompose(&fFace->glyph->outline, &funcs, path); 1178 1179 if (err != 0) { 1180 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 1181 glyph.getGlyphID(fBaseGlyphCount), flags, err)); 1182 path->reset(); 1183 return; 1184 } 1185 1186 path->close(); 1187} 1188 1189void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, 1190 SkPaint::FontMetrics* my) { 1191 if (NULL == mx && NULL == my) { 1192 return; 1193 } 1194 1195 SkAutoMutexAcquire ac(gFTMutex); 1196 1197 if (this->setupSize()) { 1198 ERROR: 1199 if (mx) { 1200 sk_bzero(mx, sizeof(SkPaint::FontMetrics)); 1201 } 1202 if (my) { 1203 sk_bzero(my, sizeof(SkPaint::FontMetrics)); 1204 } 1205 return; 1206 } 1207 1208 FT_Face face = fFace; 1209 int upem = face->units_per_EM; 1210 if (upem <= 0) { 1211 goto ERROR; 1212 } 1213 1214 SkPoint pts[6]; 1215 SkFixed ys[6]; 1216 SkFixed scaleY = fScaleY; 1217 SkFixed mxy = fMatrix22.xy; 1218 SkFixed myy = fMatrix22.yy; 1219 SkScalar xmin = SkIntToScalar(face->bbox.xMin) / upem; 1220 SkScalar xmax = SkIntToScalar(face->bbox.xMax) / upem; 1221 1222 int leading = face->height - (face->ascender + -face->descender); 1223 if (leading < 0) { 1224 leading = 0; 1225 } 1226 1227 // Try to get the OS/2 table from the font. This contains the specific 1228 // average font width metrics which Windows uses. 1229 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1230 1231 ys[0] = -face->bbox.yMax; 1232 ys[1] = -face->ascender; 1233 ys[2] = -face->descender; 1234 ys[3] = -face->bbox.yMin; 1235 ys[4] = leading; 1236 ys[5] = os2 ? os2->xAvgCharWidth : 0; 1237 1238 SkScalar x_height; 1239 if (os2 && os2->sxHeight) { 1240 x_height = SkFixedToScalar(SkMulDiv(fScaleX, os2->sxHeight, upem)); 1241 } else { 1242 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); 1243 if (x_glyph) { 1244 FT_BBox bbox; 1245 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); 1246 if (fRec.fFlags & kEmbolden_Flag) { 1247 emboldenOutline(&fFace->glyph->outline); 1248 } 1249 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); 1250 x_height = SkIntToScalar(bbox.yMax) / 64; 1251 } else { 1252 x_height = 0; 1253 } 1254 } 1255 1256 // convert upem-y values into scalar points 1257 for (int i = 0; i < 6; i++) { 1258 SkFixed y = SkMulDiv(scaleY, ys[i], upem); 1259 SkFixed x = SkFixedMul(mxy, y); 1260 y = SkFixedMul(myy, y); 1261 pts[i].set(SkFixedToScalar(x), SkFixedToScalar(y)); 1262 } 1263 1264 if (mx) { 1265 mx->fTop = pts[0].fX; 1266 mx->fAscent = pts[1].fX; 1267 mx->fDescent = pts[2].fX; 1268 mx->fBottom = pts[3].fX; 1269 mx->fLeading = pts[4].fX; 1270 mx->fAvgCharWidth = pts[5].fX; 1271 mx->fXMin = xmin; 1272 mx->fXMax = xmax; 1273 mx->fXHeight = x_height; 1274 } 1275 if (my) { 1276 my->fTop = pts[0].fY; 1277 my->fAscent = pts[1].fY; 1278 my->fDescent = pts[2].fY; 1279 my->fBottom = pts[3].fY; 1280 my->fLeading = pts[4].fY; 1281 my->fAvgCharWidth = pts[5].fY; 1282 my->fXMin = xmin; 1283 my->fXMax = xmax; 1284 my->fXHeight = x_height; 1285 } 1286} 1287 1288//////////////////////////////////////////////////////////////////////// 1289//////////////////////////////////////////////////////////////////////// 1290 1291SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { 1292 SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, (desc)); 1293 if (!c->success()) { 1294 SkDELETE(c); 1295 c = NULL; 1296 } 1297 return c; 1298} 1299 1300/////////////////////////////////////////////////////////////////////////////// 1301 1302/* Export this so that other parts of our FonttHost port can make use of our 1303 ability to extract the name+style from a stream, using FreeType's api. 1304*/ 1305SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name) { 1306 FT_Library library; 1307 if (FT_Init_FreeType(&library)) { 1308 name->set(NULL); 1309 return SkTypeface::kNormal; 1310 } 1311 1312 FT_Open_Args args; 1313 memset(&args, 0, sizeof(args)); 1314 1315 const void* memoryBase = stream->getMemoryBase(); 1316 FT_StreamRec streamRec; 1317 1318 if (NULL != memoryBase) { 1319 args.flags = FT_OPEN_MEMORY; 1320 args.memory_base = (const FT_Byte*)memoryBase; 1321 args.memory_size = stream->getLength(); 1322 } else { 1323 memset(&streamRec, 0, sizeof(streamRec)); 1324 streamRec.size = stream->read(NULL, 0); 1325 streamRec.descriptor.pointer = stream; 1326 streamRec.read = sk_stream_read; 1327 streamRec.close = sk_stream_close; 1328 1329 args.flags = FT_OPEN_STREAM; 1330 args.stream = &streamRec; 1331 } 1332 1333 FT_Face face; 1334 if (FT_Open_Face(library, &args, 0, &face)) { 1335 FT_Done_FreeType(library); 1336 name->set(NULL); 1337 return SkTypeface::kNormal; 1338 } 1339 1340 name->set(face->family_name); 1341 int style = SkTypeface::kNormal; 1342 1343 if (face->style_flags & FT_STYLE_FLAG_BOLD) { 1344 style |= SkTypeface::kBold; 1345 } 1346 if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 1347 style |= SkTypeface::kItalic; 1348 } 1349 1350 FT_Done_Face(face); 1351 FT_Done_FreeType(library); 1352 return (SkTypeface::Style)style; 1353} 1354