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