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