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