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