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