• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #include "include/core/SkColor.h"
3 #include "include/core/SkFontStyle.h"
4 #include "modules/skparagraph/include/TextStyle.h"
5 #include "modules/skparagraph/src/Run.h"
6 
7 namespace skia {
8 namespace textlayout {
9 
10 #ifdef OHOS_SUPPORT
11 struct SkStringHash {
operator ()skia::textlayout::SkStringHash12     size_t operator()(const SkString& s) const {
13         size_t hash = 0;
14         for (size_t i = 0; i < s.size(); ++i) {
15             hash ^= std::hash<char>()(s.c_str()[i]);
16         }
17         return hash;
18     }
19 };
20 
21 const std::unordered_map<SkString, SkString, SkStringHash> GENERIC_FAMILY_NAME_MAP = {
22     { SkString{"HarmonyOS Sans"}, SkString{"HarmonyOS-Sans"} },
23     { SkString{"HarmonyOS Sans Condensed"}, SkString{"HarmonyOS-Sans-Condensed"} },
24     { SkString{"HarmonyOS Sans Digit"}, SkString{"HarmonyOS-Sans-Digit"} },
25     { SkString{"Noto Serif"}, SkString{"serif"} },
26     { SkString{"Noto Sans Mono"}, SkString{"monospace"} }
27 };
28 #endif
29 
30 const std::vector<SkString>* TextStyle::kDefaultFontFamilies =
31         new std::vector<SkString>{SkString(DEFAULT_FONT_FAMILY)};
32 
cloneForPlaceholder()33 TextStyle TextStyle::cloneForPlaceholder() {
34     TextStyle result;
35     result.fColor = fColor;
36     result.fFontSize = fFontSize;
37     result.fFontFamilies = fFontFamilies;
38     result.fDecoration = fDecoration;
39     result.fHasBackground = fHasBackground;
40     result.fHasForeground = fHasForeground;
41     result.fBackground = fBackground;
42     result.fForeground = fForeground;
43     result.fHeightOverride = fHeightOverride;
44     result.fIsPlaceholder = true;
45     result.fFontFeatures = fFontFeatures;
46     result.fHalfLeading = fHalfLeading;
47     result.fBaselineShift = fBaselineShift;
48     result.fFontArguments = fFontArguments;
49     result.fBackgroundRect = fBackgroundRect;
50     result.fStyleId = fStyleId;
51     return result;
52 }
53 
equals(const TextStyle & other) const54 bool TextStyle::equals(const TextStyle& other) const {
55 
56     if (fIsPlaceholder || other.fIsPlaceholder) {
57         return false;
58     }
59 
60     if (fColor != other.fColor) {
61         return false;
62     }
63     if (!(fDecoration == other.fDecoration)) {
64         return false;
65     }
66     if (!(fFontStyle == other.fFontStyle)) {
67         return false;
68     }
69     if (fFontFamilies != other.fFontFamilies) {
70         return false;
71     }
72     if (fLetterSpacing != other.fLetterSpacing) {
73         return false;
74     }
75     if (fWordSpacing != other.fWordSpacing) {
76         return false;
77     }
78     if (fHeight != other.fHeight) {
79         return false;
80     }
81     if (fHeightOverride != other.fHeightOverride) {
82         return false;
83     }
84     if (fHalfLeading != other.fHalfLeading) {
85         return false;
86     }
87     if (fBaselineShift != other.fBaselineShift) {
88         return false;
89     }
90     if (fFontSize != other.fFontSize) {
91         return false;
92     }
93     if (fLocale != other.fLocale) {
94         return false;
95     }
96     if (fHasForeground != other.fHasForeground || fForeground != other.fForeground) {
97         return false;
98     }
99     if (fHasBackground != other.fHasBackground || fBackground != other.fBackground) {
100         return false;
101     }
102     if (fTextShadows.size() != other.fTextShadows.size()) {
103         return false;
104     }
105     for (size_t i = 0; i < fTextShadows.size(); ++i) {
106         if (fTextShadows[i] != other.fTextShadows[i]) {
107             return false;
108         }
109     }
110     if (fFontFeatures.size() != other.fFontFeatures.size()) {
111         return false;
112     }
113     for (size_t i = 0; i < fFontFeatures.size(); ++i) {
114         if (!(fFontFeatures[i] == other.fFontFeatures[i])) {
115             return false;
116         }
117     }
118     if (fFontArguments != other.fFontArguments) {
119         return false;
120     }
121     if (fStyleId != other.fStyleId || fBackgroundRect != other.fBackgroundRect) {
122         return false;
123     }
124 
125     return true;
126 }
127 
equalsByFonts(const TextStyle & that) const128 bool TextStyle::equalsByFonts(const TextStyle& that) const {
129 
130     return !fIsPlaceholder && !that.fIsPlaceholder &&
131            fFontStyle == that.fFontStyle &&
132            fFontFamilies == that.fFontFamilies &&
133            fFontFeatures == that.fFontFeatures &&
134            fFontArguments == that.getFontArguments() &&
135            nearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
136            nearlyEqual(fWordSpacing, that.fWordSpacing) &&
137            nearlyEqual(fHeight, that.fHeight) &&
138            nearlyEqual(fBaselineShift, that.fBaselineShift) &&
139            nearlyEqual(fFontSize, that.fFontSize) &&
140            fLocale == that.fLocale &&
141            fStyleId == that.fStyleId &&
142            fBackgroundRect == that.fBackgroundRect;
143 }
144 
matchOneAttribute(StyleType styleType,const TextStyle & other) const145 bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) const {
146     switch (styleType) {
147         case kForeground:
148             return (!fHasForeground && !other.fHasForeground && fColor == other.fColor) ||
149                    ( fHasForeground &&  other.fHasForeground && fForeground == other.fForeground);
150 
151         case kBackground:
152             return (!fHasBackground && !other.fHasBackground) ||
153                    ( fHasBackground &&  other.fHasBackground && fBackground == other.fBackground);
154 
155         case kShadow:
156             if (fTextShadows.size() != other.fTextShadows.size()) {
157                 return false;
158             }
159 
160             for (int32_t i = 0; i < SkToInt(fTextShadows.size()); ++i) {
161                 if (fTextShadows[i] != other.fTextShadows[i]) {
162                     return false;
163                 }
164             }
165             return true;
166 
167         case kDecorations:
168             return this->fDecoration == other.fDecoration;
169 
170         case kLetterSpacing:
171             return fLetterSpacing == other.fLetterSpacing;
172 
173         case kWordSpacing:
174             return fWordSpacing == other.fWordSpacing;
175 
176         case kAllAttributes:
177             return this->equals(other);
178 
179         case kFont:
180             // TODO: should not we take typefaces in account?
181             return fFontStyle == other.fFontStyle &&
182                    fLocale == other.fLocale &&
183                    fFontFamilies == other.fFontFamilies &&
184                    fFontSize == other.fFontSize &&
185                    fHeight == other.fHeight &&
186                    fHalfLeading == other.fHalfLeading &&
187                    fBaselineShift == other.fBaselineShift &&
188                    fFontArguments == other.fFontArguments &&
189                    fStyleId == other.fStyleId &&
190                    fBackgroundRect == other.fBackgroundRect;
191         default:
192             SkASSERT(false);
193             return false;
194     }
195 }
196 
197 #ifndef USE_SKIA_TXT
getFontMetrics(SkFontMetrics * metrics) const198 void TextStyle::getFontMetrics(SkFontMetrics* metrics) const {
199 #else
200 void TextStyle::getFontMetrics(RSFontMetrics* metrics) const {
201 #endif
202 #ifndef USE_SKIA_TXT
203     SkFont font(fTypeface, fFontSize);
204     font.setEdging(SkFont::Edging::kAntiAlias);
205     font.setSubpixel(true);
206     font.setHinting(SkFontHinting::kSlight);
207 #ifdef OHOS_SUPPORT
208     auto compressFont = font;
209     scaleFontWithCompressionConfig(compressFont, ScaleOP::COMPRESS);
210     compressFont.getMetrics(metrics);
211     metricsIncludeFontPadding(metrics, font);
212 #else
213     font.getMetrics(metrics);
214 #endif
215 #else
216     RSFont font(fTypeface, fFontSize, 1, 0);
217     font.SetEdging(RSDrawing::FontEdging::ANTI_ALIAS);
218     font.SetHinting(RSDrawing::FontHinting::SLIGHT);
219     font.SetSubpixel(true);
220 #ifdef OHOS_SUPPORT
221     auto compressFont = font;
222     scaleFontWithCompressionConfig(compressFont, ScaleOP::COMPRESS);
223     compressFont.GetMetrics(metrics);
224     metricsIncludeFontPadding(metrics, font);
225 #else
226     font.GetMetrics(metrics);
227 #endif
228 #endif
229     if (fHeightOverride) {
230         auto multiplier = fHeight * fFontSize;
231         auto height = metrics->fDescent - metrics->fAscent + metrics->fLeading;
232         metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2) * multiplier / height;
233         metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2) * multiplier / height;
234 
235     } else {
236         metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2);
237         metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2);
238     }
239     // If we shift the baseline we need to make sure the shifted text fits the line
240     metrics->fAscent += fBaselineShift;
241     metrics->fDescent += fBaselineShift;
242 }
243 
244 void TextStyle::setFontArguments(const std::optional<SkFontArguments>& args) {
245     if (!args) {
246         fFontArguments.reset();
247         return;
248     }
249 
250     fFontArguments.emplace(*args);
251 }
252 
253 bool PlaceholderStyle::equals(const PlaceholderStyle& other) const {
254     return nearlyEqual(fWidth, other.fWidth) &&
255            nearlyEqual(fHeight, other.fHeight) &&
256            fAlignment == other.fAlignment &&
257            fBaseline == other.fBaseline &&
258            (fAlignment != PlaceholderAlignment::kBaseline ||
259             nearlyEqual(fBaselineOffset, other.fBaselineOffset));
260 }
261 
262 #ifdef OHOS_SUPPORT
263 void TextStyle::setFontFamilies(std::vector<SkString> families) {
264     std::for_each(families.begin(), families.end(), [](SkString& familyName) {
265         if (GENERIC_FAMILY_NAME_MAP.count(familyName)) {
266             familyName = GENERIC_FAMILY_NAME_MAP.at(familyName);
267         }
268     });
269     fFontFamilies = std::move(families);
270 }
271 #endif
272 
273 }  // namespace textlayout
274 }  // namespace skia
275