summaryrefslogtreecommitdiffstats
path: root/skia/sgl/SkPaint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'skia/sgl/SkPaint.cpp')
-rw-r--r--skia/sgl/SkPaint.cpp1571
1 files changed, 0 insertions, 1571 deletions
diff --git a/skia/sgl/SkPaint.cpp b/skia/sgl/SkPaint.cpp
deleted file mode 100644
index bb6b31e..0000000
--- a/skia/sgl/SkPaint.cpp
+++ /dev/null
@@ -1,1571 +0,0 @@
-/* libs/graphics/sgl/SkPaint.cpp
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include "SkPaint.h"
-#include "SkColorFilter.h"
-#include "SkDrawLooper.h"
-#include "SkFontHost.h"
-#include "SkMaskFilter.h"
-#include "SkPathEffect.h"
-#include "SkRasterizer.h"
-#include "SkShader.h"
-#include "SkScalerContext.h"
-#include "SkStroke.h"
-#include "SkTypeface.h"
-#include "SkXfermode.h"
-#include "SkAutoKern.h"
-
-#define SK_DefaultTextSize SkIntToScalar(12)
-
-#define SK_DefaultFlags 0 //(kNativeHintsText_Flag)
-
-SkPaint::SkPaint()
-{
- fTypeface = NULL;
- fTextSize = SK_DefaultTextSize;
- fTextScaleX = SK_Scalar1;
- fTextSkewX = 0;
-
- fPathEffect = NULL;
- fShader = NULL;
- fXfermode = NULL;
- fMaskFilter = NULL;
- fColorFilter = NULL;
- fRasterizer = NULL;
- fLooper = NULL;
-
- fColor = SK_ColorBLACK;
- fWidth = 0;
- fMiterLimit = SK_DefaultMiterLimit;
- fFlags = SK_DefaultFlags;
- fCapType = kDefault_Cap;
- fJoinType = kDefault_Join;
- fTextAlign = kLeft_Align;
- fStyle = kFill_Style;
- fTextEncoding = kUTF8_TextEncoding;
-}
-
-SkPaint::SkPaint(const SkPaint& src)
-{
- memcpy(this, &src, sizeof(src));
-
- fTypeface->safeRef();
- fPathEffect->safeRef();
- fShader->safeRef();
- fXfermode->safeRef();
- fMaskFilter->safeRef();
- fColorFilter->safeRef();
- fRasterizer->safeRef();
- fLooper->safeRef();
-}
-
-SkPaint::~SkPaint()
-{
- fTypeface->safeUnref();
- fPathEffect->safeUnref();
- fShader->safeUnref();
- fXfermode->safeUnref();
- fMaskFilter->safeUnref();
- fColorFilter->safeUnref();
- fRasterizer->safeUnref();
- fLooper->safeUnref();
-}
-
-SkPaint& SkPaint::operator=(const SkPaint& src)
-{
- SkASSERT(&src);
-
- src.fTypeface->safeRef();
- src.fPathEffect->safeRef();
- src.fShader->safeRef();
- src.fXfermode->safeRef();
- src.fMaskFilter->safeRef();
- src.fColorFilter->safeRef();
- src.fRasterizer->safeRef();
- src.fLooper->safeRef();
-
- fTypeface->safeUnref();
- fPathEffect->safeUnref();
- fShader->safeUnref();
- fXfermode->safeUnref();
- fMaskFilter->safeUnref();
- fColorFilter->safeUnref();
- fRasterizer->safeUnref();
- fLooper->safeUnref();
-
- memcpy(this, &src, sizeof(src));
-
- return *this;
-}
-
-int operator==(const SkPaint& a, const SkPaint& b)
-{
- return memcmp(&a, &b, sizeof(a)) == 0;
-}
-
-void SkPaint::reset()
-{
- SkPaint init;
-
- *this = init;
-}
-
-void SkPaint::setFlags(uint32_t flags)
-{
- fFlags = flags;
-}
-
-void SkPaint::setAntiAlias(bool doAA)
-{
- this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
-}
-
-void SkPaint::setDither(bool doDither)
-{
- this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
-}
-
-void SkPaint::setSubpixelText(bool doSubpixel)
-{
- this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
-}
-
-void SkPaint::setLinearText(bool doLinearText)
-{
- this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
-}
-
-void SkPaint::setUnderlineText(bool doUnderline)
-{
- this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
-}
-
-void SkPaint::setStrikeThruText(bool doStrikeThru)
-{
- this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
-}
-
-void SkPaint::setFakeBoldText(bool doFakeBold)
-{
- this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
-}
-
-void SkPaint::setDevKernText(bool doDevKern)
-{
- this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
-}
-
-void SkPaint::setFilterBitmap(bool doFilter)
-{
- this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
-}
-
-void SkPaint::setStyle(Style style)
-{
- if ((unsigned)style < kStyleCount)
- fStyle = style;
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
-#endif
-}
-
-void SkPaint::setColor(SkColor color)
-{
- fColor = color;
-}
-
-void SkPaint::setAlpha(U8CPU a)
-{
- fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor));
-}
-
-void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
-{
- fColor = SkColorSetARGB(a, r, g, b);
-}
-
-void SkPaint::setStrokeWidth(SkScalar width)
-{
- if (width >= 0)
- fWidth = width;
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
-#endif
-}
-
-void SkPaint::setStrokeMiter(SkScalar limit)
-{
- if (limit >= 0)
- fMiterLimit = limit;
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
-#endif
-}
-
-void SkPaint::setStrokeCap(Cap ct)
-{
- if ((unsigned)ct < kCapCount)
- fCapType = SkToU8(ct);
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
-#endif
-}
-
-void SkPaint::setStrokeJoin(Join jt)
-{
- if ((unsigned)jt < kJoinCount)
- fJoinType = SkToU8(jt);
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
-#endif
-}
-
-//////////////////////////////////////////////////////////////////
-
-void SkPaint::setTextAlign(Align align)
-{
- if ((unsigned)align < kAlignCount)
- fTextAlign = SkToU8(align);
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
-#endif
-}
-
-void SkPaint::setTextSize(SkScalar ts)
-{
- if (ts > 0)
- fTextSize = ts;
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setTextSize() called with non-positive value\n");
-#endif
-}
-
-void SkPaint::setTextScaleX(SkScalar scaleX)
-{
- fTextScaleX = scaleX;
-}
-
-void SkPaint::setTextSkewX(SkScalar skewX)
-{
- fTextSkewX = skewX;
-}
-
-void SkPaint::setTextEncoding(TextEncoding encoding)
-{
- if ((unsigned)encoding <= kGlyphID_TextEncoding)
- fTextEncoding = encoding;
-#ifdef SK_DEBUG
- else
- SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-SkTypeface* SkPaint::setTypeface(SkTypeface* font)
-{
- SkRefCnt_SafeAssign(fTypeface, font);
- return font;
-}
-
-SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r)
-{
- SkRefCnt_SafeAssign(fRasterizer, r);
- return r;
-}
-
-SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
-{
- SkRefCnt_SafeAssign(fLooper, looper);
- return looper;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkGlyphCache.h"
-#include "SkUtils.h"
-
-int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
- uint16_t glyphs[]) const {
- if (byteLength == 0) {
- return 0;
- }
-
- SkASSERT(textData != NULL);
-
- if (NULL == glyphs) {
- switch (this->getTextEncoding()) {
- case kUTF8_TextEncoding:
- return SkUTF8_CountUnichars((const char*)textData, byteLength);
- case kUTF16_TextEncoding:
- return SkUTF16_CountUnichars((const uint16_t*)textData,
- byteLength >> 1);
- case kGlyphID_TextEncoding:
- return byteLength >> 1;
- default:
- SkASSERT(!"unknown text encoding");
- }
- return 0;
- }
-
- // if we get here, we have a valid glyphs[] array, so time to fill it in
-
- // handle this encoding before the setup for the glyphcache
- if (this->getTextEncoding() == kGlyphID_TextEncoding) {
- // we want to ignore the low bit of byteLength
- memcpy(glyphs, textData, byteLength >> 1 << 1);
- return byteLength >> 1;
- }
-
- SkAutoGlyphCache autoCache(*this, NULL);
- SkGlyphCache* cache = autoCache.getCache();
-
- const char* text = (const char*)textData;
- const char* stop = text + byteLength;
- uint16_t* gptr = glyphs;
-
- switch (this->getTextEncoding()) {
- case SkPaint::kUTF8_TextEncoding:
- while (text < stop) {
- *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
- }
- break;
- case SkPaint::kUTF16_TextEncoding: {
- const uint16_t* text16 = (const uint16_t*)text;
- const uint16_t* stop16 = (const uint16_t*)stop;
- while (text16 < stop16) {
- *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
- }
- break;
- }
- default:
- SkASSERT(!"unknown text encoding");
- }
- return gptr - glyphs;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static uint32_t sk_glyphID_next(const char** text)
-{
- const uint16_t* glyph = (const uint16_t*)text;
- int32_t value = *glyph;
- glyph += 1;
- *text = (const char*)glyph;
- return value;
-}
-
-static uint32_t sk_glyphID_prev(const char** text)
-{
- const uint16_t* glyph = (const uint16_t*)text;
- glyph -= 1;
- int32_t value = *glyph;
- *text = (const char*)glyph;
- return value;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
-}
-
-static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
-}
-
-static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
-}
-
-static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
-}
-
-static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- unsigned glyphID = *ptr;
- ptr += 1;
- *text = (const char*)ptr;
- return cache->getGlyphIDMetrics(glyphID);
-}
-
-static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- ptr -= 1;
- unsigned glyphID = *ptr;
- *text = (const char*)ptr;
- return cache->getGlyphIDMetrics(glyphID);
-}
-
-///
-
-static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
-}
-
-static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
-}
-
-static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
-}
-
-static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
-}
-
-static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- unsigned glyphID = *ptr;
- ptr += 1;
- *text = (const char*)ptr;
- return cache->getGlyphIDAdvance(glyphID);
-}
-
-static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache, const char** text)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- ptr -= 1;
- unsigned glyphID = *ptr;
- *text = (const char*)ptr;
- return cache->getGlyphIDAdvance(glyphID);
-}
-
-SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
- bool needFullMetrics) const
-{
- static const SkMeasureCacheProc gMeasureCacheProcs[] = {
- sk_getMetrics_utf8_next,
- sk_getMetrics_utf16_next,
- sk_getMetrics_glyph_next,
-
- sk_getMetrics_utf8_prev,
- sk_getMetrics_utf16_prev,
- sk_getMetrics_glyph_prev,
-
- sk_getAdvance_utf8_next,
- sk_getAdvance_utf16_next,
- sk_getAdvance_glyph_next,
-
- sk_getAdvance_utf8_prev,
- sk_getAdvance_utf16_prev,
- sk_getAdvance_glyph_prev
- };
-
- unsigned index = this->getTextEncoding();
-
- if (kBackward_TextBufferDirection == tbd)
- index += 3;
- if (!needFullMetrics && !this->isDevKernText())
- index += 6;
-
- SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
- return gMeasureCacheProcs[index];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
- const char** text, SkFixed, SkFixed)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
-}
-
-static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
- const char** text, SkFixed x, SkFixed y)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
-}
-
-static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache, const char** text,
- SkFixed, SkFixed)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
-}
-
-static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
- const char** text, SkFixed x, SkFixed y)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
- x, y);
-}
-
-static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache, const char** text,
- SkFixed, SkFixed)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- unsigned glyphID = *ptr;
- ptr += 1;
- *text = (const char*)ptr;
- return cache->getGlyphIDMetrics(glyphID);
-}
-
-static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
- const char** text, SkFixed x, SkFixed y)
-{
- SkASSERT(cache != NULL);
- SkASSERT(text != NULL);
-
- const uint16_t* ptr = *(const uint16_t**)text;
- unsigned glyphID = *ptr;
- ptr += 1;
- *text = (const char*)ptr;
- return cache->getGlyphIDMetrics(glyphID, x, y);
-}
-
-SkDrawCacheProc SkPaint::getDrawCacheProc() const
-{
- static const SkDrawCacheProc gDrawCacheProcs[] = {
- sk_getMetrics_utf8_00,
- sk_getMetrics_utf16_00,
- sk_getMetrics_glyph_00,
-
- sk_getMetrics_utf8_xy,
- sk_getMetrics_utf16_xy,
- sk_getMetrics_glyph_xy
- };
-
- unsigned index = this->getTextEncoding();
- if (fFlags & kSubpixelText_Flag)
- index += 3;
-
- SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
- return gDrawCacheProcs[index];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class SkAutoRestorePaintTextSizeAndFrame {
-public:
- SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) : fPaint((SkPaint*)paint)
- {
- fTextSize = paint->getTextSize();
- fStyle = paint->getStyle();
- fPaint->setStyle(SkPaint::kFill_Style);
- }
- ~SkAutoRestorePaintTextSizeAndFrame()
- {
- fPaint->setStyle(fStyle);
- fPaint->setTextSize(fTextSize);
- }
-
-private:
- SkPaint* fPaint;
- SkScalar fTextSize;
- SkPaint::Style fStyle;
-};
-
-static void set_bounds(const SkGlyph& g, SkRect* bounds)
-{
- bounds->set(SkIntToScalar(g.fLeft),
- SkIntToScalar(g.fTop),
- SkIntToScalar(g.fLeft + g.fWidth),
- SkIntToScalar(g.fTop + g.fHeight));
-}
-
-static void join_bounds(const SkGlyph& g, SkRect* bounds, SkFixed dx)
-{
- SkScalar sx = SkFixedToScalar(dx);
- bounds->join(SkIntToScalar(g.fLeft) + sx,
- SkIntToScalar(g.fTop),
- SkIntToScalar(g.fLeft + g.fWidth) + sx,
- SkIntToScalar(g.fTop + g.fHeight));
-}
-
-SkScalar SkPaint::measure_text(SkGlyphCache* cache,
- const char* text, size_t byteLength,
- int* count, SkRect* bounds) const
-{
- SkASSERT(count);
- if (byteLength == 0)
- {
- *count = 0;
- if (bounds)
- bounds->setEmpty();
- return 0;
- }
-
- SkMeasureCacheProc glyphCacheProc;
- glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
- NULL != bounds);
-
- int n = 1;
- const char* stop = (const char*)text + byteLength;
- const SkGlyph* g = &glyphCacheProc(cache, &text);
- SkFixed x = g->fAdvanceX;
-
- SkAutoKern autokern;
-
- if (NULL == bounds)
- {
- if (this->isDevKernText())
- {
- int rsb;
- for (; text < stop; n++) {
- rsb = g->fRsbDelta;
- g = &glyphCacheProc(cache, &text);
- x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
- }
- }
- else
- {
- for (; text < stop; n++) {
- x += glyphCacheProc(cache, &text).fAdvanceX;
- }
- }
- }
- else
- {
- set_bounds(*g, bounds);
- if (this->isDevKernText())
- {
- int rsb;
- for (; text < stop; n++) {
- rsb = g->fRsbDelta;
- g = &glyphCacheProc(cache, &text);
- x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
- join_bounds(*g, bounds, x);
- x += g->fAdvanceX;
- }
- }
- else
- {
- for (; text < stop; n++) {
- g = &glyphCacheProc(cache, &text);
- join_bounds(*g, bounds, x);
- x += g->fAdvanceX;
- }
- }
- }
- SkASSERT(text == stop);
-
- *count = n;
- return SkFixedToScalar(x);
-}
-
-SkScalar SkPaint::measureText(const void* textData, size_t length,
- SkRect* bounds, SkScalar zoom) const
-{
- const char* text = (const char*)textData;
- SkASSERT(text != NULL || length == 0);
-
- SkScalar scale = 0;
- SkAutoRestorePaintTextSizeAndFrame restore(this);
-
- if (this->isLinearText())
- {
- scale = fTextSize / kCanonicalTextSizeForPaths;
- // this gets restored by restore
- ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
- }
-
- SkMatrix zoomMatrix, *zoomPtr = NULL;
- if (zoom)
- {
- zoomMatrix.setScale(zoom, zoom);
- zoomPtr = &zoomMatrix;
- }
-
- SkAutoGlyphCache autoCache(*this, zoomPtr);
- SkGlyphCache* cache = autoCache.getCache();
-
- SkScalar width = 0;
-
- if (length > 0)
- {
- int tempCount;
-
- width = this->measure_text(cache, text, length, &tempCount, bounds);
- if (scale)
- {
- width = SkScalarMul(width, scale);
- if (bounds)
- {
- bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
- bounds->fTop = SkScalarMul(bounds->fTop, scale);
- bounds->fRight = SkScalarMul(bounds->fRight, scale);
- bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
- }
- }
- }
- return width;
-}
-
-typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
-
-static bool forward_textBufferPred(const char* text, const char* stop)
-{
- return text < stop;
-}
-
-static bool backward_textBufferPred(const char* text, const char* stop)
-{
- return text > stop;
-}
-
-static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
- const char** text, size_t length, const char** stop)
-{
- if (SkPaint::kForward_TextBufferDirection == tbd)
- {
- *stop = *text + length;
- return forward_textBufferPred;
- }
- else
- {
- // text should point to the end of the buffer, and stop to the beginning
- *stop = *text;
- *text += length;
- return backward_textBufferPred;
- }
-}
-
-size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
- SkScalar* measuredWidth,
- TextBufferDirection tbd) const
-{
- if (0 == length || 0 >= maxWidth)
- {
- if (measuredWidth)
- *measuredWidth = 0;
- return 0;
- }
-
- SkASSERT(textD != NULL);
- const char* text = (const char*)textD;
-
- SkScalar scale = 0;
- SkAutoRestorePaintTextSizeAndFrame restore(this);
-
- if (this->isLinearText())
- {
- scale = fTextSize / kCanonicalTextSizeForPaths;
- // this gets restored by restore
- ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
- }
-
- SkAutoGlyphCache autoCache(*this, NULL);
- SkGlyphCache* cache = autoCache.getCache();
-
- SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
- const char* stop;
- SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
- SkFixed max = SkScalarToFixed(maxWidth);
- SkFixed width = 0;
-
- SkAutoKern autokern;
-
- if (this->isDevKernText())
- {
- int rsb = 0;
- while (pred(text, stop))
- {
- const char* curr = text;
- const SkGlyph& g = glyphCacheProc(cache, &text);
- SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
- if ((width += x) > max)
- {
- width -= x;
- text = curr;
- break;
- }
- rsb = g.fRsbDelta;
- }
- }
- else
- {
- while (pred(text, stop))
- {
- const char* curr = text;
- SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
- if ((width += x) > max)
- {
- width -= x;
- text = curr;
- break;
- }
- }
- }
-
- if (measuredWidth)
- {
-
- SkScalar scalarWidth = SkFixedToScalar(width);
- if (scale)
- scalarWidth = SkScalarMul(scalarWidth, scale);
- *measuredWidth = scalarWidth;
- }
-
- // return the number of bytes measured
- return (kForward_TextBufferDirection == tbd) ?
- text - stop + length : stop - text + length;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context)
-{
- *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
- return false; // don't detach the cache
-}
-
-static void FontMetricsDescProc(const SkDescriptor* desc, void* context)
-{
- SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
-}
-
-SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const
-{
- SkScalar scale = 0;
- SkAutoRestorePaintTextSizeAndFrame restore(this);
-
- if (this->isLinearText())
- {
- scale = fTextSize / kCanonicalTextSizeForPaths;
- // this gets restored by restore
- ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
- }
-
- SkMatrix zoomMatrix, *zoomPtr = NULL;
- if (zoom)
- {
- zoomMatrix.setScale(zoom, zoom);
- zoomPtr = &zoomMatrix;
- }
-
-#if 0
- SkAutoGlyphCache autoCache(*this, zoomPtr);
- SkGlyphCache* cache = autoCache.getCache();
- const FontMetrics& my = cache->getFontMetricsY();
-#endif
- FontMetrics storage;
- if (NULL == metrics)
- metrics = &storage;
-
- this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
-
- if (scale)
- {
- metrics->fTop = SkScalarMul(metrics->fTop, scale);
- metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
- metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
- metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
- metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
- }
- return metrics->fDescent - metrics->fAscent + metrics->fLeading;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale)
-{
- bounds->set(g.fLeft * scale,
- g.fTop * scale,
- (g.fLeft + g.fWidth) * scale,
- (g.fTop + g.fHeight) * scale);
-}
-
-int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[],
- SkRect bounds[]) const
-{
- if (0 == byteLength)
- return 0;
-
- SkASSERT(NULL != textData);
-
- if (NULL == widths && NULL == bounds)
- return this->countText(textData, byteLength);
-
- SkAutoRestorePaintTextSizeAndFrame restore(this);
- SkScalar scale = 0;
-
- if (this->isLinearText())
- {
- scale = fTextSize / kCanonicalTextSizeForPaths;
- // this gets restored by restore
- ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
- }
-
- SkAutoGlyphCache autoCache(*this, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- SkMeasureCacheProc glyphCacheProc;
- glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
- NULL != bounds);
-
- const char* text = (const char*)textData;
- const char* stop = text + byteLength;
- int count = 0;
-
- if (this->isDevKernText())
- {
- // we adjust the widths returned here through auto-kerning
- SkAutoKern autokern;
- SkFixed prevWidth = 0;
-
- if (scale) {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache, &text);
- if (widths) {
- SkFixed adjust = autokern.adjust(g);
-
- if (count > 0) {
- SkScalar w = SkFixedToScalar(prevWidth + adjust);
- *widths++ = SkScalarMul(w, scale);
- }
- prevWidth = g.fAdvanceX;
- }
- if (bounds) {
- set_bounds(g, bounds++, scale);
- }
- ++count;
- }
- if (count > 0 && widths) {
- *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
- }
- } else {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache, &text);
- if (widths) {
- SkFixed adjust = autokern.adjust(g);
-
- if (count > 0) {
- *widths++ = SkFixedToScalar(prevWidth + adjust);
- }
- prevWidth = g.fAdvanceX;
- }
- if (bounds) {
- set_bounds(g, bounds++);
- }
- ++count;
- }
- if (count > 0 && widths) {
- *widths = SkFixedToScalar(prevWidth);
- }
- }
- } else { // no devkern
- if (scale) {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache, &text);
- if (widths) {
- *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
- scale);
- }
- if (bounds) {
- set_bounds(g, bounds++, scale);
- }
- ++count;
- }
- } else {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache, &text);
- if (widths) {
- *widths++ = SkFixedToScalar(g.fAdvanceX);
- }
- if (bounds) {
- set_bounds(g, bounds++);
- }
- ++count;
- }
- }
- }
-
- SkASSERT(text == stop);
- return count;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "SkDraw.h"
-
-void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const
-{
- const char* text = (const char*)textData;
- SkASSERT(length == 0 || text != NULL);
- if (text == NULL || length == 0 || path == NULL)
- return;
-
- SkTextToPathIter iter(text, length, *this, false, true);
- SkMatrix matrix;
- SkScalar prevXPos = 0;
-
- matrix.setScale(iter.getPathScale(), iter.getPathScale());
- matrix.postTranslate(x, y);
- path->reset();
-
- SkScalar xpos;
- const SkPath* iterPath;
- while ((iterPath = iter.next(&xpos)) != NULL)
- {
- matrix.postTranslate(xpos - prevXPos, 0);
- path->addPath(*iterPath, matrix);
- prevXPos = xpos;
- }
-}
-
-static void add_flattenable(SkDescriptor* desc, uint32_t tag,
- SkFlattenableWriteBuffer* buffer) {
- buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
-}
-
-/*
- * interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i])
- inspired by a desire to change the multiplier for thickness in fakebold
- therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient
- repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if
- key is the value of a repeated scalar in keys, the first one will be used
- - this may change if a binary search is used
- - also, this ensures that there is no divide by zero (an assert also checks for that)
-*/
-static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length)
-{
-
- SkASSERT(length > 0);
- SkASSERT(keys != NULL);
- SkASSERT(values != NULL);
-#ifdef SK_DEBUG
- for (int i = 1; i < length; i++)
- SkASSERT(keys[i] >= keys[i-1]);
-#endif
- int right = 0;
- while (right < length && key > keys[right])
- right++;
- //could use sentinal values to eliminate conditionals
- //i assume i am not in control of input values, so i want to make it simple
- if (length == right)
- return values[length-1];
- if (0 == right)
- return values[0];
- //otherwise, we interpolate between right-1 and right
- SkScalar rVal = values[right];
- SkScalar lVal = values[right-1];
- SkScalar rightKey = keys[right];
- SkScalar leftKey = keys[right-1];
- SkASSERT(rightKey != leftKey);
- //fractional amount which we will multiply by the difference in the left value and right value
- SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey);
- return lVal + SkScalarMul(fract, rVal-lVal);
-}
-
-//used for interpolating in fakeBold
-static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) };
-static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 };
-
-static SkMask::Format computeMaskFormat(const SkPaint& paint)
-{
- uint32_t flags = paint.getFlags();
-
- return (flags & SkPaint::kAntiAlias_Flag) ? SkMask::kA8_Format : SkMask::kBW_Format;
-}
-
-static SkScalerContext::Hints computeScalerHints(const SkPaint& paint)
-{
- uint32_t flags = paint.getFlags();
-
- if (flags & SkPaint::kLinearText_Flag)
- return SkScalerContext::kNo_Hints;
- else if (flags & SkPaint::kSubpixelText_Flag)
- return SkScalerContext::kSubpixel_Hints;
- else
- return SkScalerContext::kNormal_Hints;
-}
-
-void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec)
-{
- SkASSERT(deviceMatrix == NULL || (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
-
- rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
- rec->fTextSize = paint.getTextSize();
- rec->fPreScaleX = paint.getTextScaleX();
- rec->fPreSkewX = paint.getTextSkewX();
-
- if (deviceMatrix)
- {
- rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
- rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
- rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
- rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
- }
- else
- {
- rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
- rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
- }
-
- SkPaint::Style style = paint.getStyle();
- SkScalar strokeWidth = paint.getStrokeWidth();
-
- if (paint.isFakeBoldText())
- {
- SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2);
- SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
-
- if (style == SkPaint::kFill_Style)
- {
- style = SkPaint::kStrokeAndFill_Style;
- strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
- }
- else
- strokeWidth += extra;
- }
-
- unsigned flags = SkFontHost::ComputeGammaFlag(paint);
-
- if (paint.isDevKernText())
- flags |= SkScalerContext::kDevKernText_Flag;
-
- if (style != SkPaint::kFill_Style && strokeWidth > 0)
- {
- rec->fFrameWidth = strokeWidth;
- rec->fMiterLimit = paint.getStrokeMiter();
- rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
-
- if (style == SkPaint::kStrokeAndFill_Style)
- flags |= SkScalerContext::kFrameAndFill_Flag;
- }
- else
- {
- rec->fFrameWidth = 0;
- rec->fMiterLimit = 0;
- rec->fStrokeJoin = 0;
- }
-
- rec->fHints = SkToU8(computeScalerHints(paint));
- rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
- rec->fFlags = SkToU8(flags);
-}
-
-#define MIN_SIZE_FOR_EFFECT_BUFFER 1024
-
-void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
- void (*proc)(const SkDescriptor*, void*),
- void* context) const
-{
- SkScalerContext::Rec rec;
-
- SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
-
- size_t descSize = sizeof(rec);
- int entryCount = 1;
- SkPathEffect* pe = this->getPathEffect();
- SkMaskFilter* mf = this->getMaskFilter();
- SkRasterizer* ra = this->getRasterizer();
-
- SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
- SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
- SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
-
- if (pe) {
- peBuffer.writeFlattenable(pe);
- descSize += peBuffer.size();
- entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
- // seems like we could support kLCD as well at this point...
- }
- if (mf) {
- mfBuffer.writeFlattenable(mf);
- descSize += mfBuffer.size();
- entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
- }
- if (ra) {
- raBuffer.writeFlattenable(ra);
- descSize += raBuffer.size();
- entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
- }
- descSize += SkDescriptor::ComputeOverhead(entryCount);
-
- SkAutoDescriptor ad(descSize);
- SkDescriptor* desc = ad.getDesc();
-
- desc->init();
- desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
- if (pe) {
- add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
- }
- if (mf) {
- add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
- }
- if (ra) {
- add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
- }
-
- SkASSERT(descSize == desc->getLength());
- desc->computeChecksum();
-
- proc(desc, context);
-}
-
-static void DetachDescProc(const SkDescriptor* desc, void* context)
-{
- *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
-}
-
-SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
-{
- SkGlyphCache* cache;
- this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
- return cache;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkStream.h"
-
-void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
- buffer.writeTypeface(this->getTypeface());
- buffer.writeScalar(this->getTextSize());
- buffer.writeScalar(this->getTextScaleX());
- buffer.writeScalar(this->getTextSkewX());
- buffer.writeFlattenable(this->getPathEffect());
- buffer.writeFlattenable(this->getShader());
- buffer.writeFlattenable(this->getXfermode());
- buffer.writeFlattenable(this->getMaskFilter());
- buffer.writeFlattenable(this->getColorFilter());
- buffer.writeFlattenable(this->getRasterizer());
- buffer.writeFlattenable(this->getLooper());
- buffer.write32(this->getColor());
- buffer.writeScalar(this->getStrokeWidth());
- buffer.writeScalar(this->getStrokeMiter());
- buffer.write16(this->getFlags());
- buffer.write8(this->getTextAlign());
- buffer.write8(this->getStrokeCap());
- buffer.write8(this->getStrokeJoin());
- buffer.write8(this->getStyle());
- buffer.write8(this->getTextEncoding());
-}
-
-void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
- this->setTypeface(buffer.readTypeface());
- this->setTextSize(buffer.readScalar());
- this->setTextScaleX(buffer.readScalar());
- this->setTextSkewX(buffer.readScalar());
- this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
- this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
- this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
- this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
- this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
- this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
- this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
- this->setColor(buffer.readU32());
- this->setStrokeWidth(buffer.readScalar());
- this->setStrokeMiter(buffer.readScalar());
- this->setFlags(buffer.readU16());
- this->setTextAlign((SkPaint::Align) buffer.readU8());
- this->setStrokeCap((SkPaint::Cap) buffer.readU8());
- this->setStrokeJoin((SkPaint::Join) buffer.readU8());
- this->setStyle((SkPaint::Style) buffer.readU8());
- this->setTextEncoding((SkPaint::TextEncoding) buffer.readU8());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkShader* SkPaint::setShader(SkShader* shader)
-{
- SkRefCnt_SafeAssign(fShader, shader);
- return shader;
-}
-
-SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
-{
- SkRefCnt_SafeAssign(fColorFilter, filter);
- return filter;
-}
-
-SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
-{
- SkRefCnt_SafeAssign(fXfermode, mode);
- return mode;
-}
-
-SkXfermode* SkPaint::setPorterDuffXfermode(SkPorterDuff::Mode mode)
-{
- fXfermode->safeUnref();
- fXfermode = SkPorterDuff::CreateXfermode(mode);
- return fXfermode;
-}
-
-SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
-{
- SkRefCnt_SafeAssign(fPathEffect, effect);
- return effect;
-}
-
-SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
-{
- SkRefCnt_SafeAssign(fMaskFilter, filter);
- return filter;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
-{
- SkPath effectPath, strokePath;
- const SkPath* path = &src;
-
- SkScalar width = this->getStrokeWidth();
-
- switch (this->getStyle()) {
- case SkPaint::kFill_Style:
- width = -1; // mark it as no-stroke
- break;
- case SkPaint::kStrokeAndFill_Style:
- if (width == 0)
- width = -1; // mark it as no-stroke
- break;
- case SkPaint::kStroke_Style:
- break;
- default:
- SkASSERT(!"unknown paint style");
- }
-
- if (this->getPathEffect())
- {
- // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
- if (this->getStyle() == SkPaint::kStrokeAndFill_Style)
- width = -1; // mark it as no-stroke
-
- if (this->getPathEffect()->filterPath(&effectPath, src, &width))
- path = &effectPath;
-
- // restore the width if we earlier had to lie, and if we're still set to no-stroke
- // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
- // and we want to respect that (i.e. don't overwrite their setting for width)
- if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0)
- {
- width = this->getStrokeWidth();
- if (width == 0)
- width = -1;
- }
- }
-
- if (width > 0 && !path->isEmpty())
- {
- SkStroke stroker(*this, width);
- stroker.strokePath(*path, &strokePath);
- path = &strokePath;
- }
-
- if (path == &src)
- *dst = src;
- else
- {
- SkASSERT(path == &effectPath || path == &strokePath);
- dst->swap(*(SkPath*)path);
- }
-
- return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
-}
-
-bool SkPaint::canComputeFastBounds() const {
- // use bit-or since no need for early exit
- return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
- reinterpret_cast<uintptr_t>(this->getLooper()) |
- reinterpret_cast<uintptr_t>(this->getRasterizer()) |
- reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
-}
-
-const SkRect& SkPaint::computeFastBounds(const SkRect& src,
- SkRect* storage) const {
- SkASSERT(storage);
-
- if (this->getStyle() != SkPaint::kFill_Style) {
- // if we're stroked, outset the rect by the radius (and join type)
- SkScalar radius = SkScalarHalf(this->getStrokeWidth());
-
- if (0 == radius) { // hairline
- radius = SK_Scalar1;
- } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
- SkScalar scale = this->getStrokeMiter();
- if (scale > SK_Scalar1) {
- radius = SkScalarMul(radius, scale);
- }
- }
- storage->set(src.fLeft - radius, src.fTop - radius,
- src.fRight + radius, src.fBottom + radius);
- return *storage;
- }
- // no adjustments needed, just return the original rect
- return src;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-static bool has_thick_frame(const SkPaint& paint)
-{
- return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style;
-}
-
-SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
- const SkPaint& paint,
- bool applyStrokeAndPathEffects,
- bool forceLinearTextOn)
- : fPaint(paint) /* make a copy of the paint */
-{
- fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
- true);
-
- if (forceLinearTextOn)
- fPaint.setLinearText(true);
- fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
-
- if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint))
- applyStrokeAndPathEffects = false;
-
- // can't use our canonical size if we need to apply patheffects/strokes
- if (fPaint.isLinearText() && !applyStrokeAndPathEffects)
- {
- fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
- fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
- }
- else
- fScale = SK_Scalar1;
-
- if (!applyStrokeAndPathEffects)
- {
- fPaint.setStyle(SkPaint::kFill_Style);
- fPaint.setPathEffect(NULL);
- }
-
- fCache = fPaint.detachCache(NULL);
-
- SkPaint::Style style = SkPaint::kFill_Style;
- SkPathEffect* pe = NULL;
-
- if (!applyStrokeAndPathEffects)
- {
- style = paint.getStyle(); // restore
- pe = paint.getPathEffect(); // restore
- }
- fPaint.setStyle(style);
- fPaint.setPathEffect(pe);
- fPaint.setMaskFilter(paint.getMaskFilter()); // restore
-
- // now compute fXOffset if needed
-
- SkScalar xOffset = 0;
- if (paint.getTextAlign() != SkPaint::kLeft_Align) // need to measure first
- {
- int count;
- SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale);
- if (paint.getTextAlign() == SkPaint::kCenter_Align)
- width = SkScalarHalf(width);
- xOffset = -width;
- }
- fXPos = xOffset;
- fPrevAdvance = 0;
-
- fText = text;
- fStop = text + length;
-}
-
-SkTextToPathIter::~SkTextToPathIter()
-{
- SkGlyphCache::AttachCache(fCache);
-}
-
-const SkPath* SkTextToPathIter::next(SkScalar* xpos)
-{
- while (fText < fStop)
- {
- const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
-
- fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
- fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking();
-
- if (glyph.fWidth)
- {
- if (xpos)
- *xpos = fXPos;
- return fCache->findPath(glyph);
- }
- }
- return NULL;
-}