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