1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkPaint.h"
9 #include "SkAnnotation.h"
10 #include "SkAutoKern.h"
11 #include "SkChecksum.h"
12 #include "SkColorFilter.h"
13 #include "SkData.h"
14 #include "SkDeviceProperties.h"
15 #include "SkDraw.h"
16 #include "SkFontDescriptor.h"
17 #include "SkGlyphCache.h"
18 #include "SkImageFilter.h"
19 #include "SkMaskFilter.h"
20 #include "SkMaskGamma.h"
21 #include "SkReadBuffer.h"
22 #include "SkWriteBuffer.h"
23 #include "SkPaintDefaults.h"
24 #include "SkPathEffect.h"
25 #include "SkRasterizer.h"
26 #include "SkScalar.h"
27 #include "SkScalerContext.h"
28 #include "SkShader.h"
29 #include "SkStringUtils.h"
30 #include "SkStroke.h"
31 #include "SkTextFormatParams.h"
32 #include "SkTextToPathIter.h"
33 #include "SkTLazy.h"
34 #include "SkTypeface.h"
35 #include "SkXfermode.h"
36
37 // define this to get a printf for out-of-range parameter in setters
38 // e.g. setTextSize(-1)
39 //#define SK_REPORT_API_RANGE_CHECK
40
SkPaint()41 SkPaint::SkPaint() {
42 fTypeface = NULL;
43 fPathEffect = NULL;
44 fShader = NULL;
45 fXfermode = NULL;
46 fMaskFilter = NULL;
47 fColorFilter = NULL;
48 fRasterizer = NULL;
49 fLooper = NULL;
50 fImageFilter = NULL;
51 fAnnotation = NULL;
52
53 fTextSize = SkPaintDefaults_TextSize;
54 fTextScaleX = SK_Scalar1;
55 fTextSkewX = 0;
56 fColor = SK_ColorBLACK;
57 fWidth = 0;
58 fMiterLimit = SkPaintDefaults_MiterLimit;
59
60 // Zero all bitfields, then set some non-zero defaults.
61 fBitfieldsUInt = 0;
62 fBitfields.fFlags = SkPaintDefaults_Flags;
63 fBitfields.fCapType = kDefault_Cap;
64 fBitfields.fJoinType = kDefault_Join;
65 fBitfields.fTextAlign = kLeft_Align;
66 fBitfields.fStyle = kFill_Style;
67 fBitfields.fTextEncoding = kUTF8_TextEncoding;
68 fBitfields.fHinting = SkPaintDefaults_Hinting;
69 }
70
SkPaint(const SkPaint & src)71 SkPaint::SkPaint(const SkPaint& src) {
72 #define COPY(field) field = src.field
73 #define REF_COPY(field) field = SkSafeRef(src.field)
74
75 REF_COPY(fTypeface);
76 REF_COPY(fPathEffect);
77 REF_COPY(fShader);
78 REF_COPY(fXfermode);
79 REF_COPY(fMaskFilter);
80 REF_COPY(fColorFilter);
81 REF_COPY(fRasterizer);
82 REF_COPY(fLooper);
83 REF_COPY(fImageFilter);
84 REF_COPY(fAnnotation);
85
86 COPY(fTextSize);
87 COPY(fTextScaleX);
88 COPY(fTextSkewX);
89 COPY(fColor);
90 COPY(fWidth);
91 COPY(fMiterLimit);
92 COPY(fBitfields);
93
94 #undef COPY
95 #undef REF_COPY
96 }
97
~SkPaint()98 SkPaint::~SkPaint() {
99 SkSafeUnref(fTypeface);
100 SkSafeUnref(fPathEffect);
101 SkSafeUnref(fShader);
102 SkSafeUnref(fXfermode);
103 SkSafeUnref(fMaskFilter);
104 SkSafeUnref(fColorFilter);
105 SkSafeUnref(fRasterizer);
106 SkSafeUnref(fLooper);
107 SkSafeUnref(fImageFilter);
108 SkSafeUnref(fAnnotation);
109 }
110
operator =(const SkPaint & src)111 SkPaint& SkPaint::operator=(const SkPaint& src) {
112 if (this == &src) {
113 return *this;
114 }
115
116 #define COPY(field) field = src.field
117 #define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
118
119 REF_COPY(fTypeface);
120 REF_COPY(fPathEffect);
121 REF_COPY(fShader);
122 REF_COPY(fXfermode);
123 REF_COPY(fMaskFilter);
124 REF_COPY(fColorFilter);
125 REF_COPY(fRasterizer);
126 REF_COPY(fLooper);
127 REF_COPY(fImageFilter);
128 REF_COPY(fAnnotation);
129
130 COPY(fTextSize);
131 COPY(fTextScaleX);
132 COPY(fTextSkewX);
133 COPY(fColor);
134 COPY(fWidth);
135 COPY(fMiterLimit);
136 COPY(fBitfields);
137
138 return *this;
139
140 #undef COPY
141 #undef REF_COPY
142 }
143
operator ==(const SkPaint & a,const SkPaint & b)144 bool operator==(const SkPaint& a, const SkPaint& b) {
145 #define EQUAL(field) (a.field == b.field)
146 return EQUAL(fTypeface)
147 && EQUAL(fPathEffect)
148 && EQUAL(fShader)
149 && EQUAL(fXfermode)
150 && EQUAL(fMaskFilter)
151 && EQUAL(fColorFilter)
152 && EQUAL(fRasterizer)
153 && EQUAL(fLooper)
154 && EQUAL(fImageFilter)
155 && EQUAL(fAnnotation)
156 && EQUAL(fTextSize)
157 && EQUAL(fTextScaleX)
158 && EQUAL(fTextSkewX)
159 && EQUAL(fColor)
160 && EQUAL(fWidth)
161 && EQUAL(fMiterLimit)
162 && EQUAL(fBitfieldsUInt)
163 ;
164 #undef EQUAL
165 }
166
reset()167 void SkPaint::reset() {
168 SkPaint init;
169 *this = init;
170 }
171
setFilterQuality(SkFilterQuality quality)172 void SkPaint::setFilterQuality(SkFilterQuality quality) {
173 fBitfields.fFilterQuality = quality;
174 }
175
setHinting(Hinting hintingLevel)176 void SkPaint::setHinting(Hinting hintingLevel) {
177 fBitfields.fHinting = hintingLevel;
178 }
179
setFlags(uint32_t flags)180 void SkPaint::setFlags(uint32_t flags) {
181 fBitfields.fFlags = flags;
182 }
183
setAntiAlias(bool doAA)184 void SkPaint::setAntiAlias(bool doAA) {
185 this->setFlags(SkSetClearMask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
186 }
187
setDither(bool doDither)188 void SkPaint::setDither(bool doDither) {
189 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDither, kDither_Flag));
190 }
191
setSubpixelText(bool doSubpixel)192 void SkPaint::setSubpixelText(bool doSubpixel) {
193 this->setFlags(SkSetClearMask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
194 }
195
setLCDRenderText(bool doLCDRender)196 void SkPaint::setLCDRenderText(bool doLCDRender) {
197 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
198 }
199
setEmbeddedBitmapText(bool doEmbeddedBitmapText)200 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
201 this->setFlags(SkSetClearMask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
202 }
203
setAutohinted(bool useAutohinter)204 void SkPaint::setAutohinted(bool useAutohinter) {
205 this->setFlags(SkSetClearMask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
206 }
207
setLinearText(bool doLinearText)208 void SkPaint::setLinearText(bool doLinearText) {
209 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
210 }
211
setVerticalText(bool doVertical)212 void SkPaint::setVerticalText(bool doVertical) {
213 this->setFlags(SkSetClearMask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
214 }
215
setUnderlineText(bool doUnderline)216 void SkPaint::setUnderlineText(bool doUnderline) {
217 this->setFlags(SkSetClearMask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag));
218 }
219
setStrikeThruText(bool doStrikeThru)220 void SkPaint::setStrikeThruText(bool doStrikeThru) {
221 this->setFlags(SkSetClearMask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag));
222 }
223
setFakeBoldText(bool doFakeBold)224 void SkPaint::setFakeBoldText(bool doFakeBold) {
225 this->setFlags(SkSetClearMask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
226 }
227
setDevKernText(bool doDevKern)228 void SkPaint::setDevKernText(bool doDevKern) {
229 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
230 }
231
setDistanceFieldTextTEMP(bool doDistanceFieldText)232 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
233 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
234 }
235
setStyle(Style style)236 void SkPaint::setStyle(Style style) {
237 if ((unsigned)style < kStyleCount) {
238 fBitfields.fStyle = style;
239 } else {
240 #ifdef SK_REPORT_API_RANGE_CHECK
241 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
242 #endif
243 }
244 }
245
setColor(SkColor color)246 void SkPaint::setColor(SkColor color) {
247 fColor = color;
248 }
249
setAlpha(U8CPU a)250 void SkPaint::setAlpha(U8CPU a) {
251 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
252 SkColorGetG(fColor), SkColorGetB(fColor)));
253 }
254
setARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)255 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
256 this->setColor(SkColorSetARGB(a, r, g, b));
257 }
258
setStrokeWidth(SkScalar width)259 void SkPaint::setStrokeWidth(SkScalar width) {
260 if (width >= 0) {
261 fWidth = width;
262 } else {
263 #ifdef SK_REPORT_API_RANGE_CHECK
264 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
265 #endif
266 }
267 }
268
setStrokeMiter(SkScalar limit)269 void SkPaint::setStrokeMiter(SkScalar limit) {
270 if (limit >= 0) {
271 fMiterLimit = limit;
272 } else {
273 #ifdef SK_REPORT_API_RANGE_CHECK
274 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
275 #endif
276 }
277 }
278
setStrokeCap(Cap ct)279 void SkPaint::setStrokeCap(Cap ct) {
280 if ((unsigned)ct < kCapCount) {
281 fBitfields.fCapType = SkToU8(ct);
282 } else {
283 #ifdef SK_REPORT_API_RANGE_CHECK
284 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
285 #endif
286 }
287 }
288
setStrokeJoin(Join jt)289 void SkPaint::setStrokeJoin(Join jt) {
290 if ((unsigned)jt < kJoinCount) {
291 fBitfields.fJoinType = SkToU8(jt);
292 } else {
293 #ifdef SK_REPORT_API_RANGE_CHECK
294 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
295 #endif
296 }
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300
setTextAlign(Align align)301 void SkPaint::setTextAlign(Align align) {
302 if ((unsigned)align < kAlignCount) {
303 fBitfields.fTextAlign = SkToU8(align);
304 } else {
305 #ifdef SK_REPORT_API_RANGE_CHECK
306 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
307 #endif
308 }
309 }
310
setTextSize(SkScalar ts)311 void SkPaint::setTextSize(SkScalar ts) {
312 if (ts >= 0) {
313 fTextSize = ts;
314 } else {
315 #ifdef SK_REPORT_API_RANGE_CHECK
316 SkDebugf("SkPaint::setTextSize() called with negative value\n");
317 #endif
318 }
319 }
320
setTextScaleX(SkScalar scaleX)321 void SkPaint::setTextScaleX(SkScalar scaleX) {
322 fTextScaleX = scaleX;
323 }
324
setTextSkewX(SkScalar skewX)325 void SkPaint::setTextSkewX(SkScalar skewX) {
326 fTextSkewX = skewX;
327 }
328
setTextEncoding(TextEncoding encoding)329 void SkPaint::setTextEncoding(TextEncoding encoding) {
330 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
331 fBitfields.fTextEncoding = encoding;
332 } else {
333 #ifdef SK_REPORT_API_RANGE_CHECK
334 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
335 #endif
336 }
337 }
338
339 ///////////////////////////////////////////////////////////////////////////////
340
setTypeface(SkTypeface * font)341 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
342 SkRefCnt_SafeAssign(fTypeface, font);
343 return font;
344 }
345
setRasterizer(SkRasterizer * r)346 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
347 SkRefCnt_SafeAssign(fRasterizer, r);
348 return r;
349 }
350
setLooper(SkDrawLooper * looper)351 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
352 SkRefCnt_SafeAssign(fLooper, looper);
353 return looper;
354 }
355
setImageFilter(SkImageFilter * imageFilter)356 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
357 SkRefCnt_SafeAssign(fImageFilter, imageFilter);
358 return imageFilter;
359 }
360
setAnnotation(SkAnnotation * annotation)361 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
362 SkRefCnt_SafeAssign(fAnnotation, annotation);
363 return annotation;
364 }
365
366 ///////////////////////////////////////////////////////////////////////////////
367
mag2(SkScalar x,SkScalar y)368 static SkScalar mag2(SkScalar x, SkScalar y) {
369 return x * x + y * y;
370 }
371
tooBig(const SkMatrix & m,SkScalar ma2max)372 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
373 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
374 ||
375 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
376 }
377
TooBigToUseCache(const SkMatrix & ctm,const SkMatrix & textM)378 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
379 SkASSERT(!ctm.hasPerspective());
380 SkASSERT(!textM.hasPerspective());
381
382 SkMatrix matrix;
383 matrix.setConcat(ctm, textM);
384 return tooBig(matrix, MaxCacheSize2());
385 }
386
387
388 ///////////////////////////////////////////////////////////////////////////////
389
390 #include "SkGlyphCache.h"
391 #include "SkUtils.h"
392
DetachDescProc(SkTypeface * typeface,const SkDescriptor * desc,void * context)393 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
394 void* context) {
395 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
396 }
397
textToGlyphs(const void * textData,size_t byteLength,uint16_t glyphs[]) const398 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
399 uint16_t glyphs[]) const {
400 if (byteLength == 0) {
401 return 0;
402 }
403
404 SkASSERT(textData != NULL);
405
406 if (NULL == glyphs) {
407 switch (this->getTextEncoding()) {
408 case kUTF8_TextEncoding:
409 return SkUTF8_CountUnichars((const char*)textData, byteLength);
410 case kUTF16_TextEncoding:
411 return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
412 case kUTF32_TextEncoding:
413 return SkToInt(byteLength >> 2);
414 case kGlyphID_TextEncoding:
415 return SkToInt(byteLength >> 1);
416 default:
417 SkDEBUGFAIL("unknown text encoding");
418 }
419 return 0;
420 }
421
422 // if we get here, we have a valid glyphs[] array, so time to fill it in
423
424 // handle this encoding before the setup for the glyphcache
425 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
426 // we want to ignore the low bit of byteLength
427 memcpy(glyphs, textData, byteLength >> 1 << 1);
428 return SkToInt(byteLength >> 1);
429 }
430
431 SkAutoGlyphCache autoCache(*this, NULL, NULL);
432 SkGlyphCache* cache = autoCache.getCache();
433
434 const char* text = (const char*)textData;
435 const char* stop = text + byteLength;
436 uint16_t* gptr = glyphs;
437
438 switch (this->getTextEncoding()) {
439 case SkPaint::kUTF8_TextEncoding:
440 while (text < stop) {
441 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
442 }
443 break;
444 case SkPaint::kUTF16_TextEncoding: {
445 const uint16_t* text16 = (const uint16_t*)text;
446 const uint16_t* stop16 = (const uint16_t*)stop;
447 while (text16 < stop16) {
448 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
449 }
450 break;
451 }
452 case kUTF32_TextEncoding: {
453 const int32_t* text32 = (const int32_t*)text;
454 const int32_t* stop32 = (const int32_t*)stop;
455 while (text32 < stop32) {
456 *gptr++ = cache->unicharToGlyph(*text32++);
457 }
458 break;
459 }
460 default:
461 SkDEBUGFAIL("unknown text encoding");
462 }
463 return SkToInt(gptr - glyphs);
464 }
465
containsText(const void * textData,size_t byteLength) const466 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
467 if (0 == byteLength) {
468 return true;
469 }
470
471 SkASSERT(textData != NULL);
472
473 // handle this encoding before the setup for the glyphcache
474 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
475 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
476 size_t count = byteLength >> 1;
477 for (size_t i = 0; i < count; i++) {
478 if (0 == glyphID[i]) {
479 return false;
480 }
481 }
482 return true;
483 }
484
485 SkAutoGlyphCache autoCache(*this, NULL, NULL);
486 SkGlyphCache* cache = autoCache.getCache();
487
488 switch (this->getTextEncoding()) {
489 case SkPaint::kUTF8_TextEncoding: {
490 const char* text = static_cast<const char*>(textData);
491 const char* stop = text + byteLength;
492 while (text < stop) {
493 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
494 return false;
495 }
496 }
497 break;
498 }
499 case SkPaint::kUTF16_TextEncoding: {
500 const uint16_t* text = static_cast<const uint16_t*>(textData);
501 const uint16_t* stop = text + (byteLength >> 1);
502 while (text < stop) {
503 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
504 return false;
505 }
506 }
507 break;
508 }
509 case SkPaint::kUTF32_TextEncoding: {
510 const int32_t* text = static_cast<const int32_t*>(textData);
511 const int32_t* stop = text + (byteLength >> 2);
512 while (text < stop) {
513 if (0 == cache->unicharToGlyph(*text++)) {
514 return false;
515 }
516 }
517 break;
518 }
519 default:
520 SkDEBUGFAIL("unknown text encoding");
521 return false;
522 }
523 return true;
524 }
525
glyphsToUnichars(const uint16_t glyphs[],int count,SkUnichar textData[]) const526 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
527 SkUnichar textData[]) const {
528 if (count <= 0) {
529 return;
530 }
531
532 SkASSERT(glyphs != NULL);
533 SkASSERT(textData != NULL);
534
535 SkAutoGlyphCache autoCache(*this, NULL, NULL);
536 SkGlyphCache* cache = autoCache.getCache();
537
538 for (int index = 0; index < count; index++) {
539 textData[index] = cache->glyphToUnichar(glyphs[index]);
540 }
541 }
542
543 ///////////////////////////////////////////////////////////////////////////////
544
sk_getMetrics_utf8_next(SkGlyphCache * cache,const char ** text)545 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
546 const char** text) {
547 SkASSERT(cache != NULL);
548 SkASSERT(text != NULL);
549
550 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
551 }
552
sk_getMetrics_utf16_next(SkGlyphCache * cache,const char ** text)553 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
554 const char** text) {
555 SkASSERT(cache != NULL);
556 SkASSERT(text != NULL);
557
558 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
559 }
560
sk_getMetrics_utf32_next(SkGlyphCache * cache,const char ** text)561 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
562 const char** text) {
563 SkASSERT(cache != NULL);
564 SkASSERT(text != NULL);
565
566 const int32_t* ptr = *(const int32_t**)text;
567 SkUnichar uni = *ptr++;
568 *text = (const char*)ptr;
569 return cache->getUnicharMetrics(uni);
570 }
571
sk_getMetrics_glyph_next(SkGlyphCache * cache,const char ** text)572 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
573 const char** text) {
574 SkASSERT(cache != NULL);
575 SkASSERT(text != NULL);
576
577 const uint16_t* ptr = *(const uint16_t**)text;
578 unsigned glyphID = *ptr;
579 ptr += 1;
580 *text = (const char*)ptr;
581 return cache->getGlyphIDMetrics(glyphID);
582 }
583
sk_getAdvance_utf8_next(SkGlyphCache * cache,const char ** text)584 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
585 const char** text) {
586 SkASSERT(cache != NULL);
587 SkASSERT(text != NULL);
588
589 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
590 }
591
sk_getAdvance_utf16_next(SkGlyphCache * cache,const char ** text)592 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
593 const char** text) {
594 SkASSERT(cache != NULL);
595 SkASSERT(text != NULL);
596
597 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
598 }
599
sk_getAdvance_utf32_next(SkGlyphCache * cache,const char ** text)600 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
601 const char** text) {
602 SkASSERT(cache != NULL);
603 SkASSERT(text != NULL);
604
605 const int32_t* ptr = *(const int32_t**)text;
606 SkUnichar uni = *ptr++;
607 *text = (const char*)ptr;
608 return cache->getUnicharAdvance(uni);
609 }
610
sk_getAdvance_glyph_next(SkGlyphCache * cache,const char ** text)611 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
612 const char** text) {
613 SkASSERT(cache != NULL);
614 SkASSERT(text != NULL);
615
616 const uint16_t* ptr = *(const uint16_t**)text;
617 unsigned glyphID = *ptr;
618 ptr += 1;
619 *text = (const char*)ptr;
620 return cache->getGlyphIDAdvance(glyphID);
621 }
622
getMeasureCacheProc(bool needFullMetrics) const623 SkMeasureCacheProc SkPaint::getMeasureCacheProc(bool needFullMetrics) const {
624 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
625 sk_getMetrics_utf8_next,
626 sk_getMetrics_utf16_next,
627 sk_getMetrics_utf32_next,
628 sk_getMetrics_glyph_next,
629
630 sk_getAdvance_utf8_next,
631 sk_getAdvance_utf16_next,
632 sk_getAdvance_utf32_next,
633 sk_getAdvance_glyph_next,
634 };
635
636 unsigned index = this->getTextEncoding();
637
638 if (!needFullMetrics && !this->isDevKernText()) {
639 index += 4;
640 }
641
642 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
643 return gMeasureCacheProcs[index];
644 }
645
646 ///////////////////////////////////////////////////////////////////////////////
647
sk_getMetrics_utf8_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)648 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
649 const char** text, SkFixed, SkFixed) {
650 SkASSERT(cache != NULL);
651 SkASSERT(text != NULL);
652
653 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
654 }
655
sk_getMetrics_utf8_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)656 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
657 const char** text, SkFixed x, SkFixed y) {
658 SkASSERT(cache != NULL);
659 SkASSERT(text != NULL);
660
661 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
662 }
663
sk_getMetrics_utf16_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)664 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
665 const char** text, SkFixed, SkFixed) {
666 SkASSERT(cache != NULL);
667 SkASSERT(text != NULL);
668
669 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
670 }
671
sk_getMetrics_utf16_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)672 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
673 const char** text, SkFixed x, SkFixed y) {
674 SkASSERT(cache != NULL);
675 SkASSERT(text != NULL);
676
677 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
678 x, y);
679 }
680
sk_getMetrics_utf32_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)681 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
682 const char** text, SkFixed, SkFixed) {
683 SkASSERT(cache != NULL);
684 SkASSERT(text != NULL);
685
686 const int32_t* ptr = *(const int32_t**)text;
687 SkUnichar uni = *ptr++;
688 *text = (const char*)ptr;
689 return cache->getUnicharMetrics(uni);
690 }
691
sk_getMetrics_utf32_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)692 static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
693 const char** text, SkFixed x, SkFixed y) {
694 SkASSERT(cache != NULL);
695 SkASSERT(text != NULL);
696
697 const int32_t* ptr = *(const int32_t**)text;
698 SkUnichar uni = *ptr++;
699 *text = (const char*)ptr;
700 return cache->getUnicharMetrics(uni, x, y);
701 }
702
sk_getMetrics_glyph_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)703 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
704 const char** text, SkFixed, SkFixed) {
705 SkASSERT(cache != NULL);
706 SkASSERT(text != NULL);
707
708 const uint16_t* ptr = *(const uint16_t**)text;
709 unsigned glyphID = *ptr;
710 ptr += 1;
711 *text = (const char*)ptr;
712 return cache->getGlyphIDMetrics(glyphID);
713 }
714
sk_getMetrics_glyph_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)715 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
716 const char** text, SkFixed x, SkFixed y) {
717 SkASSERT(cache != NULL);
718 SkASSERT(text != NULL);
719
720 const uint16_t* ptr = *(const uint16_t**)text;
721 unsigned glyphID = *ptr;
722 ptr += 1;
723 *text = (const char*)ptr;
724 return cache->getGlyphIDMetrics(glyphID, x, y);
725 }
726
getDrawCacheProc() const727 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
728 static const SkDrawCacheProc gDrawCacheProcs[] = {
729 sk_getMetrics_utf8_00,
730 sk_getMetrics_utf16_00,
731 sk_getMetrics_utf32_00,
732 sk_getMetrics_glyph_00,
733
734 sk_getMetrics_utf8_xy,
735 sk_getMetrics_utf16_xy,
736 sk_getMetrics_utf32_xy,
737 sk_getMetrics_glyph_xy
738 };
739
740 unsigned index = this->getTextEncoding();
741 if (fBitfields.fFlags & kSubpixelText_Flag) {
742 index += 4;
743 }
744
745 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
746 return gDrawCacheProcs[index];
747 }
748
749 ///////////////////////////////////////////////////////////////////////////////
750
751 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
752 SkPaint::kDevKernText_Flag | \
753 SkPaint::kLinearText_Flag | \
754 SkPaint::kLCDRenderText_Flag | \
755 SkPaint::kEmbeddedBitmapText_Flag | \
756 SkPaint::kAutoHinting_Flag | \
757 SkPaint::kGenA8FromLCD_Flag )
758
setupForAsPaths()759 SkScalar SkPaint::setupForAsPaths() {
760 uint32_t flags = this->getFlags();
761 // clear the flags we don't care about
762 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
763 // set the flags we do care about
764 flags |= SkPaint::kSubpixelText_Flag;
765
766 this->setFlags(flags);
767 this->setHinting(SkPaint::kNo_Hinting);
768
769 SkScalar textSize = fTextSize;
770 this->setTextSize(kCanonicalTextSizeForPaths);
771 return textSize / kCanonicalTextSizeForPaths;
772 }
773
774 class SkCanonicalizePaint {
775 public:
SkCanonicalizePaint(const SkPaint & paint)776 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
777 if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
778 SkPaint* p = fLazy.set(paint);
779 fScale = p->setupForAsPaths();
780 fPaint = p;
781 }
782 }
783
getPaint() const784 const SkPaint& getPaint() const { return *fPaint; }
785
786 /**
787 * Returns 0 if the paint was unmodified, or the scale factor need to
788 * the original textSize
789 */
getScale() const790 SkScalar getScale() const { return fScale; }
791
792 private:
793 const SkPaint* fPaint;
794 SkScalar fScale;
795 SkTLazy<SkPaint> fLazy;
796 };
797
set_bounds(const SkGlyph & g,SkRect * bounds)798 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
799 bounds->set(SkIntToScalar(g.fLeft),
800 SkIntToScalar(g.fTop),
801 SkIntToScalar(g.fLeft + g.fWidth),
802 SkIntToScalar(g.fTop + g.fHeight));
803 }
804
join_bounds_x(const SkGlyph & g,SkRect * bounds,Sk48Dot16 dx)805 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
806 SkScalar sx = Sk48Dot16ToScalar(dx);
807 bounds->join(SkIntToScalar(g.fLeft) + sx,
808 SkIntToScalar(g.fTop),
809 SkIntToScalar(g.fLeft + g.fWidth) + sx,
810 SkIntToScalar(g.fTop + g.fHeight));
811 }
812
join_bounds_y(const SkGlyph & g,SkRect * bounds,Sk48Dot16 dy)813 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
814 SkScalar sy = Sk48Dot16ToScalar(dy);
815 bounds->join(SkIntToScalar(g.fLeft),
816 SkIntToScalar(g.fTop) + sy,
817 SkIntToScalar(g.fLeft + g.fWidth),
818 SkIntToScalar(g.fTop + g.fHeight) + sy);
819 }
820
821 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
822
823 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
advance(const SkGlyph & glyph,int xyIndex)824 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
825 SkASSERT(0 == xyIndex || 1 == xyIndex);
826 return (&glyph.fAdvanceX)[xyIndex];
827 }
828
measure_text(SkGlyphCache * cache,const char * text,size_t byteLength,int * count,SkRect * bounds) const829 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
830 const char* text, size_t byteLength,
831 int* count, SkRect* bounds) const {
832 SkASSERT(count);
833 if (byteLength == 0) {
834 *count = 0;
835 if (bounds) {
836 bounds->setEmpty();
837 }
838 return 0;
839 }
840
841 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(NULL != bounds);
842
843 int xyIndex;
844 JoinBoundsProc joinBoundsProc;
845 if (this->isVerticalText()) {
846 xyIndex = 1;
847 joinBoundsProc = join_bounds_y;
848 } else {
849 xyIndex = 0;
850 joinBoundsProc = join_bounds_x;
851 }
852
853 int n = 1;
854 const char* stop = (const char*)text + byteLength;
855 const SkGlyph* g = &glyphCacheProc(cache, &text);
856 // our accumulated fixed-point advances might overflow 16.16, so we use
857 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
858 // very end.
859 Sk48Dot16 x = advance(*g, xyIndex);
860
861 SkAutoKern autokern;
862
863 if (NULL == bounds) {
864 if (this->isDevKernText()) {
865 int rsb;
866 for (; text < stop; n++) {
867 rsb = g->fRsbDelta;
868 g = &glyphCacheProc(cache, &text);
869 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
870 }
871 } else {
872 for (; text < stop; n++) {
873 x += advance(glyphCacheProc(cache, &text), xyIndex);
874 }
875 }
876 } else {
877 set_bounds(*g, bounds);
878 if (this->isDevKernText()) {
879 int rsb;
880 for (; text < stop; n++) {
881 rsb = g->fRsbDelta;
882 g = &glyphCacheProc(cache, &text);
883 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
884 joinBoundsProc(*g, bounds, x);
885 x += advance(*g, xyIndex);
886 }
887 } else {
888 for (; text < stop; n++) {
889 g = &glyphCacheProc(cache, &text);
890 joinBoundsProc(*g, bounds, x);
891 x += advance(*g, xyIndex);
892 }
893 }
894 }
895 SkASSERT(text == stop);
896
897 *count = n;
898 return Sk48Dot16ToScalar(x);
899 }
900
measureText(const void * textData,size_t length,SkRect * bounds) const901 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
902 const char* text = (const char*)textData;
903 SkASSERT(text != NULL || length == 0);
904
905 SkCanonicalizePaint canon(*this);
906 const SkPaint& paint = canon.getPaint();
907 SkScalar scale = canon.getScale();
908
909 SkAutoGlyphCache autoCache(paint, NULL, NULL);
910 SkGlyphCache* cache = autoCache.getCache();
911
912 SkScalar width = 0;
913
914 if (length > 0) {
915 int tempCount;
916
917 width = paint.measure_text(cache, text, length, &tempCount, bounds);
918 if (scale) {
919 width = SkScalarMul(width, scale);
920 if (bounds) {
921 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
922 bounds->fTop = SkScalarMul(bounds->fTop, scale);
923 bounds->fRight = SkScalarMul(bounds->fRight, scale);
924 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
925 }
926 }
927 } else if (bounds) {
928 // ensure that even if we don't measure_text we still update the bounds
929 bounds->setEmpty();
930 }
931 return width;
932 }
933
breakText(const void * textD,size_t length,SkScalar maxWidth,SkScalar * measuredWidth) const934 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
935 SkScalar* measuredWidth) const {
936 if (0 == length || 0 >= maxWidth) {
937 if (measuredWidth) {
938 *measuredWidth = 0;
939 }
940 return 0;
941 }
942
943 if (0 == fTextSize) {
944 if (measuredWidth) {
945 *measuredWidth = 0;
946 }
947 return length;
948 }
949
950 SkASSERT(textD != NULL);
951 const char* text = (const char*)textD;
952 const char* stop = text + length;
953
954 SkCanonicalizePaint canon(*this);
955 const SkPaint& paint = canon.getPaint();
956 SkScalar scale = canon.getScale();
957
958 // adjust max in case we changed the textSize in paint
959 if (scale) {
960 maxWidth /= scale;
961 }
962
963 SkAutoGlyphCache autoCache(paint, NULL, NULL);
964 SkGlyphCache* cache = autoCache.getCache();
965
966 SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(false);
967 const int xyIndex = paint.isVerticalText() ? 1 : 0;
968 // use 64bits for our accumulator, to avoid overflowing 16.16
969 Sk48Dot16 max = SkScalarToFixed(maxWidth);
970 Sk48Dot16 width = 0;
971
972 SkAutoKern autokern;
973
974 if (this->isDevKernText()) {
975 int rsb = 0;
976 while (text < stop) {
977 const char* curr = text;
978 const SkGlyph& g = glyphCacheProc(cache, &text);
979 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
980 if ((width += x) > max) {
981 width -= x;
982 text = curr;
983 break;
984 }
985 rsb = g.fRsbDelta;
986 }
987 } else {
988 while (text < stop) {
989 const char* curr = text;
990 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
991 if ((width += x) > max) {
992 width -= x;
993 text = curr;
994 break;
995 }
996 }
997 }
998
999 if (measuredWidth) {
1000 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1001 if (scale) {
1002 scalarWidth = SkScalarMul(scalarWidth, scale);
1003 }
1004 *measuredWidth = scalarWidth;
1005 }
1006
1007 // return the number of bytes measured
1008 return text - stop + length;
1009 }
1010
1011 ///////////////////////////////////////////////////////////////////////////////
1012
FontMetricsCacheProc(const SkGlyphCache * cache,void * context)1013 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1014 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1015 return false; // don't detach the cache
1016 }
1017
FontMetricsDescProc(SkTypeface * typeface,const SkDescriptor * desc,void * context)1018 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1019 void* context) {
1020 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1021 }
1022
getFontMetrics(FontMetrics * metrics,SkScalar zoom) const1023 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1024 SkCanonicalizePaint canon(*this);
1025 const SkPaint& paint = canon.getPaint();
1026 SkScalar scale = canon.getScale();
1027
1028 SkMatrix zoomMatrix, *zoomPtr = NULL;
1029 if (zoom) {
1030 zoomMatrix.setScale(zoom, zoom);
1031 zoomPtr = &zoomMatrix;
1032 }
1033
1034 FontMetrics storage;
1035 if (NULL == metrics) {
1036 metrics = &storage;
1037 }
1038
1039 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1040
1041 if (scale) {
1042 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1043 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1044 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1045 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1046 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1047 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
1048 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
1049 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
1050 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
1051 metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
1052 metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
1053 }
1054 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1055 }
1056
1057 ///////////////////////////////////////////////////////////////////////////////
1058
set_bounds(const SkGlyph & g,SkRect * bounds,SkScalar scale)1059 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1060 bounds->set(g.fLeft * scale,
1061 g.fTop * scale,
1062 (g.fLeft + g.fWidth) * scale,
1063 (g.fTop + g.fHeight) * scale);
1064 }
1065
getTextWidths(const void * textData,size_t byteLength,SkScalar widths[],SkRect bounds[]) const1066 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1067 SkScalar widths[], SkRect bounds[]) const {
1068 if (0 == byteLength) {
1069 return 0;
1070 }
1071
1072 SkASSERT(textData);
1073
1074 if (NULL == widths && NULL == bounds) {
1075 return this->countText(textData, byteLength);
1076 }
1077
1078 SkCanonicalizePaint canon(*this);
1079 const SkPaint& paint = canon.getPaint();
1080 SkScalar scale = canon.getScale();
1081
1082 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1083 SkGlyphCache* cache = autoCache.getCache();
1084 SkMeasureCacheProc glyphCacheProc;
1085 glyphCacheProc = paint.getMeasureCacheProc(NULL != bounds);
1086
1087 const char* text = (const char*)textData;
1088 const char* stop = text + byteLength;
1089 int count = 0;
1090 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1091
1092 if (this->isDevKernText()) {
1093 // we adjust the widths returned here through auto-kerning
1094 SkAutoKern autokern;
1095 SkFixed prevWidth = 0;
1096
1097 if (scale) {
1098 while (text < stop) {
1099 const SkGlyph& g = glyphCacheProc(cache, &text);
1100 if (widths) {
1101 SkFixed adjust = autokern.adjust(g);
1102
1103 if (count > 0) {
1104 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1105 *widths++ = SkScalarMul(w, scale);
1106 }
1107 prevWidth = advance(g, xyIndex);
1108 }
1109 if (bounds) {
1110 set_bounds(g, bounds++, scale);
1111 }
1112 ++count;
1113 }
1114 if (count > 0 && widths) {
1115 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1116 }
1117 } else {
1118 while (text < stop) {
1119 const SkGlyph& g = glyphCacheProc(cache, &text);
1120 if (widths) {
1121 SkFixed adjust = autokern.adjust(g);
1122
1123 if (count > 0) {
1124 *widths++ = SkFixedToScalar(prevWidth + adjust);
1125 }
1126 prevWidth = advance(g, xyIndex);
1127 }
1128 if (bounds) {
1129 set_bounds(g, bounds++);
1130 }
1131 ++count;
1132 }
1133 if (count > 0 && widths) {
1134 *widths = SkFixedToScalar(prevWidth);
1135 }
1136 }
1137 } else { // no devkern
1138 if (scale) {
1139 while (text < stop) {
1140 const SkGlyph& g = glyphCacheProc(cache, &text);
1141 if (widths) {
1142 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
1143 scale);
1144 }
1145 if (bounds) {
1146 set_bounds(g, bounds++, scale);
1147 }
1148 ++count;
1149 }
1150 } else {
1151 while (text < stop) {
1152 const SkGlyph& g = glyphCacheProc(cache, &text);
1153 if (widths) {
1154 *widths++ = SkFixedToScalar(advance(g, xyIndex));
1155 }
1156 if (bounds) {
1157 set_bounds(g, bounds++);
1158 }
1159 ++count;
1160 }
1161 }
1162 }
1163
1164 SkASSERT(text == stop);
1165 return count;
1166 }
1167
1168 ///////////////////////////////////////////////////////////////////////////////
1169
1170 #include "SkDraw.h"
1171
getTextPath(const void * textData,size_t length,SkScalar x,SkScalar y,SkPath * path) const1172 void SkPaint::getTextPath(const void* textData, size_t length,
1173 SkScalar x, SkScalar y, SkPath* path) const {
1174 SkASSERT(length == 0 || textData != NULL);
1175
1176 const char* text = (const char*)textData;
1177 if (text == NULL || length == 0 || path == NULL) {
1178 return;
1179 }
1180
1181 SkTextToPathIter iter(text, length, *this, false);
1182 SkMatrix matrix;
1183 SkScalar prevXPos = 0;
1184
1185 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1186 matrix.postTranslate(x, y);
1187 path->reset();
1188
1189 SkScalar xpos;
1190 const SkPath* iterPath;
1191 while (iter.next(&iterPath, &xpos)) {
1192 matrix.postTranslate(xpos - prevXPos, 0);
1193 if (iterPath) {
1194 path->addPath(*iterPath, matrix);
1195 }
1196 prevXPos = xpos;
1197 }
1198 }
1199
getPosTextPath(const void * textData,size_t length,const SkPoint pos[],SkPath * path) const1200 void SkPaint::getPosTextPath(const void* textData, size_t length,
1201 const SkPoint pos[], SkPath* path) const {
1202 SkASSERT(length == 0 || textData != NULL);
1203
1204 const char* text = (const char*)textData;
1205 if (text == NULL || length == 0 || path == NULL) {
1206 return;
1207 }
1208
1209 SkTextToPathIter iter(text, length, *this, false);
1210 SkMatrix matrix;
1211 SkPoint prevPos;
1212 prevPos.set(0, 0);
1213
1214 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1215 path->reset();
1216
1217 unsigned int i = 0;
1218 const SkPath* iterPath;
1219 while (iter.next(&iterPath, NULL)) {
1220 matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1221 if (iterPath) {
1222 path->addPath(*iterPath, matrix);
1223 }
1224 prevPos = pos[i];
1225 i++;
1226 }
1227 }
1228
getFontBounds() const1229 SkRect SkPaint::getFontBounds() const {
1230 SkMatrix m;
1231 m.setScale(fTextSize * fTextScaleX, fTextSize);
1232 m.postSkew(fTextSkewX, 0);
1233
1234 SkTypeface* typeface = this->getTypeface();
1235 if (NULL == typeface) {
1236 typeface = SkTypeface::GetDefaultTypeface();
1237 }
1238
1239 SkRect bounds;
1240 m.mapRect(&bounds, typeface->getBounds());
1241 return bounds;
1242 }
1243
add_flattenable(SkDescriptor * desc,uint32_t tag,SkWriteBuffer * buffer)1244 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1245 SkWriteBuffer* buffer) {
1246 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
1247 }
1248
computeMaskFormat(const SkPaint & paint)1249 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1250 uint32_t flags = paint.getFlags();
1251
1252 // Antialiasing being disabled trumps all other settings.
1253 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1254 return SkMask::kBW_Format;
1255 }
1256
1257 if (flags & SkPaint::kLCDRenderText_Flag) {
1258 return SkMask::kLCD16_Format;
1259 }
1260
1261 return SkMask::kA8_Format;
1262 }
1263
1264 // if linear-text is on, then we force hinting to be off (since that's sort of
1265 // the point of linear-text.
computeHinting(const SkPaint & paint)1266 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1267 SkPaint::Hinting h = paint.getHinting();
1268 if (paint.isLinearText()) {
1269 h = SkPaint::kNo_Hinting;
1270 }
1271 return h;
1272 }
1273
1274 // return true if the paint is just a single color (i.e. not a shader). If its
1275 // a shader, then we can't compute a const luminance for it :(
justAColor(const SkPaint & paint,SkColor * color)1276 static bool justAColor(const SkPaint& paint, SkColor* color) {
1277 SkColor c = paint.getColor();
1278
1279 SkShader* shader = paint.getShader();
1280 if (shader && !shader->asLuminanceColor(&c)) {
1281 return false;
1282 }
1283 if (paint.getColorFilter()) {
1284 c = paint.getColorFilter()->filterColor(c);
1285 }
1286 if (color) {
1287 *color = c;
1288 }
1289 return true;
1290 }
1291
computeLuminanceColor() const1292 SkColor SkPaint::computeLuminanceColor() const {
1293 SkColor c;
1294 if (!justAColor(*this, &c)) {
1295 c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1296 }
1297 return c;
1298 }
1299
1300 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1301
1302 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1303 // cost more RAM and draws slower, so we set a cap.
1304 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1305 #define SK_MAX_SIZE_FOR_LCDTEXT 48
1306 #endif
1307
1308 const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
1309
too_big_for_lcd(const SkScalerContext::Rec & rec,bool checkPost2x2)1310 static bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) {
1311 if (checkPost2x2) {
1312 SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1313 rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1314 area *= rec.fTextSize * rec.fTextSize;
1315 return area > gMaxSize2ForLCDText;
1316 } else {
1317 return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
1318 }
1319 }
1320
1321 /*
1322 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1323 * that vary only slightly when we create our key into the font cache, since the font scaler
1324 * typically returns the same looking resuts for tiny changes in the matrix.
1325 */
sk_relax(SkScalar x)1326 static SkScalar sk_relax(SkScalar x) {
1327 int n = sk_float_round2int(x * 1024);
1328 return n / 1024.0f;
1329 }
1330
MakeRec(const SkPaint & paint,const SkDeviceProperties * deviceProperties,const SkMatrix * deviceMatrix,Rec * rec)1331 void SkScalerContext::MakeRec(const SkPaint& paint,
1332 const SkDeviceProperties* deviceProperties,
1333 const SkMatrix* deviceMatrix,
1334 Rec* rec) {
1335 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1336
1337 SkTypeface* typeface = paint.getTypeface();
1338 if (NULL == typeface) {
1339 typeface = SkTypeface::GetDefaultTypeface();
1340 }
1341 rec->fFontID = typeface->uniqueID();
1342 rec->fTextSize = paint.getTextSize();
1343 rec->fPreScaleX = paint.getTextScaleX();
1344 rec->fPreSkewX = paint.getTextSkewX();
1345
1346 bool checkPost2x2 = false;
1347
1348 if (deviceMatrix) {
1349 const SkMatrix::TypeMask mask = deviceMatrix->getType();
1350 if (mask & SkMatrix::kScale_Mask) {
1351 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1352 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1353 checkPost2x2 = true;
1354 } else {
1355 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1356 }
1357 if (mask & SkMatrix::kAffine_Mask) {
1358 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1359 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1360 checkPost2x2 = true;
1361 } else {
1362 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1363 }
1364 } else {
1365 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1366 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1367 }
1368
1369 SkPaint::Style style = paint.getStyle();
1370 SkScalar strokeWidth = paint.getStrokeWidth();
1371
1372 unsigned flags = 0;
1373
1374 if (paint.isFakeBoldText()) {
1375 #ifdef SK_USE_FREETYPE_EMBOLDEN
1376 flags |= SkScalerContext::kEmbolden_Flag;
1377 #else
1378 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1379 kStdFakeBoldInterpKeys,
1380 kStdFakeBoldInterpValues,
1381 kStdFakeBoldInterpLength);
1382 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1383
1384 if (style == SkPaint::kFill_Style) {
1385 style = SkPaint::kStrokeAndFill_Style;
1386 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1387 } else {
1388 strokeWidth += extra;
1389 }
1390 #endif
1391 }
1392
1393 if (paint.isDevKernText()) {
1394 flags |= SkScalerContext::kDevKernText_Flag;
1395 }
1396
1397 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1398 rec->fFrameWidth = strokeWidth;
1399 rec->fMiterLimit = paint.getStrokeMiter();
1400 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1401
1402 if (style == SkPaint::kStrokeAndFill_Style) {
1403 flags |= SkScalerContext::kFrameAndFill_Flag;
1404 }
1405 } else {
1406 rec->fFrameWidth = 0;
1407 rec->fMiterLimit = 0;
1408 rec->fStrokeJoin = 0;
1409 }
1410
1411 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1412
1413 if (SkMask::kLCD16_Format == rec->fMaskFormat) {
1414 if (too_big_for_lcd(*rec, checkPost2x2)) {
1415 rec->fMaskFormat = SkMask::kA8_Format;
1416 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1417 } else {
1418 SkPixelGeometry geometry = deviceProperties
1419 ? deviceProperties->pixelGeometry()
1420 : SkSurfacePropsDefaultPixelGeometry();
1421 switch (geometry) {
1422 case kUnknown_SkPixelGeometry:
1423 // eeek, can't support LCD
1424 rec->fMaskFormat = SkMask::kA8_Format;
1425 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1426 break;
1427 case kRGB_H_SkPixelGeometry:
1428 // our default, do nothing.
1429 break;
1430 case kBGR_H_SkPixelGeometry:
1431 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1432 break;
1433 case kRGB_V_SkPixelGeometry:
1434 flags |= SkScalerContext::kLCD_Vertical_Flag;
1435 break;
1436 case kBGR_V_SkPixelGeometry:
1437 flags |= SkScalerContext::kLCD_Vertical_Flag;
1438 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1439 break;
1440 }
1441 }
1442 }
1443
1444 if (paint.isEmbeddedBitmapText()) {
1445 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1446 }
1447 if (paint.isSubpixelText()) {
1448 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1449 }
1450 if (paint.isAutohinted()) {
1451 flags |= SkScalerContext::kForceAutohinting_Flag;
1452 }
1453 if (paint.isVerticalText()) {
1454 flags |= SkScalerContext::kVertical_Flag;
1455 }
1456 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1457 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1458 }
1459 rec->fFlags = SkToU16(flags);
1460
1461 // these modify fFlags, so do them after assigning fFlags
1462 rec->setHinting(computeHinting(paint));
1463
1464 rec->setLuminanceColor(paint.computeLuminanceColor());
1465
1466 if (NULL == deviceProperties) {
1467 rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1468 rec->setPaintGamma(SK_GAMMA_EXPONENT);
1469 } else {
1470 rec->setDeviceGamma(deviceProperties->gamma());
1471
1472 //For now always set the paint gamma equal to the device gamma.
1473 //The math in SkMaskGamma can handle them being different,
1474 //but it requires superluminous masks when
1475 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1476 rec->setPaintGamma(deviceProperties->gamma());
1477 }
1478
1479 #ifdef SK_GAMMA_CONTRAST
1480 rec->setContrast(SK_GAMMA_CONTRAST);
1481 #else
1482 /**
1483 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1484 * With lower values small text appears washed out (though correctly so).
1485 * With higher values lcd fringing is worse and the smoothing effect of
1486 * partial coverage is diminished.
1487 */
1488 rec->setContrast(0.5f);
1489 #endif
1490
1491 rec->fReservedAlign = 0;
1492
1493 /* Allow the fonthost to modify our rec before we use it as a key into the
1494 cache. This way if we're asking for something that they will ignore,
1495 they can modify our rec up front, so we don't create duplicate cache
1496 entries.
1497 */
1498 typeface->onFilterRec(rec);
1499
1500 // be sure to call PostMakeRec(rec) before you actually use it!
1501 }
1502
1503 /**
1504 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1505 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1506 * to hold it until the returned pointer is refed or forgotten.
1507 */
1508 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1509
1510 static SkMaskGamma* gLinearMaskGamma = NULL;
1511 static SkMaskGamma* gMaskGamma = NULL;
1512 static SkScalar gContrast = SK_ScalarMin;
1513 static SkScalar gPaintGamma = SK_ScalarMin;
1514 static SkScalar gDeviceGamma = SK_ScalarMin;
1515 /**
1516 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1517 * the returned SkMaskGamma pointer is refed or forgotten.
1518 */
cachedMaskGamma(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma)1519 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1520 gMaskGammaCacheMutex.assertHeld();
1521 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1522 if (NULL == gLinearMaskGamma) {
1523 gLinearMaskGamma = SkNEW(SkMaskGamma);
1524 }
1525 return *gLinearMaskGamma;
1526 }
1527 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1528 SkSafeUnref(gMaskGamma);
1529 gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
1530 gContrast = contrast;
1531 gPaintGamma = paintGamma;
1532 gDeviceGamma = deviceGamma;
1533 }
1534 return *gMaskGamma;
1535 }
1536
Term()1537 /*static*/ void SkPaint::Term() {
1538 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1539
1540 SkSafeUnref(gLinearMaskGamma);
1541 gLinearMaskGamma = NULL;
1542 SkSafeUnref(gMaskGamma);
1543 gMaskGamma = NULL;
1544 SkDEBUGCODE(gContrast = SK_ScalarMin;)
1545 SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1546 SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1547 }
1548
1549 /**
1550 * We ensure that the rec is self-consistent and efficient (where possible)
1551 */
PostMakeRec(const SkPaint &,SkScalerContext::Rec * rec)1552 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
1553 /**
1554 * If we're asking for A8, we force the colorlum to be gray, since that
1555 * limits the number of unique entries, and the scaler will only look at
1556 * the lum of one of them.
1557 */
1558 switch (rec->fMaskFormat) {
1559 case SkMask::kLCD16_Format: {
1560 // filter down the luminance color to a finite number of bits
1561 SkColor color = rec->getLuminanceColor();
1562 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1563 break;
1564 }
1565 case SkMask::kA8_Format: {
1566 // filter down the luminance to a single component, since A8 can't
1567 // use per-component information
1568 SkColor color = rec->getLuminanceColor();
1569 U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1570 SkColorGetG(color),
1571 SkColorGetB(color));
1572 // reduce to our finite number of bits
1573 color = SkColorSetRGB(lum, lum, lum);
1574 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1575 break;
1576 }
1577 case SkMask::kBW_Format:
1578 // No need to differentiate gamma if we're BW
1579 rec->ignorePreBlend();
1580 break;
1581 }
1582 }
1583
1584 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1585
1586 #ifdef SK_DEBUG
1587 #define TEST_DESC
1588 #endif
1589
write_out_descriptor(SkDescriptor * desc,const SkScalerContext::Rec & rec,const SkPathEffect * pe,SkWriteBuffer * peBuffer,const SkMaskFilter * mf,SkWriteBuffer * mfBuffer,const SkRasterizer * ra,SkWriteBuffer * raBuffer,size_t descSize)1590 static void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec,
1591 const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1592 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1593 const SkRasterizer* ra, SkWriteBuffer* raBuffer,
1594 size_t descSize) {
1595 desc->init();
1596 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1597
1598 if (pe) {
1599 add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
1600 }
1601 if (mf) {
1602 add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
1603 }
1604 if (ra) {
1605 add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer);
1606 }
1607
1608 desc->computeChecksum();
1609 }
1610
fill_out_rec(const SkPaint & paint,SkScalerContext::Rec * rec,const SkDeviceProperties * deviceProperties,const SkMatrix * deviceMatrix,bool ignoreGamma,const SkPathEffect * pe,SkWriteBuffer * peBuffer,const SkMaskFilter * mf,SkWriteBuffer * mfBuffer,const SkRasterizer * ra,SkWriteBuffer * raBuffer)1611 static size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec,
1612 const SkDeviceProperties* deviceProperties,
1613 const SkMatrix* deviceMatrix, bool ignoreGamma,
1614 const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1615 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1616 const SkRasterizer* ra, SkWriteBuffer* raBuffer) {
1617 SkScalerContext::MakeRec(paint, deviceProperties, deviceMatrix, rec);
1618 if (ignoreGamma) {
1619 rec->ignorePreBlend();
1620 }
1621
1622 int entryCount = 1;
1623 size_t descSize = sizeof(*rec);
1624
1625 if (pe) {
1626 peBuffer->writeFlattenable(pe);
1627 descSize += peBuffer->bytesWritten();
1628 entryCount += 1;
1629 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1630 // seems like we could support kLCD as well at this point...
1631 }
1632 if (mf) {
1633 mfBuffer->writeFlattenable(mf);
1634 descSize += mfBuffer->bytesWritten();
1635 entryCount += 1;
1636 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1637 /* Pre-blend is not currently applied to filtered text.
1638 The primary filter is blur, for which contrast makes no sense,
1639 and for which the destination guess error is more visible.
1640 Also, all existing users of blur have calibrated for linear. */
1641 rec->ignorePreBlend();
1642 }
1643 if (ra) {
1644 raBuffer->writeFlattenable(ra);
1645 descSize += raBuffer->bytesWritten();
1646 entryCount += 1;
1647 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1648 }
1649
1650 ///////////////////////////////////////////////////////////////////////////
1651 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1652 SkScalerContext::PostMakeRec(paint, rec);
1653
1654 descSize += SkDescriptor::ComputeOverhead(entryCount);
1655 return descSize;
1656 }
1657
1658 #ifdef TEST_DESC
test_desc(const SkScalerContext::Rec & rec,const SkPathEffect * pe,SkWriteBuffer * peBuffer,const SkMaskFilter * mf,SkWriteBuffer * mfBuffer,const SkRasterizer * ra,SkWriteBuffer * raBuffer,const SkDescriptor * desc,size_t descSize)1659 static void test_desc(const SkScalerContext::Rec& rec,
1660 const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1661 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1662 const SkRasterizer* ra, SkWriteBuffer* raBuffer,
1663 const SkDescriptor* desc, size_t descSize) {
1664 // Check that we completely write the bytes in desc (our key), and that
1665 // there are no uninitialized bytes. If there were, then we would get
1666 // false-misses (or worse, false-hits) in our fontcache.
1667 //
1668 // We do this buy filling 2 others, one with 0s and the other with 1s
1669 // and create those, and then check that all 3 are identical.
1670 SkAutoDescriptor ad1(descSize);
1671 SkAutoDescriptor ad2(descSize);
1672 SkDescriptor* desc1 = ad1.getDesc();
1673 SkDescriptor* desc2 = ad2.getDesc();
1674
1675 memset(desc1, 0x00, descSize);
1676 memset(desc2, 0xFF, descSize);
1677
1678 desc1->init();
1679 desc2->init();
1680 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1681 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1682
1683 if (pe) {
1684 add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
1685 add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
1686 }
1687 if (mf) {
1688 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
1689 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
1690 }
1691 if (ra) {
1692 add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer);
1693 add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer);
1694 }
1695
1696 SkASSERT(descSize == desc1->getLength());
1697 SkASSERT(descSize == desc2->getLength());
1698 desc1->computeChecksum();
1699 desc2->computeChecksum();
1700 SkASSERT(!memcmp(desc, desc1, descSize));
1701 SkASSERT(!memcmp(desc, desc2, descSize));
1702 }
1703 #endif
1704
1705 /* see the note on ignoreGamma on descriptorProc */
getScalerContextDescriptor(SkAutoDescriptor * ad,const SkDeviceProperties * deviceProperties,const SkMatrix * deviceMatrix,bool ignoreGamma) const1706 void SkPaint::getScalerContextDescriptor(SkAutoDescriptor* ad,
1707 const SkDeviceProperties* deviceProperties,
1708 const SkMatrix* deviceMatrix, bool ignoreGamma) const {
1709 SkScalerContext::Rec rec;
1710
1711 SkPathEffect* pe = this->getPathEffect();
1712 SkMaskFilter* mf = this->getMaskFilter();
1713 SkRasterizer* ra = this->getRasterizer();
1714
1715 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1716 size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
1717 pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1718
1719 ad->reset(descSize);
1720 SkDescriptor* desc = ad->getDesc();
1721
1722 write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1723
1724 SkASSERT(descSize == desc->getLength());
1725
1726 #ifdef TEST_DESC
1727 test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
1728 #endif
1729 }
1730
1731 /*
1732 * ignoreGamma tells us that the caller just wants metrics that are unaffected
1733 * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
1734 * contrast = 0, luminanceColor = transparent black.
1735 */
descriptorProc(const SkDeviceProperties * deviceProperties,const SkMatrix * deviceMatrix,void (* proc)(SkTypeface *,const SkDescriptor *,void *),void * context,bool ignoreGamma) const1736 void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1737 const SkMatrix* deviceMatrix,
1738 void (*proc)(SkTypeface*, const SkDescriptor*, void*),
1739 void* context, bool ignoreGamma) const {
1740 SkScalerContext::Rec rec;
1741
1742 SkPathEffect* pe = this->getPathEffect();
1743 SkMaskFilter* mf = this->getMaskFilter();
1744 SkRasterizer* ra = this->getRasterizer();
1745
1746 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1747 size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
1748 pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1749
1750 SkAutoDescriptor ad(descSize);
1751 SkDescriptor* desc = ad.getDesc();
1752
1753 write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1754
1755 SkASSERT(descSize == desc->getLength());
1756
1757 #ifdef TEST_DESC
1758 test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
1759 #endif
1760
1761 proc(fTypeface, desc, context);
1762 }
1763
detachCache(const SkDeviceProperties * deviceProperties,const SkMatrix * deviceMatrix,bool ignoreGamma) const1764 SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
1765 const SkMatrix* deviceMatrix,
1766 bool ignoreGamma) const {
1767 SkGlyphCache* cache;
1768 this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
1769 return cache;
1770 }
1771
1772 /**
1773 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1774 */
1775 //static
GetMaskPreBlend(const SkScalerContext::Rec & rec)1776 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
1777 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1778 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1779 rec.getPaintGamma(),
1780 rec.getDeviceGamma());
1781 return maskGamma.preBlend(rec.getLuminanceColor());
1782 }
1783
GetGammaLUTSize(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,int * width,int * height)1784 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
1785 SkScalar deviceGamma, int* width, int* height) {
1786 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1787 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1788 paintGamma,
1789 deviceGamma);
1790
1791 maskGamma.getGammaTableDimensions(width, height);
1792 size_t size = (*width)*(*height)*sizeof(uint8_t);
1793
1794 return size;
1795 }
1796
GetGammaLUTData(SkScalar contrast,SkScalar paintGamma,SkScalar deviceGamma,void * data)1797 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
1798 void* data) {
1799 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1800 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1801 paintGamma,
1802 deviceGamma);
1803 int width, height;
1804 maskGamma.getGammaTableDimensions(&width, &height);
1805 size_t size = width*height*sizeof(uint8_t);
1806 const uint8_t* gammaTables = maskGamma.getGammaTables();
1807 memcpy(data, gammaTables, size);
1808 }
1809
1810
1811 ///////////////////////////////////////////////////////////////////////////////
1812
1813 #include "SkStream.h"
1814
asint(const void * p)1815 static uintptr_t asint(const void* p) {
1816 return reinterpret_cast<uintptr_t>(p);
1817 }
1818
1819 union Scalar32 {
1820 SkScalar fScalar;
1821 uint32_t f32;
1822 };
1823
write_scalar(uint32_t * ptr,SkScalar value)1824 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1825 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1826 Scalar32 tmp;
1827 tmp.fScalar = value;
1828 *ptr = tmp.f32;
1829 return ptr + 1;
1830 }
1831
read_scalar(const uint32_t * & ptr)1832 static SkScalar read_scalar(const uint32_t*& ptr) {
1833 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1834 Scalar32 tmp;
1835 tmp.f32 = *ptr++;
1836 return tmp.fScalar;
1837 }
1838
pack_4(unsigned a,unsigned b,unsigned c,unsigned d)1839 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1840 SkASSERT(a == (uint8_t)a);
1841 SkASSERT(b == (uint8_t)b);
1842 SkASSERT(c == (uint8_t)c);
1843 SkASSERT(d == (uint8_t)d);
1844 return (a << 24) | (b << 16) | (c << 8) | d;
1845 }
1846
1847 #ifdef SK_DEBUG
ASSERT_FITS_IN(uint32_t value,int bitCount)1848 static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
1849 SkASSERT(bitCount > 0 && bitCount <= 32);
1850 uint32_t mask = ~0U;
1851 mask >>= (32 - bitCount);
1852 SkASSERT(0 == (value & ~mask));
1853 }
1854 #else
1855 #define ASSERT_FITS_IN(value, bitcount)
1856 #endif
1857
1858 enum FlatFlags {
1859 kHasTypeface_FlatFlag = 0x1,
1860 kHasEffects_FlatFlag = 0x2,
1861
1862 kFlatFlagMask = 0x3,
1863 };
1864
1865 enum BitsPerField {
1866 kFlags_BPF = 16,
1867 kHint_BPF = 2,
1868 kAlign_BPF = 2,
1869 kFilter_BPF = 2,
1870 kFlatFlags_BPF = 3,
1871 };
1872
BPF_Mask(int bits)1873 static inline int BPF_Mask(int bits) {
1874 return (1 << bits) - 1;
1875 }
1876
pack_paint_flags(unsigned flags,unsigned hint,unsigned align,unsigned filter,unsigned flatFlags)1877 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
1878 unsigned filter, unsigned flatFlags) {
1879 ASSERT_FITS_IN(flags, kFlags_BPF);
1880 ASSERT_FITS_IN(hint, kHint_BPF);
1881 ASSERT_FITS_IN(align, kAlign_BPF);
1882 ASSERT_FITS_IN(filter, kFilter_BPF);
1883 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
1884
1885 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
1886 // add more bits in the future.
1887 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
1888 }
1889
unpack_paint_flags(SkPaint * paint,uint32_t packed)1890 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
1891 paint->setFlags(packed >> 16);
1892 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
1893 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
1894 paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
1895 return (FlatFlags)(packed & kFlatFlagMask);
1896 }
1897
1898 // The size of a flat paint's POD fields
1899 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1900 1 * sizeof(SkColor) +
1901 1 * sizeof(uint16_t) +
1902 6 * sizeof(uint8_t);
1903
1904 /* To save space/time, we analyze the paint, and write a truncated version of
1905 it if there are not tricky elements like shaders, etc.
1906 */
flatten(SkWriteBuffer & buffer) const1907 void SkPaint::flatten(SkWriteBuffer& buffer) const {
1908 uint8_t flatFlags = 0;
1909 if (this->getTypeface()) {
1910 flatFlags |= kHasTypeface_FlatFlag;
1911 }
1912 if (asint(this->getPathEffect()) |
1913 asint(this->getShader()) |
1914 asint(this->getXfermode()) |
1915 asint(this->getMaskFilter()) |
1916 asint(this->getColorFilter()) |
1917 asint(this->getRasterizer()) |
1918 asint(this->getLooper()) |
1919 asint(this->getAnnotation()) |
1920 asint(this->getImageFilter())) {
1921 flatFlags |= kHasEffects_FlatFlag;
1922 }
1923
1924 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1925 uint32_t* ptr = buffer.reserve(kPODPaintSize);
1926
1927 ptr = write_scalar(ptr, this->getTextSize());
1928 ptr = write_scalar(ptr, this->getTextScaleX());
1929 ptr = write_scalar(ptr, this->getTextSkewX());
1930 ptr = write_scalar(ptr, this->getStrokeWidth());
1931 ptr = write_scalar(ptr, this->getStrokeMiter());
1932 *ptr++ = this->getColor();
1933
1934 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
1935 this->getFilterQuality(), flatFlags);
1936 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1937 this->getStyle(), this->getTextEncoding());
1938
1939 // now we're done with ptr and the (pre)reserved space. If we need to write
1940 // additional fields, use the buffer directly
1941 if (flatFlags & kHasTypeface_FlatFlag) {
1942 buffer.writeTypeface(this->getTypeface());
1943 }
1944 if (flatFlags & kHasEffects_FlatFlag) {
1945 buffer.writeFlattenable(this->getPathEffect());
1946 buffer.writeFlattenable(this->getShader());
1947 buffer.writeFlattenable(this->getXfermode());
1948 buffer.writeFlattenable(this->getMaskFilter());
1949 buffer.writeFlattenable(this->getColorFilter());
1950 buffer.writeFlattenable(this->getRasterizer());
1951 buffer.writeFlattenable(this->getLooper());
1952 buffer.writeFlattenable(this->getImageFilter());
1953
1954 if (fAnnotation) {
1955 buffer.writeBool(true);
1956 fAnnotation->writeToBuffer(buffer);
1957 } else {
1958 buffer.writeBool(false);
1959 }
1960 }
1961 }
1962
unflatten(SkReadBuffer & buffer)1963 void SkPaint::unflatten(SkReadBuffer& buffer) {
1964 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1965 const void* podData = buffer.skip(kPODPaintSize);
1966 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1967
1968 // the order we read must match the order we wrote in flatten()
1969 this->setTextSize(read_scalar(pod));
1970 this->setTextScaleX(read_scalar(pod));
1971 this->setTextSkewX(read_scalar(pod));
1972 this->setStrokeWidth(read_scalar(pod));
1973 this->setStrokeMiter(read_scalar(pod));
1974 this->setColor(*pod++);
1975
1976 unsigned flatFlags = unpack_paint_flags(this, *pod++);
1977
1978 uint32_t tmp = *pod++;
1979 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1980 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1981 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1982 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1983
1984 if (flatFlags & kHasTypeface_FlatFlag) {
1985 this->setTypeface(buffer.readTypeface());
1986 } else {
1987 this->setTypeface(NULL);
1988 }
1989
1990 if (flatFlags & kHasEffects_FlatFlag) {
1991 SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
1992 SkSafeUnref(this->setShader(buffer.readShader()));
1993 SkSafeUnref(this->setXfermode(buffer.readXfermode()));
1994 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
1995 SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
1996 SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
1997 SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
1998 SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
1999
2000 if (buffer.readBool()) {
2001 this->setAnnotation(SkAnnotation::Create(buffer))->unref();
2002 }
2003 } else {
2004 this->setPathEffect(NULL);
2005 this->setShader(NULL);
2006 this->setXfermode(NULL);
2007 this->setMaskFilter(NULL);
2008 this->setColorFilter(NULL);
2009 this->setRasterizer(NULL);
2010 this->setLooper(NULL);
2011 this->setImageFilter(NULL);
2012 }
2013 }
2014
2015 ///////////////////////////////////////////////////////////////////////////////
2016
setShader(SkShader * shader)2017 SkShader* SkPaint::setShader(SkShader* shader) {
2018 SkRefCnt_SafeAssign(fShader, shader);
2019 return shader;
2020 }
2021
setColorFilter(SkColorFilter * filter)2022 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2023 SkRefCnt_SafeAssign(fColorFilter, filter);
2024 return filter;
2025 }
2026
setXfermode(SkXfermode * mode)2027 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2028 SkRefCnt_SafeAssign(fXfermode, mode);
2029 return mode;
2030 }
2031
setXfermodeMode(SkXfermode::Mode mode)2032 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2033 SkSafeUnref(fXfermode);
2034 fXfermode = SkXfermode::Create(mode);
2035 return fXfermode;
2036 }
2037
setPathEffect(SkPathEffect * effect)2038 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2039 SkRefCnt_SafeAssign(fPathEffect, effect);
2040 return effect;
2041 }
2042
setMaskFilter(SkMaskFilter * filter)2043 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2044 SkRefCnt_SafeAssign(fMaskFilter, filter);
2045 return filter;
2046 }
2047
2048 ///////////////////////////////////////////////////////////////////////////////
2049
getFillPath(const SkPath & src,SkPath * dst,const SkRect * cullRect,SkScalar resScale) const2050 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
2051 SkScalar resScale) const {
2052 SkStrokeRec rec(*this, resScale);
2053
2054 const SkPath* srcPtr = &src;
2055 SkPath tmpPath;
2056
2057 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2058 srcPtr = &tmpPath;
2059 }
2060
2061 if (!rec.applyToPath(dst, *srcPtr)) {
2062 if (srcPtr == &tmpPath) {
2063 // If path's were copy-on-write, this trick would not be needed.
2064 // As it is, we want to save making a deep-copy from tmpPath -> dst
2065 // since we know we're just going to delete tmpPath when we return,
2066 // so the swap saves that copy.
2067 dst->swap(tmpPath);
2068 } else {
2069 *dst = *srcPtr;
2070 }
2071 }
2072 return !rec.isHairlineStyle();
2073 }
2074
doComputeFastBounds(const SkRect & origSrc,SkRect * storage,Style style) const2075 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2076 SkRect* storage,
2077 Style style) const {
2078 SkASSERT(storage);
2079
2080 const SkRect* src = &origSrc;
2081
2082 if (this->getLooper()) {
2083 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2084 this->getLooper()->computeFastBounds(*this, *src, storage);
2085 return *storage;
2086 }
2087
2088 SkRect tmpSrc;
2089 if (this->getPathEffect()) {
2090 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2091 src = &tmpSrc;
2092 }
2093
2094 if (kFill_Style != style) {
2095 // since we're stroked, outset the rect by the radius (and join type)
2096 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2097 if (0 == radius) { // hairline
2098 radius = SK_Scalar1;
2099 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2100 SkScalar scale = this->getStrokeMiter();
2101 if (scale > SK_Scalar1) {
2102 radius = SkScalarMul(radius, scale);
2103 }
2104 }
2105 storage->set(src->fLeft - radius, src->fTop - radius,
2106 src->fRight + radius, src->fBottom + radius);
2107 } else {
2108 *storage = *src;
2109 }
2110
2111 if (this->getMaskFilter()) {
2112 this->getMaskFilter()->computeFastBounds(*storage, storage);
2113 }
2114
2115 if (this->getImageFilter()) {
2116 this->getImageFilter()->computeFastBounds(*storage, storage);
2117 }
2118
2119 return *storage;
2120 }
2121
2122 #ifndef SK_IGNORE_TO_STRING
2123
toString(SkString * str) const2124 void SkPaint::toString(SkString* str) const {
2125 str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2126
2127 SkTypeface* typeface = this->getTypeface();
2128 if (typeface) {
2129 SkDynamicMemoryWStream ostream;
2130 typeface->serialize(&ostream);
2131 SkAutoTDelete<SkStreamAsset> istream(ostream.detachAsStream());
2132 SkFontDescriptor descriptor(istream);
2133
2134 str->append("<dt>Font Family Name:</dt><dd>");
2135 str->append(descriptor.getFamilyName());
2136 str->append("</dd><dt>Font Full Name:</dt><dd>");
2137 str->append(descriptor.getFullName());
2138 str->append("</dd><dt>Font PS Name:</dt><dd>");
2139 str->append(descriptor.getPostscriptName());
2140 str->append("</dd>");
2141 }
2142
2143 str->append("<dt>TextSize:</dt><dd>");
2144 str->appendScalar(this->getTextSize());
2145 str->append("</dd>");
2146
2147 str->append("<dt>TextScaleX:</dt><dd>");
2148 str->appendScalar(this->getTextScaleX());
2149 str->append("</dd>");
2150
2151 str->append("<dt>TextSkewX:</dt><dd>");
2152 str->appendScalar(this->getTextSkewX());
2153 str->append("</dd>");
2154
2155 SkPathEffect* pathEffect = this->getPathEffect();
2156 if (pathEffect) {
2157 str->append("<dt>PathEffect:</dt><dd>");
2158 pathEffect->toString(str);
2159 str->append("</dd>");
2160 }
2161
2162 SkShader* shader = this->getShader();
2163 if (shader) {
2164 str->append("<dt>Shader:</dt><dd>");
2165 shader->toString(str);
2166 str->append("</dd>");
2167 }
2168
2169 SkXfermode* xfer = this->getXfermode();
2170 if (xfer) {
2171 str->append("<dt>Xfermode:</dt><dd>");
2172 xfer->toString(str);
2173 str->append("</dd>");
2174 }
2175
2176 SkMaskFilter* maskFilter = this->getMaskFilter();
2177 if (maskFilter) {
2178 str->append("<dt>MaskFilter:</dt><dd>");
2179 maskFilter->toString(str);
2180 str->append("</dd>");
2181 }
2182
2183 SkColorFilter* colorFilter = this->getColorFilter();
2184 if (colorFilter) {
2185 str->append("<dt>ColorFilter:</dt><dd>");
2186 colorFilter->toString(str);
2187 str->append("</dd>");
2188 }
2189
2190 SkRasterizer* rasterizer = this->getRasterizer();
2191 if (rasterizer) {
2192 str->append("<dt>Rasterizer:</dt><dd>");
2193 str->append("</dd>");
2194 }
2195
2196 SkDrawLooper* looper = this->getLooper();
2197 if (looper) {
2198 str->append("<dt>DrawLooper:</dt><dd>");
2199 looper->toString(str);
2200 str->append("</dd>");
2201 }
2202
2203 SkImageFilter* imageFilter = this->getImageFilter();
2204 if (imageFilter) {
2205 str->append("<dt>ImageFilter:</dt><dd>");
2206 imageFilter->toString(str);
2207 str->append("</dd>");
2208 }
2209
2210 SkAnnotation* annotation = this->getAnnotation();
2211 if (annotation) {
2212 str->append("<dt>Annotation:</dt><dd>");
2213 str->append("</dd>");
2214 }
2215
2216 str->append("<dt>Color:</dt><dd>0x");
2217 SkColor color = this->getColor();
2218 str->appendHex(color);
2219 str->append("</dd>");
2220
2221 str->append("<dt>Stroke Width:</dt><dd>");
2222 str->appendScalar(this->getStrokeWidth());
2223 str->append("</dd>");
2224
2225 str->append("<dt>Stroke Miter:</dt><dd>");
2226 str->appendScalar(this->getStrokeMiter());
2227 str->append("</dd>");
2228
2229 str->append("<dt>Flags:</dt><dd>(");
2230 if (this->getFlags()) {
2231 bool needSeparator = false;
2232 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2233 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2234 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2235 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2236 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2237 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2238 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2239 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2240 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2241 SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2242 "EmbeddedBitmapText", &needSeparator);
2243 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2244 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2245 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2246 "GenA8FromLCD", &needSeparator);
2247 } else {
2248 str->append("None");
2249 }
2250 str->append(")</dd>");
2251
2252 str->append("<dt>FilterLevel:</dt><dd>");
2253 static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" };
2254 str->append(gFilterQualityStrings[this->getFilterQuality()]);
2255 str->append("</dd>");
2256
2257 str->append("<dt>TextAlign:</dt><dd>");
2258 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2259 str->append(gTextAlignStrings[this->getTextAlign()]);
2260 str->append("</dd>");
2261
2262 str->append("<dt>CapType:</dt><dd>");
2263 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2264 str->append(gStrokeCapStrings[this->getStrokeCap()]);
2265 str->append("</dd>");
2266
2267 str->append("<dt>JoinType:</dt><dd>");
2268 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2269 str->append(gJoinStrings[this->getStrokeJoin()]);
2270 str->append("</dd>");
2271
2272 str->append("<dt>Style:</dt><dd>");
2273 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2274 str->append(gStyleStrings[this->getStyle()]);
2275 str->append("</dd>");
2276
2277 str->append("<dt>TextEncoding:</dt><dd>");
2278 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2279 str->append(gTextEncodingStrings[this->getTextEncoding()]);
2280 str->append("</dd>");
2281
2282 str->append("<dt>Hinting:</dt><dd>");
2283 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2284 str->append(gHintingStrings[this->getHinting()]);
2285 str->append("</dd>");
2286
2287 str->append("</dd></dl></dl>");
2288 }
2289 #endif
2290
2291 ///////////////////////////////////////////////////////////////////////////////
2292
has_thick_frame(const SkPaint & paint)2293 static bool has_thick_frame(const SkPaint& paint) {
2294 return paint.getStrokeWidth() > 0 &&
2295 paint.getStyle() != SkPaint::kFill_Style;
2296 }
2297
SkTextToPathIter(const char text[],size_t length,const SkPaint & paint,bool applyStrokeAndPathEffects)2298 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
2299 const SkPaint& paint,
2300 bool applyStrokeAndPathEffects)
2301 : fPaint(paint) {
2302 fGlyphCacheProc = paint.getMeasureCacheProc(true);
2303
2304 fPaint.setLinearText(true);
2305 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2306
2307 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2308 applyStrokeAndPathEffects = false;
2309 }
2310
2311 // can't use our canonical size if we need to apply patheffects
2312 if (fPaint.getPathEffect() == NULL) {
2313 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2314 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2315 if (has_thick_frame(fPaint)) {
2316 fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale);
2317 }
2318 } else {
2319 fScale = SK_Scalar1;
2320 }
2321
2322 if (!applyStrokeAndPathEffects) {
2323 fPaint.setStyle(SkPaint::kFill_Style);
2324 fPaint.setPathEffect(NULL);
2325 }
2326
2327 fCache = fPaint.detachCache(NULL, NULL, false);
2328
2329 SkPaint::Style style = SkPaint::kFill_Style;
2330 SkPathEffect* pe = NULL;
2331
2332 if (!applyStrokeAndPathEffects) {
2333 style = paint.getStyle(); // restore
2334 pe = paint.getPathEffect(); // restore
2335 }
2336 fPaint.setStyle(style);
2337 fPaint.setPathEffect(pe);
2338 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
2339
2340 // now compute fXOffset if needed
2341
2342 SkScalar xOffset = 0;
2343 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2344 int count;
2345 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
2346 &count, NULL), fScale);
2347 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2348 width = SkScalarHalf(width);
2349 }
2350 xOffset = -width;
2351 }
2352 fXPos = xOffset;
2353 fPrevAdvance = 0;
2354
2355 fText = text;
2356 fStop = text + length;
2357
2358 fXYIndex = paint.isVerticalText() ? 1 : 0;
2359 }
2360
~SkTextToPathIter()2361 SkTextToPathIter::~SkTextToPathIter() {
2362 SkGlyphCache::AttachCache(fCache);
2363 }
2364
next(const SkPath ** path,SkScalar * xpos)2365 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2366 if (fText < fStop) {
2367 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2368
2369 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2370 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2371
2372 if (glyph.fWidth) {
2373 if (path) {
2374 *path = fCache->findPath(glyph);
2375 }
2376 } else {
2377 if (path) {
2378 *path = NULL;
2379 }
2380 }
2381 if (xpos) {
2382 *xpos = fXPos;
2383 }
2384 return true;
2385 }
2386 return false;
2387 }
2388
2389 ///////////////////////////////////////////////////////////////////////////////
2390
2391 // return true if the filter exists, and may affect alpha
affects_alpha(const SkColorFilter * cf)2392 static bool affects_alpha(const SkColorFilter* cf) {
2393 return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
2394 }
2395
2396 // return true if the filter exists, and may affect alpha
affects_alpha(const SkImageFilter * imf)2397 static bool affects_alpha(const SkImageFilter* imf) {
2398 // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
2399 // ala colorfilters
2400 return imf != NULL;
2401 }
2402
nothingToDraw() const2403 bool SkPaint::nothingToDraw() const {
2404 if (fLooper) {
2405 return false;
2406 }
2407 SkXfermode::Mode mode;
2408 if (SkXfermode::AsMode(fXfermode, &mode)) {
2409 switch (mode) {
2410 case SkXfermode::kSrcOver_Mode:
2411 case SkXfermode::kSrcATop_Mode:
2412 case SkXfermode::kDstOut_Mode:
2413 case SkXfermode::kDstOver_Mode:
2414 case SkXfermode::kPlus_Mode:
2415 if (0 == this->getAlpha()) {
2416 return !affects_alpha(fColorFilter) && !affects_alpha(fImageFilter);
2417 }
2418 break;
2419 case SkXfermode::kDst_Mode:
2420 return true;
2421 default:
2422 break;
2423 }
2424 }
2425 return false;
2426 }
2427
getHash() const2428 uint32_t SkPaint::getHash() const {
2429 // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
2430 // so fBitfields should be 10 pointers and 6 32-bit values from the start.
2431 SK_COMPILE_ASSERT(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t),
2432 SkPaint_notPackedTightly);
2433 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this),
2434 offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
2435 }
2436