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