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