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