Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 SkDELETE(rec); | 331 SkDELETE(rec); |
| 332 } | 332 } |
| 333 return; | 333 return; |
| 334 } | 334 } |
| 335 prev = rec; | 335 prev = rec; |
| 336 rec = next; | 336 rec = next; |
| 337 } | 337 } |
| 338 SkDEBUGFAIL("shouldn't get here, face not in list"); | 338 SkDEBUGFAIL("shouldn't get here, face not in list"); |
| 339 } | 339 } |
| 340 | 340 |
| 341 class AutoFTAccess { | |
| 342 public: | |
| 343 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { | |
| 344 gFTMutex.acquire(); | |
| 345 if (1 == ++gFTCount) { | |
| 346 if (!InitFreetype()) { | |
| 347 sk_throw(); | |
| 348 } | |
| 349 } | |
| 350 fRec = ref_ft_face(tf); | |
| 351 if (fRec) { | |
| 352 fFace = fRec->fFace; | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 ~AutoFTAccess() { | |
| 357 if (fFace) { | |
| 358 unref_ft_face(fFace); | |
| 359 } | |
| 360 if (0 == --gFTCount) { | |
| 361 FT_Done_FreeType(gFTLibrary); | |
| 362 } | |
| 363 gFTMutex.release(); | |
| 364 } | |
| 365 | |
| 366 SkFaceRec* rec() { return fRec; } | |
| 367 FT_Face face() { return fFace; } | |
| 368 | |
| 369 private: | |
| 370 SkFaceRec* fRec; | |
| 371 FT_Face fFace; | |
| 372 }; | |
| 373 | |
| 341 /////////////////////////////////////////////////////////////////////////// | 374 /////////////////////////////////////////////////////////////////////////// |
| 342 | 375 |
| 343 // Work around for old versions of freetype. | 376 // Work around for old versions of freetype. |
| 344 static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count, | 377 static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count, |
| 345 FT_Int32 loadFlags, FT_Fixed* advances) { | 378 FT_Int32 loadFlags, FT_Fixed* advances) { |
| 346 #ifdef FT_ADVANCES_H | 379 #ifdef FT_ADVANCES_H |
| 347 return FT_Get_Advances(face, start, count, loadFlags, advances); | 380 return FT_Get_Advances(face, start, count, loadFlags, advances); |
| 348 #else | 381 #else |
| 349 if (!face || start >= face->num_glyphs || | 382 if (!face || start >= face->num_glyphs || |
| 350 start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) { | 383 start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 } | 481 } |
| 449 } | 482 } |
| 450 | 483 |
| 451 SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( | 484 SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( |
| 452 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, | 485 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, |
| 453 const uint32_t* glyphIDs, | 486 const uint32_t* glyphIDs, |
| 454 uint32_t glyphIDsCount) const { | 487 uint32_t glyphIDsCount) const { |
| 455 #if defined(SK_BUILD_FOR_MAC) | 488 #if defined(SK_BUILD_FOR_MAC) |
| 456 return NULL; | 489 return NULL; |
| 457 #else | 490 #else |
| 458 SkAutoMutexAcquire ac(gFTMutex); | 491 AutoFTAccess fta(this); |
| 459 FT_Library libInit = NULL; | 492 FT_Face face = fta.face(); |
| 460 if (gFTCount == 0) { | 493 if (!face) { |
| 461 if (!InitFreetype()) | 494 return NULL; |
| 462 sk_throw(); | |
| 463 libInit = gFTLibrary; | |
| 464 } | 495 } |
| 465 SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); | |
| 466 SkFaceRec* rec = ref_ft_face(this); | |
| 467 if (NULL == rec) | |
| 468 return NULL; | |
| 469 FT_Face face = rec->fFace; | |
| 470 | 496 |
| 471 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; | 497 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; |
| 472 info->fFontName.set(FT_Get_Postscript_Name(face)); | 498 info->fFontName.set(FT_Get_Postscript_Name(face)); |
| 473 info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face); | 499 info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face); |
| 474 info->fLastGlyphID = face->num_glyphs - 1; | 500 info->fLastGlyphID = face->num_glyphs - 1; |
| 475 info->fEmSize = 1000; | 501 info->fEmSize = 1000; |
| 476 | 502 |
| 477 bool cid = false; | 503 bool cid = false; |
| 478 const char* fontType = FT_Get_X11_Font_Format(face); | 504 const char* fontType = FT_Get_X11_Font_Format(face); |
| 479 if (strcmp(fontType, "Type 1") == 0) { | 505 if (strcmp(fontType, "Type 1") == 0) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 | 647 |
| 622 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo && | 648 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo && |
| 623 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && | 649 info->fType != SkAdvancedTypefaceMetrics::kType1_Font && |
| 624 face->num_charmaps) { | 650 face->num_charmaps) { |
| 625 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); | 651 populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); |
| 626 } | 652 } |
| 627 | 653 |
| 628 if (!canEmbed(face)) | 654 if (!canEmbed(face)) |
| 629 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; | 655 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; |
| 630 | 656 |
| 631 unref_ft_face(face); | |
| 632 return info; | 657 return info; |
| 633 #endif | 658 #endif |
| 634 } | 659 } |
| 635 | 660 |
| 636 /////////////////////////////////////////////////////////////////////////// | 661 /////////////////////////////////////////////////////////////////////////// |
| 637 | 662 |
| 638 #define BLACK_LUMINANCE_LIMIT 0x40 | 663 #define BLACK_LUMINANCE_LIMIT 0x40 |
| 639 #define WHITE_LUMINANCE_LIMIT 0xA0 | 664 #define WHITE_LUMINANCE_LIMIT 0xA0 |
| 640 | 665 |
| 641 static bool bothZero(SkScalar a, SkScalar b) { | 666 static bool bothZero(SkScalar a, SkScalar b) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 rec->setHinting(h); | 718 rec->setHinting(h); |
| 694 | 719 |
| 695 #ifndef SK_GAMMA_APPLY_TO_A8 | 720 #ifndef SK_GAMMA_APPLY_TO_A8 |
| 696 if (!isLCD(*rec)) { | 721 if (!isLCD(*rec)) { |
| 697 rec->ignorePreBlend(); | 722 rec->ignorePreBlend(); |
| 698 } | 723 } |
| 699 #endif | 724 #endif |
| 700 } | 725 } |
| 701 | 726 |
| 702 int SkTypeface_FreeType::onGetUPEM() const { | 727 int SkTypeface_FreeType::onGetUPEM() const { |
| 703 SkAutoMutexAcquire ac(gFTMutex); | 728 AutoFTAccess fta(this); |
| 704 FT_Library libInit = NULL; | 729 FT_Face face = fta.face(); |
| 705 if (gFTCount == 0) { | 730 return face ? face->units_per_EM : 0; |
| 706 if (!InitFreetype()) | |
| 707 sk_throw(); | |
| 708 libInit = gFTLibrary; | |
| 709 } | |
| 710 SkAutoTCallIProc<struct FT_LibraryRec_, FT_Done_FreeType> ftLib(libInit); | |
| 711 SkFaceRec *rec = ref_ft_face(this); | |
| 712 int unitsPerEm = 0; | |
| 713 | |
| 714 if (rec != NULL && rec->fFace != NULL) { | |
| 715 unitsPerEm = rec->fFace->units_per_EM; | |
| 716 unref_ft_face(rec->fFace); | |
| 717 } | |
| 718 | |
| 719 return unitsPerEm; | |
| 720 } | 731 } |
| 721 | 732 |
| 722 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, | 733 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, |
| 723 const SkDescriptor* desc) | 734 const SkDescriptor* desc) |
| 724 : SkScalerContext_FreeType_Base(typeface, desc) { | 735 : SkScalerContext_FreeType_Base(typeface, desc) { |
| 725 SkAutoMutexAcquire ac(gFTMutex); | 736 SkAutoMutexAcquire ac(gFTMutex); |
| 726 | 737 |
| 727 if (gFTCount == 0) { | 738 if (gFTCount == 0) { |
| 728 if (!InitFreetype()) { | 739 if (!InitFreetype()) { |
| 729 sk_throw(); | 740 sk_throw(); |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1313 my->fDescent = pts[2].fY; | 1324 my->fDescent = pts[2].fY; |
| 1314 my->fBottom = pts[3].fY; | 1325 my->fBottom = pts[3].fY; |
| 1315 my->fLeading = pts[4].fY; | 1326 my->fLeading = pts[4].fY; |
| 1316 my->fAvgCharWidth = pts[5].fY; | 1327 my->fAvgCharWidth = pts[5].fY; |
| 1317 my->fXMin = xmin; | 1328 my->fXMin = xmin; |
| 1318 my->fXMax = xmax; | 1329 my->fXMax = xmax; |
| 1319 my->fXHeight = x_height; | 1330 my->fXHeight = x_height; |
| 1320 } | 1331 } |
| 1321 } | 1332 } |
| 1322 | 1333 |
| 1323 //////////////////////////////////////////////////////////////////////// | 1334 /////////////////////////////////////////////////////////////////////////////// |
| 1324 //////////////////////////////////////////////////////////////////////// | 1335 |
| 1336 #include "SkUtils.h" | |
| 1337 | |
| 1338 static SkUnichar next_utf8(const void** chars) { | |
| 1339 return SkUTF8_NextUnichar((const char**)chars); | |
| 1340 } | |
| 1341 | |
| 1342 static SkUnichar next_utf16(const void** chars) { | |
| 1343 return SkUTF16_NextUnichar((const uint16_t**)chars); | |
| 1344 } | |
| 1345 | |
| 1346 static SkUnichar next_utf32(const void** chars) { | |
| 1347 const SkUnichar** uniChars = (const SkUnichar**)chars; | |
| 1348 SkUnichar uni = **uniChars; | |
| 1349 *uniChars += 1; | |
| 1350 return uni; | |
| 1351 } | |
| 1352 | |
| 1353 typedef SkUnichar (*EncodingProc)(const void**); | |
| 1354 | |
| 1355 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { | |
| 1356 static const EncodingProc gProcs[] = { | |
| 1357 next_utf8, next_utf16, next_utf32 | |
| 1358 }; | |
| 1359 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); | |
| 1360 return gProcs[enc]; | |
| 1361 } | |
| 1362 | |
| 1363 int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, | |
| 1364 uint16_t glyphs[], int glyphCount) const { | |
| 1365 AutoFTAccess fta(this); | |
| 1366 FT_Face face = fta.face(); | |
| 1367 if (!face) { | |
| 1368 if (glyphs) { | |
| 1369 sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); | |
| 1370 } | |
| 1371 return 0; | |
| 1372 } | |
| 1373 | |
| 1374 EncodingProc next_uni_proc = find_encoding_proc(encoding); | |
| 1375 | |
| 1376 if (NULL == glyphs) { | |
| 1377 for (int i = 0; i < glyphCount; ++i) { | |
| 1378 if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { | |
| 1379 return i; | |
| 1380 } | |
| 1381 } | |
| 1382 return glyphCount; | |
| 1383 } else { | |
| 1384 int first = glyphCount; | |
| 1385 for (int i = 0; i < glyphCount; ++i) { | |
| 1386 unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); | |
| 1387 glyphs[i] = SkToU16(id); | |
| 1388 if (0 == id && i < first) { | |
| 1389 first = i; | |
| 1390 } | |
| 1391 } | |
| 1392 return first; | |
| 1393 } | |
| 1394 } | |
| 1395 | |
| 1396 int SkTypeface_FreeType::onCountGlyphs() const { | |
|
bungeman-skia
2013/07/02 16:04:20
Is this intended to replace SkScalerContext::gener
reed1
2013/07/02 16:14:37
Not sure I follow : I'm extracting a cached FT_Fac
bungeman-skia
2013/07/02 16:25:31
I suppose I'm just pointing out that the entirety
| |
| 1397 // we cache this value, using -1 as a sentinel for "not computed" | |
| 1398 if (fGlyphCount < 0) { | |
| 1399 AutoFTAccess fta(this); | |
| 1400 FT_Face face = fta.face(); | |
| 1401 // if the face failed, we still assign a non-negative value | |
| 1402 fGlyphCount = face ? face->num_glyphs : 0; | |
| 1403 } | |
| 1404 return fGlyphCount; | |
| 1405 } | |
| 1406 | |
| 1407 /////////////////////////////////////////////////////////////////////////////// | |
| 1408 /////////////////////////////////////////////////////////////////////////////// | |
| 1325 | 1409 |
| 1326 /* Export this so that other parts of our FonttHost port can make use of our | 1410 /* Export this so that other parts of our FonttHost port can make use of our |
| 1327 ability to extract the name+style from a stream, using FreeType's api. | 1411 ability to extract the name+style from a stream, using FreeType's api. |
| 1328 */ | 1412 */ |
| 1329 bool find_name_and_attributes(SkStream* stream, SkString* name, | 1413 bool find_name_and_attributes(SkStream* stream, SkString* name, |
| 1330 SkTypeface::Style* style, bool* isFixedPitch) { | 1414 SkTypeface::Style* style, bool* isFixedPitch) { |
| 1331 FT_Library library; | 1415 FT_Library library; |
| 1332 if (FT_Init_FreeType(&library)) { | 1416 if (FT_Init_FreeType(&library)) { |
| 1333 return false; | 1417 return false; |
| 1334 } | 1418 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1375 *style = (SkTypeface::Style) tempStyle; | 1459 *style = (SkTypeface::Style) tempStyle; |
| 1376 } | 1460 } |
| 1377 if (isFixedPitch) { | 1461 if (isFixedPitch) { |
| 1378 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1462 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
| 1379 } | 1463 } |
| 1380 | 1464 |
| 1381 FT_Done_Face(face); | 1465 FT_Done_Face(face); |
| 1382 FT_Done_FreeType(library); | 1466 FT_Done_FreeType(library); |
| 1383 return true; | 1467 return true; |
| 1384 } | 1468 } |
| OLD | NEW |