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