Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2014 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 SkTextBlob_DEFINED
      9 #define SkTextBlob_DEFINED
     10 
     11 #include "SkPaint.h"
     12 #include "SkRefCnt.h"
     13 #include "SkTArray.h"
     14 #include "SkTDArray.h"
     15 
     16 class SkReadBuffer;
     17 class SkWriteBuffer;
     18 
     19 /** \class SkTextBlob
     20 
     21     SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
     22 */
     23 class SK_API SkTextBlob : public SkRefCnt {
     24 public:
     25     /**
     26      *  Returns a conservative blob bounding box.
     27      */
     28     const SkRect& bounds() const { return fBounds; }
     29 
     30     /**
     31      *  Return a non-zero, unique value representing the text blob.
     32      */
     33     uint32_t uniqueID() const { return fUniqueID; }
     34 
     35     /**
     36      *  Serialize to a buffer.
     37      */
     38     void flatten(SkWriteBuffer&) const;
     39 
     40     /**
     41      *  Recreate an SkTextBlob that was serialized into a buffer.
     42      *
     43      *  @param  SkReadBuffer Serialized blob data.
     44      *  @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
     45      *          invalid.
     46      */
     47     static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
     48 
     49 private:
     50     enum GlyphPositioning {
     51         kDefault_Positioning      = 0, // Default glyph advances -- zero scalars per glyph.
     52         kHorizontal_Positioning   = 1, // Horizontal positioning -- one scalar per glyph.
     53         kFull_Positioning         = 2  // Point positioning -- two scalars per glyph.
     54     };
     55 
     56     class RunRecord;
     57 
     58     class RunIterator {
     59     public:
     60         RunIterator(const SkTextBlob* blob);
     61 
     62         bool done() const;
     63         void next();
     64 
     65         uint32_t glyphCount() const;
     66         const uint16_t* glyphs() const;
     67         const SkScalar* pos() const;
     68         const SkPoint& offset() const;
     69         void applyFontToPaint(SkPaint*) const;
     70         GlyphPositioning positioning() const;
     71         bool isLCD() const;
     72 
     73     private:
     74         const RunRecord* fCurrentRun;
     75         int              fRemainingRuns;
     76 
     77         SkDEBUGCODE(uint8_t* fStorageTop;)
     78     };
     79 
     80     SkTextBlob(int runCount, const SkRect& bounds);
     81 
     82     virtual ~SkTextBlob();
     83 
     84     // Memory for objects of this class is created with sk_malloc rather than operator new and must
     85     // be freed with sk_free.
     86     void operator delete(void* p) { sk_free(p); }
     87     void* operator new(size_t) {
     88         SkFAIL("All blobs are created by placement new.");
     89         return sk_malloc_throw(0);
     90     }
     91     void* operator new(size_t, void* p) { return p; }
     92 
     93     static unsigned ScalarsPerGlyph(GlyphPositioning pos);
     94 
     95     friend class GrAtlasTextContext;
     96     friend class GrTextBlobCache;
     97     friend class GrTextContext;
     98     friend class SkBaseDevice;
     99     friend class SkTextBlobBuilder;
    100     friend class TextBlobTester;
    101 
    102     const int        fRunCount;
    103     const SkRect     fBounds;
    104     const uint32_t fUniqueID;
    105 
    106     SkDEBUGCODE(size_t fStorageSize;)
    107 
    108     // The actual payload resides in externally-managed storage, following the object.
    109     // (see the .cpp for more details)
    110 
    111     typedef SkRefCnt INHERITED;
    112 };
    113 
    114 /** \class SkTextBlobBuilder
    115 
    116     Helper class for constructing SkTextBlobs.
    117  */
    118 class SK_API SkTextBlobBuilder {
    119 public:
    120     SkTextBlobBuilder();
    121 
    122     ~SkTextBlobBuilder();
    123 
    124     /**
    125      *  Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
    126      *  can be reused.
    127      */
    128     const SkTextBlob* build();
    129 
    130     /**
    131      *  Glyph and position buffers associated with a run.
    132      *
    133      *  A run is a sequence of glyphs sharing the same font metrics and positioning mode.
    134      */
    135     struct RunBuffer {
    136         uint16_t* glyphs;
    137         SkScalar* pos;
    138     };
    139 
    140     /**
    141      *  Allocates a new default-positioned run and returns its writable glyph buffer
    142      *  for direct manipulation.
    143      *
    144      *  @param font    The font to be used for this run.
    145      *  @param count   Number of glyphs.
    146      *  @param x,y     Position within the blob.
    147      *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
    148      *                 be used when computing the blob bounds, to avoid re-measuring.
    149      *
    150      *  @return        A writable glyph buffer, valid until the next allocRun() or
    151      *                 build() call. The buffer is guaranteed to hold @count@ glyphs.
    152      */
    153     const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
    154                               const SkRect* bounds = NULL);
    155 
    156     /**
    157      *  Allocates a new horizontally-positioned run and returns its writable glyph and position
    158      *  buffers for direct manipulation.
    159      *
    160      *  @param font    The font to be used for this run.
    161      *  @param count   Number of glyphs.
    162      *  @param y       Vertical offset within the blob.
    163      *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will
    164      *                 be used when computing the blob bounds, to avoid re-measuring.
    165      *
    166      *  @return        Writable glyph and position buffers, valid until the next allocRun()
    167      *                 or build() call. The buffers are guaranteed to hold @count@ elements.
    168      */
    169     const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
    170                                   const SkRect* bounds = NULL);
    171 
    172     /**
    173      *  Allocates a new fully-positioned run and returns its writable glyph and position
    174      *  buffers for direct manipulation.
    175      *
    176      *  @param font   The font to be used for this run.
    177      *  @param count  Number of glyphs.
    178      *  @param bounds Optional run bounding box. If known in advance (!= NULL), it will
    179      *                be used when computing the blob bounds, to avoid re-measuring.
    180      *
    181      *  @return       Writable glyph and position buffers, valid until the next allocRun()
    182      *                or build() call. The glyph buffer and position buffer are
    183      *                guaranteed to hold @count@ and 2 * @count@ elements, respectively.
    184      */
    185     const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
    186 
    187 private:
    188     void reserve(size_t size);
    189     void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
    190                        int count, SkPoint offset, const SkRect* bounds);
    191     bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
    192                   int count, SkPoint offset);
    193     void updateDeferredBounds();
    194 
    195     static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
    196     static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
    197 
    198     SkAutoTMalloc<uint8_t> fStorage;
    199     size_t                 fStorageSize;
    200     size_t                 fStorageUsed;
    201 
    202     SkRect                 fBounds;
    203     int                    fRunCount;
    204     bool                   fDeferredBounds;
    205     size_t                 fLastRun; // index into fStorage
    206 
    207     RunBuffer              fCurrentRunBuffer;
    208 };
    209 
    210 #endif // SkTextBlob_DEFINED
    211