/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkTextToPathIter_DEFINED #define SkTextToPathIter_DEFINED #include "SkPaint.h" #include "SkStrikeCache.h" class SkTextBaseIter { protected: SkTextBaseIter(const char text[], size_t length, const SkPaint& paint, bool applyStrokeAndPathEffects); SkExclusiveStrikePtr fCache; SkPaint fPaint; SkScalar fScale; SkScalar fPrevAdvance; const char* fText; const char* fStop; SkPaint::GlyphCacheProc fGlyphCacheProc; SkScalar fXPos; // accumulated xpos, returned in next int fXYIndex; // cache for horizontal -vs- vertical text }; class SkTextToPathIter : SkTextBaseIter { public: SkTextToPathIter(const char text[], size_t length, const SkPaint& paint, bool applyStrokeAndPathEffects) : SkTextBaseIter(text, length, paint, applyStrokeAndPathEffects) { } const SkPaint& getPaint() const { return fPaint; } SkScalar getPathScale() const { return fScale; } /** * Returns false when all of the text has been consumed */ bool next(const SkPath** path, SkScalar* xpos); }; class SkTextInterceptsIter : SkTextBaseIter { public: enum class TextType { kText, kPosText }; SkTextInterceptsIter(const char text[], size_t length, const SkPaint& paint, const SkScalar bounds[2], SkScalar x, SkScalar y, TextType textType) : SkTextBaseIter(text, length, paint, false) , fTextType(textType) { fBoundsBase[0] = bounds[0]; fBoundsBase[1] = bounds[1]; this->setPosition(x, y); } /** * Returns false when all of the text has been consumed */ bool next(SkScalar* array, int* count); void setPosition(SkScalar x, SkScalar y) { SkScalar xOffset = TextType::kText == fTextType && fXYIndex ? fXPos : 0; if (TextType::kPosText == fTextType && fPaint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first const char* text = fText; const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &text, fStop); SkScalar width = (&glyph.fAdvanceX)[0] * fScale; if (fPaint.getTextAlign() == SkPaint::kCenter_Align) { width = SkScalarHalf(width); } xOffset = width; } for (int i = 0; i < (int) SK_ARRAY_COUNT(fBounds); ++i) { SkScalar bound = fBoundsBase[i] - (fXYIndex ? x : y); if (fXYIndex) { bound += xOffset; } fBounds[i] = bound / fScale; } fXPos = xOffset + (fXYIndex ? y : x); fPrevAdvance = 0; } private: SkScalar fBounds[2]; SkScalar fBoundsBase[2]; TextType fTextType; }; #endif