gfx/skia/trunk/src/core/SkPaint.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:a5884c28b5b8
1
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 */
8
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"
37
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 };
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
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));
76
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
92
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 }
109
110 SkPaint::SkPaint(const SkPaint& src) {
111 memcpy(this, &src, sizeof(src));
112
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);
123
124 #ifdef SK_BUILD_FOR_ANDROID
125 new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
126 #endif
127 }
128
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 }
141
142 SkPaint& SkPaint::operator=(const SkPaint& src) {
143 SkASSERT(&src);
144
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);
155
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);
166
167 #ifdef SK_BUILD_FOR_ANDROID
168 fPaintOptionsAndroid.~SkPaintOptionsAndroid();
169
170 uint32_t oldGenerationID = fGenerationID;
171 #endif
172 memcpy(this, &src, sizeof(src));
173 #ifdef SK_BUILD_FOR_ANDROID
174 fGenerationID = oldGenerationID + 1;
175
176 new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
177 #endif
178
179 return *this;
180 }
181
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 }
190
191 void SkPaint::reset() {
192 SkPaint init;
193
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 }
202
203 #ifdef SK_BUILD_FOR_ANDROID
204 uint32_t SkPaint::getGenerationID() const {
205 return fGenerationID;
206 }
207
208 void SkPaint::setGenerationID(uint32_t generationID) {
209 fGenerationID = generationID;
210 }
211
212 unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
213 SkAutoGlyphCache autoCache(*this, NULL, NULL);
214 SkGlyphCache* cache = autoCache.getCache();
215 return cache->getBaseGlyphCount(text);
216 }
217
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
226
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 }
237
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 }
249
250 void SkPaint::setHinting(Hinting hintingLevel) {
251 GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
252 fHinting = hintingLevel;
253 fDirtyBits |= kBitfields_DirtyBit;
254 }
255
256 void SkPaint::setFlags(uint32_t flags) {
257 GEN_ID_INC_EVAL(fFlags != flags);
258 fFlags = flags;
259 fDirtyBits |= kBitfields_DirtyBit;
260 }
261
262 void SkPaint::setAntiAlias(bool doAA) {
263 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
264 }
265
266 void SkPaint::setDither(bool doDither) {
267 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
268 }
269
270 void SkPaint::setSubpixelText(bool doSubpixel) {
271 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
272 }
273
274 void SkPaint::setLCDRenderText(bool doLCDRender) {
275 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
276 }
277
278 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
279 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
280 }
281
282 void SkPaint::setAutohinted(bool useAutohinter) {
283 this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
284 }
285
286 void SkPaint::setLinearText(bool doLinearText) {
287 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
288 }
289
290 void SkPaint::setVerticalText(bool doVertical) {
291 this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
292 }
293
294 void SkPaint::setUnderlineText(bool doUnderline) {
295 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
296 }
297
298 void SkPaint::setStrikeThruText(bool doStrikeThru) {
299 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
300 }
301
302 void SkPaint::setFakeBoldText(bool doFakeBold) {
303 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
304 }
305
306 void SkPaint::setDevKernText(bool doDevKern) {
307 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
308 }
309
310 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
311 this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
312 }
313
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 }
325
326 void SkPaint::setColor(SkColor color) {
327 GEN_ID_INC_EVAL(color != fColor);
328 fColor = color;
329 fDirtyBits |= kColor_DirtyBit;
330 }
331
332 void SkPaint::setAlpha(U8CPU a) {
333 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
334 SkColorGetG(fColor), SkColorGetB(fColor)));
335 }
336
337 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
338 this->setColor(SkColorSetARGB(a, r, g, b));
339 }
340
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 }
352
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 }
364
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 }
376
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 }
388
389 ///////////////////////////////////////////////////////////////////////////////
390
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 }
402
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 }
414
415 void SkPaint::setTextScaleX(SkScalar scaleX) {
416 GEN_ID_INC_EVAL(scaleX != fTextScaleX);
417 fTextScaleX = scaleX;
418 fDirtyBits |= kTextScaleX_DirtyBit;
419 }
420
421 void SkPaint::setTextSkewX(SkScalar skewX) {
422 GEN_ID_INC_EVAL(skewX != fTextSkewX);
423 fTextSkewX = skewX;
424 fDirtyBits |= kTextSkewX_DirtyBit;
425 }
426
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 }
438
439 ///////////////////////////////////////////////////////////////////////////////
440
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 }
445
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 }
452
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 }
459
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 }
466
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 }
473
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 }
480
481 ///////////////////////////////////////////////////////////////////////////////
482
483 static SkScalar mag2(SkScalar x, SkScalar y) {
484 return x * x + y * y;
485 }
486
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 }
492
493 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
494 SkASSERT(!ctm.hasPerspective());
495 SkASSERT(!textM.hasPerspective());
496
497 SkMatrix matrix;
498 matrix.setConcat(ctm, textM);
499 return tooBig(matrix, MaxCacheSize2());
500 }
501
502 bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
503 SkMatrix textM;
504 return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
505 }
506
507 bool SkPaint::tooBigToUseCache() const {
508 SkMatrix textM;
509 return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
510 }
511
512 ///////////////////////////////////////////////////////////////////////////////
513
514 #include "SkGlyphCache.h"
515 #include "SkUtils.h"
516
517 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
518 void* context) {
519 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
520 }
521
522 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
523 uint16_t glyphs[]) const {
524 if (byteLength == 0) {
525 return 0;
526 }
527
528 SkASSERT(textData != NULL);
529
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 }
546
547 // if we get here, we have a valid glyphs[] array, so time to fill it in
548
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 }
555
556 SkAutoGlyphCache autoCache(*this, NULL, NULL);
557 SkGlyphCache* cache = autoCache.getCache();
558
559 const char* text = (const char*)textData;
560 const char* stop = text + byteLength;
561 uint16_t* gptr = glyphs;
562
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 }
590
591 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
592 if (0 == byteLength) {
593 return true;
594 }
595
596 SkASSERT(textData != NULL);
597
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 }
609
610 SkAutoGlyphCache autoCache(*this, NULL, NULL);
611 SkGlyphCache* cache = autoCache.getCache();
612
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 }
650
651 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
652 SkUnichar textData[]) const {
653 if (count <= 0) {
654 return;
655 }
656
657 SkASSERT(glyphs != NULL);
658 SkASSERT(textData != NULL);
659
660 SkAutoGlyphCache autoCache(*this, NULL, NULL);
661 SkGlyphCache* cache = autoCache.getCache();
662
663 for (int index = 0; index < count; index++) {
664 textData[index] = cache->glyphToUnichar(glyphs[index]);
665 }
666 }
667
668 ///////////////////////////////////////////////////////////////////////////////
669
670 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
671 const char** text) {
672 SkASSERT(cache != NULL);
673 SkASSERT(text != NULL);
674
675 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
676 }
677
678 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
679 const char** text) {
680 SkASSERT(cache != NULL);
681 SkASSERT(text != NULL);
682
683 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
684 }
685
686 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
687 const char** text) {
688 SkASSERT(cache != NULL);
689 SkASSERT(text != NULL);
690
691 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
692 }
693
694 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
695 const char** text) {
696 SkASSERT(cache != NULL);
697 SkASSERT(text != NULL);
698
699 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
700 }
701
702 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
703 const char** text) {
704 SkASSERT(cache != NULL);
705 SkASSERT(text != NULL);
706
707 const int32_t* ptr = *(const int32_t**)text;
708 SkUnichar uni = *ptr++;
709 *text = (const char*)ptr;
710 return cache->getUnicharMetrics(uni);
711 }
712
713 static const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
714 const char** text) {
715 SkASSERT(cache != NULL);
716 SkASSERT(text != NULL);
717
718 const int32_t* ptr = *(const int32_t**)text;
719 SkUnichar uni = *--ptr;
720 *text = (const char*)ptr;
721 return cache->getUnicharMetrics(uni);
722 }
723
724 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
725 const char** text) {
726 SkASSERT(cache != NULL);
727 SkASSERT(text != NULL);
728
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 }
735
736 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
737 const char** text) {
738 SkASSERT(cache != NULL);
739 SkASSERT(text != NULL);
740
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 }
747
748 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
749 const char** text) {
750 SkASSERT(cache != NULL);
751 SkASSERT(text != NULL);
752
753 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
754 }
755
756 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
757 const char** text) {
758 SkASSERT(cache != NULL);
759 SkASSERT(text != NULL);
760
761 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
762 }
763
764 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
765 const char** text) {
766 SkASSERT(cache != NULL);
767 SkASSERT(text != NULL);
768
769 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
770 }
771
772 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
773 const char** text) {
774 SkASSERT(cache != NULL);
775 SkASSERT(text != NULL);
776
777 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
778 }
779
780 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
781 const char** text) {
782 SkASSERT(cache != NULL);
783 SkASSERT(text != NULL);
784
785 const int32_t* ptr = *(const int32_t**)text;
786 SkUnichar uni = *ptr++;
787 *text = (const char*)ptr;
788 return cache->getUnicharAdvance(uni);
789 }
790
791 static const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
792 const char** text) {
793 SkASSERT(cache != NULL);
794 SkASSERT(text != NULL);
795
796 const int32_t* ptr = *(const int32_t**)text;
797 SkUnichar uni = *--ptr;
798 *text = (const char*)ptr;
799 return cache->getUnicharAdvance(uni);
800 }
801
802 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
803 const char** text) {
804 SkASSERT(cache != NULL);
805 SkASSERT(text != NULL);
806
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 }
813
814 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
815 const char** text) {
816 SkASSERT(cache != NULL);
817 SkASSERT(text != NULL);
818
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 }
825
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,
833
834 sk_getMetrics_utf8_prev,
835 sk_getMetrics_utf16_prev,
836 sk_getMetrics_utf32_prev,
837 sk_getMetrics_glyph_prev,
838
839 sk_getAdvance_utf8_next,
840 sk_getAdvance_utf16_next,
841 sk_getAdvance_utf32_next,
842 sk_getAdvance_glyph_next,
843
844 sk_getAdvance_utf8_prev,
845 sk_getAdvance_utf16_prev,
846 sk_getAdvance_utf32_prev,
847 sk_getAdvance_glyph_prev
848 };
849
850 unsigned index = this->getTextEncoding();
851
852 if (kBackward_TextBufferDirection == tbd) {
853 index += 4;
854 }
855 if (!needFullMetrics && !this->isDevKernText()) {
856 index += 8;
857 }
858
859 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
860 return gMeasureCacheProcs[index];
861 }
862
863 ///////////////////////////////////////////////////////////////////////////////
864
865 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
866 const char** text, SkFixed, SkFixed) {
867 SkASSERT(cache != NULL);
868 SkASSERT(text != NULL);
869
870 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
871 }
872
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);
877
878 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
879 }
880
881 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
882 const char** text, SkFixed, SkFixed) {
883 SkASSERT(cache != NULL);
884 SkASSERT(text != NULL);
885
886 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
887 }
888
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);
893
894 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
895 x, y);
896 }
897
898 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
899 const char** text, SkFixed, SkFixed) {
900 SkASSERT(cache != NULL);
901 SkASSERT(text != NULL);
902
903 const int32_t* ptr = *(const int32_t**)text;
904 SkUnichar uni = *ptr++;
905 *text = (const char*)ptr;
906 return cache->getUnicharMetrics(uni);
907 }
908
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);
913
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 }
919
920 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
921 const char** text, SkFixed, SkFixed) {
922 SkASSERT(cache != NULL);
923 SkASSERT(text != NULL);
924
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 }
931
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);
936
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 }
943
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,
950
951 sk_getMetrics_utf8_xy,
952 sk_getMetrics_utf16_xy,
953 sk_getMetrics_utf32_xy,
954 sk_getMetrics_glyph_xy
955 };
956
957 unsigned index = this->getTextEncoding();
958 if (fFlags & kSubpixelText_Flag) {
959 index += 4;
960 }
961
962 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
963 return gDrawCacheProcs[index];
964 }
965
966 ///////////////////////////////////////////////////////////////////////////////
967
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 )
975
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;
982
983 this->setFlags(flags);
984 this->setHinting(SkPaint::kNo_Hinting);
985
986 SkScalar textSize = fTextSize;
987 this->setTextSize(kCanonicalTextSizeForPaths);
988 return textSize / kCanonicalTextSizeForPaths;
989 }
990
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 }
1000
1001 const SkPaint& getPaint() const { return *fPaint; }
1002
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; }
1008
1009 private:
1010 const SkPaint* fPaint;
1011 SkScalar fScale;
1012 SkTLazy<SkPaint> fLazy;
1013 };
1014
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 }
1021
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;
1025
1026 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
1027 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
1028 }
1029
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 }
1037
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 }
1045
1046 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
1047
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 }
1053
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 }
1065
1066 SkMeasureCacheProc glyphCacheProc;
1067 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1068 NULL != bounds);
1069
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 }
1079
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);
1087
1088 SkAutoKern autokern;
1089
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);
1123
1124 *count = n;
1125 return Sk48Dot16ToScalar(x);
1126 }
1127
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);
1132
1133 SkCanonicalizePaint canon(*this);
1134 const SkPaint& paint = canon.getPaint();
1135 SkScalar scale = canon.getScale();
1136
1137 SkMatrix zoomMatrix, *zoomPtr = NULL;
1138 if (zoom) {
1139 zoomMatrix.setScale(zoom, zoom);
1140 zoomPtr = &zoomMatrix;
1141 }
1142
1143 SkAutoGlyphCache autoCache(paint, NULL, zoomPtr);
1144 SkGlyphCache* cache = autoCache.getCache();
1145
1146 SkScalar width = 0;
1147
1148 if (length > 0) {
1149 int tempCount;
1150
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 }
1167
1168 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
1169
1170 static bool forward_textBufferPred(const char* text, const char* stop) {
1171 return text < stop;
1172 }
1173
1174 static bool backward_textBufferPred(const char* text, const char* stop) {
1175 return text > stop;
1176 }
1177
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 }
1191
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 }
1201
1202 if (0 == fTextSize) {
1203 if (measuredWidth) {
1204 *measuredWidth = 0;
1205 }
1206 return length;
1207 }
1208
1209 SkASSERT(textD != NULL);
1210 const char* text = (const char*)textD;
1211
1212 SkCanonicalizePaint canon(*this);
1213 const SkPaint& paint = canon.getPaint();
1214 SkScalar scale = canon.getScale();
1215
1216 // adjust max in case we changed the textSize in paint
1217 if (scale) {
1218 maxWidth /= scale;
1219 }
1220
1221 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1222 SkGlyphCache* cache = autoCache.getCache();
1223
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;
1231
1232 SkAutoKern autokern;
1233
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 }
1258
1259 if (measuredWidth) {
1260 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1261 if (scale) {
1262 scalarWidth = SkScalarMul(scalarWidth, scale);
1263 }
1264 *measuredWidth = scalarWidth;
1265 }
1266
1267 // return the number of bytes measured
1268 return (kForward_TextBufferDirection == tbd) ?
1269 text - stop + length : stop - text + length;
1270 }
1271
1272 ///////////////////////////////////////////////////////////////////////////////
1273
1274 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1275 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1276 return false; // don't detach the cache
1277 }
1278
1279 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1280 void* context) {
1281 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1282 }
1283
1284 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1285 SkCanonicalizePaint canon(*this);
1286 const SkPaint& paint = canon.getPaint();
1287 SkScalar scale = canon.getScale();
1288
1289 SkMatrix zoomMatrix, *zoomPtr = NULL;
1290 if (zoom) {
1291 zoomMatrix.setScale(zoom, zoom);
1292 zoomPtr = &zoomMatrix;
1293 }
1294
1295 FontMetrics storage;
1296 if (NULL == metrics) {
1297 metrics = &storage;
1298 }
1299
1300 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1301
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 }
1317
1318 ///////////////////////////////////////////////////////////////////////////////
1319
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 }
1326
1327 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1328 SkScalar widths[], SkRect bounds[]) const {
1329 if (0 == byteLength) {
1330 return 0;
1331 }
1332
1333 SkASSERT(NULL != textData);
1334
1335 if (NULL == widths && NULL == bounds) {
1336 return this->countText(textData, byteLength);
1337 }
1338
1339 SkCanonicalizePaint canon(*this);
1340 const SkPaint& paint = canon.getPaint();
1341 SkScalar scale = canon.getScale();
1342
1343 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1344 SkGlyphCache* cache = autoCache.getCache();
1345 SkMeasureCacheProc glyphCacheProc;
1346 glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
1347 NULL != bounds);
1348
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;
1353
1354 if (this->isDevKernText()) {
1355 // we adjust the widths returned here through auto-kerning
1356 SkAutoKern autokern;
1357 SkFixed prevWidth = 0;
1358
1359 if (scale) {
1360 while (text < stop) {
1361 const SkGlyph& g = glyphCacheProc(cache, &text);
1362 if (widths) {
1363 SkFixed adjust = autokern.adjust(g);
1364
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);
1384
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 }
1425
1426 SkASSERT(text == stop);
1427 return count;
1428 }
1429
1430 ///////////////////////////////////////////////////////////////////////////////
1431
1432 #include "SkDraw.h"
1433
1434 void SkPaint::getTextPath(const void* textData, size_t length,
1435 SkScalar x, SkScalar y, SkPath* path) const {
1436 SkASSERT(length == 0 || textData != NULL);
1437
1438 const char* text = (const char*)textData;
1439 if (text == NULL || length == 0 || path == NULL) {
1440 return;
1441 }
1442
1443 SkTextToPathIter iter(text, length, *this, false);
1444 SkMatrix matrix;
1445 SkScalar prevXPos = 0;
1446
1447 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1448 matrix.postTranslate(x, y);
1449 path->reset();
1450
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 }
1461
1462 void SkPaint::getPosTextPath(const void* textData, size_t length,
1463 const SkPoint pos[], SkPath* path) const {
1464 SkASSERT(length == 0 || textData != NULL);
1465
1466 const char* text = (const char*)textData;
1467 if (text == NULL || length == 0 || path == NULL) {
1468 return;
1469 }
1470
1471 SkTextToPathIter iter(text, length, *this, false);
1472 SkMatrix matrix;
1473 SkPoint prevPos;
1474 prevPos.set(0, 0);
1475
1476 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1477 path->reset();
1478
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 }
1490
1491 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1492 SkWriteBuffer* buffer) {
1493 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
1494 }
1495
1496 // SkFontHost can override this choice in FilterRec()
1497 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1498 uint32_t flags = paint.getFlags();
1499
1500 // Antialiasing being disabled trumps all other settings.
1501 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1502 return SkMask::kBW_Format;
1503 }
1504
1505 if (flags & SkPaint::kLCDRenderText_Flag) {
1506 return SkMask::kLCD16_Format;
1507 }
1508
1509 return SkMask::kA8_Format;
1510 }
1511
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 }
1521
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 }
1537
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 }
1545
1546 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1547
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
1553
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 }
1560
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 }
1570
1571 void SkScalerContext::MakeRec(const SkPaint& paint,
1572 const SkDeviceProperties* deviceProperties,
1573 const SkMatrix* deviceMatrix,
1574 Rec* rec) {
1575 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1576
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();
1586
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 }
1596
1597 SkPaint::Style style = paint.getStyle();
1598 SkScalar strokeWidth = paint.getStrokeWidth();
1599
1600 unsigned flags = 0;
1601
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);
1611
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 }
1620
1621 if (paint.isDevKernText()) {
1622 flags |= SkScalerContext::kDevKernText_Flag;
1623 }
1624
1625 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1626 rec->fFrameWidth = strokeWidth;
1627 rec->fMiterLimit = paint.getStrokeMiter();
1628 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1629
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 }
1638
1639 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1640
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 }
1657
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);
1674
1675 // these modify fFlags, so do them after assigning fFlags
1676 rec->setHinting(computeHinting(paint));
1677
1678 rec->setLuminanceColor(computeLuminanceColor(paint));
1679
1680 if (NULL == deviceProperties) {
1681 rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1682 rec->setPaintGamma(SK_GAMMA_EXPONENT);
1683 } else {
1684 rec->setDeviceGamma(deviceProperties->fGamma);
1685
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 }
1692
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
1704
1705 rec->fReservedAlign = 0;
1706
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);
1713
1714 // be sure to call PostMakeRec(rec) before you actually use it!
1715 }
1716
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);
1723
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 }
1749
1750 /*static*/ void SkPaint::Term() {
1751 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1752
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 }
1761
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
1782
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 }
1790
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 }
1802
1803 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1804
1805 #ifdef SK_DEBUG
1806 #define TEST_DESC
1807 #endif
1808
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;
1821
1822 SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
1823 if (ignoreGamma) {
1824 rec.setLuminanceColor(0);
1825 }
1826
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();
1832
1833 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1834
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 }
1859
1860 #ifdef SK_BUILD_FOR_ANDROID
1861 SkWriteBuffer androidBuffer;
1862 fPaintOptionsAndroid.flatten(androidBuffer);
1863 descSize += androidBuffer.bytesWritten();
1864 entryCount += 1;
1865 #endif
1866
1867 ///////////////////////////////////////////////////////////////////////////
1868 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1869 SkScalerContext::PostMakeRec(*this, &rec);
1870
1871 descSize += SkDescriptor::ComputeOverhead(entryCount);
1872
1873 SkAutoDescriptor ad(descSize);
1874 SkDescriptor* desc = ad.getDesc();
1875
1876 desc->init();
1877 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1878
1879 #ifdef SK_BUILD_FOR_ANDROID
1880 add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1881 #endif
1882
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 }
1892
1893 SkASSERT(descSize == desc->getLength());
1894 desc->computeChecksum();
1895
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();
1908
1909 memset(desc1, 0x00, descSize);
1910 memset(desc2, 0xFF, descSize);
1911
1912 desc1->init();
1913 desc2->init();
1914 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1915 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1916
1917 #ifdef SK_BUILD_FOR_ANDROID
1918 add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1919 add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1920 #endif
1921
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 }
1934
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
1943
1944 proc(fTypeface, desc, context);
1945 }
1946
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 }
1953
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 }
1965
1966 ///////////////////////////////////////////////////////////////////////////////
1967
1968 #include "SkStream.h"
1969
1970 static uintptr_t asint(const void* p) {
1971 return reinterpret_cast<uintptr_t>(p);
1972 }
1973
1974 union Scalar32 {
1975 SkScalar fScalar;
1976 uint32_t f32;
1977 };
1978
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 }
1986
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 }
1993
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 }
2001
2002 enum FlatFlags {
2003 kHasTypeface_FlatFlag = 0x01,
2004 kHasEffects_FlatFlag = 0x02,
2005 kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
2006 };
2007
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);
2013
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
2038
2039 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
2040 uint32_t* ptr = buffer.reserve(kPODPaintSize);
2041
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());
2057
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());
2072
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 }
2086
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);
2092
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++);
2100
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);
2105
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));
2109
2110 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
2111
2112 flatFlags = tmp & 0xFF;
2113
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));
2119
2120 if (flatFlags & kHasTypeface_FlatFlag) {
2121 this->setTypeface(buffer.readTypeface());
2122 } else {
2123 this->setTypeface(NULL);
2124 }
2125
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()));
2135
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 }
2149
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 }
2161
2162 ///////////////////////////////////////////////////////////////////////////////
2163
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 }
2170
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 }
2177
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 }
2184
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 }
2192
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 }
2199
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 }
2206
2207 ///////////////////////////////////////////////////////////////////////////////
2208
2209 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
2210 const SkRect* cullRect) const {
2211 SkStrokeRec rec(*this);
2212
2213 const SkPath* srcPtr = &src;
2214 SkPath tmpPath;
2215
2216 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2217 srcPtr = &tmpPath;
2218 }
2219
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 }
2233
2234 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2235 SkRect* storage,
2236 Style style) const {
2237 SkASSERT(storage);
2238
2239 const SkRect* src = &origSrc;
2240
2241 if (this->getLooper()) {
2242 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2243 this->getLooper()->computeFastBounds(*this, *src, storage);
2244 return *storage;
2245 }
2246
2247 SkRect tmpSrc;
2248 if (this->getPathEffect()) {
2249 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2250 src = &tmpSrc;
2251 }
2252
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 }
2269
2270 if (this->getMaskFilter()) {
2271 this->getMaskFilter()->computeFastBounds(*storage, storage);
2272 }
2273
2274 if (this->getImageFilter()) {
2275 this->getImageFilter()->computeFastBounds(*storage, storage);
2276 }
2277
2278 return *storage;
2279 }
2280
2281 #ifndef SK_IGNORE_TO_STRING
2282 void SkPaint::toString(SkString* str) const {
2283 str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2284
2285 SkTypeface* typeface = this->getTypeface();
2286 if (NULL != typeface) {
2287 SkDynamicMemoryWStream ostream;
2288 typeface->serialize(&ostream);
2289 SkAutoTUnref<SkData> data(ostream.copyToData());
2290
2291 SkMemoryStream stream(data);
2292 SkFontDescriptor descriptor(&stream);
2293
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 }
2304
2305 str->append("<dt>TextSize:</dt><dd>");
2306 str->appendScalar(this->getTextSize());
2307 str->append("</dd>");
2308
2309 str->append("<dt>TextScaleX:</dt><dd>");
2310 str->appendScalar(this->getTextScaleX());
2311 str->append("</dd>");
2312
2313 str->append("<dt>TextSkewX:</dt><dd>");
2314 str->appendScalar(this->getTextSkewX());
2315 str->append("</dd>");
2316
2317 SkPathEffect* pathEffect = this->getPathEffect();
2318 if (NULL != pathEffect) {
2319 str->append("<dt>PathEffect:</dt><dd>");
2320 str->append("</dd>");
2321 }
2322
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 }
2329
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 }
2336
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 }
2343
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 }
2350
2351 SkRasterizer* rasterizer = this->getRasterizer();
2352 if (NULL != rasterizer) {
2353 str->append("<dt>Rasterizer:</dt><dd>");
2354 str->append("</dd>");
2355 }
2356
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 }
2363
2364 SkImageFilter* imageFilter = this->getImageFilter();
2365 if (NULL != imageFilter) {
2366 str->append("<dt>ImageFilter:</dt><dd>");
2367 str->append("</dd>");
2368 }
2369
2370 SkAnnotation* annotation = this->getAnnotation();
2371 if (NULL != annotation) {
2372 str->append("<dt>Annotation:</dt><dd>");
2373 str->append("</dd>");
2374 }
2375
2376 str->append("<dt>Color:</dt><dd>0x");
2377 SkColor color = this->getColor();
2378 str->appendHex(color);
2379 str->append("</dd>");
2380
2381 str->append("<dt>Stroke Width:</dt><dd>");
2382 str->appendScalar(this->getStrokeWidth());
2383 str->append("</dd>");
2384
2385 str->append("<dt>Stroke Miter:</dt><dd>");
2386 str->appendScalar(this->getStrokeMiter());
2387 str->append("</dd>");
2388
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>");
2411
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>");
2416
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>");
2421
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>");
2426
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>");
2431
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>");
2436
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>");
2441
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>");
2446
2447 str->append("</dd></dl></dl>");
2448 }
2449 #endif
2450
2451 ///////////////////////////////////////////////////////////////////////////////
2452
2453 static bool has_thick_frame(const SkPaint& paint) {
2454 return paint.getStrokeWidth() > 0 &&
2455 paint.getStyle() != SkPaint::kFill_Style;
2456 }
2457
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);
2464
2465 fPaint.setLinearText(true);
2466 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2467
2468 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2469 applyStrokeAndPathEffects = false;
2470 }
2471
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 }
2482
2483 if (!applyStrokeAndPathEffects) {
2484 fPaint.setStyle(SkPaint::kFill_Style);
2485 fPaint.setPathEffect(NULL);
2486 }
2487
2488 fCache = fPaint.detachCache(NULL, NULL);
2489
2490 SkPaint::Style style = SkPaint::kFill_Style;
2491 SkPathEffect* pe = NULL;
2492
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
2500
2501 // now compute fXOffset if needed
2502
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;
2515
2516 fText = text;
2517 fStop = text + length;
2518
2519 fXYIndex = paint.isVerticalText() ? 1 : 0;
2520 }
2521
2522 SkTextToPathIter::~SkTextToPathIter() {
2523 SkGlyphCache::AttachCache(fCache);
2524 }
2525
2526 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2527 if (fText < fStop) {
2528 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2529
2530 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2531 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2532
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 }
2549
2550 ///////////////////////////////////////////////////////////////////////////////
2551
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 }
2573
2574 void SkPaint::setBitfields(uint32_t bitfields) {
2575 fBitfields = bitfields;
2576 fDirtyBits |= kBitfields_DirtyBit;
2577 }
2578
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 }
2586
2587 void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
2588 const uint32_t dirty = paint.fDirtyBits;
2589
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 }
2598
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 }
2625
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()
2636
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 }

mercurial