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