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