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