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