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