• 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 
6 namespace skia {
7 namespace textlayout {
8 
9 const std::vector<SkString>* TextStyle::kDefaultFontFamilies =
10         new std::vector<SkString>{SkString(DEFAULT_FONT_FAMILY)};
11 
cloneForPlaceholder()12 TextStyle TextStyle::cloneForPlaceholder() {
13     TextStyle result;
14     result.fColor = fColor;
15     result.fFontSize = fFontSize;
16     result.fFontFamilies = fFontFamilies;
17     result.fDecoration = fDecoration;
18     result.fHasBackground = fHasBackground;
19     result.fHasForeground = fHasForeground;
20     result.fBackground = fBackground;
21     result.fForeground = fForeground;
22     result.fHeightOverride = fHeightOverride;
23     result.fIsPlaceholder = true;
24     result.fFontFeatures = fFontFeatures;
25     result.fHalfLeading = fHalfLeading;
26     result.fBaselineShift = fBaselineShift;
27     result.fFontArguments = fFontArguments;
28     result.fBackgroundRect = fBackgroundRect;
29     result.fStyleId = fStyleId;
30     return result;
31 }
32 
equals(const TextStyle & other) const33 bool TextStyle::equals(const TextStyle& other) const {
34 
35     if (fIsPlaceholder || other.fIsPlaceholder) {
36         return false;
37     }
38 
39     if (fColor != other.fColor) {
40         return false;
41     }
42     if (!(fDecoration == other.fDecoration)) {
43         return false;
44     }
45     if (!(fFontStyle == other.fFontStyle)) {
46         return false;
47     }
48     if (fFontFamilies != other.fFontFamilies) {
49         return false;
50     }
51     if (fLetterSpacing != other.fLetterSpacing) {
52         return false;
53     }
54     if (fWordSpacing != other.fWordSpacing) {
55         return false;
56     }
57     if (fHeight != other.fHeight) {
58         return false;
59     }
60     if (fHeightOverride != other.fHeightOverride) {
61         return false;
62     }
63     if (fHalfLeading != other.fHalfLeading) {
64         return false;
65     }
66     if (fBaselineShift != other.fBaselineShift) {
67         return false;
68     }
69     if (fFontSize != other.fFontSize) {
70         return false;
71     }
72     if (fLocale != other.fLocale) {
73         return false;
74     }
75     if (fHasForeground != other.fHasForeground || fForeground != other.fForeground) {
76         return false;
77     }
78     if (fHasBackground != other.fHasBackground || fBackground != other.fBackground) {
79         return false;
80     }
81     if (fTextShadows.size() != other.fTextShadows.size()) {
82         return false;
83     }
84     for (size_t i = 0; i < fTextShadows.size(); ++i) {
85         if (fTextShadows[i] != other.fTextShadows[i]) {
86             return false;
87         }
88     }
89     if (fFontFeatures.size() != other.fFontFeatures.size()) {
90         return false;
91     }
92     for (size_t i = 0; i < fFontFeatures.size(); ++i) {
93         if (!(fFontFeatures[i] == other.fFontFeatures[i])) {
94             return false;
95         }
96     }
97     if (fFontArguments != other.fFontArguments) {
98         return false;
99     }
100 
101     return true;
102 }
103 
equalsByFonts(const TextStyle & that) const104 bool TextStyle::equalsByFonts(const TextStyle& that) const {
105 
106     return !fIsPlaceholder && !that.fIsPlaceholder &&
107            fFontStyle == that.fFontStyle &&
108            fFontFamilies == that.fFontFamilies &&
109            fFontFeatures == that.fFontFeatures &&
110            fFontArguments == that.getFontArguments() &&
111            nearlyEqual(fLetterSpacing, that.fLetterSpacing) &&
112            nearlyEqual(fWordSpacing, that.fWordSpacing) &&
113            nearlyEqual(fHeight, that.fHeight) &&
114            nearlyEqual(fBaselineShift, that.fBaselineShift) &&
115            nearlyEqual(fFontSize, that.fFontSize) &&
116            fLocale == that.fLocale;
117 }
118 
matchOneAttribute(StyleType styleType,const TextStyle & other) const119 bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) const {
120     switch (styleType) {
121         case kForeground:
122             return (!fHasForeground && !other.fHasForeground && fColor == other.fColor) ||
123                    ( fHasForeground &&  other.fHasForeground && fForeground == other.fForeground);
124 
125         case kBackground:
126             return (!fHasBackground && !other.fHasBackground) ||
127                    ( fHasBackground &&  other.fHasBackground && fBackground == other.fBackground);
128 
129         case kShadow:
130             if (fTextShadows.size() != other.fTextShadows.size()) {
131                 return false;
132             }
133 
134             for (int32_t i = 0; i < SkToInt(fTextShadows.size()); ++i) {
135                 if (fTextShadows[i] != other.fTextShadows[i]) {
136                     return false;
137                 }
138             }
139             return true;
140 
141         case kDecorations:
142             return this->fDecoration == other.fDecoration;
143 
144         case kLetterSpacing:
145             return fLetterSpacing == other.fLetterSpacing;
146 
147         case kWordSpacing:
148             return fWordSpacing == other.fWordSpacing;
149 
150         case kAllAttributes:
151             return this->equals(other);
152 
153         case kFont:
154             // TODO: should not we take typefaces in account?
155             return fFontStyle == other.fFontStyle &&
156                    fLocale == other.fLocale &&
157                    fFontFamilies == other.fFontFamilies &&
158                    fFontSize == other.fFontSize &&
159                    fHeight == other.fHeight &&
160                    fHalfLeading == other.fHalfLeading &&
161                    fBaselineShift == other.fBaselineShift &&
162                    fFontArguments == other.fFontArguments;
163         default:
164             SkASSERT(false);
165             return false;
166     }
167 }
168 
getFontMetrics(SkFontMetrics * metrics) const169 void TextStyle::getFontMetrics(SkFontMetrics* metrics) const {
170     SkFont font(fTypeface, fFontSize);
171     font.setEdging(SkFont::Edging::kAntiAlias);
172     font.setSubpixel(true);
173     font.setHinting(SkFontHinting::kSlight);
174     font.getMetrics(metrics);
175     if (fHeightOverride) {
176         auto multiplier = fHeight * fFontSize;
177         auto height = metrics->fDescent - metrics->fAscent + metrics->fLeading;
178         metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2) * multiplier / height;
179         metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2) * multiplier / height;
180 
181     } else {
182         metrics->fAscent = (metrics->fAscent - metrics->fLeading / 2);
183         metrics->fDescent = (metrics->fDescent + metrics->fLeading / 2);
184     }
185     // If we shift the baseline we need to make sure the shifted text fits the line
186     metrics->fAscent += fBaselineShift;
187     metrics->fDescent += fBaselineShift;
188 }
189 
setFontArguments(const std::optional<SkFontArguments> & args)190 void TextStyle::setFontArguments(const std::optional<SkFontArguments>& args) {
191     if (!args) {
192         fFontArguments.reset();
193         return;
194     }
195 
196     fFontArguments.emplace(*args);
197 }
198 
equals(const PlaceholderStyle & other) const199 bool PlaceholderStyle::equals(const PlaceholderStyle& other) const {
200     return nearlyEqual(fWidth, other.fWidth) &&
201            nearlyEqual(fHeight, other.fHeight) &&
202            fAlignment == other.fAlignment &&
203            fBaseline == other.fBaseline &&
204            (fAlignment != PlaceholderAlignment::kBaseline ||
205             nearlyEqual(fBaselineOffset, other.fBaselineOffset));
206 }
207 
208 }  // namespace textlayout
209 }  // namespace skia
210