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