Index: src/ports/SkFontConfigInterface_direct.cpp |
diff --git a/src/ports/SkFontConfigInterface_direct.cpp b/src/ports/SkFontConfigInterface_direct.cpp |
index f5f494986bab87dcdd5e73b833a03ca54189d09d..1c42e2d37e7585678c8e28be47dcb56980a67d60 100644 |
--- a/src/ports/SkFontConfigInterface_direct.cpp |
+++ b/src/ports/SkFontConfigInterface_direct.cpp |
@@ -9,6 +9,7 @@ |
#include "SkBuffer.h" |
#include "SkDataTable.h" |
+#include "SkFixed.h" |
#include "SkFontConfigInterface_direct.h" |
#include "SkFontStyle.h" |
#include "SkMutex.h" |
@@ -304,6 +305,7 @@ bool IsFallbackFontAllowed(const SkString& family) { |
} |
// Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. |
+#ifdef SK_VERY_LEGACY_CREATE_TYPEFACE |
SkTypeface::Style GetFontStyle(FcPattern* font) { |
int resulting_bold; |
if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) |
@@ -335,6 +337,136 @@ SkTypeface::Style GetFontStyle(FcPattern* font) { |
return (SkTypeface::Style)styleBits; |
} |
+#else |
+ |
+static int get_int(FcPattern* pattern, const char object[], int missing) { |
+ int value; |
+ if (FcPatternGetInteger(pattern, object, 0, &value) != FcResultMatch) { |
+ return missing; |
+ } |
+ return value; |
+} |
+ |
+static int map_range(SkFixed value, |
+ SkFixed old_min, SkFixed old_max, |
+ SkFixed new_min, SkFixed new_max) |
+{ |
+ SkASSERT(old_min < old_max); |
+ SkASSERT(new_min <= new_max); |
+ return new_min + SkMulDiv(value - old_min, new_max - new_min, old_max - old_min); |
+} |
+ |
+struct MapRanges { |
+ SkFixed old_val; |
+ SkFixed new_val; |
+}; |
+ |
+static SkFixed map_ranges_fixed(SkFixed val, MapRanges const ranges[], int rangesCount) { |
+ // -Inf to [0] |
+ if (val < ranges[0].old_val) { |
+ return ranges[0].new_val; |
+ } |
+ |
+ // Linear from [i] to [i+1] |
+ for (int i = 0; i < rangesCount - 1; ++i) { |
+ if (val < ranges[i+1].old_val) { |
+ return map_range(val, ranges[i].old_val, ranges[i+1].old_val, |
+ ranges[i].new_val, ranges[i+1].new_val); |
+ } |
+ } |
+ |
+ // From [n] to +Inf |
+ // if (fcweight < Inf) |
+ return ranges[rangesCount-1].new_val; |
+} |
+ |
+static int map_ranges(int val, MapRanges const ranges[], int rangesCount) { |
+ return SkFixedRoundToInt(map_ranges_fixed(SkIntToFixed(val), ranges, rangesCount)); |
+} |
+ |
+template<int n> struct SkTFixed { |
+ static_assert(-32768 <= n && n <= 32767, "SkTFixed_n_not_in_range"); |
+ static const SkFixed value = static_cast<SkFixed>(n << 16); |
+}; |
+ |
+static SkFontStyle skfontstyle_from_fcpattern(FcPattern* pattern) { |
+ typedef SkFontStyle SkFS; |
+ |
+ static const MapRanges weightRanges[] = { |
+ { SkTFixed<FC_WEIGHT_THIN>::value, SkTFixed<SkFS::kThin_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_EXTRALIGHT>::value, SkTFixed<SkFS::kExtraLight_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_LIGHT>::value, SkTFixed<SkFS::kLight_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_REGULAR>::value, SkTFixed<SkFS::kNormal_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_MEDIUM>::value, SkTFixed<SkFS::kMedium_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_DEMIBOLD>::value, SkTFixed<SkFS::kSemiBold_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_BOLD>::value, SkTFixed<SkFS::kBold_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_EXTRABOLD>::value, SkTFixed<SkFS::kExtraBold_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_BLACK>::value, SkTFixed<SkFS::kBlack_Weight>::value }, |
+ { SkTFixed<FC_WEIGHT_EXTRABLACK>::value, SkTFixed<1000>::value }, |
+ }; |
+ int weight = map_ranges(get_int(pattern, FC_WEIGHT, FC_WEIGHT_REGULAR), |
+ weightRanges, SK_ARRAY_COUNT(weightRanges)); |
+ |
+ static const MapRanges widthRanges[] = { |
+ { SkTFixed<FC_WIDTH_ULTRACONDENSED>::value, SkTFixed<SkFS::kUltraCondensed_Width>::value }, |
+ { SkTFixed<FC_WIDTH_EXTRACONDENSED>::value, SkTFixed<SkFS::kExtraCondensed_Width>::value }, |
+ { SkTFixed<FC_WIDTH_CONDENSED>::value, SkTFixed<SkFS::kCondensed_Width>::value }, |
+ { SkTFixed<FC_WIDTH_SEMICONDENSED>::value, SkTFixed<SkFS::kSemiCondensed_Width>::value }, |
+ { SkTFixed<FC_WIDTH_NORMAL>::value, SkTFixed<SkFS::kNormal_Width>::value }, |
+ { SkTFixed<FC_WIDTH_SEMIEXPANDED>::value, SkTFixed<SkFS::kSemiExpanded_Width>::value }, |
+ { SkTFixed<FC_WIDTH_EXPANDED>::value, SkTFixed<SkFS::kExpanded_Width>::value }, |
+ { SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value, SkTFixed<SkFS::kExtraExpanded_Width>::value }, |
+ { SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value, SkTFixed<SkFS::kUltaExpanded_Width>::value }, |
+ }; |
+ int width = map_ranges(get_int(pattern, FC_WIDTH, FC_WIDTH_NORMAL), |
+ widthRanges, SK_ARRAY_COUNT(widthRanges)); |
+ |
+ SkFS::Slant slant = get_int(pattern, FC_SLANT, FC_SLANT_ROMAN) > 0 |
+ ? SkFS::kItalic_Slant |
+ : SkFS::kUpright_Slant; |
+ |
+ return SkFontStyle(weight, width, slant); |
+} |
+ |
+static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) { |
+ typedef SkFontStyle SkFS; |
+ |
+ static const MapRanges weightRanges[] = { |
+ { SkTFixed<SkFS::kThin_Weight>::value, SkTFixed<FC_WEIGHT_THIN>::value }, |
+ { SkTFixed<SkFS::kExtraLight_Weight>::value, SkTFixed<FC_WEIGHT_EXTRALIGHT>::value }, |
+ { SkTFixed<SkFS::kLight_Weight>::value, SkTFixed<FC_WEIGHT_LIGHT>::value }, |
+ { SkTFixed<SkFS::kNormal_Weight>::value, SkTFixed<FC_WEIGHT_REGULAR>::value }, |
+ { SkTFixed<SkFS::kMedium_Weight>::value, SkTFixed<FC_WEIGHT_MEDIUM>::value }, |
+ { SkTFixed<SkFS::kSemiBold_Weight>::value, SkTFixed<FC_WEIGHT_DEMIBOLD>::value }, |
+ { SkTFixed<SkFS::kBold_Weight>::value, SkTFixed<FC_WEIGHT_BOLD>::value }, |
+ { SkTFixed<SkFS::kExtraBold_Weight>::value, SkTFixed<FC_WEIGHT_EXTRABOLD>::value }, |
+ { SkTFixed<SkFS::kBlack_Weight>::value, SkTFixed<FC_WEIGHT_BLACK>::value }, |
+ { SkTFixed<1000>::value, SkTFixed<FC_WEIGHT_EXTRABLACK>::value }, |
+ }; |
+ int weight = map_ranges(style.weight(), weightRanges, SK_ARRAY_COUNT(weightRanges)); |
+ |
+ static const MapRanges widthRanges[] = { |
+ { SkTFixed<SkFS::kUltraCondensed_Width>::value, SkTFixed<FC_WIDTH_ULTRACONDENSED>::value }, |
+ { SkTFixed<SkFS::kExtraCondensed_Width>::value, SkTFixed<FC_WIDTH_EXTRACONDENSED>::value }, |
+ { SkTFixed<SkFS::kCondensed_Width>::value, SkTFixed<FC_WIDTH_CONDENSED>::value }, |
+ { SkTFixed<SkFS::kSemiCondensed_Width>::value, SkTFixed<FC_WIDTH_SEMICONDENSED>::value }, |
+ { SkTFixed<SkFS::kNormal_Width>::value, SkTFixed<FC_WIDTH_NORMAL>::value }, |
+ { SkTFixed<SkFS::kSemiExpanded_Width>::value, SkTFixed<FC_WIDTH_SEMIEXPANDED>::value }, |
+ { SkTFixed<SkFS::kExpanded_Width>::value, SkTFixed<FC_WIDTH_EXPANDED>::value }, |
+ { SkTFixed<SkFS::kExtraExpanded_Width>::value, SkTFixed<FC_WIDTH_EXTRAEXPANDED>::value }, |
+ { SkTFixed<SkFS::kUltaExpanded_Width>::value, SkTFixed<FC_WIDTH_ULTRAEXPANDED>::value }, |
+ }; |
+ int width = map_ranges(style.width(), widthRanges, SK_ARRAY_COUNT(widthRanges)); |
+ |
+ FcPatternAddInteger(pattern, FC_WEIGHT, weight); |
+ FcPatternAddInteger(pattern, FC_WIDTH, width); |
+ FcPatternAddInteger(pattern, FC_SLANT, style.isItalic() ? FC_SLANT_ITALIC : FC_SLANT_ROMAN); |
+} |
+ |
+SkFontStyle GetFontStyle(FcPattern* font) { |
+ return skfontstyle_from_fcpattern(font); |
+} |
+#endif |
} // anonymous namespace |
@@ -417,11 +549,19 @@ FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set, |
return match; |
} |
+#ifdef SK_VERY_LEGACY_CREATE_TYPEFACE |
bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
SkTypeface::Style style, |
FontIdentity* outIdentity, |
SkString* outFamilyName, |
SkTypeface::Style* outStyle) { |
+#else |
+bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
+ SkFontStyle style, |
+ FontIdentity* outIdentity, |
+ SkString* outFamilyName, |
+ SkFontStyle* outStyle) { |
+#endif |
SkString familyStr(familyName ? familyName : ""); |
if (familyStr.size() > kMaxFontFamilyLength) { |
return false; |
@@ -434,12 +574,17 @@ bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
if (familyName) { |
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
} |
+#ifdef SK_VERY_LEGACY_CREATE_TYPEFACE |
FcPatternAddInteger(pattern, FC_WEIGHT, |
(style & SkTypeface::kBold) ? FC_WEIGHT_BOLD |
: FC_WEIGHT_NORMAL); |
FcPatternAddInteger(pattern, FC_SLANT, |
(style & SkTypeface::kItalic) ? FC_SLANT_ITALIC |
: FC_SLANT_ROMAN); |
+#else |
+ fcpattern_from_skfontstyle(style, pattern); |
+#endif |
+ |
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
FcConfigSubstitute(nullptr, pattern, FcMatchPattern); |