SkPaint.cpp revision 9b1cba8ccd7554cb30905711a426bd86ad8dd38c
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        maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
820        // this gets restored by restore
821        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
822    }
823
824    SkAutoGlyphCache    autoCache(*this, NULL);
825    SkGlyphCache*       cache = autoCache.getCache();
826
827    SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
828    const char*      stop;
829    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
830    SkFixed          max = SkScalarToFixed(maxWidth);
831    SkFixed          width = 0;
832
833    SkAutoKern  autokern;
834
835    if (this->isDevKernText())
836    {
837        int rsb = 0;
838        while (pred(text, stop))
839        {
840            const char* curr = text;
841            const SkGlyph& g = glyphCacheProc(cache, &text);
842            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
843            if ((width += x) > max)
844            {
845                width -= x;
846                text = curr;
847                break;
848            }
849            rsb = g.fRsbDelta;
850        }
851    }
852    else
853    {
854        while (pred(text, stop))
855        {
856            const char* curr = text;
857            SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
858            if ((width += x) > max)
859            {
860                width -= x;
861                text = curr;
862                break;
863            }
864        }
865    }
866
867    if (measuredWidth)
868    {
869
870        SkScalar scalarWidth = SkFixedToScalar(width);
871        if (scale)
872            scalarWidth = SkScalarMul(scalarWidth, scale);
873        *measuredWidth = scalarWidth;
874    }
875
876    // return the number of bytes measured
877    return (kForward_TextBufferDirection == tbd) ?
878                text - stop + length : stop - text + length;
879}
880
881///////////////////////////////////////////////////////////////////////////////
882
883static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context)
884{
885    *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
886    return false;   // don't detach the cache
887}
888
889static void FontMetricsDescProc(const SkDescriptor* desc, void* context)
890{
891    SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
892}
893
894SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const
895{
896    SkScalar                            scale = 0;
897    SkAutoRestorePaintTextSizeAndFrame  restore(this);
898
899    if (this->isLinearText())
900    {
901        scale = fTextSize / kCanonicalTextSizeForPaths;
902        // this gets restored by restore
903        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
904    }
905
906    SkMatrix    zoomMatrix, *zoomPtr = NULL;
907    if (zoom)
908    {
909        zoomMatrix.setScale(zoom, zoom);
910        zoomPtr = &zoomMatrix;
911    }
912
913#if 0
914    SkAutoGlyphCache    autoCache(*this, zoomPtr);
915    SkGlyphCache*       cache = autoCache.getCache();
916    const FontMetrics&  my = cache->getFontMetricsY();
917#endif
918    FontMetrics storage;
919    if (NULL == metrics)
920        metrics = &storage;
921
922    this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
923
924    if (scale)
925    {
926        metrics->fTop = SkScalarMul(metrics->fTop, scale);
927        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
928        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
929        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
930        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
931    }
932    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
933}
934
935////////////////////////////////////////////////////////////////////////////////////////////
936
937static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale)
938{
939    bounds->set(g.fLeft * scale,
940                g.fTop * scale,
941                (g.fLeft + g.fWidth) * scale,
942                (g.fTop + g.fHeight) * scale);
943}
944
945int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[],
946                           SkRect bounds[]) const
947{
948    if (0 == byteLength)
949        return 0;
950
951    SkASSERT(NULL != textData);
952
953    if (NULL == widths && NULL == bounds)
954        return this->countText(textData, byteLength);
955
956    SkAutoRestorePaintTextSizeAndFrame  restore(this);
957    SkScalar                            scale = 0;
958
959    if (this->isLinearText())
960    {
961        scale = fTextSize / kCanonicalTextSizeForPaths;
962        // this gets restored by restore
963        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
964    }
965
966    SkAutoGlyphCache    autoCache(*this, NULL);
967    SkGlyphCache*       cache = autoCache.getCache();
968    SkMeasureCacheProc  glyphCacheProc;
969    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
970                                               NULL != bounds);
971
972    const char* text = (const char*)textData;
973    const char* stop = text + byteLength;
974    int         count = 0;
975
976    if (this->isDevKernText())
977    {
978        // we adjust the widths returned here through auto-kerning
979        SkAutoKern  autokern;
980        SkFixed     prevWidth = 0;
981
982        if (scale) {
983            while (text < stop) {
984                const SkGlyph& g = glyphCacheProc(cache, &text);
985                if (widths) {
986                    SkFixed  adjust = autokern.adjust(g);
987
988                    if (count > 0) {
989                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
990                        *widths++ = SkScalarMul(w, scale);
991                    }
992                    prevWidth = g.fAdvanceX;
993                }
994                if (bounds) {
995                    set_bounds(g, bounds++, scale);
996                }
997                ++count;
998            }
999            if (count > 0 && widths) {
1000                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1001            }
1002        } else {
1003            while (text < stop) {
1004                const SkGlyph& g = glyphCacheProc(cache, &text);
1005                if (widths) {
1006                    SkFixed  adjust = autokern.adjust(g);
1007
1008                    if (count > 0) {
1009                        *widths++ = SkFixedToScalar(prevWidth + adjust);
1010                    }
1011                    prevWidth = g.fAdvanceX;
1012                }
1013                if (bounds) {
1014                    set_bounds(g, bounds++);
1015                }
1016                ++count;
1017            }
1018            if (count > 0 && widths) {
1019                *widths = SkFixedToScalar(prevWidth);
1020            }
1021        }
1022    } else {    // no devkern
1023        if (scale) {
1024            while (text < stop) {
1025                const SkGlyph& g = glyphCacheProc(cache, &text);
1026                if (widths) {
1027                    *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
1028                                            scale);
1029                }
1030                if (bounds) {
1031                    set_bounds(g, bounds++, scale);
1032                }
1033                ++count;
1034            }
1035        } else {
1036            while (text < stop) {
1037                const SkGlyph& g = glyphCacheProc(cache, &text);
1038                if (widths) {
1039                    *widths++ = SkFixedToScalar(g.fAdvanceX);
1040                }
1041                if (bounds) {
1042                    set_bounds(g, bounds++);
1043                }
1044                ++count;
1045            }
1046        }
1047    }
1048
1049    SkASSERT(text == stop);
1050    return count;
1051}
1052
1053////////////////////////////////////////////////////////////////////////////////////////////
1054
1055#include "SkDraw.h"
1056
1057void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const
1058{
1059    const char* text = (const char*)textData;
1060    SkASSERT(length == 0 || text != NULL);
1061    if (text == NULL || length == 0 || path == NULL)
1062        return;
1063
1064    SkTextToPathIter    iter(text, length, *this, false, true);
1065    SkMatrix            matrix;
1066    SkScalar            prevXPos = 0;
1067
1068    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1069    matrix.postTranslate(x, y);
1070    path->reset();
1071
1072    SkScalar        xpos;
1073    const SkPath*   iterPath;
1074    while ((iterPath = iter.next(&xpos)) != NULL)
1075    {
1076        matrix.postTranslate(xpos - prevXPos, 0);
1077        path->addPath(*iterPath, matrix);
1078        prevXPos = xpos;
1079    }
1080}
1081
1082static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1083                            SkFlattenableWriteBuffer* buffer) {
1084    buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
1085}
1086
1087/*
1088 *  interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i])
1089    inspired by a desire to change the multiplier for thickness in fakebold
1090    therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient
1091    repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if
1092        key is the value of a repeated scalar in keys, the first one will be used
1093    - this may change if a binary search is used
1094    - also, this ensures that there is no divide by zero (an assert also checks for that)
1095*/
1096static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length)
1097{
1098
1099    SkASSERT(length > 0);
1100    SkASSERT(keys != NULL);
1101    SkASSERT(values != NULL);
1102#ifdef SK_DEBUG
1103    for (int i = 1; i < length; i++)
1104        SkASSERT(keys[i] >= keys[i-1]);
1105#endif
1106    int right = 0;
1107    while (right < length && key > keys[right])
1108        right++;
1109    //could use sentinal values to eliminate conditionals
1110    //i assume i am not in control of input values, so i want to make it simple
1111    if (length == right)
1112        return values[length-1];
1113    if (0 == right)
1114        return values[0];
1115    //otherwise, we interpolate between right-1 and right
1116    SkScalar rVal = values[right];
1117    SkScalar lVal = values[right-1];
1118    SkScalar rightKey = keys[right];
1119    SkScalar leftKey = keys[right-1];
1120    SkASSERT(rightKey != leftKey);
1121    //fractional amount which we will multiply by the difference in the left value and right value
1122    SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey);
1123    return lVal + SkScalarMul(fract, rVal-lVal);
1124}
1125
1126//used for interpolating in fakeBold
1127static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) };
1128static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 };
1129
1130static SkMask::Format computeMaskFormat(const SkPaint& paint)
1131{
1132    uint32_t flags = paint.getFlags();
1133
1134    if (flags & SkPaint::kLCDRenderText_Flag)
1135#if defined(SK_SUPPORT_LCDTEXT)
1136        return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
1137                   SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
1138#else
1139        return SkMask::kA8_Format;
1140#endif
1141    if (flags & SkPaint::kAntiAlias_Flag)
1142        return SkMask::kA8_Format;
1143    return SkMask::kBW_Format;
1144}
1145
1146// if linear-text is on, then we force hinting to be off (since that's sort of
1147// the point of linear-text.
1148static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1149    SkPaint::Hinting h = paint.getHinting();
1150    if (paint.isLinearText()) {
1151        h = SkPaint::kNo_Hinting;
1152    }
1153    return h;
1154}
1155
1156void SkScalerContext::MakeRec(const SkPaint& paint,
1157                              const SkMatrix* deviceMatrix, Rec* rec)
1158{
1159    SkASSERT(deviceMatrix == NULL ||
1160             (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
1161
1162    rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
1163    rec->fTextSize = paint.getTextSize();
1164    rec->fPreScaleX = paint.getTextScaleX();
1165    rec->fPreSkewX  = paint.getTextSkewX();
1166
1167    if (deviceMatrix)
1168    {
1169        rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
1170        rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
1171        rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
1172        rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
1173    }
1174    else
1175    {
1176        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1177        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1178    }
1179
1180    SkPaint::Style  style = paint.getStyle();
1181    SkScalar        strokeWidth = paint.getStrokeWidth();
1182
1183    if (paint.isFakeBoldText())
1184    {
1185        SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2);
1186        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1187
1188        if (style == SkPaint::kFill_Style)
1189        {
1190            style = SkPaint::kStrokeAndFill_Style;
1191            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
1192        }
1193        else
1194            strokeWidth += extra;
1195    }
1196
1197    unsigned flags = SkFontHost::ComputeGammaFlag(paint);
1198
1199    if (paint.isDevKernText())
1200        flags |= SkScalerContext::kDevKernText_Flag;
1201
1202    if (style != SkPaint::kFill_Style && strokeWidth > 0)
1203    {
1204        rec->fFrameWidth = strokeWidth;
1205        rec->fMiterLimit = paint.getStrokeMiter();
1206        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1207
1208        if (style == SkPaint::kStrokeAndFill_Style)
1209            flags |= SkScalerContext::kFrameAndFill_Flag;
1210    }
1211    else
1212    {
1213        rec->fFrameWidth = 0;
1214        rec->fMiterLimit = 0;
1215        rec->fStrokeJoin = 0;
1216    }
1217
1218    rec->fSubpixelPositioning = paint.isSubpixelText();
1219    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1220    rec->fFlags = SkToU8(flags);
1221    rec->setHinting(computeHinting(paint));
1222
1223    /*  Allow the fonthost to modify our rec before we use it as a key into the
1224        cache. This way if we're asking for something that they will ignore,
1225        they can modify our rec up front, so we don't create duplicate cache
1226        entries.
1227     */
1228    SkFontHost::FilterRec(rec);
1229}
1230
1231#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
1232
1233void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
1234                             void (*proc)(const SkDescriptor*, void*),
1235                             void* context) const
1236{
1237    SkScalerContext::Rec    rec;
1238
1239    SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1240
1241    size_t          descSize = sizeof(rec);
1242    int             entryCount = 1;
1243    SkPathEffect*   pe = this->getPathEffect();
1244    SkMaskFilter*   mf = this->getMaskFilter();
1245    SkRasterizer*   ra = this->getRasterizer();
1246
1247    SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1248    SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1249    SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1250
1251    if (pe) {
1252        peBuffer.writeFlattenable(pe);
1253        descSize += peBuffer.size();
1254        entryCount += 1;
1255        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
1256        // seems like we could support kLCD as well at this point...
1257    }
1258    if (mf) {
1259        mfBuffer.writeFlattenable(mf);
1260        descSize += mfBuffer.size();
1261        entryCount += 1;
1262        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1263    }
1264    if (ra) {
1265        raBuffer.writeFlattenable(ra);
1266        descSize += raBuffer.size();
1267        entryCount += 1;
1268        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
1269    }
1270    descSize += SkDescriptor::ComputeOverhead(entryCount);
1271
1272    SkAutoDescriptor    ad(descSize);
1273    SkDescriptor*       desc = ad.getDesc();
1274
1275    desc->init();
1276    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1277
1278    if (pe) {
1279        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1280    }
1281    if (mf) {
1282        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1283    }
1284    if (ra) {
1285        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1286    }
1287
1288    SkASSERT(descSize == desc->getLength());
1289    desc->computeChecksum();
1290
1291    proc(desc, context);
1292}
1293
1294static void DetachDescProc(const SkDescriptor* desc, void* context)
1295{
1296    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
1297}
1298
1299SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
1300{
1301    SkGlyphCache* cache;
1302    this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
1303    return cache;
1304}
1305
1306///////////////////////////////////////////////////////////////////////////////
1307
1308#include "SkStream.h"
1309
1310static uintptr_t asint(const void* p) {
1311    return reinterpret_cast<uintptr_t>(p);
1312}
1313
1314union Scalar32 {
1315    SkScalar    fScalar;
1316    uint32_t    f32;
1317};
1318
1319static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1320    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1321    Scalar32 tmp;
1322    tmp.fScalar = value;
1323    *ptr = tmp.f32;
1324    return ptr + 1;
1325}
1326
1327static SkScalar read_scalar(const uint32_t*& ptr) {
1328    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1329    Scalar32 tmp;
1330    tmp.f32 = *ptr++;
1331    return tmp.fScalar;
1332}
1333
1334static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1335    SkASSERT(a == (uint8_t)a);
1336    SkASSERT(b == (uint8_t)b);
1337    SkASSERT(c == (uint8_t)c);
1338    SkASSERT(d == (uint8_t)d);
1339    return (a << 24) | (b << 16) | (c << 8) | d;
1340}
1341
1342enum FlatFlags {
1343    kHasTypeface_FlatFlag   = 0x01,
1344    kHasEffects_FlatFlag    = 0x02
1345};
1346
1347// The size of a flat paint's POD fields
1348static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
1349                                        1 * sizeof(SkColor) +
1350                                        1 * sizeof(uint16_t) +
1351                                        6 * sizeof(uint8_t);
1352
1353/*  To save space/time, we analyze the paint, and write a truncated version of
1354    it if there are not tricky elements like shaders, etc.
1355 */
1356void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
1357    uint8_t flatFlags = 0;
1358    if (this->getTypeface()) {
1359        flatFlags |= kHasTypeface_FlatFlag;
1360    }
1361    if (asint(this->getPathEffect()) |
1362        asint(this->getShader()) |
1363        asint(this->getXfermode()) |
1364        asint(this->getMaskFilter()) |
1365        asint(this->getColorFilter()) |
1366        asint(this->getRasterizer()) |
1367        asint(this->getLooper())) {
1368        flatFlags |= kHasEffects_FlatFlag;
1369    }
1370
1371    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1372    uint32_t* ptr = buffer.reserve(kPODPaintSize);
1373
1374    ptr = write_scalar(ptr, this->getTextSize());
1375    ptr = write_scalar(ptr, this->getTextScaleX());
1376    ptr = write_scalar(ptr, this->getTextSkewX());
1377    ptr = write_scalar(ptr, this->getStrokeWidth());
1378    ptr = write_scalar(ptr, this->getStrokeMiter());
1379    *ptr++ = this->getColor();
1380    *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
1381    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1382                    this->getStyle(), this->getTextEncoding());
1383
1384    // now we're done with ptr and the (pre)reserved space. If we need to write
1385    // additional fields, use the buffer directly
1386    if (flatFlags & kHasTypeface_FlatFlag) {
1387        buffer.writeTypeface(this->getTypeface());
1388    }
1389    if (flatFlags & kHasEffects_FlatFlag) {
1390        buffer.writeFlattenable(this->getPathEffect());
1391        buffer.writeFlattenable(this->getShader());
1392        buffer.writeFlattenable(this->getXfermode());
1393        buffer.writeFlattenable(this->getMaskFilter());
1394        buffer.writeFlattenable(this->getColorFilter());
1395        buffer.writeFlattenable(this->getRasterizer());
1396        buffer.writeFlattenable(this->getLooper());
1397    }
1398}
1399
1400void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
1401    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1402    const void* podData = buffer.skip(kPODPaintSize);
1403    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1404
1405    // the order we read must match the order we wrote in flatten()
1406    this->setTextSize(read_scalar(pod));
1407    this->setTextScaleX(read_scalar(pod));
1408    this->setTextSkewX(read_scalar(pod));
1409    this->setStrokeWidth(read_scalar(pod));
1410    this->setStrokeMiter(read_scalar(pod));
1411    this->setColor(*pod++);
1412
1413    uint32_t tmp = *pod++;
1414    this->setFlags(tmp >> 16);
1415    this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
1416    uint8_t flatFlags = tmp & 0xFF;
1417
1418    tmp = *pod++;
1419    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1420    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1421    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1422    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1423
1424    if (flatFlags & kHasTypeface_FlatFlag) {
1425        this->setTypeface(buffer.readTypeface());
1426    } else {
1427        this->setTypeface(NULL);
1428    }
1429
1430    if (flatFlags & kHasEffects_FlatFlag) {
1431        this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
1432        this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
1433        this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
1434        this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
1435        this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
1436        this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
1437        this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
1438    } else {
1439        this->setPathEffect(NULL);
1440        this->setShader(NULL);
1441        this->setXfermode(NULL);
1442        this->setMaskFilter(NULL);
1443        this->setColorFilter(NULL);
1444        this->setRasterizer(NULL);
1445        this->setLooper(NULL);
1446    }
1447}
1448
1449///////////////////////////////////////////////////////////////////////////////
1450
1451SkShader* SkPaint::setShader(SkShader* shader)
1452{
1453    SkRefCnt_SafeAssign(fShader, shader);
1454    return shader;
1455}
1456
1457SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
1458{
1459    SkRefCnt_SafeAssign(fColorFilter, filter);
1460    return filter;
1461}
1462
1463SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
1464{
1465    SkRefCnt_SafeAssign(fXfermode, mode);
1466    return mode;
1467}
1468
1469SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
1470    SkSafeUnref(fXfermode);
1471    fXfermode = SkXfermode::Create(mode);
1472    return fXfermode;
1473}
1474
1475SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
1476{
1477    SkRefCnt_SafeAssign(fPathEffect, effect);
1478    return effect;
1479}
1480
1481SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
1482{
1483    SkRefCnt_SafeAssign(fMaskFilter, filter);
1484    return filter;
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////////////
1488
1489bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
1490{
1491    SkPath          effectPath, strokePath;
1492    const SkPath*   path = &src;
1493
1494    SkScalar width = this->getStrokeWidth();
1495
1496    switch (this->getStyle()) {
1497    case SkPaint::kFill_Style:
1498        width = -1; // mark it as no-stroke
1499        break;
1500    case SkPaint::kStrokeAndFill_Style:
1501        if (width == 0)
1502            width = -1; // mark it as no-stroke
1503        break;
1504    case SkPaint::kStroke_Style:
1505        break;
1506    default:
1507        SkASSERT(!"unknown paint style");
1508    }
1509
1510    if (this->getPathEffect())
1511    {
1512        // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
1513        if (this->getStyle() == SkPaint::kStrokeAndFill_Style)
1514            width = -1; // mark it as no-stroke
1515
1516        if (this->getPathEffect()->filterPath(&effectPath, src, &width))
1517            path = &effectPath;
1518
1519        // restore the width if we earlier had to lie, and if we're still set to no-stroke
1520        // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
1521        // and we want to respect that (i.e. don't overwrite their setting for width)
1522        if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0)
1523        {
1524            width = this->getStrokeWidth();
1525            if (width == 0)
1526                width = -1;
1527        }
1528    }
1529
1530    if (width > 0 && !path->isEmpty())
1531    {
1532        SkStroke stroker(*this, width);
1533        stroker.strokePath(*path, &strokePath);
1534        path = &strokePath;
1535    }
1536
1537    if (path == &src)
1538        *dst = src;
1539    else
1540    {
1541        SkASSERT(path == &effectPath || path == &strokePath);
1542        dst->swap(*(SkPath*)path);
1543    }
1544
1545    return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
1546}
1547
1548const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
1549                                               SkRect* storage) const {
1550    SkASSERT(storage);
1551    SkASSERT(this->getStyle() != SkPaint::kFill_Style);
1552
1553    // since we're stroked, outset the rect by the radius (and join type)
1554    SkScalar radius = SkScalarHalf(this->getStrokeWidth());
1555    if (0 == radius) {  // hairline
1556        radius = SK_Scalar1;
1557    } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
1558        SkScalar scale = this->getStrokeMiter();
1559        if (scale > SK_Scalar1) {
1560            radius = SkScalarMul(radius, scale);
1561        }
1562    }
1563    storage->set(src.fLeft - radius, src.fTop - radius,
1564                 src.fRight + radius, src.fBottom + radius);
1565    return *storage;
1566}
1567
1568////////////////////////////////////////////////////////////////////////////////////////
1569
1570static bool has_thick_frame(const SkPaint& paint)
1571{
1572    return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style;
1573}
1574
1575SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
1576                                    const SkPaint& paint,
1577                                    bool applyStrokeAndPathEffects,
1578                                    bool forceLinearTextOn)
1579                                    : fPaint(paint) /* make a copy of the paint */
1580{
1581    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
1582                                                true);
1583
1584    if (forceLinearTextOn)
1585        fPaint.setLinearText(true);
1586    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
1587
1588    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint))
1589        applyStrokeAndPathEffects = false;
1590
1591    // can't use our canonical size if we need to apply patheffects/strokes
1592    if (fPaint.isLinearText() && !applyStrokeAndPathEffects)
1593    {
1594        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
1595        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
1596    }
1597    else
1598        fScale = SK_Scalar1;
1599
1600    if (!applyStrokeAndPathEffects)
1601    {
1602        fPaint.setStyle(SkPaint::kFill_Style);
1603        fPaint.setPathEffect(NULL);
1604    }
1605
1606    fCache = fPaint.detachCache(NULL);
1607
1608    SkPaint::Style  style = SkPaint::kFill_Style;
1609    SkPathEffect*   pe = NULL;
1610
1611    if (!applyStrokeAndPathEffects)
1612    {
1613        style = paint.getStyle();   // restore
1614        pe = paint.getPathEffect();     // restore
1615    }
1616    fPaint.setStyle(style);
1617    fPaint.setPathEffect(pe);
1618    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
1619
1620    // now compute fXOffset if needed
1621
1622    SkScalar xOffset = 0;
1623    if (paint.getTextAlign() != SkPaint::kLeft_Align)   // need to measure first
1624    {
1625        int      count;
1626        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale);
1627        if (paint.getTextAlign() == SkPaint::kCenter_Align)
1628            width = SkScalarHalf(width);
1629        xOffset = -width;
1630    }
1631    fXPos = xOffset;
1632    fPrevAdvance = 0;
1633
1634    fText = text;
1635    fStop = text + length;
1636}
1637
1638SkTextToPathIter::~SkTextToPathIter()
1639{
1640    SkGlyphCache::AttachCache(fCache);
1641}
1642
1643const SkPath* SkTextToPathIter::next(SkScalar* xpos)
1644{
1645    while (fText < fStop)
1646    {
1647        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1648
1649        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
1650        fPrevAdvance = glyph.fAdvanceX;   // + fPaint.getTextTracking();
1651
1652        if (glyph.fWidth)
1653        {
1654            if (xpos)
1655                *xpos = fXPos;
1656            return fCache->findPath(glyph);
1657        }
1658    }
1659    return NULL;
1660}
1661