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