2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkAnnotation.h"
10 #include "SkAutoKern.h"
11 #include "SkColorFilter.h"
13 #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 "SkPathEffect.h"
25 #include "SkRasterizer.h"
27 #include "SkScalerContext.h"
29 #include "SkStringUtils.h"
31 #include "SkTextFormatParams.h"
32 #include "SkTextToPathIter.h"
34 #include "SkTypeface.h"
35 #include "SkXfermode.h"
38 kColor_DirtyBit = 1 << 0,
39 kTextSize_DirtyBit = 1 << 1,
40 kTextScaleX_DirtyBit = 1 << 2,
41 kTextSkewX_DirtyBit = 1 << 3,
42 kStrokeWidth_DirtyBit = 1 << 4,
43 kStrokeMiter_DirtyBit = 1 << 5,
45 kPOD_DirtyBitMask = 63,
47 kPathEffect_DirtyBit = 1 << 6,
48 kShader_DirtyBit = 1 << 7,
49 kXfermode_DirtyBit = 1 << 8,
50 kMaskFilter_DirtyBit = 1 << 9,
51 kColorFilter_DirtyBit = 1 << 10,
52 kRasterizer_DirtyBit = 1 << 11,
53 kLooper_DirtyBit = 1 << 12,
54 kImageFilter_DirtyBit = 1 << 13,
55 kTypeface_DirtyBit = 1 << 14,
56 kAnnotation_DirtyBit = 1 << 15,
59 // define this to get a printf for out-of-range parameter in setters
60 // e.g. setTextSize(-1)
61 //#define SK_REPORT_API_RANGE_CHECK
63 #ifdef SK_BUILD_FOR_ANDROID
64 #define GEN_ID_INC fGenerationID++
65 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
68 #define GEN_ID_INC_EVAL(expression)
83 fTextSize = SkPaintDefaults_TextSize;
84 fTextScaleX = SK_Scalar1;
86 fColor = SK_ColorBLACK;
88 fMiterLimit = SkPaintDefaults_MiterLimit;
90 // Zero all bitfields, then set some non-zero defaults.
92 fBitfields.fFlags = SkPaintDefaults_Flags;
93 fBitfields.fCapType = kDefault_Cap;
94 fBitfields.fJoinType = kDefault_Join;
95 fBitfields.fTextAlign = kLeft_Align;
96 fBitfields.fStyle = kFill_Style;
97 fBitfields.fTextEncoding = kUTF8_TextEncoding;
98 fBitfields.fHinting = SkPaintDefaults_Hinting;
101 #ifdef SK_BUILD_FOR_ANDROID
106 SkPaint::SkPaint(const SkPaint& src) {
107 #define COPY(field) field = src.field
108 #define REF_COPY(field) field = SkSafeRef(src.field)
111 REF_COPY(fPathEffect);
114 REF_COPY(fMaskFilter);
115 REF_COPY(fColorFilter);
116 REF_COPY(fRasterizer);
118 REF_COPY(fImageFilter);
119 REF_COPY(fAnnotation);
130 #ifdef SK_BUILD_FOR_ANDROID
138 SkPaint::~SkPaint() {
139 SkSafeUnref(fTypeface);
140 SkSafeUnref(fPathEffect);
141 SkSafeUnref(fShader);
142 SkSafeUnref(fXfermode);
143 SkSafeUnref(fMaskFilter);
144 SkSafeUnref(fColorFilter);
145 SkSafeUnref(fRasterizer);
146 SkSafeUnref(fLooper);
147 SkSafeUnref(fImageFilter);
148 SkSafeUnref(fAnnotation);
151 SkPaint& SkPaint::operator=(const SkPaint& src) {
156 #define COPY(field) field = src.field
157 #define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
162 REF_COPY(fPathEffect);
165 REF_COPY(fMaskFilter);
166 REF_COPY(fColorFilter);
167 REF_COPY(fRasterizer);
169 REF_COPY(fImageFilter);
170 REF_COPY(fAnnotation);
181 #ifdef SK_BUILD_FOR_ANDROID
191 bool operator==(const SkPaint& a, const SkPaint& b) {
192 #define EQUAL(field) (a.field == b.field)
193 // Don't check fGenerationID or fDirtyBits, which can be different for logically equal paints.
194 return EQUAL(fTypeface)
195 && EQUAL(fPathEffect)
198 && EQUAL(fMaskFilter)
199 && EQUAL(fColorFilter)
200 && EQUAL(fRasterizer)
202 && EQUAL(fImageFilter)
203 && EQUAL(fAnnotation)
205 && EQUAL(fTextScaleX)
209 && EQUAL(fMiterLimit)
210 && EQUAL(fBitfieldsUInt)
215 void SkPaint::reset() {
218 #ifdef SK_BUILD_FOR_ANDROID
219 uint32_t oldGenerationID = fGenerationID;
222 #ifdef SK_BUILD_FOR_ANDROID
223 fGenerationID = oldGenerationID + 1;
227 #ifdef SK_BUILD_FOR_ANDROID
228 uint32_t SkPaint::getGenerationID() const {
229 return fGenerationID;
232 void SkPaint::setGenerationID(uint32_t generationID) {
233 fGenerationID = generationID;
237 void SkPaint::setFilterLevel(FilterLevel level) {
238 GEN_ID_INC_EVAL((unsigned) level != fBitfields.fFilterLevel);
239 fBitfields.fFilterLevel = level;
242 void SkPaint::setHinting(Hinting hintingLevel) {
243 GEN_ID_INC_EVAL((unsigned) hintingLevel != fBitfields.fHinting);
244 fBitfields.fHinting = hintingLevel;
247 void SkPaint::setFlags(uint32_t flags) {
248 GEN_ID_INC_EVAL(flags != fBitfields.fFlags);
249 fBitfields.fFlags = flags;
252 void SkPaint::setAntiAlias(bool doAA) {
253 this->setFlags(SkSetClearMask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
256 void SkPaint::setDither(bool doDither) {
257 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDither, kDither_Flag));
260 void SkPaint::setSubpixelText(bool doSubpixel) {
261 this->setFlags(SkSetClearMask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
264 void SkPaint::setLCDRenderText(bool doLCDRender) {
265 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
268 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
269 this->setFlags(SkSetClearMask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
272 void SkPaint::setAutohinted(bool useAutohinter) {
273 this->setFlags(SkSetClearMask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
276 void SkPaint::setLinearText(bool doLinearText) {
277 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
280 void SkPaint::setVerticalText(bool doVertical) {
281 this->setFlags(SkSetClearMask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
284 void SkPaint::setUnderlineText(bool doUnderline) {
285 this->setFlags(SkSetClearMask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag));
288 void SkPaint::setStrikeThruText(bool doStrikeThru) {
289 this->setFlags(SkSetClearMask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag));
292 void SkPaint::setFakeBoldText(bool doFakeBold) {
293 this->setFlags(SkSetClearMask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
296 void SkPaint::setDevKernText(bool doDevKern) {
297 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
300 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
301 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
304 void SkPaint::setStyle(Style style) {
305 if ((unsigned)style < kStyleCount) {
306 GEN_ID_INC_EVAL((unsigned)style != fBitfields.fStyle);
307 fBitfields.fStyle = style;
309 #ifdef SK_REPORT_API_RANGE_CHECK
310 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
315 void SkPaint::setColor(SkColor color) {
316 GEN_ID_INC_EVAL(color != fColor);
318 fDirtyBits |= kColor_DirtyBit;
321 void SkPaint::setAlpha(U8CPU a) {
322 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
323 SkColorGetG(fColor), SkColorGetB(fColor)));
326 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
327 this->setColor(SkColorSetARGB(a, r, g, b));
330 void SkPaint::setStrokeWidth(SkScalar width) {
332 GEN_ID_INC_EVAL(width != fWidth);
334 fDirtyBits |= kStrokeWidth_DirtyBit;
336 #ifdef SK_REPORT_API_RANGE_CHECK
337 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
342 void SkPaint::setStrokeMiter(SkScalar limit) {
344 GEN_ID_INC_EVAL(limit != fMiterLimit);
346 fDirtyBits |= kStrokeMiter_DirtyBit;
348 #ifdef SK_REPORT_API_RANGE_CHECK
349 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
354 void SkPaint::setStrokeCap(Cap ct) {
355 if ((unsigned)ct < kCapCount) {
356 GEN_ID_INC_EVAL((unsigned)ct != fBitfields.fCapType);
357 fBitfields.fCapType = SkToU8(ct);
359 #ifdef SK_REPORT_API_RANGE_CHECK
360 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
365 void SkPaint::setStrokeJoin(Join jt) {
366 if ((unsigned)jt < kJoinCount) {
367 GEN_ID_INC_EVAL((unsigned)jt != fBitfields.fJoinType);
368 fBitfields.fJoinType = SkToU8(jt);
370 #ifdef SK_REPORT_API_RANGE_CHECK
371 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
376 ///////////////////////////////////////////////////////////////////////////////
378 void SkPaint::setTextAlign(Align align) {
379 if ((unsigned)align < kAlignCount) {
380 GEN_ID_INC_EVAL((unsigned)align != fBitfields.fTextAlign);
381 fBitfields.fTextAlign = SkToU8(align);
383 #ifdef SK_REPORT_API_RANGE_CHECK
384 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
389 void SkPaint::setTextSize(SkScalar ts) {
391 GEN_ID_INC_EVAL(ts != fTextSize);
393 fDirtyBits |= kTextSize_DirtyBit;
395 #ifdef SK_REPORT_API_RANGE_CHECK
396 SkDebugf("SkPaint::setTextSize() called with negative value\n");
401 void SkPaint::setTextScaleX(SkScalar scaleX) {
402 GEN_ID_INC_EVAL(scaleX != fTextScaleX);
403 fTextScaleX = scaleX;
404 fDirtyBits |= kTextScaleX_DirtyBit;
407 void SkPaint::setTextSkewX(SkScalar skewX) {
408 GEN_ID_INC_EVAL(skewX != fTextSkewX);
410 fDirtyBits |= kTextSkewX_DirtyBit;
413 void SkPaint::setTextEncoding(TextEncoding encoding) {
414 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
415 GEN_ID_INC_EVAL((unsigned)encoding != fBitfields.fTextEncoding);
416 fBitfields.fTextEncoding = encoding;
418 #ifdef SK_REPORT_API_RANGE_CHECK
419 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
424 ///////////////////////////////////////////////////////////////////////////////
426 // Returns dst with the given bitmask enabled or disabled, depending on value.
427 inline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
428 return value ? (dst | bitmask) : (dst & ~bitmask);
431 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
432 SkRefCnt_SafeAssign(fTypeface, font);
434 fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
438 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
439 SkRefCnt_SafeAssign(fRasterizer, r);
441 fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
445 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
446 SkRefCnt_SafeAssign(fLooper, looper);
448 fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
452 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
453 SkRefCnt_SafeAssign(fImageFilter, imageFilter);
455 fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
459 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
460 SkRefCnt_SafeAssign(fAnnotation, annotation);
462 fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
466 ///////////////////////////////////////////////////////////////////////////////
468 static SkScalar mag2(SkScalar x, SkScalar y) {
469 return x * x + y * y;
472 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
473 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
475 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
478 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
479 SkASSERT(!ctm.hasPerspective());
480 SkASSERT(!textM.hasPerspective());
483 matrix.setConcat(ctm, textM);
484 return tooBig(matrix, MaxCacheSize2());
488 ///////////////////////////////////////////////////////////////////////////////
490 #include "SkGlyphCache.h"
493 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
495 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
498 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
499 uint16_t glyphs[]) const {
500 if (byteLength == 0) {
504 SkASSERT(textData != NULL);
506 if (NULL == glyphs) {
507 switch (this->getTextEncoding()) {
508 case kUTF8_TextEncoding:
509 return SkUTF8_CountUnichars((const char*)textData, byteLength);
510 case kUTF16_TextEncoding:
511 return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
512 case kUTF32_TextEncoding:
513 return SkToInt(byteLength >> 2);
514 case kGlyphID_TextEncoding:
515 return SkToInt(byteLength >> 1);
517 SkDEBUGFAIL("unknown text encoding");
522 // if we get here, we have a valid glyphs[] array, so time to fill it in
524 // handle this encoding before the setup for the glyphcache
525 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
526 // we want to ignore the low bit of byteLength
527 memcpy(glyphs, textData, byteLength >> 1 << 1);
528 return SkToInt(byteLength >> 1);
531 SkAutoGlyphCache autoCache(*this, NULL, NULL);
532 SkGlyphCache* cache = autoCache.getCache();
534 const char* text = (const char*)textData;
535 const char* stop = text + byteLength;
536 uint16_t* gptr = glyphs;
538 switch (this->getTextEncoding()) {
539 case SkPaint::kUTF8_TextEncoding:
540 while (text < stop) {
541 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
544 case SkPaint::kUTF16_TextEncoding: {
545 const uint16_t* text16 = (const uint16_t*)text;
546 const uint16_t* stop16 = (const uint16_t*)stop;
547 while (text16 < stop16) {
548 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
552 case kUTF32_TextEncoding: {
553 const int32_t* text32 = (const int32_t*)text;
554 const int32_t* stop32 = (const int32_t*)stop;
555 while (text32 < stop32) {
556 *gptr++ = cache->unicharToGlyph(*text32++);
561 SkDEBUGFAIL("unknown text encoding");
563 return SkToInt(gptr - glyphs);
566 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
567 if (0 == byteLength) {
571 SkASSERT(textData != NULL);
573 // handle this encoding before the setup for the glyphcache
574 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
575 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
576 size_t count = byteLength >> 1;
577 for (size_t i = 0; i < count; i++) {
578 if (0 == glyphID[i]) {
585 SkAutoGlyphCache autoCache(*this, NULL, NULL);
586 SkGlyphCache* cache = autoCache.getCache();
588 switch (this->getTextEncoding()) {
589 case SkPaint::kUTF8_TextEncoding: {
590 const char* text = static_cast<const char*>(textData);
591 const char* stop = text + byteLength;
592 while (text < stop) {
593 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
599 case SkPaint::kUTF16_TextEncoding: {
600 const uint16_t* text = static_cast<const uint16_t*>(textData);
601 const uint16_t* stop = text + (byteLength >> 1);
602 while (text < stop) {
603 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
609 case SkPaint::kUTF32_TextEncoding: {
610 const int32_t* text = static_cast<const int32_t*>(textData);
611 const int32_t* stop = text + (byteLength >> 2);
612 while (text < stop) {
613 if (0 == cache->unicharToGlyph(*text++)) {
620 SkDEBUGFAIL("unknown text encoding");
626 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
627 SkUnichar textData[]) const {
632 SkASSERT(glyphs != NULL);
633 SkASSERT(textData != NULL);
635 SkAutoGlyphCache autoCache(*this, NULL, NULL);
636 SkGlyphCache* cache = autoCache.getCache();
638 for (int index = 0; index < count; index++) {
639 textData[index] = cache->glyphToUnichar(glyphs[index]);
643 ///////////////////////////////////////////////////////////////////////////////
645 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
647 SkASSERT(cache != NULL);
648 SkASSERT(text != NULL);
650 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
653 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
655 SkASSERT(cache != NULL);
656 SkASSERT(text != NULL);
658 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
661 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
663 SkASSERT(cache != NULL);
664 SkASSERT(text != NULL);
666 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
669 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
671 SkASSERT(cache != NULL);
672 SkASSERT(text != NULL);
674 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
677 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
679 SkASSERT(cache != NULL);
680 SkASSERT(text != NULL);
682 const int32_t* ptr = *(const int32_t**)text;
683 SkUnichar uni = *ptr++;
684 *text = (const char*)ptr;
685 return cache->getUnicharMetrics(uni);
688 static const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
690 SkASSERT(cache != NULL);
691 SkASSERT(text != NULL);
693 const int32_t* ptr = *(const int32_t**)text;
694 SkUnichar uni = *--ptr;
695 *text = (const char*)ptr;
696 return cache->getUnicharMetrics(uni);
699 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
701 SkASSERT(cache != NULL);
702 SkASSERT(text != NULL);
704 const uint16_t* ptr = *(const uint16_t**)text;
705 unsigned glyphID = *ptr;
707 *text = (const char*)ptr;
708 return cache->getGlyphIDMetrics(glyphID);
711 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
713 SkASSERT(cache != NULL);
714 SkASSERT(text != NULL);
716 const uint16_t* ptr = *(const uint16_t**)text;
718 unsigned glyphID = *ptr;
719 *text = (const char*)ptr;
720 return cache->getGlyphIDMetrics(glyphID);
723 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
725 SkASSERT(cache != NULL);
726 SkASSERT(text != NULL);
728 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
731 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
733 SkASSERT(cache != NULL);
734 SkASSERT(text != NULL);
736 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
739 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
741 SkASSERT(cache != NULL);
742 SkASSERT(text != NULL);
744 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
747 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
749 SkASSERT(cache != NULL);
750 SkASSERT(text != NULL);
752 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
755 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
757 SkASSERT(cache != NULL);
758 SkASSERT(text != NULL);
760 const int32_t* ptr = *(const int32_t**)text;
761 SkUnichar uni = *ptr++;
762 *text = (const char*)ptr;
763 return cache->getUnicharAdvance(uni);
766 static const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
768 SkASSERT(cache != NULL);
769 SkASSERT(text != NULL);
771 const int32_t* ptr = *(const int32_t**)text;
772 SkUnichar uni = *--ptr;
773 *text = (const char*)ptr;
774 return cache->getUnicharAdvance(uni);
777 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
779 SkASSERT(cache != NULL);
780 SkASSERT(text != NULL);
782 const uint16_t* ptr = *(const uint16_t**)text;
783 unsigned glyphID = *ptr;
785 *text = (const char*)ptr;
786 return cache->getGlyphIDAdvance(glyphID);
789 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
791 SkASSERT(cache != NULL);
792 SkASSERT(text != NULL);
794 const uint16_t* ptr = *(const uint16_t**)text;
796 unsigned glyphID = *ptr;
797 *text = (const char*)ptr;
798 return cache->getGlyphIDAdvance(glyphID);
801 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
802 bool needFullMetrics) const {
803 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
804 sk_getMetrics_utf8_next,
805 sk_getMetrics_utf16_next,
806 sk_getMetrics_utf32_next,
807 sk_getMetrics_glyph_next,
809 sk_getMetrics_utf8_prev,
810 sk_getMetrics_utf16_prev,
811 sk_getMetrics_utf32_prev,
812 sk_getMetrics_glyph_prev,
814 sk_getAdvance_utf8_next,
815 sk_getAdvance_utf16_next,
816 sk_getAdvance_utf32_next,
817 sk_getAdvance_glyph_next,
819 sk_getAdvance_utf8_prev,
820 sk_getAdvance_utf16_prev,
821 sk_getAdvance_utf32_prev,
822 sk_getAdvance_glyph_prev
825 unsigned index = this->getTextEncoding();
827 if (kBackward_TextBufferDirection == tbd) {
830 if (!needFullMetrics && !this->isDevKernText()) {
834 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
835 return gMeasureCacheProcs[index];
838 ///////////////////////////////////////////////////////////////////////////////
840 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
841 const char** text, SkFixed, SkFixed) {
842 SkASSERT(cache != NULL);
843 SkASSERT(text != NULL);
845 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
848 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
849 const char** text, SkFixed x, SkFixed y) {
850 SkASSERT(cache != NULL);
851 SkASSERT(text != NULL);
853 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
856 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
857 const char** text, SkFixed, SkFixed) {
858 SkASSERT(cache != NULL);
859 SkASSERT(text != NULL);
861 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
864 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
865 const char** text, SkFixed x, SkFixed y) {
866 SkASSERT(cache != NULL);
867 SkASSERT(text != NULL);
869 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
873 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
874 const char** text, SkFixed, SkFixed) {
875 SkASSERT(cache != NULL);
876 SkASSERT(text != NULL);
878 const int32_t* ptr = *(const int32_t**)text;
879 SkUnichar uni = *ptr++;
880 *text = (const char*)ptr;
881 return cache->getUnicharMetrics(uni);
884 static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
885 const char** text, SkFixed x, SkFixed y) {
886 SkASSERT(cache != NULL);
887 SkASSERT(text != NULL);
889 const int32_t* ptr = *(const int32_t**)text;
890 SkUnichar uni = *ptr++;
891 *text = (const char*)ptr;
892 return cache->getUnicharMetrics(uni, x, y);
895 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
896 const char** text, SkFixed, SkFixed) {
897 SkASSERT(cache != NULL);
898 SkASSERT(text != NULL);
900 const uint16_t* ptr = *(const uint16_t**)text;
901 unsigned glyphID = *ptr;
903 *text = (const char*)ptr;
904 return cache->getGlyphIDMetrics(glyphID);
907 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
908 const char** text, SkFixed x, SkFixed y) {
909 SkASSERT(cache != NULL);
910 SkASSERT(text != NULL);
912 const uint16_t* ptr = *(const uint16_t**)text;
913 unsigned glyphID = *ptr;
915 *text = (const char*)ptr;
916 return cache->getGlyphIDMetrics(glyphID, x, y);
919 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
920 static const SkDrawCacheProc gDrawCacheProcs[] = {
921 sk_getMetrics_utf8_00,
922 sk_getMetrics_utf16_00,
923 sk_getMetrics_utf32_00,
924 sk_getMetrics_glyph_00,
926 sk_getMetrics_utf8_xy,
927 sk_getMetrics_utf16_xy,
928 sk_getMetrics_utf32_xy,
929 sk_getMetrics_glyph_xy
932 unsigned index = this->getTextEncoding();
933 if (fBitfields.fFlags & kSubpixelText_Flag) {
937 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
938 return gDrawCacheProcs[index];
941 ///////////////////////////////////////////////////////////////////////////////
943 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
944 SkPaint::kDevKernText_Flag | \
945 SkPaint::kLinearText_Flag | \
946 SkPaint::kLCDRenderText_Flag | \
947 SkPaint::kEmbeddedBitmapText_Flag | \
948 SkPaint::kAutoHinting_Flag | \
949 SkPaint::kGenA8FromLCD_Flag )
951 SkScalar SkPaint::setupForAsPaths() {
952 uint32_t flags = this->getFlags();
953 // clear the flags we don't care about
954 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
955 // set the flags we do care about
956 flags |= SkPaint::kSubpixelText_Flag;
958 this->setFlags(flags);
959 this->setHinting(SkPaint::kNo_Hinting);
961 SkScalar textSize = fTextSize;
962 this->setTextSize(kCanonicalTextSizeForPaths);
963 return textSize / kCanonicalTextSizeForPaths;
966 class SkCanonicalizePaint {
968 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
969 if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
970 SkPaint* p = fLazy.set(paint);
971 fScale = p->setupForAsPaths();
976 const SkPaint& getPaint() const { return *fPaint; }
979 * Returns 0 if the paint was unmodified, or the scale factor need to
980 * the original textSize
982 SkScalar getScale() const { return fScale; }
985 const SkPaint* fPaint;
987 SkTLazy<SkPaint> fLazy;
990 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
991 bounds->set(SkIntToScalar(g.fLeft),
992 SkIntToScalar(g.fTop),
993 SkIntToScalar(g.fLeft + g.fWidth),
994 SkIntToScalar(g.fTop + g.fHeight));
997 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
998 // we don't overflow along the way
999 typedef int64_t Sk48Dot16;
1001 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
1002 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
1005 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
1006 SkScalar sx = Sk48Dot16ToScalar(dx);
1007 bounds->join(SkIntToScalar(g.fLeft) + sx,
1008 SkIntToScalar(g.fTop),
1009 SkIntToScalar(g.fLeft + g.fWidth) + sx,
1010 SkIntToScalar(g.fTop + g.fHeight));
1013 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
1014 SkScalar sy = Sk48Dot16ToScalar(dy);
1015 bounds->join(SkIntToScalar(g.fLeft),
1016 SkIntToScalar(g.fTop) + sy,
1017 SkIntToScalar(g.fLeft + g.fWidth),
1018 SkIntToScalar(g.fTop + g.fHeight) + sy);
1021 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
1023 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
1024 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
1025 SkASSERT(0 == xyIndex || 1 == xyIndex);
1026 return (&glyph.fAdvanceX)[xyIndex];
1029 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
1030 const char* text, size_t byteLength,
1031 int* count, SkRect* bounds) const {
1033 if (byteLength == 0) {
1041 SkMeasureCacheProc glyphCacheProc;
1042 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1046 JoinBoundsProc joinBoundsProc;
1047 if (this->isVerticalText()) {
1049 joinBoundsProc = join_bounds_y;
1052 joinBoundsProc = join_bounds_x;
1056 const char* stop = (const char*)text + byteLength;
1057 const SkGlyph* g = &glyphCacheProc(cache, &text);
1058 // our accumulated fixed-point advances might overflow 16.16, so we use
1059 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
1061 Sk48Dot16 x = advance(*g, xyIndex);
1063 SkAutoKern autokern;
1065 if (NULL == bounds) {
1066 if (this->isDevKernText()) {
1068 for (; text < stop; n++) {
1070 g = &glyphCacheProc(cache, &text);
1071 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
1074 for (; text < stop; n++) {
1075 x += advance(glyphCacheProc(cache, &text), xyIndex);
1079 set_bounds(*g, bounds);
1080 if (this->isDevKernText()) {
1082 for (; text < stop; n++) {
1084 g = &glyphCacheProc(cache, &text);
1085 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
1086 joinBoundsProc(*g, bounds, x);
1087 x += advance(*g, xyIndex);
1090 for (; text < stop; n++) {
1091 g = &glyphCacheProc(cache, &text);
1092 joinBoundsProc(*g, bounds, x);
1093 x += advance(*g, xyIndex);
1097 SkASSERT(text == stop);
1100 return Sk48Dot16ToScalar(x);
1103 SkScalar SkPaint::measureText(const void* textData, size_t length,
1104 SkRect* bounds, SkScalar zoom) const {
1105 const char* text = (const char*)textData;
1106 SkASSERT(text != NULL || length == 0);
1108 SkCanonicalizePaint canon(*this);
1109 const SkPaint& paint = canon.getPaint();
1110 SkScalar scale = canon.getScale();
1112 SkMatrix zoomMatrix, *zoomPtr = NULL;
1114 zoomMatrix.setScale(zoom, zoom);
1115 zoomPtr = &zoomMatrix;
1118 SkAutoGlyphCache autoCache(paint, NULL, zoomPtr);
1119 SkGlyphCache* cache = autoCache.getCache();
1126 width = paint.measure_text(cache, text, length, &tempCount, bounds);
1128 width = SkScalarMul(width, scale);
1130 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
1131 bounds->fTop = SkScalarMul(bounds->fTop, scale);
1132 bounds->fRight = SkScalarMul(bounds->fRight, scale);
1133 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
1136 } else if (bounds) {
1137 // ensure that even if we don't measure_text we still update the bounds
1143 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
1145 static bool forward_textBufferPred(const char* text, const char* stop) {
1149 static bool backward_textBufferPred(const char* text, const char* stop) {
1153 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
1154 const char** text, size_t length,
1155 const char** stop) {
1156 if (SkPaint::kForward_TextBufferDirection == tbd) {
1157 *stop = *text + length;
1158 return forward_textBufferPred;
1160 // text should point to the end of the buffer, and stop to the beginning
1163 return backward_textBufferPred;
1167 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
1168 SkScalar* measuredWidth,
1169 TextBufferDirection tbd) const {
1170 if (0 == length || 0 >= maxWidth) {
1171 if (measuredWidth) {
1177 if (0 == fTextSize) {
1178 if (measuredWidth) {
1184 SkASSERT(textD != NULL);
1185 const char* text = (const char*)textD;
1187 SkCanonicalizePaint canon(*this);
1188 const SkPaint& paint = canon.getPaint();
1189 SkScalar scale = canon.getScale();
1191 // adjust max in case we changed the textSize in paint
1196 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1197 SkGlyphCache* cache = autoCache.getCache();
1199 SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
1201 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1202 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1203 // use 64bits for our accumulator, to avoid overflowing 16.16
1204 Sk48Dot16 max = SkScalarToFixed(maxWidth);
1205 Sk48Dot16 width = 0;
1207 SkAutoKern autokern;
1209 if (this->isDevKernText()) {
1211 while (pred(text, stop)) {
1212 const char* curr = text;
1213 const SkGlyph& g = glyphCacheProc(cache, &text);
1214 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
1215 if ((width += x) > max) {
1223 while (pred(text, stop)) {
1224 const char* curr = text;
1225 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
1226 if ((width += x) > max) {
1234 if (measuredWidth) {
1235 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1237 scalarWidth = SkScalarMul(scalarWidth, scale);
1239 *measuredWidth = scalarWidth;
1242 // return the number of bytes measured
1243 return (kForward_TextBufferDirection == tbd) ?
1244 text - stop + length : stop - text + length;
1247 ///////////////////////////////////////////////////////////////////////////////
1249 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1250 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1251 return false; // don't detach the cache
1254 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1256 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1259 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1260 SkCanonicalizePaint canon(*this);
1261 const SkPaint& paint = canon.getPaint();
1262 SkScalar scale = canon.getScale();
1264 SkMatrix zoomMatrix, *zoomPtr = NULL;
1266 zoomMatrix.setScale(zoom, zoom);
1267 zoomPtr = &zoomMatrix;
1270 FontMetrics storage;
1271 if (NULL == metrics) {
1275 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1278 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1279 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1280 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1281 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1282 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1283 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
1284 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
1285 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
1286 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
1287 metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
1288 metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
1290 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1293 ///////////////////////////////////////////////////////////////////////////////
1295 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1296 bounds->set(g.fLeft * scale,
1298 (g.fLeft + g.fWidth) * scale,
1299 (g.fTop + g.fHeight) * scale);
1302 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1303 SkScalar widths[], SkRect bounds[]) const {
1304 if (0 == byteLength) {
1308 SkASSERT(NULL != textData);
1310 if (NULL == widths && NULL == bounds) {
1311 return this->countText(textData, byteLength);
1314 SkCanonicalizePaint canon(*this);
1315 const SkPaint& paint = canon.getPaint();
1316 SkScalar scale = canon.getScale();
1318 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1319 SkGlyphCache* cache = autoCache.getCache();
1320 SkMeasureCacheProc glyphCacheProc;
1321 glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
1324 const char* text = (const char*)textData;
1325 const char* stop = text + byteLength;
1327 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1329 if (this->isDevKernText()) {
1330 // we adjust the widths returned here through auto-kerning
1331 SkAutoKern autokern;
1332 SkFixed prevWidth = 0;
1335 while (text < stop) {
1336 const SkGlyph& g = glyphCacheProc(cache, &text);
1338 SkFixed adjust = autokern.adjust(g);
1341 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1342 *widths++ = SkScalarMul(w, scale);
1344 prevWidth = advance(g, xyIndex);
1347 set_bounds(g, bounds++, scale);
1351 if (count > 0 && widths) {
1352 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1355 while (text < stop) {
1356 const SkGlyph& g = glyphCacheProc(cache, &text);
1358 SkFixed adjust = autokern.adjust(g);
1361 *widths++ = SkFixedToScalar(prevWidth + adjust);
1363 prevWidth = advance(g, xyIndex);
1366 set_bounds(g, bounds++);
1370 if (count > 0 && widths) {
1371 *widths = SkFixedToScalar(prevWidth);
1374 } else { // no devkern
1376 while (text < stop) {
1377 const SkGlyph& g = glyphCacheProc(cache, &text);
1379 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
1383 set_bounds(g, bounds++, scale);
1388 while (text < stop) {
1389 const SkGlyph& g = glyphCacheProc(cache, &text);
1391 *widths++ = SkFixedToScalar(advance(g, xyIndex));
1394 set_bounds(g, bounds++);
1401 SkASSERT(text == stop);
1405 ///////////////////////////////////////////////////////////////////////////////
1409 void SkPaint::getTextPath(const void* textData, size_t length,
1410 SkScalar x, SkScalar y, SkPath* path) const {
1411 SkASSERT(length == 0 || textData != NULL);
1413 const char* text = (const char*)textData;
1414 if (text == NULL || length == 0 || path == NULL) {
1418 SkTextToPathIter iter(text, length, *this, false);
1420 SkScalar prevXPos = 0;
1422 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1423 matrix.postTranslate(x, y);
1427 const SkPath* iterPath;
1428 while (iter.next(&iterPath, &xpos)) {
1429 matrix.postTranslate(xpos - prevXPos, 0);
1431 path->addPath(*iterPath, matrix);
1437 void SkPaint::getPosTextPath(const void* textData, size_t length,
1438 const SkPoint pos[], SkPath* path) const {
1439 SkASSERT(length == 0 || textData != NULL);
1441 const char* text = (const char*)textData;
1442 if (text == NULL || length == 0 || path == NULL) {
1446 SkTextToPathIter iter(text, length, *this, false);
1451 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1455 const SkPath* iterPath;
1456 while (iter.next(&iterPath, NULL)) {
1457 matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1459 path->addPath(*iterPath, matrix);
1466 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1467 SkWriteBuffer* buffer) {
1468 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
1471 // SkFontHost can override this choice in FilterRec()
1472 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1473 uint32_t flags = paint.getFlags();
1475 // Antialiasing being disabled trumps all other settings.
1476 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1477 return SkMask::kBW_Format;
1480 if (flags & SkPaint::kLCDRenderText_Flag) {
1481 return SkMask::kLCD16_Format;
1484 return SkMask::kA8_Format;
1487 // if linear-text is on, then we force hinting to be off (since that's sort of
1488 // the point of linear-text.
1489 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1490 SkPaint::Hinting h = paint.getHinting();
1491 if (paint.isLinearText()) {
1492 h = SkPaint::kNo_Hinting;
1497 // return true if the paint is just a single color (i.e. not a shader). If its
1498 // a shader, then we can't compute a const luminance for it :(
1499 static bool justAColor(const SkPaint& paint, SkColor* color) {
1500 if (paint.getShader()) {
1503 SkColor c = paint.getColor();
1504 if (paint.getColorFilter()) {
1505 c = paint.getColorFilter()->filterColor(c);
1513 static SkColor computeLuminanceColor(const SkPaint& paint) {
1515 if (!justAColor(paint, &c)) {
1516 c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1521 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1523 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1524 // cost more RAM and draws slower, so we set a cap.
1525 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1526 #define SK_MAX_SIZE_FOR_LCDTEXT 48
1529 static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
1530 SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1531 rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1532 SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
1533 return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
1537 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1538 * that vary only slightly when we create our key into the font cache, since the font scaler
1539 * typically returns the same looking resuts for tiny changes in the matrix.
1541 static SkScalar sk_relax(SkScalar x) {
1542 int n = sk_float_round2int(x * 1024);
1546 void SkScalerContext::MakeRec(const SkPaint& paint,
1547 const SkDeviceProperties* deviceProperties,
1548 const SkMatrix* deviceMatrix,
1550 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1552 SkTypeface* typeface = paint.getTypeface();
1553 if (NULL == typeface) {
1554 typeface = SkTypeface::GetDefaultTypeface();
1556 rec->fOrigFontID = typeface->uniqueID();
1557 rec->fFontID = rec->fOrigFontID;
1558 rec->fTextSize = paint.getTextSize();
1559 rec->fPreScaleX = paint.getTextScaleX();
1560 rec->fPreSkewX = paint.getTextSkewX();
1563 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1564 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1565 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1566 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1568 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1569 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1572 SkPaint::Style style = paint.getStyle();
1573 SkScalar strokeWidth = paint.getStrokeWidth();
1577 if (paint.isFakeBoldText()) {
1578 #ifdef SK_USE_FREETYPE_EMBOLDEN
1579 flags |= SkScalerContext::kEmbolden_Flag;
1581 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1582 kStdFakeBoldInterpKeys,
1583 kStdFakeBoldInterpValues,
1584 kStdFakeBoldInterpLength);
1585 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1587 if (style == SkPaint::kFill_Style) {
1588 style = SkPaint::kStrokeAndFill_Style;
1589 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1591 strokeWidth += extra;
1596 if (paint.isDevKernText()) {
1597 flags |= SkScalerContext::kDevKernText_Flag;
1600 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1601 rec->fFrameWidth = strokeWidth;
1602 rec->fMiterLimit = paint.getStrokeMiter();
1603 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1605 if (style == SkPaint::kStrokeAndFill_Style) {
1606 flags |= SkScalerContext::kFrameAndFill_Flag;
1609 rec->fFrameWidth = 0;
1610 rec->fMiterLimit = 0;
1611 rec->fStrokeJoin = 0;
1614 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1616 SkDeviceProperties::Geometry geometry = deviceProperties
1617 ? deviceProperties->fGeometry
1618 : SkDeviceProperties::Geometry::MakeDefault();
1619 if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
1620 if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) {
1621 // eeek, can't support LCD
1622 rec->fMaskFormat = SkMask::kA8_Format;
1624 if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) {
1625 flags |= SkScalerContext::kLCD_Vertical_Flag;
1627 if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) {
1628 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1633 if (paint.isEmbeddedBitmapText()) {
1634 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1636 if (paint.isSubpixelText()) {
1637 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1639 if (paint.isAutohinted()) {
1640 flags |= SkScalerContext::kForceAutohinting_Flag;
1642 if (paint.isVerticalText()) {
1643 flags |= SkScalerContext::kVertical_Flag;
1645 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1646 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1648 rec->fFlags = SkToU16(flags);
1650 // these modify fFlags, so do them after assigning fFlags
1651 rec->setHinting(computeHinting(paint));
1653 rec->setLuminanceColor(computeLuminanceColor(paint));
1655 if (NULL == deviceProperties) {
1656 rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1657 rec->setPaintGamma(SK_GAMMA_EXPONENT);
1659 rec->setDeviceGamma(deviceProperties->fGamma);
1661 //For now always set the paint gamma equal to the device gamma.
1662 //The math in SkMaskGamma can handle them being different,
1663 //but it requires superluminous masks when
1664 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1665 rec->setPaintGamma(deviceProperties->fGamma);
1668 #ifdef SK_GAMMA_CONTRAST
1669 rec->setContrast(SK_GAMMA_CONTRAST);
1672 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1673 * With lower values small text appears washed out (though correctly so).
1674 * With higher values lcd fringing is worse and the smoothing effect of
1675 * partial coverage is diminished.
1677 rec->setContrast(0.5f);
1680 rec->fReservedAlign = 0;
1682 /* Allow the fonthost to modify our rec before we use it as a key into the
1683 cache. This way if we're asking for something that they will ignore,
1684 they can modify our rec up front, so we don't create duplicate cache
1687 typeface->onFilterRec(rec);
1689 // be sure to call PostMakeRec(rec) before you actually use it!
1693 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1694 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1695 * to hold it until the returned pointer is refed or forgotten.
1697 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1699 static SkMaskGamma* gLinearMaskGamma = NULL;
1700 static SkMaskGamma* gMaskGamma = NULL;
1701 static SkScalar gContrast = SK_ScalarMin;
1702 static SkScalar gPaintGamma = SK_ScalarMin;
1703 static SkScalar gDeviceGamma = SK_ScalarMin;
1705 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1706 * the returned SkMaskGamma pointer is refed or forgotten.
1708 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1709 gMaskGammaCacheMutex.assertHeld();
1710 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1711 if (NULL == gLinearMaskGamma) {
1712 gLinearMaskGamma = SkNEW(SkMaskGamma);
1714 return *gLinearMaskGamma;
1716 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1717 SkSafeUnref(gMaskGamma);
1718 gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
1719 gContrast = contrast;
1720 gPaintGamma = paintGamma;
1721 gDeviceGamma = deviceGamma;
1726 /*static*/ void SkPaint::Term() {
1727 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1729 SkSafeUnref(gLinearMaskGamma);
1730 gLinearMaskGamma = NULL;
1731 SkSafeUnref(gMaskGamma);
1733 SkDEBUGCODE(gContrast = SK_ScalarMin;)
1734 SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1735 SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1739 * We ensure that the rec is self-consistent and efficient (where possible)
1741 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
1743 * If we're asking for A8, we force the colorlum to be gray, since that
1744 * limits the number of unique entries, and the scaler will only look at
1745 * the lum of one of them.
1747 switch (rec->fMaskFormat) {
1748 case SkMask::kLCD16_Format:
1749 case SkMask::kLCD32_Format: {
1750 // filter down the luminance color to a finite number of bits
1751 SkColor color = rec->getLuminanceColor();
1752 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1755 case SkMask::kA8_Format: {
1756 // filter down the luminance to a single component, since A8 can't
1757 // use per-component information
1758 SkColor color = rec->getLuminanceColor();
1759 U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1761 SkColorGetB(color));
1762 // reduce to our finite number of bits
1763 color = SkColorSetRGB(lum, lum, lum);
1764 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1767 case SkMask::kBW_Format:
1768 // No need to differentiate gamma if we're BW
1769 rec->ignorePreBlend();
1774 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1781 * ignoreGamma tells us that the caller just wants metrics that are unaffected
1782 * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
1783 * contrast = 0, luminanceColor = transparent black.
1785 void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1786 const SkMatrix* deviceMatrix,
1787 void (*proc)(SkTypeface*, const SkDescriptor*, void*),
1788 void* context, bool ignoreGamma) const {
1789 SkScalerContext::Rec rec;
1791 SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
1793 rec.ignorePreBlend();
1796 size_t descSize = sizeof(rec);
1798 SkPathEffect* pe = this->getPathEffect();
1799 SkMaskFilter* mf = this->getMaskFilter();
1800 SkRasterizer* ra = this->getRasterizer();
1802 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1805 peBuffer.writeFlattenable(pe);
1806 descSize += peBuffer.bytesWritten();
1808 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1809 // seems like we could support kLCD as well at this point...
1812 mfBuffer.writeFlattenable(mf);
1813 descSize += mfBuffer.bytesWritten();
1815 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1816 /* Pre-blend is not currently applied to filtered text.
1817 The primary filter is blur, for which contrast makes no sense,
1818 and for which the destination guess error is more visible.
1819 Also, all existing users of blur have calibrated for linear. */
1820 rec.ignorePreBlend();
1823 raBuffer.writeFlattenable(ra);
1824 descSize += raBuffer.bytesWritten();
1826 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1829 ///////////////////////////////////////////////////////////////////////////
1830 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1831 SkScalerContext::PostMakeRec(*this, &rec);
1833 descSize += SkDescriptor::ComputeOverhead(entryCount);
1835 SkAutoDescriptor ad(descSize);
1836 SkDescriptor* desc = ad.getDesc();
1839 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1842 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1845 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1848 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1851 SkASSERT(descSize == desc->getLength());
1852 desc->computeChecksum();
1856 // Check that we completely write the bytes in desc (our key), and that
1857 // there are no uninitialized bytes. If there were, then we would get
1858 // false-misses (or worse, false-hits) in our fontcache.
1860 // We do this buy filling 2 others, one with 0s and the other with 1s
1861 // and create those, and then check that all 3 are identical.
1862 SkAutoDescriptor ad1(descSize);
1863 SkAutoDescriptor ad2(descSize);
1864 SkDescriptor* desc1 = ad1.getDesc();
1865 SkDescriptor* desc2 = ad2.getDesc();
1867 memset(desc1, 0x00, descSize);
1868 memset(desc2, 0xFF, descSize);
1872 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1873 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1876 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
1877 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
1880 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
1881 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
1884 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
1885 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
1888 SkASSERT(descSize == desc1->getLength());
1889 SkASSERT(descSize == desc2->getLength());
1890 desc1->computeChecksum();
1891 desc2->computeChecksum();
1892 SkASSERT(!memcmp(desc, desc1, descSize));
1893 SkASSERT(!memcmp(desc, desc2, descSize));
1897 proc(fTypeface, desc, context);
1900 SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
1901 const SkMatrix* deviceMatrix,
1902 bool ignoreGamma) const {
1903 SkGlyphCache* cache;
1904 this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
1909 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1912 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
1913 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1914 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1915 rec.getPaintGamma(),
1916 rec.getDeviceGamma());
1917 return maskGamma.preBlend(rec.getLuminanceColor());
1920 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
1921 SkScalar deviceGamma, int* width, int* height) {
1922 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1923 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1927 maskGamma.getGammaTableDimensions(width, height);
1928 size_t size = (*width)*(*height)*sizeof(uint8_t);
1933 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
1935 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1936 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1940 maskGamma.getGammaTableDimensions(&width, &height);
1941 size_t size = width*height*sizeof(uint8_t);
1942 const uint8_t* gammaTables = maskGamma.getGammaTables();
1943 memcpy(data, gammaTables, size);
1947 ///////////////////////////////////////////////////////////////////////////////
1949 #include "SkStream.h"
1951 static uintptr_t asint(const void* p) {
1952 return reinterpret_cast<uintptr_t>(p);
1960 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1961 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1963 tmp.fScalar = value;
1968 static SkScalar read_scalar(const uint32_t*& ptr) {
1969 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1975 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1976 SkASSERT(a == (uint8_t)a);
1977 SkASSERT(b == (uint8_t)b);
1978 SkASSERT(c == (uint8_t)c);
1979 SkASSERT(d == (uint8_t)d);
1980 return (a << 24) | (b << 16) | (c << 8) | d;
1984 static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
1985 SkASSERT(bitCount > 0 && bitCount <= 32);
1986 uint32_t mask = ~0U;
1987 mask >>= (32 - bitCount);
1988 SkASSERT(0 == (value & ~mask));
1991 #define ASSERT_FITS_IN(value, bitcount)
1995 kHasTypeface_FlatFlag = 0x01,
1996 kHasEffects_FlatFlag = 0x02,
1997 kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
1999 kFlatFlagMask = 0x7,
2010 static inline int BPF_Mask(int bits) {
2011 return (1 << bits) - 1;
2014 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
2015 unsigned filter, unsigned flatFlags) {
2016 ASSERT_FITS_IN(flags, kFlags_BPF);
2017 ASSERT_FITS_IN(hint, kHint_BPF);
2018 ASSERT_FITS_IN(align, kAlign_BPF);
2019 ASSERT_FITS_IN(filter, kFilter_BPF);
2020 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
2022 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
2023 // add more bits in the future.
2024 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
2027 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
2028 paint->setFlags(packed >> 16);
2029 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
2030 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
2031 paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
2032 return (FlatFlags)(packed & kFlatFlagMask);
2035 // V22_COMPATIBILITY_CODE
2036 static FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
2038 kFilterBitmap_Flag = 0x02,
2039 kHighQualityFilterBitmap_Flag = 0x4000,
2041 kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
2044 // previously flags:16, textAlign:8, flatFlags:8
2045 // now flags:16, hinting:4, textAlign:4, flatFlags:8
2046 unsigned flags = packed >> 16;
2048 if (flags & kFilterBitmap_Flag) {
2051 if (flags & kHighQualityFilterBitmap_Flag) {
2054 paint->setFilterLevel((SkPaint::FilterLevel)filter);
2055 flags &= ~kAll_Flags; // remove these (now dead) bit flags
2057 paint->setFlags(flags);
2059 // hinting added later. 0 in this nibble means use the default.
2060 uint32_t hinting = (packed >> 12) & 0xF;
2061 paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
2062 paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
2063 return (FlatFlags)(packed & kFlatFlagMask);
2066 // The size of a flat paint's POD fields
2067 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
2068 1 * sizeof(SkColor) +
2069 1 * sizeof(uint16_t) +
2070 6 * sizeof(uint8_t);
2072 /* To save space/time, we analyze the paint, and write a truncated version of
2073 it if there are not tricky elements like shaders, etc.
2075 void SkPaint::flatten(SkWriteBuffer& buffer) const {
2076 uint8_t flatFlags = 0;
2077 if (this->getTypeface()) {
2078 flatFlags |= kHasTypeface_FlatFlag;
2080 if (asint(this->getPathEffect()) |
2081 asint(this->getShader()) |
2082 asint(this->getXfermode()) |
2083 asint(this->getMaskFilter()) |
2084 asint(this->getColorFilter()) |
2085 asint(this->getRasterizer()) |
2086 asint(this->getLooper()) |
2087 asint(this->getAnnotation()) |
2088 asint(this->getImageFilter())) {
2089 flatFlags |= kHasEffects_FlatFlag;
2092 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
2093 uint32_t* ptr = buffer.reserve(kPODPaintSize);
2095 ptr = write_scalar(ptr, this->getTextSize());
2096 ptr = write_scalar(ptr, this->getTextScaleX());
2097 ptr = write_scalar(ptr, this->getTextSkewX());
2098 ptr = write_scalar(ptr, this->getStrokeWidth());
2099 ptr = write_scalar(ptr, this->getStrokeMiter());
2100 *ptr++ = this->getColor();
2102 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
2103 this->getFilterLevel(), flatFlags);
2104 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
2105 this->getStyle(), this->getTextEncoding());
2107 // now we're done with ptr and the (pre)reserved space. If we need to write
2108 // additional fields, use the buffer directly
2109 if (flatFlags & kHasTypeface_FlatFlag) {
2110 buffer.writeTypeface(this->getTypeface());
2112 if (flatFlags & kHasEffects_FlatFlag) {
2113 buffer.writeFlattenable(this->getPathEffect());
2114 buffer.writeFlattenable(this->getShader());
2115 buffer.writeFlattenable(this->getXfermode());
2116 buffer.writeFlattenable(this->getMaskFilter());
2117 buffer.writeFlattenable(this->getColorFilter());
2118 buffer.writeFlattenable(this->getRasterizer());
2119 buffer.writeFlattenable(this->getLooper());
2120 buffer.writeFlattenable(this->getImageFilter());
2123 buffer.writeBool(true);
2124 fAnnotation->writeToBuffer(buffer);
2126 buffer.writeBool(false);
2131 void SkPaint::unflatten(SkReadBuffer& buffer) {
2132 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
2133 const void* podData = buffer.skip(kPODPaintSize);
2134 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
2136 // the order we read must match the order we wrote in flatten()
2137 this->setTextSize(read_scalar(pod));
2138 this->setTextScaleX(read_scalar(pod));
2139 this->setTextSkewX(read_scalar(pod));
2140 this->setStrokeWidth(read_scalar(pod));
2141 this->setStrokeMiter(read_scalar(pod));
2142 this->setColor(*pod++);
2144 unsigned flatFlags = 0;
2145 if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) {
2146 flatFlags = unpack_paint_flags_v22(this, *pod++);
2148 flatFlags = unpack_paint_flags(this, *pod++);
2151 uint32_t tmp = *pod++;
2152 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
2153 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
2154 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
2155 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
2157 if (flatFlags & kHasTypeface_FlatFlag) {
2158 this->setTypeface(buffer.readTypeface());
2160 this->setTypeface(NULL);
2163 if (flatFlags & kHasEffects_FlatFlag) {
2164 SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
2165 SkSafeUnref(this->setShader(buffer.readShader()));
2166 SkSafeUnref(this->setXfermode(buffer.readXfermode()));
2167 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
2168 SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
2169 SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
2170 SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
2171 SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
2173 if (buffer.readBool()) {
2174 this->setAnnotation(SkAnnotation::Create(buffer))->unref();
2177 this->setPathEffect(NULL);
2178 this->setShader(NULL);
2179 this->setXfermode(NULL);
2180 this->setMaskFilter(NULL);
2181 this->setColorFilter(NULL);
2182 this->setRasterizer(NULL);
2183 this->setLooper(NULL);
2184 this->setImageFilter(NULL);
2187 if (buffer.isVersionLT(SkReadBuffer::kRemoveAndroidPaintOpts_Version) &&
2188 flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
2191 buffer.readString(&tag);
2196 ///////////////////////////////////////////////////////////////////////////////
2198 SkShader* SkPaint::setShader(SkShader* shader) {
2199 GEN_ID_INC_EVAL(shader != fShader);
2200 SkRefCnt_SafeAssign(fShader, shader);
2201 fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
2205 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2206 GEN_ID_INC_EVAL(filter != fColorFilter);
2207 SkRefCnt_SafeAssign(fColorFilter, filter);
2208 fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
2212 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2213 GEN_ID_INC_EVAL(mode != fXfermode);
2214 SkRefCnt_SafeAssign(fXfermode, mode);
2215 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
2219 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2220 SkSafeUnref(fXfermode);
2221 fXfermode = SkXfermode::Create(mode);
2223 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
2227 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2228 GEN_ID_INC_EVAL(effect != fPathEffect);
2229 SkRefCnt_SafeAssign(fPathEffect, effect);
2230 fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
2234 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2235 GEN_ID_INC_EVAL(filter != fMaskFilter);
2236 SkRefCnt_SafeAssign(fMaskFilter, filter);
2237 fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
2241 ///////////////////////////////////////////////////////////////////////////////
2243 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
2244 const SkRect* cullRect) const {
2245 SkStrokeRec rec(*this);
2247 const SkPath* srcPtr = &src;
2250 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2254 if (!rec.applyToPath(dst, *srcPtr)) {
2255 if (srcPtr == &tmpPath) {
2256 // If path's were copy-on-write, this trick would not be needed.
2257 // As it is, we want to save making a deep-copy from tmpPath -> dst
2258 // since we know we're just going to delete tmpPath when we return,
2259 // so the swap saves that copy.
2265 return !rec.isHairlineStyle();
2268 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2270 Style style) const {
2273 const SkRect* src = &origSrc;
2275 if (this->getLooper()) {
2276 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2277 this->getLooper()->computeFastBounds(*this, *src, storage);
2282 if (this->getPathEffect()) {
2283 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2287 if (kFill_Style != style) {
2288 // since we're stroked, outset the rect by the radius (and join type)
2289 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2290 if (0 == radius) { // hairline
2291 radius = SK_Scalar1;
2292 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2293 SkScalar scale = this->getStrokeMiter();
2294 if (scale > SK_Scalar1) {
2295 radius = SkScalarMul(radius, scale);
2298 storage->set(src->fLeft - radius, src->fTop - radius,
2299 src->fRight + radius, src->fBottom + radius);
2304 if (this->getMaskFilter()) {
2305 this->getMaskFilter()->computeFastBounds(*storage, storage);
2308 if (this->getImageFilter()) {
2309 this->getImageFilter()->computeFastBounds(*storage, storage);
2315 #ifndef SK_IGNORE_TO_STRING
2316 void SkPaint::toString(SkString* str) const {
2317 str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2319 SkTypeface* typeface = this->getTypeface();
2320 if (NULL != typeface) {
2321 SkDynamicMemoryWStream ostream;
2322 typeface->serialize(&ostream);
2323 SkAutoTUnref<SkData> data(ostream.copyToData());
2325 SkMemoryStream stream(data);
2326 SkFontDescriptor descriptor(&stream);
2328 str->append("<dt>Font Family Name:</dt><dd>");
2329 str->append(descriptor.getFamilyName());
2330 str->append("</dd><dt>Font Full Name:</dt><dd>");
2331 str->append(descriptor.getFullName());
2332 str->append("</dd><dt>Font PS Name:</dt><dd>");
2333 str->append(descriptor.getPostscriptName());
2334 str->append("</dd><dt>Font File Name:</dt><dd>");
2335 str->append(descriptor.getFontFileName());
2336 str->append("</dd>");
2339 str->append("<dt>TextSize:</dt><dd>");
2340 str->appendScalar(this->getTextSize());
2341 str->append("</dd>");
2343 str->append("<dt>TextScaleX:</dt><dd>");
2344 str->appendScalar(this->getTextScaleX());
2345 str->append("</dd>");
2347 str->append("<dt>TextSkewX:</dt><dd>");
2348 str->appendScalar(this->getTextSkewX());
2349 str->append("</dd>");
2351 SkPathEffect* pathEffect = this->getPathEffect();
2352 if (NULL != pathEffect) {
2353 str->append("<dt>PathEffect:</dt><dd>");
2354 str->append("</dd>");
2357 SkShader* shader = this->getShader();
2358 if (NULL != shader) {
2359 str->append("<dt>Shader:</dt><dd>");
2360 shader->toString(str);
2361 str->append("</dd>");
2364 SkXfermode* xfer = this->getXfermode();
2366 str->append("<dt>Xfermode:</dt><dd>");
2367 xfer->toString(str);
2368 str->append("</dd>");
2371 SkMaskFilter* maskFilter = this->getMaskFilter();
2372 if (NULL != maskFilter) {
2373 str->append("<dt>MaskFilter:</dt><dd>");
2374 maskFilter->toString(str);
2375 str->append("</dd>");
2378 SkColorFilter* colorFilter = this->getColorFilter();
2379 if (NULL != colorFilter) {
2380 str->append("<dt>ColorFilter:</dt><dd>");
2381 colorFilter->toString(str);
2382 str->append("</dd>");
2385 SkRasterizer* rasterizer = this->getRasterizer();
2386 if (NULL != rasterizer) {
2387 str->append("<dt>Rasterizer:</dt><dd>");
2388 str->append("</dd>");
2391 SkDrawLooper* looper = this->getLooper();
2392 if (NULL != looper) {
2393 str->append("<dt>DrawLooper:</dt><dd>");
2394 looper->toString(str);
2395 str->append("</dd>");
2398 SkImageFilter* imageFilter = this->getImageFilter();
2399 if (NULL != imageFilter) {
2400 str->append("<dt>ImageFilter:</dt><dd>");
2401 str->append("</dd>");
2404 SkAnnotation* annotation = this->getAnnotation();
2405 if (NULL != annotation) {
2406 str->append("<dt>Annotation:</dt><dd>");
2407 str->append("</dd>");
2410 str->append("<dt>Color:</dt><dd>0x");
2411 SkColor color = this->getColor();
2412 str->appendHex(color);
2413 str->append("</dd>");
2415 str->append("<dt>Stroke Width:</dt><dd>");
2416 str->appendScalar(this->getStrokeWidth());
2417 str->append("</dd>");
2419 str->append("<dt>Stroke Miter:</dt><dd>");
2420 str->appendScalar(this->getStrokeMiter());
2421 str->append("</dd>");
2423 str->append("<dt>Flags:</dt><dd>(");
2424 if (this->getFlags()) {
2425 bool needSeparator = false;
2426 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2427 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2428 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2429 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2430 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2431 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2432 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2433 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2434 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2435 SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2436 "EmbeddedBitmapText", &needSeparator);
2437 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2438 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2439 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2440 "GenA8FromLCD", &needSeparator);
2442 str->append("None");
2444 str->append(")</dd>");
2446 str->append("<dt>FilterLevel:</dt><dd>");
2447 static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
2448 str->append(gFilterLevelStrings[this->getFilterLevel()]);
2449 str->append("</dd>");
2451 str->append("<dt>TextAlign:</dt><dd>");
2452 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2453 str->append(gTextAlignStrings[this->getTextAlign()]);
2454 str->append("</dd>");
2456 str->append("<dt>CapType:</dt><dd>");
2457 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2458 str->append(gStrokeCapStrings[this->getStrokeCap()]);
2459 str->append("</dd>");
2461 str->append("<dt>JoinType:</dt><dd>");
2462 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2463 str->append(gJoinStrings[this->getStrokeJoin()]);
2464 str->append("</dd>");
2466 str->append("<dt>Style:</dt><dd>");
2467 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2468 str->append(gStyleStrings[this->getStyle()]);
2469 str->append("</dd>");
2471 str->append("<dt>TextEncoding:</dt><dd>");
2472 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2473 str->append(gTextEncodingStrings[this->getTextEncoding()]);
2474 str->append("</dd>");
2476 str->append("<dt>Hinting:</dt><dd>");
2477 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2478 str->append(gHintingStrings[this->getHinting()]);
2479 str->append("</dd>");
2481 str->append("</dd></dl></dl>");
2485 ///////////////////////////////////////////////////////////////////////////////
2487 static bool has_thick_frame(const SkPaint& paint) {
2488 return paint.getStrokeWidth() > 0 &&
2489 paint.getStyle() != SkPaint::kFill_Style;
2492 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
2493 const SkPaint& paint,
2494 bool applyStrokeAndPathEffects)
2496 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
2499 fPaint.setLinearText(true);
2500 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2502 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2503 applyStrokeAndPathEffects = false;
2506 // can't use our canonical size if we need to apply patheffects
2507 if (fPaint.getPathEffect() == NULL) {
2508 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2509 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2510 if (has_thick_frame(fPaint)) {
2511 fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2514 fScale = SK_Scalar1;
2517 if (!applyStrokeAndPathEffects) {
2518 fPaint.setStyle(SkPaint::kFill_Style);
2519 fPaint.setPathEffect(NULL);
2522 fCache = fPaint.detachCache(NULL, NULL, false);
2524 SkPaint::Style style = SkPaint::kFill_Style;
2525 SkPathEffect* pe = NULL;
2527 if (!applyStrokeAndPathEffects) {
2528 style = paint.getStyle(); // restore
2529 pe = paint.getPathEffect(); // restore
2531 fPaint.setStyle(style);
2532 fPaint.setPathEffect(pe);
2533 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
2535 // now compute fXOffset if needed
2537 SkScalar xOffset = 0;
2538 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2540 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
2541 &count, NULL), fScale);
2542 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2543 width = SkScalarHalf(width);
2551 fStop = text + length;
2553 fXYIndex = paint.isVerticalText() ? 1 : 0;
2556 SkTextToPathIter::~SkTextToPathIter() {
2557 SkGlyphCache::AttachCache(fCache);
2560 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2561 if (fText < fStop) {
2562 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2564 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2565 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2569 *path = fCache->findPath(glyph);
2584 ///////////////////////////////////////////////////////////////////////////////
2586 bool SkPaint::nothingToDraw() const {
2590 SkXfermode::Mode mode;
2591 if (SkXfermode::AsMode(fXfermode, &mode)) {
2593 case SkXfermode::kSrcOver_Mode:
2594 case SkXfermode::kSrcATop_Mode:
2595 case SkXfermode::kDstOut_Mode:
2596 case SkXfermode::kDstOver_Mode:
2597 case SkXfermode::kPlus_Mode:
2598 return 0 == this->getAlpha();
2599 case SkXfermode::kDst_Mode:
2608 inline static unsigned popcount(uint8_t x) {
2609 // As in Hacker's delight, adapted for just 8 bits.
2610 x = (x & 0x55) + ((x >> 1) & 0x55); // a b c d w x y z -> a+b c+d w+x y+z
2611 x = (x & 0x33) + ((x >> 2) & 0x33); // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
2612 x = (x & 0x0F) + ((x >> 4) & 0x0F); // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
2616 void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
2617 const uint32_t dirty = paint.fDirtyBits;
2619 // Each of the low 7 dirty bits corresponds to a 4-byte flat value,
2620 // plus one for the dirty bits and one for the bitfields
2621 const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2);
2622 SkASSERT(flatBytes <= 32);
2623 uint32_t* u32 = buffer.reserve(flatBytes);
2625 *u32++ = paint.fBitfieldsUInt;
2630 #define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
2632 SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
2636 F(f32, StrokeWidth);
2637 F(f32, StrokeMiter);
2639 #define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
2649 if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
2650 if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
2653 void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
2654 const uint32_t dirty = buffer.readUInt();
2655 paint->fBitfieldsUInt = buffer.readUInt();
2659 #define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
2660 // Same function, except it unrefs the object newly set on the paint:
2661 #define F_UNREF(field, reader) \
2662 if (dirty & k##field##_DirtyBit) \
2663 paint->set##field(buffer.reader())->unref()
2666 F(TextSize, readScalar);
2667 F(TextScaleX, readScalar);
2668 F(TextSkewX, readScalar);
2669 F(StrokeWidth, readScalar);
2670 F(StrokeMiter, readScalar);
2671 F_UNREF(PathEffect, readPathEffect);
2672 F_UNREF(Shader, readShader);
2673 F_UNREF(Xfermode, readXfermode);
2674 F_UNREF(MaskFilter, readMaskFilter);
2675 F_UNREF(ColorFilter, readColorFilter);
2676 F_UNREF(Rasterizer, readRasterizer);
2677 F_UNREF(Looper, readDrawLooper);
2678 F_UNREF(ImageFilter, readImageFilter);
2679 F(Typeface, readTypeface);
2682 if (dirty & kAnnotation_DirtyBit) {
2683 paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
2685 SkASSERT(dirty == paint->fDirtyBits);