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