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