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