1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkPaint.h"
9 #include "SkPaintPriv.h"
10 #include "SkAutoKern.h"
11 #include "SkColorFilter.h"
12 #include "SkData.h"
13 #include "SkDraw.h"
14 #include "SkFontDescriptor.h"
15 #include "SkGraphics.h"
16 #include "SkGlyphCache.h"
17 #include "SkImageFilter.h"
18 #include "SkMaskFilter.h"
19 #include "SkMaskGamma.h"
20 #include "SkMutex.h"
21 #include "SkReadBuffer.h"
22 #include "SkWriteBuffer.h"
23 #include "SkOpts.h"
24 #include "SkPaintDefaults.h"
25 #include "SkPathEffect.h"
26 #include "SkSafeRange.h"
27 #include "SkScalar.h"
28 #include "SkScalerContext.h"
29 #include "SkShader.h"
30 #include "SkShaderBase.h"
31 #include "SkStringUtils.h"
32 #include "SkStroke.h"
33 #include "SkStrokeRec.h"
34 #include "SkSurfacePriv.h"
35 #include "SkTextBlob.h"
36 #include "SkTextBlobRunIterator.h"
37 #include "SkTextFormatParams.h"
38 #include "SkTextToPathIter.h"
39 #include "SkTLazy.h"
40 #include "SkTypeface.h"
41 
set_clear_mask(uint32_t bits,bool cond,uint32_t mask)42 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
43     return cond ? bits | mask : bits & ~mask;
44 }
45 
46 // define this to get a printf for out-of-range parameter in setters
47 // e.g. setTextSize(-1)
48 //#define SK_REPORT_API_RANGE_CHECK
49 
SkPaint()50 SkPaint::SkPaint() {
51     fTextSize   = SkPaintDefaults_TextSize;
52     fTextScaleX = SK_Scalar1;
53     fTextSkewX  = 0;
54     fColor      = SK_ColorBLACK;
55     fWidth      = 0;
56     fMiterLimit = SkPaintDefaults_MiterLimit;
57     fBlendMode  = (unsigned)SkBlendMode::kSrcOver;
58 
59     // Zero all bitfields, then set some non-zero defaults.
60     fBitfieldsUInt           = 0;
61     fBitfields.fFlags        = SkPaintDefaults_Flags;
62     fBitfields.fCapType      = kDefault_Cap;
63     fBitfields.fJoinType     = kDefault_Join;
64     fBitfields.fTextAlign    = kLeft_Align;
65     fBitfields.fStyle        = kFill_Style;
66     fBitfields.fTextEncoding = kUTF8_TextEncoding;
67     fBitfields.fHinting      = SkPaintDefaults_Hinting;
68 }
69 
SkPaint(const SkPaint & src)70 SkPaint::SkPaint(const SkPaint& src)
71 #define COPY(field) field(src.field)
72     : COPY(fTypeface)
73     , COPY(fPathEffect)
74     , COPY(fShader)
75     , COPY(fMaskFilter)
76     , COPY(fColorFilter)
77     , COPY(fDrawLooper)
78     , COPY(fImageFilter)
79     , COPY(fTextSize)
80     , COPY(fTextScaleX)
81     , COPY(fTextSkewX)
82     , COPY(fColor)
83     , COPY(fWidth)
84     , COPY(fMiterLimit)
85     , COPY(fBlendMode)
86     , COPY(fBitfields)
87 #undef COPY
88 {}
89 
SkPaint(SkPaint && src)90 SkPaint::SkPaint(SkPaint&& src) {
91 #define MOVE(field) field = std::move(src.field)
92     MOVE(fTypeface);
93     MOVE(fPathEffect);
94     MOVE(fShader);
95     MOVE(fMaskFilter);
96     MOVE(fColorFilter);
97     MOVE(fDrawLooper);
98     MOVE(fImageFilter);
99     MOVE(fTextSize);
100     MOVE(fTextScaleX);
101     MOVE(fTextSkewX);
102     MOVE(fColor);
103     MOVE(fWidth);
104     MOVE(fMiterLimit);
105     MOVE(fBlendMode);
106     MOVE(fBitfields);
107 #undef MOVE
108 }
109 
~SkPaint()110 SkPaint::~SkPaint() {}
111 
operator =(const SkPaint & src)112 SkPaint& SkPaint::operator=(const SkPaint& src) {
113     if (this == &src) {
114         return *this;
115     }
116 
117 #define ASSIGN(field) field = src.field
118     ASSIGN(fTypeface);
119     ASSIGN(fPathEffect);
120     ASSIGN(fShader);
121     ASSIGN(fMaskFilter);
122     ASSIGN(fColorFilter);
123     ASSIGN(fDrawLooper);
124     ASSIGN(fImageFilter);
125     ASSIGN(fTextSize);
126     ASSIGN(fTextScaleX);
127     ASSIGN(fTextSkewX);
128     ASSIGN(fColor);
129     ASSIGN(fWidth);
130     ASSIGN(fMiterLimit);
131     ASSIGN(fBlendMode);
132     ASSIGN(fBitfields);
133 #undef ASSIGN
134 
135     return *this;
136 }
137 
operator =(SkPaint && src)138 SkPaint& SkPaint::operator=(SkPaint&& src) {
139     if (this == &src) {
140         return *this;
141     }
142 
143 #define MOVE(field) field = std::move(src.field)
144     MOVE(fTypeface);
145     MOVE(fPathEffect);
146     MOVE(fShader);
147     MOVE(fMaskFilter);
148     MOVE(fColorFilter);
149     MOVE(fDrawLooper);
150     MOVE(fImageFilter);
151     MOVE(fTextSize);
152     MOVE(fTextScaleX);
153     MOVE(fTextSkewX);
154     MOVE(fColor);
155     MOVE(fWidth);
156     MOVE(fMiterLimit);
157     MOVE(fBlendMode);
158     MOVE(fBitfields);
159 #undef MOVE
160 
161     return *this;
162 }
163 
operator ==(const SkPaint & a,const SkPaint & b)164 bool operator==(const SkPaint& a, const SkPaint& b) {
165 #define EQUAL(field) (a.field == b.field)
166     return EQUAL(fTypeface)
167         && EQUAL(fPathEffect)
168         && EQUAL(fShader)
169         && EQUAL(fMaskFilter)
170         && EQUAL(fColorFilter)
171         && EQUAL(fDrawLooper)
172         && EQUAL(fImageFilter)
173         && EQUAL(fTextSize)
174         && EQUAL(fTextScaleX)
175         && EQUAL(fTextSkewX)
176         && EQUAL(fColor)
177         && EQUAL(fWidth)
178         && EQUAL(fMiterLimit)
179         && EQUAL(fBlendMode)
180         && EQUAL(fBitfieldsUInt)
181         ;
182 #undef EQUAL
183 }
184 
185 #define DEFINE_REF_FOO(type)    sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
186 DEFINE_REF_FOO(ColorFilter)
DEFINE_REF_FOO(DrawLooper)187 DEFINE_REF_FOO(DrawLooper)
188 DEFINE_REF_FOO(ImageFilter)
189 DEFINE_REF_FOO(MaskFilter)
190 DEFINE_REF_FOO(PathEffect)
191 DEFINE_REF_FOO(Shader)
192 DEFINE_REF_FOO(Typeface)
193 #undef DEFINE_REF_FOO
194 
195 void SkPaint::reset() {
196     SkPaint init;
197     *this = init;
198 }
199 
setFilterQuality(SkFilterQuality quality)200 void SkPaint::setFilterQuality(SkFilterQuality quality) {
201     fBitfields.fFilterQuality = quality;
202 }
203 
setHinting(Hinting hintingLevel)204 void SkPaint::setHinting(Hinting hintingLevel) {
205     fBitfields.fHinting = hintingLevel;
206 }
207 
setFlags(uint32_t flags)208 void SkPaint::setFlags(uint32_t flags) {
209     fBitfields.fFlags = flags;
210 }
211 
setAntiAlias(bool doAA)212 void SkPaint::setAntiAlias(bool doAA) {
213     this->setFlags(set_clear_mask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
214 }
215 
setDither(bool doDither)216 void SkPaint::setDither(bool doDither) {
217     this->setFlags(set_clear_mask(fBitfields.fFlags, doDither, kDither_Flag));
218 }
219 
setSubpixelText(bool doSubpixel)220 void SkPaint::setSubpixelText(bool doSubpixel) {
221     this->setFlags(set_clear_mask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
222 }
223 
setLCDRenderText(bool doLCDRender)224 void SkPaint::setLCDRenderText(bool doLCDRender) {
225     this->setFlags(set_clear_mask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
226 }
227 
setEmbeddedBitmapText(bool doEmbeddedBitmapText)228 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
229     this->setFlags(set_clear_mask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
230 }
231 
setAutohinted(bool useAutohinter)232 void SkPaint::setAutohinted(bool useAutohinter) {
233     this->setFlags(set_clear_mask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
234 }
235 
setLinearText(bool doLinearText)236 void SkPaint::setLinearText(bool doLinearText) {
237     this->setFlags(set_clear_mask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
238 }
239 
setVerticalText(bool doVertical)240 void SkPaint::setVerticalText(bool doVertical) {
241     this->setFlags(set_clear_mask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
242 }
243 
setFakeBoldText(bool doFakeBold)244 void SkPaint::setFakeBoldText(bool doFakeBold) {
245     this->setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
246 }
247 
setDevKernText(bool doDevKern)248 void SkPaint::setDevKernText(bool doDevKern) {
249     this->setFlags(set_clear_mask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
250 }
251 
setStyle(Style style)252 void SkPaint::setStyle(Style style) {
253     if ((unsigned)style < kStyleCount) {
254         fBitfields.fStyle = style;
255     } else {
256 #ifdef SK_REPORT_API_RANGE_CHECK
257         SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
258 #endif
259     }
260 }
261 
setColor(SkColor color)262 void SkPaint::setColor(SkColor color) {
263     fColor = color;
264 }
265 
setAlpha(U8CPU a)266 void SkPaint::setAlpha(U8CPU a) {
267     this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
268                                   SkColorGetG(fColor), SkColorGetB(fColor)));
269 }
270 
setARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)271 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
272     this->setColor(SkColorSetARGB(a, r, g, b));
273 }
274 
setStrokeWidth(SkScalar width)275 void SkPaint::setStrokeWidth(SkScalar width) {
276     if (width >= 0) {
277         fWidth = width;
278     } else {
279 #ifdef SK_REPORT_API_RANGE_CHECK
280         SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
281 #endif
282     }
283 }
284 
setStrokeMiter(SkScalar limit)285 void SkPaint::setStrokeMiter(SkScalar limit) {
286     if (limit >= 0) {
287         fMiterLimit = limit;
288     } else {
289 #ifdef SK_REPORT_API_RANGE_CHECK
290         SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
291 #endif
292     }
293 }
294 
setStrokeCap(Cap ct)295 void SkPaint::setStrokeCap(Cap ct) {
296     if ((unsigned)ct < kCapCount) {
297         fBitfields.fCapType = SkToU8(ct);
298     } else {
299 #ifdef SK_REPORT_API_RANGE_CHECK
300         SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
301 #endif
302     }
303 }
304 
setStrokeJoin(Join jt)305 void SkPaint::setStrokeJoin(Join jt) {
306     if ((unsigned)jt < kJoinCount) {
307         fBitfields.fJoinType = SkToU8(jt);
308     } else {
309 #ifdef SK_REPORT_API_RANGE_CHECK
310         SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
311 #endif
312     }
313 }
314 
315 ///////////////////////////////////////////////////////////////////////////////
316 
setTextAlign(Align align)317 void SkPaint::setTextAlign(Align align) {
318     if ((unsigned)align < kAlignCount) {
319         fBitfields.fTextAlign = SkToU8(align);
320     } else {
321 #ifdef SK_REPORT_API_RANGE_CHECK
322         SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
323 #endif
324     }
325 }
326 
setTextSize(SkScalar ts)327 void SkPaint::setTextSize(SkScalar ts) {
328     if (ts >= 0) {
329         fTextSize = ts;
330     } else {
331 #ifdef SK_REPORT_API_RANGE_CHECK
332         SkDebugf("SkPaint::setTextSize() called with negative value\n");
333 #endif
334     }
335 }
336 
setTextScaleX(SkScalar scaleX)337 void SkPaint::setTextScaleX(SkScalar scaleX) {
338     fTextScaleX = scaleX;
339 }
340 
setTextSkewX(SkScalar skewX)341 void SkPaint::setTextSkewX(SkScalar skewX) {
342     fTextSkewX = skewX;
343 }
344 
setTextEncoding(TextEncoding encoding)345 void SkPaint::setTextEncoding(TextEncoding encoding) {
346     if ((unsigned)encoding <= kGlyphID_TextEncoding) {
347         fBitfields.fTextEncoding = encoding;
348     } else {
349 #ifdef SK_REPORT_API_RANGE_CHECK
350         SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
351 #endif
352     }
353 }
354 
355 ///////////////////////////////////////////////////////////////////////////////
356 
357 #define MOVE_FIELD(Field) void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
358 MOVE_FIELD(Typeface)
MOVE_FIELD(ImageFilter)359 MOVE_FIELD(ImageFilter)
360 MOVE_FIELD(Shader)
361 MOVE_FIELD(ColorFilter)
362 MOVE_FIELD(PathEffect)
363 MOVE_FIELD(MaskFilter)
364 MOVE_FIELD(DrawLooper)
365 #undef MOVE_FIELD
366 void SkPaint::setLooper(sk_sp<SkDrawLooper> looper) { fDrawLooper = std::move(looper); }
367 
368 ///////////////////////////////////////////////////////////////////////////////
369 
mag2(SkScalar x,SkScalar y)370 static SkScalar mag2(SkScalar x, SkScalar y) {
371     return x * x + y * y;
372 }
373 
tooBig(const SkMatrix & m,SkScalar ma2max)374 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
375     return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
376             ||
377             mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
378 }
379 
TooBigToUseCache(const SkMatrix & ctm,const SkMatrix & textM,SkScalar maxLimit)380 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit) {
381     SkASSERT(!ctm.hasPerspective());
382     SkASSERT(!textM.hasPerspective());
383 
384     SkMatrix matrix;
385     matrix.setConcat(ctm, textM);
386     return tooBig(matrix, MaxCacheSize2(maxLimit));
387 }
388 
MaxCacheSize2(SkScalar maxLimit)389 SkScalar SkPaint::MaxCacheSize2(SkScalar maxLimit) {
390     // we have a self-imposed maximum, just for memory-usage sanity
391     const int limit = SkMin32(SkGraphics::GetFontCachePointSizeLimit(), maxLimit);
392     const SkScalar maxSize = SkIntToScalar(limit);
393     return maxSize * maxSize;
394 }
395 
396 ///////////////////////////////////////////////////////////////////////////////
397 
398 #include "SkGlyphCache.h"
399 #include "SkUtils.h"
400 
textToGlyphs(const void * textData,size_t byteLength,uint16_t glyphs[]) const401 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const {
402     if (byteLength == 0) {
403         return 0;
404     }
405 
406     SkASSERT(textData != nullptr);
407 
408     if (nullptr == glyphs) {
409         switch (this->getTextEncoding()) {
410         case kUTF8_TextEncoding:
411             return SkUTF8_CountUnichars(textData, byteLength);
412         case kUTF16_TextEncoding:
413             return SkUTF16_CountUnichars(textData, byteLength);
414         case kUTF32_TextEncoding:
415             return SkToInt(byteLength >> 2);
416         case kGlyphID_TextEncoding:
417             return SkToInt(byteLength >> 1);
418         default:
419             SkDEBUGFAIL("unknown text encoding");
420         }
421         return 0;
422     }
423 
424     // if we get here, we have a valid glyphs[] array, so time to fill it in
425 
426     // handle this encoding before the setup for the glyphcache
427     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
428         // we want to ignore the low bit of byteLength
429         memcpy(glyphs, textData, byteLength >> 1 << 1);
430         return SkToInt(byteLength >> 1);
431     }
432 
433     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
434     SkGlyphCache*    cache = autoCache.getCache();
435 
436     const char* text = (const char*)textData;
437     const char* stop = text + byteLength;
438     uint16_t*   gptr = glyphs;
439 
440     switch (this->getTextEncoding()) {
441         case SkPaint::kUTF8_TextEncoding:
442             while (text < stop) {
443                 SkUnichar u = SkUTF8_NextUnicharWithError(&text, stop);
444                 if (u < 0) {
445                     return 0;  // bad UTF-8 sequence
446                 }
447                 *gptr++ = cache->unicharToGlyph(u);
448             }
449             break;
450         case SkPaint::kUTF16_TextEncoding: {
451             const uint16_t* text16 = (const uint16_t*)text;
452             const uint16_t* stop16 = (const uint16_t*)stop;
453             while (text16 < stop16) {
454                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
455             }
456             break;
457         }
458         case kUTF32_TextEncoding: {
459             const int32_t* text32 = (const int32_t*)text;
460             const int32_t* stop32 = (const int32_t*)stop;
461             while (text32 < stop32) {
462                 *gptr++ = cache->unicharToGlyph(*text32++);
463             }
464             break;
465         }
466         default:
467             SkDEBUGFAIL("unknown text encoding");
468     }
469     return SkToInt(gptr - glyphs);
470 }
471 
containsText(const void * textData,size_t byteLength) const472 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
473     if (0 == byteLength) {
474         return true;
475     }
476 
477     SkASSERT(textData != nullptr);
478 
479     // handle this encoding before the setup for the glyphcache
480     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
481         const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
482         size_t count = byteLength >> 1;
483         for (size_t i = 0; i < count; i++) {
484             if (0 == glyphID[i]) {
485                 return false;
486             }
487         }
488         return true;
489     }
490 
491     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
492     SkGlyphCache*    cache = autoCache.getCache();
493 
494     switch (this->getTextEncoding()) {
495         case SkPaint::kUTF8_TextEncoding: {
496             const char* text = static_cast<const char*>(textData);
497             const char* stop = text + byteLength;
498             while (text < stop) {
499                 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
500                     return false;
501                 }
502             }
503             break;
504         }
505         case SkPaint::kUTF16_TextEncoding: {
506             const uint16_t* text = static_cast<const uint16_t*>(textData);
507             const uint16_t* stop = text + (byteLength >> 1);
508             while (text < stop) {
509                 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
510                     return false;
511                 }
512             }
513             break;
514         }
515         case SkPaint::kUTF32_TextEncoding: {
516             const int32_t* text = static_cast<const int32_t*>(textData);
517             const int32_t* stop = text + (byteLength >> 2);
518             while (text < stop) {
519                 if (0 == cache->unicharToGlyph(*text++)) {
520                     return false;
521                 }
522             }
523             break;
524         }
525         default:
526             SkDEBUGFAIL("unknown text encoding");
527             return false;
528     }
529     return true;
530 }
531 
glyphsToUnichars(const uint16_t glyphs[],int count,SkUnichar textData[]) const532 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count, SkUnichar textData[]) const {
533     if (count <= 0) {
534         return;
535     }
536 
537     SkASSERT(glyphs != nullptr);
538     SkASSERT(textData != nullptr);
539 
540     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
541     SkAutoGlyphCache autoCache(*this, &props, nullptr);
542     SkGlyphCache*    cache = autoCache.getCache();
543 
544     for (int index = 0; index < count; index++) {
545         textData[index] = cache->glyphToUnichar(glyphs[index]);
546     }
547 }
548 
549 ///////////////////////////////////////////////////////////////////////////////
550 
sk_getMetrics_utf8_next(SkGlyphCache * cache,const char ** text)551 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
552                                               const char** text) {
553     SkASSERT(cache != nullptr);
554     SkASSERT(text != nullptr);
555 
556     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
557 }
558 
sk_getMetrics_utf16_next(SkGlyphCache * cache,const char ** text)559 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
560                                                const char** text) {
561     SkASSERT(cache != nullptr);
562     SkASSERT(text != nullptr);
563 
564     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
565 }
566 
sk_getMetrics_utf32_next(SkGlyphCache * cache,const char ** text)567 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
568                                                const char** text) {
569     SkASSERT(cache != nullptr);
570     SkASSERT(text != nullptr);
571 
572     const int32_t* ptr = *(const int32_t**)text;
573     SkUnichar uni = *ptr++;
574     *text = (const char*)ptr;
575     return cache->getUnicharMetrics(uni);
576 }
577 
sk_getMetrics_glyph_next(SkGlyphCache * cache,const char ** text)578 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
579                                                const char** text) {
580     SkASSERT(cache != nullptr);
581     SkASSERT(text != nullptr);
582 
583     const uint16_t* ptr = *(const uint16_t**)text;
584     unsigned glyphID = *ptr;
585     ptr += 1;
586     *text = (const char*)ptr;
587     return cache->getGlyphIDMetrics(glyphID);
588 }
589 
sk_getAdvance_utf8_next(SkGlyphCache * cache,const char ** text)590 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
591                                               const char** text) {
592     SkASSERT(cache != nullptr);
593     SkASSERT(text != nullptr);
594 
595     return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
596 }
597 
sk_getAdvance_utf16_next(SkGlyphCache * cache,const char ** text)598 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
599                                                const char** text) {
600     SkASSERT(cache != nullptr);
601     SkASSERT(text != nullptr);
602 
603     return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
604 }
605 
sk_getAdvance_utf32_next(SkGlyphCache * cache,const char ** text)606 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
607                                                const char** text) {
608     SkASSERT(cache != nullptr);
609     SkASSERT(text != nullptr);
610 
611     const int32_t* ptr = *(const int32_t**)text;
612     SkUnichar uni = *ptr++;
613     *text = (const char*)ptr;
614     return cache->getUnicharAdvance(uni);
615 }
616 
sk_getAdvance_glyph_next(SkGlyphCache * cache,const char ** text)617 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
618                                                const char** text) {
619     SkASSERT(cache != nullptr);
620     SkASSERT(text != nullptr);
621 
622     const uint16_t* ptr = *(const uint16_t**)text;
623     unsigned glyphID = *ptr;
624     ptr += 1;
625     *text = (const char*)ptr;
626     return cache->getGlyphIDAdvance(glyphID);
627 }
628 
GetGlyphCacheProc(TextEncoding encoding,bool isDevKern,bool needFullMetrics)629 SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
630                                                    bool isDevKern,
631                                                    bool needFullMetrics) {
632     static const GlyphCacheProc gGlyphCacheProcs[] = {
633         sk_getMetrics_utf8_next,
634         sk_getMetrics_utf16_next,
635         sk_getMetrics_utf32_next,
636         sk_getMetrics_glyph_next,
637 
638         sk_getAdvance_utf8_next,
639         sk_getAdvance_utf16_next,
640         sk_getAdvance_utf32_next,
641         sk_getAdvance_glyph_next,
642     };
643 
644     unsigned index = encoding;
645 
646     if (!needFullMetrics && !isDevKern) {
647         index += 4;
648     }
649 
650     SkASSERT(index < SK_ARRAY_COUNT(gGlyphCacheProcs));
651     return gGlyphCacheProcs[index];
652 }
653 
654 ///////////////////////////////////////////////////////////////////////////////
655 
656 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
657 SkPaint::kDevKernText_Flag          |       \
658 SkPaint::kLinearText_Flag           |       \
659 SkPaint::kLCDRenderText_Flag        |       \
660 SkPaint::kEmbeddedBitmapText_Flag   |       \
661 SkPaint::kAutoHinting_Flag          |       \
662 SkPaint::kGenA8FromLCD_Flag )
663 
setupForAsPaths()664 SkScalar SkPaint::setupForAsPaths() {
665     uint32_t flags = this->getFlags();
666     // clear the flags we don't care about
667     flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
668     // set the flags we do care about
669     flags |= SkPaint::kSubpixelText_Flag;
670 
671     this->setFlags(flags);
672     this->setHinting(SkPaint::kNo_Hinting);
673 
674     SkScalar textSize = fTextSize;
675     this->setTextSize(kCanonicalTextSizeForPaths);
676     return textSize / kCanonicalTextSizeForPaths;
677 }
678 
679 class SkCanonicalizePaint {
680 public:
SkCanonicalizePaint(const SkPaint & paint)681     SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
682         if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
683             SkPaint* p = fLazy.set(paint);
684             fScale = p->setupForAsPaths();
685             fPaint = p;
686         }
687     }
688 
getPaint() const689     const SkPaint& getPaint() const { return *fPaint; }
690 
691     /**
692      *  Returns 0 if the paint was unmodified, or the scale factor need to
693      *  the original textSize
694      */
getScale() const695     SkScalar getScale() const { return fScale; }
696 
697 private:
698     const SkPaint*   fPaint;
699     SkScalar         fScale;
700     SkTLazy<SkPaint> fLazy;
701 };
702 
set_bounds(const SkGlyph & g,SkRect * bounds)703 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
704     bounds->set(SkIntToScalar(g.fLeft),
705                 SkIntToScalar(g.fTop),
706                 SkIntToScalar(g.fLeft + g.fWidth),
707                 SkIntToScalar(g.fTop + g.fHeight));
708 }
709 
join_bounds_x(const SkGlyph & g,SkRect * bounds,SkScalar dx)710 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) {
711     bounds->join(SkIntToScalar(g.fLeft) + dx,
712                  SkIntToScalar(g.fTop),
713                  SkIntToScalar(g.fLeft + g.fWidth) + dx,
714                  SkIntToScalar(g.fTop + g.fHeight));
715 }
716 
join_bounds_y(const SkGlyph & g,SkRect * bounds,SkScalar dy)717 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, SkScalar dy) {
718     bounds->join(SkIntToScalar(g.fLeft),
719                  SkIntToScalar(g.fTop) + dy,
720                  SkIntToScalar(g.fLeft + g.fWidth),
721                  SkIntToScalar(g.fTop + g.fHeight) + dy);
722 }
723 
724 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, SkScalar);
725 
726 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
advance(const SkGlyph & glyph,int xyIndex)727 static SkScalar advance(const SkGlyph& glyph, int xyIndex) {
728     SkASSERT(0 == xyIndex || 1 == xyIndex);
729     return SkFloatToScalar((&glyph.fAdvanceX)[xyIndex]);
730 }
731 
measure_text(SkGlyphCache * cache,const char * text,size_t byteLength,int * count,SkRect * bounds) const732 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
733                                const char* text, size_t byteLength,
734                                int* count, SkRect* bounds) const {
735     SkASSERT(count);
736     if (byteLength == 0) {
737         *count = 0;
738         if (bounds) {
739             bounds->setEmpty();
740         }
741         return 0;
742     }
743 
744     GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(this->getTextEncoding(),
745                                                                this->isDevKernText(),
746                                                                nullptr != bounds);
747 
748     int xyIndex;
749     JoinBoundsProc joinBoundsProc;
750     if (this->isVerticalText()) {
751         xyIndex = 1;
752         joinBoundsProc = join_bounds_y;
753     } else {
754         xyIndex = 0;
755         joinBoundsProc = join_bounds_x;
756     }
757 
758     int         n = 1;
759     const char* stop = (const char*)text + byteLength;
760     const SkGlyph* g = &glyphCacheProc(cache, &text);
761     SkScalar x = advance(*g, xyIndex);
762 
763     if (nullptr == bounds) {
764         if (this->isDevKernText()) {
765             for (; text < stop; n++) {
766                 const int rsb = g->fRsbDelta;
767                 g = &glyphCacheProc(cache, &text);
768                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta) + advance(*g, xyIndex);
769             }
770         } else {
771             for (; text < stop; n++) {
772                 x += advance(glyphCacheProc(cache, &text), xyIndex);
773             }
774         }
775     } else {
776         set_bounds(*g, bounds);
777         if (this->isDevKernText()) {
778             for (; text < stop; n++) {
779                 const int rsb = g->fRsbDelta;
780                 g = &glyphCacheProc(cache, &text);
781                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta);
782                 joinBoundsProc(*g, bounds, x);
783                 x += advance(*g, xyIndex);
784             }
785         } else {
786             for (; text < stop; n++) {
787                 g = &glyphCacheProc(cache, &text);
788                 joinBoundsProc(*g, bounds, x);
789                 x += advance(*g, xyIndex);
790             }
791         }
792     }
793     SkASSERT(text == stop);
794 
795     *count = n;
796     return x;
797 }
798 
measureText(const void * textData,size_t length,SkRect * bounds) const799 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
800     const char* text = (const char*)textData;
801     SkASSERT(text != nullptr || length == 0);
802 
803     SkCanonicalizePaint canon(*this);
804     const SkPaint& paint = canon.getPaint();
805     SkScalar scale = canon.getScale();
806 
807     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
808     SkGlyphCache*       cache = autoCache.getCache();
809 
810     SkScalar width = 0;
811 
812     if (length > 0) {
813         int tempCount;
814 
815         width = paint.measure_text(cache, text, length, &tempCount, bounds);
816         if (scale) {
817             width *= scale;
818             if (bounds) {
819                 bounds->fLeft *= scale;
820                 bounds->fTop *= scale;
821                 bounds->fRight *= scale;
822                 bounds->fBottom *= scale;
823             }
824         }
825     } else if (bounds) {
826         // ensure that even if we don't measure_text we still update the bounds
827         bounds->setEmpty();
828     }
829     return width;
830 }
831 
breakText(const void * textD,size_t length,SkScalar maxWidth,SkScalar * measuredWidth) const832 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
833                           SkScalar* measuredWidth) const {
834     if (0 == length || 0 >= maxWidth) {
835         if (measuredWidth) {
836             *measuredWidth = 0;
837         }
838         return 0;
839     }
840 
841     if (0 == fTextSize) {
842         if (measuredWidth) {
843             *measuredWidth = 0;
844         }
845         return length;
846     }
847 
848     SkASSERT(textD != nullptr);
849     const char* text = (const char*)textD;
850     const char* stop = text + length;
851 
852     SkCanonicalizePaint canon(*this);
853     const SkPaint& paint = canon.getPaint();
854     SkScalar scale = canon.getScale();
855 
856     // adjust max in case we changed the textSize in paint
857     if (scale) {
858         maxWidth /= scale;
859     }
860 
861     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
862     SkGlyphCache*       cache = autoCache.getCache();
863 
864     GlyphCacheProc   glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
865                                                                  paint.isDevKernText(),
866                                                                  false);
867     const int        xyIndex = paint.isVerticalText() ? 1 : 0;
868     SkScalar         width = 0;
869 
870     if (this->isDevKernText()) {
871         int rsb = 0;
872         while (text < stop) {
873             const char* curr = text;
874             const SkGlyph& g = glyphCacheProc(cache, &text);
875             SkScalar x = SkAutoKern_Adjust(rsb, g.fLsbDelta) + advance(g, xyIndex);
876             if ((width += x) > maxWidth) {
877                 width -= x;
878                 text = curr;
879                 break;
880             }
881             rsb = g.fRsbDelta;
882         }
883     } else {
884         while (text < stop) {
885             const char* curr = text;
886             SkScalar x = advance(glyphCacheProc(cache, &text), xyIndex);
887             if ((width += x) > maxWidth) {
888                 width -= x;
889                 text = curr;
890                 break;
891             }
892         }
893     }
894 
895     if (measuredWidth) {
896         if (scale) {
897             width *= scale;
898         }
899         *measuredWidth = width;
900     }
901 
902     // return the number of bytes measured
903     return text - stop + length;
904 }
905 
906 ///////////////////////////////////////////////////////////////////////////////
907 
FontMetricsCacheProc(const SkGlyphCache * cache,void * context)908 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
909     *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
910     return false;   // don't detach the cache
911 }
912 
getFontMetrics(FontMetrics * metrics,SkScalar zoom) const913 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
914     SkCanonicalizePaint canon(*this);
915     const SkPaint& paint = canon.getPaint();
916     SkScalar scale = canon.getScale();
917 
918     SkMatrix zoomMatrix, *zoomPtr = nullptr;
919     if (zoom) {
920         zoomMatrix.setScale(zoom, zoom);
921         zoomPtr = &zoomMatrix;
922     }
923 
924     FontMetrics storage;
925     if (nullptr == metrics) {
926         metrics = &storage;
927     }
928 
929     SkAutoDescriptor ad;
930     SkScalerContextEffects effects;
931 
932     auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
933         paint, nullptr, SkScalerContextFlags::kNone, zoomPtr, &ad, &effects);
934 
935     SkGlyphCache::VisitCache(paint.getTypeface(), effects, desc, FontMetricsCacheProc, metrics);
936 
937     if (scale) {
938         SkPaintPriv::ScaleFontMetrics(metrics, scale);
939     }
940     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
941 }
942 
943 ///////////////////////////////////////////////////////////////////////////////
944 
set_bounds(const SkGlyph & g,SkRect * bounds,SkScalar scale)945 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
946     bounds->set(g.fLeft * scale,
947                 g.fTop * scale,
948                 (g.fLeft + g.fWidth) * scale,
949                 (g.fTop + g.fHeight) * scale);
950 }
951 
getTextWidths(const void * textData,size_t byteLength,SkScalar widths[],SkRect bounds[]) const952 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
953                            SkScalar widths[], SkRect bounds[]) const {
954     if (0 == byteLength) {
955         return 0;
956     }
957 
958     SkASSERT(textData);
959 
960     if (nullptr == widths && nullptr == bounds) {
961         return this->countText(textData, byteLength);
962     }
963 
964     SkCanonicalizePaint canon(*this);
965     const SkPaint& paint = canon.getPaint();
966     SkScalar scale = canon.getScale();
967 
968     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
969     SkGlyphCache*       cache = autoCache.getCache();
970     GlyphCacheProc      glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
971                                                                     paint.isDevKernText(),
972                                                                     nullptr != bounds);
973 
974     const char* text = (const char*)textData;
975     const char* stop = text + byteLength;
976     int         count = 0;
977     const int   xyIndex = paint.isVerticalText() ? 1 : 0;
978 
979     if (this->isDevKernText()) {
980         // we adjust the widths returned here through auto-kerning
981         SkAutoKern  autokern;
982         SkScalar    prevWidth = 0;
983 
984         if (scale) {
985             while (text < stop) {
986                 const SkGlyph& g = glyphCacheProc(cache, &text);
987                 if (widths) {
988                     SkScalar adjust = autokern.adjust(g);
989 
990                     if (count > 0) {
991                         *widths++ = (prevWidth + adjust) * scale;
992                     }
993                     prevWidth = advance(g, xyIndex);
994                 }
995                 if (bounds) {
996                     set_bounds(g, bounds++, scale);
997                 }
998                 ++count;
999             }
1000             if (count > 0 && widths) {
1001                 *widths = prevWidth * scale;
1002             }
1003         } else {
1004             while (text < stop) {
1005                 const SkGlyph& g = glyphCacheProc(cache, &text);
1006                 if (widths) {
1007                     SkScalar adjust = autokern.adjust(g);
1008 
1009                     if (count > 0) {
1010                         *widths++ = prevWidth + adjust;
1011                     }
1012                     prevWidth = advance(g, xyIndex);
1013                 }
1014                 if (bounds) {
1015                     set_bounds(g, bounds++);
1016                 }
1017                 ++count;
1018             }
1019             if (count > 0 && widths) {
1020                 *widths = prevWidth;
1021             }
1022         }
1023     } else {    // no devkern
1024         if (scale) {
1025             while (text < stop) {
1026                 const SkGlyph& g = glyphCacheProc(cache, &text);
1027                 if (widths) {
1028                     *widths++ = advance(g, xyIndex) * scale;
1029                 }
1030                 if (bounds) {
1031                     set_bounds(g, bounds++, scale);
1032                 }
1033                 ++count;
1034             }
1035         } else {
1036             while (text < stop) {
1037                 const SkGlyph& g = glyphCacheProc(cache, &text);
1038                 if (widths) {
1039                     *widths++ = advance(g, xyIndex);
1040                 }
1041                 if (bounds) {
1042                     set_bounds(g, bounds++);
1043                 }
1044                 ++count;
1045             }
1046         }
1047     }
1048 
1049     SkASSERT(text == stop);
1050     return count;
1051 }
1052 
1053 ///////////////////////////////////////////////////////////////////////////////
1054 
1055 #include "SkDraw.h"
1056 
getTextPath(const void * textData,size_t length,SkScalar x,SkScalar y,SkPath * path) const1057 void SkPaint::getTextPath(const void* textData, size_t length,
1058                           SkScalar x, SkScalar y, SkPath* path) const {
1059     SkASSERT(length == 0 || textData != nullptr);
1060 
1061     const char* text = (const char*)textData;
1062     if (text == nullptr || length == 0 || path == nullptr) {
1063         return;
1064     }
1065 
1066     SkTextToPathIter    iter(text, length, *this, false);
1067     SkMatrix            matrix;
1068     SkScalar            prevXPos = 0;
1069 
1070     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1071     matrix.postTranslate(x, y);
1072     path->reset();
1073 
1074     SkScalar        xpos;
1075     const SkPath*   iterPath;
1076     while (iter.next(&iterPath, &xpos)) {
1077         matrix.postTranslate(xpos - prevXPos, 0);
1078         if (iterPath) {
1079             path->addPath(*iterPath, matrix);
1080         }
1081         prevXPos = xpos;
1082     }
1083 }
1084 
getPosTextPath(const void * textData,size_t length,const SkPoint pos[],SkPath * path) const1085 void SkPaint::getPosTextPath(const void* textData, size_t length,
1086                              const SkPoint pos[], SkPath* path) const {
1087     SkASSERT(length == 0 || textData != nullptr);
1088 
1089     const char* text = (const char*)textData;
1090     if (text == nullptr || length == 0 || path == nullptr) {
1091         return;
1092     }
1093 
1094     SkTextToPathIter    iter(text, length, *this, false);
1095     SkMatrix            matrix;
1096     SkPoint             prevPos;
1097     prevPos.set(0, 0);
1098 
1099     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1100     path->reset();
1101 
1102     unsigned int    i = 0;
1103     const SkPath*   iterPath;
1104     while (iter.next(&iterPath, nullptr)) {
1105         matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1106         if (iterPath) {
1107             path->addPath(*iterPath, matrix);
1108         }
1109         prevPos = pos[i];
1110         i++;
1111     }
1112 }
1113 
1114 template <SkTextInterceptsIter::TextType TextType, typename Func>
GetTextIntercepts(const SkPaint & paint,const void * text,size_t length,const SkScalar bounds[2],SkScalar * array,Func posMaker)1115 int GetTextIntercepts(const SkPaint& paint, const void* text, size_t length,
1116                       const SkScalar bounds[2], SkScalar* array, Func posMaker) {
1117     SkASSERT(length == 0 || text != nullptr);
1118     if (!length) {
1119         return 0;
1120     }
1121 
1122     const SkPoint pos0 = posMaker(0);
1123     SkTextInterceptsIter iter(static_cast<const char*>(text), length, paint, bounds,
1124                               pos0.x(), pos0.y(), TextType);
1125 
1126     int i = 0;
1127     int count = 0;
1128     while (iter.next(array, &count)) {
1129         if (TextType == SkTextInterceptsIter::TextType::kPosText) {
1130             const SkPoint pos = posMaker(++i);
1131             iter.setPosition(pos.x(), pos.y());
1132         }
1133     }
1134 
1135     return count;
1136 }
1137 
getTextIntercepts(const void * textData,size_t length,SkScalar x,SkScalar y,const SkScalar bounds[2],SkScalar * array) const1138 int SkPaint::getTextIntercepts(const void* textData, size_t length,
1139                                SkScalar x, SkScalar y, const SkScalar bounds[2],
1140                                SkScalar* array) const {
1141 
1142     return GetTextIntercepts<SkTextInterceptsIter::TextType::kText>(
1143         *this, textData, length, bounds, array, [&x, &y] (int) -> SkPoint {
1144             return SkPoint::Make(x, y);
1145         });
1146 }
1147 
getPosTextIntercepts(const void * textData,size_t length,const SkPoint pos[],const SkScalar bounds[2],SkScalar * array) const1148 int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[],
1149                                   const SkScalar bounds[2], SkScalar* array) const {
1150 
1151     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
1152         *this, textData, length, bounds, array, [&pos] (int i) -> SkPoint {
1153             return pos[i];
1154         });
1155 }
1156 
getPosTextHIntercepts(const void * textData,size_t length,const SkScalar xpos[],SkScalar constY,const SkScalar bounds[2],SkScalar * array) const1157 int SkPaint::getPosTextHIntercepts(const void* textData, size_t length, const SkScalar xpos[],
1158                                    SkScalar constY, const SkScalar bounds[2],
1159                                    SkScalar* array) const {
1160 
1161     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
1162         *this, textData, length, bounds, array, [&xpos, &constY] (int i) -> SkPoint {
1163             return SkPoint::Make(xpos[i], constY);
1164         });
1165 }
1166 
getTextBlobIntercepts(const SkTextBlob * blob,const SkScalar bounds[2],SkScalar * intervals) const1167 int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
1168                                    SkScalar* intervals) const {
1169     int count = 0;
1170     SkPaint runPaint(*this);
1171 
1172     SkTextBlobRunIterator it(blob);
1173     while (!it.done()) {
1174         it.applyFontToPaint(&runPaint);
1175         const size_t runByteCount = it.glyphCount() * sizeof(SkGlyphID);
1176         SkScalar* runIntervals = intervals ? intervals + count : nullptr;
1177 
1178         switch (it.positioning()) {
1179         case SkTextBlob::kDefault_Positioning:
1180             count += runPaint.getTextIntercepts(it.glyphs(), runByteCount, it.offset().x(),
1181                                                 it.offset().y(), bounds, runIntervals);
1182             break;
1183         case SkTextBlob::kHorizontal_Positioning:
1184             count += runPaint.getPosTextHIntercepts(it.glyphs(), runByteCount, it.pos(),
1185                                                     it.offset().y(), bounds, runIntervals);
1186             break;
1187         case SkTextBlob::kFull_Positioning:
1188             count += runPaint.getPosTextIntercepts(it.glyphs(), runByteCount,
1189                                                    reinterpret_cast<const SkPoint*>(it.pos()),
1190                                                    bounds, runIntervals);
1191             break;
1192         }
1193 
1194         it.next();
1195     }
1196 
1197     return count;
1198 }
1199 
getFontBounds() const1200 SkRect SkPaint::getFontBounds() const {
1201     SkMatrix m;
1202     m.setScale(fTextSize * fTextScaleX, fTextSize);
1203     m.postSkew(fTextSkewX, 0);
1204 
1205     SkTypeface* typeface = this->getTypeface();
1206     if (nullptr == typeface) {
1207         typeface = SkTypeface::GetDefaultTypeface();
1208     }
1209 
1210     SkRect bounds;
1211     m.mapRect(&bounds, typeface->getBounds());
1212     return bounds;
1213 }
1214 
1215 // return true if the paint is just a single color (i.e. not a shader). If its
1216 // a shader, then we can't compute a const luminance for it :(
just_a_color(const SkPaint & paint,SkColor * color)1217 static bool just_a_color(const SkPaint& paint, SkColor* color) {
1218     SkColor c = paint.getColor();
1219 
1220     const auto* shader = as_SB(paint.getShader());
1221     if (shader && !shader->asLuminanceColor(&c)) {
1222         return false;
1223     }
1224     if (paint.getColorFilter()) {
1225         c = paint.getColorFilter()->filterColor(c);
1226     }
1227     if (color) {
1228         *color = c;
1229     }
1230     return true;
1231 }
1232 
computeLuminanceColor() const1233 SkColor SkPaint::computeLuminanceColor() const {
1234     SkColor c;
1235     if (!just_a_color(*this, &c)) {
1236         c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1237     }
1238     return c;
1239 }
1240 
1241 /**
1242  * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1243  * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1244  * to hold it until the returned pointer is refed or forgotten.
1245  */
1246 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1247 
1248 static SkMaskGamma* gLinearMaskGamma = nullptr;
1249 static SkMaskGamma* gMaskGamma = nullptr;
1250 static SkScalar gContrast = SK_ScalarMin;
1251 static SkScalar gPaintGamma = SK_ScalarMin;
1252 static SkScalar gDeviceGamma = SK_ScalarMin;
1253 
1254 /**
1255  * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1256  * the returned SkMaskGamma pointer is refed or forgotten.
1257  */
cached_mask_gamma(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma)1258 static const SkMaskGamma& cached_mask_gamma(SkScalar contrast, SkScalar paintGamma,
1259                                             SkScalar deviceGamma) {
1260     gMaskGammaCacheMutex.assertHeld();
1261     if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1262         if (nullptr == gLinearMaskGamma) {
1263             gLinearMaskGamma = new SkMaskGamma;
1264         }
1265         return *gLinearMaskGamma;
1266     }
1267     if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1268         SkSafeUnref(gMaskGamma);
1269         gMaskGamma = new SkMaskGamma(contrast, paintGamma, deviceGamma);
1270         gContrast = contrast;
1271         gPaintGamma = paintGamma;
1272         gDeviceGamma = deviceGamma;
1273     }
1274     return *gMaskGamma;
1275 }
1276 
1277 /**
1278  * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1279  */
GetMaskPreBlend(const SkScalerContextRec & rec)1280 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContextRec& rec) {
1281     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1282     const SkMaskGamma& maskGamma = cached_mask_gamma(rec.getContrast(),
1283                                                      rec.getPaintGamma(),
1284                                                      rec.getDeviceGamma());
1285     return maskGamma.preBlend(rec.getLuminanceColor());
1286 }
1287 
GetGammaLUTSize(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,int * width,int * height)1288 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
1289                                         SkScalar deviceGamma, int* width, int* height) {
1290     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1291     const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
1292                                                      paintGamma,
1293                                                      deviceGamma);
1294 
1295     maskGamma.getGammaTableDimensions(width, height);
1296     size_t size = (*width)*(*height)*sizeof(uint8_t);
1297 
1298     return size;
1299 }
1300 
GetGammaLUTData(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,uint8_t * data)1301 bool SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
1302                                       uint8_t* data) {
1303     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1304     const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
1305                                                      paintGamma,
1306                                                      deviceGamma);
1307     const uint8_t* gammaTables = maskGamma.getGammaTables();
1308     if (!gammaTables) {
1309         return false;
1310     }
1311 
1312     int width, height;
1313     maskGamma.getGammaTableDimensions(&width, &height);
1314     size_t size = width*height * sizeof(uint8_t);
1315     memcpy(data, gammaTables, size);
1316     return true;
1317 }
1318 
1319 ///////////////////////////////////////////////////////////////////////////////
1320 
1321 #include "SkStream.h"
1322 
asint(const void * p)1323 static uintptr_t asint(const void* p) {
1324     return reinterpret_cast<uintptr_t>(p);
1325 }
1326 
pack_4(unsigned a,unsigned b,unsigned c,unsigned d)1327 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1328     SkASSERT(a == (uint8_t)a);
1329     SkASSERT(b == (uint8_t)b);
1330     SkASSERT(c == (uint8_t)c);
1331     SkASSERT(d == (uint8_t)d);
1332     return (a << 24) | (b << 16) | (c << 8) | d;
1333 }
1334 
1335 #ifdef SK_DEBUG
ASSERT_FITS_IN(uint32_t value,int bitCount)1336     static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
1337         SkASSERT(bitCount > 0 && bitCount <= 32);
1338         uint32_t mask = ~0U;
1339         mask >>= (32 - bitCount);
1340         SkASSERT(0 == (value & ~mask));
1341     }
1342 #else
1343     #define ASSERT_FITS_IN(value, bitcount)
1344 #endif
1345 
1346 enum FlatFlags {
1347     kHasTypeface_FlatFlag = 0x1,
1348     kHasEffects_FlatFlag  = 0x2,
1349 
1350     kFlatFlagMask         = 0x3,
1351 };
1352 
1353 enum BitsPerField {
1354     kFlags_BPF  = 16,
1355     kHint_BPF   = 2,
1356     kAlign_BPF  = 2,
1357     kFilter_BPF = 2,
1358     kFlatFlags_BPF  = 3,
1359 };
1360 
BPF_Mask(int bits)1361 static inline int BPF_Mask(int bits) {
1362     return (1 << bits) - 1;
1363 }
1364 
pack_paint_flags(unsigned flags,unsigned hint,unsigned align,unsigned filter,unsigned flatFlags)1365 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
1366                                  unsigned filter, unsigned flatFlags) {
1367     ASSERT_FITS_IN(flags, kFlags_BPF);
1368     ASSERT_FITS_IN(hint, kHint_BPF);
1369     ASSERT_FITS_IN(align, kAlign_BPF);
1370     ASSERT_FITS_IN(filter, kFilter_BPF);
1371     ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
1372 
1373     // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
1374     // add more bits in the future.
1375     return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
1376 }
1377 
unpack_paint_flags(SkPaint * paint,uint32_t packed)1378 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
1379     paint->setFlags(packed >> 16);
1380     paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
1381     paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
1382     paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
1383     return (FlatFlags)(packed & kFlatFlagMask);
1384 }
1385 
1386 /*  To save space/time, we analyze the paint, and write a truncated version of
1387     it if there are not tricky elements like shaders, etc.
1388  */
flatten(SkWriteBuffer & buffer) const1389 void SkPaint::flatten(SkWriteBuffer& buffer) const {
1390     SkTypeface* tf = this->getTypeface();
1391     if (!tf) {
1392         // We force recording our typeface, even if its "default" since the receiver process
1393         // may have a different notion of default.
1394         tf = SkTypeface::GetDefaultTypeface();
1395         SkASSERT(tf);
1396     }
1397 
1398     uint8_t flatFlags = kHasTypeface_FlatFlag;
1399 
1400     if (asint(this->getPathEffect()) |
1401         asint(this->getShader()) |
1402         asint(this->getMaskFilter()) |
1403         asint(this->getColorFilter()) |
1404         asint(this->getLooper()) |
1405         asint(this->getImageFilter())) {
1406         flatFlags |= kHasEffects_FlatFlag;
1407     }
1408 
1409     buffer.writeScalar(this->getTextSize());
1410     buffer.writeScalar(this->getTextScaleX());
1411     buffer.writeScalar(this->getTextSkewX());
1412     buffer.writeScalar(this->getStrokeWidth());
1413     buffer.writeScalar(this->getStrokeMiter());
1414     buffer.writeColor(this->getColor());
1415 
1416     buffer.writeUInt(pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
1417                                       this->getFilterQuality(), flatFlags));
1418     buffer.writeUInt(pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1419                             (this->getStyle() << 4) | this->getTextEncoding(),
1420                             fBlendMode));
1421 
1422     buffer.writeTypeface(tf);
1423 
1424     if (flatFlags & kHasEffects_FlatFlag) {
1425         buffer.writeFlattenable(this->getPathEffect());
1426         buffer.writeFlattenable(this->getShader());
1427         buffer.writeFlattenable(this->getMaskFilter());
1428         buffer.writeFlattenable(this->getColorFilter());
1429         buffer.write32(0);  // use to be SkRasterizer
1430         buffer.writeFlattenable(this->getLooper());
1431         buffer.writeFlattenable(this->getImageFilter());
1432     }
1433 }
1434 
unflatten(SkReadBuffer & buffer)1435 bool SkPaint::unflatten(SkReadBuffer& buffer) {
1436     SkSafeRange safe;
1437 
1438     this->setTextSize(buffer.readScalar());
1439     this->setTextScaleX(buffer.readScalar());
1440     this->setTextSkewX(buffer.readScalar());
1441     this->setStrokeWidth(buffer.readScalar());
1442     this->setStrokeMiter(buffer.readScalar());
1443     this->setColor(buffer.readColor());
1444 
1445     unsigned flatFlags = unpack_paint_flags(this, buffer.readUInt());
1446 
1447     uint32_t tmp = buffer.readUInt();
1448     this->setStrokeCap(safe.checkLE((tmp >> 24) & 0xFF, kLast_Cap));
1449     this->setStrokeJoin(safe.checkLE((tmp >> 16) & 0xFF, kLast_Join));
1450     this->setStyle(safe.checkLE((tmp >> 12) & 0xF, kStrokeAndFill_Style));
1451     this->setTextEncoding(safe.checkLE((tmp >> 8) & 0xF, kGlyphID_TextEncoding));
1452     this->setBlendMode(safe.checkLE(tmp & 0xFF, SkBlendMode::kLastMode));
1453 
1454     if (flatFlags & kHasTypeface_FlatFlag) {
1455         this->setTypeface(buffer.readTypeface());
1456     } else {
1457         this->setTypeface(nullptr);
1458     }
1459 
1460     if (flatFlags & kHasEffects_FlatFlag) {
1461         this->setPathEffect(buffer.readPathEffect());
1462         this->setShader(buffer.readShader());
1463         this->setMaskFilter(buffer.readMaskFilter());
1464         this->setColorFilter(buffer.readColorFilter());
1465         (void)buffer.read32();  // use to be SkRasterizer
1466         this->setLooper(buffer.readDrawLooper());
1467         this->setImageFilter(buffer.readImageFilter());
1468     } else {
1469         this->setPathEffect(nullptr);
1470         this->setShader(nullptr);
1471         this->setMaskFilter(nullptr);
1472         this->setColorFilter(nullptr);
1473         this->setLooper(nullptr);
1474         this->setImageFilter(nullptr);
1475     }
1476 
1477     if (!buffer.validate(safe)) {
1478         this->reset();
1479         return false;
1480     }
1481     return true;
1482 }
1483 
1484 ///////////////////////////////////////////////////////////////////////////////
1485 
getFillPath(const SkPath & src,SkPath * dst,const SkRect * cullRect,SkScalar resScale) const1486 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
1487                           SkScalar resScale) const {
1488     if (!src.isFinite()) {
1489         dst->reset();
1490         return false;
1491     }
1492 
1493     SkStrokeRec rec(*this, resScale);
1494 
1495     const SkPath* srcPtr = &src;
1496     SkPath tmpPath;
1497 
1498     if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
1499         srcPtr = &tmpPath;
1500     }
1501 
1502     if (!rec.applyToPath(dst, *srcPtr)) {
1503         if (srcPtr == &tmpPath) {
1504             // If path's were copy-on-write, this trick would not be needed.
1505             // As it is, we want to save making a deep-copy from tmpPath -> dst
1506             // since we know we're just going to delete tmpPath when we return,
1507             // so the swap saves that copy.
1508             dst->swap(tmpPath);
1509         } else {
1510             *dst = *srcPtr;
1511         }
1512     }
1513 
1514     if (!dst->isFinite()) {
1515         dst->reset();
1516         return false;
1517     }
1518     return !rec.isHairlineStyle();
1519 }
1520 
canComputeFastBounds() const1521 bool SkPaint::canComputeFastBounds() const {
1522     if (this->getLooper()) {
1523         return this->getLooper()->canComputeFastBounds(*this);
1524     }
1525     if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
1526         return false;
1527     }
1528     return true;
1529 }
1530 
doComputeFastBounds(const SkRect & origSrc,SkRect * storage,Style style) const1531 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
1532                                            SkRect* storage,
1533                                            Style style) const {
1534     SkASSERT(storage);
1535 
1536     const SkRect* src = &origSrc;
1537 
1538     if (this->getLooper()) {
1539         SkASSERT(this->getLooper()->canComputeFastBounds(*this));
1540         this->getLooper()->computeFastBounds(*this, *src, storage);
1541         return *storage;
1542     }
1543 
1544     SkRect tmpSrc;
1545     if (this->getPathEffect()) {
1546         this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
1547         src = &tmpSrc;
1548     }
1549 
1550     SkScalar radius = SkStrokeRec::GetInflationRadius(*this, style);
1551     *storage = src->makeOutset(radius, radius);
1552 
1553     if (this->getMaskFilter()) {
1554         as_MFB(this->getMaskFilter())->computeFastBounds(*storage, storage);
1555     }
1556 
1557     if (this->getImageFilter()) {
1558         *storage = this->getImageFilter()->computeFastBounds(*storage);
1559     }
1560 
1561     return *storage;
1562 }
1563 
1564 #ifndef SK_IGNORE_TO_STRING
1565 
toString(SkString * str) const1566 void SkPaint::toString(SkString* str) const {
1567     str->append("<dl><dt>SkPaint:</dt><dd><dl>");
1568 
1569     SkTypeface* typeface = this->getTypeface();
1570     if (typeface) {
1571         SkDynamicMemoryWStream ostream;
1572         typeface->serialize(&ostream);
1573         std::unique_ptr<SkStreamAsset> istream(ostream.detachAsStream());
1574 
1575         SkFontDescriptor descriptor;
1576         if (!SkFontDescriptor::Deserialize(istream.get(), &descriptor)) {
1577             str->append("<dt>FontDescriptor deserialization failed</dt>");
1578         } else {
1579             str->append("<dt>Font Family Name:</dt><dd>");
1580             str->append(descriptor.getFamilyName());
1581             str->append("</dd><dt>Font Full Name:</dt><dd>");
1582             str->append(descriptor.getFullName());
1583             str->append("</dd><dt>Font PS Name:</dt><dd>");
1584             str->append(descriptor.getPostscriptName());
1585             str->append("</dd>");
1586         }
1587     }
1588 
1589     str->append("<dt>TextSize:</dt><dd>");
1590     str->appendScalar(this->getTextSize());
1591     str->append("</dd>");
1592 
1593     str->append("<dt>TextScaleX:</dt><dd>");
1594     str->appendScalar(this->getTextScaleX());
1595     str->append("</dd>");
1596 
1597     str->append("<dt>TextSkewX:</dt><dd>");
1598     str->appendScalar(this->getTextSkewX());
1599     str->append("</dd>");
1600 
1601     SkPathEffect* pathEffect = this->getPathEffect();
1602     if (pathEffect) {
1603         str->append("<dt>PathEffect:</dt><dd>");
1604         pathEffect->toString(str);
1605         str->append("</dd>");
1606     }
1607 
1608     if (const auto* shader = as_SB(this->getShader())) {
1609         str->append("<dt>Shader:</dt><dd>");
1610         shader->toString(str);
1611         str->append("</dd>");
1612     }
1613 
1614     if (!this->isSrcOver()) {
1615         str->appendf("<dt>Xfermode:</dt><dd>%d</dd>", fBlendMode);
1616     }
1617 
1618     SkMaskFilter* maskFilter = this->getMaskFilter();
1619     if (maskFilter) {
1620         str->append("<dt>MaskFilter:</dt><dd>");
1621         as_MFB(maskFilter)->toString(str);
1622         str->append("</dd>");
1623     }
1624 
1625     SkColorFilter* colorFilter = this->getColorFilter();
1626     if (colorFilter) {
1627         str->append("<dt>ColorFilter:</dt><dd>");
1628         colorFilter->toString(str);
1629         str->append("</dd>");
1630     }
1631 
1632     SkDrawLooper* looper = this->getLooper();
1633     if (looper) {
1634         str->append("<dt>DrawLooper:</dt><dd>");
1635         looper->toString(str);
1636         str->append("</dd>");
1637     }
1638 
1639     SkImageFilter* imageFilter = this->getImageFilter();
1640     if (imageFilter) {
1641         str->append("<dt>ImageFilter:</dt><dd>");
1642         imageFilter->toString(str);
1643         str->append("</dd>");
1644     }
1645 
1646     str->append("<dt>Color:</dt><dd>0x");
1647     SkColor color = this->getColor();
1648     str->appendHex(color);
1649     str->append("</dd>");
1650 
1651     str->append("<dt>Stroke Width:</dt><dd>");
1652     str->appendScalar(this->getStrokeWidth());
1653     str->append("</dd>");
1654 
1655     str->append("<dt>Stroke Miter:</dt><dd>");
1656     str->appendScalar(this->getStrokeMiter());
1657     str->append("</dd>");
1658 
1659     str->append("<dt>Flags:</dt><dd>(");
1660     if (this->getFlags()) {
1661         bool needSeparator = false;
1662         SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
1663         SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
1664         SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
1665         SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
1666         SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
1667         SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
1668         SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
1669         SkAddFlagToString(str, this->isEmbeddedBitmapText(),
1670                           "EmbeddedBitmapText", &needSeparator);
1671         SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
1672         SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
1673         SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
1674                           "GenA8FromLCD", &needSeparator);
1675     } else {
1676         str->append("None");
1677     }
1678     str->append(")</dd>");
1679 
1680     str->append("<dt>FilterLevel:</dt><dd>");
1681     static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" };
1682     str->append(gFilterQualityStrings[this->getFilterQuality()]);
1683     str->append("</dd>");
1684 
1685     str->append("<dt>TextAlign:</dt><dd>");
1686     static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
1687     str->append(gTextAlignStrings[this->getTextAlign()]);
1688     str->append("</dd>");
1689 
1690     str->append("<dt>CapType:</dt><dd>");
1691     static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
1692     str->append(gStrokeCapStrings[this->getStrokeCap()]);
1693     str->append("</dd>");
1694 
1695     str->append("<dt>JoinType:</dt><dd>");
1696     static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
1697     str->append(gJoinStrings[this->getStrokeJoin()]);
1698     str->append("</dd>");
1699 
1700     str->append("<dt>Style:</dt><dd>");
1701     static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
1702     str->append(gStyleStrings[this->getStyle()]);
1703     str->append("</dd>");
1704 
1705     str->append("<dt>TextEncoding:</dt><dd>");
1706     static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
1707     str->append(gTextEncodingStrings[this->getTextEncoding()]);
1708     str->append("</dd>");
1709 
1710     str->append("<dt>Hinting:</dt><dd>");
1711     static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
1712     str->append(gHintingStrings[this->getHinting()]);
1713     str->append("</dd>");
1714 
1715     str->append("</dd></dl></dl>");
1716 }
1717 #endif
1718 
1719 ///////////////////////////////////////////////////////////////////////////////
1720 
has_thick_frame(const SkPaint & paint)1721 static bool has_thick_frame(const SkPaint& paint) {
1722     return  paint.getStrokeWidth() > 0 &&
1723             paint.getStyle() != SkPaint::kFill_Style;
1724 }
1725 
SkTextBaseIter(const char text[],size_t length,const SkPaint & paint,bool applyStrokeAndPathEffects)1726 SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
1727                                    const SkPaint& paint,
1728                                    bool applyStrokeAndPathEffects)
1729     : fPaint(paint) {
1730     fGlyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
1731                                                  paint.isDevKernText(),
1732                                                  true);
1733 
1734     fPaint.setLinearText(true);
1735     fPaint.setMaskFilter(nullptr);   // don't want this affecting our path-cache lookup
1736 
1737     if (fPaint.getPathEffect() == nullptr && !has_thick_frame(fPaint)) {
1738         applyStrokeAndPathEffects = false;
1739     }
1740 
1741     // can't use our canonical size if we need to apply patheffects
1742     if (fPaint.getPathEffect() == nullptr) {
1743         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
1744         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
1745         if (has_thick_frame(fPaint)) {
1746             fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale);
1747         }
1748     } else {
1749         fScale = SK_Scalar1;
1750     }
1751 
1752     if (!applyStrokeAndPathEffects) {
1753         fPaint.setStyle(SkPaint::kFill_Style);
1754         fPaint.setPathEffect(nullptr);
1755     }
1756 
1757     // SRGBTODO: Is this correct?
1758     fCache = SkGlyphCache::DetachCacheUsingPaint(fPaint, nullptr,
1759                                                  SkScalerContextFlags::kFakeGammaAndBoostContrast,
1760                                                  nullptr);
1761 
1762     SkPaint::Style  style = SkPaint::kFill_Style;
1763     sk_sp<SkPathEffect> pe;
1764 
1765     if (!applyStrokeAndPathEffects) {
1766         style = paint.getStyle();       // restore
1767         pe = paint.refPathEffect();     // restore
1768     }
1769     fPaint.setStyle(style);
1770     fPaint.setPathEffect(pe);
1771     fPaint.setMaskFilter(paint.refMaskFilter());    // restore
1772 
1773     // now compute fXOffset if needed
1774 
1775     SkScalar xOffset = 0;
1776     if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
1777         int      count;
1778         SkScalar width = fPaint.measure_text(fCache, text, length, &count, nullptr) * fScale;
1779         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1780             width = SkScalarHalf(width);
1781         }
1782         xOffset = -width;
1783     }
1784     fXPos = xOffset;
1785     fPrevAdvance = 0;
1786 
1787     fText = text;
1788     fStop = text + length;
1789 
1790     fXYIndex = paint.isVerticalText() ? 1 : 0;
1791 }
1792 
~SkTextBaseIter()1793 SkTextBaseIter::~SkTextBaseIter() {
1794     SkGlyphCache::AttachCache(fCache);
1795 }
1796 
next(const SkPath ** path,SkScalar * xpos)1797 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
1798     if (fText < fStop) {
1799         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1800 
1801         fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
1802         fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
1803 
1804         if (glyph.fWidth) {
1805             if (path) {
1806                 *path = fCache->findPath(glyph);
1807             }
1808         } else {
1809             if (path) {
1810                 *path = nullptr;
1811             }
1812         }
1813         if (xpos) {
1814             *xpos = fXPos;
1815         }
1816         return true;
1817     }
1818     return false;
1819 }
1820 
next(SkScalar * array,int * count)1821 bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
1822     const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1823     fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
1824     fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
1825     if (fCache->findPath(glyph)) {
1826         fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex),
1827                 const_cast<SkGlyph*>(&glyph), array, count);
1828     }
1829     return fText < fStop;
1830 }
1831 
1832 ///////////////////////////////////////////////////////////////////////////////
1833 
1834 // return true if the filter exists, and may affect alpha
affects_alpha(const SkColorFilter * cf)1835 static bool affects_alpha(const SkColorFilter* cf) {
1836     return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
1837 }
1838 
1839 // return true if the filter exists, and may affect alpha
affects_alpha(const SkImageFilter * imf)1840 static bool affects_alpha(const SkImageFilter* imf) {
1841     // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
1842     // ala colorfilters
1843     return imf != nullptr;
1844 }
1845 
nothingToDraw() const1846 bool SkPaint::nothingToDraw() const {
1847     if (fDrawLooper) {
1848         return false;
1849     }
1850     switch ((SkBlendMode)fBlendMode) {
1851         case SkBlendMode::kSrcOver:
1852         case SkBlendMode::kSrcATop:
1853         case SkBlendMode::kDstOut:
1854         case SkBlendMode::kDstOver:
1855         case SkBlendMode::kPlus:
1856             if (0 == this->getAlpha()) {
1857                 return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
1858             }
1859             break;
1860         case SkBlendMode::kDst:
1861             return true;
1862         default:
1863             break;
1864     }
1865     return false;
1866 }
1867 
getHash() const1868 uint32_t SkPaint::getHash() const {
1869     // We're going to hash 7 pointers and 7 32-bit values, finishing up with fBitfields,
1870     // so fBitfields should be 7 pointers and 6 32-bit values from the start.
1871     static_assert(offsetof(SkPaint, fBitfields) == 7 * sizeof(void*) + 7 * sizeof(uint32_t),
1872                   "SkPaint_notPackedTightly");
1873     return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
1874                         offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
1875 }
1876