Home | History | Annotate | Download | only in core
      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