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 #ifdef SK_BUILD_FOR_MAC | 9 #ifdef SK_BUILD_FOR_MAC |
10 #import <ApplicationServices/ApplicationServices.h> | 10 #import <ApplicationServices/ApplicationServices.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #ifdef SK_BUILD_FOR_IOS | 13 #ifdef SK_BUILD_FOR_IOS |
14 #include <CoreText/CoreText.h> | 14 #include <CoreText/CoreText.h> |
15 #include <CoreText/CTFontManager.h> | 15 #include <CoreText/CTFontManager.h> |
16 #include <CoreGraphics/CoreGraphics.h> | 16 #include <CoreGraphics/CoreGraphics.h> |
17 #include <CoreFoundation/CoreFoundation.h> | 17 #include <CoreFoundation/CoreFoundation.h> |
18 #endif | 18 #endif |
19 | 19 |
20 #include "SkFontHost.h" | 20 #include "SkFontHost.h" |
21 #include "SkCGUtils.h" | 21 #include "SkCGUtils.h" |
22 #include "SkColorPriv.h" | 22 #include "SkColorPriv.h" |
23 #include "SkDescriptor.h" | 23 #include "SkDescriptor.h" |
24 #include "SkEndian.h" | 24 #include "SkEndian.h" |
25 #include "SkFontDescriptor.h" | 25 #include "SkFontDescriptor.h" |
26 #include "SkFloatingPoint.h" | 26 #include "SkFloatingPoint.h" |
27 #include "SkGlyph.h" | 27 #include "SkGlyph.h" |
| 28 #include "SkLazyFnPtr.h" |
28 #include "SkMaskGamma.h" | 29 #include "SkMaskGamma.h" |
29 #include "SkSFNTHeader.h" | 30 #include "SkSFNTHeader.h" |
30 #include "SkOTTable_glyf.h" | 31 #include "SkOTTable_glyf.h" |
31 #include "SkOTTable_head.h" | 32 #include "SkOTTable_head.h" |
32 #include "SkOTTable_hhea.h" | 33 #include "SkOTTable_hhea.h" |
33 #include "SkOTTable_loca.h" | 34 #include "SkOTTable_loca.h" |
34 #include "SkOTUtils.h" | 35 #include "SkOTUtils.h" |
35 #include "SkPaint.h" | 36 #include "SkPaint.h" |
36 #include "SkPath.h" | 37 #include "SkPath.h" |
37 #include "SkString.h" | 38 #include "SkString.h" |
38 #include "SkStream.h" | 39 #include "SkStream.h" |
39 #include "SkThread.h" | 40 #include "SkThread.h" |
40 #include "SkTypeface_mac.h" | 41 #include "SkTypeface_mac.h" |
41 #include "SkUtils.h" | 42 #include "SkUtils.h" |
42 #include "SkTypefaceCache.h" | 43 #include "SkTypefaceCache.h" |
43 #include "SkFontMgr.h" | 44 #include "SkFontMgr.h" |
44 #include "SkUtils.h" | 45 #include "SkUtils.h" |
45 | 46 |
46 //#define HACK_COLORGLYPHS | 47 #include <dlfcn.h> |
47 | 48 |
48 class SkScalerContext_Mac; | 49 class SkScalerContext_Mac; |
49 | 50 |
50 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we | 51 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we |
51 // provide a wrapper here that will return an empty array if need be. | 52 // provide a wrapper here that will return an empty array if need be. |
52 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { | 53 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { |
53 #ifdef SK_BUILD_FOR_IOS | 54 #ifdef SK_BUILD_FOR_IOS |
54 return CFArrayCreate(NULL, NULL, 0, NULL); | 55 return CFArrayCreate(NULL, NULL, 0, NULL); |
55 #else | 56 #else |
56 return CTFontManagerCopyAvailableFontFamilyNames(); | 57 return CTFontManagerCopyAvailableFontFamilyNames(); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), | 267 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), |
267 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), | 268 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), |
268 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), | 269 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), |
269 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), | 270 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), |
270 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); | 271 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); |
271 } | 272 } |
272 | 273 |
273 /////////////////////////////////////////////////////////////////////////////// | 274 /////////////////////////////////////////////////////////////////////////////// |
274 | 275 |
275 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) | 276 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) |
276 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) | |
277 | 277 |
278 /** | 278 /** |
279 * There does not appear to be a publicly accessable API for determining if lcd | 279 * There does not appear to be a publicly accessable API for determining if lcd |
280 * font smoothing will be applied if we request it. The main issue is that if | 280 * font smoothing will be applied if we request it. The main issue is that if |
281 * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. | 281 * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. |
282 */ | 282 */ |
283 static bool supports_LCD() { | 283 static bool supports_LCD() { |
284 static int gSupportsLCD = -1; | 284 static int gSupportsLCD = -1; |
285 if (gSupportsLCD >= 0) { | 285 if (gSupportsLCD >= 0) { |
286 return (bool) gSupportsLCD; | 286 return (bool) gSupportsLCD; |
(...skipping 10 matching lines...) Expand all Loading... |
297 CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1); | 297 CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1); |
298 uint32_t r = (rgb >> 16) & 0xFF; | 298 uint32_t r = (rgb >> 16) & 0xFF; |
299 uint32_t g = (rgb >> 8) & 0xFF; | 299 uint32_t g = (rgb >> 8) & 0xFF; |
300 uint32_t b = (rgb >> 0) & 0xFF; | 300 uint32_t b = (rgb >> 0) & 0xFF; |
301 gSupportsLCD = (r != g || r != b); | 301 gSupportsLCD = (r != g || r != b); |
302 return (bool) gSupportsLCD; | 302 return (bool) gSupportsLCD; |
303 } | 303 } |
304 | 304 |
305 class Offscreen { | 305 class Offscreen { |
306 public: | 306 public: |
307 Offscreen(); | 307 Offscreen() |
| 308 : fRGBSpace(NULL) |
| 309 , fCG(NULL) |
| 310 , fDoAA(false) |
| 311 , fDoLCD(false) |
| 312 { |
| 313 fSize.set(0, 0); |
| 314 } |
308 | 315 |
309 CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, | 316 CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, |
310 CGGlyph glyphID, size_t* rowBytesPtr, | 317 CGGlyph glyphID, size_t* rowBytesPtr, |
311 bool generateA8FromLCD); | 318 bool generateA8FromLCD); |
312 | 319 |
313 private: | 320 private: |
314 enum { | 321 enum { |
315 kSize = 32 * 32 * sizeof(CGRGBPixel) | 322 kSize = 32 * 32 * sizeof(CGRGBPixel) |
316 }; | 323 }; |
317 SkAutoSMalloc<kSize> fImageStorage; | 324 SkAutoSMalloc<kSize> fImageStorage; |
318 AutoCFRelease<CGColorSpaceRef> fRGBSpace; | 325 AutoCFRelease<CGColorSpaceRef> fRGBSpace; |
319 | 326 |
320 // cached state | 327 // cached state |
321 AutoCFRelease<CGContextRef> fCG; | 328 AutoCFRelease<CGContextRef> fCG; |
322 SkISize fSize; | 329 SkISize fSize; |
323 bool fDoAA; | 330 bool fDoAA; |
324 bool fDoLCD; | 331 bool fDoLCD; |
325 | 332 |
326 static int RoundSize(int dimension) { | 333 static int RoundSize(int dimension) { |
327 return SkNextPow2(dimension); | 334 return SkNextPow2(dimension); |
328 } | 335 } |
329 }; | 336 }; |
330 | 337 |
331 Offscreen::Offscreen() : fRGBSpace(NULL), fCG(NULL), | |
332 fDoAA(false), fDoLCD(false) { | |
333 fSize.set(0, 0); | |
334 } | |
335 | |
336 /////////////////////////////////////////////////////////////////////////////// | 338 /////////////////////////////////////////////////////////////////////////////// |
337 | 339 |
338 static bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value
) { | 340 static bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value
) { |
339 CFNumberRef num; | 341 CFNumberRef num; |
340 return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num) | 342 return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num) |
341 && CFNumberIsFloatType(num) | 343 && CFNumberIsFloatType(num) |
342 && CFNumberGetValue(num, kCFNumberFloatType, value); | 344 && CFNumberGetValue(num, kCFNumberFloatType, value); |
343 } | 345 } |
344 | 346 |
345 static int unit_weight_to_fontstyle(float unit) { | 347 static int unit_weight_to_fontstyle(float unit) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_W
eight)/2) | 435 #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_W
eight)/2) |
434 | 436 |
435 class SkTypeface_Mac : public SkTypeface { | 437 class SkTypeface_Mac : public SkTypeface { |
436 public: | 438 public: |
437 SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch, | 439 SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch, |
438 CTFontRef fontRef, const char requestedName[], bool isLocalSt
ream) | 440 CTFontRef fontRef, const char requestedName[], bool isLocalSt
ream) |
439 : SkTypeface(fs, fontID, isFixedPitch) | 441 : SkTypeface(fs, fontID, isFixedPitch) |
440 , fRequestedName(requestedName) | 442 , fRequestedName(requestedName) |
441 , fFontRef(fontRef) // caller has already called CFRetain for us | 443 , fFontRef(fontRef) // caller has already called CFRetain for us |
442 , fIsLocalStream(isLocalStream) | 444 , fIsLocalStream(isLocalStream) |
| 445 , fHasSbixTable(false) |
443 { | 446 { |
444 SkASSERT(fontRef); | 447 SkASSERT(fontRef); |
| 448 |
| 449 AutoCFRelease<CFArrayRef> tags(CTFontCopyAvailableTables(fFontRef,kCTFon
tTableOptionNoOptions)); |
| 450 if (tags) { |
| 451 int count = SkToInt(CFArrayGetCount(tags)); |
| 452 for (int i = 0; i < count; ++i) { |
| 453 uintptr_t tag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtInd
ex(tags, i)); |
| 454 if ('sbix' == tag) { |
| 455 fHasSbixTable = true; |
| 456 break; |
| 457 } |
| 458 } |
| 459 } |
445 } | 460 } |
446 | 461 |
447 SkString fRequestedName; | 462 SkString fRequestedName; |
448 AutoCFRelease<CTFontRef> fFontRef; | 463 AutoCFRelease<CTFontRef> fFontRef; |
449 | 464 |
450 protected: | 465 protected: |
451 friend class SkFontHost; // to access our protected members for deprecate
d methods | 466 friend class SkFontHost; // to access our protected members for deprecate
d methods |
452 | 467 |
453 virtual int onGetUPEM() const SK_OVERRIDE; | 468 virtual int onGetUPEM() const SK_OVERRIDE; |
454 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; | 469 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; |
455 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE; | 470 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE; |
456 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_
OVERRIDE; | 471 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_
OVERRIDE; |
457 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; | 472 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; |
458 virtual size_t onGetTableData(SkFontTableTag, size_t offset, | 473 virtual size_t onGetTableData(SkFontTableTag, size_t offset, |
459 size_t length, void* data) const SK_OVERRIDE; | 474 size_t length, void* data) const SK_OVERRIDE; |
460 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; | 475 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; |
461 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; | 476 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; |
462 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | 477 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; |
463 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | 478 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
464 SkAdvancedTypefaceMetrics::PerGlyphInfo, | 479 SkAdvancedTypefaceMetrics::PerGlyphInfo, |
465 const uint32_t*, uint32_t) const SK_OVERRIDE; | 480 const uint32_t*, uint32_t) const SK_OVERRIDE; |
466 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], | 481 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], |
467 int glyphCount) const SK_OVERRIDE; | 482 int glyphCount) const SK_OVERRIDE; |
468 virtual int onCountGlyphs() const SK_OVERRIDE; | 483 virtual int onCountGlyphs() const SK_OVERRIDE; |
469 | 484 |
470 private: | 485 private: |
471 bool fIsLocalStream; | 486 bool fIsLocalStream; |
| 487 bool fHasSbixTable; |
472 | 488 |
473 typedef SkTypeface INHERITED; | 489 typedef SkTypeface INHERITED; |
474 }; | 490 }; |
475 | 491 |
476 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL
ocalStream) { | 492 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL
ocalStream) { |
477 SkASSERT(fontRef); | 493 SkASSERT(fontRef); |
478 bool isFixedPitch; | 494 bool isFixedPitch; |
479 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); | 495 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); |
480 SkFontID fontID = CTFontRef_to_SkFontID(fontRef); | 496 SkFontID fontID = CTFontRef_to_SkFontID(fontRef); |
481 | 497 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 | 672 |
657 /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). | 673 /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). |
658 * | 674 * |
659 * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. | 675 * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. |
660 * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. | 676 * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. |
661 */ | 677 */ |
662 SkMatrix fFUnitMatrix; | 678 SkMatrix fFUnitMatrix; |
663 | 679 |
664 Offscreen fOffscreen; | 680 Offscreen fOffscreen; |
665 AutoCFRelease<CTFontRef> fCTFont; | 681 AutoCFRelease<CTFontRef> fCTFont; |
| 682 CGAffineTransform fInvTransform; |
666 | 683 |
667 /** Vertical variant of fCTFont. | 684 /** Vertical variant of fCTFont. |
668 * | 685 * |
669 * CT vertical metrics are pre-rotated (in em space, before transform) 90de
g clock-wise. | 686 * CT vertical metrics are pre-rotated (in em space, before transform) 90de
g clock-wise. |
670 * This makes kCTFontDefaultOrientation dangerous, because the metrics from | 687 * This makes kCTFontDefaultOrientation dangerous, because the metrics from |
671 * kCTFontHorizontalOrientation are in a different space from kCTFontVertic
alOrientation. | 688 * kCTFontHorizontalOrientation are in a different space from kCTFontVertic
alOrientation. |
672 * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in th
e same space. | 689 * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in th
e same space. |
673 */ | 690 */ |
674 AutoCFRelease<CTFontRef> fCTVerticalFont; | 691 AutoCFRelease<CTFontRef> fCTVerticalFont; |
675 | 692 |
(...skipping 18 matching lines...) Expand all Loading... |
694 , fGeneratedFBoundingBoxes(false) | 711 , fGeneratedFBoundingBoxes(false) |
695 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) | 712 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) |
696 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) | 713 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) |
697 | 714 |
698 { | 715 { |
699 CTFontRef ctFont = typeface->fFontRef.get(); | 716 CTFontRef ctFont = typeface->fFontRef.get(); |
700 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); | 717 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
701 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); | 718 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
702 fGlyphCount = SkToU16(numGlyphs); | 719 fGlyphCount = SkToU16(numGlyphs); |
703 | 720 |
| 721 // 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. |
| 723 SkVector scale; |
704 SkMatrix skTransform; | 724 SkMatrix skTransform; |
705 fRec.getSingleMatrixWithoutTextSize(&skTransform); | 725 fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &
skTransform, |
| 726 NULL, NULL, &fFUnitMatrix); |
706 CGAffineTransform transform = MatrixToCGAffineTransform(skTransform); | 727 CGAffineTransform transform = MatrixToCGAffineTransform(skTransform); |
| 728 fInvTransform = CGAffineTransformInvert(transform); |
707 | 729 |
708 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; | 730 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; |
709 if (fVertical) { | 731 if (fVertical) { |
710 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( | 732 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( |
711 kCFAllocatorDefault, 0, | 733 kCFAllocatorDefault, 0, |
712 &kCFTypeDictionaryKeyCallBacks, | 734 &kCFTypeDictionaryKeyCallBacks, |
713 &kCFTypeDictionaryValueCallBacks)); | 735 &kCFTypeDictionaryValueCallBacks)); |
714 if (cfAttributes) { | 736 if (cfAttributes) { |
715 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; | 737 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; |
716 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( | 738 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( |
717 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); | 739 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); |
718 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); | 740 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); |
719 ctFontDesc.reset(CTFontDescriptorCreateWithAttributes(cfAttributes))
; | 741 ctFontDesc.reset(CTFontDescriptorCreateWithAttributes(cfAttributes))
; |
720 } | 742 } |
721 } | 743 } |
722 | 744 |
723 // The transform contains everything except the requested text size. | 745 // The transform contains everything except the requested text size. |
724 // Some properties, like 'trak', are based on the text size (before applying
the matrix). | 746 // Some properties, like 'trak', are based on the text size (before applying
the matrix). |
725 CGFloat textSize = ScalarToCG(fRec.fTextSize); | 747 CGFloat textSize = ScalarToCG(scale.y()); |
726 | |
727 // If a text size of 0 is requested, CoreGraphics will use 12 instead. | |
728 // If the text size is 0, set it to something tiny. | |
729 if (textSize < CGFLOAT_MIN) { | |
730 textSize = CGFLOAT_MIN; | |
731 } | |
732 | 748 |
733 fCTFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &transform, c
tFontDesc)); | 749 fCTFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &transform, c
tFontDesc)); |
734 fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, NULL)); | 750 fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, NULL)); |
735 if (fVertical) { | 751 if (fVertical) { |
736 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); | 752 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); |
737 transform = CGAffineTransformConcat(rotateLeft, transform); | 753 transform = CGAffineTransformConcat(rotateLeft, transform); |
738 fCTVerticalFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &
transform, NULL)); | 754 fCTVerticalFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &
transform, NULL)); |
739 } | 755 } |
740 | 756 |
741 // The fUnitMatrix includes the text size (and em) as it is used to scale th
e raw font data. | 757 // The fUnitMatrix includes the text size (and em) as it is used to scale th
e raw font data. |
742 fRec.getSingleMatrix(&fFUnitMatrix); | |
743 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFo
nt))); | 758 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFo
nt))); |
744 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); | 759 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); |
745 } | 760 } |
746 | 761 |
| 762 extern "C" { |
| 763 |
| 764 /** CTFontDrawGlyphs was introduced in 10.7. */ |
| 765 typedef void (*CTFontDrawGlyphsProc)(CTFontRef, const CGGlyph[], const CGPoint[]
, |
| 766 size_t, CGContextRef); |
| 767 |
| 768 /** This is an implementation of CTFontDrawGlyphs for 10.6. */ |
| 769 static void sk_legacy_CTFontDrawGlyphs(CTFontRef, const CGGlyph glyphs[], const
CGPoint points[], |
| 770 size_t count, CGContextRef cg) |
| 771 { |
| 772 CGContextShowGlyphsAtPositions(cg, glyphs, points, count); |
| 773 } |
| 774 |
| 775 } |
| 776 |
| 777 CTFontDrawGlyphsProc SkChooseCTFontDrawGlyphs() { |
| 778 CTFontDrawGlyphsProc realCTFontDrawGlyphs; |
| 779 *reinterpret_cast<void**>(&realCTFontDrawGlyphs) = dlsym(RTLD_DEFAULT, "CTFo
ntDrawGlyphs"); |
| 780 return realCTFontDrawGlyphs ? realCTFontDrawGlyphs : sk_legacy_CTFontDrawGly
phs; |
| 781 }; |
| 782 |
| 783 SK_DECLARE_STATIC_LAZY_FN_PTR(CTFontDrawGlyphsProc, gCTFontDrawGlyphs, SkChooseC
TFontDrawGlyphs); |
| 784 |
747 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, | 785 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, |
748 CGGlyph glyphID, size_t* rowBytesPtr, | 786 CGGlyph glyphID, size_t* rowBytesPtr, |
749 bool generateA8FromLCD) { | 787 bool generateA8FromLCD) |
| 788 { |
| 789 CTFontDrawGlyphsProc ctFontDrawGlyphs = gCTFontDrawGlyphs.get(); |
| 790 |
750 if (!fRGBSpace) { | 791 if (!fRGBSpace) { |
751 //It doesn't appear to matter what color space is specified. | 792 //It doesn't appear to matter what color space is specified. |
752 //Regular blends and antialiased text are always (s*a + d*(1-a)) | 793 //Regular blends and antialiased text are always (s*a + d*(1-a)) |
753 //and smoothed text is always g=2.0. | 794 //and smoothed text is always g=2.0. |
754 fRGBSpace.reset(CGColorSpaceCreateDeviceRGB()); | 795 fRGBSpace.reset(CGColorSpaceCreateDeviceRGB()); |
755 } | 796 } |
756 | 797 |
757 // default to kBW_Format | 798 // default to kBW_Format |
758 bool doAA = false; | 799 bool doAA = false; |
759 bool doLCD = false; | 800 bool doLCD = false; |
760 | 801 |
761 if (SkMask::kBW_Format != glyph.fMaskFormat) { | 802 if (SkMask::kBW_Format != glyph.fMaskFormat) { |
762 doLCD = true; | 803 doLCD = true; |
763 doAA = true; | 804 doAA = true; |
764 } | 805 } |
765 | 806 |
766 // FIXME: lcd smoothed un-hinted rasterization unsupported. | 807 // FIXME: lcd smoothed un-hinted rasterization unsupported. |
767 if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { | 808 if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { |
768 doLCD = false; | 809 doLCD = false; |
769 doAA = true; | 810 doAA = true; |
770 } | 811 } |
771 | 812 |
| 813 // If this font might have color glyphs, disable LCD as there's no way to su
pport it. |
| 814 // CoreText doesn't tell us which format it ended up using, so we can't dete
ct it. |
| 815 // A8 will be ugly too (white on transparent), but TODO: we can detect gray
and set to A8. |
| 816 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
| 817 doLCD = false; |
| 818 } |
| 819 |
772 size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); | 820 size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); |
773 if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { | 821 if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { |
774 if (fSize.fWidth < glyph.fWidth) { | 822 if (fSize.fWidth < glyph.fWidth) { |
775 fSize.fWidth = RoundSize(glyph.fWidth); | 823 fSize.fWidth = RoundSize(glyph.fWidth); |
776 } | 824 } |
777 if (fSize.fHeight < glyph.fHeight) { | 825 if (fSize.fHeight < glyph.fHeight) { |
778 fSize.fHeight = RoundSize(glyph.fHeight); | 826 fSize.fHeight = RoundSize(glyph.fHeight); |
779 } | 827 } |
780 | 828 |
781 rowBytes = fSize.fWidth * sizeof(CGRGBPixel); | 829 rowBytes = fSize.fWidth * sizeof(CGRGBPixel); |
782 void* image = fImageStorage.reset(rowBytes * fSize.fHeight); | 830 void* image = fImageStorage.reset(rowBytes * fSize.fHeight); |
| 831 const CGImageAlphaInfo alpha = (SkMask::kARGB32_Format == glyph.fMaskFor
mat) |
| 832 ? kCGImageAlphaPremultipliedFirst |
| 833 : kCGImageAlphaNoneSkipFirst; |
| 834 const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha; |
783 fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, | 835 fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, |
784 rowBytes, fRGBSpace, BITMAP_INFO_RGB)); | 836 rowBytes, fRGBSpace, bitmapInfo)); |
785 | 837 |
786 // skia handles quantization itself, so we disable this for cg to get | 838 // Skia handles quantization and subpixel positioning, |
787 // full fractional data from them. | 839 // so disable quantization and enabe subpixel positioning in CG. |
788 CGContextSetAllowsFontSubpixelQuantization(fCG, false); | 840 CGContextSetAllowsFontSubpixelQuantization(fCG, false); |
789 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); | 841 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); |
790 | 842 |
791 CGContextSetTextDrawingMode(fCG, kCGTextFill); | |
792 CGContextSetFont(fCG, context.fCGFont); | |
793 CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); | |
794 CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); | |
795 | |
796 // Because CG always draws from the horizontal baseline, | 843 // Because CG always draws from the horizontal baseline, |
797 // if there is a non-integral translation from the horizontal origin to
the vertical origin, | 844 // if there is a non-integral translation from the horizontal origin to
the vertical origin, |
798 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. | 845 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. |
799 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition ||
context.fVertical); | 846 CGContextSetAllowsFontSubpixelPositioning(fCG, true); |
800 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || c
ontext.fVertical); | 847 CGContextSetShouldSubpixelPositionFonts(fCG, true); |
| 848 |
| 849 CGContextSetTextDrawingMode(fCG, kCGTextFill); |
801 | 850 |
802 // Draw white on black to create mask. | 851 // Draw white on black to create mask. |
803 // TODO: Draw black on white and invert, CG has a special case codepath. | 852 // TODO: Draw black on white and invert, CG has a special case codepath. |
804 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); | 853 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); |
805 | 854 |
806 // force our checks below to happen | 855 // force our checks below to happen |
807 fDoAA = !doAA; | 856 fDoAA = !doAA; |
808 fDoLCD = !doLCD; | 857 fDoLCD = !doLCD; |
| 858 |
| 859 if (sk_legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) { |
| 860 // CTFontDrawGlyphs will apply the font, font size, and font matrix
to the CGContext. |
| 861 // Our 'fake' one does not, so set up the CGContext here. |
| 862 CGContextSetFont(fCG, context.fCGFont); |
| 863 CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); |
| 864 CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); |
| 865 } |
809 } | 866 } |
810 | 867 |
811 if (fDoAA != doAA) { | 868 if (fDoAA != doAA) { |
812 CGContextSetShouldAntialias(fCG, doAA); | 869 CGContextSetShouldAntialias(fCG, doAA); |
813 fDoAA = doAA; | 870 fDoAA = doAA; |
814 } | 871 } |
815 if (fDoLCD != doLCD) { | 872 if (fDoLCD != doLCD) { |
816 CGContextSetShouldSmoothFonts(fCG, doLCD); | 873 CGContextSetShouldSmoothFonts(fCG, doLCD); |
817 fDoLCD = doLCD; | 874 fDoLCD = doLCD; |
818 } | 875 } |
819 | 876 |
820 CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); | 877 CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); |
821 // skip rows based on the glyph's height | 878 // skip rows based on the glyph's height |
822 image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; | 879 image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; |
823 | 880 |
824 // erase to black | 881 // erase to black |
825 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); | 882 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); |
826 | 883 |
827 float subX = 0; | 884 float subX = 0; |
828 float subY = 0; | 885 float subY = 0; |
829 if (context.fDoSubPosition) { | 886 if (context.fDoSubPosition) { |
830 subX = SkFixedToFloat(glyph.getSubXFixed()); | 887 subX = SkFixedToFloat(glyph.getSubXFixed()); |
831 subY = SkFixedToFloat(glyph.getSubYFixed()); | 888 subY = SkFixedToFloat(glyph.getSubYFixed()); |
832 } | 889 } |
833 | 890 |
834 // CGContextShowGlyphsAtPoint always draws using the horizontal baseline ori
gin. | 891 // CoreText and CoreGraphics always draw using the horizontal baseline origi
n. |
835 if (context.fVertical) { | 892 if (context.fVertical) { |
836 SkPoint offset; | 893 SkPoint offset; |
837 context.getVerticalOffset(glyphID, &offset); | 894 context.getVerticalOffset(glyphID, &offset); |
838 subX += offset.fX; | 895 subX += offset.fX; |
839 subY += offset.fY; | 896 subY += offset.fY; |
840 } | 897 } |
841 | 898 |
842 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, | 899 // CTFontDrawGlyphs and CGContextShowGlyphsAtPositions take 'positions' whic
h are in text space. |
843 glyph.fTop + glyph.fHeight - subY, | 900 // The glyph location (in device space) must be mapped into text space, so t
hat CG can convert |
844 &glyphID, 1); | 901 // it back into device space. |
| 902 CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight
- subY); |
| 903 point = CGPointApplyAffineTransform(point, context.fInvTransform); |
| 904 ctFontDrawGlyphs(context.fCTFont, &glyphID, &point, 1, fCG); |
845 | 905 |
846 SkASSERT(rowBytesPtr); | 906 SkASSERT(rowBytesPtr); |
847 *rowBytesPtr = rowBytes; | 907 *rowBytesPtr = rowBytes; |
848 return image; | 908 return image; |
849 } | 909 } |
850 | 910 |
851 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
nst { | 911 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
nst { |
852 // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em
space, y up). | 912 // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em
space, y up). |
853 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). | 913 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). |
854 CGSize cgVertOffset; | 914 CGSize cgVertOffset; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 skBounds.roundOut(&skIBounds); | 1098 skBounds.roundOut(&skIBounds); |
1039 // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. | 1099 // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. |
1040 // Note that this outset is to allow room for LCD smoothed glyphs. However,
the correct outset | 1100 // Note that this outset is to allow room for LCD smoothed glyphs. However,
the correct outset |
1041 // is not currently known, as CG dilates the outlines by some percentage. | 1101 // is not currently known, as CG dilates the outlines by some percentage. |
1042 // Note that if this context is A8 and not back-forming from LCD, there is n
o need to outset. | 1102 // Note that if this context is A8 and not back-forming from LCD, there is n
o need to outset. |
1043 skIBounds.outset(1, 1); | 1103 skIBounds.outset(1, 1); |
1044 glyph->fLeft = SkToS16(skIBounds.fLeft); | 1104 glyph->fLeft = SkToS16(skIBounds.fLeft); |
1045 glyph->fTop = SkToS16(skIBounds.fTop); | 1105 glyph->fTop = SkToS16(skIBounds.fTop); |
1046 glyph->fWidth = SkToU16(skIBounds.width()); | 1106 glyph->fWidth = SkToU16(skIBounds.width()); |
1047 glyph->fHeight = SkToU16(skIBounds.height()); | 1107 glyph->fHeight = SkToU16(skIBounds.height()); |
1048 | |
1049 #ifdef HACK_COLORGLYPHS | |
1050 glyph->fMaskFormat = SkMask::kARGB32_Format; | |
1051 #endif | |
1052 } | 1108 } |
1053 | 1109 |
1054 #include "SkColorPriv.h" | 1110 #include "SkColorPriv.h" |
1055 | 1111 |
1056 static void build_power_table(uint8_t table[], float ee) { | 1112 static void build_power_table(uint8_t table[], float ee) { |
1057 for (int i = 0; i < 256; i++) { | 1113 for (int i = 0; i < 256; i++) { |
1058 float x = i / 255.f; | 1114 float x = i / 255.f; |
1059 x = sk_float_pow(x, ee); | 1115 x = sk_float_pow(x, ee); |
1060 int xx = SkScalarRoundToInt(x * 255); | 1116 int xx = SkScalarRoundToInt(x * 255); |
1061 table[i] = SkToU8(xx); | 1117 table[i] = SkToU8(xx); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 | 1189 |
1134 for (int y = 0; y < glyph.fHeight; y++) { | 1190 for (int y = 0; y < glyph.fHeight; y++) { |
1135 for (int i = 0; i < width; i++) { | 1191 for (int i = 0; i < width; i++) { |
1136 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, t
ableB); | 1192 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, t
ableB); |
1137 } | 1193 } |
1138 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); | 1194 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); |
1139 dst = (uint16_t*)((char*)dst + dstRB); | 1195 dst = (uint16_t*)((char*)dst + dstRB); |
1140 } | 1196 } |
1141 } | 1197 } |
1142 | 1198 |
1143 #ifdef HACK_COLORGLYPHS | 1199 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) { |
1144 // hack to colorize the output for testing kARGB32_Format | 1200 U8CPU a = (rgb >> 24) & 0xFF; |
1145 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb, const SkGlyph& glyph, | |
1146 int x, int y) { | |
1147 U8CPU r = (rgb >> 16) & 0xFF; | 1201 U8CPU r = (rgb >> 16) & 0xFF; |
1148 U8CPU g = (rgb >> 8) & 0xFF; | 1202 U8CPU g = (rgb >> 8) & 0xFF; |
1149 U8CPU b = (rgb >> 0) & 0xFF; | 1203 U8CPU b = (rgb >> 0) & 0xFF; |
1150 unsigned a = SkComputeLuminance(r, g, b); | |
1151 | 1204 |
1152 // compute gradient from x,y | 1205 return SkPackARGB32(a, r, g, b); |
1153 r = x * 255 / glyph.fWidth; | |
1154 g = 0; | |
1155 b = (glyph.fHeight - y) * 255 / glyph.fHeight; | |
1156 return SkPreMultiplyARGB(a, r, g, b); // red | |
1157 } | 1206 } |
1158 #endif | |
1159 | 1207 |
1160 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { | 1208 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { |
1161 return (T*)((char*)ptr + byteOffset); | 1209 return (T*)((char*)ptr + byteOffset); |
1162 } | 1210 } |
1163 | 1211 |
1164 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { | 1212 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { |
1165 CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); | 1213 CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); |
1166 | 1214 |
1167 // FIXME: lcd smoothed un-hinted rasterization unsupported. | 1215 // FIXME: lcd smoothed un-hinted rasterization unsupported. |
1168 bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; | 1216 bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 case SkMask::kBW_Format: { | 1269 case SkMask::kBW_Format: { |
1222 const int width = glyph.fWidth; | 1270 const int width = glyph.fWidth; |
1223 size_t dstRB = glyph.rowBytes(); | 1271 size_t dstRB = glyph.rowBytes(); |
1224 uint8_t* dst = (uint8_t*)glyph.fImage; | 1272 uint8_t* dst = (uint8_t*)glyph.fImage; |
1225 for (int y = 0; y < glyph.fHeight; y++) { | 1273 for (int y = 0; y < glyph.fHeight; y++) { |
1226 cgpixels_to_bits(dst, cgPixels, width); | 1274 cgpixels_to_bits(dst, cgPixels, width); |
1227 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); | 1275 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); |
1228 dst += dstRB; | 1276 dst += dstRB; |
1229 } | 1277 } |
1230 } break; | 1278 } break; |
1231 #ifdef HACK_COLORGLYPHS | |
1232 case SkMask::kARGB32_Format: { | 1279 case SkMask::kARGB32_Format: { |
1233 const int width = glyph.fWidth; | 1280 const int width = glyph.fWidth; |
1234 size_t dstRB = glyph.rowBytes(); | 1281 size_t dstRB = glyph.rowBytes(); |
1235 SkPMColor* dst = (SkPMColor*)glyph.fImage; | 1282 SkPMColor* dst = (SkPMColor*)glyph.fImage; |
1236 for (int y = 0; y < glyph.fHeight; y++) { | 1283 for (int y = 0; y < glyph.fHeight; y++) { |
1237 for (int x = 0; x < width; ++x) { | 1284 for (int x = 0; x < width; ++x) { |
1238 dst[x] = cgpixels_to_pmcolor(cgPixels[x], glyph, x, y); | 1285 dst[x] = cgpixels_to_pmcolor(cgPixels[x]); |
1239 } | 1286 } |
1240 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); | 1287 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); |
1241 dst = (SkPMColor*)((char*)dst + dstRB); | 1288 dst = (SkPMColor*)((char*)dst + dstRB); |
1242 } | 1289 } |
1243 } break; | 1290 } break; |
1244 #endif | |
1245 default: | 1291 default: |
1246 SkDEBUGFAIL("unexpected mask format"); | 1292 SkDEBUGFAIL("unexpected mask format"); |
1247 break; | 1293 break; |
1248 } | 1294 } |
1249 } | 1295 } |
1250 | 1296 |
1251 /* | 1297 /* |
1252 * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 | 1298 * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 |
1253 * seems sufficient, and possibly even correct, to allow the hinted outline | 1299 * seems sufficient, and possibly even correct, to allow the hinted outline |
1254 * to be subpixel positioned. | 1300 * to be subpixel positioned. |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 if (isLCDFormat(rec->fMaskFormat)) { | 1867 if (isLCDFormat(rec->fMaskFormat)) { |
1822 if (lcdSupport) { | 1868 if (lcdSupport) { |
1823 //CoreGraphics creates 555 masks for smoothed text anyway. | 1869 //CoreGraphics creates 555 masks for smoothed text anyway. |
1824 rec->fMaskFormat = SkMask::kLCD16_Format; | 1870 rec->fMaskFormat = SkMask::kLCD16_Format; |
1825 rec->setHinting(SkPaint::kNormal_Hinting); | 1871 rec->setHinting(SkPaint::kNormal_Hinting); |
1826 } else { | 1872 } else { |
1827 rec->fMaskFormat = SkMask::kA8_Format; | 1873 rec->fMaskFormat = SkMask::kA8_Format; |
1828 } | 1874 } |
1829 } | 1875 } |
1830 | 1876 |
| 1877 // CoreText provides no information as to whether a glyph will be color or n
ot. |
| 1878 // Fonts may mix outlines and bitmaps, so information is needed on a glyph b
y glyph basis. |
| 1879 // If a font contains an 'sbix' table, consider it to be a color font, and d
isable lcd. |
| 1880 if (fHasSbixTable) { |
| 1881 rec->fMaskFormat = SkMask::kARGB32_Format; |
| 1882 } |
| 1883 |
1831 // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMM
A_APPLY_TO_A8. | 1884 // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMM
A_APPLY_TO_A8. |
1832 // All other masks can use regular gamma. | 1885 // All other masks can use regular gamma. |
1833 if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hintin
g) { | 1886 if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hintin
g) { |
1834 #ifndef SK_GAMMA_APPLY_TO_A8 | 1887 #ifndef SK_GAMMA_APPLY_TO_A8 |
1835 rec->ignorePreBlend(); | 1888 rec->ignorePreBlend(); |
1836 #endif | 1889 #endif |
1837 } else { | 1890 } else { |
1838 //CoreGraphics dialates smoothed text as needed. | 1891 //CoreGraphics dialates smoothed text as needed. |
1839 rec->setContrast(0); | 1892 rec->setContrast(0); |
1840 } | 1893 } |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2211 } | 2264 } |
2212 return face; | 2265 return face; |
2213 } | 2266 } |
2214 }; | 2267 }; |
2215 | 2268 |
2216 /////////////////////////////////////////////////////////////////////////////// | 2269 /////////////////////////////////////////////////////////////////////////////// |
2217 | 2270 |
2218 SkFontMgr* SkFontMgr::Factory() { | 2271 SkFontMgr* SkFontMgr::Factory() { |
2219 return SkNEW(SkFontMgr_Mac); | 2272 return SkNEW(SkFontMgr_Mac); |
2220 } | 2273 } |
OLD | NEW |