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      */
bounds()28     const SkRect& bounds() const { return fBounds; }
29 
30     /**
31      *  Return a non-zero, unique value representing the text blob.
32      */
uniqueID()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.
delete(void * p)86     void operator delete(void* p) { sk_free(p); }
new(size_t)87     void* operator new(size_t) {
88         SkFAIL("All blobs are created by placement new.");
89         return sk_malloc_throw(0);
90     }
new(size_t,void * p)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