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