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