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