| 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 |