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