3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #include "SkAnnotation.h"
11 #include "SkAutoKern.h"
12 #include "SkColorFilter.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"
28 #include "SkScalerContext.h"
30 #include "SkStringUtils.h"
32 #include "SkTextFormatParams.h"
33 #include "SkTextToPathIter.h"
35 #include "SkTypeface.h"
36 #include "SkXfermode.h"
39 kColor_DirtyBit = 1 << 0,
40 kTextSize_DirtyBit = 1 << 1,
41 kTextScaleX_DirtyBit = 1 << 2,
42 kTextSkewX_DirtyBit = 1 << 3,
43 kStrokeWidth_DirtyBit = 1 << 4,
44 kStrokeMiter_DirtyBit = 1 << 5,
46 kPOD_DirtyBitMask = 63,
48 kPathEffect_DirtyBit = 1 << 6,
49 kShader_DirtyBit = 1 << 7,
50 kXfermode_DirtyBit = 1 << 8,
51 kMaskFilter_DirtyBit = 1 << 9,
52 kColorFilter_DirtyBit = 1 << 10,
53 kRasterizer_DirtyBit = 1 << 11,
54 kLooper_DirtyBit = 1 << 12,
55 kImageFilter_DirtyBit = 1 << 13,
56 kTypeface_DirtyBit = 1 << 14,
57 kAnnotation_DirtyBit = 1 << 15,
58 kPaintOptionsAndroid_DirtyBit = 1 << 16,
61 // define this to get a printf for out-of-range parameter in setters
62 // e.g. setTextSize(-1)
63 //#define SK_REPORT_API_RANGE_CHECK
65 #ifdef SK_BUILD_FOR_ANDROID
66 #define GEN_ID_INC fGenerationID++
67 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
70 #define GEN_ID_INC_EVAL(expression)
85 fTextSize = SkPaintDefaults_TextSize;
86 fTextScaleX = SK_Scalar1;
88 fColor = SK_ColorBLACK;
90 fMiterLimit = SkPaintDefaults_MiterLimit;
92 // Zero all bitfields, then set some non-zero defaults.
94 fFlags = SkPaintDefaults_Flags;
95 fCapType = kDefault_Cap;
96 fJoinType = kDefault_Join;
97 fTextAlign = kLeft_Align;
99 fTextEncoding = kUTF8_TextEncoding;
100 fHinting = SkPaintDefaults_Hinting;
103 #ifdef SK_BUILD_FOR_ANDROID
104 new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
109 SkPaint::SkPaint(const SkPaint& src) {
110 // Diagnoistic. May remove later. See crbug.com/364224
115 #define COPY(field) field = src.field
116 #define REF_COPY(field) field = SkSafeRef(src.field)
119 REF_COPY(fPathEffect);
122 REF_COPY(fMaskFilter);
123 REF_COPY(fColorFilter);
124 REF_COPY(fRasterizer);
126 REF_COPY(fImageFilter);
127 REF_COPY(fAnnotation);
138 #ifdef SK_BUILD_FOR_ANDROID
139 new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
147 SkPaint::~SkPaint() {
148 SkSafeUnref(fTypeface);
149 SkSafeUnref(fPathEffect);
150 SkSafeUnref(fShader);
151 SkSafeUnref(fXfermode);
152 SkSafeUnref(fMaskFilter);
153 SkSafeUnref(fColorFilter);
154 SkSafeUnref(fRasterizer);
155 SkSafeUnref(fLooper);
156 SkSafeUnref(fImageFilter);
157 SkSafeUnref(fAnnotation);
160 SkPaint& SkPaint::operator=(const SkPaint& src) {
165 #define COPY(field) field = src.field
166 #define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
171 REF_COPY(fPathEffect);
174 REF_COPY(fMaskFilter);
175 REF_COPY(fColorFilter);
176 REF_COPY(fRasterizer);
178 REF_COPY(fImageFilter);
179 REF_COPY(fAnnotation);
190 #ifdef SK_BUILD_FOR_ANDROID
191 fPaintOptionsAndroid.~SkPaintOptionsAndroid();
192 new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
202 bool operator==(const SkPaint& a, const SkPaint& b) {
203 #define EQUAL(field) (a.field == b.field)
204 // Don't check fGenerationID or fDirtyBits, which can be different for logically equal paints.
205 return EQUAL(fTypeface)
206 && EQUAL(fPathEffect)
209 && EQUAL(fMaskFilter)
210 && EQUAL(fColorFilter)
211 && EQUAL(fRasterizer)
213 && EQUAL(fImageFilter)
214 && EQUAL(fAnnotation)
216 && EQUAL(fTextScaleX)
220 && EQUAL(fMiterLimit)
222 #ifdef SK_BUILD_FOR_ANDROID
223 && EQUAL(fPaintOptionsAndroid)
229 void SkPaint::reset() {
232 #ifdef SK_BUILD_FOR_ANDROID
233 uint32_t oldGenerationID = fGenerationID;
236 #ifdef SK_BUILD_FOR_ANDROID
237 fGenerationID = oldGenerationID + 1;
241 #ifdef SK_BUILD_FOR_ANDROID
242 uint32_t SkPaint::getGenerationID() const {
243 return fGenerationID;
246 void SkPaint::setGenerationID(uint32_t generationID) {
247 fGenerationID = generationID;
250 unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
251 SkAutoGlyphCache autoCache(*this, NULL, NULL);
252 SkGlyphCache* cache = autoCache.getCache();
253 return cache->getBaseGlyphCount(text);
256 void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
257 if (options != fPaintOptionsAndroid) {
258 fPaintOptionsAndroid = options;
260 fDirtyBits |= kPaintOptionsAndroid_DirtyBit;
265 void SkPaint::setFilterLevel(FilterLevel level) {
266 GEN_ID_INC_EVAL((unsigned) level != fFilterLevel);
267 fFilterLevel = level;
270 void SkPaint::setHinting(Hinting hintingLevel) {
271 GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
272 fHinting = hintingLevel;
275 void SkPaint::setFlags(uint32_t flags) {
276 GEN_ID_INC_EVAL(fFlags != flags);
280 void SkPaint::setAntiAlias(bool doAA) {
281 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
284 void SkPaint::setDither(bool doDither) {
285 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
288 void SkPaint::setSubpixelText(bool doSubpixel) {
289 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
292 void SkPaint::setLCDRenderText(bool doLCDRender) {
293 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
296 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
297 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
300 void SkPaint::setAutohinted(bool useAutohinter) {
301 this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
304 void SkPaint::setLinearText(bool doLinearText) {
305 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
308 void SkPaint::setVerticalText(bool doVertical) {
309 this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
312 void SkPaint::setUnderlineText(bool doUnderline) {
313 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
316 void SkPaint::setStrikeThruText(bool doStrikeThru) {
317 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
320 void SkPaint::setFakeBoldText(bool doFakeBold) {
321 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
324 void SkPaint::setDevKernText(bool doDevKern) {
325 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
328 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
329 this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
332 void SkPaint::setStyle(Style style) {
333 if ((unsigned)style < kStyleCount) {
334 GEN_ID_INC_EVAL((unsigned)style != fStyle);
337 #ifdef SK_REPORT_API_RANGE_CHECK
338 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
343 void SkPaint::setColor(SkColor color) {
344 GEN_ID_INC_EVAL(color != fColor);
346 fDirtyBits |= kColor_DirtyBit;
349 void SkPaint::setAlpha(U8CPU a) {
350 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
351 SkColorGetG(fColor), SkColorGetB(fColor)));
354 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
355 this->setColor(SkColorSetARGB(a, r, g, b));
358 void SkPaint::setStrokeWidth(SkScalar width) {
360 GEN_ID_INC_EVAL(width != fWidth);
362 fDirtyBits |= kStrokeWidth_DirtyBit;
364 #ifdef SK_REPORT_API_RANGE_CHECK
365 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
370 void SkPaint::setStrokeMiter(SkScalar limit) {
372 GEN_ID_INC_EVAL(limit != fMiterLimit);
374 fDirtyBits |= kStrokeMiter_DirtyBit;
376 #ifdef SK_REPORT_API_RANGE_CHECK
377 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
382 void SkPaint::setStrokeCap(Cap ct) {
383 if ((unsigned)ct < kCapCount) {
384 GEN_ID_INC_EVAL((unsigned)ct != fCapType);
385 fCapType = SkToU8(ct);
387 #ifdef SK_REPORT_API_RANGE_CHECK
388 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
393 void SkPaint::setStrokeJoin(Join jt) {
394 if ((unsigned)jt < kJoinCount) {
395 GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
396 fJoinType = SkToU8(jt);
398 #ifdef SK_REPORT_API_RANGE_CHECK
399 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
404 ///////////////////////////////////////////////////////////////////////////////
406 void SkPaint::setTextAlign(Align align) {
407 if ((unsigned)align < kAlignCount) {
408 GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
409 fTextAlign = SkToU8(align);
411 #ifdef SK_REPORT_API_RANGE_CHECK
412 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
417 void SkPaint::setTextSize(SkScalar ts) {
419 GEN_ID_INC_EVAL(ts != fTextSize);
421 fDirtyBits |= kTextSize_DirtyBit;
423 #ifdef SK_REPORT_API_RANGE_CHECK
424 SkDebugf("SkPaint::setTextSize() called with negative value\n");
429 void SkPaint::setTextScaleX(SkScalar scaleX) {
430 GEN_ID_INC_EVAL(scaleX != fTextScaleX);
431 fTextScaleX = scaleX;
432 fDirtyBits |= kTextScaleX_DirtyBit;
435 void SkPaint::setTextSkewX(SkScalar skewX) {
436 GEN_ID_INC_EVAL(skewX != fTextSkewX);
438 fDirtyBits |= kTextSkewX_DirtyBit;
441 void SkPaint::setTextEncoding(TextEncoding encoding) {
442 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
443 GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
444 fTextEncoding = encoding;
446 #ifdef SK_REPORT_API_RANGE_CHECK
447 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
452 ///////////////////////////////////////////////////////////////////////////////
454 // Returns dst with the given bitmask enabled or disabled, depending on value.
455 inline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
456 return value ? (dst | bitmask) : (dst & ~bitmask);
459 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
460 SkRefCnt_SafeAssign(fTypeface, font);
462 fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
466 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
467 SkRefCnt_SafeAssign(fRasterizer, r);
469 fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
473 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
474 SkRefCnt_SafeAssign(fLooper, looper);
476 fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
480 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
481 SkRefCnt_SafeAssign(fImageFilter, imageFilter);
483 fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
487 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
488 SkRefCnt_SafeAssign(fAnnotation, annotation);
490 fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
494 ///////////////////////////////////////////////////////////////////////////////
496 static SkScalar mag2(SkScalar x, SkScalar y) {
497 return x * x + y * y;
500 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
501 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
503 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
506 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
507 SkASSERT(!ctm.hasPerspective());
508 SkASSERT(!textM.hasPerspective());
511 matrix.setConcat(ctm, textM);
512 return tooBig(matrix, MaxCacheSize2());
515 bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
517 return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
520 bool SkPaint::tooBigToUseCache() const {
522 return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
525 ///////////////////////////////////////////////////////////////////////////////
527 #include "SkGlyphCache.h"
530 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
532 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
535 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
536 uint16_t glyphs[]) const {
537 if (byteLength == 0) {
541 SkASSERT(textData != NULL);
543 if (NULL == glyphs) {
544 switch (this->getTextEncoding()) {
545 case kUTF8_TextEncoding:
546 return SkUTF8_CountUnichars((const char*)textData, byteLength);
547 case kUTF16_TextEncoding:
548 return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
549 case kUTF32_TextEncoding:
550 return SkToInt(byteLength >> 2);
551 case kGlyphID_TextEncoding:
552 return SkToInt(byteLength >> 1);
554 SkDEBUGFAIL("unknown text encoding");
559 // if we get here, we have a valid glyphs[] array, so time to fill it in
561 // handle this encoding before the setup for the glyphcache
562 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
563 // we want to ignore the low bit of byteLength
564 memcpy(glyphs, textData, byteLength >> 1 << 1);
565 return SkToInt(byteLength >> 1);
568 SkAutoGlyphCache autoCache(*this, NULL, NULL);
569 SkGlyphCache* cache = autoCache.getCache();
571 const char* text = (const char*)textData;
572 const char* stop = text + byteLength;
573 uint16_t* gptr = glyphs;
575 switch (this->getTextEncoding()) {
576 case SkPaint::kUTF8_TextEncoding:
577 while (text < stop) {
578 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
581 case SkPaint::kUTF16_TextEncoding: {
582 const uint16_t* text16 = (const uint16_t*)text;
583 const uint16_t* stop16 = (const uint16_t*)stop;
584 while (text16 < stop16) {
585 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
589 case kUTF32_TextEncoding: {
590 const int32_t* text32 = (const int32_t*)text;
591 const int32_t* stop32 = (const int32_t*)stop;
592 while (text32 < stop32) {
593 *gptr++ = cache->unicharToGlyph(*text32++);
598 SkDEBUGFAIL("unknown text encoding");
600 return SkToInt(gptr - glyphs);
603 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
604 if (0 == byteLength) {
608 SkASSERT(textData != NULL);
610 // handle this encoding before the setup for the glyphcache
611 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
612 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
613 size_t count = byteLength >> 1;
614 for (size_t i = 0; i < count; i++) {
615 if (0 == glyphID[i]) {
622 SkAutoGlyphCache autoCache(*this, NULL, NULL);
623 SkGlyphCache* cache = autoCache.getCache();
625 switch (this->getTextEncoding()) {
626 case SkPaint::kUTF8_TextEncoding: {
627 const char* text = static_cast<const char*>(textData);
628 const char* stop = text + byteLength;
629 while (text < stop) {
630 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
636 case SkPaint::kUTF16_TextEncoding: {
637 const uint16_t* text = static_cast<const uint16_t*>(textData);
638 const uint16_t* stop = text + (byteLength >> 1);
639 while (text < stop) {
640 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
646 case SkPaint::kUTF32_TextEncoding: {
647 const int32_t* text = static_cast<const int32_t*>(textData);
648 const int32_t* stop = text + (byteLength >> 2);
649 while (text < stop) {
650 if (0 == cache->unicharToGlyph(*text++)) {
657 SkDEBUGFAIL("unknown text encoding");
663 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
664 SkUnichar textData[]) const {
669 SkASSERT(glyphs != NULL);
670 SkASSERT(textData != NULL);
672 SkAutoGlyphCache autoCache(*this, NULL, NULL);
673 SkGlyphCache* cache = autoCache.getCache();
675 for (int index = 0; index < count; index++) {
676 textData[index] = cache->glyphToUnichar(glyphs[index]);
680 ///////////////////////////////////////////////////////////////////////////////
682 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
684 SkASSERT(cache != NULL);
685 SkASSERT(text != NULL);
687 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
690 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
692 SkASSERT(cache != NULL);
693 SkASSERT(text != NULL);
695 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
698 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
700 SkASSERT(cache != NULL);
701 SkASSERT(text != NULL);
703 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
706 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
708 SkASSERT(cache != NULL);
709 SkASSERT(text != NULL);
711 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
714 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
716 SkASSERT(cache != NULL);
717 SkASSERT(text != NULL);
719 const int32_t* ptr = *(const int32_t**)text;
720 SkUnichar uni = *ptr++;
721 *text = (const char*)ptr;
722 return cache->getUnicharMetrics(uni);
725 static const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
727 SkASSERT(cache != NULL);
728 SkASSERT(text != NULL);
730 const int32_t* ptr = *(const int32_t**)text;
731 SkUnichar uni = *--ptr;
732 *text = (const char*)ptr;
733 return cache->getUnicharMetrics(uni);
736 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
738 SkASSERT(cache != NULL);
739 SkASSERT(text != NULL);
741 const uint16_t* ptr = *(const uint16_t**)text;
742 unsigned glyphID = *ptr;
744 *text = (const char*)ptr;
745 return cache->getGlyphIDMetrics(glyphID);
748 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
750 SkASSERT(cache != NULL);
751 SkASSERT(text != NULL);
753 const uint16_t* ptr = *(const uint16_t**)text;
755 unsigned glyphID = *ptr;
756 *text = (const char*)ptr;
757 return cache->getGlyphIDMetrics(glyphID);
760 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
762 SkASSERT(cache != NULL);
763 SkASSERT(text != NULL);
765 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
768 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
770 SkASSERT(cache != NULL);
771 SkASSERT(text != NULL);
773 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
776 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
778 SkASSERT(cache != NULL);
779 SkASSERT(text != NULL);
781 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
784 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
786 SkASSERT(cache != NULL);
787 SkASSERT(text != NULL);
789 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
792 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
794 SkASSERT(cache != NULL);
795 SkASSERT(text != NULL);
797 const int32_t* ptr = *(const int32_t**)text;
798 SkUnichar uni = *ptr++;
799 *text = (const char*)ptr;
800 return cache->getUnicharAdvance(uni);
803 static const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
805 SkASSERT(cache != NULL);
806 SkASSERT(text != NULL);
808 const int32_t* ptr = *(const int32_t**)text;
809 SkUnichar uni = *--ptr;
810 *text = (const char*)ptr;
811 return cache->getUnicharAdvance(uni);
814 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
816 SkASSERT(cache != NULL);
817 SkASSERT(text != NULL);
819 const uint16_t* ptr = *(const uint16_t**)text;
820 unsigned glyphID = *ptr;
822 *text = (const char*)ptr;
823 return cache->getGlyphIDAdvance(glyphID);
826 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
828 SkASSERT(cache != NULL);
829 SkASSERT(text != NULL);
831 const uint16_t* ptr = *(const uint16_t**)text;
833 unsigned glyphID = *ptr;
834 *text = (const char*)ptr;
835 return cache->getGlyphIDAdvance(glyphID);
838 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
839 bool needFullMetrics) const {
840 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
841 sk_getMetrics_utf8_next,
842 sk_getMetrics_utf16_next,
843 sk_getMetrics_utf32_next,
844 sk_getMetrics_glyph_next,
846 sk_getMetrics_utf8_prev,
847 sk_getMetrics_utf16_prev,
848 sk_getMetrics_utf32_prev,
849 sk_getMetrics_glyph_prev,
851 sk_getAdvance_utf8_next,
852 sk_getAdvance_utf16_next,
853 sk_getAdvance_utf32_next,
854 sk_getAdvance_glyph_next,
856 sk_getAdvance_utf8_prev,
857 sk_getAdvance_utf16_prev,
858 sk_getAdvance_utf32_prev,
859 sk_getAdvance_glyph_prev
862 unsigned index = this->getTextEncoding();
864 if (kBackward_TextBufferDirection == tbd) {
867 if (!needFullMetrics && !this->isDevKernText()) {
871 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
872 return gMeasureCacheProcs[index];
875 ///////////////////////////////////////////////////////////////////////////////
877 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
878 const char** text, SkFixed, SkFixed) {
879 SkASSERT(cache != NULL);
880 SkASSERT(text != NULL);
882 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
885 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
886 const char** text, SkFixed x, SkFixed y) {
887 SkASSERT(cache != NULL);
888 SkASSERT(text != NULL);
890 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
893 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
894 const char** text, SkFixed, SkFixed) {
895 SkASSERT(cache != NULL);
896 SkASSERT(text != NULL);
898 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
901 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
902 const char** text, SkFixed x, SkFixed y) {
903 SkASSERT(cache != NULL);
904 SkASSERT(text != NULL);
906 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
910 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
911 const char** text, SkFixed, SkFixed) {
912 SkASSERT(cache != NULL);
913 SkASSERT(text != NULL);
915 const int32_t* ptr = *(const int32_t**)text;
916 SkUnichar uni = *ptr++;
917 *text = (const char*)ptr;
918 return cache->getUnicharMetrics(uni);
921 static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
922 const char** text, SkFixed x, SkFixed y) {
923 SkASSERT(cache != NULL);
924 SkASSERT(text != NULL);
926 const int32_t* ptr = *(const int32_t**)text;
927 SkUnichar uni = *--ptr;
928 *text = (const char*)ptr;
929 return cache->getUnicharMetrics(uni, x, y);
932 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
933 const char** text, SkFixed, SkFixed) {
934 SkASSERT(cache != NULL);
935 SkASSERT(text != NULL);
937 const uint16_t* ptr = *(const uint16_t**)text;
938 unsigned glyphID = *ptr;
940 *text = (const char*)ptr;
941 return cache->getGlyphIDMetrics(glyphID);
944 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
945 const char** text, SkFixed x, SkFixed y) {
946 SkASSERT(cache != NULL);
947 SkASSERT(text != NULL);
949 const uint16_t* ptr = *(const uint16_t**)text;
950 unsigned glyphID = *ptr;
952 *text = (const char*)ptr;
953 return cache->getGlyphIDMetrics(glyphID, x, y);
956 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
957 static const SkDrawCacheProc gDrawCacheProcs[] = {
958 sk_getMetrics_utf8_00,
959 sk_getMetrics_utf16_00,
960 sk_getMetrics_utf32_00,
961 sk_getMetrics_glyph_00,
963 sk_getMetrics_utf8_xy,
964 sk_getMetrics_utf16_xy,
965 sk_getMetrics_utf32_xy,
966 sk_getMetrics_glyph_xy
969 unsigned index = this->getTextEncoding();
970 if (fFlags & kSubpixelText_Flag) {
974 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
975 return gDrawCacheProcs[index];
978 ///////////////////////////////////////////////////////////////////////////////
980 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
981 SkPaint::kDevKernText_Flag | \
982 SkPaint::kLinearText_Flag | \
983 SkPaint::kLCDRenderText_Flag | \
984 SkPaint::kEmbeddedBitmapText_Flag | \
985 SkPaint::kAutoHinting_Flag | \
986 SkPaint::kGenA8FromLCD_Flag )
988 SkScalar SkPaint::setupForAsPaths() {
989 uint32_t flags = this->getFlags();
990 // clear the flags we don't care about
991 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
992 // set the flags we do care about
993 flags |= SkPaint::kSubpixelText_Flag;
995 this->setFlags(flags);
996 this->setHinting(SkPaint::kNo_Hinting);
998 SkScalar textSize = fTextSize;
999 this->setTextSize(kCanonicalTextSizeForPaths);
1000 return textSize / kCanonicalTextSizeForPaths;
1003 class SkCanonicalizePaint {
1005 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
1006 if (paint.isLinearText() || paint.tooBigToUseCache()) {
1007 SkPaint* p = fLazy.set(paint);
1008 fScale = p->setupForAsPaths();
1013 const SkPaint& getPaint() const { return *fPaint; }
1016 * Returns 0 if the paint was unmodified, or the scale factor need to
1017 * the original textSize
1019 SkScalar getScale() const { return fScale; }
1022 const SkPaint* fPaint;
1024 SkTLazy<SkPaint> fLazy;
1027 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
1028 bounds->set(SkIntToScalar(g.fLeft),
1029 SkIntToScalar(g.fTop),
1030 SkIntToScalar(g.fLeft + g.fWidth),
1031 SkIntToScalar(g.fTop + g.fHeight));
1034 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
1035 // we don't overflow along the way
1036 typedef int64_t Sk48Dot16;
1038 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
1039 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
1042 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
1043 SkScalar sx = Sk48Dot16ToScalar(dx);
1044 bounds->join(SkIntToScalar(g.fLeft) + sx,
1045 SkIntToScalar(g.fTop),
1046 SkIntToScalar(g.fLeft + g.fWidth) + sx,
1047 SkIntToScalar(g.fTop + g.fHeight));
1050 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
1051 SkScalar sy = Sk48Dot16ToScalar(dy);
1052 bounds->join(SkIntToScalar(g.fLeft),
1053 SkIntToScalar(g.fTop) + sy,
1054 SkIntToScalar(g.fLeft + g.fWidth),
1055 SkIntToScalar(g.fTop + g.fHeight) + sy);
1058 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
1060 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
1061 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
1062 SkASSERT(0 == xyIndex || 1 == xyIndex);
1063 return (&glyph.fAdvanceX)[xyIndex];
1066 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
1067 const char* text, size_t byteLength,
1068 int* count, SkRect* bounds) const {
1070 if (byteLength == 0) {
1078 SkMeasureCacheProc glyphCacheProc;
1079 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1083 JoinBoundsProc joinBoundsProc;
1084 if (this->isVerticalText()) {
1086 joinBoundsProc = join_bounds_y;
1089 joinBoundsProc = join_bounds_x;
1093 const char* stop = (const char*)text + byteLength;
1094 const SkGlyph* g = &glyphCacheProc(cache, &text);
1095 // our accumulated fixed-point advances might overflow 16.16, so we use
1096 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
1098 Sk48Dot16 x = advance(*g, xyIndex);
1100 SkAutoKern autokern;
1102 if (NULL == bounds) {
1103 if (this->isDevKernText()) {
1105 for (; text < stop; n++) {
1107 g = &glyphCacheProc(cache, &text);
1108 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
1111 for (; text < stop; n++) {
1112 x += advance(glyphCacheProc(cache, &text), xyIndex);
1116 set_bounds(*g, bounds);
1117 if (this->isDevKernText()) {
1119 for (; text < stop; n++) {
1121 g = &glyphCacheProc(cache, &text);
1122 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
1123 joinBoundsProc(*g, bounds, x);
1124 x += advance(*g, xyIndex);
1127 for (; text < stop; n++) {
1128 g = &glyphCacheProc(cache, &text);
1129 joinBoundsProc(*g, bounds, x);
1130 x += advance(*g, xyIndex);
1134 SkASSERT(text == stop);
1137 return Sk48Dot16ToScalar(x);
1140 SkScalar SkPaint::measureText(const void* textData, size_t length,
1141 SkRect* bounds, SkScalar zoom) const {
1142 const char* text = (const char*)textData;
1143 SkASSERT(text != NULL || length == 0);
1145 SkCanonicalizePaint canon(*this);
1146 const SkPaint& paint = canon.getPaint();
1147 SkScalar scale = canon.getScale();
1149 SkMatrix zoomMatrix, *zoomPtr = NULL;
1151 zoomMatrix.setScale(zoom, zoom);
1152 zoomPtr = &zoomMatrix;
1155 SkAutoGlyphCache autoCache(paint, NULL, zoomPtr);
1156 SkGlyphCache* cache = autoCache.getCache();
1163 width = paint.measure_text(cache, text, length, &tempCount, bounds);
1165 width = SkScalarMul(width, scale);
1167 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
1168 bounds->fTop = SkScalarMul(bounds->fTop, scale);
1169 bounds->fRight = SkScalarMul(bounds->fRight, scale);
1170 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
1173 } else if (bounds) {
1174 // ensure that even if we don't measure_text we still update the bounds
1180 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
1182 static bool forward_textBufferPred(const char* text, const char* stop) {
1186 static bool backward_textBufferPred(const char* text, const char* stop) {
1190 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
1191 const char** text, size_t length,
1192 const char** stop) {
1193 if (SkPaint::kForward_TextBufferDirection == tbd) {
1194 *stop = *text + length;
1195 return forward_textBufferPred;
1197 // text should point to the end of the buffer, and stop to the beginning
1200 return backward_textBufferPred;
1204 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
1205 SkScalar* measuredWidth,
1206 TextBufferDirection tbd) const {
1207 if (0 == length || 0 >= maxWidth) {
1208 if (measuredWidth) {
1214 if (0 == fTextSize) {
1215 if (measuredWidth) {
1221 SkASSERT(textD != NULL);
1222 const char* text = (const char*)textD;
1224 SkCanonicalizePaint canon(*this);
1225 const SkPaint& paint = canon.getPaint();
1226 SkScalar scale = canon.getScale();
1228 // adjust max in case we changed the textSize in paint
1233 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1234 SkGlyphCache* cache = autoCache.getCache();
1236 SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
1238 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1239 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1240 // use 64bits for our accumulator, to avoid overflowing 16.16
1241 Sk48Dot16 max = SkScalarToFixed(maxWidth);
1242 Sk48Dot16 width = 0;
1244 SkAutoKern autokern;
1246 if (this->isDevKernText()) {
1248 while (pred(text, stop)) {
1249 const char* curr = text;
1250 const SkGlyph& g = glyphCacheProc(cache, &text);
1251 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
1252 if ((width += x) > max) {
1260 while (pred(text, stop)) {
1261 const char* curr = text;
1262 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
1263 if ((width += x) > max) {
1271 if (measuredWidth) {
1272 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1274 scalarWidth = SkScalarMul(scalarWidth, scale);
1276 *measuredWidth = scalarWidth;
1279 // return the number of bytes measured
1280 return (kForward_TextBufferDirection == tbd) ?
1281 text - stop + length : stop - text + length;
1284 ///////////////////////////////////////////////////////////////////////////////
1286 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1287 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1288 return false; // don't detach the cache
1291 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1293 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1296 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1297 SkCanonicalizePaint canon(*this);
1298 const SkPaint& paint = canon.getPaint();
1299 SkScalar scale = canon.getScale();
1301 SkMatrix zoomMatrix, *zoomPtr = NULL;
1303 zoomMatrix.setScale(zoom, zoom);
1304 zoomPtr = &zoomMatrix;
1307 FontMetrics storage;
1308 if (NULL == metrics) {
1312 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1315 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1316 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1317 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1318 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1319 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1320 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
1321 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
1322 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
1323 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
1324 metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
1325 metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
1327 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1330 ///////////////////////////////////////////////////////////////////////////////
1332 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1333 bounds->set(g.fLeft * scale,
1335 (g.fLeft + g.fWidth) * scale,
1336 (g.fTop + g.fHeight) * scale);
1339 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1340 SkScalar widths[], SkRect bounds[]) const {
1341 if (0 == byteLength) {
1345 SkASSERT(NULL != textData);
1347 if (NULL == widths && NULL == bounds) {
1348 return this->countText(textData, byteLength);
1351 SkCanonicalizePaint canon(*this);
1352 const SkPaint& paint = canon.getPaint();
1353 SkScalar scale = canon.getScale();
1355 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1356 SkGlyphCache* cache = autoCache.getCache();
1357 SkMeasureCacheProc glyphCacheProc;
1358 glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
1361 const char* text = (const char*)textData;
1362 const char* stop = text + byteLength;
1364 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1366 if (this->isDevKernText()) {
1367 // we adjust the widths returned here through auto-kerning
1368 SkAutoKern autokern;
1369 SkFixed prevWidth = 0;
1372 while (text < stop) {
1373 const SkGlyph& g = glyphCacheProc(cache, &text);
1375 SkFixed adjust = autokern.adjust(g);
1378 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1379 *widths++ = SkScalarMul(w, scale);
1381 prevWidth = advance(g, xyIndex);
1384 set_bounds(g, bounds++, scale);
1388 if (count > 0 && widths) {
1389 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1392 while (text < stop) {
1393 const SkGlyph& g = glyphCacheProc(cache, &text);
1395 SkFixed adjust = autokern.adjust(g);
1398 *widths++ = SkFixedToScalar(prevWidth + adjust);
1400 prevWidth = advance(g, xyIndex);
1403 set_bounds(g, bounds++);
1407 if (count > 0 && widths) {
1408 *widths = SkFixedToScalar(prevWidth);
1411 } else { // no devkern
1413 while (text < stop) {
1414 const SkGlyph& g = glyphCacheProc(cache, &text);
1416 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
1420 set_bounds(g, bounds++, scale);
1425 while (text < stop) {
1426 const SkGlyph& g = glyphCacheProc(cache, &text);
1428 *widths++ = SkFixedToScalar(advance(g, xyIndex));
1431 set_bounds(g, bounds++);
1438 SkASSERT(text == stop);
1442 ///////////////////////////////////////////////////////////////////////////////
1446 void SkPaint::getTextPath(const void* textData, size_t length,
1447 SkScalar x, SkScalar y, SkPath* path) const {
1448 SkASSERT(length == 0 || textData != NULL);
1450 const char* text = (const char*)textData;
1451 if (text == NULL || length == 0 || path == NULL) {
1455 SkTextToPathIter iter(text, length, *this, false);
1457 SkScalar prevXPos = 0;
1459 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1460 matrix.postTranslate(x, y);
1464 const SkPath* iterPath;
1465 while (iter.next(&iterPath, &xpos)) {
1466 matrix.postTranslate(xpos - prevXPos, 0);
1468 path->addPath(*iterPath, matrix);
1474 void SkPaint::getPosTextPath(const void* textData, size_t length,
1475 const SkPoint pos[], SkPath* path) const {
1476 SkASSERT(length == 0 || textData != NULL);
1478 const char* text = (const char*)textData;
1479 if (text == NULL || length == 0 || path == NULL) {
1483 SkTextToPathIter iter(text, length, *this, false);
1488 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1492 const SkPath* iterPath;
1493 while (iter.next(&iterPath, NULL)) {
1494 matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1496 path->addPath(*iterPath, matrix);
1503 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1504 SkWriteBuffer* buffer) {
1505 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
1508 // SkFontHost can override this choice in FilterRec()
1509 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1510 uint32_t flags = paint.getFlags();
1512 // Antialiasing being disabled trumps all other settings.
1513 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1514 return SkMask::kBW_Format;
1517 if (flags & SkPaint::kLCDRenderText_Flag) {
1518 return SkMask::kLCD16_Format;
1521 return SkMask::kA8_Format;
1524 // if linear-text is on, then we force hinting to be off (since that's sort of
1525 // the point of linear-text.
1526 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1527 SkPaint::Hinting h = paint.getHinting();
1528 if (paint.isLinearText()) {
1529 h = SkPaint::kNo_Hinting;
1534 // return true if the paint is just a single color (i.e. not a shader). If its
1535 // a shader, then we can't compute a const luminance for it :(
1536 static bool justAColor(const SkPaint& paint, SkColor* color) {
1537 if (paint.getShader()) {
1540 SkColor c = paint.getColor();
1541 if (paint.getColorFilter()) {
1542 c = paint.getColorFilter()->filterColor(c);
1550 static SkColor computeLuminanceColor(const SkPaint& paint) {
1552 if (!justAColor(paint, &c)) {
1553 c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1558 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1560 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1561 // cost more RAM and draws slower, so we set a cap.
1562 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1563 #define SK_MAX_SIZE_FOR_LCDTEXT 48
1566 static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
1567 SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1568 rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1569 SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
1570 return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
1574 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1575 * that vary only slightly when we create our key into the font cache, since the font scaler
1576 * typically returns the same looking resuts for tiny changes in the matrix.
1578 static SkScalar sk_relax(SkScalar x) {
1579 int n = sk_float_round2int(x * 1024);
1583 void SkScalerContext::MakeRec(const SkPaint& paint,
1584 const SkDeviceProperties* deviceProperties,
1585 const SkMatrix* deviceMatrix,
1587 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1589 SkTypeface* typeface = paint.getTypeface();
1590 if (NULL == typeface) {
1591 typeface = SkTypeface::GetDefaultTypeface();
1593 rec->fOrigFontID = typeface->uniqueID();
1594 rec->fFontID = rec->fOrigFontID;
1595 rec->fTextSize = paint.getTextSize();
1596 rec->fPreScaleX = paint.getTextScaleX();
1597 rec->fPreSkewX = paint.getTextSkewX();
1600 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1601 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1602 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1603 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1605 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1606 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1609 SkPaint::Style style = paint.getStyle();
1610 SkScalar strokeWidth = paint.getStrokeWidth();
1614 if (paint.isFakeBoldText()) {
1615 #ifdef SK_USE_FREETYPE_EMBOLDEN
1616 flags |= SkScalerContext::kEmbolden_Flag;
1618 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1619 kStdFakeBoldInterpKeys,
1620 kStdFakeBoldInterpValues,
1621 kStdFakeBoldInterpLength);
1622 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1624 if (style == SkPaint::kFill_Style) {
1625 style = SkPaint::kStrokeAndFill_Style;
1626 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1628 strokeWidth += extra;
1633 if (paint.isDevKernText()) {
1634 flags |= SkScalerContext::kDevKernText_Flag;
1637 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1638 rec->fFrameWidth = strokeWidth;
1639 rec->fMiterLimit = paint.getStrokeMiter();
1640 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1642 if (style == SkPaint::kStrokeAndFill_Style) {
1643 flags |= SkScalerContext::kFrameAndFill_Flag;
1646 rec->fFrameWidth = 0;
1647 rec->fMiterLimit = 0;
1648 rec->fStrokeJoin = 0;
1651 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1653 SkDeviceProperties::Geometry geometry = deviceProperties
1654 ? deviceProperties->fGeometry
1655 : SkDeviceProperties::Geometry::MakeDefault();
1656 if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
1657 if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) {
1658 // eeek, can't support LCD
1659 rec->fMaskFormat = SkMask::kA8_Format;
1661 if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) {
1662 flags |= SkScalerContext::kLCD_Vertical_Flag;
1664 if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) {
1665 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1670 if (paint.isEmbeddedBitmapText()) {
1671 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1673 if (paint.isSubpixelText()) {
1674 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1676 if (paint.isAutohinted()) {
1677 flags |= SkScalerContext::kForceAutohinting_Flag;
1679 if (paint.isVerticalText()) {
1680 flags |= SkScalerContext::kVertical_Flag;
1682 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1683 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1685 rec->fFlags = SkToU16(flags);
1687 // these modify fFlags, so do them after assigning fFlags
1688 rec->setHinting(computeHinting(paint));
1690 rec->setLuminanceColor(computeLuminanceColor(paint));
1692 if (NULL == deviceProperties) {
1693 rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1694 rec->setPaintGamma(SK_GAMMA_EXPONENT);
1696 rec->setDeviceGamma(deviceProperties->fGamma);
1698 //For now always set the paint gamma equal to the device gamma.
1699 //The math in SkMaskGamma can handle them being different,
1700 //but it requires superluminous masks when
1701 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1702 rec->setPaintGamma(deviceProperties->fGamma);
1705 #ifdef SK_GAMMA_CONTRAST
1706 rec->setContrast(SK_GAMMA_CONTRAST);
1709 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1710 * With lower values small text appears washed out (though correctly so).
1711 * With higher values lcd fringing is worse and the smoothing effect of
1712 * partial coverage is diminished.
1714 rec->setContrast(0.5f);
1717 rec->fReservedAlign = 0;
1719 /* Allow the fonthost to modify our rec before we use it as a key into the
1720 cache. This way if we're asking for something that they will ignore,
1721 they can modify our rec up front, so we don't create duplicate cache
1724 typeface->onFilterRec(rec);
1726 // be sure to call PostMakeRec(rec) before you actually use it!
1730 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1731 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1732 * to hold it until the returned pointer is refed or forgotten.
1734 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1736 static SkMaskGamma* gLinearMaskGamma = NULL;
1737 static SkMaskGamma* gMaskGamma = NULL;
1738 static SkScalar gContrast = SK_ScalarMin;
1739 static SkScalar gPaintGamma = SK_ScalarMin;
1740 static SkScalar gDeviceGamma = SK_ScalarMin;
1742 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1743 * the returned SkMaskGamma pointer is refed or forgotten.
1745 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1746 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1747 if (NULL == gLinearMaskGamma) {
1748 gLinearMaskGamma = SkNEW(SkMaskGamma);
1750 return *gLinearMaskGamma;
1752 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1753 SkSafeUnref(gMaskGamma);
1754 gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
1755 gContrast = contrast;
1756 gPaintGamma = paintGamma;
1757 gDeviceGamma = deviceGamma;
1762 /*static*/ void SkPaint::Term() {
1763 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1765 SkSafeUnref(gLinearMaskGamma);
1766 gLinearMaskGamma = NULL;
1767 SkSafeUnref(gMaskGamma);
1769 SkDEBUGCODE(gContrast = SK_ScalarMin;)
1770 SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1771 SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1775 * We ensure that the rec is self-consistent and efficient (where possible)
1777 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
1779 * If we're asking for A8, we force the colorlum to be gray, since that
1780 * limits the number of unique entries, and the scaler will only look at
1781 * the lum of one of them.
1783 switch (rec->fMaskFormat) {
1784 case SkMask::kLCD16_Format:
1785 case SkMask::kLCD32_Format: {
1786 // filter down the luminance color to a finite number of bits
1787 SkColor color = rec->getLuminanceColor();
1788 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1791 case SkMask::kA8_Format: {
1792 // filter down the luminance to a single component, since A8 can't
1793 // use per-component information
1795 SkColor color = rec->getLuminanceColor();
1796 U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color);
1797 //If we are asked to look like LCD, look like LCD.
1798 if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
1799 // HACK: Prevents green from being pre-blended as white.
1800 lum -= ((255 - lum) * lum) / 255;
1803 // reduce to our finite number of bits
1804 color = SkColorSetRGB(lum, lum, lum);
1805 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1808 case SkMask::kBW_Format:
1809 // No need to differentiate gamma if we're BW
1810 rec->ignorePreBlend();
1815 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1822 * ignoreGamma tells us that the caller just wants metrics that are unaffected
1823 * by gamma correction, so we jam the luminance field to 0 (most common value
1824 * for black text) in hopes that we get a cache hit easier. A better solution
1825 * would be for the fontcache lookup to know to ignore the luminance field
1826 * entirely, but not sure how to do that and keep it fast.
1828 void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1829 const SkMatrix* deviceMatrix,
1830 void (*proc)(SkTypeface*, const SkDescriptor*, void*),
1831 void* context, bool ignoreGamma) const {
1832 SkScalerContext::Rec rec;
1834 SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
1836 rec.setLuminanceColor(0);
1839 size_t descSize = sizeof(rec);
1841 SkPathEffect* pe = this->getPathEffect();
1842 SkMaskFilter* mf = this->getMaskFilter();
1843 SkRasterizer* ra = this->getRasterizer();
1845 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1848 peBuffer.writeFlattenable(pe);
1849 descSize += peBuffer.bytesWritten();
1851 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1852 // seems like we could support kLCD as well at this point...
1855 mfBuffer.writeFlattenable(mf);
1856 descSize += mfBuffer.bytesWritten();
1858 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1859 /* Pre-blend is not currently applied to filtered text.
1860 The primary filter is blur, for which contrast makes no sense,
1861 and for which the destination guess error is more visible.
1862 Also, all existing users of blur have calibrated for linear. */
1863 rec.ignorePreBlend();
1866 raBuffer.writeFlattenable(ra);
1867 descSize += raBuffer.bytesWritten();
1869 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1872 #ifdef SK_BUILD_FOR_ANDROID
1873 SkWriteBuffer androidBuffer;
1874 fPaintOptionsAndroid.flatten(androidBuffer);
1875 descSize += androidBuffer.bytesWritten();
1879 ///////////////////////////////////////////////////////////////////////////
1880 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1881 SkScalerContext::PostMakeRec(*this, &rec);
1883 descSize += SkDescriptor::ComputeOverhead(entryCount);
1885 SkAutoDescriptor ad(descSize);
1886 SkDescriptor* desc = ad.getDesc();
1889 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1891 #ifdef SK_BUILD_FOR_ANDROID
1892 add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1896 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1899 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1902 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1905 SkASSERT(descSize == desc->getLength());
1906 desc->computeChecksum();
1910 // Check that we completely write the bytes in desc (our key), and that
1911 // there are no uninitialized bytes. If there were, then we would get
1912 // false-misses (or worse, false-hits) in our fontcache.
1914 // We do this buy filling 2 others, one with 0s and the other with 1s
1915 // and create those, and then check that all 3 are identical.
1916 SkAutoDescriptor ad1(descSize);
1917 SkAutoDescriptor ad2(descSize);
1918 SkDescriptor* desc1 = ad1.getDesc();
1919 SkDescriptor* desc2 = ad2.getDesc();
1921 memset(desc1, 0x00, descSize);
1922 memset(desc2, 0xFF, descSize);
1926 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1927 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1929 #ifdef SK_BUILD_FOR_ANDROID
1930 add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1931 add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1935 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
1936 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
1939 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
1940 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
1943 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
1944 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
1947 SkASSERT(descSize == desc1->getLength());
1948 SkASSERT(descSize == desc2->getLength());
1949 desc1->computeChecksum();
1950 desc2->computeChecksum();
1951 SkASSERT(!memcmp(desc, desc1, descSize));
1952 SkASSERT(!memcmp(desc, desc2, descSize));
1956 proc(fTypeface, desc, context);
1959 SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
1960 const SkMatrix* deviceMatrix) const {
1961 SkGlyphCache* cache;
1962 this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false);
1967 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1970 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
1971 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1972 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1973 rec.getPaintGamma(),
1974 rec.getDeviceGamma());
1975 return maskGamma.preBlend(rec.getLuminanceColor());
1978 ///////////////////////////////////////////////////////////////////////////////
1980 #include "SkStream.h"
1982 static uintptr_t asint(const void* p) {
1983 return reinterpret_cast<uintptr_t>(p);
1991 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1992 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1994 tmp.fScalar = value;
1999 static SkScalar read_scalar(const uint32_t*& ptr) {
2000 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
2006 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
2007 SkASSERT(a == (uint8_t)a);
2008 SkASSERT(b == (uint8_t)b);
2009 SkASSERT(c == (uint8_t)c);
2010 SkASSERT(d == (uint8_t)d);
2011 return (a << 24) | (b << 16) | (c << 8) | d;
2015 static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
2016 SkASSERT(bitCount > 0 && bitCount <= 32);
2017 uint32_t mask = ~0U;
2018 mask >>= (32 - bitCount);
2019 SkASSERT(0 == (value & ~mask));
2022 #define ASSERT_FITS_IN(value, bitcount)
2026 kHasTypeface_FlatFlag = 0x01,
2027 kHasEffects_FlatFlag = 0x02,
2028 kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
2030 kFlatFlagMask = 0x7,
2041 static inline int BPF_Mask(int bits) {
2042 return (1 << bits) - 1;
2045 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
2046 unsigned filter, unsigned flatFlags) {
2047 ASSERT_FITS_IN(flags, kFlags_BPF);
2048 ASSERT_FITS_IN(hint, kHint_BPF);
2049 ASSERT_FITS_IN(align, kAlign_BPF);
2050 ASSERT_FITS_IN(filter, kFilter_BPF);
2051 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
2053 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
2054 // add more bits in the future.
2055 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
2058 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
2059 paint->setFlags(packed >> 16);
2060 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
2061 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
2062 paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
2063 return (FlatFlags)(packed & kFlatFlagMask);
2066 // V22_COMPATIBILITY_CODE
2067 static FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
2069 kFilterBitmap_Flag = 0x02,
2070 kHighQualityFilterBitmap_Flag = 0x4000,
2072 kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
2075 // previously flags:16, textAlign:8, flatFlags:8
2076 // now flags:16, hinting:4, textAlign:4, flatFlags:8
2077 unsigned flags = packed >> 16;
2079 if (flags & kFilterBitmap_Flag) {
2082 if (flags & kHighQualityFilterBitmap_Flag) {
2085 paint->setFilterLevel((SkPaint::FilterLevel)filter);
2086 flags &= ~kAll_Flags; // remove these (now dead) bit flags
2088 paint->setFlags(flags);
2090 // hinting added later. 0 in this nibble means use the default.
2091 uint32_t hinting = (packed >> 12) & 0xF;
2092 paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
2093 paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
2094 return (FlatFlags)(packed & kFlatFlagMask);
2097 // The size of a flat paint's POD fields
2098 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
2099 1 * sizeof(SkColor) +
2100 1 * sizeof(uint16_t) +
2101 6 * sizeof(uint8_t);
2103 /* To save space/time, we analyze the paint, and write a truncated version of
2104 it if there are not tricky elements like shaders, etc.
2106 void SkPaint::flatten(SkWriteBuffer& buffer) const {
2107 uint8_t flatFlags = 0;
2108 if (this->getTypeface()) {
2109 flatFlags |= kHasTypeface_FlatFlag;
2111 if (asint(this->getPathEffect()) |
2112 asint(this->getShader()) |
2113 asint(this->getXfermode()) |
2114 asint(this->getMaskFilter()) |
2115 asint(this->getColorFilter()) |
2116 asint(this->getRasterizer()) |
2117 asint(this->getLooper()) |
2118 asint(this->getAnnotation()) |
2119 asint(this->getImageFilter())) {
2120 flatFlags |= kHasEffects_FlatFlag;
2122 #ifdef SK_BUILD_FOR_ANDROID
2123 if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) {
2124 flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag;
2128 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
2129 uint32_t* ptr = buffer.reserve(kPODPaintSize);
2131 ptr = write_scalar(ptr, this->getTextSize());
2132 ptr = write_scalar(ptr, this->getTextScaleX());
2133 ptr = write_scalar(ptr, this->getTextSkewX());
2134 ptr = write_scalar(ptr, this->getStrokeWidth());
2135 ptr = write_scalar(ptr, this->getStrokeMiter());
2136 *ptr++ = this->getColor();
2138 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
2139 this->getFilterLevel(), flatFlags);
2140 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
2141 this->getStyle(), this->getTextEncoding());
2143 // now we're done with ptr and the (pre)reserved space. If we need to write
2144 // additional fields, use the buffer directly
2145 if (flatFlags & kHasTypeface_FlatFlag) {
2146 buffer.writeTypeface(this->getTypeface());
2148 if (flatFlags & kHasEffects_FlatFlag) {
2149 buffer.writeFlattenable(this->getPathEffect());
2150 buffer.writeFlattenable(this->getShader());
2151 buffer.writeFlattenable(this->getXfermode());
2152 buffer.writeFlattenable(this->getMaskFilter());
2153 buffer.writeFlattenable(this->getColorFilter());
2154 buffer.writeFlattenable(this->getRasterizer());
2155 buffer.writeFlattenable(this->getLooper());
2156 buffer.writeFlattenable(this->getImageFilter());
2159 buffer.writeBool(true);
2160 fAnnotation->writeToBuffer(buffer);
2162 buffer.writeBool(false);
2165 #ifdef SK_BUILD_FOR_ANDROID
2166 if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
2167 this->getPaintOptionsAndroid().flatten(buffer);
2172 void SkPaint::unflatten(SkReadBuffer& buffer) {
2173 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
2174 const void* podData = buffer.skip(kPODPaintSize);
2175 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
2177 // the order we read must match the order we wrote in flatten()
2178 this->setTextSize(read_scalar(pod));
2179 this->setTextScaleX(read_scalar(pod));
2180 this->setTextSkewX(read_scalar(pod));
2181 this->setStrokeWidth(read_scalar(pod));
2182 this->setStrokeMiter(read_scalar(pod));
2183 this->setColor(*pod++);
2185 const int picVer = buffer.pictureVersion();
2186 unsigned flatFlags = 0;
2187 if (picVer > 0 && picVer <= 22) {
2188 flatFlags = unpack_paint_flags_v22(this, *pod++);
2190 flatFlags = unpack_paint_flags(this, *pod++);
2193 uint32_t tmp = *pod++;
2194 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
2195 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
2196 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
2197 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
2199 if (flatFlags & kHasTypeface_FlatFlag) {
2200 this->setTypeface(buffer.readTypeface());
2202 this->setTypeface(NULL);
2205 if (flatFlags & kHasEffects_FlatFlag) {
2206 SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
2207 SkSafeUnref(this->setShader(buffer.readShader()));
2208 SkSafeUnref(this->setXfermode(buffer.readXfermode()));
2209 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
2210 SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
2211 SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
2212 SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
2213 SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
2215 if (buffer.readBool()) {
2216 this->setAnnotation(SkAnnotation::Create(buffer))->unref();
2219 this->setPathEffect(NULL);
2220 this->setShader(NULL);
2221 this->setXfermode(NULL);
2222 this->setMaskFilter(NULL);
2223 this->setColorFilter(NULL);
2224 this->setRasterizer(NULL);
2225 this->setLooper(NULL);
2226 this->setImageFilter(NULL);
2229 #ifdef SK_BUILD_FOR_ANDROID
2230 this->setPaintOptionsAndroid(SkPaintOptionsAndroid());
2232 if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
2233 SkPaintOptionsAndroid options;
2234 options.unflatten(buffer);
2235 #ifdef SK_BUILD_FOR_ANDROID
2236 this->setPaintOptionsAndroid(options);
2241 ///////////////////////////////////////////////////////////////////////////////
2243 SkShader* SkPaint::setShader(SkShader* shader) {
2244 GEN_ID_INC_EVAL(shader != fShader);
2245 SkRefCnt_SafeAssign(fShader, shader);
2246 fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
2250 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2251 GEN_ID_INC_EVAL(filter != fColorFilter);
2252 SkRefCnt_SafeAssign(fColorFilter, filter);
2253 fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
2257 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2258 GEN_ID_INC_EVAL(mode != fXfermode);
2259 SkRefCnt_SafeAssign(fXfermode, mode);
2260 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
2264 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2265 SkSafeUnref(fXfermode);
2266 fXfermode = SkXfermode::Create(mode);
2268 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
2272 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2273 GEN_ID_INC_EVAL(effect != fPathEffect);
2274 SkRefCnt_SafeAssign(fPathEffect, effect);
2275 fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
2279 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2280 GEN_ID_INC_EVAL(filter != fMaskFilter);
2281 SkRefCnt_SafeAssign(fMaskFilter, filter);
2282 fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
2286 ///////////////////////////////////////////////////////////////////////////////
2288 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
2289 const SkRect* cullRect) const {
2290 SkStrokeRec rec(*this);
2292 const SkPath* srcPtr = &src;
2295 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2299 if (!rec.applyToPath(dst, *srcPtr)) {
2300 if (srcPtr == &tmpPath) {
2301 // If path's were copy-on-write, this trick would not be needed.
2302 // As it is, we want to save making a deep-copy from tmpPath -> dst
2303 // since we know we're just going to delete tmpPath when we return,
2304 // so the swap saves that copy.
2310 return !rec.isHairlineStyle();
2313 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2315 Style style) const {
2318 const SkRect* src = &origSrc;
2320 if (this->getLooper()) {
2321 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2322 this->getLooper()->computeFastBounds(*this, *src, storage);
2327 if (this->getPathEffect()) {
2328 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2332 if (kFill_Style != style) {
2333 // since we're stroked, outset the rect by the radius (and join type)
2334 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2335 if (0 == radius) { // hairline
2336 radius = SK_Scalar1;
2337 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2338 SkScalar scale = this->getStrokeMiter();
2339 if (scale > SK_Scalar1) {
2340 radius = SkScalarMul(radius, scale);
2343 storage->set(src->fLeft - radius, src->fTop - radius,
2344 src->fRight + radius, src->fBottom + radius);
2349 if (this->getMaskFilter()) {
2350 this->getMaskFilter()->computeFastBounds(*storage, storage);
2353 if (this->getImageFilter()) {
2354 this->getImageFilter()->computeFastBounds(*storage, storage);
2360 #ifndef SK_IGNORE_TO_STRING
2361 void SkPaint::toString(SkString* str) const {
2362 str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2364 SkTypeface* typeface = this->getTypeface();
2365 if (NULL != typeface) {
2366 SkDynamicMemoryWStream ostream;
2367 typeface->serialize(&ostream);
2368 SkAutoTUnref<SkData> data(ostream.copyToData());
2370 SkMemoryStream stream(data);
2371 SkFontDescriptor descriptor(&stream);
2373 str->append("<dt>Font Family Name:</dt><dd>");
2374 str->append(descriptor.getFamilyName());
2375 str->append("</dd><dt>Font Full Name:</dt><dd>");
2376 str->append(descriptor.getFullName());
2377 str->append("</dd><dt>Font PS Name:</dt><dd>");
2378 str->append(descriptor.getPostscriptName());
2379 str->append("</dd><dt>Font File Name:</dt><dd>");
2380 str->append(descriptor.getFontFileName());
2381 str->append("</dd>");
2384 str->append("<dt>TextSize:</dt><dd>");
2385 str->appendScalar(this->getTextSize());
2386 str->append("</dd>");
2388 str->append("<dt>TextScaleX:</dt><dd>");
2389 str->appendScalar(this->getTextScaleX());
2390 str->append("</dd>");
2392 str->append("<dt>TextSkewX:</dt><dd>");
2393 str->appendScalar(this->getTextSkewX());
2394 str->append("</dd>");
2396 SkPathEffect* pathEffect = this->getPathEffect();
2397 if (NULL != pathEffect) {
2398 str->append("<dt>PathEffect:</dt><dd>");
2399 str->append("</dd>");
2402 SkShader* shader = this->getShader();
2403 if (NULL != shader) {
2404 str->append("<dt>Shader:</dt><dd>");
2405 shader->toString(str);
2406 str->append("</dd>");
2409 SkXfermode* xfer = this->getXfermode();
2411 str->append("<dt>Xfermode:</dt><dd>");
2412 xfer->toString(str);
2413 str->append("</dd>");
2416 SkMaskFilter* maskFilter = this->getMaskFilter();
2417 if (NULL != maskFilter) {
2418 str->append("<dt>MaskFilter:</dt><dd>");
2419 maskFilter->toString(str);
2420 str->append("</dd>");
2423 SkColorFilter* colorFilter = this->getColorFilter();
2424 if (NULL != colorFilter) {
2425 str->append("<dt>ColorFilter:</dt><dd>");
2426 colorFilter->toString(str);
2427 str->append("</dd>");
2430 SkRasterizer* rasterizer = this->getRasterizer();
2431 if (NULL != rasterizer) {
2432 str->append("<dt>Rasterizer:</dt><dd>");
2433 str->append("</dd>");
2436 SkDrawLooper* looper = this->getLooper();
2437 if (NULL != looper) {
2438 str->append("<dt>DrawLooper:</dt><dd>");
2439 looper->toString(str);
2440 str->append("</dd>");
2443 SkImageFilter* imageFilter = this->getImageFilter();
2444 if (NULL != imageFilter) {
2445 str->append("<dt>ImageFilter:</dt><dd>");
2446 str->append("</dd>");
2449 SkAnnotation* annotation = this->getAnnotation();
2450 if (NULL != annotation) {
2451 str->append("<dt>Annotation:</dt><dd>");
2452 str->append("</dd>");
2455 str->append("<dt>Color:</dt><dd>0x");
2456 SkColor color = this->getColor();
2457 str->appendHex(color);
2458 str->append("</dd>");
2460 str->append("<dt>Stroke Width:</dt><dd>");
2461 str->appendScalar(this->getStrokeWidth());
2462 str->append("</dd>");
2464 str->append("<dt>Stroke Miter:</dt><dd>");
2465 str->appendScalar(this->getStrokeMiter());
2466 str->append("</dd>");
2468 str->append("<dt>Flags:</dt><dd>(");
2469 if (this->getFlags()) {
2470 bool needSeparator = false;
2471 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2472 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2473 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2474 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2475 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2476 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2477 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2478 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2479 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2480 SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2481 "EmbeddedBitmapText", &needSeparator);
2482 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2483 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2484 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2485 "GenA8FromLCD", &needSeparator);
2487 str->append("None");
2489 str->append(")</dd>");
2491 str->append("<dt>FilterLevel:</dt><dd>");
2492 static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
2493 str->append(gFilterLevelStrings[this->getFilterLevel()]);
2494 str->append("</dd>");
2496 str->append("<dt>TextAlign:</dt><dd>");
2497 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2498 str->append(gTextAlignStrings[this->getTextAlign()]);
2499 str->append("</dd>");
2501 str->append("<dt>CapType:</dt><dd>");
2502 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2503 str->append(gStrokeCapStrings[this->getStrokeCap()]);
2504 str->append("</dd>");
2506 str->append("<dt>JoinType:</dt><dd>");
2507 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2508 str->append(gJoinStrings[this->getStrokeJoin()]);
2509 str->append("</dd>");
2511 str->append("<dt>Style:</dt><dd>");
2512 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2513 str->append(gStyleStrings[this->getStyle()]);
2514 str->append("</dd>");
2516 str->append("<dt>TextEncoding:</dt><dd>");
2517 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2518 str->append(gTextEncodingStrings[this->getTextEncoding()]);
2519 str->append("</dd>");
2521 str->append("<dt>Hinting:</dt><dd>");
2522 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2523 str->append(gHintingStrings[this->getHinting()]);
2524 str->append("</dd>");
2526 str->append("</dd></dl></dl>");
2530 ///////////////////////////////////////////////////////////////////////////////
2532 static bool has_thick_frame(const SkPaint& paint) {
2533 return paint.getStrokeWidth() > 0 &&
2534 paint.getStyle() != SkPaint::kFill_Style;
2537 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
2538 const SkPaint& paint,
2539 bool applyStrokeAndPathEffects)
2541 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
2544 fPaint.setLinearText(true);
2545 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2547 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2548 applyStrokeAndPathEffects = false;
2551 // can't use our canonical size if we need to apply patheffects
2552 if (fPaint.getPathEffect() == NULL) {
2553 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2554 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2555 if (has_thick_frame(fPaint)) {
2556 fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2559 fScale = SK_Scalar1;
2562 if (!applyStrokeAndPathEffects) {
2563 fPaint.setStyle(SkPaint::kFill_Style);
2564 fPaint.setPathEffect(NULL);
2567 fCache = fPaint.detachCache(NULL, NULL);
2569 SkPaint::Style style = SkPaint::kFill_Style;
2570 SkPathEffect* pe = NULL;
2572 if (!applyStrokeAndPathEffects) {
2573 style = paint.getStyle(); // restore
2574 pe = paint.getPathEffect(); // restore
2576 fPaint.setStyle(style);
2577 fPaint.setPathEffect(pe);
2578 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
2580 // now compute fXOffset if needed
2582 SkScalar xOffset = 0;
2583 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2585 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
2586 &count, NULL), fScale);
2587 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2588 width = SkScalarHalf(width);
2596 fStop = text + length;
2598 fXYIndex = paint.isVerticalText() ? 1 : 0;
2601 SkTextToPathIter::~SkTextToPathIter() {
2602 SkGlyphCache::AttachCache(fCache);
2605 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2606 if (fText < fStop) {
2607 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2609 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2610 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2614 *path = fCache->findPath(glyph);
2629 ///////////////////////////////////////////////////////////////////////////////
2631 bool SkPaint::nothingToDraw() const {
2635 SkXfermode::Mode mode;
2636 if (SkXfermode::AsMode(fXfermode, &mode)) {
2638 case SkXfermode::kSrcOver_Mode:
2639 case SkXfermode::kSrcATop_Mode:
2640 case SkXfermode::kDstOut_Mode:
2641 case SkXfermode::kDstOver_Mode:
2642 case SkXfermode::kPlus_Mode:
2643 return 0 == this->getAlpha();
2644 case SkXfermode::kDst_Mode:
2653 void SkPaint::setBitfields(uint32_t bitfields) {
2654 fBitfields = bitfields;
2657 inline static unsigned popcount(uint8_t x) {
2658 // As in Hacker's delight, adapted for just 8 bits.
2659 x = (x & 0x55) + ((x >> 1) & 0x55); // a b c d w x y z -> a+b c+d w+x y+z
2660 x = (x & 0x33) + ((x >> 2) & 0x33); // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
2661 x = (x & 0x0F) + ((x >> 4) & 0x0F); // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
2665 void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
2666 const uint32_t dirty = paint.fDirtyBits;
2668 // Each of the low 7 dirty bits corresponds to a 4-byte flat value,
2669 // plus one for the dirty bits and one for the bitfields
2670 const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2);
2671 SkASSERT(flatBytes <= 32);
2672 uint32_t* u32 = buffer.reserve(flatBytes);
2674 *u32++ = paint.getBitfields();
2679 #define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
2681 SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
2685 F(f32, StrokeWidth);
2686 F(f32, StrokeMiter);
2688 #define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
2698 if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
2699 if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
2700 #ifdef SK_BUILD_FOR_ANDROID
2701 if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer);
2705 void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
2706 const uint32_t dirty = buffer.readUInt();
2707 paint->setBitfields(buffer.readUInt());
2711 #define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
2712 // Same function, except it unrefs the object newly set on the paint:
2713 #define F_UNREF(field, reader) \
2714 if (dirty & k##field##_DirtyBit) \
2715 paint->set##field(buffer.reader())->unref()
2718 F(TextSize, readScalar);
2719 F(TextScaleX, readScalar);
2720 F(TextSkewX, readScalar);
2721 F(StrokeWidth, readScalar);
2722 F(StrokeMiter, readScalar);
2723 F_UNREF(PathEffect, readPathEffect);
2724 F_UNREF(Shader, readShader);
2725 F_UNREF(Xfermode, readXfermode);
2726 F_UNREF(MaskFilter, readMaskFilter);
2727 F_UNREF(ColorFilter, readColorFilter);
2728 F_UNREF(Rasterizer, readRasterizer);
2729 F_UNREF(Looper, readDrawLooper);
2730 F_UNREF(ImageFilter, readImageFilter);
2731 F(Typeface, readTypeface);
2734 if (dirty & kAnnotation_DirtyBit) {
2735 paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
2737 #ifdef SK_BUILD_FOR_ANDROID
2738 if (dirty & kPaintOptionsAndroid_DirtyBit) {
2739 SkPaintOptionsAndroid options;
2740 options.unflatten(buffer);
2741 paint->setPaintOptionsAndroid(options);
2744 SkASSERT(dirty == paint->fDirtyBits);