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