1 // Copyright 2019 Google LLC. 2 #ifndef TextStyle_DEFINED 3 #define TextStyle_DEFINED 4 5 #include <vector> 6 #include "include/core/SkColor.h" 7 #include "include/core/SkFont.h" 8 #include "include/core/SkFontMetrics.h" 9 #include "include/core/SkFontStyle.h" 10 #include "include/core/SkPaint.h" 11 #include "include/core/SkScalar.h" 12 #include "modules/skparagraph/include/DartTypes.h" 13 #include "modules/skparagraph/include/TextShadow.h" 14 15 // TODO: Make it external so the other platforms (Android) could use it 16 #define DEFAULT_FONT_FAMILY "sans-serif" 17 18 namespace skia { 19 namespace textlayout { 20 21 static inline bool nearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) { 22 if (SkScalarIsFinite(x)) { 23 return SkScalarNearlyZero(x, tolerance); 24 } 25 return false; 26 } 27 28 static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) { 29 if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) { 30 return SkScalarNearlyEqual(x, y, tolerance); 31 } 32 // Inf == Inf, anything else is false 33 return x == y; 34 } 35 36 // Multiple decorations can be applied at once. Ex: Underline and overline is 37 // (0x1 | 0x2) 38 enum TextDecoration { 39 kNoDecoration = 0x0, 40 kUnderline = 0x1, 41 kOverline = 0x2, 42 kLineThrough = 0x4, 43 }; 44 constexpr TextDecoration AllTextDecorations[] = { 45 kNoDecoration, 46 kUnderline, 47 kOverline, 48 kLineThrough, 49 }; 50 51 enum TextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy }; 52 53 enum StyleType { 54 kAllAttributes, 55 kFont, 56 kForeground, 57 kBackground, 58 kShadow, 59 kDecorations, 60 kLetterSpacing, 61 kWordSpacing 62 }; 63 64 struct Decoration { 65 TextDecoration fType; 66 SkColor fColor; 67 TextDecorationStyle fStyle; 68 SkScalar fThicknessMultiplier; 69 70 bool operator==(const Decoration& other) const { 71 return this->fType == other.fType && 72 this->fColor == other.fColor && 73 this->fStyle == other.fStyle && 74 this->fThicknessMultiplier == other.fThicknessMultiplier; 75 } 76 }; 77 78 /// Where to vertically align the placeholder relative to the surrounding text. 79 enum class PlaceholderAlignment { 80 /// Match the baseline of the placeholder with the baseline. 81 kBaseline, 82 83 /// Align the bottom edge of the placeholder with the baseline such that the 84 /// placeholder sits on top of the baseline. 85 kAboveBaseline, 86 87 /// Align the top edge of the placeholder with the baseline specified in 88 /// such that the placeholder hangs below the baseline. 89 kBelowBaseline, 90 91 /// Align the top edge of the placeholder with the top edge of the font. 92 /// When the placeholder is very tall, the extra space will hang from 93 /// the top and extend through the bottom of the line. 94 kTop, 95 96 /// Align the bottom edge of the placeholder with the top edge of the font. 97 /// When the placeholder is very tall, the extra space will rise from 98 /// the bottom and extend through the top of the line. 99 kBottom, 100 101 /// Align the middle of the placeholder with the middle of the text. When the 102 /// placeholder is very tall, the extra space will grow equally from 103 /// the top and bottom of the line. 104 kMiddle, 105 }; 106 107 struct FontFeature { FontFeatureFontFeature108 FontFeature(const SkString name, int value) : fName(name), fValue(value) { } FontFeatureFontFeature109 FontFeature(const FontFeature& other) : fName(other.fName), fValue(other.fValue) { } 110 bool operator==(const FontFeature& other) const { 111 return fName == other.fName && fValue == other.fValue; 112 } 113 SkString fName; 114 int fValue; 115 }; 116 117 struct PlaceholderStyle { PlaceholderStylePlaceholderStyle118 PlaceholderStyle() 119 : fWidth(0) 120 , fHeight(0) 121 , fAlignment(PlaceholderAlignment::kBaseline) 122 , fBaseline(TextBaseline::kAlphabetic) 123 , fBaselineOffset(0) {} 124 PlaceholderStylePlaceholderStyle125 PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment, 126 TextBaseline baseline, SkScalar offset) 127 : fWidth(width) 128 , fHeight(height) 129 , fAlignment(alignment) 130 , fBaseline(baseline) 131 , fBaselineOffset(offset) {} 132 133 bool equals(const PlaceholderStyle& other) const; 134 135 SkScalar fWidth; 136 SkScalar fHeight; 137 PlaceholderAlignment fAlignment; 138 TextBaseline fBaseline; 139 // Distance from the top edge of the rect to the baseline position. This 140 // baseline will be aligned against the alphabetic baseline of the surrounding 141 // text. 142 // 143 // Positive values drop the baseline lower (positions the rect higher) and 144 // small or negative values will cause the rect to be positioned underneath 145 // the line. When baseline == height, the bottom edge of the rect will rest on 146 // the alphabetic baseline. 147 SkScalar fBaselineOffset; 148 }; 149 150 class TextStyle { 151 public: 152 TextStyle(); 153 TextStyle(const TextStyle& other, bool placeholder); 154 ~TextStyle() = default; 155 156 bool equals(const TextStyle& other) const; 157 bool equalsByFonts(const TextStyle& that) const; 158 bool matchOneAttribute(StyleType styleType, const TextStyle& other) const; 159 bool operator==(const TextStyle& rhs) const { return this->equals(rhs); } 160 161 // Colors getColor()162 SkColor getColor() const { return fColor; } setColor(SkColor color)163 void setColor(SkColor color) { fColor = color; } 164 hasForeground()165 bool hasForeground() const { return fHasForeground; } getForeground()166 SkPaint getForeground() const { return fForeground; } setForegroundColor(SkPaint paint)167 void setForegroundColor(SkPaint paint) { 168 fHasForeground = true; 169 fForeground = std::move(paint); 170 } clearForegroundColor()171 void clearForegroundColor() { fHasForeground = false; } 172 hasBackground()173 bool hasBackground() const { return fHasBackground; } getBackground()174 SkPaint getBackground() const { return fBackground; } setBackgroundColor(SkPaint paint)175 void setBackgroundColor(SkPaint paint) { 176 fHasBackground = true; 177 fBackground = std::move(paint); 178 } clearBackgroundColor()179 void clearBackgroundColor() { fHasBackground = false; } 180 181 // Decorations getDecoration()182 Decoration getDecoration() const { return fDecoration; } getDecorationType()183 TextDecoration getDecorationType() const { return fDecoration.fType; } getDecorationColor()184 SkColor getDecorationColor() const { return fDecoration.fColor; } getDecorationStyle()185 TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; } getDecorationThicknessMultiplier()186 SkScalar getDecorationThicknessMultiplier() const { 187 return fDecoration.fThicknessMultiplier; 188 } setDecoration(TextDecoration decoration)189 void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; } setDecorationStyle(TextDecorationStyle style)190 void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; } setDecorationColor(SkColor color)191 void setDecorationColor(SkColor color) { fDecoration.fColor = color; } setDecorationThicknessMultiplier(SkScalar m)192 void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; } 193 194 // Weight/Width/Slant getFontStyle()195 SkFontStyle getFontStyle() const { return fFontStyle; } setFontStyle(SkFontStyle fontStyle)196 void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; } 197 198 // Shadows getShadowNumber()199 size_t getShadowNumber() const { return fTextShadows.size(); } getShadows()200 std::vector<TextShadow> getShadows() const { return fTextShadows; } addShadow(TextShadow shadow)201 void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); } resetShadows()202 void resetShadows() { fTextShadows.clear(); } 203 204 // Font features getFontFeatureNumber()205 size_t getFontFeatureNumber() const { return fFontFeatures.size(); } getFontFeatures()206 std::vector<FontFeature> getFontFeatures() const { return fFontFeatures; } addFontFeature(const SkString & fontFeature,int value)207 void addFontFeature(const SkString& fontFeature, int value) 208 { fFontFeatures.emplace_back(fontFeature, value); } resetFontFeatures()209 void resetFontFeatures() { fFontFeatures.clear(); } 210 getFontSize()211 SkScalar getFontSize() const { return fFontSize; } setFontSize(SkScalar size)212 void setFontSize(SkScalar size) { fFontSize = size; } 213 getFontFamilies()214 const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; } setFontFamilies(std::vector<SkString> families)215 void setFontFamilies(std::vector<SkString> families) { 216 fFontFamilies = std::move(families); 217 } 218 setHeight(SkScalar height)219 void setHeight(SkScalar height) { fHeight = height; } getHeight()220 SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; } 221 setHeightOverride(bool heightOverride)222 void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; } getHeightOverride()223 bool getHeightOverride() const { return fHeightOverride; } 224 setLetterSpacing(SkScalar letterSpacing)225 void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; } getLetterSpacing()226 SkScalar getLetterSpacing() const { return fLetterSpacing; } 227 setWordSpacing(SkScalar wordSpacing)228 void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; } getWordSpacing()229 SkScalar getWordSpacing() const { return fWordSpacing; } 230 getTypeface()231 SkTypeface* getTypeface() const { return fTypeface.get(); } refTypeface()232 sk_sp<SkTypeface> refTypeface() const { return fTypeface; } setTypeface(sk_sp<SkTypeface> typeface)233 void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); } 234 getLocale()235 SkString getLocale() const { return fLocale; } setLocale(const SkString & locale)236 void setLocale(const SkString& locale) { fLocale = locale; } 237 getTextBaseline()238 TextBaseline getTextBaseline() const { return fTextBaseline; } setTextBaseline(TextBaseline baseline)239 void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; } 240 241 void getFontMetrics(SkFontMetrics* metrics) const; 242 isPlaceholder()243 bool isPlaceholder() const { return fIsPlaceholder; } setPlaceholder()244 void setPlaceholder() { fIsPlaceholder = true; } 245 246 private: 247 248 Decoration fDecoration; 249 250 SkFontStyle fFontStyle; 251 252 std::vector<SkString> fFontFamilies; 253 SkScalar fFontSize; 254 SkScalar fHeight; 255 bool fHeightOverride; 256 SkString fLocale; 257 SkScalar fLetterSpacing; 258 SkScalar fWordSpacing; 259 260 TextBaseline fTextBaseline; 261 262 SkColor fColor; 263 bool fHasBackground; 264 SkPaint fBackground; 265 bool fHasForeground; 266 SkPaint fForeground; 267 268 std::vector<TextShadow> fTextShadows; 269 270 sk_sp<SkTypeface> fTypeface; 271 bool fIsPlaceholder; 272 273 std::vector<FontFeature> fFontFeatures; 274 }; 275 276 typedef size_t TextIndex; 277 typedef SkRange<size_t> TextRange; 278 const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE; 279 280 281 struct Block { BlockBlock282 Block() : fRange(EMPTY_RANGE), fStyle() { } BlockBlock283 Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {} BlockBlock284 Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {} 285 BlockBlock286 Block(const Block& other) : fRange(other.fRange), fStyle(other.fStyle) {} 287 addBlock288 void add(TextRange tail) { 289 SkASSERT(fRange.end == tail.start); 290 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width()); 291 } 292 293 TextRange fRange; 294 TextStyle fStyle; 295 }; 296 297 298 typedef size_t BlockIndex; 299 typedef SkRange<size_t> BlockRange; 300 const size_t EMPTY_BLOCK = EMPTY_INDEX; 301 const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE; 302 303 struct Placeholder { PlaceholderPlaceholder304 Placeholder() : fRange(EMPTY_RANGE), fStyle() {} 305 PlaceholderPlaceholder306 Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle, 307 BlockRange blocksBefore, TextRange textBefore) 308 : fRange(start, end) 309 , fStyle(style) 310 , fTextStyle(textStyle) 311 , fBlocksBefore(blocksBefore) 312 , fTextBefore(textBefore) {} 313 PlaceholderPlaceholder314 Placeholder(const Placeholder& other) 315 : fRange(other.fRange) 316 , fStyle(other.fStyle) 317 , fTextStyle(other.fTextStyle) 318 , fBlocksBefore(other.fBlocksBefore) 319 , fTextBefore(other.fTextBefore) {} 320 321 TextRange fRange; 322 PlaceholderStyle fStyle; 323 TextStyle fTextStyle; 324 BlockRange fBlocksBefore; 325 TextRange fTextBefore; 326 }; 327 328 } // namespace textlayout 329 } // namespace skia 330 331 #endif // TextStyle_DEFINED 332