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 "SkTypes.h" // Keep this before any #ifdef ... | 9 #include "SkTypes.h" // Keep this before any #ifdef ... |
10 | 10 |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "SkSFNTHeader.h" | 41 #include "SkSFNTHeader.h" |
42 #include "SkStream.h" | 42 #include "SkStream.h" |
43 #include "SkString.h" | 43 #include "SkString.h" |
44 #include "SkTypefaceCache.h" | 44 #include "SkTypefaceCache.h" |
45 #include "SkTypeface_mac.h" | 45 #include "SkTypeface_mac.h" |
46 #include "SkUtils.h" | 46 #include "SkUtils.h" |
47 #include "SkUtils.h" | 47 #include "SkUtils.h" |
48 | 48 |
49 #include <dlfcn.h> | 49 #include <dlfcn.h> |
50 | 50 |
| 51 // Experimental code to use a global lock whenever we access CG, to see if this
reduces |
| 52 // crashes in Chrome |
| 53 #define USE_GLOBAL_MUTEX_FOR_CG_ACCESS |
| 54 |
| 55 #ifdef USE_GLOBAL_MUTEX_FOR_CG_ACCESS |
| 56 static SkMutex gCGMutex; |
| 57 #define AUTO_CG_LOCK() SkAutoMutexAcquire amc(gCGMutex) |
| 58 #else |
| 59 #define AUTO_CG_LOCK() |
| 60 #endif |
| 61 |
51 // Set to make glyph bounding boxes visible. | 62 // Set to make glyph bounding boxes visible. |
52 #define SK_SHOW_TEXT_BLIT_COVERAGE 0 | 63 #define SK_SHOW_TEXT_BLIT_COVERAGE 0 |
53 | 64 |
54 class SkScalerContext_Mac; | 65 class SkScalerContext_Mac; |
55 | 66 |
56 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we | 67 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we |
57 // provide a wrapper here that will return an empty array if need be. | 68 // provide a wrapper here that will return an empty array if need be. |
58 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { | 69 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { |
59 #ifdef SK_BUILD_FOR_IOS | 70 #ifdef SK_BUILD_FOR_IOS |
60 return CFArrayCreate(NULL, NULL, 0, NULL); | 71 return CFArrayCreate(NULL, NULL, 0, NULL); |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, | 717 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, |
707 const SkDescriptor* desc) | 718 const SkDescriptor* desc) |
708 : INHERITED(typeface, desc) | 719 : INHERITED(typeface, desc) |
709 , fFBoundingBoxes() | 720 , fFBoundingBoxes() |
710 , fFBoundingBoxesGlyphOffset(0) | 721 , fFBoundingBoxesGlyphOffset(0) |
711 , fGeneratedFBoundingBoxes(false) | 722 , fGeneratedFBoundingBoxes(false) |
712 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) | 723 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) |
713 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) | 724 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) |
714 | 725 |
715 { | 726 { |
| 727 AUTO_CG_LOCK(); |
| 728 |
716 CTFontRef ctFont = typeface->fFontRef.get(); | 729 CTFontRef ctFont = typeface->fFontRef.get(); |
717 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); | 730 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
718 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); | 731 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
719 fGlyphCount = SkToU16(numGlyphs); | 732 fGlyphCount = SkToU16(numGlyphs); |
720 | 733 |
721 // CT on (at least) 10.9 will size color glyphs down from the requested size
, but not up. | 734 // CT on (at least) 10.9 will size color glyphs down from the requested size
, but not up. |
722 // As a result, it is necessary to know the actual device size and request t
hat. | 735 // As a result, it is necessary to know the actual device size and request t
hat. |
723 SkVector scale; | 736 SkVector scale; |
724 SkMatrix skTransform; | 737 SkMatrix skTransform; |
725 fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &
skTransform, | 738 fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &
skTransform, |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 } | 991 } |
979 | 992 |
980 return true; | 993 return true; |
981 } | 994 } |
982 | 995 |
983 unsigned SkScalerContext_Mac::generateGlyphCount(void) { | 996 unsigned SkScalerContext_Mac::generateGlyphCount(void) { |
984 return fGlyphCount; | 997 return fGlyphCount; |
985 } | 998 } |
986 | 999 |
987 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { | 1000 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { |
| 1001 AUTO_CG_LOCK(); |
| 1002 |
988 CGGlyph cgGlyph[2]; | 1003 CGGlyph cgGlyph[2]; |
989 UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit. | 1004 UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit. |
990 | 1005 |
991 // Get the glyph | 1006 // Get the glyph |
992 size_t numUniChar = SkUTF16_FromUnichar(uni, theChar); | 1007 size_t numUniChar = SkUTF16_FromUnichar(uni, theChar); |
993 SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); | 1008 SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); |
994 | 1009 |
995 // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code p
oints: | 1010 // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code p
oints: |
996 // When a surrogate pair is detected, the glyph index used is the index of t
he high surrogate. | 1011 // When a surrogate pair is detected, the glyph index used is the index of t
he high surrogate. |
997 // It is documented that if a mapping is unavailable, the glyph will be set
to 0. | 1012 // It is documented that if a mapping is unavailable, the glyph will be set
to 0. |
998 CTFontGetGlyphsForCharacters(fCTFont, theChar, cgGlyph, numUniChar); | 1013 CTFontGetGlyphsForCharacters(fCTFont, theChar, cgGlyph, numUniChar); |
999 return cgGlyph[0]; | 1014 return cgGlyph[0]; |
1000 } | 1015 } |
1001 | 1016 |
1002 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { | 1017 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { |
1003 this->generateMetrics(glyph); | 1018 this->generateMetrics(glyph); |
1004 } | 1019 } |
1005 | 1020 |
1006 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { | 1021 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { |
| 1022 AUTO_CG_LOCK(); |
| 1023 |
1007 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(); | 1024 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(); |
1008 glyph->zeroMetrics(); | 1025 glyph->zeroMetrics(); |
1009 | 1026 |
1010 // The following block produces cgAdvance in CG units (pixels, y up). | 1027 // The following block produces cgAdvance in CG units (pixels, y up). |
1011 CGSize cgAdvance; | 1028 CGSize cgAdvance; |
1012 if (fVertical) { | 1029 if (fVertical) { |
1013 CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontVerticalOrientation, | 1030 CTFontGetAdvancesForGlyphs(fCTUnrotatedFont, kCTFontVerticalOrientation, |
1014 &cgGlyph, &cgAdvance, 1); | 1031 &cgGlyph, &cgAdvance, 1); |
1015 // Vertical advances are returned as widths instead of heights. | 1032 // Vertical advances are returned as widths instead of heights. |
1016 SkTSwap(cgAdvance.height, cgAdvance.width); | 1033 SkTSwap(cgAdvance.height, cgAdvance.width); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1313 } | 1330 } |
1314 | 1331 |
1315 /* | 1332 /* |
1316 * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 | 1333 * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 |
1317 * seems sufficient, and possibly even correct, to allow the hinted outline | 1334 * seems sufficient, and possibly even correct, to allow the hinted outline |
1318 * to be subpixel positioned. | 1335 * to be subpixel positioned. |
1319 */ | 1336 */ |
1320 #define kScaleForSubPixelPositionHinting (4.0f) | 1337 #define kScaleForSubPixelPositionHinting (4.0f) |
1321 | 1338 |
1322 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { | 1339 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { |
| 1340 AUTO_CG_LOCK(); |
| 1341 |
1323 CTFontRef font = fCTFont; | 1342 CTFontRef font = fCTFont; |
1324 SkScalar scaleX = SK_Scalar1; | 1343 SkScalar scaleX = SK_Scalar1; |
1325 SkScalar scaleY = SK_Scalar1; | 1344 SkScalar scaleY = SK_Scalar1; |
1326 | 1345 |
1327 /* | 1346 /* |
1328 * For subpixel positioning, we want to return an unhinted outline, so it | 1347 * For subpixel positioning, we want to return an unhinted outline, so it |
1329 * can be positioned nicely at fractional offsets. However, we special-case | 1348 * can be positioned nicely at fractional offsets. However, we special-case |
1330 * if the baseline of the (horizontal) text is axis-aligned. In those cases | 1349 * if the baseline of the (horizontal) text is axis-aligned. In those cases |
1331 * we want to retain hinting in the direction orthogonal to the baseline. | 1350 * we want to retain hinting in the direction orthogonal to the baseline. |
1332 * e.g. for horizontal baseline, we want to retain hinting in Y. | 1351 * e.g. for horizontal baseline, we want to retain hinting in Y. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 getVerticalOffset(cgGlyph, &offset); | 1395 getVerticalOffset(cgGlyph, &offset); |
1377 path->offset(offset.fX, offset.fY); | 1396 path->offset(offset.fX, offset.fY); |
1378 } | 1397 } |
1379 } | 1398 } |
1380 | 1399 |
1381 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) { | 1400 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) { |
1382 if (NULL == metrics) { | 1401 if (NULL == metrics) { |
1383 return; | 1402 return; |
1384 } | 1403 } |
1385 | 1404 |
| 1405 AUTO_CG_LOCK(); |
| 1406 |
1386 CGRect theBounds = CTFontGetBoundingBox(fCTFont); | 1407 CGRect theBounds = CTFontGetBoundingBox(fCTFont); |
1387 | 1408 |
1388 metrics->fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); | 1409 metrics->fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); |
1389 metrics->fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); | 1410 metrics->fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); |
1390 metrics->fDescent = CGToScalar( CTFontGetDescent(fCTFont)); | 1411 metrics->fDescent = CGToScalar( CTFontGetDescent(fCTFont)); |
1391 metrics->fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds)); | 1412 metrics->fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds)); |
1392 metrics->fLeading = CGToScalar( CTFontGetLeading(fCTFont)); | 1413 metrics->fLeading = CGToScalar( CTFontGetLeading(fCTFont)); |
1393 metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds)); | 1414 metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds)); |
1394 metrics->fXMin = CGToScalar( CGRectGetMinX_inline(theBounds)); | 1415 metrics->fXMin = CGToScalar( CGRectGetMinX_inline(theBounds)); |
1395 metrics->fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds)); | 1416 metrics->fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds)); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1537 CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8); | 1558 CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8); |
1538 // Resize to the actual UTF-8 length used, stripping the null character. | 1559 // Resize to the actual UTF-8 length used, stripping the null character. |
1539 dst->resize(strlen(dst->c_str())); | 1560 dst->resize(strlen(dst->c_str())); |
1540 } | 1561 } |
1541 | 1562 |
1542 SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( | 1563 SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( |
1543 PerGlyphInfo perGlyphInfo, | 1564 PerGlyphInfo perGlyphInfo, |
1544 const uint32_t* glyphIDs, | 1565 const uint32_t* glyphIDs, |
1545 uint32_t glyphIDsCount) const { | 1566 uint32_t glyphIDsCount) const { |
1546 | 1567 |
| 1568 AUTO_CG_LOCK(); |
| 1569 |
1547 CTFontRef originalCTFont = fFontRef.get(); | 1570 CTFontRef originalCTFont = fFontRef.get(); |
1548 AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes( | 1571 AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes( |
1549 originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL)); | 1572 originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL)); |
1550 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; | 1573 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; |
1551 | 1574 |
1552 { | 1575 { |
1553 AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont)); | 1576 AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont)); |
1554 if (fontName.get()) { | 1577 if (fontName.get()) { |
1555 CFStringToSkString(fontName, &info->fFontName); | 1578 CFStringToSkString(fontName, &info->fFontName); |
1556 } | 1579 } |
(...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2461 } | 2484 } |
2462 return face; | 2485 return face; |
2463 } | 2486 } |
2464 }; | 2487 }; |
2465 | 2488 |
2466 /////////////////////////////////////////////////////////////////////////////// | 2489 /////////////////////////////////////////////////////////////////////////////// |
2467 | 2490 |
2468 SkFontMgr* SkFontMgr::Factory() { | 2491 SkFontMgr* SkFontMgr::Factory() { |
2469 return SkNEW(SkFontMgr_Mac); | 2492 return SkNEW(SkFontMgr_Mac); |
2470 } | 2493 } |
OLD | NEW |