blob: af29933b4ff4419608b7014f837a923d6d15bf40 [file] [log] [blame]
fmalita00d5c2c2014-08-21 08:53:26 -07001/*
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
fmalitab7425172014-08-26 07:56:44 -070016class SkReadBuffer;
17class SkWriteBuffer;
18
fmalita00d5c2c2014-08-21 08:53:26 -070019/** \class SkTextBlob
20
21 SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
22*/
jbroman3053dfa2014-08-25 06:22:12 -070023class SK_API SkTextBlob : public SkRefCnt {
fmalita00d5c2c2014-08-21 08:53:26 -070024public:
25 /**
26 * Returns the 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;
34
35private:
36 enum GlyphPositioning {
37 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
38 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
39 kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
40 };
41
42 class RunIterator {
43 public:
44 RunIterator(const SkTextBlob* blob);
45
46 bool done() const;
47 void next();
48
49 uint32_t glyphCount() const;
50 const uint16_t* glyphs() const;
51 const SkScalar* pos() const;
52 const SkPoint& offset() const;
fmalita37ecbaf2014-08-22 09:01:19 -070053 void applyFontToPaint(SkPaint*) const;
fmalita00d5c2c2014-08-21 08:53:26 -070054 GlyphPositioning positioning() const;
55
56 private:
57 const SkTextBlob* fBlob;
58 int fIndex;
59 };
60
61 // A run is a sequence of glyphs sharing the same font metrics and positioning mode.
62 struct Run {
63 uint32_t count;
64 uint32_t glyphStart; // index into fGlyphBuffer
65 uint32_t posStart; // index into fPosBuffer
66 SkPoint offset; // run offset (unsued for fully positioned glyphs)
67 SkPaint font;
68 GlyphPositioning positioning;
69 };
70
71 SkTextBlob(uint16_t* glyphs, SkScalar* pos, const SkTArray<Run>* runs, const SkRect& bounds);
72
fmalitab7425172014-08-26 07:56:44 -070073 void flatten(SkWriteBuffer&) const;
74 static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
75
76 static unsigned ScalarsPerGlyph(GlyphPositioning pos);
77
fmalita00d5c2c2014-08-21 08:53:26 -070078 friend class SkCanvas;
fmalitab7425172014-08-26 07:56:44 -070079 friend class SkPictureData;
fmalita00d5c2c2014-08-21 08:53:26 -070080 friend class SkTextBlobBuilder;
fmalitac6765d62014-08-21 15:03:04 -070081 friend class TextBlobTester;
fmalita00d5c2c2014-08-21 08:53:26 -070082
83 const SkAutoTMalloc<uint16_t> fGlyphBuffer;
84 const SkAutoTMalloc<SkScalar> fPosBuffer;
85
86 // SkTArray required here for run font destruction.
87 SkAutoTDelete<const SkTArray<Run> > fRuns;
88 const SkRect fBounds;
89
90 mutable uint32_t fUniqueID;
91
92 typedef SkRefCnt INHERITED;
93};
94
95/** \class SkTextBlobBuilder
96
97 Helper class for constructing SkTextBlobs.
98 */
jbroman3053dfa2014-08-25 06:22:12 -070099class SK_API SkTextBlobBuilder {
fmalita00d5c2c2014-08-21 08:53:26 -0700100public:
101 /**
102 * @param runs The number of runs to be added, if known. This is a storage hint and
103 * not a limit.
104 */
105 SkTextBlobBuilder(unsigned runs = 0);
106
107 ~SkTextBlobBuilder();
108
109 /**
110 * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
111 * can be reused.
112 */
113 const SkTextBlob* build();
114
115 /**
116 * Glyph and position buffers associated with a run.
117 *
118 * A run is a sequence of glyphs sharing the same font metrics and positioning mode.
119 */
120 struct RunBuffer {
121 uint16_t* glyphs;
122 SkScalar* pos;
123 };
124
125 /**
126 * Allocates a new default-positioned run and returns its writable glyph buffer
127 * for direct manipulation.
128 *
129 * @param font The font to be used for this run.
130 * @param count Number of glyphs.
131 * @param x,y Position within the blob.
132 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
133 * be used when computing the blob bounds, to avoid re-measuring.
134 *
135 * @return A writable glyph buffer, valid until the next allocRun() or
136 * build() call. The buffer is guaranteed to hold @count@ glyphs.
137 */
138 const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
139 const SkRect* bounds = NULL);
140
141 /**
142 * Allocates a new horizontally-positioned run and returns its writable glyph and position
143 * buffers for direct manipulation.
144 *
145 * @param font The font to be used for this run.
146 * @param count Number of glyphs.
147 * @param y Vertical offset within the blob.
148 * @param bounds Optional run bounding box. If known in advance (!= NULL), it will
149 * be used when computing the blob bounds, to avoid re-measuring.
150 *
151 * @return Writable glyph and position buffers, valid until the next allocRun()
152 * or build() call. The buffers are guaranteed to hold @count@ elements.
153 */
154 const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
155 const SkRect* bounds = NULL);
156
157 /**
158 * Allocates a new fully-positioned run and returns its writable glyph and position
159 * buffers for direct manipulation.
160 *
161 * @param font The font to be used for this run.
162 * @param count Number of glyphs.
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 glyph buffer and position buffer are
168 * guaranteed to hold @count@ and 2 * @count@ elements, respectively.
169 */
170 const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
171
172private:
173 void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
174 int count, SkPoint offset, const SkRect* bounds);
175 void ensureRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
176 const SkPoint& offset);
177 void updateDeferredBounds();
178
179 SkTDArray<uint16_t> fGlyphBuffer;
180 SkTDArray<SkScalar> fPosBuffer;
181 SkTArray<SkTextBlob::Run>* fRuns;
182
183 SkRect fBounds;
184 bool fDeferredBounds;
185
186 RunBuffer fCurrentRunBuffer;
187};
188
189#endif // SkTextBlob_DEFINED