SkPaint.cpp revision 4526a847da6dc738dc73103ec4d47cc0dbdec478
1/* libs/graphics/sgl/SkPaint.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkPaint.h"
19#include "SkColorFilter.h"
20#include "SkDrawLooper.h"
21#include "SkFontHost.h"
22#include "SkMaskFilter.h"
23#include "SkPathEffect.h"
24#include "SkRasterizer.h"
25#include "SkShader.h"
26#include "SkScalerContext.h"
27#include "SkStroke.h"
28#include "SkTypeface.h"
29#include "SkXfermode.h"
30#include "SkAutoKern.h"
31
32#define SK_DefaultTextSize      SkIntToScalar(12)
33
34#define SK_DefaultFlags         0   //(kNativeHintsText_Flag)
35
36SkPaint::SkPaint() {
37    // since we may have padding, we zero everything so that our memcmp() call
38    // in operator== will work correctly.
39    // with this, we can skip 0 and null individual initializations
40    sk_bzero(this, sizeof(*this));
41
42#if 0   // not needed with the bzero call above
43    fTypeface   = NULL;
44    fTextSkewX  = 0;
45    fPathEffect  = NULL;
46    fShader      = NULL;
47    fXfermode    = NULL;
48    fMaskFilter  = NULL;
49    fColorFilter = NULL;
50    fRasterizer  = NULL;
51    fLooper      = NULL;
52    fWidth      = 0;
53#endif
54
55    fTextSize   = SK_DefaultTextSize;
56    fTextScaleX = SK_Scalar1;
57    fColor      = SK_ColorBLACK;
58    fMiterLimit = SK_DefaultMiterLimit;
59    fFlags      = SK_DefaultFlags;
60    fCapType    = kDefault_Cap;
61    fJoinType   = kDefault_Join;
62    fTextAlign  = kLeft_Align;
63    fStyle      = kFill_Style;
64    fTextEncoding = kUTF8_TextEncoding;
65    fHinting    = kNormal_Hinting;
66}
67
68SkPaint::SkPaint(const SkPaint& src)
69{
70    memcpy(this, &src, sizeof(src));
71
72    fTypeface->safeRef();
73    fPathEffect->safeRef();
74    fShader->safeRef();
75    fXfermode->safeRef();
76    fMaskFilter->safeRef();
77    fColorFilter->safeRef();
78    fRasterizer->safeRef();
79    fLooper->safeRef();
80}
81
82SkPaint::~SkPaint()
83{
84    fTypeface->safeUnref();
85    fPathEffect->safeUnref();
86    fShader->safeUnref();
87    fXfermode->safeUnref();
88    fMaskFilter->safeUnref();
89    fColorFilter->safeUnref();
90    fRasterizer->safeUnref();
91    fLooper->safeUnref();
92}
93
94SkPaint& SkPaint::operator=(const SkPaint& src)
95{
96    SkASSERT(&src);
97
98    src.fTypeface->safeRef();
99    src.fPathEffect->safeRef();
100    src.fShader->safeRef();
101    src.fXfermode->safeRef();
102    src.fMaskFilter->safeRef();
103    src.fColorFilter->safeRef();
104    src.fRasterizer->safeRef();
105    src.fLooper->safeRef();
106
107    fTypeface->safeUnref();
108    fPathEffect->safeUnref();
109    fShader->safeUnref();
110    fXfermode->safeUnref();
111    fMaskFilter->safeUnref();
112    fColorFilter->safeUnref();
113    fRasterizer->safeUnref();
114    fLooper->safeUnref();
115
116    memcpy(this, &src, sizeof(src));
117
118    return *this;
119}
120
121int operator==(const SkPaint& a, const SkPaint& b)
122{
123    return memcmp(&a, &b, sizeof(a)) == 0;
124}
125
126void SkPaint::reset()
127{
128    SkPaint init;
129
130    *this = init;
131}
132
133void SkPaint::setFlags(uint32_t flags)
134{
135    fFlags = flags;
136}
137
138void SkPaint::setAntiAlias(bool doAA)
139{
140    this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
141}
142
143void SkPaint::setDither(bool doDither)
144{
145    this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
146}
147
148void SkPaint::setSubpixelText(bool doSubpixel)
149{
150    this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
151}
152
153void SkPaint::setLCDRenderText(bool doLCDRender)
154{
155    this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
156}
157
158void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText)
159{
160    this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
161}
162
163void SkPaint::setLinearText(bool doLinearText)
164{
165    this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
166}
167
168void SkPaint::setUnderlineText(bool doUnderline)
169{
170    this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
171}
172
173void SkPaint::setStrikeThruText(bool doStrikeThru)
174{
175    this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
176}
177
178void SkPaint::setFakeBoldText(bool doFakeBold)
179{
180    this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
181}
182
183void SkPaint::setDevKernText(bool doDevKern)
184{
185    this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
186}
187
188void SkPaint::setFilterBitmap(bool doFilter)
189{
190    this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
191}
192
193void SkPaint::setStyle(Style style)
194{
195    if ((unsigned)style < kStyleCount)
196        fStyle = style;
197#ifdef SK_DEBUG
198    else
199        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
200#endif
201}
202
203void SkPaint::setColor(SkColor color)
204{
205    fColor = color;
206}
207
208void SkPaint::setAlpha(U8CPU a)
209{
210    fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor));
211}
212
213void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
214{
215    fColor = SkColorSetARGB(a, r, g, b);
216}
217
218void SkPaint::setStrokeWidth(SkScalar width)
219{
220    if (width >= 0)
221        fWidth = width;
222#ifdef SK_DEBUG
223    else
224        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
225#endif
226}
227
228void SkPaint::setStrokeMiter(SkScalar limit)
229{
230    if (limit >= 0)
231        fMiterLimit = limit;
232#ifdef SK_DEBUG
233    else
234        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
235#endif
236}
237
238void SkPaint::setStrokeCap(Cap ct)
239{
240    if ((unsigned)ct < kCapCount)
241        fCapType = SkToU8(ct);
242#ifdef SK_DEBUG
243    else
244        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
245#endif
246}
247
248void SkPaint::setStrokeJoin(Join jt)
249{
250    if ((unsigned)jt < kJoinCount)
251        fJoinType = SkToU8(jt);
252#ifdef SK_DEBUG
253    else
254        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
255#endif
256}
257
258//////////////////////////////////////////////////////////////////
259
260void SkPaint::setTextAlign(Align align)
261{
262    if ((unsigned)align < kAlignCount)
263        fTextAlign = SkToU8(align);
264#ifdef SK_DEBUG
265    else
266        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
267#endif
268}
269
270void SkPaint::setTextSize(SkScalar ts)
271{
272    if (ts > 0)
273        fTextSize = ts;
274#ifdef SK_DEBUG
275    else
276        SkDebugf("SkPaint::setTextSize() called with non-positive value\n");
277#endif
278}
279
280void SkPaint::setTextScaleX(SkScalar scaleX)
281{
282    fTextScaleX = scaleX;
283}
284
285void SkPaint::setTextSkewX(SkScalar skewX)
286{
287    fTextSkewX = skewX;
288}
289
290void SkPaint::setTextEncoding(TextEncoding encoding)
291{
292    if ((unsigned)encoding <= kGlyphID_TextEncoding)
293        fTextEncoding = encoding;
294#ifdef SK_DEBUG
295    else
296        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
297#endif
298}
299
300///////////////////////////////////////////////////////////////////////////////////////
301
302SkTypeface* SkPaint::setTypeface(SkTypeface* font)
303{
304    SkRefCnt_SafeAssign(fTypeface, font);
305    return font;
306}
307
308SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r)
309{
310    SkRefCnt_SafeAssign(fRasterizer, r);
311    return r;
312}
313
314SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
315{
316    SkRefCnt_SafeAssign(fLooper, looper);
317    return looper;
318}
319
320///////////////////////////////////////////////////////////////////////////////
321
322#include "SkGlyphCache.h"
323#include "SkUtils.h"
324
325int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
326                          uint16_t glyphs[]) const {
327    if (byteLength == 0) {
328        return 0;
329    }
330
331    SkASSERT(textData != NULL);
332
333    if (NULL == glyphs) {
334        switch (this->getTextEncoding()) {
335        case kUTF8_TextEncoding:
336            return SkUTF8_CountUnichars((const char*)textData, byteLength);
337        case kUTF16_TextEncoding:
338            return SkUTF16_CountUnichars((const uint16_t*)textData,
339                                         byteLength >> 1);
340        case kGlyphID_TextEncoding:
341            return byteLength >> 1;
342        default:
343            SkASSERT(!"unknown text encoding");
344        }
345        return 0;
346    }
347
348    // if we get here, we have a valid glyphs[] array, so time to fill it in
349
350    // handle this encoding before the setup for the glyphcache
351    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
352        // we want to ignore the low bit of byteLength
353        memcpy(glyphs, textData, byteLength >> 1 << 1);
354        return byteLength >> 1;
355    }
356
357    SkAutoGlyphCache autoCache(*this, NULL);
358    SkGlyphCache*    cache = autoCache.getCache();
359
360    const char* text = (const char*)textData;
361    const char* stop = text + byteLength;
362    uint16_t*   gptr = glyphs;
363
364    switch (this->getTextEncoding()) {
365        case SkPaint::kUTF8_TextEncoding:
366            while (text < stop) {
367                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
368            }
369            break;
370        case SkPaint::kUTF16_TextEncoding: {
371            const uint16_t* text16 = (const uint16_t*)text;
372            const uint16_t* stop16 = (const uint16_t*)stop;
373            while (text16 < stop16) {
374                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
375            }
376            break;
377        }
378        default:
379            SkASSERT(!"unknown text encoding");
380    }
381    return gptr - glyphs;
382}
383
384bool SkPaint::containsText(const void* textData, size_t byteLength) const {
385    if (0 == byteLength) {
386        return true;
387    }
388
389    SkASSERT(textData != NULL);
390
391    // handle this encoding before the setup for the glyphcache
392    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
393        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
394        size_t count = byteLength >> 1;
395        for (size_t i = 0; i < count; i++) {
396            if (0 == glyphID[i]) {
397                return false;
398            }
399        }
400        return true;
401    }
402
403    SkAutoGlyphCache autoCache(*this, NULL);
404    SkGlyphCache*    cache = autoCache.getCache();
405
406    switch (this->getTextEncoding()) {
407        case SkPaint::kUTF8_TextEncoding: {
408            const char* text = static_cast<const char*>(textData);
409            const char* stop = text + byteLength;
410            while (text < stop) {
411                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
412                    return false;
413                }
414            }
415            break;
416        }
417        case SkPaint::kUTF16_TextEncoding: {
418            const uint16_t* text = static_cast<const uint16_t*>(textData);
419            const uint16_t* stop = text + (byteLength >> 1);
420            while (text < stop) {
421                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
422                    return false;
423                }
424            }
425            break;
426        }
427        default:
428            SkASSERT(!"unknown text encoding");
429            return false;
430    }
431    return true;
432}
433
434void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
435                               SkUnichar textData[]) const {
436    if (count <= 0) {
437        return;
438    }
439
440    SkASSERT(glyphs != NULL);
441    SkASSERT(textData != NULL);
442
443    SkAutoGlyphCache autoCache(*this, NULL);
444    SkGlyphCache*    cache = autoCache.getCache();
445
446    for (int index = 0; index < count; index++) {
447        textData[index] = cache->glyphToUnichar(glyphs[index]);
448    }
449}
450
451///////////////////////////////////////////////////////////////////////////////
452
453static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, const char** text)
454{
455    SkASSERT(cache != NULL);
456    SkASSERT(text != NULL);
457
458    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
459}
460
461static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache, const char** text)
462{
463    SkASSERT(cache != NULL);
464    SkASSERT(text != NULL);
465
466    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
467}
468
469static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, const char** text)
470{
471    SkASSERT(cache != NULL);
472    SkASSERT(text != NULL);
473
474    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
475}
476
477static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache, const char** text)
478{
479    SkASSERT(cache != NULL);
480    SkASSERT(text != NULL);
481
482    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
483}
484
485static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, const char** text)
486{
487    SkASSERT(cache != NULL);
488    SkASSERT(text != NULL);
489
490    const uint16_t* ptr = *(const uint16_t**)text;
491    unsigned glyphID = *ptr;
492    ptr += 1;
493    *text = (const char*)ptr;
494    return cache->getGlyphIDMetrics(glyphID);
495}
496
497static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache, const char** text)
498{
499    SkASSERT(cache != NULL);
500    SkASSERT(text != NULL);
501
502    const uint16_t* ptr = *(const uint16_t**)text;
503    ptr -= 1;
504    unsigned glyphID = *ptr;
505    *text = (const char*)ptr;
506    return cache->getGlyphIDMetrics(glyphID);
507}
508
509///
510
511static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, const char** text)
512{
513    SkASSERT(cache != NULL);
514    SkASSERT(text != NULL);
515
516    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
517}
518
519static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache, const char** text)
520{
521    SkASSERT(cache != NULL);
522    SkASSERT(text != NULL);
523
524    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
525}
526
527static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, const char** text)
528{
529    SkASSERT(cache != NULL);
530    SkASSERT(text != NULL);
531
532    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
533}
534
535static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache, const char** text)
536{
537    SkASSERT(cache != NULL);
538    SkASSERT(text != NULL);
539
540    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
541}
542
543static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, const char** text)
544{
545    SkASSERT(cache != NULL);
546    SkASSERT(text != NULL);
547
548    const uint16_t* ptr = *(const uint16_t**)text;
549    unsigned glyphID = *ptr;
550    ptr += 1;
551    *text = (const char*)ptr;
552    return cache->getGlyphIDAdvance(glyphID);
553}
554
555static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache, const char** text)
556{
557    SkASSERT(cache != NULL);
558    SkASSERT(text != NULL);
559
560    const uint16_t* ptr = *(const uint16_t**)text;
561    ptr -= 1;
562    unsigned glyphID = *ptr;
563    *text = (const char*)ptr;
564    return cache->getGlyphIDAdvance(glyphID);
565}
566
567SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
568                                                bool needFullMetrics) const
569{
570    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
571        sk_getMetrics_utf8_next,
572        sk_getMetrics_utf16_next,
573        sk_getMetrics_glyph_next,
574
575        sk_getMetrics_utf8_prev,
576        sk_getMetrics_utf16_prev,
577        sk_getMetrics_glyph_prev,
578
579        sk_getAdvance_utf8_next,
580        sk_getAdvance_utf16_next,
581        sk_getAdvance_glyph_next,
582
583        sk_getAdvance_utf8_prev,
584        sk_getAdvance_utf16_prev,
585        sk_getAdvance_glyph_prev
586    };
587
588    unsigned index = this->getTextEncoding();
589
590    if (kBackward_TextBufferDirection == tbd)
591        index += 3;
592    if (!needFullMetrics && !this->isDevKernText())
593        index += 6;
594
595    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
596    return gMeasureCacheProcs[index];
597}
598
599///////////////////////////////////////////////////////////////////////////////
600
601static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
602                                            const char** text, SkFixed, SkFixed)
603{
604    SkASSERT(cache != NULL);
605    SkASSERT(text != NULL);
606
607    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
608}
609
610static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
611                                            const char** text, SkFixed x, SkFixed y)
612{
613    SkASSERT(cache != NULL);
614    SkASSERT(text != NULL);
615
616    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
617}
618
619static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache, const char** text,
620                                             SkFixed, SkFixed)
621{
622    SkASSERT(cache != NULL);
623    SkASSERT(text != NULL);
624
625    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
626}
627
628static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
629                                             const char** text, SkFixed x, SkFixed y)
630{
631    SkASSERT(cache != NULL);
632    SkASSERT(text != NULL);
633
634    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
635                                    x, y);
636}
637
638static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache, const char** text,
639                                             SkFixed, SkFixed)
640{
641    SkASSERT(cache != NULL);
642    SkASSERT(text != NULL);
643
644    const uint16_t* ptr = *(const uint16_t**)text;
645    unsigned glyphID = *ptr;
646    ptr += 1;
647    *text = (const char*)ptr;
648    return cache->getGlyphIDMetrics(glyphID);
649}
650
651static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
652                                             const char** text, SkFixed x, SkFixed y)
653{
654    SkASSERT(cache != NULL);
655    SkASSERT(text != NULL);
656
657    const uint16_t* ptr = *(const uint16_t**)text;
658    unsigned glyphID = *ptr;
659    ptr += 1;
660    *text = (const char*)ptr;
661    return cache->getGlyphIDMetrics(glyphID, x, y);
662}
663
664SkDrawCacheProc SkPaint::getDrawCacheProc() const
665{
666    static const SkDrawCacheProc gDrawCacheProcs[] = {
667        sk_getMetrics_utf8_00,
668        sk_getMetrics_utf16_00,
669        sk_getMetrics_glyph_00,
670
671        sk_getMetrics_utf8_xy,
672        sk_getMetrics_utf16_xy,
673        sk_getMetrics_glyph_xy
674    };
675
676    unsigned index = this->getTextEncoding();
677    if (fFlags & kSubpixelText_Flag)
678        index += 3;
679
680    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
681    return gDrawCacheProcs[index];
682}
683
684///////////////////////////////////////////////////////////////////////////////
685
686class SkAutoRestorePaintTextSizeAndFrame {
687public:
688    SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) : fPaint((SkPaint*)paint)
689    {
690        fTextSize = paint->getTextSize();
691        fStyle = paint->getStyle();
692        fPaint->setStyle(SkPaint::kFill_Style);
693    }
694    ~SkAutoRestorePaintTextSizeAndFrame()
695    {
696        fPaint->setStyle(fStyle);
697        fPaint->setTextSize(fTextSize);
698    }
699
700private:
701    SkPaint*        fPaint;
702    SkScalar        fTextSize;
703    SkPaint::Style  fStyle;
704};
705
706static void set_bounds(const SkGlyph& g, SkRect* bounds)
707{
708    bounds->set(SkIntToScalar(g.fLeft),
709                SkIntToScalar(g.fTop),
710                SkIntToScalar(g.fLeft + g.fWidth),
711                SkIntToScalar(g.fTop + g.fHeight));
712}
713
714static void join_bounds(const SkGlyph& g, SkRect* bounds, SkFixed dx)
715{
716    SkScalar sx = SkFixedToScalar(dx);
717    bounds->join(SkIntToScalar(g.fLeft) + sx,
718                 SkIntToScalar(g.fTop),
719                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
720                 SkIntToScalar(g.fTop + g.fHeight));
721}
722
723SkScalar SkPaint::measure_text(SkGlyphCache* cache,
724                               const char* text, size_t byteLength,
725                               int* count, SkRect* bounds) const
726{
727    SkASSERT(count);
728    if (byteLength == 0)
729    {
730        *count = 0;
731        if (bounds)
732            bounds->setEmpty();
733        return 0;
734    }
735
736    SkMeasureCacheProc glyphCacheProc;
737    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
738                                               NULL != bounds);
739
740    int         n = 1;
741    const char* stop = (const char*)text + byteLength;
742    const SkGlyph* g = &glyphCacheProc(cache, &text);
743    SkFixed x = g->fAdvanceX;
744
745    SkAutoKern  autokern;
746
747    if (NULL == bounds)
748    {
749        if (this->isDevKernText())
750        {
751            int rsb;
752            for (; text < stop; n++) {
753                rsb = g->fRsbDelta;
754                g = &glyphCacheProc(cache, &text);
755                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
756            }
757        }
758        else
759        {
760            for (; text < stop; n++) {
761                x += glyphCacheProc(cache, &text).fAdvanceX;
762            }
763        }
764    }
765    else
766    {
767        set_bounds(*g, bounds);
768        if (this->isDevKernText())
769        {
770            int rsb;
771            for (; text < stop; n++) {
772                rsb = g->fRsbDelta;
773                g = &glyphCacheProc(cache, &text);
774                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
775                join_bounds(*g, bounds, x);
776                x += g->fAdvanceX;
777            }
778        }
779        else
780        {
781            for (; text < stop; n++) {
782                g = &glyphCacheProc(cache, &text);
783                join_bounds(*g, bounds, x);
784                x += g->fAdvanceX;
785            }
786        }
787    }
788    SkASSERT(text == stop);
789
790    *count = n;
791    return SkFixedToScalar(x);
792}
793
794SkScalar SkPaint::measureText(const void* textData, size_t length,
795                              SkRect* bounds, SkScalar zoom) const
796{
797    const char* text = (const char*)textData;
798    SkASSERT(text != NULL || length == 0);
799
800    SkScalar                            scale = 0;
801    SkAutoRestorePaintTextSizeAndFrame  restore(this);
802
803    if (this->isLinearText())
804    {
805        scale = fTextSize / kCanonicalTextSizeForPaths;
806        // this gets restored by restore
807        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
808    }
809
810    SkMatrix    zoomMatrix, *zoomPtr = NULL;
811    if (zoom)
812    {
813        zoomMatrix.setScale(zoom, zoom);
814        zoomPtr = &zoomMatrix;
815    }
816
817    SkAutoGlyphCache    autoCache(*this, zoomPtr);
818    SkGlyphCache*       cache = autoCache.getCache();
819
820    SkScalar width = 0;
821
822    if (length > 0)
823    {
824        int tempCount;
825
826        width = this->measure_text(cache, text, length, &tempCount, bounds);
827        if (scale)
828        {
829            width = SkScalarMul(width, scale);
830            if (bounds)
831            {
832                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
833                bounds->fTop = SkScalarMul(bounds->fTop, scale);
834                bounds->fRight = SkScalarMul(bounds->fRight, scale);
835                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
836            }
837        }
838    }
839    return width;
840}
841
842typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
843
844static bool forward_textBufferPred(const char* text, const char* stop)
845{
846    return text < stop;
847}
848
849static bool backward_textBufferPred(const char* text, const char* stop)
850{
851    return text > stop;
852}
853
854static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
855                            const char** text, size_t length, const char** stop)
856{
857    if (SkPaint::kForward_TextBufferDirection == tbd)
858    {
859        *stop = *text + length;
860        return forward_textBufferPred;
861    }
862    else
863    {
864        // text should point to the end of the buffer, and stop to the beginning
865        *stop = *text;
866        *text += length;
867        return backward_textBufferPred;
868    }
869}
870
871size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
872                          SkScalar* measuredWidth,
873                          TextBufferDirection tbd) const
874{
875    if (0 == length || 0 >= maxWidth)
876    {
877        if (measuredWidth)
878            *measuredWidth = 0;
879        return 0;
880    }
881
882    SkASSERT(textD != NULL);
883    const char* text = (const char*)textD;
884
885    SkScalar                            scale = 0;
886    SkAutoRestorePaintTextSizeAndFrame  restore(this);
887
888    if (this->isLinearText())
889    {
890        scale = fTextSize / kCanonicalTextSizeForPaths;
891        // this gets restored by restore
892        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
893    }
894
895    SkAutoGlyphCache    autoCache(*this, NULL);
896    SkGlyphCache*       cache = autoCache.getCache();
897
898    SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
899    const char*      stop;
900    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
901    SkFixed          max = SkScalarToFixed(maxWidth);
902    SkFixed          width = 0;
903
904    SkAutoKern  autokern;
905
906    if (this->isDevKernText())
907    {
908        int rsb = 0;
909        while (pred(text, stop))
910        {
911            const char* curr = text;
912            const SkGlyph& g = glyphCacheProc(cache, &text);
913            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
914            if ((width += x) > max)
915            {
916                width -= x;
917                text = curr;
918                break;
919            }
920            rsb = g.fRsbDelta;
921        }
922    }
923    else
924    {
925        while (pred(text, stop))
926        {
927            const char* curr = text;
928            SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
929            if ((width += x) > max)
930            {
931                width -= x;
932                text = curr;
933                break;
934            }
935        }
936    }
937
938    if (measuredWidth)
939    {
940
941        SkScalar scalarWidth = SkFixedToScalar(width);
942        if (scale)
943            scalarWidth = SkScalarMul(scalarWidth, scale);
944        *measuredWidth = scalarWidth;
945    }
946
947    // return the number of bytes measured
948    return (kForward_TextBufferDirection == tbd) ?
949                text - stop + length : stop - text + length;
950}
951
952///////////////////////////////////////////////////////////////////////////////
953
954static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context)
955{
956    *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
957    return false;   // don't detach the cache
958}
959
960static void FontMetricsDescProc(const SkDescriptor* desc, void* context)
961{
962    SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
963}
964
965SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const
966{
967    SkScalar                            scale = 0;
968    SkAutoRestorePaintTextSizeAndFrame  restore(this);
969
970    if (this->isLinearText())
971    {
972        scale = fTextSize / kCanonicalTextSizeForPaths;
973        // this gets restored by restore
974        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
975    }
976
977    SkMatrix    zoomMatrix, *zoomPtr = NULL;
978    if (zoom)
979    {
980        zoomMatrix.setScale(zoom, zoom);
981        zoomPtr = &zoomMatrix;
982    }
983
984#if 0
985    SkAutoGlyphCache    autoCache(*this, zoomPtr);
986    SkGlyphCache*       cache = autoCache.getCache();
987    const FontMetrics&  my = cache->getFontMetricsY();
988#endif
989    FontMetrics storage;
990    if (NULL == metrics)
991        metrics = &storage;
992
993    this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
994
995    if (scale)
996    {
997        metrics->fTop = SkScalarMul(metrics->fTop, scale);
998        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
999        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1000        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1001        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1002    }
1003    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1004}
1005
1006////////////////////////////////////////////////////////////////////////////////////////////
1007
1008static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale)
1009{
1010    bounds->set(g.fLeft * scale,
1011                g.fTop * scale,
1012                (g.fLeft + g.fWidth) * scale,
1013                (g.fTop + g.fHeight) * scale);
1014}
1015
1016int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[],
1017                           SkRect bounds[]) const
1018{
1019    if (0 == byteLength)
1020        return 0;
1021
1022    SkASSERT(NULL != textData);
1023
1024    if (NULL == widths && NULL == bounds)
1025        return this->countText(textData, byteLength);
1026
1027    SkAutoRestorePaintTextSizeAndFrame  restore(this);
1028    SkScalar                            scale = 0;
1029
1030    if (this->isLinearText())
1031    {
1032        scale = fTextSize / kCanonicalTextSizeForPaths;
1033        // this gets restored by restore
1034        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
1035    }
1036
1037    SkAutoGlyphCache    autoCache(*this, NULL);
1038    SkGlyphCache*       cache = autoCache.getCache();
1039    SkMeasureCacheProc  glyphCacheProc;
1040    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1041                                               NULL != bounds);
1042
1043    const char* text = (const char*)textData;
1044    const char* stop = text + byteLength;
1045    int         count = 0;
1046
1047    if (this->isDevKernText())
1048    {
1049        // we adjust the widths returned here through auto-kerning
1050        SkAutoKern  autokern;
1051        SkFixed     prevWidth = 0;
1052
1053        if (scale) {
1054            while (text < stop) {
1055                const SkGlyph& g = glyphCacheProc(cache, &text);
1056                if (widths) {
1057                    SkFixed  adjust = autokern.adjust(g);
1058
1059                    if (count > 0) {
1060                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
1061                        *widths++ = SkScalarMul(w, scale);
1062                    }
1063                    prevWidth = g.fAdvanceX;
1064                }
1065                if (bounds) {
1066                    set_bounds(g, bounds++, scale);
1067                }
1068                ++count;
1069            }
1070            if (count > 0 && widths) {
1071                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1072            }
1073        } else {
1074            while (text < stop) {
1075                const SkGlyph& g = glyphCacheProc(cache, &text);
1076                if (widths) {
1077                    SkFixed  adjust = autokern.adjust(g);
1078
1079                    if (count > 0) {
1080                        *widths++ = SkFixedToScalar(prevWidth + adjust);
1081                    }
1082                    prevWidth = g.fAdvanceX;
1083                }
1084                if (bounds) {
1085                    set_bounds(g, bounds++);
1086                }
1087                ++count;
1088            }
1089            if (count > 0 && widths) {
1090                *widths = SkFixedToScalar(prevWidth);
1091            }
1092        }
1093    } else {    // no devkern
1094        if (scale) {
1095            while (text < stop) {
1096                const SkGlyph& g = glyphCacheProc(cache, &text);
1097                if (widths) {
1098                    *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
1099                                            scale);
1100                }
1101                if (bounds) {
1102                    set_bounds(g, bounds++, scale);
1103                }
1104                ++count;
1105            }
1106        } else {
1107            while (text < stop) {
1108                const SkGlyph& g = glyphCacheProc(cache, &text);
1109                if (widths) {
1110                    *widths++ = SkFixedToScalar(g.fAdvanceX);
1111                }
1112                if (bounds) {
1113                    set_bounds(g, bounds++);
1114                }
1115                ++count;
1116            }
1117        }
1118    }
1119
1120    SkASSERT(text == stop);
1121    return count;
1122}
1123
1124////////////////////////////////////////////////////////////////////////////////////////////
1125
1126#include "SkDraw.h"
1127
1128void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const
1129{
1130    const char* text = (const char*)textData;
1131    SkASSERT(length == 0 || text != NULL);
1132    if (text == NULL || length == 0 || path == NULL)
1133        return;
1134
1135    SkTextToPathIter    iter(text, length, *this, false, true);
1136    SkMatrix            matrix;
1137    SkScalar            prevXPos = 0;
1138
1139    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1140    matrix.postTranslate(x, y);
1141    path->reset();
1142
1143    SkScalar        xpos;
1144    const SkPath*   iterPath;
1145    while ((iterPath = iter.next(&xpos)) != NULL)
1146    {
1147        matrix.postTranslate(xpos - prevXPos, 0);
1148        path->addPath(*iterPath, matrix);
1149        prevXPos = xpos;
1150    }
1151}
1152
1153static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1154                            SkFlattenableWriteBuffer* buffer) {
1155    buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
1156}
1157
1158/*
1159 *  interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i])
1160    inspired by a desire to change the multiplier for thickness in fakebold
1161    therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient
1162    repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if
1163        key is the value of a repeated scalar in keys, the first one will be used
1164    - this may change if a binary search is used
1165    - also, this ensures that there is no divide by zero (an assert also checks for that)
1166*/
1167static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length)
1168{
1169
1170    SkASSERT(length > 0);
1171    SkASSERT(keys != NULL);
1172    SkASSERT(values != NULL);
1173#ifdef SK_DEBUG
1174    for (int i = 1; i < length; i++)
1175        SkASSERT(keys[i] >= keys[i-1]);
1176#endif
1177    int right = 0;
1178    while (right < length && key > keys[right])
1179        right++;
1180    //could use sentinal values to eliminate conditionals
1181    //i assume i am not in control of input values, so i want to make it simple
1182    if (length == right)
1183        return values[length-1];
1184    if (0 == right)
1185        return values[0];
1186    //otherwise, we interpolate between right-1 and right
1187    SkScalar rVal = values[right];
1188    SkScalar lVal = values[right-1];
1189    SkScalar rightKey = keys[right];
1190    SkScalar leftKey = keys[right-1];
1191    SkASSERT(rightKey != leftKey);
1192    //fractional amount which we will multiply by the difference in the left value and right value
1193    SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey);
1194    return lVal + SkScalarMul(fract, rVal-lVal);
1195}
1196
1197//used for interpolating in fakeBold
1198static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) };
1199static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 };
1200
1201static SkMask::Format computeMaskFormat(const SkPaint& paint)
1202{
1203    uint32_t flags = paint.getFlags();
1204
1205    // Antialiasing being disabled trumps all other settings.
1206    if (!(flags & SkPaint::kAntiAlias_Flag))
1207        return SkMask::kBW_Format;
1208
1209#if defined(SK_SUPPORT_LCDTEXT)
1210    if (flags & SkPaint::kLCDRenderText_Flag)
1211        return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
1212                   SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
1213#endif
1214
1215    return SkMask::kA8_Format;
1216}
1217
1218// if linear-text is on, then we force hinting to be off (since that's sort of
1219// the point of linear-text.
1220static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1221    SkPaint::Hinting h = paint.getHinting();
1222    if (paint.isLinearText()) {
1223        h = SkPaint::kNo_Hinting;
1224    }
1225    return h;
1226}
1227
1228void SkScalerContext::MakeRec(const SkPaint& paint,
1229                              const SkMatrix* deviceMatrix, Rec* rec)
1230{
1231    SkASSERT(deviceMatrix == NULL ||
1232             (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
1233
1234    rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
1235    rec->fTextSize = paint.getTextSize();
1236    rec->fPreScaleX = paint.getTextScaleX();
1237    rec->fPreSkewX  = paint.getTextSkewX();
1238
1239    if (deviceMatrix)
1240    {
1241        rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
1242        rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
1243        rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
1244        rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
1245    }
1246    else
1247    {
1248        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1249        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1250    }
1251
1252    SkPaint::Style  style = paint.getStyle();
1253    SkScalar        strokeWidth = paint.getStrokeWidth();
1254
1255    unsigned flags = SkFontHost::ComputeGammaFlag(paint);
1256
1257    if (paint.isFakeBoldText())
1258    {
1259#ifdef SK_USE_FREETYPE_EMBOLDEN
1260        flags |= SkScalerContext::kEmbolden_Flag;
1261#else
1262        SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2);
1263        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1264
1265        if (style == SkPaint::kFill_Style)
1266        {
1267            style = SkPaint::kStrokeAndFill_Style;
1268            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
1269        }
1270        else
1271            strokeWidth += extra;
1272#endif
1273    }
1274
1275    if (paint.isDevKernText())
1276        flags |= SkScalerContext::kDevKernText_Flag;
1277
1278    if (style != SkPaint::kFill_Style && strokeWidth > 0)
1279    {
1280        rec->fFrameWidth = strokeWidth;
1281        rec->fMiterLimit = paint.getStrokeMiter();
1282        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1283
1284        if (style == SkPaint::kStrokeAndFill_Style)
1285            flags |= SkScalerContext::kFrameAndFill_Flag;
1286    }
1287    else
1288    {
1289        rec->fFrameWidth = 0;
1290        rec->fMiterLimit = 0;
1291        rec->fStrokeJoin = 0;
1292    }
1293
1294    rec->fSubpixelPositioning = paint.isSubpixelText();
1295    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1296    rec->fFlags = SkToU8(flags);
1297    rec->setHinting(computeHinting(paint));
1298    if (paint.isEmbeddedBitmapText())
1299        rec->fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1300
1301    /*  Allow the fonthost to modify our rec before we use it as a key into the
1302        cache. This way if we're asking for something that they will ignore,
1303        they can modify our rec up front, so we don't create duplicate cache
1304        entries.
1305     */
1306    SkFontHost::FilterRec(rec);
1307}
1308
1309#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
1310
1311void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
1312                             void (*proc)(const SkDescriptor*, void*),
1313                             void* context) const
1314{
1315    SkScalerContext::Rec    rec;
1316
1317    SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1318
1319    size_t          descSize = sizeof(rec);
1320    int             entryCount = 1;
1321    SkPathEffect*   pe = this->getPathEffect();
1322    SkMaskFilter*   mf = this->getMaskFilter();
1323    SkRasterizer*   ra = this->getRasterizer();
1324
1325    SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1326    SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1327    SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1328
1329    if (pe) {
1330        peBuffer.writeFlattenable(pe);
1331        descSize += peBuffer.size();
1332        entryCount += 1;
1333        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
1334        // seems like we could support kLCD as well at this point...
1335    }
1336    if (mf) {
1337        mfBuffer.writeFlattenable(mf);
1338        descSize += mfBuffer.size();
1339        entryCount += 1;
1340        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1341    }
1342    if (ra) {
1343        raBuffer.writeFlattenable(ra);
1344        descSize += raBuffer.size();
1345        entryCount += 1;
1346        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
1347    }
1348    descSize += SkDescriptor::ComputeOverhead(entryCount);
1349
1350    SkAutoDescriptor    ad(descSize);
1351    SkDescriptor*       desc = ad.getDesc();
1352
1353    desc->init();
1354    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1355
1356    if (pe) {
1357        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1358    }
1359    if (mf) {
1360        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1361    }
1362    if (ra) {
1363        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1364    }
1365
1366    SkASSERT(descSize == desc->getLength());
1367    desc->computeChecksum();
1368
1369    proc(desc, context);
1370}
1371
1372static void DetachDescProc(const SkDescriptor* desc, void* context)
1373{
1374    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
1375}
1376
1377SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
1378{
1379    SkGlyphCache* cache;
1380    this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
1381    return cache;
1382}
1383
1384///////////////////////////////////////////////////////////////////////////////
1385
1386#include "SkStream.h"
1387
1388static uintptr_t asint(const void* p) {
1389    return reinterpret_cast<uintptr_t>(p);
1390}
1391
1392union Scalar32 {
1393    SkScalar    fScalar;
1394    uint32_t    f32;
1395};
1396
1397static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1398    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1399    Scalar32 tmp;
1400    tmp.fScalar = value;
1401    *ptr = tmp.f32;
1402    return ptr + 1;
1403}
1404
1405static SkScalar read_scalar(const uint32_t*& ptr) {
1406    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1407    Scalar32 tmp;
1408    tmp.f32 = *ptr++;
1409    return tmp.fScalar;
1410}
1411
1412static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1413    SkASSERT(a == (uint8_t)a);
1414    SkASSERT(b == (uint8_t)b);
1415    SkASSERT(c == (uint8_t)c);
1416    SkASSERT(d == (uint8_t)d);
1417    return (a << 24) | (b << 16) | (c << 8) | d;
1418}
1419
1420enum FlatFlags {
1421    kHasTypeface_FlatFlag   = 0x01,
1422    kHasEffects_FlatFlag    = 0x02
1423};
1424
1425// The size of a flat paint's POD fields
1426static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
1427                                        1 * sizeof(SkColor) +
1428                                        1 * sizeof(uint16_t) +
1429                                        6 * sizeof(uint8_t);
1430
1431/*  To save space/time, we analyze the paint, and write a truncated version of
1432    it if there are not tricky elements like shaders, etc.
1433 */
1434void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
1435    uint8_t flatFlags = 0;
1436    if (this->getTypeface()) {
1437        flatFlags |= kHasTypeface_FlatFlag;
1438    }
1439    if (asint(this->getPathEffect()) |
1440        asint(this->getShader()) |
1441        asint(this->getXfermode()) |
1442        asint(this->getMaskFilter()) |
1443        asint(this->getColorFilter()) |
1444        asint(this->getRasterizer()) |
1445        asint(this->getLooper())) {
1446        flatFlags |= kHasEffects_FlatFlag;
1447    }
1448
1449    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1450    uint32_t* ptr = buffer.reserve(kPODPaintSize);
1451
1452    ptr = write_scalar(ptr, this->getTextSize());
1453    ptr = write_scalar(ptr, this->getTextScaleX());
1454    ptr = write_scalar(ptr, this->getTextSkewX());
1455    ptr = write_scalar(ptr, this->getStrokeWidth());
1456    ptr = write_scalar(ptr, this->getStrokeMiter());
1457    *ptr++ = this->getColor();
1458    *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
1459    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1460                    this->getStyle(), this->getTextEncoding());
1461
1462    // now we're done with ptr and the (pre)reserved space. If we need to write
1463    // additional fields, use the buffer directly
1464    if (flatFlags & kHasTypeface_FlatFlag) {
1465        buffer.writeTypeface(this->getTypeface());
1466    }
1467    if (flatFlags & kHasEffects_FlatFlag) {
1468        buffer.writeFlattenable(this->getPathEffect());
1469        buffer.writeFlattenable(this->getShader());
1470        buffer.writeFlattenable(this->getXfermode());
1471        buffer.writeFlattenable(this->getMaskFilter());
1472        buffer.writeFlattenable(this->getColorFilter());
1473        buffer.writeFlattenable(this->getRasterizer());
1474        buffer.writeFlattenable(this->getLooper());
1475    }
1476}
1477
1478void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
1479    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1480    const void* podData = buffer.skip(kPODPaintSize);
1481    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1482
1483    // the order we read must match the order we wrote in flatten()
1484    this->setTextSize(read_scalar(pod));
1485    this->setTextScaleX(read_scalar(pod));
1486    this->setTextSkewX(read_scalar(pod));
1487    this->setStrokeWidth(read_scalar(pod));
1488    this->setStrokeMiter(read_scalar(pod));
1489    this->setColor(*pod++);
1490
1491    uint32_t tmp = *pod++;
1492    this->setFlags(tmp >> 16);
1493    this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
1494    uint8_t flatFlags = tmp & 0xFF;
1495
1496    tmp = *pod++;
1497    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1498    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1499    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1500    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1501
1502    if (flatFlags & kHasTypeface_FlatFlag) {
1503        this->setTypeface(buffer.readTypeface());
1504    } else {
1505        this->setTypeface(NULL);
1506    }
1507
1508    if (flatFlags & kHasEffects_FlatFlag) {
1509        this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
1510        this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
1511        this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
1512        this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
1513        this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
1514        this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
1515        this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
1516    } else {
1517        this->setPathEffect(NULL);
1518        this->setShader(NULL);
1519        this->setXfermode(NULL);
1520        this->setMaskFilter(NULL);
1521        this->setColorFilter(NULL);
1522        this->setRasterizer(NULL);
1523        this->setLooper(NULL);
1524    }
1525}
1526
1527///////////////////////////////////////////////////////////////////////////////
1528
1529SkShader* SkPaint::setShader(SkShader* shader)
1530{
1531    SkRefCnt_SafeAssign(fShader, shader);
1532    return shader;
1533}
1534
1535SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
1536{
1537    SkRefCnt_SafeAssign(fColorFilter, filter);
1538    return filter;
1539}
1540
1541SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
1542{
1543    SkRefCnt_SafeAssign(fXfermode, mode);
1544    return mode;
1545}
1546
1547SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
1548    SkSafeUnref(fXfermode);
1549    fXfermode = SkXfermode::Create(mode);
1550    return fXfermode;
1551}
1552
1553SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
1554{
1555    SkRefCnt_SafeAssign(fPathEffect, effect);
1556    return effect;
1557}
1558
1559SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
1560{
1561    SkRefCnt_SafeAssign(fMaskFilter, filter);
1562    return filter;
1563}
1564
1565////////////////////////////////////////////////////////////////////////////////////////
1566
1567bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
1568{
1569    SkPath          effectPath, strokePath;
1570    const SkPath*   path = &src;
1571
1572    SkScalar width = this->getStrokeWidth();
1573
1574    switch (this->getStyle()) {
1575    case SkPaint::kFill_Style:
1576        width = -1; // mark it as no-stroke
1577        break;
1578    case SkPaint::kStrokeAndFill_Style:
1579        if (width == 0)
1580            width = -1; // mark it as no-stroke
1581        break;
1582    case SkPaint::kStroke_Style:
1583        break;
1584    default:
1585        SkASSERT(!"unknown paint style");
1586    }
1587
1588    if (this->getPathEffect())
1589    {
1590        // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
1591        if (this->getStyle() == SkPaint::kStrokeAndFill_Style)
1592            width = -1; // mark it as no-stroke
1593
1594        if (this->getPathEffect()->filterPath(&effectPath, src, &width))
1595            path = &effectPath;
1596
1597        // restore the width if we earlier had to lie, and if we're still set to no-stroke
1598        // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
1599        // and we want to respect that (i.e. don't overwrite their setting for width)
1600        if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0)
1601        {
1602            width = this->getStrokeWidth();
1603            if (width == 0)
1604                width = -1;
1605        }
1606    }
1607
1608    if (width > 0 && !path->isEmpty())
1609    {
1610        SkStroke stroker(*this, width);
1611        stroker.strokePath(*path, &strokePath);
1612        path = &strokePath;
1613    }
1614
1615    if (path == &src)
1616        *dst = src;
1617    else
1618    {
1619        SkASSERT(path == &effectPath || path == &strokePath);
1620        dst->swap(*(SkPath*)path);
1621    }
1622
1623    return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
1624}
1625
1626const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
1627                                               SkRect* storage) const {
1628    SkASSERT(storage);
1629    SkASSERT(this->getStyle() != SkPaint::kFill_Style);
1630
1631    // since we're stroked, outset the rect by the radius (and join type)
1632    SkScalar radius = SkScalarHalf(this->getStrokeWidth());
1633    if (0 == radius) {  // hairline
1634        radius = SK_Scalar1;
1635    } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
1636        SkScalar scale = this->getStrokeMiter();
1637        if (scale > SK_Scalar1) {
1638            radius = SkScalarMul(radius, scale);
1639        }
1640    }
1641    storage->set(src.fLeft - radius, src.fTop - radius,
1642                 src.fRight + radius, src.fBottom + radius);
1643    return *storage;
1644}
1645
1646////////////////////////////////////////////////////////////////////////////////////////
1647
1648static bool has_thick_frame(const SkPaint& paint)
1649{
1650    return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style;
1651}
1652
1653SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
1654                                    const SkPaint& paint,
1655                                    bool applyStrokeAndPathEffects,
1656                                    bool forceLinearTextOn)
1657                                    : fPaint(paint) /* make a copy of the paint */
1658{
1659    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
1660                                                true);
1661
1662    if (forceLinearTextOn)
1663        fPaint.setLinearText(true);
1664    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
1665
1666    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint))
1667        applyStrokeAndPathEffects = false;
1668
1669    // can't use our canonical size if we need to apply patheffects/strokes
1670    if (fPaint.isLinearText() && !applyStrokeAndPathEffects)
1671    {
1672        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
1673        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
1674    }
1675    else
1676        fScale = SK_Scalar1;
1677
1678    if (!applyStrokeAndPathEffects)
1679    {
1680        fPaint.setStyle(SkPaint::kFill_Style);
1681        fPaint.setPathEffect(NULL);
1682    }
1683
1684    fCache = fPaint.detachCache(NULL);
1685
1686    SkPaint::Style  style = SkPaint::kFill_Style;
1687    SkPathEffect*   pe = NULL;
1688
1689    if (!applyStrokeAndPathEffects)
1690    {
1691        style = paint.getStyle();   // restore
1692        pe = paint.getPathEffect();     // restore
1693    }
1694    fPaint.setStyle(style);
1695    fPaint.setPathEffect(pe);
1696    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
1697
1698    // now compute fXOffset if needed
1699
1700    SkScalar xOffset = 0;
1701    if (paint.getTextAlign() != SkPaint::kLeft_Align)   // need to measure first
1702    {
1703        int      count;
1704        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale);
1705        if (paint.getTextAlign() == SkPaint::kCenter_Align)
1706            width = SkScalarHalf(width);
1707        xOffset = -width;
1708    }
1709    fXPos = xOffset;
1710    fPrevAdvance = 0;
1711
1712    fText = text;
1713    fStop = text + length;
1714}
1715
1716SkTextToPathIter::~SkTextToPathIter()
1717{
1718    SkGlyphCache::AttachCache(fCache);
1719}
1720
1721const SkPath* SkTextToPathIter::next(SkScalar* xpos)
1722{
1723    while (fText < fStop)
1724    {
1725        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1726
1727        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
1728        fPrevAdvance = glyph.fAdvanceX;   // + fPaint.getTextTracking();
1729
1730        if (glyph.fWidth)
1731        {
1732            if (xpos)
1733                *xpos = fXPos;
1734            return fCache->findPath(glyph);
1735        }
1736    }
1737    return NULL;
1738}
1739