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 "SkGlyphCache.h"
16 #include "SkImageFilter.h"
17 #include "SkMaskFilter.h"
18 #include "SkMaskGamma.h"
19 #include "SkMutex.h"
20 #include "SkReadBuffer.h"
21 #include "SkWriteBuffer.h"
22 #include "SkOpts.h"
23 #include "SkPaintDefaults.h"
24 #include "SkPathEffect.h"
25 #include "SkRasterizer.h"
26 #include "SkScalar.h"
27 #include "SkScalerContext.h"
28 #include "SkShader.h"
29 #include "SkStringUtils.h"
30 #include "SkStroke.h"
31 #include "SkStrokeRec.h"
32 #include "SkSurfacePriv.h"
33 #include "SkTextBlob.h"
34 #include "SkTextBlobRunIterator.h"
35 #include "SkTextFormatParams.h"
36 #include "SkTextToPathIter.h"
37 #include "SkTLazy.h"
38 #include "SkTypeface.h"
39 
set_clear_mask(uint32_t bits,bool cond,uint32_t mask)40 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
41     return cond ? bits | mask : bits & ~mask;
42 }
43 
44 // define this to get a printf for out-of-range parameter in setters
45 // e.g. setTextSize(-1)
46 //#define SK_REPORT_API_RANGE_CHECK
47 
SkPaint()48 SkPaint::SkPaint() {
49     fTextSize   = SkPaintDefaults_TextSize;
50     fTextScaleX = SK_Scalar1;
51     fTextSkewX  = 0;
52     fColor      = SK_ColorBLACK;
53     fWidth      = 0;
54     fMiterLimit = SkPaintDefaults_MiterLimit;
55     fBlendMode  = (unsigned)SkBlendMode::kSrcOver;
56 
57     // Zero all bitfields, then set some non-zero defaults.
58     fBitfieldsUInt           = 0;
59     fBitfields.fFlags        = SkPaintDefaults_Flags;
60     fBitfields.fCapType      = kDefault_Cap;
61     fBitfields.fJoinType     = kDefault_Join;
62     fBitfields.fTextAlign    = kLeft_Align;
63     fBitfields.fStyle        = kFill_Style;
64     fBitfields.fTextEncoding = kUTF8_TextEncoding;
65     fBitfields.fHinting      = SkPaintDefaults_Hinting;
66 }
67 
SkPaint(const SkPaint & src)68 SkPaint::SkPaint(const SkPaint& src)
69 #define COPY(field) field(src.field)
70     : COPY(fTypeface)
71     , COPY(fPathEffect)
72     , COPY(fShader)
73     , COPY(fMaskFilter)
74     , COPY(fColorFilter)
75     , COPY(fRasterizer)
76     , COPY(fDrawLooper)
77     , COPY(fImageFilter)
78     , COPY(fTextSize)
79     , COPY(fTextScaleX)
80     , COPY(fTextSkewX)
81     , COPY(fColor)
82     , COPY(fWidth)
83     , COPY(fMiterLimit)
84     , COPY(fBlendMode)
85     , COPY(fBitfields)
86 #undef COPY
87 {}
88 
SkPaint(SkPaint && src)89 SkPaint::SkPaint(SkPaint&& src) {
90 #define MOVE(field) field = std::move(src.field)
91     MOVE(fTypeface);
92     MOVE(fPathEffect);
93     MOVE(fShader);
94     MOVE(fMaskFilter);
95     MOVE(fColorFilter);
96     MOVE(fRasterizer);
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(fRasterizer);
124     ASSIGN(fDrawLooper);
125     ASSIGN(fImageFilter);
126     ASSIGN(fTextSize);
127     ASSIGN(fTextScaleX);
128     ASSIGN(fTextSkewX);
129     ASSIGN(fColor);
130     ASSIGN(fWidth);
131     ASSIGN(fMiterLimit);
132     ASSIGN(fBlendMode);
133     ASSIGN(fBitfields);
134 #undef ASSIGN
135 
136     return *this;
137 }
138 
operator =(SkPaint && src)139 SkPaint& SkPaint::operator=(SkPaint&& src) {
140     if (this == &src) {
141         return *this;
142     }
143 
144 #define MOVE(field) field = std::move(src.field)
145     MOVE(fTypeface);
146     MOVE(fPathEffect);
147     MOVE(fShader);
148     MOVE(fMaskFilter);
149     MOVE(fColorFilter);
150     MOVE(fRasterizer);
151     MOVE(fDrawLooper);
152     MOVE(fImageFilter);
153     MOVE(fTextSize);
154     MOVE(fTextScaleX);
155     MOVE(fTextSkewX);
156     MOVE(fColor);
157     MOVE(fWidth);
158     MOVE(fMiterLimit);
159     MOVE(fBlendMode);
160     MOVE(fBitfields);
161 #undef MOVE
162 
163     return *this;
164 }
165 
operator ==(const SkPaint & a,const SkPaint & b)166 bool operator==(const SkPaint& a, const SkPaint& b) {
167 #define EQUAL(field) (a.field == b.field)
168     return EQUAL(fTypeface)
169         && EQUAL(fPathEffect)
170         && EQUAL(fShader)
171         && EQUAL(fMaskFilter)
172         && EQUAL(fColorFilter)
173         && EQUAL(fRasterizer)
174         && EQUAL(fDrawLooper)
175         && EQUAL(fImageFilter)
176         && EQUAL(fTextSize)
177         && EQUAL(fTextScaleX)
178         && EQUAL(fTextSkewX)
179         && EQUAL(fColor)
180         && EQUAL(fWidth)
181         && EQUAL(fMiterLimit)
182         && EQUAL(fBlendMode)
183         && EQUAL(fBitfieldsUInt)
184         ;
185 #undef EQUAL
186 }
187 
188 #define DEFINE_REF_FOO(type)    sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
189 DEFINE_REF_FOO(ColorFilter)
DEFINE_REF_FOO(DrawLooper)190 DEFINE_REF_FOO(DrawLooper)
191 DEFINE_REF_FOO(ImageFilter)
192 DEFINE_REF_FOO(MaskFilter)
193 DEFINE_REF_FOO(PathEffect)
194 DEFINE_REF_FOO(Rasterizer)
195 DEFINE_REF_FOO(Shader)
196 DEFINE_REF_FOO(Typeface)
197 #undef DEFINE_REF_FOO
198 
199 void SkPaint::reset() {
200     SkPaint init;
201     *this = init;
202 }
203 
setFilterQuality(SkFilterQuality quality)204 void SkPaint::setFilterQuality(SkFilterQuality quality) {
205     fBitfields.fFilterQuality = quality;
206 }
207 
setHinting(Hinting hintingLevel)208 void SkPaint::setHinting(Hinting hintingLevel) {
209     fBitfields.fHinting = hintingLevel;
210 }
211 
setFlags(uint32_t flags)212 void SkPaint::setFlags(uint32_t flags) {
213     fBitfields.fFlags = flags;
214 }
215 
setAntiAlias(bool doAA)216 void SkPaint::setAntiAlias(bool doAA) {
217     this->setFlags(set_clear_mask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
218 }
219 
setDither(bool doDither)220 void SkPaint::setDither(bool doDither) {
221     this->setFlags(set_clear_mask(fBitfields.fFlags, doDither, kDither_Flag));
222 }
223 
setSubpixelText(bool doSubpixel)224 void SkPaint::setSubpixelText(bool doSubpixel) {
225     this->setFlags(set_clear_mask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
226 }
227 
setLCDRenderText(bool doLCDRender)228 void SkPaint::setLCDRenderText(bool doLCDRender) {
229     this->setFlags(set_clear_mask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
230 }
231 
setEmbeddedBitmapText(bool doEmbeddedBitmapText)232 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
233     this->setFlags(set_clear_mask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
234 }
235 
setAutohinted(bool useAutohinter)236 void SkPaint::setAutohinted(bool useAutohinter) {
237     this->setFlags(set_clear_mask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
238 }
239 
setLinearText(bool doLinearText)240 void SkPaint::setLinearText(bool doLinearText) {
241     this->setFlags(set_clear_mask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
242 }
243 
setVerticalText(bool doVertical)244 void SkPaint::setVerticalText(bool doVertical) {
245     this->setFlags(set_clear_mask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
246 }
247 
setFakeBoldText(bool doFakeBold)248 void SkPaint::setFakeBoldText(bool doFakeBold) {
249     this->setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
250 }
251 
setDevKernText(bool doDevKern)252 void SkPaint::setDevKernText(bool doDevKern) {
253     this->setFlags(set_clear_mask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
254 }
255 
setStyle(Style style)256 void SkPaint::setStyle(Style style) {
257     if ((unsigned)style < kStyleCount) {
258         fBitfields.fStyle = style;
259     } else {
260 #ifdef SK_REPORT_API_RANGE_CHECK
261         SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
262 #endif
263     }
264 }
265 
setColor(SkColor color)266 void SkPaint::setColor(SkColor color) {
267     fColor = color;
268 }
269 
setAlpha(U8CPU a)270 void SkPaint::setAlpha(U8CPU a) {
271     this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
272                                   SkColorGetG(fColor), SkColorGetB(fColor)));
273 }
274 
setARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)275 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
276     this->setColor(SkColorSetARGB(a, r, g, b));
277 }
278 
setStrokeWidth(SkScalar width)279 void SkPaint::setStrokeWidth(SkScalar width) {
280     if (width >= 0) {
281         fWidth = width;
282     } else {
283 #ifdef SK_REPORT_API_RANGE_CHECK
284         SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
285 #endif
286     }
287 }
288 
setStrokeMiter(SkScalar limit)289 void SkPaint::setStrokeMiter(SkScalar limit) {
290     if (limit >= 0) {
291         fMiterLimit = limit;
292     } else {
293 #ifdef SK_REPORT_API_RANGE_CHECK
294         SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
295 #endif
296     }
297 }
298 
setStrokeCap(Cap ct)299 void SkPaint::setStrokeCap(Cap ct) {
300     if ((unsigned)ct < kCapCount) {
301         fBitfields.fCapType = SkToU8(ct);
302     } else {
303 #ifdef SK_REPORT_API_RANGE_CHECK
304         SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
305 #endif
306     }
307 }
308 
setStrokeJoin(Join jt)309 void SkPaint::setStrokeJoin(Join jt) {
310     if ((unsigned)jt < kJoinCount) {
311         fBitfields.fJoinType = SkToU8(jt);
312     } else {
313 #ifdef SK_REPORT_API_RANGE_CHECK
314         SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
315 #endif
316     }
317 }
318 
319 ///////////////////////////////////////////////////////////////////////////////
320 
setTextAlign(Align align)321 void SkPaint::setTextAlign(Align align) {
322     if ((unsigned)align < kAlignCount) {
323         fBitfields.fTextAlign = SkToU8(align);
324     } else {
325 #ifdef SK_REPORT_API_RANGE_CHECK
326         SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
327 #endif
328     }
329 }
330 
setTextSize(SkScalar ts)331 void SkPaint::setTextSize(SkScalar ts) {
332     if (ts >= 0) {
333         fTextSize = ts;
334     } else {
335 #ifdef SK_REPORT_API_RANGE_CHECK
336         SkDebugf("SkPaint::setTextSize() called with negative value\n");
337 #endif
338     }
339 }
340 
setTextScaleX(SkScalar scaleX)341 void SkPaint::setTextScaleX(SkScalar scaleX) {
342     fTextScaleX = scaleX;
343 }
344 
setTextSkewX(SkScalar skewX)345 void SkPaint::setTextSkewX(SkScalar skewX) {
346     fTextSkewX = skewX;
347 }
348 
setTextEncoding(TextEncoding encoding)349 void SkPaint::setTextEncoding(TextEncoding encoding) {
350     if ((unsigned)encoding <= kGlyphID_TextEncoding) {
351         fBitfields.fTextEncoding = encoding;
352     } else {
353 #ifdef SK_REPORT_API_RANGE_CHECK
354         SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
355 #endif
356     }
357 }
358 
359 ///////////////////////////////////////////////////////////////////////////////
360 
361 #define MOVE_FIELD(Field) void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
362 MOVE_FIELD(Typeface)
MOVE_FIELD(Rasterizer)363 MOVE_FIELD(Rasterizer)
364 MOVE_FIELD(ImageFilter)
365 MOVE_FIELD(Shader)
366 MOVE_FIELD(ColorFilter)
367 MOVE_FIELD(PathEffect)
368 MOVE_FIELD(MaskFilter)
369 MOVE_FIELD(DrawLooper)
370 #undef MOVE_FIELD
371 void SkPaint::setLooper(sk_sp<SkDrawLooper> looper) { fDrawLooper = std::move(looper); }
372 
373 ///////////////////////////////////////////////////////////////////////////////
374 
mag2(SkScalar x,SkScalar y)375 static SkScalar mag2(SkScalar x, SkScalar y) {
376     return x * x + y * y;
377 }
378 
tooBig(const SkMatrix & m,SkScalar ma2max)379 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
380     return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
381             ||
382             mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
383 }
384 
TooBigToUseCache(const SkMatrix & ctm,const SkMatrix & textM)385 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
386     SkASSERT(!ctm.hasPerspective());
387     SkASSERT(!textM.hasPerspective());
388 
389     SkMatrix matrix;
390     matrix.setConcat(ctm, textM);
391     return tooBig(matrix, MaxCacheSize2());
392 }
393 
394 
395 ///////////////////////////////////////////////////////////////////////////////
396 
397 #include "SkGlyphCache.h"
398 #include "SkUtils.h"
399 
DetachDescProc(SkTypeface * typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc,void * context)400 static void DetachDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
401                            const SkDescriptor* desc, void* context) {
402     *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, effects, desc);
403 }
404 
textToGlyphs(const void * textData,size_t byteLength,uint16_t glyphs[]) const405 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const {
406     if (byteLength == 0) {
407         return 0;
408     }
409 
410     SkASSERT(textData != nullptr);
411 
412     if (nullptr == glyphs) {
413         switch (this->getTextEncoding()) {
414         case kUTF8_TextEncoding:
415             return SkUTF8_CountUnichars((const char*)textData, byteLength);
416         case kUTF16_TextEncoding:
417             return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
418         case kUTF32_TextEncoding:
419             return SkToInt(byteLength >> 2);
420         case kGlyphID_TextEncoding:
421             return SkToInt(byteLength >> 1);
422         default:
423             SkDEBUGFAIL("unknown text encoding");
424         }
425         return 0;
426     }
427 
428     // if we get here, we have a valid glyphs[] array, so time to fill it in
429 
430     // handle this encoding before the setup for the glyphcache
431     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
432         // we want to ignore the low bit of byteLength
433         memcpy(glyphs, textData, byteLength >> 1 << 1);
434         return SkToInt(byteLength >> 1);
435     }
436 
437     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
438     SkGlyphCache*    cache = autoCache.getCache();
439 
440     const char* text = (const char*)textData;
441     const char* stop = text + byteLength;
442     uint16_t*   gptr = glyphs;
443 
444     switch (this->getTextEncoding()) {
445         case SkPaint::kUTF8_TextEncoding:
446             while (text < stop) {
447                 SkUnichar u = SkUTF8_NextUnicharWithError(&text, stop);
448                 if (u < 0) {
449                     return 0;  // bad UTF-8 sequence
450                 }
451                 *gptr++ = cache->unicharToGlyph(u);
452             }
453             break;
454         case SkPaint::kUTF16_TextEncoding: {
455             const uint16_t* text16 = (const uint16_t*)text;
456             const uint16_t* stop16 = (const uint16_t*)stop;
457             while (text16 < stop16) {
458                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
459             }
460             break;
461         }
462         case kUTF32_TextEncoding: {
463             const int32_t* text32 = (const int32_t*)text;
464             const int32_t* stop32 = (const int32_t*)stop;
465             while (text32 < stop32) {
466                 *gptr++ = cache->unicharToGlyph(*text32++);
467             }
468             break;
469         }
470         default:
471             SkDEBUGFAIL("unknown text encoding");
472     }
473     return SkToInt(gptr - glyphs);
474 }
475 
containsText(const void * textData,size_t byteLength) const476 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
477     if (0 == byteLength) {
478         return true;
479     }
480 
481     SkASSERT(textData != nullptr);
482 
483     // handle this encoding before the setup for the glyphcache
484     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
485         const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
486         size_t count = byteLength >> 1;
487         for (size_t i = 0; i < count; i++) {
488             if (0 == glyphID[i]) {
489                 return false;
490             }
491         }
492         return true;
493     }
494 
495     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
496     SkGlyphCache*    cache = autoCache.getCache();
497 
498     switch (this->getTextEncoding()) {
499         case SkPaint::kUTF8_TextEncoding: {
500             const char* text = static_cast<const char*>(textData);
501             const char* stop = text + byteLength;
502             while (text < stop) {
503                 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
504                     return false;
505                 }
506             }
507             break;
508         }
509         case SkPaint::kUTF16_TextEncoding: {
510             const uint16_t* text = static_cast<const uint16_t*>(textData);
511             const uint16_t* stop = text + (byteLength >> 1);
512             while (text < stop) {
513                 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
514                     return false;
515                 }
516             }
517             break;
518         }
519         case SkPaint::kUTF32_TextEncoding: {
520             const int32_t* text = static_cast<const int32_t*>(textData);
521             const int32_t* stop = text + (byteLength >> 2);
522             while (text < stop) {
523                 if (0 == cache->unicharToGlyph(*text++)) {
524                     return false;
525                 }
526             }
527             break;
528         }
529         default:
530             SkDEBUGFAIL("unknown text encoding");
531             return false;
532     }
533     return true;
534 }
535 
glyphsToUnichars(const uint16_t glyphs[],int count,SkUnichar textData[]) const536 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count, SkUnichar textData[]) const {
537     if (count <= 0) {
538         return;
539     }
540 
541     SkASSERT(glyphs != nullptr);
542     SkASSERT(textData != nullptr);
543 
544     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
545     SkAutoGlyphCache autoCache(*this, &props, nullptr);
546     SkGlyphCache*    cache = autoCache.getCache();
547 
548     for (int index = 0; index < count; index++) {
549         textData[index] = cache->glyphToUnichar(glyphs[index]);
550     }
551 }
552 
553 ///////////////////////////////////////////////////////////////////////////////
554 
sk_getMetrics_utf8_next(SkGlyphCache * cache,const char ** text)555 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
556                                               const char** text) {
557     SkASSERT(cache != nullptr);
558     SkASSERT(text != nullptr);
559 
560     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
561 }
562 
sk_getMetrics_utf16_next(SkGlyphCache * cache,const char ** text)563 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
564                                                const char** text) {
565     SkASSERT(cache != nullptr);
566     SkASSERT(text != nullptr);
567 
568     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
569 }
570 
sk_getMetrics_utf32_next(SkGlyphCache * cache,const char ** text)571 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
572                                                const char** text) {
573     SkASSERT(cache != nullptr);
574     SkASSERT(text != nullptr);
575 
576     const int32_t* ptr = *(const int32_t**)text;
577     SkUnichar uni = *ptr++;
578     *text = (const char*)ptr;
579     return cache->getUnicharMetrics(uni);
580 }
581 
sk_getMetrics_glyph_next(SkGlyphCache * cache,const char ** text)582 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
583                                                const char** text) {
584     SkASSERT(cache != nullptr);
585     SkASSERT(text != nullptr);
586 
587     const uint16_t* ptr = *(const uint16_t**)text;
588     unsigned glyphID = *ptr;
589     ptr += 1;
590     *text = (const char*)ptr;
591     return cache->getGlyphIDMetrics(glyphID);
592 }
593 
sk_getAdvance_utf8_next(SkGlyphCache * cache,const char ** text)594 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
595                                               const char** text) {
596     SkASSERT(cache != nullptr);
597     SkASSERT(text != nullptr);
598 
599     return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
600 }
601 
sk_getAdvance_utf16_next(SkGlyphCache * cache,const char ** text)602 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
603                                                const char** text) {
604     SkASSERT(cache != nullptr);
605     SkASSERT(text != nullptr);
606 
607     return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
608 }
609 
sk_getAdvance_utf32_next(SkGlyphCache * cache,const char ** text)610 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
611                                                const char** text) {
612     SkASSERT(cache != nullptr);
613     SkASSERT(text != nullptr);
614 
615     const int32_t* ptr = *(const int32_t**)text;
616     SkUnichar uni = *ptr++;
617     *text = (const char*)ptr;
618     return cache->getUnicharAdvance(uni);
619 }
620 
sk_getAdvance_glyph_next(SkGlyphCache * cache,const char ** text)621 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
622                                                const char** text) {
623     SkASSERT(cache != nullptr);
624     SkASSERT(text != nullptr);
625 
626     const uint16_t* ptr = *(const uint16_t**)text;
627     unsigned glyphID = *ptr;
628     ptr += 1;
629     *text = (const char*)ptr;
630     return cache->getGlyphIDAdvance(glyphID);
631 }
632 
GetGlyphCacheProc(TextEncoding encoding,bool isDevKern,bool needFullMetrics)633 SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
634                                                    bool isDevKern,
635                                                    bool needFullMetrics) {
636     static const GlyphCacheProc gGlyphCacheProcs[] = {
637         sk_getMetrics_utf8_next,
638         sk_getMetrics_utf16_next,
639         sk_getMetrics_utf32_next,
640         sk_getMetrics_glyph_next,
641 
642         sk_getAdvance_utf8_next,
643         sk_getAdvance_utf16_next,
644         sk_getAdvance_utf32_next,
645         sk_getAdvance_glyph_next,
646     };
647 
648     unsigned index = encoding;
649 
650     if (!needFullMetrics && !isDevKern) {
651         index += 4;
652     }
653 
654     SkASSERT(index < SK_ARRAY_COUNT(gGlyphCacheProcs));
655     return gGlyphCacheProcs[index];
656 }
657 
658 ///////////////////////////////////////////////////////////////////////////////
659 
660 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
661 SkPaint::kDevKernText_Flag          |       \
662 SkPaint::kLinearText_Flag           |       \
663 SkPaint::kLCDRenderText_Flag        |       \
664 SkPaint::kEmbeddedBitmapText_Flag   |       \
665 SkPaint::kAutoHinting_Flag          |       \
666 SkPaint::kGenA8FromLCD_Flag )
667 
setupForAsPaths()668 SkScalar SkPaint::setupForAsPaths() {
669     uint32_t flags = this->getFlags();
670     // clear the flags we don't care about
671     flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
672     // set the flags we do care about
673     flags |= SkPaint::kSubpixelText_Flag;
674 
675     this->setFlags(flags);
676     this->setHinting(SkPaint::kNo_Hinting);
677 
678     SkScalar textSize = fTextSize;
679     this->setTextSize(kCanonicalTextSizeForPaths);
680     return textSize / kCanonicalTextSizeForPaths;
681 }
682 
683 class SkCanonicalizePaint {
684 public:
SkCanonicalizePaint(const SkPaint & paint)685     SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
686         if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
687             SkPaint* p = fLazy.set(paint);
688             fScale = p->setupForAsPaths();
689             fPaint = p;
690         }
691     }
692 
getPaint() const693     const SkPaint& getPaint() const { return *fPaint; }
694 
695     /**
696      *  Returns 0 if the paint was unmodified, or the scale factor need to
697      *  the original textSize
698      */
getScale() const699     SkScalar getScale() const { return fScale; }
700 
701 private:
702     const SkPaint*   fPaint;
703     SkScalar         fScale;
704     SkTLazy<SkPaint> fLazy;
705 };
706 
set_bounds(const SkGlyph & g,SkRect * bounds)707 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
708     bounds->set(SkIntToScalar(g.fLeft),
709                 SkIntToScalar(g.fTop),
710                 SkIntToScalar(g.fLeft + g.fWidth),
711                 SkIntToScalar(g.fTop + g.fHeight));
712 }
713 
join_bounds_x(const SkGlyph & g,SkRect * bounds,SkScalar dx)714 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) {
715     bounds->join(SkIntToScalar(g.fLeft) + dx,
716                  SkIntToScalar(g.fTop),
717                  SkIntToScalar(g.fLeft + g.fWidth) + dx,
718                  SkIntToScalar(g.fTop + g.fHeight));
719 }
720 
join_bounds_y(const SkGlyph & g,SkRect * bounds,SkScalar dy)721 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, SkScalar dy) {
722     bounds->join(SkIntToScalar(g.fLeft),
723                  SkIntToScalar(g.fTop) + dy,
724                  SkIntToScalar(g.fLeft + g.fWidth),
725                  SkIntToScalar(g.fTop + g.fHeight) + dy);
726 }
727 
728 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, SkScalar);
729 
730 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
advance(const SkGlyph & glyph,int xyIndex)731 static SkScalar advance(const SkGlyph& glyph, int xyIndex) {
732     SkASSERT(0 == xyIndex || 1 == xyIndex);
733     return SkFloatToScalar((&glyph.fAdvanceX)[xyIndex]);
734 }
735 
measure_text(SkGlyphCache * cache,const char * text,size_t byteLength,int * count,SkRect * bounds) const736 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
737                                const char* text, size_t byteLength,
738                                int* count, SkRect* bounds) const {
739     SkASSERT(count);
740     if (byteLength == 0) {
741         *count = 0;
742         if (bounds) {
743             bounds->setEmpty();
744         }
745         return 0;
746     }
747 
748     GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(this->getTextEncoding(),
749                                                                this->isDevKernText(),
750                                                                nullptr != bounds);
751 
752     int xyIndex;
753     JoinBoundsProc joinBoundsProc;
754     if (this->isVerticalText()) {
755         xyIndex = 1;
756         joinBoundsProc = join_bounds_y;
757     } else {
758         xyIndex = 0;
759         joinBoundsProc = join_bounds_x;
760     }
761 
762     int         n = 1;
763     const char* stop = (const char*)text + byteLength;
764     const SkGlyph* g = &glyphCacheProc(cache, &text);
765     SkScalar x = advance(*g, xyIndex);
766 
767     if (nullptr == bounds) {
768         if (this->isDevKernText()) {
769             for (; text < stop; n++) {
770                 const int rsb = g->fRsbDelta;
771                 g = &glyphCacheProc(cache, &text);
772                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta) + advance(*g, xyIndex);
773             }
774         } else {
775             for (; text < stop; n++) {
776                 x += advance(glyphCacheProc(cache, &text), xyIndex);
777             }
778         }
779     } else {
780         set_bounds(*g, bounds);
781         if (this->isDevKernText()) {
782             for (; text < stop; n++) {
783                 const int rsb = g->fRsbDelta;
784                 g = &glyphCacheProc(cache, &text);
785                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta);
786                 joinBoundsProc(*g, bounds, x);
787                 x += advance(*g, xyIndex);
788             }
789         } else {
790             for (; text < stop; n++) {
791                 g = &glyphCacheProc(cache, &text);
792                 joinBoundsProc(*g, bounds, x);
793                 x += advance(*g, xyIndex);
794             }
795         }
796     }
797     SkASSERT(text == stop);
798 
799     *count = n;
800     return x;
801 }
802 
measureText(const void * textData,size_t length,SkRect * bounds) const803 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
804     const char* text = (const char*)textData;
805     SkASSERT(text != nullptr || length == 0);
806 
807     SkCanonicalizePaint canon(*this);
808     const SkPaint& paint = canon.getPaint();
809     SkScalar scale = canon.getScale();
810 
811     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
812     SkGlyphCache*       cache = autoCache.getCache();
813 
814     SkScalar width = 0;
815 
816     if (length > 0) {
817         int tempCount;
818 
819         width = paint.measure_text(cache, text, length, &tempCount, bounds);
820         if (scale) {
821             width *= scale;
822             if (bounds) {
823                 bounds->fLeft *= scale;
824                 bounds->fTop *= scale;
825                 bounds->fRight *= scale;
826                 bounds->fBottom *= scale;
827             }
828         }
829     } else if (bounds) {
830         // ensure that even if we don't measure_text we still update the bounds
831         bounds->setEmpty();
832     }
833     return width;
834 }
835 
breakText(const void * textD,size_t length,SkScalar maxWidth,SkScalar * measuredWidth) const836 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
837                           SkScalar* measuredWidth) const {
838     if (0 == length || 0 >= maxWidth) {
839         if (measuredWidth) {
840             *measuredWidth = 0;
841         }
842         return 0;
843     }
844 
845     if (0 == fTextSize) {
846         if (measuredWidth) {
847             *measuredWidth = 0;
848         }
849         return length;
850     }
851 
852     SkASSERT(textD != nullptr);
853     const char* text = (const char*)textD;
854     const char* stop = text + length;
855 
856     SkCanonicalizePaint canon(*this);
857     const SkPaint& paint = canon.getPaint();
858     SkScalar scale = canon.getScale();
859 
860     // adjust max in case we changed the textSize in paint
861     if (scale) {
862         maxWidth /= scale;
863     }
864 
865     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
866     SkGlyphCache*       cache = autoCache.getCache();
867 
868     GlyphCacheProc   glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
869                                                                  paint.isDevKernText(),
870                                                                  false);
871     const int        xyIndex = paint.isVerticalText() ? 1 : 0;
872     SkScalar         width = 0;
873 
874     if (this->isDevKernText()) {
875         int rsb = 0;
876         while (text < stop) {
877             const char* curr = text;
878             const SkGlyph& g = glyphCacheProc(cache, &text);
879             SkScalar x = SkAutoKern_Adjust(rsb, g.fLsbDelta) + advance(g, xyIndex);
880             if ((width += x) > maxWidth) {
881                 width -= x;
882                 text = curr;
883                 break;
884             }
885             rsb = g.fRsbDelta;
886         }
887     } else {
888         while (text < stop) {
889             const char* curr = text;
890             SkScalar x = advance(glyphCacheProc(cache, &text), xyIndex);
891             if ((width += x) > maxWidth) {
892                 width -= x;
893                 text = curr;
894                 break;
895             }
896         }
897     }
898 
899     if (measuredWidth) {
900         if (scale) {
901             width *= scale;
902         }
903         *measuredWidth = width;
904     }
905 
906     // return the number of bytes measured
907     return text - stop + length;
908 }
909 
910 ///////////////////////////////////////////////////////////////////////////////
911 
FontMetricsCacheProc(const SkGlyphCache * cache,void * context)912 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
913     *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
914     return false;   // don't detach the cache
915 }
916 
FontMetricsDescProc(SkTypeface * typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc,void * context)917 static void FontMetricsDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
918                                 const SkDescriptor* desc, void* context) {
919     SkGlyphCache::VisitCache(typeface, effects, desc, FontMetricsCacheProc, context);
920 }
921 
getFontMetrics(FontMetrics * metrics,SkScalar zoom) const922 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
923     SkCanonicalizePaint canon(*this);
924     const SkPaint& paint = canon.getPaint();
925     SkScalar scale = canon.getScale();
926 
927     SkMatrix zoomMatrix, *zoomPtr = nullptr;
928     if (zoom) {
929         zoomMatrix.setScale(zoom, zoom);
930         zoomPtr = &zoomMatrix;
931     }
932 
933     FontMetrics storage;
934     if (nullptr == metrics) {
935         metrics = &storage;
936     }
937 
938     paint.descriptorProc(nullptr, kNone_ScalerContextFlags, zoomPtr, FontMetricsDescProc, metrics);
939 
940     if (scale) {
941         SkPaintPriv::ScaleFontMetrics(metrics, scale);
942     }
943     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
944 }
945 
946 ///////////////////////////////////////////////////////////////////////////////
947 
set_bounds(const SkGlyph & g,SkRect * bounds,SkScalar scale)948 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
949     bounds->set(g.fLeft * scale,
950                 g.fTop * scale,
951                 (g.fLeft + g.fWidth) * scale,
952                 (g.fTop + g.fHeight) * scale);
953 }
954 
getTextWidths(const void * textData,size_t byteLength,SkScalar widths[],SkRect bounds[]) const955 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
956                            SkScalar widths[], SkRect bounds[]) const {
957     if (0 == byteLength) {
958         return 0;
959     }
960 
961     SkASSERT(textData);
962 
963     if (nullptr == widths && nullptr == bounds) {
964         return this->countText(textData, byteLength);
965     }
966 
967     SkCanonicalizePaint canon(*this);
968     const SkPaint& paint = canon.getPaint();
969     SkScalar scale = canon.getScale();
970 
971     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
972     SkGlyphCache*       cache = autoCache.getCache();
973     GlyphCacheProc      glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
974                                                                     paint.isDevKernText(),
975                                                                     nullptr != bounds);
976 
977     const char* text = (const char*)textData;
978     const char* stop = text + byteLength;
979     int         count = 0;
980     const int   xyIndex = paint.isVerticalText() ? 1 : 0;
981 
982     if (this->isDevKernText()) {
983         // we adjust the widths returned here through auto-kerning
984         SkAutoKern  autokern;
985         SkScalar    prevWidth = 0;
986 
987         if (scale) {
988             while (text < stop) {
989                 const SkGlyph& g = glyphCacheProc(cache, &text);
990                 if (widths) {
991                     SkScalar adjust = autokern.adjust(g);
992 
993                     if (count > 0) {
994                         *widths++ = (prevWidth + adjust) * scale;
995                     }
996                     prevWidth = advance(g, xyIndex);
997                 }
998                 if (bounds) {
999                     set_bounds(g, bounds++, scale);
1000                 }
1001                 ++count;
1002             }
1003             if (count > 0 && widths) {
1004                 *widths = prevWidth * scale;
1005             }
1006         } else {
1007             while (text < stop) {
1008                 const SkGlyph& g = glyphCacheProc(cache, &text);
1009                 if (widths) {
1010                     SkScalar adjust = autokern.adjust(g);
1011 
1012                     if (count > 0) {
1013                         *widths++ = prevWidth + adjust;
1014                     }
1015                     prevWidth = advance(g, xyIndex);
1016                 }
1017                 if (bounds) {
1018                     set_bounds(g, bounds++);
1019                 }
1020                 ++count;
1021             }
1022             if (count > 0 && widths) {
1023                 *widths = prevWidth;
1024             }
1025         }
1026     } else {    // no devkern
1027         if (scale) {
1028             while (text < stop) {
1029                 const SkGlyph& g = glyphCacheProc(cache, &text);
1030                 if (widths) {
1031                     *widths++ = advance(g, xyIndex) * scale;
1032                 }
1033                 if (bounds) {
1034                     set_bounds(g, bounds++, scale);
1035                 }
1036                 ++count;
1037             }
1038         } else {
1039             while (text < stop) {
1040                 const SkGlyph& g = glyphCacheProc(cache, &text);
1041                 if (widths) {
1042                     *widths++ = advance(g, xyIndex);
1043                 }
1044                 if (bounds) {
1045                     set_bounds(g, bounds++);
1046                 }
1047                 ++count;
1048             }
1049         }
1050     }
1051 
1052     SkASSERT(text == stop);
1053     return count;
1054 }
1055 
1056 ///////////////////////////////////////////////////////////////////////////////
1057 
1058 #include "SkDraw.h"
1059 
getTextPath(const void * textData,size_t length,SkScalar x,SkScalar y,SkPath * path) const1060 void SkPaint::getTextPath(const void* textData, size_t length,
1061                           SkScalar x, SkScalar y, SkPath* path) const {
1062     SkASSERT(length == 0 || textData != nullptr);
1063 
1064     const char* text = (const char*)textData;
1065     if (text == nullptr || length == 0 || path == nullptr) {
1066         return;
1067     }
1068 
1069     SkTextToPathIter    iter(text, length, *this, false);
1070     SkMatrix            matrix;
1071     SkScalar            prevXPos = 0;
1072 
1073     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1074     matrix.postTranslate(x, y);
1075     path->reset();
1076 
1077     SkScalar        xpos;
1078     const SkPath*   iterPath;
1079     while (iter.next(&iterPath, &xpos)) {
1080         matrix.postTranslate(xpos - prevXPos, 0);
1081         if (iterPath) {
1082             path->addPath(*iterPath, matrix);
1083         }
1084         prevXPos = xpos;
1085     }
1086 }
1087 
getPosTextPath(const void * textData,size_t length,const SkPoint pos[],SkPath * path) const1088 void SkPaint::getPosTextPath(const void* textData, size_t length,
1089                              const SkPoint pos[], SkPath* path) const {
1090     SkASSERT(length == 0 || textData != nullptr);
1091 
1092     const char* text = (const char*)textData;
1093     if (text == nullptr || length == 0 || path == nullptr) {
1094         return;
1095     }
1096 
1097     SkTextToPathIter    iter(text, length, *this, false);
1098     SkMatrix            matrix;
1099     SkPoint             prevPos;
1100     prevPos.set(0, 0);
1101 
1102     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1103     path->reset();
1104 
1105     unsigned int    i = 0;
1106     const SkPath*   iterPath;
1107     while (iter.next(&iterPath, nullptr)) {
1108         matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1109         if (iterPath) {
1110             path->addPath(*iterPath, matrix);
1111         }
1112         prevPos = pos[i];
1113         i++;
1114     }
1115 }
1116 
1117 template <SkTextInterceptsIter::TextType TextType, typename Func>
GetTextIntercepts(const SkPaint & paint,const void * text,size_t length,const SkScalar bounds[2],SkScalar * array,Func posMaker)1118 int GetTextIntercepts(const SkPaint& paint, const void* text, size_t length,
1119                       const SkScalar bounds[2], SkScalar* array, Func posMaker) {
1120     SkASSERT(length == 0 || text != nullptr);
1121     if (!length) {
1122         return 0;
1123     }
1124 
1125     const SkPoint pos0 = posMaker(0);
1126     SkTextInterceptsIter iter(static_cast<const char*>(text), length, paint, bounds,
1127                               pos0.x(), pos0.y(), TextType);
1128 
1129     int i = 0;
1130     int count = 0;
1131     while (iter.next(array, &count)) {
1132         if (TextType == SkTextInterceptsIter::TextType::kPosText) {
1133             const SkPoint pos = posMaker(++i);
1134             iter.setPosition(pos.x(), pos.y());
1135         }
1136     }
1137 
1138     return count;
1139 }
1140 
getTextIntercepts(const void * textData,size_t length,SkScalar x,SkScalar y,const SkScalar bounds[2],SkScalar * array) const1141 int SkPaint::getTextIntercepts(const void* textData, size_t length,
1142                                SkScalar x, SkScalar y, const SkScalar bounds[2],
1143                                SkScalar* array) const {
1144 
1145     return GetTextIntercepts<SkTextInterceptsIter::TextType::kText>(
1146         *this, textData, length, bounds, array, [&x, &y] (int) -> SkPoint {
1147             return SkPoint::Make(x, y);
1148         });
1149 }
1150 
getPosTextIntercepts(const void * textData,size_t length,const SkPoint pos[],const SkScalar bounds[2],SkScalar * array) const1151 int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[],
1152                                   const SkScalar bounds[2], SkScalar* array) const {
1153 
1154     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
1155         *this, textData, length, bounds, array, [&pos] (int i) -> SkPoint {
1156             return pos[i];
1157         });
1158 }
1159 
getPosTextHIntercepts(const void * textData,size_t length,const SkScalar xpos[],SkScalar constY,const SkScalar bounds[2],SkScalar * array) const1160 int SkPaint::getPosTextHIntercepts(const void* textData, size_t length, const SkScalar xpos[],
1161                                    SkScalar constY, const SkScalar bounds[2],
1162                                    SkScalar* array) const {
1163 
1164     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
1165         *this, textData, length, bounds, array, [&xpos, &constY] (int i) -> SkPoint {
1166             return SkPoint::Make(xpos[i], constY);
1167         });
1168 }
1169 
getTextBlobIntercepts(const SkTextBlob * blob,const SkScalar bounds[2],SkScalar * intervals) const1170 int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
1171                                    SkScalar* intervals) const {
1172     int count = 0;
1173     SkPaint runPaint(*this);
1174 
1175     SkTextBlobRunIterator it(blob);
1176     while (!it.done()) {
1177         it.applyFontToPaint(&runPaint);
1178         const size_t runByteCount = it.glyphCount() * sizeof(SkGlyphID);
1179         SkScalar* runIntervals = intervals ? intervals + count : nullptr;
1180 
1181         switch (it.positioning()) {
1182         case SkTextBlob::kDefault_Positioning:
1183             count += runPaint.getTextIntercepts(it.glyphs(), runByteCount, it.offset().x(),
1184                                                 it.offset().y(), bounds, runIntervals);
1185             break;
1186         case SkTextBlob::kHorizontal_Positioning:
1187             count += runPaint.getPosTextHIntercepts(it.glyphs(), runByteCount, it.pos(),
1188                                                     it.offset().y(), bounds, runIntervals);
1189             break;
1190         case SkTextBlob::kFull_Positioning:
1191             count += runPaint.getPosTextIntercepts(it.glyphs(), runByteCount,
1192                                                    reinterpret_cast<const SkPoint*>(it.pos()),
1193                                                    bounds, runIntervals);
1194             break;
1195         }
1196 
1197         it.next();
1198     }
1199 
1200     return count;
1201 }
1202 
getFontBounds() const1203 SkRect SkPaint::getFontBounds() const {
1204     SkMatrix m;
1205     m.setScale(fTextSize * fTextScaleX, fTextSize);
1206     m.postSkew(fTextSkewX, 0);
1207 
1208     SkTypeface* typeface = this->getTypeface();
1209     if (nullptr == typeface) {
1210         typeface = SkTypeface::GetDefaultTypeface();
1211     }
1212 
1213     SkRect bounds;
1214     m.mapRect(&bounds, typeface->getBounds());
1215     return bounds;
1216 }
1217 
add_flattenable(SkDescriptor * desc,uint32_t tag,SkBinaryWriteBuffer * buffer)1218 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1219                             SkBinaryWriteBuffer* buffer) {
1220     buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
1221 }
1222 
compute_mask_format(const SkPaint & paint)1223 static SkMask::Format compute_mask_format(const SkPaint& paint) {
1224     uint32_t flags = paint.getFlags();
1225 
1226     // Antialiasing being disabled trumps all other settings.
1227     if (!(flags & SkPaint::kAntiAlias_Flag)) {
1228         return SkMask::kBW_Format;
1229     }
1230 
1231     if (flags & SkPaint::kLCDRenderText_Flag) {
1232         return SkMask::kLCD16_Format;
1233     }
1234 
1235     return SkMask::kA8_Format;
1236 }
1237 
1238 // if linear-text is on, then we force hinting to be off (since that's sort of
1239 // the point of linear-text.
computeHinting(const SkPaint & paint)1240 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1241     SkPaint::Hinting h = paint.getHinting();
1242     if (paint.isLinearText()) {
1243         h = SkPaint::kNo_Hinting;
1244     }
1245     return h;
1246 }
1247 
1248 // return true if the paint is just a single color (i.e. not a shader). If its
1249 // a shader, then we can't compute a const luminance for it :(
justAColor(const SkPaint & paint,SkColor * color)1250 static bool justAColor(const SkPaint& paint, SkColor* color) {
1251     SkColor c = paint.getColor();
1252 
1253     SkShader* shader = paint.getShader();
1254     if (shader && !shader->asLuminanceColor(&c)) {
1255         return false;
1256     }
1257     if (paint.getColorFilter()) {
1258         c = paint.getColorFilter()->filterColor(c);
1259     }
1260     if (color) {
1261         *color = c;
1262     }
1263     return true;
1264 }
1265 
computeLuminanceColor() const1266 SkColor SkPaint::computeLuminanceColor() const {
1267     SkColor c;
1268     if (!justAColor(*this, &c)) {
1269         c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1270     }
1271     return c;
1272 }
1273 
1274 #define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
1275 
1276 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1277 // cost more RAM and draws slower, so we set a cap.
1278 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1279     #define SK_MAX_SIZE_FOR_LCDTEXT    48
1280 #endif
1281 
1282 const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
1283 
too_big_for_lcd(const SkScalerContext::Rec & rec,bool checkPost2x2)1284 static bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) {
1285     if (checkPost2x2) {
1286         SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1287                         rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1288         area *= rec.fTextSize * rec.fTextSize;
1289         return area > gMaxSize2ForLCDText;
1290     } else {
1291         return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
1292     }
1293 }
1294 
1295 /*
1296  *  Return the scalar with only limited fractional precision. Used to consolidate matrices
1297  *  that vary only slightly when we create our key into the font cache, since the font scaler
1298  *  typically returns the same looking resuts for tiny changes in the matrix.
1299  */
sk_relax(SkScalar x)1300 static SkScalar sk_relax(SkScalar x) {
1301     SkScalar n = SkScalarRoundToScalar(x * 1024);
1302     return n / 1024.0f;
1303 }
1304 
MakeRec(const SkPaint & paint,const SkSurfaceProps * surfaceProps,const SkMatrix * deviceMatrix,Rec * rec)1305 void SkScalerContext::MakeRec(const SkPaint& paint,
1306                               const SkSurfaceProps* surfaceProps,
1307                               const SkMatrix* deviceMatrix,
1308                               Rec* rec) {
1309     SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective());
1310 
1311     SkTypeface* typeface = paint.getTypeface();
1312     if (nullptr == typeface) {
1313         typeface = SkTypeface::GetDefaultTypeface();
1314     }
1315     rec->fFontID = typeface->uniqueID();
1316     rec->fTextSize = paint.getTextSize();
1317     rec->fPreScaleX = paint.getTextScaleX();
1318     rec->fPreSkewX  = paint.getTextSkewX();
1319 
1320     bool checkPost2x2 = false;
1321 
1322     if (deviceMatrix) {
1323         const SkMatrix::TypeMask mask = deviceMatrix->getType();
1324         if (mask & SkMatrix::kScale_Mask) {
1325             rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1326             rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1327             checkPost2x2 = true;
1328         } else {
1329             rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1330         }
1331         if (mask & SkMatrix::kAffine_Mask) {
1332             rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1333             rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1334             checkPost2x2 = true;
1335         } else {
1336             rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1337         }
1338     } else {
1339         rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1340         rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1341     }
1342 
1343     SkPaint::Style  style = paint.getStyle();
1344     SkScalar        strokeWidth = paint.getStrokeWidth();
1345 
1346     unsigned flags = 0;
1347 
1348     if (paint.isFakeBoldText()) {
1349 #ifdef SK_USE_FREETYPE_EMBOLDEN
1350         flags |= SkScalerContext::kEmbolden_Flag;
1351 #else
1352         SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1353                                                     kStdFakeBoldInterpKeys,
1354                                                     kStdFakeBoldInterpValues,
1355                                                     kStdFakeBoldInterpLength);
1356         SkScalar extra = paint.getTextSize() * fakeBoldScale;
1357 
1358         if (style == SkPaint::kFill_Style) {
1359             style = SkPaint::kStrokeAndFill_Style;
1360             strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
1361         } else {
1362             strokeWidth += extra;
1363         }
1364 #endif
1365     }
1366 
1367     if (paint.isDevKernText()) {
1368         flags |= SkScalerContext::kDevKernText_Flag;
1369     }
1370 
1371     if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1372         rec->fFrameWidth = strokeWidth;
1373         rec->fMiterLimit = paint.getStrokeMiter();
1374         rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1375         rec->fStrokeCap = SkToU8(paint.getStrokeCap());
1376 
1377         if (style == SkPaint::kStrokeAndFill_Style) {
1378             flags |= SkScalerContext::kFrameAndFill_Flag;
1379         }
1380     } else {
1381         rec->fFrameWidth = 0;
1382         rec->fMiterLimit = 0;
1383         rec->fStrokeJoin = 0;
1384         rec->fStrokeCap = 0;
1385     }
1386 
1387     rec->fMaskFormat = SkToU8(compute_mask_format(paint));
1388 
1389     if (SkMask::kLCD16_Format == rec->fMaskFormat) {
1390         if (too_big_for_lcd(*rec, checkPost2x2)) {
1391             rec->fMaskFormat = SkMask::kA8_Format;
1392             flags |= SkScalerContext::kGenA8FromLCD_Flag;
1393         } else {
1394             SkPixelGeometry geometry = surfaceProps
1395                                      ? surfaceProps->pixelGeometry()
1396                                      : SkSurfacePropsDefaultPixelGeometry();
1397             switch (geometry) {
1398                 case kUnknown_SkPixelGeometry:
1399                     // eeek, can't support LCD
1400                     rec->fMaskFormat = SkMask::kA8_Format;
1401                     flags |= SkScalerContext::kGenA8FromLCD_Flag;
1402                     break;
1403                 case kRGB_H_SkPixelGeometry:
1404                     // our default, do nothing.
1405                     break;
1406                 case kBGR_H_SkPixelGeometry:
1407                     flags |= SkScalerContext::kLCD_BGROrder_Flag;
1408                     break;
1409                 case kRGB_V_SkPixelGeometry:
1410                     flags |= SkScalerContext::kLCD_Vertical_Flag;
1411                     break;
1412                 case kBGR_V_SkPixelGeometry:
1413                     flags |= SkScalerContext::kLCD_Vertical_Flag;
1414                     flags |= SkScalerContext::kLCD_BGROrder_Flag;
1415                     break;
1416             }
1417         }
1418     }
1419 
1420     if (paint.isEmbeddedBitmapText()) {
1421         flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1422     }
1423     if (paint.isSubpixelText()) {
1424         flags |= SkScalerContext::kSubpixelPositioning_Flag;
1425     }
1426     if (paint.isAutohinted()) {
1427         flags |= SkScalerContext::kForceAutohinting_Flag;
1428     }
1429     if (paint.isVerticalText()) {
1430         flags |= SkScalerContext::kVertical_Flag;
1431     }
1432     if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1433         flags |= SkScalerContext::kGenA8FromLCD_Flag;
1434     }
1435     rec->fFlags = SkToU16(flags);
1436 
1437     // these modify fFlags, so do them after assigning fFlags
1438     rec->setHinting(computeHinting(paint));
1439 
1440     rec->setLuminanceColor(paint.computeLuminanceColor());
1441 
1442     //For now always set the paint gamma equal to the device gamma.
1443     //The math in SkMaskGamma can handle them being different,
1444     //but it requires superluminous masks when
1445     //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1446     rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1447     rec->setPaintGamma(SK_GAMMA_EXPONENT);
1448 
1449 #ifdef SK_GAMMA_CONTRAST
1450     rec->setContrast(SK_GAMMA_CONTRAST);
1451 #else
1452     /**
1453      * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1454      * With lower values small text appears washed out (though correctly so).
1455      * With higher values lcd fringing is worse and the smoothing effect of
1456      * partial coverage is diminished.
1457      */
1458     rec->setContrast(0.5f);
1459 #endif
1460 
1461     rec->fReservedAlign = 0;
1462 
1463     /*  Allow the fonthost to modify our rec before we use it as a key into the
1464         cache. This way if we're asking for something that they will ignore,
1465         they can modify our rec up front, so we don't create duplicate cache
1466         entries.
1467      */
1468     typeface->onFilterRec(rec);
1469 
1470     // be sure to call PostMakeRec(rec) before you actually use it!
1471 }
1472 
1473 /**
1474  * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1475  * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1476  * to hold it until the returned pointer is refed or forgotten.
1477  */
1478 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1479 
1480 static SkMaskGamma* gLinearMaskGamma = nullptr;
1481 static SkMaskGamma* gMaskGamma = nullptr;
1482 static SkScalar gContrast = SK_ScalarMin;
1483 static SkScalar gPaintGamma = SK_ScalarMin;
1484 static SkScalar gDeviceGamma = SK_ScalarMin;
1485 /**
1486  * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1487  * the returned SkMaskGamma pointer is refed or forgotten.
1488  */
cachedMaskGamma(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma)1489 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1490     gMaskGammaCacheMutex.assertHeld();
1491     if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1492         if (nullptr == gLinearMaskGamma) {
1493             gLinearMaskGamma = new SkMaskGamma;
1494         }
1495         return *gLinearMaskGamma;
1496     }
1497     if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1498         SkSafeUnref(gMaskGamma);
1499         gMaskGamma = new SkMaskGamma(contrast, paintGamma, deviceGamma);
1500         gContrast = contrast;
1501         gPaintGamma = paintGamma;
1502         gDeviceGamma = deviceGamma;
1503     }
1504     return *gMaskGamma;
1505 }
1506 
1507 /**
1508  *  We ensure that the rec is self-consistent and efficient (where possible)
1509  */
PostMakeRec(const SkPaint &,SkScalerContext::Rec * rec)1510 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
1511     /**
1512      *  If we're asking for A8, we force the colorlum to be gray, since that
1513      *  limits the number of unique entries, and the scaler will only look at
1514      *  the lum of one of them.
1515      */
1516     switch (rec->fMaskFormat) {
1517         case SkMask::kLCD16_Format: {
1518             // filter down the luminance color to a finite number of bits
1519             SkColor color = rec->getLuminanceColor();
1520             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1521             break;
1522         }
1523         case SkMask::kA8_Format: {
1524             // filter down the luminance to a single component, since A8 can't
1525             // use per-component information
1526             SkColor color = rec->getLuminanceColor();
1527             U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1528                                            SkColorGetG(color),
1529                                            SkColorGetB(color));
1530             // reduce to our finite number of bits
1531             color = SkColorSetRGB(lum, lum, lum);
1532             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1533             break;
1534         }
1535         case SkMask::kBW_Format:
1536             // No need to differentiate gamma or apply contrast if we're BW
1537             rec->ignorePreBlend();
1538             break;
1539     }
1540 }
1541 
1542 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
1543 
1544 #ifdef SK_DEBUG
1545     #define TEST_DESC
1546 #endif
1547 
write_out_descriptor(SkDescriptor * desc,const SkScalerContext::Rec & rec,const SkPathEffect * pe,SkBinaryWriteBuffer * peBuffer,const SkMaskFilter * mf,SkBinaryWriteBuffer * mfBuffer,const SkRasterizer * ra,SkBinaryWriteBuffer * raBuffer,size_t descSize)1548 static void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec,
1549                                  const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
1550                                  const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
1551                                  const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer,
1552                                  size_t descSize) {
1553     desc->init();
1554     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1555 
1556     if (pe) {
1557         add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
1558     }
1559     if (mf) {
1560         add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
1561     }
1562     if (ra) {
1563         add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer);
1564     }
1565 
1566     desc->computeChecksum();
1567 }
1568 
fill_out_rec(const SkPaint & paint,SkScalerContext::Rec * rec,const SkSurfaceProps * surfaceProps,bool fakeGamma,bool boostContrast,const SkMatrix * deviceMatrix,const SkPathEffect * pe,SkBinaryWriteBuffer * peBuffer,const SkMaskFilter * mf,SkBinaryWriteBuffer * mfBuffer,const SkRasterizer * ra,SkBinaryWriteBuffer * raBuffer)1569 static size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec,
1570                            const SkSurfaceProps* surfaceProps,
1571                            bool fakeGamma, bool boostContrast,
1572                            const SkMatrix* deviceMatrix,
1573                            const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
1574                            const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
1575                            const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer) {
1576     SkScalerContext::MakeRec(paint, surfaceProps, deviceMatrix, rec);
1577     if (!fakeGamma) {
1578         rec->ignoreGamma();
1579     }
1580     if (!boostContrast) {
1581         rec->setContrast(0);
1582     }
1583 
1584     int entryCount = 1;
1585     size_t descSize = sizeof(*rec);
1586 
1587     if (pe) {
1588         pe->flatten(*peBuffer);
1589         descSize += peBuffer->bytesWritten();
1590         entryCount += 1;
1591         rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
1592         // seems like we could support kLCD as well at this point...
1593     }
1594     if (mf) {
1595         mf->flatten(*mfBuffer);
1596         descSize += mfBuffer->bytesWritten();
1597         entryCount += 1;
1598         rec->fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1599         /* Pre-blend is not currently applied to filtered text.
1600            The primary filter is blur, for which contrast makes no sense,
1601            and for which the destination guess error is more visible.
1602            Also, all existing users of blur have calibrated for linear. */
1603         rec->ignorePreBlend();
1604     }
1605     if (ra) {
1606         ra->flatten(*raBuffer);
1607         descSize += raBuffer->bytesWritten();
1608         entryCount += 1;
1609         rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
1610     }
1611 
1612     ///////////////////////////////////////////////////////////////////////////
1613     // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1614     SkScalerContext::PostMakeRec(paint, rec);
1615 
1616     descSize += SkDescriptor::ComputeOverhead(entryCount);
1617     return descSize;
1618 }
1619 
1620 #ifdef TEST_DESC
test_desc(const SkScalerContext::Rec & rec,const SkPathEffect * pe,SkBinaryWriteBuffer * peBuffer,const SkMaskFilter * mf,SkBinaryWriteBuffer * mfBuffer,const SkRasterizer * ra,SkBinaryWriteBuffer * raBuffer,const SkDescriptor * desc,size_t descSize)1621 static void test_desc(const SkScalerContext::Rec& rec,
1622                       const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
1623                       const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
1624                       const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer,
1625                       const SkDescriptor* desc, size_t descSize) {
1626     // Check that we completely write the bytes in desc (our key), and that
1627     // there are no uninitialized bytes. If there were, then we would get
1628     // false-misses (or worse, false-hits) in our fontcache.
1629     //
1630     // We do this buy filling 2 others, one with 0s and the other with 1s
1631     // and create those, and then check that all 3 are identical.
1632     SkAutoDescriptor    ad1(descSize);
1633     SkAutoDescriptor    ad2(descSize);
1634     SkDescriptor*       desc1 = ad1.getDesc();
1635     SkDescriptor*       desc2 = ad2.getDesc();
1636 
1637     memset(desc1, 0x00, descSize);
1638     memset(desc2, 0xFF, descSize);
1639 
1640     desc1->init();
1641     desc2->init();
1642     desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1643     desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1644 
1645     if (pe) {
1646         add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
1647         add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
1648     }
1649     if (mf) {
1650         add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
1651         add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
1652     }
1653     if (ra) {
1654         add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer);
1655         add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer);
1656     }
1657 
1658     SkASSERT(descSize == desc1->getLength());
1659     SkASSERT(descSize == desc2->getLength());
1660     desc1->computeChecksum();
1661     desc2->computeChecksum();
1662     SkASSERT(!memcmp(desc, desc1, descSize));
1663     SkASSERT(!memcmp(desc, desc2, descSize));
1664 }
1665 #endif
1666 
1667 /* see the note on ignoreGamma on descriptorProc */
getScalerContextDescriptor(SkScalerContextEffects * effects,SkAutoDescriptor * ad,const SkSurfaceProps & surfaceProps,uint32_t scalerContextFlags,const SkMatrix * deviceMatrix) const1668 void SkPaint::getScalerContextDescriptor(SkScalerContextEffects* effects,
1669                                          SkAutoDescriptor* ad,
1670                                          const SkSurfaceProps& surfaceProps,
1671                                          uint32_t scalerContextFlags,
1672                                          const SkMatrix* deviceMatrix) const {
1673     SkScalerContext::Rec    rec;
1674 
1675     SkPathEffect*   pe = this->getPathEffect();
1676     SkMaskFilter*   mf = this->getMaskFilter();
1677     SkRasterizer*   ra = this->getRasterizer();
1678 
1679     SkBinaryWriteBuffer   peBuffer, mfBuffer, raBuffer;
1680     size_t descSize = fill_out_rec(*this, &rec, &surfaceProps,
1681                                    SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
1682                                    SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
1683                                    deviceMatrix, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1684 
1685     ad->reset(descSize);
1686     SkDescriptor* desc = ad->getDesc();
1687 
1688     write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1689 
1690     SkASSERT(descSize == desc->getLength());
1691 
1692 #ifdef TEST_DESC
1693     test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
1694 #endif
1695 
1696     effects->fPathEffect = pe;
1697     effects->fMaskFilter = mf;
1698     effects->fRasterizer = ra;
1699 }
1700 
1701 /*
1702  *  ignoreGamma tells us that the caller just wants metrics that are unaffected
1703  *  by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
1704  *  contrast = 0, luminanceColor = transparent black.
1705  */
descriptorProc(const SkSurfaceProps * surfaceProps,uint32_t scalerContextFlags,const SkMatrix * deviceMatrix,void (* proc)(SkTypeface *,const SkScalerContextEffects &,const SkDescriptor *,void *),void * context) const1706 void SkPaint::descriptorProc(const SkSurfaceProps* surfaceProps,
1707                              uint32_t scalerContextFlags,
1708                              const SkMatrix* deviceMatrix,
1709                              void (*proc)(SkTypeface*, const SkScalerContextEffects&,
1710                                           const SkDescriptor*, void*),
1711                              void* context) const {
1712     SkScalerContext::Rec    rec;
1713 
1714     SkPathEffect*   pe = this->getPathEffect();
1715     SkMaskFilter*   mf = this->getMaskFilter();
1716     SkRasterizer*   ra = this->getRasterizer();
1717 
1718     SkBinaryWriteBuffer   peBuffer, mfBuffer, raBuffer;
1719     size_t descSize = fill_out_rec(*this, &rec, surfaceProps,
1720                                    SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
1721                                    SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
1722                                    deviceMatrix, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1723 
1724     SkAutoDescriptor    ad(descSize);
1725     SkDescriptor*       desc = ad.getDesc();
1726 
1727     write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1728 
1729     SkASSERT(descSize == desc->getLength());
1730 
1731 #ifdef TEST_DESC
1732     test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
1733 #endif
1734 
1735     proc(fTypeface.get(), { pe, mf, ra }, desc, context);
1736 }
1737 
detachCache(const SkSurfaceProps * surfaceProps,uint32_t scalerContextFlags,const SkMatrix * deviceMatrix) const1738 SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps,
1739                                    uint32_t scalerContextFlags,
1740                                    const SkMatrix* deviceMatrix) const {
1741     SkGlyphCache* cache;
1742     this->descriptorProc(surfaceProps, scalerContextFlags, deviceMatrix, DetachDescProc, &cache);
1743     return cache;
1744 }
1745 
1746 /**
1747  * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1748  */
1749 //static
GetMaskPreBlend(const SkScalerContext::Rec & rec)1750 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
1751     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1752     const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1753                                                    rec.getPaintGamma(),
1754                                                    rec.getDeviceGamma());
1755     return maskGamma.preBlend(rec.getLuminanceColor());
1756 }
1757 
GetGammaLUTSize(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,int * width,int * height)1758 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
1759                                         SkScalar deviceGamma, int* width, int* height) {
1760     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1761     const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1762                                                    paintGamma,
1763                                                    deviceGamma);
1764 
1765     maskGamma.getGammaTableDimensions(width, height);
1766     size_t size = (*width)*(*height)*sizeof(uint8_t);
1767 
1768     return size;
1769 }
1770 
GetGammaLUTData(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,void * data)1771 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
1772                                       void* data) {
1773     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1774     const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1775                                                    paintGamma,
1776                                                    deviceGamma);
1777     int width, height;
1778     maskGamma.getGammaTableDimensions(&width, &height);
1779     size_t size = width*height*sizeof(uint8_t);
1780     const uint8_t* gammaTables = maskGamma.getGammaTables();
1781     memcpy(data, gammaTables, size);
1782 }
1783 
1784 
1785 ///////////////////////////////////////////////////////////////////////////////
1786 
1787 #include "SkStream.h"
1788 
asint(const void * p)1789 static uintptr_t asint(const void* p) {
1790     return reinterpret_cast<uintptr_t>(p);
1791 }
1792 
pack_4(unsigned a,unsigned b,unsigned c,unsigned d)1793 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1794     SkASSERT(a == (uint8_t)a);
1795     SkASSERT(b == (uint8_t)b);
1796     SkASSERT(c == (uint8_t)c);
1797     SkASSERT(d == (uint8_t)d);
1798     return (a << 24) | (b << 16) | (c << 8) | d;
1799 }
1800 
1801 #ifdef SK_DEBUG
ASSERT_FITS_IN(uint32_t value,int bitCount)1802     static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
1803         SkASSERT(bitCount > 0 && bitCount <= 32);
1804         uint32_t mask = ~0U;
1805         mask >>= (32 - bitCount);
1806         SkASSERT(0 == (value & ~mask));
1807     }
1808 #else
1809     #define ASSERT_FITS_IN(value, bitcount)
1810 #endif
1811 
1812 enum FlatFlags {
1813     kHasTypeface_FlatFlag = 0x1,
1814     kHasEffects_FlatFlag  = 0x2,
1815 
1816     kFlatFlagMask         = 0x3,
1817 };
1818 
1819 enum BitsPerField {
1820     kFlags_BPF  = 16,
1821     kHint_BPF   = 2,
1822     kAlign_BPF  = 2,
1823     kFilter_BPF = 2,
1824     kFlatFlags_BPF  = 3,
1825 };
1826 
BPF_Mask(int bits)1827 static inline int BPF_Mask(int bits) {
1828     return (1 << bits) - 1;
1829 }
1830 
pack_paint_flags(unsigned flags,unsigned hint,unsigned align,unsigned filter,unsigned flatFlags)1831 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
1832                                  unsigned filter, unsigned flatFlags) {
1833     ASSERT_FITS_IN(flags, kFlags_BPF);
1834     ASSERT_FITS_IN(hint, kHint_BPF);
1835     ASSERT_FITS_IN(align, kAlign_BPF);
1836     ASSERT_FITS_IN(filter, kFilter_BPF);
1837     ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
1838 
1839     // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
1840     // add more bits in the future.
1841     return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
1842 }
1843 
unpack_paint_flags(SkPaint * paint,uint32_t packed)1844 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
1845     paint->setFlags(packed >> 16);
1846     paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
1847     paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
1848     paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
1849     return (FlatFlags)(packed & kFlatFlagMask);
1850 }
1851 
1852 /*  To save space/time, we analyze the paint, and write a truncated version of
1853     it if there are not tricky elements like shaders, etc.
1854  */
flatten(SkWriteBuffer & buffer) const1855 void SkPaint::flatten(SkWriteBuffer& buffer) const {
1856     uint8_t flatFlags = 0;
1857     if (this->getTypeface()) {
1858         flatFlags |= kHasTypeface_FlatFlag;
1859     }
1860     if (asint(this->getPathEffect()) |
1861         asint(this->getShader()) |
1862         asint(this->getMaskFilter()) |
1863         asint(this->getColorFilter()) |
1864         asint(this->getRasterizer()) |
1865         asint(this->getLooper()) |
1866         asint(this->getImageFilter())) {
1867         flatFlags |= kHasEffects_FlatFlag;
1868     }
1869 
1870     buffer.writeScalar(this->getTextSize());
1871     buffer.writeScalar(this->getTextScaleX());
1872     buffer.writeScalar(this->getTextSkewX());
1873     buffer.writeScalar(this->getStrokeWidth());
1874     buffer.writeScalar(this->getStrokeMiter());
1875     buffer.writeColor(this->getColor());
1876 
1877     buffer.writeUInt(pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
1878                                       this->getFilterQuality(), flatFlags));
1879     buffer.writeUInt(pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1880                             (this->getStyle() << 4) | this->getTextEncoding(),
1881                             fBlendMode));
1882 
1883     // now we're done with ptr and the (pre)reserved space. If we need to write
1884     // additional fields, use the buffer directly
1885     if (flatFlags & kHasTypeface_FlatFlag) {
1886         buffer.writeTypeface(this->getTypeface());
1887     }
1888     if (flatFlags & kHasEffects_FlatFlag) {
1889         buffer.writeFlattenable(this->getPathEffect());
1890         buffer.writeFlattenable(this->getShader());
1891         buffer.writeFlattenable(this->getMaskFilter());
1892         buffer.writeFlattenable(this->getColorFilter());
1893         buffer.writeFlattenable(this->getRasterizer());
1894         buffer.writeFlattenable(this->getLooper());
1895         buffer.writeFlattenable(this->getImageFilter());
1896     }
1897 }
1898 
unflatten(SkReadBuffer & buffer)1899 void SkPaint::unflatten(SkReadBuffer& buffer) {
1900     this->setTextSize(buffer.readScalar());
1901     this->setTextScaleX(buffer.readScalar());
1902     this->setTextSkewX(buffer.readScalar());
1903     this->setStrokeWidth(buffer.readScalar());
1904     this->setStrokeMiter(buffer.readScalar());
1905     this->setColor(buffer.readColor());
1906 
1907     unsigned flatFlags = unpack_paint_flags(this, buffer.readUInt());
1908 
1909     uint32_t tmp = buffer.readUInt();
1910     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1911     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1912     if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
1913         this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1914         this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1915     } else {
1916         this->setStyle(static_cast<Style>((tmp >> 12) & 0xF));
1917         this->setTextEncoding(static_cast<TextEncoding>((tmp >> 8) & 0xF));
1918         this->setBlendMode((SkBlendMode)(tmp & 0xFF));
1919     }
1920 
1921     if (flatFlags & kHasTypeface_FlatFlag) {
1922         this->setTypeface(buffer.readTypeface());
1923     } else {
1924         this->setTypeface(nullptr);
1925     }
1926 
1927     if (flatFlags & kHasEffects_FlatFlag) {
1928         this->setPathEffect(buffer.readPathEffect());
1929         this->setShader(buffer.readShader());
1930         if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
1931             sk_sp<SkXfermode> xfer = buffer.readXfermode();
1932             this->setBlendMode(xfer ? xfer->blend() : SkBlendMode::kSrcOver);
1933         }
1934         this->setMaskFilter(buffer.readMaskFilter());
1935         this->setColorFilter(buffer.readColorFilter());
1936         this->setRasterizer(buffer.readRasterizer());
1937         this->setLooper(buffer.readDrawLooper());
1938         this->setImageFilter(buffer.readImageFilter());
1939 
1940         if (buffer.isVersionLT(SkReadBuffer::kAnnotationsMovedToCanvas_Version)) {
1941             // We used to store annotations here (string+skdata) if this bool was true
1942             if (buffer.readBool()) {
1943                 // Annotations have moved to drawAnnotation, so we just drop this one on the floor.
1944                 SkString key;
1945                 buffer.readString(&key);
1946                 (void)buffer.readByteArrayAsData();
1947             }
1948         }
1949     } else {
1950         this->setPathEffect(nullptr);
1951         this->setShader(nullptr);
1952         this->setMaskFilter(nullptr);
1953         this->setColorFilter(nullptr);
1954         this->setRasterizer(nullptr);
1955         this->setLooper(nullptr);
1956         this->setImageFilter(nullptr);
1957     }
1958 }
1959 
1960 ///////////////////////////////////////////////////////////////////////////////
1961 
getFillPath(const SkPath & src,SkPath * dst,const SkRect * cullRect,SkScalar resScale) const1962 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
1963                           SkScalar resScale) const {
1964     SkStrokeRec rec(*this, resScale);
1965 
1966     const SkPath* srcPtr = &src;
1967     SkPath tmpPath;
1968 
1969     if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
1970         srcPtr = &tmpPath;
1971     }
1972 
1973     if (!rec.applyToPath(dst, *srcPtr)) {
1974         if (srcPtr == &tmpPath) {
1975             // If path's were copy-on-write, this trick would not be needed.
1976             // As it is, we want to save making a deep-copy from tmpPath -> dst
1977             // since we know we're just going to delete tmpPath when we return,
1978             // so the swap saves that copy.
1979             dst->swap(tmpPath);
1980         } else {
1981             *dst = *srcPtr;
1982         }
1983     }
1984     return !rec.isHairlineStyle();
1985 }
1986 
canComputeFastBounds() const1987 bool SkPaint::canComputeFastBounds() const {
1988     if (this->getLooper()) {
1989         return this->getLooper()->canComputeFastBounds(*this);
1990     }
1991     if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
1992         return false;
1993     }
1994     return !this->getRasterizer();
1995 }
1996 
doComputeFastBounds(const SkRect & origSrc,SkRect * storage,Style style) const1997 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
1998                                            SkRect* storage,
1999                                            Style style) const {
2000     SkASSERT(storage);
2001 
2002     const SkRect* src = &origSrc;
2003 
2004     if (this->getLooper()) {
2005         SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2006         this->getLooper()->computeFastBounds(*this, *src, storage);
2007         return *storage;
2008     }
2009 
2010     SkRect tmpSrc;
2011     if (this->getPathEffect()) {
2012         this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2013         src = &tmpSrc;
2014     }
2015 
2016     SkScalar radius = SkStrokeRec::GetInflationRadius(*this, style);
2017     *storage = src->makeOutset(radius, radius);
2018 
2019     if (this->getMaskFilter()) {
2020         this->getMaskFilter()->computeFastBounds(*storage, storage);
2021     }
2022 
2023     if (this->getImageFilter()) {
2024         *storage = this->getImageFilter()->computeFastBounds(*storage);
2025     }
2026 
2027     return *storage;
2028 }
2029 
2030 #ifndef SK_IGNORE_TO_STRING
2031 
toString(SkString * str) const2032 void SkPaint::toString(SkString* str) const {
2033     str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2034 
2035     SkTypeface* typeface = this->getTypeface();
2036     if (typeface) {
2037         SkDynamicMemoryWStream ostream;
2038         typeface->serialize(&ostream);
2039         std::unique_ptr<SkStreamAsset> istream(ostream.detachAsStream());
2040 
2041         SkFontDescriptor descriptor;
2042         if (!SkFontDescriptor::Deserialize(istream.get(), &descriptor)) {
2043             str->append("<dt>FontDescriptor deserialization failed</dt>");
2044         } else {
2045             str->append("<dt>Font Family Name:</dt><dd>");
2046             str->append(descriptor.getFamilyName());
2047             str->append("</dd><dt>Font Full Name:</dt><dd>");
2048             str->append(descriptor.getFullName());
2049             str->append("</dd><dt>Font PS Name:</dt><dd>");
2050             str->append(descriptor.getPostscriptName());
2051             str->append("</dd>");
2052         }
2053     }
2054 
2055     str->append("<dt>TextSize:</dt><dd>");
2056     str->appendScalar(this->getTextSize());
2057     str->append("</dd>");
2058 
2059     str->append("<dt>TextScaleX:</dt><dd>");
2060     str->appendScalar(this->getTextScaleX());
2061     str->append("</dd>");
2062 
2063     str->append("<dt>TextSkewX:</dt><dd>");
2064     str->appendScalar(this->getTextSkewX());
2065     str->append("</dd>");
2066 
2067     SkPathEffect* pathEffect = this->getPathEffect();
2068     if (pathEffect) {
2069         str->append("<dt>PathEffect:</dt><dd>");
2070         pathEffect->toString(str);
2071         str->append("</dd>");
2072     }
2073 
2074     SkShader* shader = this->getShader();
2075     if (shader) {
2076         str->append("<dt>Shader:</dt><dd>");
2077         shader->toString(str);
2078         str->append("</dd>");
2079     }
2080 
2081     if (!this->isSrcOver()) {
2082         str->appendf("<dt>Xfermode:</dt><dd>%d</dd>", fBlendMode);
2083     }
2084 
2085     SkMaskFilter* maskFilter = this->getMaskFilter();
2086     if (maskFilter) {
2087         str->append("<dt>MaskFilter:</dt><dd>");
2088         maskFilter->toString(str);
2089         str->append("</dd>");
2090     }
2091 
2092     SkColorFilter* colorFilter = this->getColorFilter();
2093     if (colorFilter) {
2094         str->append("<dt>ColorFilter:</dt><dd>");
2095         colorFilter->toString(str);
2096         str->append("</dd>");
2097     }
2098 
2099     SkRasterizer* rasterizer = this->getRasterizer();
2100     if (rasterizer) {
2101         str->append("<dt>Rasterizer:</dt><dd>");
2102         str->append("</dd>");
2103     }
2104 
2105     SkDrawLooper* looper = this->getLooper();
2106     if (looper) {
2107         str->append("<dt>DrawLooper:</dt><dd>");
2108         looper->toString(str);
2109         str->append("</dd>");
2110     }
2111 
2112     SkImageFilter* imageFilter = this->getImageFilter();
2113     if (imageFilter) {
2114         str->append("<dt>ImageFilter:</dt><dd>");
2115         imageFilter->toString(str);
2116         str->append("</dd>");
2117     }
2118 
2119     str->append("<dt>Color:</dt><dd>0x");
2120     SkColor color = this->getColor();
2121     str->appendHex(color);
2122     str->append("</dd>");
2123 
2124     str->append("<dt>Stroke Width:</dt><dd>");
2125     str->appendScalar(this->getStrokeWidth());
2126     str->append("</dd>");
2127 
2128     str->append("<dt>Stroke Miter:</dt><dd>");
2129     str->appendScalar(this->getStrokeMiter());
2130     str->append("</dd>");
2131 
2132     str->append("<dt>Flags:</dt><dd>(");
2133     if (this->getFlags()) {
2134         bool needSeparator = false;
2135         SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2136         SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2137         SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2138         SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2139         SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2140         SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2141         SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2142         SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2143                           "EmbeddedBitmapText", &needSeparator);
2144         SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2145         SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2146         SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2147                           "GenA8FromLCD", &needSeparator);
2148     } else {
2149         str->append("None");
2150     }
2151     str->append(")</dd>");
2152 
2153     str->append("<dt>FilterLevel:</dt><dd>");
2154     static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" };
2155     str->append(gFilterQualityStrings[this->getFilterQuality()]);
2156     str->append("</dd>");
2157 
2158     str->append("<dt>TextAlign:</dt><dd>");
2159     static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2160     str->append(gTextAlignStrings[this->getTextAlign()]);
2161     str->append("</dd>");
2162 
2163     str->append("<dt>CapType:</dt><dd>");
2164     static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2165     str->append(gStrokeCapStrings[this->getStrokeCap()]);
2166     str->append("</dd>");
2167 
2168     str->append("<dt>JoinType:</dt><dd>");
2169     static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2170     str->append(gJoinStrings[this->getStrokeJoin()]);
2171     str->append("</dd>");
2172 
2173     str->append("<dt>Style:</dt><dd>");
2174     static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2175     str->append(gStyleStrings[this->getStyle()]);
2176     str->append("</dd>");
2177 
2178     str->append("<dt>TextEncoding:</dt><dd>");
2179     static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2180     str->append(gTextEncodingStrings[this->getTextEncoding()]);
2181     str->append("</dd>");
2182 
2183     str->append("<dt>Hinting:</dt><dd>");
2184     static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2185     str->append(gHintingStrings[this->getHinting()]);
2186     str->append("</dd>");
2187 
2188     str->append("</dd></dl></dl>");
2189 }
2190 #endif
2191 
2192 ///////////////////////////////////////////////////////////////////////////////
2193 
has_thick_frame(const SkPaint & paint)2194 static bool has_thick_frame(const SkPaint& paint) {
2195     return  paint.getStrokeWidth() > 0 &&
2196             paint.getStyle() != SkPaint::kFill_Style;
2197 }
2198 
SkTextBaseIter(const char text[],size_t length,const SkPaint & paint,bool applyStrokeAndPathEffects)2199 SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
2200                                    const SkPaint& paint,
2201                                    bool applyStrokeAndPathEffects)
2202     : fPaint(paint) {
2203     fGlyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
2204                                                  paint.isDevKernText(),
2205                                                  true);
2206 
2207     fPaint.setLinearText(true);
2208     fPaint.setMaskFilter(nullptr);   // don't want this affecting our path-cache lookup
2209 
2210     if (fPaint.getPathEffect() == nullptr && !has_thick_frame(fPaint)) {
2211         applyStrokeAndPathEffects = false;
2212     }
2213 
2214     // can't use our canonical size if we need to apply patheffects
2215     if (fPaint.getPathEffect() == nullptr) {
2216         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2217         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2218         if (has_thick_frame(fPaint)) {
2219             fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale);
2220         }
2221     } else {
2222         fScale = SK_Scalar1;
2223     }
2224 
2225     if (!applyStrokeAndPathEffects) {
2226         fPaint.setStyle(SkPaint::kFill_Style);
2227         fPaint.setPathEffect(nullptr);
2228     }
2229 
2230     // SRGBTODO: Is this correct?
2231     fCache = fPaint.detachCache(nullptr, SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags,
2232                                 nullptr);
2233 
2234     SkPaint::Style  style = SkPaint::kFill_Style;
2235     sk_sp<SkPathEffect> pe;
2236 
2237     if (!applyStrokeAndPathEffects) {
2238         style = paint.getStyle();       // restore
2239         pe = paint.refPathEffect();     // restore
2240     }
2241     fPaint.setStyle(style);
2242     fPaint.setPathEffect(pe);
2243     fPaint.setMaskFilter(paint.refMaskFilter());    // restore
2244 
2245     // now compute fXOffset if needed
2246 
2247     SkScalar xOffset = 0;
2248     if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2249         int      count;
2250         SkScalar width = fPaint.measure_text(fCache, text, length, &count, nullptr) * fScale;
2251         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2252             width = SkScalarHalf(width);
2253         }
2254         xOffset = -width;
2255     }
2256     fXPos = xOffset;
2257     fPrevAdvance = 0;
2258 
2259     fText = text;
2260     fStop = text + length;
2261 
2262     fXYIndex = paint.isVerticalText() ? 1 : 0;
2263 }
2264 
~SkTextBaseIter()2265 SkTextBaseIter::~SkTextBaseIter() {
2266     SkGlyphCache::AttachCache(fCache);
2267 }
2268 
next(const SkPath ** path,SkScalar * xpos)2269 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2270     if (fText < fStop) {
2271         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2272 
2273         fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
2274         fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
2275 
2276         if (glyph.fWidth) {
2277             if (path) {
2278                 *path = fCache->findPath(glyph);
2279             }
2280         } else {
2281             if (path) {
2282                 *path = nullptr;
2283             }
2284         }
2285         if (xpos) {
2286             *xpos = fXPos;
2287         }
2288         return true;
2289     }
2290     return false;
2291 }
2292 
next(SkScalar * array,int * count)2293 bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
2294     const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2295     fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
2296     fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
2297     if (fCache->findPath(glyph)) {
2298         fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex),
2299                 const_cast<SkGlyph*>(&glyph), array, count);
2300     }
2301     return fText < fStop;
2302 }
2303 
2304 ///////////////////////////////////////////////////////////////////////////////
2305 
2306 // return true if the filter exists, and may affect alpha
affects_alpha(const SkColorFilter * cf)2307 static bool affects_alpha(const SkColorFilter* cf) {
2308     return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
2309 }
2310 
2311 // return true if the filter exists, and may affect alpha
affects_alpha(const SkImageFilter * imf)2312 static bool affects_alpha(const SkImageFilter* imf) {
2313     // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
2314     // ala colorfilters
2315     return imf != nullptr;
2316 }
2317 
nothingToDraw() const2318 bool SkPaint::nothingToDraw() const {
2319     if (fDrawLooper) {
2320         return false;
2321     }
2322     switch ((SkBlendMode)fBlendMode) {
2323         case SkBlendMode::kSrcOver:
2324         case SkBlendMode::kSrcATop:
2325         case SkBlendMode::kDstOut:
2326         case SkBlendMode::kDstOver:
2327         case SkBlendMode::kPlus:
2328             if (0 == this->getAlpha()) {
2329                 return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
2330             }
2331             break;
2332         case SkBlendMode::kDst:
2333             return true;
2334         default:
2335             break;
2336     }
2337     return false;
2338 }
2339 
getHash() const2340 uint32_t SkPaint::getHash() const {
2341     // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
2342     // so fBitfields should be 10 pointers and 6 32-bit values from the start.
2343     static_assert(offsetof(SkPaint, fBitfields) == 8 * sizeof(void*) + 7 * sizeof(uint32_t),
2344                   "SkPaint_notPackedTightly");
2345     return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
2346                         offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
2347 }
2348