1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkTextToPathIter_DEFINED 9 #define SkTextToPathIter_DEFINED 10 11 #include "SkAutoKern.h" 12 #include "SkPaint.h" 13 14 class SkGlyphCache; 15 16 class SkTextBaseIter { 17 protected: 18 SkTextBaseIter(const char text[], size_t length, const SkPaint& paint, 19 bool applyStrokeAndPathEffects); 20 ~SkTextBaseIter(); 21 22 SkGlyphCache* fCache; 23 SkPaint fPaint; 24 SkScalar fScale; 25 SkFixed fPrevAdvance; 26 const char* fText; 27 const char* fStop; 28 SkPaint::GlyphCacheProc fGlyphCacheProc; 29 30 SkScalar fXPos; // accumulated xpos, returned in next 31 SkAutoKern fAutoKern; 32 int fXYIndex; // cache for horizontal -vs- vertical text 33 }; 34 35 class SkTextToPathIter : SkTextBaseIter { 36 public: 37 SkTextToPathIter(const char text[], size_t length, const SkPaint& paint, 38 bool applyStrokeAndPathEffects) 39 : SkTextBaseIter(text, length, paint, applyStrokeAndPathEffects) { 40 } 41 42 const SkPaint& getPaint() const { return fPaint; } 43 SkScalar getPathScale() const { return fScale; } 44 45 /** 46 * Returns false when all of the text has been consumed 47 */ 48 bool next(const SkPath** path, SkScalar* xpos); 49 }; 50 51 class SkTextInterceptsIter : SkTextBaseIter { 52 public: 53 enum class TextType { 54 kText, 55 kPosText 56 }; 57 58 SkTextInterceptsIter(const char text[], size_t length, const SkPaint& paint, 59 const SkScalar bounds[2], SkScalar x, SkScalar y, TextType textType) 60 : SkTextBaseIter(text, length, paint, false) 61 , fTextType(textType) { 62 fBoundsBase[0] = bounds[0]; 63 fBoundsBase[1] = bounds[1]; 64 this->setPosition(x, y); 65 } 66 67 /** 68 * Returns false when all of the text has been consumed 69 */ 70 bool next(SkScalar* array, int* count); 71 72 void setPosition(SkScalar x, SkScalar y) { 73 SkScalar xOffset = TextType::kText == fTextType && fXYIndex ? fXPos : 0; 74 if (TextType::kPosText == fTextType 75 && fPaint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first 76 const char* text = fText; 77 const SkGlyph& glyph = fGlyphCacheProc(fCache, &text); 78 SkScalar width = SkScalarMul(SkFixedToScalar((&glyph.fAdvanceX)[0]), fScale); 79 if (fPaint.getTextAlign() == SkPaint::kCenter_Align) { 80 width = SkScalarHalf(width); 81 } 82 xOffset = width; 83 } 84 85 for (int i = 0; i < (int) SK_ARRAY_COUNT(fBounds); ++i) { 86 SkScalar bound = fBoundsBase[i] - (fXYIndex ? x : y); 87 if (fXYIndex) { 88 bound += xOffset; 89 } 90 fBounds[i] = bound / fScale; 91 } 92 93 fXPos = xOffset + (fXYIndex ? y : x); 94 fPrevAdvance = 0; 95 } 96 97 private: 98 SkScalar fBounds[2]; 99 SkScalar fBoundsBase[2]; 100 TextType fTextType; 101 }; 102 103 #endif 104