OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
8 | 8 |
9 #include "GrDrawContext.h" | 9 #include "GrDrawContext.h" |
10 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include "SkGpuDevice.h" | 27 #include "SkGpuDevice.h" |
28 #include "SkGrPriv.h" | 28 #include "SkGrPriv.h" |
29 #include "SkPath.h" | 29 #include "SkPath.h" |
30 #include "SkRTConf.h" | 30 #include "SkRTConf.h" |
31 #include "SkStrokeRec.h" | 31 #include "SkStrokeRec.h" |
32 #include "SkTextBlob.h" | 32 #include "SkTextBlob.h" |
33 #include "SkTextMapStateProc.h" | 33 #include "SkTextMapStateProc.h" |
34 | 34 |
35 #include "batches/GrAtlasTextBatch.h" | 35 #include "batches/GrAtlasTextBatch.h" |
36 | 36 |
37 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps&
surfaceProps) | 37 GrAtlasTextContext::GrAtlasTextContext(GrContext* context) |
38 : INHERITED(context, surfaceProps) | 38 : INHERITED(context) |
39 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { | 39 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { |
40 // We overallocate vertices in our textblobs based on the assumption that A8
has the greatest | 40 // We overallocate vertices in our textblobs based on the assumption that A8
has the greatest |
41 // vertexStride | 41 // vertexStride |
42 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTex
tVASize && | 42 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTex
tVASize && |
43 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextV
ASize, | 43 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextV
ASize, |
44 "vertex_attribute_changed"); | 44 "vertex_attribute_changed"); |
45 fCache = context->getTextBlobCache(); | 45 fCache = context->getTextBlobCache(); |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context, | 49 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context) { |
50 const SkSurfaceProps& surfaceProp
s) { | 50 return new GrAtlasTextContext(context); |
51 return new GrAtlasTextContext(context, surfaceProps); | |
52 } | 51 } |
53 | 52 |
54 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, const SkMatrix& viewMat
rix) { | 53 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, |
55 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfacePro
ps, | 54 const SkMatrix& viewMatrix, |
| 55 const SkSurfaceProps& props) { |
| 56 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, |
56 *fContext->caps()->shaderCaps())
|| | 57 *fContext->caps()->shaderCaps())
|| |
57 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); | 58 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); |
58 } | 59 } |
59 | 60 |
60 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd
) { | 61 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd
) { |
61 GrColor canonicalColor = paint.computeLuminanceColor(); | 62 GrColor canonicalColor = paint.computeLuminanceColor(); |
62 if (lcd) { | 63 if (lcd) { |
63 // This is the correct computation, but there are tons of cases where LC
D can be overridden. | 64 // This is the correct computation, but there are tons of cases where LC
D can be overridden. |
64 // For now we just regenerate if any run in a textblob has LCD. | 65 // For now we just regenerate if any run in a textblob has LCD. |
65 // TODO figure out where all of these overrides are and see if we can in
corporate that logic | 66 // TODO figure out where all of these overrides are and see if we can in
corporate that logic |
(...skipping 20 matching lines...) Expand all Loading... |
86 for (; !it.done(); it.next()) { | 87 for (; !it.done(); it.next()) { |
87 if (it.isLCD()) { | 88 if (it.isLCD()) { |
88 return true; | 89 return true; |
89 } | 90 } |
90 } | 91 } |
91 return false; | 92 return false; |
92 } | 93 } |
93 | 94 |
94 void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc, | 95 void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc, |
95 const GrClip& clip, const SkPaint& skPaint
, | 96 const GrClip& clip, const SkPaint& skPaint
, |
96 const SkMatrix& viewMatrix, const SkTextBl
ob* blob, | 97 const SkMatrix& viewMatrix, |
| 98 const SkSurfaceProps& props, const SkTextB
lob* blob, |
97 SkScalar x, SkScalar y, | 99 SkScalar x, SkScalar y, |
98 SkDrawFilter* drawFilter, const SkIRect& c
lipBounds) { | 100 SkDrawFilter* drawFilter, const SkIRect& c
lipBounds) { |
99 // If we have been abandoned, then don't draw | 101 // If we have been abandoned, then don't draw |
100 if (fContext->abandoned()) { | 102 if (fContext->abandoned()) { |
101 return; | 103 return; |
102 } | 104 } |
103 | 105 |
104 SkAutoTUnref<GrAtlasTextBlob> cacheBlob; | 106 SkAutoTUnref<GrAtlasTextBlob> cacheBlob; |
105 SkMaskFilter::BlurRec blurRec; | 107 SkMaskFilter::BlurRec blurRec; |
106 GrAtlasTextBlob::Key key; | 108 GrAtlasTextBlob::Key key; |
107 // It might be worth caching these things, but its not clear at this time | 109 // It might be worth caching these things, but its not clear at this time |
108 // TODO for animated mask filters, this will fill up our cache. We need a s
afeguard here | 110 // TODO for animated mask filters, this will fill up our cache. We need a s
afeguard here |
109 const SkMaskFilter* mf = skPaint.getMaskFilter(); | 111 const SkMaskFilter* mf = skPaint.getMaskFilter(); |
110 bool canCache = !(skPaint.getPathEffect() || | 112 bool canCache = !(skPaint.getPathEffect() || |
111 (mf && !mf->asABlur(&blurRec)) || | 113 (mf && !mf->asABlur(&blurRec)) || |
112 drawFilter); | 114 drawFilter); |
113 | 115 |
114 if (canCache) { | 116 if (canCache) { |
115 bool hasLCD = HasLCD(blob); | 117 bool hasLCD = HasLCD(blob); |
116 | 118 |
117 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry | 119 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry |
118 SkPixelGeometry pixelGeometry = hasLCD ? fSurfaceProps.pixelGeometry() : | 120 SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : |
119 kUnknown_SkPixelGeometry; | 121 kUnknown_SkPixelGeometry; |
120 | 122 |
121 // TODO we want to figure out a way to be able to use the canonical colo
r on LCD text, | 123 // TODO we want to figure out a way to be able to use the canonical colo
r on LCD text, |
122 // see the note on ComputeCanonicalColor above. We pick a dummy value f
or LCD text to | 124 // see the note on ComputeCanonicalColor above. We pick a dummy value f
or LCD text to |
123 // ensure we always match the same key | 125 // ensure we always match the same key |
124 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : | 126 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : |
125 ComputeCanonicalColor(skPaint, hasLCD)
; | 127 ComputeCanonicalColor(skPaint, hasLCD)
; |
126 | 128 |
127 key.fPixelGeometry = pixelGeometry; | 129 key.fPixelGeometry = pixelGeometry; |
128 key.fUniqueID = blob->uniqueID(); | 130 key.fUniqueID = blob->uniqueID(); |
(...skipping 14 matching lines...) Expand all Loading... |
143 } | 145 } |
144 | 146 |
145 if (cacheBlob) { | 147 if (cacheBlob) { |
146 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColo
r(), blurRec, | 148 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColo
r(), blurRec, |
147 viewMatrix, x, y)) { | 149 viewMatrix, x, y)) { |
148 // We have to remake the blob because changes may invalidate our mas
ks. | 150 // We have to remake the blob because changes may invalidate our mas
ks. |
149 // TODO we could probably get away reuse most of the time if the poi
nter is unique, | 151 // TODO we could probably get away reuse most of the time if the poi
nter is unique, |
150 // but we'd have to clear the subrun information | 152 // but we'd have to clear the subrun information |
151 fCache->remove(cacheBlob); | 153 fCache->remove(cacheBlob); |
152 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint))); | 154 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint))); |
153 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, | 155 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, props, |
154 blob, x, y, drawFilter); | 156 blob, x, y, drawFilter); |
155 } else { | 157 } else { |
156 fCache->makeMRU(cacheBlob); | 158 fCache->makeMRU(cacheBlob); |
157 | 159 |
158 if (CACHE_SANITY_CHECK) { | 160 if (CACHE_SANITY_CHECK) { |
159 int glyphCount = 0; | 161 int glyphCount = 0; |
160 int runCount = 0; | 162 int runCount = 0; |
161 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); | 163 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); |
162 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp
hCount, runCount)); | 164 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp
hCount, runCount)); |
163 sanityBlob->setupKey(key, blurRec, skPaint); | 165 sanityBlob->setupKey(key, blurRec, skPaint); |
164 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor()
, viewMatrix, | 166 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor()
, viewMatrix, props, |
165 blob, x, y, drawFilter); | 167 blob, x, y, drawFilter); |
166 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); | 168 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); |
167 } | 169 } |
168 } | 170 } |
169 } else { | 171 } else { |
170 if (canCache) { | 172 if (canCache) { |
171 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint))); | 173 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint))); |
172 } else { | 174 } else { |
173 cacheBlob.reset(fCache->createBlob(blob)); | 175 cacheBlob.reset(fCache->createBlob(blob)); |
174 } | 176 } |
175 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, | 177 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, props, |
176 blob, x, y, drawFilter); | 178 blob, x, y, drawFilter); |
177 } | 179 } |
178 | 180 |
179 cacheBlob->flushCached(fContext, dc, blob, fSurfaceProps, fDistanceAdjustTab
le, skPaint, | 181 cacheBlob->flushCached(fContext, dc, blob, props, fDistanceAdjustTable, skPa
int, |
180 grPaint, drawFilter, clip, viewMatrix, clipBounds, x,
y, transX, transY); | 182 grPaint, drawFilter, clip, viewMatrix, clipBounds, x,
y, transX, transY); |
181 } | 183 } |
182 | 184 |
183 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, | 185 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, |
184 const SkPaint& skPaint, GrColor colo
r, | 186 const SkPaint& skPaint, GrColor colo
r, |
185 const SkMatrix& viewMatrix, | 187 const SkMatrix& viewMatrix, |
| 188 const SkSurfaceProps& props, |
186 const SkTextBlob* blob, SkScalar x,
SkScalar y, | 189 const SkTextBlob* blob, SkScalar x,
SkScalar y, |
187 SkDrawFilter* drawFilter) { | 190 SkDrawFilter* drawFilter) { |
188 cacheBlob->initReusableBlob(color, viewMatrix, x, y); | 191 cacheBlob->initReusableBlob(color, viewMatrix, x, y); |
189 | 192 |
190 // Regenerate textblob | 193 // Regenerate textblob |
191 SkPaint runPaint = skPaint; | 194 SkPaint runPaint = skPaint; |
192 SkTextBlobRunIterator it(blob); | 195 SkTextBlobRunIterator it(blob); |
193 for (int run = 0; !it.done(); it.next(), run++) { | 196 for (int run = 0; !it.done(); it.next(), run++) { |
194 int glyphCount = it.glyphCount(); | 197 int glyphCount = it.glyphCount(); |
195 size_t textLen = glyphCount * sizeof(uint16_t); | 198 size_t textLen = glyphCount * sizeof(uint16_t); |
196 const SkPoint& offset = it.offset(); | 199 const SkPoint& offset = it.offset(); |
197 // applyFontToPaint() always overwrites the exact same attributes, | 200 // applyFontToPaint() always overwrites the exact same attributes, |
198 // so it is safe to not re-seed the paint for this reason. | 201 // so it is safe to not re-seed the paint for this reason. |
199 it.applyFontToPaint(&runPaint); | 202 it.applyFontToPaint(&runPaint); |
200 | 203 |
201 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { | 204 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { |
202 // A false return from filter() means we should abort the current dr
aw. | 205 // A false return from filter() means we should abort the current dr
aw. |
203 runPaint = skPaint; | 206 runPaint = skPaint; |
204 continue; | 207 continue; |
205 } | 208 } |
206 | 209 |
207 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint)); | 210 runPaint.setFlags(FilterTextFlags(props, runPaint)); |
208 | 211 |
209 cacheBlob->push_back_run(run); | 212 cacheBlob->push_back_run(run); |
210 | 213 |
211 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, fSurfaceP
rops, | 214 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, |
212 *fContext->caps()->shaderCaps()
)) { | 215 *fContext->caps()->shaderCaps()
)) { |
213 switch (it.positioning()) { | 216 switch (it.positioning()) { |
214 case SkTextBlob::kDefault_Positioning: { | 217 case SkTextBlob::kDefault_Positioning: { |
215 GrTextUtils::DrawDFText(cacheBlob, run, fContext->getBatchFo
ntCache(), | 218 GrTextUtils::DrawDFText(cacheBlob, run, fContext->getBatchFo
ntCache(), |
216 fSurfaceProps, runPaint, color, view
Matrix, | 219 props, runPaint, color, viewMatrix, |
217 (const char *)it.glyphs(), textLen, | 220 (const char *)it.glyphs(), textLen, |
218 x + offset.x(), y + offset.y()); | 221 x + offset.x(), y + offset.y()); |
219 break; | 222 break; |
220 } | 223 } |
221 case SkTextBlob::kHorizontal_Positioning: { | 224 case SkTextBlob::kHorizontal_Positioning: { |
222 SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); | 225 SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); |
223 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatc
hFontCache(), | 226 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatc
hFontCache(), |
224 fSurfaceProps, runPaint, color, v
iewMatrix, | 227 props, runPaint, color, viewMatri
x, |
225 (const char*)it.glyphs(), textLen
, it.pos(), | 228 (const char*)it.glyphs(), textLen
, it.pos(), |
226 1, dfOffset); | 229 1, dfOffset); |
227 break; | 230 break; |
228 } | 231 } |
229 case SkTextBlob::kFull_Positioning: { | 232 case SkTextBlob::kFull_Positioning: { |
230 SkPoint dfOffset = SkPoint::Make(x, y); | 233 SkPoint dfOffset = SkPoint::Make(x, y); |
231 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBat
chFontCache(), | 234 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBat
chFontCache(), |
232 fSurfaceProps, runPaint, color, v
iewMatrix, | 235 props, runPaint, color, viewMatri
x, |
233 (const char*)it.glyphs(), textLen
, it.pos(), | 236 (const char*)it.glyphs(), textLen
, it.pos(), |
234 2, dfOffset); | 237 2, dfOffset); |
235 break; | 238 break; |
236 } | 239 } |
237 } | 240 } |
238 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { | 241 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { |
239 cacheBlob->setRunDrawAsPaths(run); | 242 cacheBlob->setRunDrawAsPaths(run); |
240 } else { | 243 } else { |
241 switch (it.positioning()) { | 244 switch (it.positioning()) { |
242 case SkTextBlob::kDefault_Positioning: | 245 case SkTextBlob::kDefault_Positioning: |
243 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchF
ontCache(), | 246 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchF
ontCache(), |
244 fSurfaceProps, runPaint, color, vie
wMatrix, | 247 props, runPaint, color, viewMatrix, |
245 (const char *)it.glyphs(), textLen, | 248 (const char *)it.glyphs(), textLen, |
246 x + offset.x(), y + offset.y()); | 249 x + offset.x(), y + offset.y()); |
247 break; | 250 break; |
248 case SkTextBlob::kHorizontal_Positioning: | 251 case SkTextBlob::kHorizontal_Positioning: |
249 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat
chFontCache(), | 252 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat
chFontCache(), |
250 fSurfaceProps, runPaint, color,
viewMatrix, | 253 props, runPaint, color, viewMatr
ix, |
251 (const char*)it.glyphs(), textLe
n, it.pos(), 1, | 254 (const char*)it.glyphs(), textLe
n, it.pos(), 1, |
252 SkPoint::Make(x, y + offset.y())
); | 255 SkPoint::Make(x, y + offset.y())
); |
253 break; | 256 break; |
254 case SkTextBlob::kFull_Positioning: | 257 case SkTextBlob::kFull_Positioning: |
255 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat
chFontCache(), | 258 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat
chFontCache(), |
256 fSurfaceProps, runPaint, color,
viewMatrix, | 259 props, runPaint, color, viewMatr
ix, |
257 (const char*)it.glyphs(), textLe
n, it.pos(), 2, | 260 (const char*)it.glyphs(), textLe
n, it.pos(), 2, |
258 SkPoint::Make(x, y)); | 261 SkPoint::Make(x, y)); |
259 break; | 262 break; |
260 } | 263 } |
261 } | 264 } |
262 | 265 |
263 if (drawFilter) { | 266 if (drawFilter) { |
264 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. | 267 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. |
265 runPaint = skPaint; | 268 runPaint = skPaint; |
266 } | 269 } |
267 } | 270 } |
268 } | 271 } |
269 | 272 |
270 inline GrAtlasTextBlob* | 273 inline GrAtlasTextBlob* |
271 GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, const SkPaint& skPa
int, | 274 GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, |
| 275 const SkPaint& skPaint, |
272 const SkMatrix& viewMatrix, | 276 const SkMatrix& viewMatrix, |
| 277 const SkSurfaceProps& props, |
273 const char text[], size_t byteLength, | 278 const char text[], size_t byteLength, |
274 SkScalar x, SkScalar y) { | 279 SkScalar x, SkScalar y) { |
275 int glyphCount = skPaint.countText(text, byteLength); | 280 int glyphCount = skPaint.countText(text, byteLength); |
276 | 281 |
277 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); | 282 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); |
278 blob->initThrowawayBlob(viewMatrix, x, y); | 283 blob->initThrowawayBlob(viewMatrix, x, y); |
279 | 284 |
280 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps, | 285 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, |
281 *fContext->caps()->shaderCaps())) { | 286 *fContext->caps()->shaderCaps())) { |
282 GrTextUtils::DrawDFText(blob, 0, fContext->getBatchFontCache(), fSurface
Props, | 287 GrTextUtils::DrawDFText(blob, 0, fContext->getBatchFontCache(), props, |
283 skPaint, paint.getColor(), viewMatrix, text, | 288 skPaint, paint.getColor(), viewMatrix, text, |
284 byteLength, x, y); | 289 byteLength, x, y); |
285 } else { | 290 } else { |
286 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), fSurfac
eProps, skPaint, | 291 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), props,
skPaint, |
287 paint.getColor(), viewMatrix, text, byteLength,
x, y); | 292 paint.getColor(), viewMatrix, text, byteLength,
x, y); |
288 } | 293 } |
289 return blob; | 294 return blob; |
290 } | 295 } |
291 | 296 |
292 inline GrAtlasTextBlob* | 297 inline GrAtlasTextBlob* |
293 GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& s
kPaint, | 298 GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& s
kPaint, |
294 const SkMatrix& viewMatrix, | 299 const SkMatrix& viewMatrix, const SkSu
rfaceProps& props, |
295 const char text[], size_t byteLength, | 300 const char text[], size_t byteLength, |
296 const SkScalar pos[], int scalarsPerPo
sition, | 301 const SkScalar pos[], int scalarsPerPo
sition, |
297 const SkPoint& offset) { | 302 const SkPoint& offset) { |
298 int glyphCount = skPaint.countText(text, byteLength); | 303 int glyphCount = skPaint.countText(text, byteLength); |
299 | 304 |
300 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); | 305 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); |
301 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); | 306 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); |
302 | 307 |
303 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps, | 308 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, |
304 *fContext->caps()->shaderCaps())) { | 309 *fContext->caps()->shaderCaps())) { |
305 GrTextUtils::DrawDFPosText(blob, 0, fContext->getBatchFontCache(), fSurf
aceProps, | 310 GrTextUtils::DrawDFPosText(blob, 0, fContext->getBatchFontCache(), props
, |
306 skPaint, paint.getColor(), viewMatrix, text, | 311 skPaint, paint.getColor(), viewMatrix, text, |
307 byteLength, pos, scalarsPerPosition, offset); | 312 byteLength, pos, scalarsPerPosition, offset); |
308 } else { | 313 } else { |
309 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), fSur
faceProps, skPaint, | 314 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), prop
s, skPaint, |
310 paint.getColor(), viewMatrix, text, | 315 paint.getColor(), viewMatrix, text, |
311 byteLength, pos, scalarsPerPosition, offset)
; | 316 byteLength, pos, scalarsPerPosition, offset)
; |
312 } | 317 } |
313 return blob; | 318 return blob; |
314 } | 319 } |
315 | 320 |
316 void GrAtlasTextContext::drawText(GrDrawContext* dc, | 321 void GrAtlasTextContext::drawText(GrDrawContext* dc, |
317 const GrClip& clip, | 322 const GrClip& clip, |
318 const GrPaint& paint, const SkPaint& skPaint, | 323 const GrPaint& paint, const SkPaint& skPaint, |
319 const SkMatrix& viewMatrix, | 324 const SkMatrix& viewMatrix, |
| 325 const SkSurfaceProps& props, |
320 const char text[], size_t byteLength, | 326 const char text[], size_t byteLength, |
321 SkScalar x, SkScalar y, const SkIRect& regionC
lipBounds) { | 327 SkScalar x, SkScalar y, const SkIRect& regionC
lipBounds) { |
322 if (fContext->abandoned()) { | 328 if (fContext->abandoned()) { |
323 return; | 329 return; |
324 } else if (this->canDraw(skPaint, viewMatrix)) { | 330 } else if (this->canDraw(skPaint, viewMatrix, props)) { |
325 SkAutoTUnref<GrAtlasTextBlob> blob( | 331 SkAutoTUnref<GrAtlasTextBlob> blob( |
326 this->createDrawTextBlob(paint, skPaint, viewMatrix, text, byteLengt
h, x, y)); | 332 this->createDrawTextBlob(paint, skPaint, viewMatrix, props, text, by
teLength, x, y)); |
327 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable,
skPaint, paint, | 333 blob->flushThrowaway(fContext, dc, props, fDistanceAdjustTable, skPaint,
paint, |
328 clip, regionClipBounds); | 334 clip, regionClipBounds); |
329 return; | 335 return; |
330 } | 336 } |
331 | 337 |
332 // fall back to drawing as a path | 338 // fall back to drawing as a path |
333 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b
yteLength, x, y, | 339 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b
yteLength, x, y, |
334 regionClipBounds); | 340 regionClipBounds); |
335 } | 341 } |
336 | 342 |
337 void GrAtlasTextContext::drawPosText(GrDrawContext* dc, | 343 void GrAtlasTextContext::drawPosText(GrDrawContext* dc, |
338 const GrClip& clip, | 344 const GrClip& clip, |
339 const GrPaint& paint, const SkPaint& skPain
t, | 345 const GrPaint& paint, const SkPaint& skPain
t, |
340 const SkMatrix& viewMatrix, | 346 const SkMatrix& viewMatrix, |
| 347 const SkSurfaceProps& props, |
341 const char text[], size_t byteLength, | 348 const char text[], size_t byteLength, |
342 const SkScalar pos[], int scalarsPerPositio
n, | 349 const SkScalar pos[], int scalarsPerPositio
n, |
343 const SkPoint& offset, const SkIRect& regio
nClipBounds) { | 350 const SkPoint& offset, const SkIRect& regio
nClipBounds) { |
344 if (fContext->abandoned()) { | 351 if (fContext->abandoned()) { |
345 return; | 352 return; |
346 } else if (this->canDraw(skPaint, viewMatrix)) { | 353 } else if (this->canDraw(skPaint, viewMatrix, props)) { |
347 SkAutoTUnref<GrAtlasTextBlob> blob( | 354 SkAutoTUnref<GrAtlasTextBlob> blob( |
348 this->createDrawPosTextBlob(paint, skPaint, viewMatrix, | 355 this->createDrawPosTextBlob(paint, skPaint, viewMatrix, props, |
349 text, byteLength, | 356 text, byteLength, |
350 pos, scalarsPerPosition, | 357 pos, scalarsPerPosition, |
351 offset)); | 358 offset)); |
352 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable,
skPaint, paint, | 359 blob->flushThrowaway(fContext, dc, props, fDistanceAdjustTable, skPaint,
paint, |
353 clip, regionClipBounds); | 360 clip, regionClipBounds); |
354 return; | 361 return; |
355 } | 362 } |
356 | 363 |
357 // fall back to drawing as a path | 364 // fall back to drawing as a path |
358 GrTextUtils::DrawPosTextAsPath(fContext, dc, fSurfaceProps, clip, skPaint, v
iewMatrix, text, | 365 GrTextUtils::DrawPosTextAsPath(fContext, dc, props, clip, skPaint, viewMatri
x, text, |
359 byteLength, pos, scalarsPerPosition, offset,
regionClipBounds); | 366 byteLength, pos, scalarsPerPosition, offset,
regionClipBounds); |
360 } | 367 } |
361 | 368 |
362 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 369 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
363 | 370 |
364 #ifdef GR_TEST_UTILS | 371 #ifdef GR_TEST_UTILS |
365 | 372 |
366 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { | 373 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { |
367 static uint32_t gContextID = SK_InvalidGenID; | 374 static uint32_t gContextID = SK_InvalidGenID; |
368 static GrAtlasTextContext* gTextContext = nullptr; | 375 static GrAtlasTextContext* gTextContext = nullptr; |
369 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType
); | 376 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType
); |
370 | 377 |
371 if (context->uniqueID() != gContextID) { | 378 if (context->uniqueID() != gContextID) { |
372 gContextID = context->uniqueID(); | 379 gContextID = context->uniqueID(); |
373 delete gTextContext; | 380 delete gTextContext; |
374 | 381 |
375 // We don't yet test the fall back to paths in the GrTextContext base cl
ass. This is mostly | 382 // We don't yet test the fall back to paths in the GrTextContext base cl
ass. This is mostly |
376 // because we don't really want to have a gpu device here. | 383 // because we don't really want to have a gpu device here. |
377 // We enable distance fields by twiddling a knob on the paint | 384 // We enable distance fields by twiddling a knob on the paint |
378 gTextContext = GrAtlasTextContext::Create(context, gSurfaceProps); | 385 gTextContext = GrAtlasTextContext::Create(context); |
379 } | 386 } |
380 | 387 |
381 // Setup dummy SkPaint / GrPaint | 388 // Setup dummy SkPaint / GrPaint |
382 GrColor color = GrRandomColor(random); | 389 GrColor color = GrRandomColor(random); |
383 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); | 390 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); |
384 SkPaint skPaint; | 391 SkPaint skPaint; |
385 skPaint.setColor(color); | 392 skPaint.setColor(color); |
386 skPaint.setLCDRenderText(random->nextBool()); | 393 skPaint.setLCDRenderText(random->nextBool()); |
387 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); | 394 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); |
388 skPaint.setSubpixelText(random->nextBool()); | 395 skPaint.setSubpixelText(random->nextBool()); |
389 | 396 |
390 GrPaint grPaint; | 397 GrPaint grPaint; |
391 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { | 398 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { |
392 SkFAIL("couldn't convert paint\n"); | 399 SkFAIL("couldn't convert paint\n"); |
393 } | 400 } |
394 | 401 |
395 const char* text = "The quick brown fox jumps over the lazy dog."; | 402 const char* text = "The quick brown fox jumps over the lazy dog."; |
396 int textLen = (int)strlen(text); | 403 int textLen = (int)strlen(text); |
397 | 404 |
398 // Setup clip | 405 // Setup clip |
399 GrClip clip; | 406 GrClip clip; |
400 | 407 |
401 // right now we don't handle textblobs, nor do we handle drawPosText. Since
we only | 408 // right now we don't handle textblobs, nor do we handle drawPosText. Since
we only |
402 // intend to test the batch with this unit test, that is okay. | 409 // intend to test the batch with this unit test, that is okay. |
403 SkAutoTUnref<GrAtlasTextBlob> blob( | 410 SkAutoTUnref<GrAtlasTextBlob> blob( |
404 gTextContext->createDrawTextBlob(grPaint, skPaint, viewMatrix, text, | 411 gTextContext->createDrawTextBlob(grPaint, skPaint, viewMatrix, gSurf
aceProps, text, |
405 static_cast<size_t>(textLen), 0, 0)
); | 412 static_cast<size_t>(textLen), 0, 0)
); |
406 | 413 |
407 // We'd like to be able to test this with random translations, but currently
the vertex | 414 // We'd like to be able to test this with random translations, but currently
the vertex |
408 // bounds and vertices will get out of sync | 415 // bounds and vertices will get out of sync |
409 SkScalar transX = 0.f;//SkIntToScalar(random->nextU()); | 416 SkScalar transX = 0.f;//SkIntToScalar(random->nextU()); |
410 SkScalar transY = 0.f;//SkIntToScalar(random->nextU()); | 417 SkScalar transY = 0.f;//SkIntToScalar(random->nextU()); |
411 return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint, | 418 return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint, |
412 gSurfaceProps, gTextContext->dfAdjustTable(), | 419 gSurfaceProps, gTextContext->dfAdjustTable(), |
413 context->getBatchFontCache()); | 420 context->getBatchFontCache()); |
414 } | 421 } |
415 | 422 |
416 #endif | 423 #endif |
OLD | NEW |