diff options
author | bungeman <bungeman@google.com> | 2017-01-13 11:40:21 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-01-13 20:14:07 +0000 |
commit | 2873c767fdb6b5f785a88cf593bfee27d044fbb5 (patch) | |
tree | 2de88c2e3b0eb05b05cce9f7fcc1de173d2de9f6 /src/ports/SkFontHost_mac.cpp | |
parent | 1d8e198d75d57ec8f6dae0c1498df69cd6769cb6 (diff) |
Decode system font weight correctly on Mac.
The -1 to 1 weights reported by CTFontDescriptors have different mappings
depending on if the CTFont is native or created from a CGDataProvider.
Change-Id: I725b04a31c224a4b01c0763137fa04bb4088def7
Reviewed-on: https://skia-review.googlesource.com/6979
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
Diffstat (limited to 'src/ports/SkFontHost_mac.cpp')
-rw-r--r-- | src/ports/SkFontHost_mac.cpp | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 3e3887b4a7..3aeb0aae32 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -307,15 +307,22 @@ struct RoundCGFloatToInt { int operator()(CGFloat s) { return s + 0.5; } }; -static int ct_weight_to_fontstyle(CGFloat cgWeight) { +/** Convert the [-1, 1] CTFontDescriptor weight to [0, 1000] CSS weight. + * + * The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the + * CTFont is native or created from a CGDataProvider. + */ +static int ct_weight_to_fontstyle(CGFloat cgWeight, bool fromDataProvider) { using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>; - // Values determined by creating font data with every weight, creating a CTFont, - // and asking the CTFont for its weight. See TypefaceStyle test for basics. - // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100. - // However, on this end we can't tell. - static constexpr Interpolator::Mapping weightMappings[] = { + // However, on this end we can't tell, so this is ignored. + + /** This mapping for CGDataProvider created fonts is determined by creating font data with every + * weight, creating a CTFont, and asking the CTFont for its weight. See the TypefaceStyle test + * in tests/TypefaceTest.cpp for the code used to determine these values. + */ + static constexpr Interpolator::Mapping dataProviderWeightMappings[] = { { -1.00, 0 }, { -0.70, 100 }, { -0.50, 200 }, @@ -328,8 +335,39 @@ static int ct_weight_to_fontstyle(CGFloat cgWeight) { { 0.80, 900 }, { 1.00, 1000 }, }; - static constexpr Interpolator interpolater(weightMappings, SK_ARRAY_COUNT(weightMappings)); - return interpolater.map(cgWeight); + static constexpr Interpolator dataProviderInterpolator( + dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings)); + + /** This mapping for native fonts is determined by running the following in an .mm file + * #include <AppKit/AppKit> + * printf("{ % #.2f, 100 },\n", NSFontWeightUltraLight); + * printf("{ % #.2f, 200 },\n", NSFontWeightThin); + * printf("{ % #.2f, 300 },\n", NSFontWeightLight); + * printf("{ % #.2f, 400 },\n", NSFontWeightRegular); + * printf("{ % #.2f, 500 },\n", NSFontWeightMedium); + * printf("{ % #.2f, 600 },\n", NSFontWeightSemibold); + * printf("{ % #.2f, 700 },\n", NSFontWeightBold); + * printf("{ % #.2f, 800 },\n", NSFontWeightHeavy); + * printf("{ % #.2f, 900 },\n", NSFontWeightBlack); + */ + static constexpr Interpolator::Mapping nativeWeightMappings[] = { + { -1.00, 0 }, + { -0.80, 100 }, + { -0.60, 200 }, + { -0.40, 300 }, + { 0.00, 400 }, + { 0.23, 500 }, + { 0.30, 600 }, + { 0.40, 700 }, + { 0.56, 800 }, + { 0.62, 900 }, + { 1.00, 1000 }, + }; + static constexpr Interpolator nativeInterpolator( + nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings)); + + return fromDataProvider ? dataProviderInterpolator.map(cgWeight) + : nativeInterpolator.map(cgWeight); } static int ct_width_to_fontstyle(CGFloat cgWidth) { @@ -341,11 +379,11 @@ static int ct_width_to_fontstyle(CGFloat cgWidth) { { -0.5, 0 }, { 0.5, 10 }, }; - static constexpr Interpolator interpolater(widthMappings, SK_ARRAY_COUNT(widthMappings)); - return interpolater.map(cgWidth); + static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings)); + return interpolator.map(cgWidth); } -static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc) { +static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc, bool fromDataProvider) { UniqueCFRef<CFTypeRef> fontTraits(CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute)); if (!fontTraits || CFDictionaryGetTypeID() != CFGetTypeID(fontTraits.get())) { return SkFontStyle(); @@ -363,7 +401,7 @@ static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc) { slant = 0; } - return SkFontStyle(ct_weight_to_fontstyle(weight), + return SkFontStyle(ct_weight_to_fontstyle(weight, fromDataProvider), ct_width_to_fontstyle(width), slant ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); @@ -433,7 +471,7 @@ static SkTypeface* create_from_CTFontRef(UniqueCFRef<CTFontRef> font, } UniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get())); - SkFontStyle style = fontstyle_from_descriptor(desc.get()); + SkFontStyle style = fontstyle_from_descriptor(desc.get(), isLocalStream); CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get()); bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait); @@ -1959,7 +1997,7 @@ public: SkASSERT((unsigned)index < (unsigned)fCount); CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index); if (style) { - *style = fontstyle_from_descriptor(desc); + *style = fontstyle_from_descriptor(desc, false); } if (name) { if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) { @@ -1992,7 +2030,7 @@ private: for (int i = 0; i < fCount; ++i) { CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i); - int metric = compute_metric(pattern, fontstyle_from_descriptor(desc)); + int metric = compute_metric(pattern, fontstyle_from_descriptor(desc, false)); if (0 == metric) { return desc; } |