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