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 "SkChecksum.h"
12 #include "SkColorFilter.h"
14 #include "SkDeviceProperties.h"
16 #include "SkFontDescriptor.h"
17 #include "SkFontHost.h"
18 #include "SkGlyphCache.h"
19 #include "SkImageFilter.h"
20 #include "SkMaskFilter.h"
21 #include "SkMaskGamma.h"
22 #include "SkReadBuffer.h"
23 #include "SkWriteBuffer.h"
24 #include "SkPaintDefaults.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"
38 // define this to get a printf for out-of-range parameter in setters
39 // e.g. setTextSize(-1)
40 //#define SK_REPORT_API_RANGE_CHECK
54 fTextSize = SkPaintDefaults_TextSize;
55 fTextScaleX = SK_Scalar1;
57 fColor = SK_ColorBLACK;
59 fMiterLimit = SkPaintDefaults_MiterLimit;
61 // Zero all bitfields, then set some non-zero defaults.
63 fBitfields.fFlags = SkPaintDefaults_Flags;
64 fBitfields.fCapType = kDefault_Cap;
65 fBitfields.fJoinType = kDefault_Join;
66 fBitfields.fTextAlign = kLeft_Align;
67 fBitfields.fStyle = kFill_Style;
68 fBitfields.fTextEncoding = kUTF8_TextEncoding;
69 fBitfields.fHinting = SkPaintDefaults_Hinting;
72 SkPaint::SkPaint(const SkPaint& src) {
73 #define COPY(field) field = src.field
74 #define REF_COPY(field) field = SkSafeRef(src.field)
77 REF_COPY(fPathEffect);
80 REF_COPY(fMaskFilter);
81 REF_COPY(fColorFilter);
82 REF_COPY(fRasterizer);
84 REF_COPY(fImageFilter);
85 REF_COPY(fAnnotation);
100 SkSafeUnref(fTypeface);
101 SkSafeUnref(fPathEffect);
102 SkSafeUnref(fShader);
103 SkSafeUnref(fXfermode);
104 SkSafeUnref(fMaskFilter);
105 SkSafeUnref(fColorFilter);
106 SkSafeUnref(fRasterizer);
107 SkSafeUnref(fLooper);
108 SkSafeUnref(fImageFilter);
109 SkSafeUnref(fAnnotation);
112 SkPaint& SkPaint::operator=(const SkPaint& src) {
117 #define COPY(field) field = src.field
118 #define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
123 REF_COPY(fPathEffect);
126 REF_COPY(fMaskFilter);
127 REF_COPY(fColorFilter);
128 REF_COPY(fRasterizer);
130 REF_COPY(fImageFilter);
131 REF_COPY(fAnnotation);
147 bool operator==(const SkPaint& a, const SkPaint& b) {
148 #define EQUAL(field) (a.field == b.field)
149 return EQUAL(fTypeface)
150 && EQUAL(fPathEffect)
153 && EQUAL(fMaskFilter)
154 && EQUAL(fColorFilter)
155 && EQUAL(fRasterizer)
157 && EQUAL(fImageFilter)
158 && EQUAL(fAnnotation)
160 && EQUAL(fTextScaleX)
164 && EQUAL(fMiterLimit)
165 && EQUAL(fBitfieldsUInt)
170 void SkPaint::reset() {
175 void SkPaint::setFilterLevel(FilterLevel level) {
176 fBitfields.fFilterLevel = level;
179 void SkPaint::setHinting(Hinting hintingLevel) {
180 fBitfields.fHinting = hintingLevel;
183 void SkPaint::setFlags(uint32_t flags) {
184 fBitfields.fFlags = flags;
187 void SkPaint::setAntiAlias(bool doAA) {
188 this->setFlags(SkSetClearMask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
191 void SkPaint::setDither(bool doDither) {
192 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDither, kDither_Flag));
195 void SkPaint::setSubpixelText(bool doSubpixel) {
196 this->setFlags(SkSetClearMask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
199 void SkPaint::setLCDRenderText(bool doLCDRender) {
200 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
203 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
204 this->setFlags(SkSetClearMask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
207 void SkPaint::setAutohinted(bool useAutohinter) {
208 this->setFlags(SkSetClearMask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
211 void SkPaint::setLinearText(bool doLinearText) {
212 this->setFlags(SkSetClearMask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
215 void SkPaint::setVerticalText(bool doVertical) {
216 this->setFlags(SkSetClearMask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
219 void SkPaint::setUnderlineText(bool doUnderline) {
220 this->setFlags(SkSetClearMask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag));
223 void SkPaint::setStrikeThruText(bool doStrikeThru) {
224 this->setFlags(SkSetClearMask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag));
227 void SkPaint::setFakeBoldText(bool doFakeBold) {
228 this->setFlags(SkSetClearMask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
231 void SkPaint::setDevKernText(bool doDevKern) {
232 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
235 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
236 this->setFlags(SkSetClearMask(fBitfields.fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
239 void SkPaint::setStyle(Style style) {
240 if ((unsigned)style < kStyleCount) {
241 fBitfields.fStyle = style;
243 #ifdef SK_REPORT_API_RANGE_CHECK
244 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
249 void SkPaint::setColor(SkColor color) {
253 void SkPaint::setAlpha(U8CPU a) {
254 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
255 SkColorGetG(fColor), SkColorGetB(fColor)));
258 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
259 this->setColor(SkColorSetARGB(a, r, g, b));
262 void SkPaint::setStrokeWidth(SkScalar width) {
266 #ifdef SK_REPORT_API_RANGE_CHECK
267 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
272 void SkPaint::setStrokeMiter(SkScalar limit) {
276 #ifdef SK_REPORT_API_RANGE_CHECK
277 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
282 void SkPaint::setStrokeCap(Cap ct) {
283 if ((unsigned)ct < kCapCount) {
284 fBitfields.fCapType = SkToU8(ct);
286 #ifdef SK_REPORT_API_RANGE_CHECK
287 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
292 void SkPaint::setStrokeJoin(Join jt) {
293 if ((unsigned)jt < kJoinCount) {
294 fBitfields.fJoinType = SkToU8(jt);
296 #ifdef SK_REPORT_API_RANGE_CHECK
297 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
302 ///////////////////////////////////////////////////////////////////////////////
304 void SkPaint::setTextAlign(Align align) {
305 if ((unsigned)align < kAlignCount) {
306 fBitfields.fTextAlign = SkToU8(align);
308 #ifdef SK_REPORT_API_RANGE_CHECK
309 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
314 void SkPaint::setTextSize(SkScalar ts) {
318 #ifdef SK_REPORT_API_RANGE_CHECK
319 SkDebugf("SkPaint::setTextSize() called with negative value\n");
324 void SkPaint::setTextScaleX(SkScalar scaleX) {
325 fTextScaleX = scaleX;
328 void SkPaint::setTextSkewX(SkScalar skewX) {
332 void SkPaint::setTextEncoding(TextEncoding encoding) {
333 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
334 fBitfields.fTextEncoding = encoding;
336 #ifdef SK_REPORT_API_RANGE_CHECK
337 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
342 ///////////////////////////////////////////////////////////////////////////////
344 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
345 SkRefCnt_SafeAssign(fTypeface, font);
349 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
350 SkRefCnt_SafeAssign(fRasterizer, r);
354 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
355 SkRefCnt_SafeAssign(fLooper, looper);
359 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
360 SkRefCnt_SafeAssign(fImageFilter, imageFilter);
364 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
365 SkRefCnt_SafeAssign(fAnnotation, annotation);
369 ///////////////////////////////////////////////////////////////////////////////
371 static SkScalar mag2(SkScalar x, SkScalar y) {
372 return x * x + y * y;
375 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
376 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
378 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
381 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
382 SkASSERT(!ctm.hasPerspective());
383 SkASSERT(!textM.hasPerspective());
386 matrix.setConcat(ctm, textM);
387 return tooBig(matrix, MaxCacheSize2());
391 ///////////////////////////////////////////////////////////////////////////////
393 #include "SkGlyphCache.h"
396 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
398 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
401 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
402 uint16_t glyphs[]) const {
403 if (byteLength == 0) {
407 SkASSERT(textData != NULL);
409 if (NULL == glyphs) {
410 switch (this->getTextEncoding()) {
411 case kUTF8_TextEncoding:
412 return SkUTF8_CountUnichars((const char*)textData, byteLength);
413 case kUTF16_TextEncoding:
414 return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
415 case kUTF32_TextEncoding:
416 return SkToInt(byteLength >> 2);
417 case kGlyphID_TextEncoding:
418 return SkToInt(byteLength >> 1);
420 SkDEBUGFAIL("unknown text encoding");
425 // if we get here, we have a valid glyphs[] array, so time to fill it in
427 // handle this encoding before the setup for the glyphcache
428 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
429 // we want to ignore the low bit of byteLength
430 memcpy(glyphs, textData, byteLength >> 1 << 1);
431 return SkToInt(byteLength >> 1);
434 SkAutoGlyphCache autoCache(*this, NULL, NULL);
435 SkGlyphCache* cache = autoCache.getCache();
437 const char* text = (const char*)textData;
438 const char* stop = text + byteLength;
439 uint16_t* gptr = glyphs;
441 switch (this->getTextEncoding()) {
442 case SkPaint::kUTF8_TextEncoding:
443 while (text < stop) {
444 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
447 case SkPaint::kUTF16_TextEncoding: {
448 const uint16_t* text16 = (const uint16_t*)text;
449 const uint16_t* stop16 = (const uint16_t*)stop;
450 while (text16 < stop16) {
451 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
455 case kUTF32_TextEncoding: {
456 const int32_t* text32 = (const int32_t*)text;
457 const int32_t* stop32 = (const int32_t*)stop;
458 while (text32 < stop32) {
459 *gptr++ = cache->unicharToGlyph(*text32++);
464 SkDEBUGFAIL("unknown text encoding");
466 return SkToInt(gptr - glyphs);
469 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
470 if (0 == byteLength) {
474 SkASSERT(textData != NULL);
476 // handle this encoding before the setup for the glyphcache
477 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
478 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
479 size_t count = byteLength >> 1;
480 for (size_t i = 0; i < count; i++) {
481 if (0 == glyphID[i]) {
488 SkAutoGlyphCache autoCache(*this, NULL, NULL);
489 SkGlyphCache* cache = autoCache.getCache();
491 switch (this->getTextEncoding()) {
492 case SkPaint::kUTF8_TextEncoding: {
493 const char* text = static_cast<const char*>(textData);
494 const char* stop = text + byteLength;
495 while (text < stop) {
496 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
502 case SkPaint::kUTF16_TextEncoding: {
503 const uint16_t* text = static_cast<const uint16_t*>(textData);
504 const uint16_t* stop = text + (byteLength >> 1);
505 while (text < stop) {
506 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
512 case SkPaint::kUTF32_TextEncoding: {
513 const int32_t* text = static_cast<const int32_t*>(textData);
514 const int32_t* stop = text + (byteLength >> 2);
515 while (text < stop) {
516 if (0 == cache->unicharToGlyph(*text++)) {
523 SkDEBUGFAIL("unknown text encoding");
529 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
530 SkUnichar textData[]) const {
535 SkASSERT(glyphs != NULL);
536 SkASSERT(textData != NULL);
538 SkAutoGlyphCache autoCache(*this, NULL, NULL);
539 SkGlyphCache* cache = autoCache.getCache();
541 for (int index = 0; index < count; index++) {
542 textData[index] = cache->glyphToUnichar(glyphs[index]);
546 ///////////////////////////////////////////////////////////////////////////////
548 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
550 SkASSERT(cache != NULL);
551 SkASSERT(text != NULL);
553 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
556 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
558 SkASSERT(cache != NULL);
559 SkASSERT(text != NULL);
561 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
564 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
566 SkASSERT(cache != NULL);
567 SkASSERT(text != NULL);
569 const int32_t* ptr = *(const int32_t**)text;
570 SkUnichar uni = *ptr++;
571 *text = (const char*)ptr;
572 return cache->getUnicharMetrics(uni);
575 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
577 SkASSERT(cache != NULL);
578 SkASSERT(text != NULL);
580 const uint16_t* ptr = *(const uint16_t**)text;
581 unsigned glyphID = *ptr;
583 *text = (const char*)ptr;
584 return cache->getGlyphIDMetrics(glyphID);
587 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
589 SkASSERT(cache != NULL);
590 SkASSERT(text != NULL);
592 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
595 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
597 SkASSERT(cache != NULL);
598 SkASSERT(text != NULL);
600 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
603 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
605 SkASSERT(cache != NULL);
606 SkASSERT(text != NULL);
608 const int32_t* ptr = *(const int32_t**)text;
609 SkUnichar uni = *ptr++;
610 *text = (const char*)ptr;
611 return cache->getUnicharAdvance(uni);
614 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
616 SkASSERT(cache != NULL);
617 SkASSERT(text != NULL);
619 const uint16_t* ptr = *(const uint16_t**)text;
620 unsigned glyphID = *ptr;
622 *text = (const char*)ptr;
623 return cache->getGlyphIDAdvance(glyphID);
626 SkMeasureCacheProc SkPaint::getMeasureCacheProc(bool needFullMetrics) const {
627 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
628 sk_getMetrics_utf8_next,
629 sk_getMetrics_utf16_next,
630 sk_getMetrics_utf32_next,
631 sk_getMetrics_glyph_next,
633 sk_getAdvance_utf8_next,
634 sk_getAdvance_utf16_next,
635 sk_getAdvance_utf32_next,
636 sk_getAdvance_glyph_next,
639 unsigned index = this->getTextEncoding();
641 if (!needFullMetrics && !this->isDevKernText()) {
645 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
646 return gMeasureCacheProcs[index];
649 ///////////////////////////////////////////////////////////////////////////////
651 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
652 const char** text, SkFixed, SkFixed) {
653 SkASSERT(cache != NULL);
654 SkASSERT(text != NULL);
656 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
659 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
660 const char** text, SkFixed x, SkFixed y) {
661 SkASSERT(cache != NULL);
662 SkASSERT(text != NULL);
664 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
667 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
668 const char** text, SkFixed, SkFixed) {
669 SkASSERT(cache != NULL);
670 SkASSERT(text != NULL);
672 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
675 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
676 const char** text, SkFixed x, SkFixed y) {
677 SkASSERT(cache != NULL);
678 SkASSERT(text != NULL);
680 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
684 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
685 const char** text, SkFixed, SkFixed) {
686 SkASSERT(cache != NULL);
687 SkASSERT(text != NULL);
689 const int32_t* ptr = *(const int32_t**)text;
690 SkUnichar uni = *ptr++;
691 *text = (const char*)ptr;
692 return cache->getUnicharMetrics(uni);
695 static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
696 const char** text, SkFixed x, SkFixed y) {
697 SkASSERT(cache != NULL);
698 SkASSERT(text != NULL);
700 const int32_t* ptr = *(const int32_t**)text;
701 SkUnichar uni = *ptr++;
702 *text = (const char*)ptr;
703 return cache->getUnicharMetrics(uni, x, y);
706 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
707 const char** text, SkFixed, SkFixed) {
708 SkASSERT(cache != NULL);
709 SkASSERT(text != NULL);
711 const uint16_t* ptr = *(const uint16_t**)text;
712 unsigned glyphID = *ptr;
714 *text = (const char*)ptr;
715 return cache->getGlyphIDMetrics(glyphID);
718 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
719 const char** text, SkFixed x, SkFixed y) {
720 SkASSERT(cache != NULL);
721 SkASSERT(text != NULL);
723 const uint16_t* ptr = *(const uint16_t**)text;
724 unsigned glyphID = *ptr;
726 *text = (const char*)ptr;
727 return cache->getGlyphIDMetrics(glyphID, x, y);
730 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
731 static const SkDrawCacheProc gDrawCacheProcs[] = {
732 sk_getMetrics_utf8_00,
733 sk_getMetrics_utf16_00,
734 sk_getMetrics_utf32_00,
735 sk_getMetrics_glyph_00,
737 sk_getMetrics_utf8_xy,
738 sk_getMetrics_utf16_xy,
739 sk_getMetrics_utf32_xy,
740 sk_getMetrics_glyph_xy
743 unsigned index = this->getTextEncoding();
744 if (fBitfields.fFlags & kSubpixelText_Flag) {
748 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
749 return gDrawCacheProcs[index];
752 ///////////////////////////////////////////////////////////////////////////////
754 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
755 SkPaint::kDevKernText_Flag | \
756 SkPaint::kLinearText_Flag | \
757 SkPaint::kLCDRenderText_Flag | \
758 SkPaint::kEmbeddedBitmapText_Flag | \
759 SkPaint::kAutoHinting_Flag | \
760 SkPaint::kGenA8FromLCD_Flag )
762 SkScalar SkPaint::setupForAsPaths() {
763 uint32_t flags = this->getFlags();
764 // clear the flags we don't care about
765 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
766 // set the flags we do care about
767 flags |= SkPaint::kSubpixelText_Flag;
769 this->setFlags(flags);
770 this->setHinting(SkPaint::kNo_Hinting);
772 SkScalar textSize = fTextSize;
773 this->setTextSize(kCanonicalTextSizeForPaths);
774 return textSize / kCanonicalTextSizeForPaths;
777 class SkCanonicalizePaint {
779 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
780 if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
781 SkPaint* p = fLazy.set(paint);
782 fScale = p->setupForAsPaths();
787 const SkPaint& getPaint() const { return *fPaint; }
790 * Returns 0 if the paint was unmodified, or the scale factor need to
791 * the original textSize
793 SkScalar getScale() const { return fScale; }
796 const SkPaint* fPaint;
798 SkTLazy<SkPaint> fLazy;
801 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
802 bounds->set(SkIntToScalar(g.fLeft),
803 SkIntToScalar(g.fTop),
804 SkIntToScalar(g.fLeft + g.fWidth),
805 SkIntToScalar(g.fTop + g.fHeight));
808 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
809 // we don't overflow along the way
810 typedef int64_t Sk48Dot16;
812 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
813 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
816 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
817 SkScalar sx = Sk48Dot16ToScalar(dx);
818 bounds->join(SkIntToScalar(g.fLeft) + sx,
819 SkIntToScalar(g.fTop),
820 SkIntToScalar(g.fLeft + g.fWidth) + sx,
821 SkIntToScalar(g.fTop + g.fHeight));
824 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
825 SkScalar sy = Sk48Dot16ToScalar(dy);
826 bounds->join(SkIntToScalar(g.fLeft),
827 SkIntToScalar(g.fTop) + sy,
828 SkIntToScalar(g.fLeft + g.fWidth),
829 SkIntToScalar(g.fTop + g.fHeight) + sy);
832 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
834 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
835 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
836 SkASSERT(0 == xyIndex || 1 == xyIndex);
837 return (&glyph.fAdvanceX)[xyIndex];
840 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
841 const char* text, size_t byteLength,
842 int* count, SkRect* bounds) const {
844 if (byteLength == 0) {
852 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(NULL != bounds);
855 JoinBoundsProc joinBoundsProc;
856 if (this->isVerticalText()) {
858 joinBoundsProc = join_bounds_y;
861 joinBoundsProc = join_bounds_x;
865 const char* stop = (const char*)text + byteLength;
866 const SkGlyph* g = &glyphCacheProc(cache, &text);
867 // our accumulated fixed-point advances might overflow 16.16, so we use
868 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
870 Sk48Dot16 x = advance(*g, xyIndex);
874 if (NULL == bounds) {
875 if (this->isDevKernText()) {
877 for (; text < stop; n++) {
879 g = &glyphCacheProc(cache, &text);
880 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
883 for (; text < stop; n++) {
884 x += advance(glyphCacheProc(cache, &text), xyIndex);
888 set_bounds(*g, bounds);
889 if (this->isDevKernText()) {
891 for (; text < stop; n++) {
893 g = &glyphCacheProc(cache, &text);
894 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
895 joinBoundsProc(*g, bounds, x);
896 x += advance(*g, xyIndex);
899 for (; text < stop; n++) {
900 g = &glyphCacheProc(cache, &text);
901 joinBoundsProc(*g, bounds, x);
902 x += advance(*g, xyIndex);
906 SkASSERT(text == stop);
909 return Sk48Dot16ToScalar(x);
912 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
913 const char* text = (const char*)textData;
914 SkASSERT(text != NULL || length == 0);
916 SkCanonicalizePaint canon(*this);
917 const SkPaint& paint = canon.getPaint();
918 SkScalar scale = canon.getScale();
920 SkAutoGlyphCache autoCache(paint, NULL, NULL);
921 SkGlyphCache* cache = autoCache.getCache();
928 width = paint.measure_text(cache, text, length, &tempCount, bounds);
930 width = SkScalarMul(width, scale);
932 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
933 bounds->fTop = SkScalarMul(bounds->fTop, scale);
934 bounds->fRight = SkScalarMul(bounds->fRight, scale);
935 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
939 // ensure that even if we don't measure_text we still update the bounds
945 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
946 SkScalar* measuredWidth) const {
947 if (0 == length || 0 >= maxWidth) {
954 if (0 == fTextSize) {
961 SkASSERT(textD != NULL);
962 const char* text = (const char*)textD;
963 const char* stop = text + length;
965 SkCanonicalizePaint canon(*this);
966 const SkPaint& paint = canon.getPaint();
967 SkScalar scale = canon.getScale();
969 // adjust max in case we changed the textSize in paint
974 SkAutoGlyphCache autoCache(paint, NULL, NULL);
975 SkGlyphCache* cache = autoCache.getCache();
977 SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(false);
978 const int xyIndex = paint.isVerticalText() ? 1 : 0;
979 // use 64bits for our accumulator, to avoid overflowing 16.16
980 Sk48Dot16 max = SkScalarToFixed(maxWidth);
985 if (this->isDevKernText()) {
987 while (text < stop) {
988 const char* curr = text;
989 const SkGlyph& g = glyphCacheProc(cache, &text);
990 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
991 if ((width += x) > max) {
999 while (text < stop) {
1000 const char* curr = text;
1001 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
1002 if ((width += x) > max) {
1010 if (measuredWidth) {
1011 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1013 scalarWidth = SkScalarMul(scalarWidth, scale);
1015 *measuredWidth = scalarWidth;
1018 // return the number of bytes measured
1019 return text - stop + length;
1022 ///////////////////////////////////////////////////////////////////////////////
1024 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1025 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1026 return false; // don't detach the cache
1029 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1031 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1034 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1035 SkCanonicalizePaint canon(*this);
1036 const SkPaint& paint = canon.getPaint();
1037 SkScalar scale = canon.getScale();
1039 SkMatrix zoomMatrix, *zoomPtr = NULL;
1041 zoomMatrix.setScale(zoom, zoom);
1042 zoomPtr = &zoomMatrix;
1045 FontMetrics storage;
1046 if (NULL == metrics) {
1050 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1053 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1054 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1055 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1056 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1057 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1058 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
1059 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
1060 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
1061 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
1062 metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
1063 metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
1065 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1068 ///////////////////////////////////////////////////////////////////////////////
1070 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1071 bounds->set(g.fLeft * scale,
1073 (g.fLeft + g.fWidth) * scale,
1074 (g.fTop + g.fHeight) * scale);
1077 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1078 SkScalar widths[], SkRect bounds[]) const {
1079 if (0 == byteLength) {
1085 if (NULL == widths && NULL == bounds) {
1086 return this->countText(textData, byteLength);
1089 SkCanonicalizePaint canon(*this);
1090 const SkPaint& paint = canon.getPaint();
1091 SkScalar scale = canon.getScale();
1093 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1094 SkGlyphCache* cache = autoCache.getCache();
1095 SkMeasureCacheProc glyphCacheProc;
1096 glyphCacheProc = paint.getMeasureCacheProc(NULL != bounds);
1098 const char* text = (const char*)textData;
1099 const char* stop = text + byteLength;
1101 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1103 if (this->isDevKernText()) {
1104 // we adjust the widths returned here through auto-kerning
1105 SkAutoKern autokern;
1106 SkFixed prevWidth = 0;
1109 while (text < stop) {
1110 const SkGlyph& g = glyphCacheProc(cache, &text);
1112 SkFixed adjust = autokern.adjust(g);
1115 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1116 *widths++ = SkScalarMul(w, scale);
1118 prevWidth = advance(g, xyIndex);
1121 set_bounds(g, bounds++, scale);
1125 if (count > 0 && widths) {
1126 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1129 while (text < stop) {
1130 const SkGlyph& g = glyphCacheProc(cache, &text);
1132 SkFixed adjust = autokern.adjust(g);
1135 *widths++ = SkFixedToScalar(prevWidth + adjust);
1137 prevWidth = advance(g, xyIndex);
1140 set_bounds(g, bounds++);
1144 if (count > 0 && widths) {
1145 *widths = SkFixedToScalar(prevWidth);
1148 } else { // no devkern
1150 while (text < stop) {
1151 const SkGlyph& g = glyphCacheProc(cache, &text);
1153 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
1157 set_bounds(g, bounds++, scale);
1162 while (text < stop) {
1163 const SkGlyph& g = glyphCacheProc(cache, &text);
1165 *widths++ = SkFixedToScalar(advance(g, xyIndex));
1168 set_bounds(g, bounds++);
1175 SkASSERT(text == stop);
1179 ///////////////////////////////////////////////////////////////////////////////
1183 void SkPaint::getTextPath(const void* textData, size_t length,
1184 SkScalar x, SkScalar y, SkPath* path) const {
1185 SkASSERT(length == 0 || textData != NULL);
1187 const char* text = (const char*)textData;
1188 if (text == NULL || length == 0 || path == NULL) {
1192 SkTextToPathIter iter(text, length, *this, false);
1194 SkScalar prevXPos = 0;
1196 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1197 matrix.postTranslate(x, y);
1201 const SkPath* iterPath;
1202 while (iter.next(&iterPath, &xpos)) {
1203 matrix.postTranslate(xpos - prevXPos, 0);
1205 path->addPath(*iterPath, matrix);
1211 void SkPaint::getPosTextPath(const void* textData, size_t length,
1212 const SkPoint pos[], SkPath* path) const {
1213 SkASSERT(length == 0 || textData != NULL);
1215 const char* text = (const char*)textData;
1216 if (text == NULL || length == 0 || path == NULL) {
1220 SkTextToPathIter iter(text, length, *this, false);
1225 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1229 const SkPath* iterPath;
1230 while (iter.next(&iterPath, NULL)) {
1231 matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
1233 path->addPath(*iterPath, matrix);
1240 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1241 SkWriteBuffer* buffer) {
1242 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
1245 // SkFontHost can override this choice in FilterRec()
1246 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1247 uint32_t flags = paint.getFlags();
1249 // Antialiasing being disabled trumps all other settings.
1250 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1251 return SkMask::kBW_Format;
1254 if (flags & SkPaint::kLCDRenderText_Flag) {
1255 return SkMask::kLCD16_Format;
1258 return SkMask::kA8_Format;
1261 // if linear-text is on, then we force hinting to be off (since that's sort of
1262 // the point of linear-text.
1263 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1264 SkPaint::Hinting h = paint.getHinting();
1265 if (paint.isLinearText()) {
1266 h = SkPaint::kNo_Hinting;
1271 // return true if the paint is just a single color (i.e. not a shader). If its
1272 // a shader, then we can't compute a const luminance for it :(
1273 static bool justAColor(const SkPaint& paint, SkColor* color) {
1274 SkColor c = paint.getColor();
1276 SkShader* shader = paint.getShader();
1277 if (shader && !shader->asLuminanceColor(&c)) {
1280 if (paint.getColorFilter()) {
1281 c = paint.getColorFilter()->filterColor(c);
1289 static SkColor computeLuminanceColor(const SkPaint& paint) {
1291 if (!justAColor(paint, &c)) {
1292 c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1297 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1299 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1300 // cost more RAM and draws slower, so we set a cap.
1301 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1302 #define SK_MAX_SIZE_FOR_LCDTEXT 48
1305 const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
1307 static bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) {
1309 SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1310 rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1311 area *= rec.fTextSize * rec.fTextSize;
1312 return area > gMaxSize2ForLCDText;
1314 return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
1319 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1320 * that vary only slightly when we create our key into the font cache, since the font scaler
1321 * typically returns the same looking resuts for tiny changes in the matrix.
1323 static SkScalar sk_relax(SkScalar x) {
1324 int n = sk_float_round2int(x * 1024);
1328 void SkScalerContext::MakeRec(const SkPaint& paint,
1329 const SkDeviceProperties* deviceProperties,
1330 const SkMatrix* deviceMatrix,
1332 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1334 SkTypeface* typeface = paint.getTypeface();
1335 if (NULL == typeface) {
1336 typeface = SkTypeface::GetDefaultTypeface();
1338 rec->fFontID = typeface->uniqueID();
1339 rec->fTextSize = paint.getTextSize();
1340 rec->fPreScaleX = paint.getTextScaleX();
1341 rec->fPreSkewX = paint.getTextSkewX();
1343 bool checkPost2x2 = false;
1346 const SkMatrix::TypeMask mask = deviceMatrix->getType();
1347 if (mask & SkMatrix::kScale_Mask) {
1348 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1349 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1350 checkPost2x2 = true;
1352 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1354 if (mask & SkMatrix::kAffine_Mask) {
1355 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1356 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1357 checkPost2x2 = true;
1359 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1362 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1363 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1366 SkPaint::Style style = paint.getStyle();
1367 SkScalar strokeWidth = paint.getStrokeWidth();
1371 if (paint.isFakeBoldText()) {
1372 #ifdef SK_USE_FREETYPE_EMBOLDEN
1373 flags |= SkScalerContext::kEmbolden_Flag;
1375 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1376 kStdFakeBoldInterpKeys,
1377 kStdFakeBoldInterpValues,
1378 kStdFakeBoldInterpLength);
1379 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1381 if (style == SkPaint::kFill_Style) {
1382 style = SkPaint::kStrokeAndFill_Style;
1383 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1385 strokeWidth += extra;
1390 if (paint.isDevKernText()) {
1391 flags |= SkScalerContext::kDevKernText_Flag;
1394 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1395 rec->fFrameWidth = strokeWidth;
1396 rec->fMiterLimit = paint.getStrokeMiter();
1397 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1399 if (style == SkPaint::kStrokeAndFill_Style) {
1400 flags |= SkScalerContext::kFrameAndFill_Flag;
1403 rec->fFrameWidth = 0;
1404 rec->fMiterLimit = 0;
1405 rec->fStrokeJoin = 0;
1408 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1410 if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
1411 if (too_big_for_lcd(*rec, checkPost2x2)) {
1412 rec->fMaskFormat = SkMask::kA8_Format;
1413 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1415 SkPixelGeometry geometry = deviceProperties
1416 ? deviceProperties->pixelGeometry()
1417 : SkSurfacePropsDefaultPixelGeometry();
1419 case kUnknown_SkPixelGeometry:
1420 // eeek, can't support LCD
1421 rec->fMaskFormat = SkMask::kA8_Format;
1422 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1424 case kRGB_H_SkPixelGeometry:
1425 // our default, do nothing.
1427 case kBGR_H_SkPixelGeometry:
1428 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1430 case kRGB_V_SkPixelGeometry:
1431 flags |= SkScalerContext::kLCD_Vertical_Flag;
1433 case kBGR_V_SkPixelGeometry:
1434 flags |= SkScalerContext::kLCD_Vertical_Flag;
1435 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1441 if (paint.isEmbeddedBitmapText()) {
1442 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1444 if (paint.isSubpixelText()) {
1445 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1447 if (paint.isAutohinted()) {
1448 flags |= SkScalerContext::kForceAutohinting_Flag;
1450 if (paint.isVerticalText()) {
1451 flags |= SkScalerContext::kVertical_Flag;
1453 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1454 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1456 rec->fFlags = SkToU16(flags);
1458 // these modify fFlags, so do them after assigning fFlags
1459 rec->setHinting(computeHinting(paint));
1461 rec->setLuminanceColor(computeLuminanceColor(paint));
1463 if (NULL == deviceProperties) {
1464 rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1465 rec->setPaintGamma(SK_GAMMA_EXPONENT);
1467 rec->setDeviceGamma(deviceProperties->gamma());
1469 //For now always set the paint gamma equal to the device gamma.
1470 //The math in SkMaskGamma can handle them being different,
1471 //but it requires superluminous masks when
1472 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1473 rec->setPaintGamma(deviceProperties->gamma());
1476 #ifdef SK_GAMMA_CONTRAST
1477 rec->setContrast(SK_GAMMA_CONTRAST);
1480 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1481 * With lower values small text appears washed out (though correctly so).
1482 * With higher values lcd fringing is worse and the smoothing effect of
1483 * partial coverage is diminished.
1485 rec->setContrast(0.5f);
1488 rec->fReservedAlign = 0;
1490 /* Allow the fonthost to modify our rec before we use it as a key into the
1491 cache. This way if we're asking for something that they will ignore,
1492 they can modify our rec up front, so we don't create duplicate cache
1495 typeface->onFilterRec(rec);
1497 // be sure to call PostMakeRec(rec) before you actually use it!
1501 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
1502 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
1503 * to hold it until the returned pointer is refed or forgotten.
1505 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
1507 static SkMaskGamma* gLinearMaskGamma = NULL;
1508 static SkMaskGamma* gMaskGamma = NULL;
1509 static SkScalar gContrast = SK_ScalarMin;
1510 static SkScalar gPaintGamma = SK_ScalarMin;
1511 static SkScalar gDeviceGamma = SK_ScalarMin;
1513 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
1514 * the returned SkMaskGamma pointer is refed or forgotten.
1516 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1517 gMaskGammaCacheMutex.assertHeld();
1518 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1519 if (NULL == gLinearMaskGamma) {
1520 gLinearMaskGamma = SkNEW(SkMaskGamma);
1522 return *gLinearMaskGamma;
1524 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
1525 SkSafeUnref(gMaskGamma);
1526 gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
1527 gContrast = contrast;
1528 gPaintGamma = paintGamma;
1529 gDeviceGamma = deviceGamma;
1534 /*static*/ void SkPaint::Term() {
1535 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1537 SkSafeUnref(gLinearMaskGamma);
1538 gLinearMaskGamma = NULL;
1539 SkSafeUnref(gMaskGamma);
1541 SkDEBUGCODE(gContrast = SK_ScalarMin;)
1542 SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1543 SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1547 * We ensure that the rec is self-consistent and efficient (where possible)
1549 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
1551 * If we're asking for A8, we force the colorlum to be gray, since that
1552 * limits the number of unique entries, and the scaler will only look at
1553 * the lum of one of them.
1555 switch (rec->fMaskFormat) {
1556 case SkMask::kLCD16_Format:
1557 case SkMask::kLCD32_Format: {
1558 // filter down the luminance color to a finite number of bits
1559 SkColor color = rec->getLuminanceColor();
1560 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1563 case SkMask::kA8_Format: {
1564 // filter down the luminance to a single component, since A8 can't
1565 // use per-component information
1566 SkColor color = rec->getLuminanceColor();
1567 U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1569 SkColorGetB(color));
1570 // reduce to our finite number of bits
1571 color = SkColorSetRGB(lum, lum, lum);
1572 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1575 case SkMask::kBW_Format:
1576 // No need to differentiate gamma if we're BW
1577 rec->ignorePreBlend();
1582 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1589 * ignoreGamma tells us that the caller just wants metrics that are unaffected
1590 * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
1591 * contrast = 0, luminanceColor = transparent black.
1593 void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1594 const SkMatrix* deviceMatrix,
1595 void (*proc)(SkTypeface*, const SkDescriptor*, void*),
1596 void* context, bool ignoreGamma) const {
1597 SkScalerContext::Rec rec;
1599 SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
1601 rec.ignorePreBlend();
1604 size_t descSize = sizeof(rec);
1606 SkPathEffect* pe = this->getPathEffect();
1607 SkMaskFilter* mf = this->getMaskFilter();
1608 SkRasterizer* ra = this->getRasterizer();
1610 SkWriteBuffer peBuffer, mfBuffer, raBuffer;
1613 peBuffer.writeFlattenable(pe);
1614 descSize += peBuffer.bytesWritten();
1616 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1617 // seems like we could support kLCD as well at this point...
1620 mfBuffer.writeFlattenable(mf);
1621 descSize += mfBuffer.bytesWritten();
1623 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1624 /* Pre-blend is not currently applied to filtered text.
1625 The primary filter is blur, for which contrast makes no sense,
1626 and for which the destination guess error is more visible.
1627 Also, all existing users of blur have calibrated for linear. */
1628 rec.ignorePreBlend();
1631 raBuffer.writeFlattenable(ra);
1632 descSize += raBuffer.bytesWritten();
1634 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1637 ///////////////////////////////////////////////////////////////////////////
1638 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1639 SkScalerContext::PostMakeRec(*this, &rec);
1641 descSize += SkDescriptor::ComputeOverhead(entryCount);
1643 SkAutoDescriptor ad(descSize);
1644 SkDescriptor* desc = ad.getDesc();
1647 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1650 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1653 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1656 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1659 SkASSERT(descSize == desc->getLength());
1660 desc->computeChecksum();
1664 // Check that we completely write the bytes in desc (our key), and that
1665 // there are no uninitialized bytes. If there were, then we would get
1666 // false-misses (or worse, false-hits) in our fontcache.
1668 // We do this buy filling 2 others, one with 0s and the other with 1s
1669 // and create those, and then check that all 3 are identical.
1670 SkAutoDescriptor ad1(descSize);
1671 SkAutoDescriptor ad2(descSize);
1672 SkDescriptor* desc1 = ad1.getDesc();
1673 SkDescriptor* desc2 = ad2.getDesc();
1675 memset(desc1, 0x00, descSize);
1676 memset(desc2, 0xFF, descSize);
1680 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1681 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1684 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
1685 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
1688 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
1689 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
1692 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
1693 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
1696 SkASSERT(descSize == desc1->getLength());
1697 SkASSERT(descSize == desc2->getLength());
1698 desc1->computeChecksum();
1699 desc2->computeChecksum();
1700 SkASSERT(!memcmp(desc, desc1, descSize));
1701 SkASSERT(!memcmp(desc, desc2, descSize));
1705 proc(fTypeface, desc, context);
1708 SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
1709 const SkMatrix* deviceMatrix,
1710 bool ignoreGamma) const {
1711 SkGlyphCache* cache;
1712 this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
1717 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
1720 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
1721 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1722 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1723 rec.getPaintGamma(),
1724 rec.getDeviceGamma());
1725 return maskGamma.preBlend(rec.getLuminanceColor());
1728 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
1729 SkScalar deviceGamma, int* width, int* height) {
1730 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1731 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1735 maskGamma.getGammaTableDimensions(width, height);
1736 size_t size = (*width)*(*height)*sizeof(uint8_t);
1741 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
1743 SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1744 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
1748 maskGamma.getGammaTableDimensions(&width, &height);
1749 size_t size = width*height*sizeof(uint8_t);
1750 const uint8_t* gammaTables = maskGamma.getGammaTables();
1751 memcpy(data, gammaTables, size);
1755 ///////////////////////////////////////////////////////////////////////////////
1757 #include "SkStream.h"
1759 static uintptr_t asint(const void* p) {
1760 return reinterpret_cast<uintptr_t>(p);
1768 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1769 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1771 tmp.fScalar = value;
1776 static SkScalar read_scalar(const uint32_t*& ptr) {
1777 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1783 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1784 SkASSERT(a == (uint8_t)a);
1785 SkASSERT(b == (uint8_t)b);
1786 SkASSERT(c == (uint8_t)c);
1787 SkASSERT(d == (uint8_t)d);
1788 return (a << 24) | (b << 16) | (c << 8) | d;
1792 static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
1793 SkASSERT(bitCount > 0 && bitCount <= 32);
1794 uint32_t mask = ~0U;
1795 mask >>= (32 - bitCount);
1796 SkASSERT(0 == (value & ~mask));
1799 #define ASSERT_FITS_IN(value, bitcount)
1803 kHasTypeface_FlatFlag = 0x01,
1804 kHasEffects_FlatFlag = 0x02,
1805 kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
1807 kFlatFlagMask = 0x7,
1818 static inline int BPF_Mask(int bits) {
1819 return (1 << bits) - 1;
1822 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
1823 unsigned filter, unsigned flatFlags) {
1824 ASSERT_FITS_IN(flags, kFlags_BPF);
1825 ASSERT_FITS_IN(hint, kHint_BPF);
1826 ASSERT_FITS_IN(align, kAlign_BPF);
1827 ASSERT_FITS_IN(filter, kFilter_BPF);
1828 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
1830 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
1831 // add more bits in the future.
1832 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
1835 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
1836 paint->setFlags(packed >> 16);
1837 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
1838 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
1839 paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
1840 return (FlatFlags)(packed & kFlatFlagMask);
1843 // V22_COMPATIBILITY_CODE
1844 static FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
1846 kFilterBitmap_Flag = 0x02,
1847 kHighQualityFilterBitmap_Flag = 0x4000,
1849 kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
1852 // previously flags:16, textAlign:8, flatFlags:8
1853 // now flags:16, hinting:4, textAlign:4, flatFlags:8
1854 unsigned flags = packed >> 16;
1856 if (flags & kFilterBitmap_Flag) {
1859 if (flags & kHighQualityFilterBitmap_Flag) {
1862 paint->setFilterLevel((SkPaint::FilterLevel)filter);
1863 flags &= ~kAll_Flags; // remove these (now dead) bit flags
1865 paint->setFlags(flags);
1867 // hinting added later. 0 in this nibble means use the default.
1868 uint32_t hinting = (packed >> 12) & 0xF;
1869 paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
1870 paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
1871 return (FlatFlags)(packed & kFlatFlagMask);
1874 // The size of a flat paint's POD fields
1875 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1876 1 * sizeof(SkColor) +
1877 1 * sizeof(uint16_t) +
1878 6 * sizeof(uint8_t);
1880 /* To save space/time, we analyze the paint, and write a truncated version of
1881 it if there are not tricky elements like shaders, etc.
1883 void SkPaint::flatten(SkWriteBuffer& buffer) const {
1884 uint8_t flatFlags = 0;
1885 if (this->getTypeface()) {
1886 flatFlags |= kHasTypeface_FlatFlag;
1888 if (asint(this->getPathEffect()) |
1889 asint(this->getShader()) |
1890 asint(this->getXfermode()) |
1891 asint(this->getMaskFilter()) |
1892 asint(this->getColorFilter()) |
1893 asint(this->getRasterizer()) |
1894 asint(this->getLooper()) |
1895 asint(this->getAnnotation()) |
1896 asint(this->getImageFilter())) {
1897 flatFlags |= kHasEffects_FlatFlag;
1900 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1901 uint32_t* ptr = buffer.reserve(kPODPaintSize);
1903 ptr = write_scalar(ptr, this->getTextSize());
1904 ptr = write_scalar(ptr, this->getTextScaleX());
1905 ptr = write_scalar(ptr, this->getTextSkewX());
1906 ptr = write_scalar(ptr, this->getStrokeWidth());
1907 ptr = write_scalar(ptr, this->getStrokeMiter());
1908 *ptr++ = this->getColor();
1910 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
1911 this->getFilterLevel(), flatFlags);
1912 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1913 this->getStyle(), this->getTextEncoding());
1915 // now we're done with ptr and the (pre)reserved space. If we need to write
1916 // additional fields, use the buffer directly
1917 if (flatFlags & kHasTypeface_FlatFlag) {
1918 buffer.writeTypeface(this->getTypeface());
1920 if (flatFlags & kHasEffects_FlatFlag) {
1921 buffer.writeFlattenable(this->getPathEffect());
1922 buffer.writeFlattenable(this->getShader());
1923 buffer.writeFlattenable(this->getXfermode());
1924 buffer.writeFlattenable(this->getMaskFilter());
1925 buffer.writeFlattenable(this->getColorFilter());
1926 buffer.writeFlattenable(this->getRasterizer());
1927 buffer.writeFlattenable(this->getLooper());
1928 buffer.writeFlattenable(this->getImageFilter());
1931 buffer.writeBool(true);
1932 fAnnotation->writeToBuffer(buffer);
1934 buffer.writeBool(false);
1939 void SkPaint::unflatten(SkReadBuffer& buffer) {
1940 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1941 const void* podData = buffer.skip(kPODPaintSize);
1942 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1944 // the order we read must match the order we wrote in flatten()
1945 this->setTextSize(read_scalar(pod));
1946 this->setTextScaleX(read_scalar(pod));
1947 this->setTextSkewX(read_scalar(pod));
1948 this->setStrokeWidth(read_scalar(pod));
1949 this->setStrokeMiter(read_scalar(pod));
1950 this->setColor(*pod++);
1952 unsigned flatFlags = 0;
1953 if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) {
1954 flatFlags = unpack_paint_flags_v22(this, *pod++);
1956 flatFlags = unpack_paint_flags(this, *pod++);
1959 uint32_t tmp = *pod++;
1960 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1961 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1962 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1963 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1965 if (flatFlags & kHasTypeface_FlatFlag) {
1966 this->setTypeface(buffer.readTypeface());
1968 this->setTypeface(NULL);
1971 if (flatFlags & kHasEffects_FlatFlag) {
1972 SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
1973 SkSafeUnref(this->setShader(buffer.readShader()));
1974 SkSafeUnref(this->setXfermode(buffer.readXfermode()));
1975 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
1976 SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
1977 SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
1978 SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
1979 SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
1981 if (buffer.readBool()) {
1982 this->setAnnotation(SkAnnotation::Create(buffer))->unref();
1985 this->setPathEffect(NULL);
1986 this->setShader(NULL);
1987 this->setXfermode(NULL);
1988 this->setMaskFilter(NULL);
1989 this->setColorFilter(NULL);
1990 this->setRasterizer(NULL);
1991 this->setLooper(NULL);
1992 this->setImageFilter(NULL);
1995 if (buffer.isVersionLT(SkReadBuffer::kRemoveAndroidPaintOpts_Version) &&
1996 flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
1999 buffer.readString(&tag);
2004 ///////////////////////////////////////////////////////////////////////////////
2006 SkShader* SkPaint::setShader(SkShader* shader) {
2007 SkRefCnt_SafeAssign(fShader, shader);
2011 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2012 SkRefCnt_SafeAssign(fColorFilter, filter);
2016 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2017 SkRefCnt_SafeAssign(fXfermode, mode);
2021 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2022 SkSafeUnref(fXfermode);
2023 fXfermode = SkXfermode::Create(mode);
2027 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2028 SkRefCnt_SafeAssign(fPathEffect, effect);
2032 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2033 SkRefCnt_SafeAssign(fMaskFilter, filter);
2037 ///////////////////////////////////////////////////////////////////////////////
2039 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
2040 const SkRect* cullRect) const {
2041 SkStrokeRec rec(*this);
2043 const SkPath* srcPtr = &src;
2046 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2050 if (!rec.applyToPath(dst, *srcPtr)) {
2051 if (srcPtr == &tmpPath) {
2052 // If path's were copy-on-write, this trick would not be needed.
2053 // As it is, we want to save making a deep-copy from tmpPath -> dst
2054 // since we know we're just going to delete tmpPath when we return,
2055 // so the swap saves that copy.
2061 return !rec.isHairlineStyle();
2064 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2066 Style style) const {
2069 const SkRect* src = &origSrc;
2071 if (this->getLooper()) {
2072 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2073 this->getLooper()->computeFastBounds(*this, *src, storage);
2078 if (this->getPathEffect()) {
2079 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2083 if (kFill_Style != style) {
2084 // since we're stroked, outset the rect by the radius (and join type)
2085 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2086 if (0 == radius) { // hairline
2087 radius = SK_Scalar1;
2088 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2089 SkScalar scale = this->getStrokeMiter();
2090 if (scale > SK_Scalar1) {
2091 radius = SkScalarMul(radius, scale);
2094 storage->set(src->fLeft - radius, src->fTop - radius,
2095 src->fRight + radius, src->fBottom + radius);
2100 if (this->getMaskFilter()) {
2101 this->getMaskFilter()->computeFastBounds(*storage, storage);
2104 if (this->getImageFilter()) {
2105 this->getImageFilter()->computeFastBounds(*storage, storage);
2111 #ifndef SK_IGNORE_TO_STRING
2113 void SkPaint::toString(SkString* str) const {
2114 str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2116 SkTypeface* typeface = this->getTypeface();
2118 SkDynamicMemoryWStream ostream;
2119 typeface->serialize(&ostream);
2120 SkAutoTUnref<SkStreamAsset> istream(ostream.detachAsStream());
2121 SkFontDescriptor descriptor(istream);
2123 str->append("<dt>Font Family Name:</dt><dd>");
2124 str->append(descriptor.getFamilyName());
2125 str->append("</dd><dt>Font Full Name:</dt><dd>");
2126 str->append(descriptor.getFullName());
2127 str->append("</dd><dt>Font PS Name:</dt><dd>");
2128 str->append(descriptor.getPostscriptName());
2129 str->append("</dd><dt>Font File Name:</dt><dd>");
2130 str->append(descriptor.getFontFileName());
2131 str->append("</dd>");
2134 str->append("<dt>TextSize:</dt><dd>");
2135 str->appendScalar(this->getTextSize());
2136 str->append("</dd>");
2138 str->append("<dt>TextScaleX:</dt><dd>");
2139 str->appendScalar(this->getTextScaleX());
2140 str->append("</dd>");
2142 str->append("<dt>TextSkewX:</dt><dd>");
2143 str->appendScalar(this->getTextSkewX());
2144 str->append("</dd>");
2146 SkPathEffect* pathEffect = this->getPathEffect();
2148 str->append("<dt>PathEffect:</dt><dd>");
2149 str->append("</dd>");
2152 SkShader* shader = this->getShader();
2154 str->append("<dt>Shader:</dt><dd>");
2155 shader->toString(str);
2156 str->append("</dd>");
2159 SkXfermode* xfer = this->getXfermode();
2161 str->append("<dt>Xfermode:</dt><dd>");
2162 xfer->toString(str);
2163 str->append("</dd>");
2166 SkMaskFilter* maskFilter = this->getMaskFilter();
2168 str->append("<dt>MaskFilter:</dt><dd>");
2169 maskFilter->toString(str);
2170 str->append("</dd>");
2173 SkColorFilter* colorFilter = this->getColorFilter();
2175 str->append("<dt>ColorFilter:</dt><dd>");
2176 colorFilter->toString(str);
2177 str->append("</dd>");
2180 SkRasterizer* rasterizer = this->getRasterizer();
2182 str->append("<dt>Rasterizer:</dt><dd>");
2183 str->append("</dd>");
2186 SkDrawLooper* looper = this->getLooper();
2188 str->append("<dt>DrawLooper:</dt><dd>");
2189 looper->toString(str);
2190 str->append("</dd>");
2193 SkImageFilter* imageFilter = this->getImageFilter();
2195 str->append("<dt>ImageFilter:</dt><dd>");
2196 str->append("</dd>");
2199 SkAnnotation* annotation = this->getAnnotation();
2201 str->append("<dt>Annotation:</dt><dd>");
2202 str->append("</dd>");
2205 str->append("<dt>Color:</dt><dd>0x");
2206 SkColor color = this->getColor();
2207 str->appendHex(color);
2208 str->append("</dd>");
2210 str->append("<dt>Stroke Width:</dt><dd>");
2211 str->appendScalar(this->getStrokeWidth());
2212 str->append("</dd>");
2214 str->append("<dt>Stroke Miter:</dt><dd>");
2215 str->appendScalar(this->getStrokeMiter());
2216 str->append("</dd>");
2218 str->append("<dt>Flags:</dt><dd>(");
2219 if (this->getFlags()) {
2220 bool needSeparator = false;
2221 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2222 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2223 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2224 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2225 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2226 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2227 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2228 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2229 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2230 SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2231 "EmbeddedBitmapText", &needSeparator);
2232 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2233 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2234 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2235 "GenA8FromLCD", &needSeparator);
2237 str->append("None");
2239 str->append(")</dd>");
2241 str->append("<dt>FilterLevel:</dt><dd>");
2242 static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
2243 str->append(gFilterLevelStrings[this->getFilterLevel()]);
2244 str->append("</dd>");
2246 str->append("<dt>TextAlign:</dt><dd>");
2247 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2248 str->append(gTextAlignStrings[this->getTextAlign()]);
2249 str->append("</dd>");
2251 str->append("<dt>CapType:</dt><dd>");
2252 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2253 str->append(gStrokeCapStrings[this->getStrokeCap()]);
2254 str->append("</dd>");
2256 str->append("<dt>JoinType:</dt><dd>");
2257 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2258 str->append(gJoinStrings[this->getStrokeJoin()]);
2259 str->append("</dd>");
2261 str->append("<dt>Style:</dt><dd>");
2262 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2263 str->append(gStyleStrings[this->getStyle()]);
2264 str->append("</dd>");
2266 str->append("<dt>TextEncoding:</dt><dd>");
2267 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2268 str->append(gTextEncodingStrings[this->getTextEncoding()]);
2269 str->append("</dd>");
2271 str->append("<dt>Hinting:</dt><dd>");
2272 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2273 str->append(gHintingStrings[this->getHinting()]);
2274 str->append("</dd>");
2276 str->append("</dd></dl></dl>");
2280 ///////////////////////////////////////////////////////////////////////////////
2282 static bool has_thick_frame(const SkPaint& paint) {
2283 return paint.getStrokeWidth() > 0 &&
2284 paint.getStyle() != SkPaint::kFill_Style;
2287 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
2288 const SkPaint& paint,
2289 bool applyStrokeAndPathEffects)
2291 fGlyphCacheProc = paint.getMeasureCacheProc(true);
2293 fPaint.setLinearText(true);
2294 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2296 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2297 applyStrokeAndPathEffects = false;
2300 // can't use our canonical size if we need to apply patheffects
2301 if (fPaint.getPathEffect() == NULL) {
2302 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2303 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2304 if (has_thick_frame(fPaint)) {
2305 fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2308 fScale = SK_Scalar1;
2311 if (!applyStrokeAndPathEffects) {
2312 fPaint.setStyle(SkPaint::kFill_Style);
2313 fPaint.setPathEffect(NULL);
2316 fCache = fPaint.detachCache(NULL, NULL, false);
2318 SkPaint::Style style = SkPaint::kFill_Style;
2319 SkPathEffect* pe = NULL;
2321 if (!applyStrokeAndPathEffects) {
2322 style = paint.getStyle(); // restore
2323 pe = paint.getPathEffect(); // restore
2325 fPaint.setStyle(style);
2326 fPaint.setPathEffect(pe);
2327 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
2329 // now compute fXOffset if needed
2331 SkScalar xOffset = 0;
2332 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2334 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
2335 &count, NULL), fScale);
2336 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2337 width = SkScalarHalf(width);
2345 fStop = text + length;
2347 fXYIndex = paint.isVerticalText() ? 1 : 0;
2350 SkTextToPathIter::~SkTextToPathIter() {
2351 SkGlyphCache::AttachCache(fCache);
2354 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
2355 if (fText < fStop) {
2356 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2358 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2359 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2363 *path = fCache->findPath(glyph);
2378 ///////////////////////////////////////////////////////////////////////////////
2380 bool SkPaint::nothingToDraw() const {
2384 SkXfermode::Mode mode;
2385 if (SkXfermode::AsMode(fXfermode, &mode)) {
2387 case SkXfermode::kSrcOver_Mode:
2388 case SkXfermode::kSrcATop_Mode:
2389 case SkXfermode::kDstOut_Mode:
2390 case SkXfermode::kDstOver_Mode:
2391 case SkXfermode::kPlus_Mode:
2392 return 0 == this->getAlpha();
2393 case SkXfermode::kDst_Mode:
2402 uint32_t SkPaint::getHash() const {
2403 // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
2404 // so fBitfields should be 10 pointers and 6 32-bit values from the start.
2405 SK_COMPILE_ASSERT(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t),
2406 SkPaint_notPackedTightly);
2407 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this),
2408 offsetof(SkPaint, fBitfields) + sizeof(fBitfields));