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