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