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