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