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