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