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 |