OLD | NEW |
---|---|
(Empty) | |
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 #include "SkTextBlob.h" | |
9 | |
10 #include "SkDevice.h" | |
11 | |
12 const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, con st SkPaint& paint, | |
13 const SkRect* bounds) { | |
14 if (NULL == glyphs || 0 == count) { | |
15 return NULL; | |
16 } | |
17 | |
18 return SkNEW_ARGS(SkTextChunk, (glyphs, count, paint, bounds)); | |
19 } | |
20 | |
21 const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, con st SkScalar* pos, | |
22 const SkPaint& paint, const SkRect* bounds) { | |
23 if (NULL == glyphs || NULL == pos || 0 == count) { | |
24 return NULL; | |
25 } | |
26 | |
27 return SkNEW_ARGS(SkTextChunk, (glyphs, count, pos, paint, bounds)); | |
28 } | |
29 | |
30 const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, con st SkPoint* pos, | |
31 const SkPaint& paint, const SkRect* bounds) { | |
32 if (NULL == glyphs || NULL == pos || 0 == count) { | |
33 return NULL; | |
34 } | |
35 | |
36 return SkNEW_ARGS(SkTextChunk, (glyphs, count, pos, paint, bounds)); | |
37 } | |
38 | |
39 SkTextChunk::SkTextChunk(const uint16_t *glyphs, size_t count, const SkPaint &pa int, | |
40 const SkRect* bounds) | |
41 : fPos(NULL) | |
42 , fFont(paint) | |
43 , fScalarsPerPos(0) { | |
44 | |
45 SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()); | |
46 init(glyphs, count, bounds, NULL); | |
47 } | |
48 | |
49 SkTextChunk::SkTextChunk(const uint16_t *glyphs, size_t count, const SkScalar* p os, | |
50 const SkPaint &paint, const SkRect* bounds) | |
51 : fPos(NULL) | |
52 , fFont(paint) | |
53 , fScalarsPerPos(1) { | |
54 | |
55 SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()); | |
56 init(glyphs, count, bounds, pos); | |
57 } | |
58 | |
59 SkTextChunk::SkTextChunk(const uint16_t *glyphs, size_t count, const SkPoint* po s, | |
60 const SkPaint &paint, const SkRect* bounds) | |
61 : fPos(NULL) | |
62 , fFont(paint) | |
63 , fScalarsPerPos(2) { | |
64 | |
65 SK_COMPILE_ASSERT(sizeof(SkScalar) * 2 == sizeof(SkPoint), point_is_two_scal ars); | |
66 | |
67 SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()); | |
68 init(glyphs, count, bounds, (const SkScalar*)pos); | |
mtklein
2014/08/14 14:00:42
Can't hurt to label this explicitly as reinterpret
f(malita)
2014/08/14 14:29:26
Done.
| |
69 } | |
70 | |
71 SkTextChunk::~SkTextChunk() { | |
72 sk_free(fGlyphs); | |
73 sk_free(fPos); | |
74 } | |
75 | |
76 void SkTextChunk::init(const uint16_t* glyphs, size_t count, const SkRect* bound s, | |
77 const SkScalar* pos) { | |
78 SkASSERT(glyphs); | |
79 SkASSERT(count > 0); | |
80 | |
81 size_t storageSize = sizeof(uint16_t) * count; | |
82 | |
83 fGlyphCount = count; | |
84 fGlyphs = static_cast<uint16_t*>(sk_malloc_throw(storageSize)); | |
85 memcpy(fGlyphs, glyphs, storageSize); | |
86 | |
87 fBoundsDirty = NULL == bounds; | |
88 if (!fBoundsDirty) { | |
89 fBounds = *bounds; | |
90 } | |
91 | |
92 if (NULL != pos) { | |
93 size_t posStorageSize = sizeof(SkScalar) * fScalarsPerPos * count; | |
94 fPos = static_cast<SkScalar*>(sk_malloc_throw(posStorageSize)); | |
95 memcpy(fPos, pos, posStorageSize); | |
96 } | |
97 } | |
98 | |
99 const SkRect& SkTextChunk::bounds() const { | |
100 if (fBoundsDirty) { | |
101 fFont.measureText(fGlyphs, fGlyphCount, &fBounds); | |
102 fBoundsDirty = false; | |
103 } | |
104 | |
105 return fBounds; | |
106 } | |
107 | |
108 void SkTextChunk::draw(SkBaseDevice* device, const SkDraw& draw, const SkPaint& paint) const { | |
109 SkASSERT(NULL != device); | |
110 SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()); | |
111 | |
112 size_t length = sizeof(uint16_t) * fGlyphCount; | |
113 if (NULL != fPos) { | |
114 SkASSERT(1 == fScalarsPerPos || 2 == fScalarsPerPos); | |
115 device->drawPosText(draw, fGlyphs, length, fPos, 0, fScalarsPerPos, pain t); | |
116 } else { | |
117 SkASSERT(0 == fScalarsPerPos); | |
118 device->drawText(draw, fGlyphs, length, 0, 0, paint); | |
119 } | |
120 } | |
121 | |
122 const SkTextBlob* SkTextBlob::Create(const SkTextChunk *chunk) { | |
123 SkTDArray<const SkTextChunk*> chunks; | |
124 chunks.setReserve(1); | |
125 *chunks.append() = chunk; | |
126 return SkNEW_ARGS(SkTextBlob, (chunks)); | |
127 } | |
128 | |
129 const SkTextBlob* SkTextBlob::Create(const SkTDArray<const SkTextChunk*>& chunks ) { | |
130 return SkNEW_ARGS(SkTextBlob, (chunks)); | |
131 } | |
132 | |
133 SkTextBlob::SkTextBlob(const SkTDArray<const SkTextChunk*>& chunks) | |
134 : fChunks(chunks) | |
135 , fUniqueID(SK_InvalidGenID) { | |
136 } | |
137 | |
138 SkTextBlob::~SkTextBlob() { | |
139 Iter it(this); | |
140 while (const SkTextChunk* chunk = it.next()) { | |
141 SkDELETE(chunk); | |
142 } | |
143 } | |
144 | |
145 uint32_t SkTextBlob::uniqueID() const { | |
146 static int32_t gTextBlobGenerationID; // = 0; | |
147 | |
148 // do a loop in case our global wraps around, as we never want to | |
149 // return SK_InvalidGenID | |
150 while (SK_InvalidGenID == fUniqueID) { | |
151 fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1; | |
152 } | |
153 | |
154 return fUniqueID; | |
155 } | |
156 | |
157 SkTextBlobBuilder::SkTextBlobBuilder() { | |
158 } | |
159 | |
160 SkTextBlobBuilder::~SkTextBlobBuilder() { | |
161 // unused chunks. | |
162 for (int i = 0; i < fChunks.count(); ++i) { | |
163 SkDELETE(fChunks[i]); | |
164 } | |
165 } | |
166 | |
167 const SkTextBlob* SkTextBlobBuilder::build() { | |
168 const SkTextBlob* blob = SkTextBlob::Create(fChunks); | |
169 fChunks.rewind(); | |
170 return blob; | |
171 } | |
172 | |
173 void SkTextBlobBuilder::addChunk(const SkTextChunk* chunk) { | |
174 *fChunks.append() = chunk; | |
175 } | |
176 | |
177 | |
OLD | NEW |