Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(875)

Side by Side Diff: src/gpu/GrBitmapTextContext.cpp

Issue 141863005: Add standalone drawText for GrTextContext. (Closed) Base URL: https://skia.googlesource.com/skia.git@issue2018-factory
Patch Set: Remove SkDevice* from TextContext. Fix up some SK_OVERRIDEs. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 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 7
8 #include "GrBitmapTextContext.h" 8 #include "GrBitmapTextContext.h"
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrDrawTarget.h" 10 #include "GrDrawTarget.h"
11 #include "GrFontScaler.h" 11 #include "GrFontScaler.h"
12 #include "GrIndexBuffer.h" 12 #include "GrIndexBuffer.h"
13 #include "GrTextStrike.h" 13 #include "GrTextStrike.h"
14 #include "GrTextStrike_impl.h" 14 #include "GrTextStrike_impl.h"
15 #include "SkColorPriv.h" 15 #include "SkColorPriv.h"
16 #include "SkPath.h" 16 #include "SkPath.h"
17 #include "SkRTConf.h" 17 #include "SkRTConf.h"
18 #include "SkStrokeRec.h" 18 #include "SkStrokeRec.h"
19 #include "effects/GrCustomCoordsTextureEffect.h" 19 #include "effects/GrCustomCoordsTextureEffect.h"
20 20
21 #include "SkAutoKern.h"
22 #include "SkGlyphCache.h"
23 #include "SkGpuDevice.h"
24 #include "SkGr.h"
25
21 static const int kGlyphCoordsAttributeIndex = 1; 26 static const int kGlyphCoordsAttributeIndex = 1;
22 27
23 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, 28 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
24 "Dump the contents of the font cache before every purge."); 29 "Dump the contents of the font cache before every purge.");
25 30
26 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& pain t, 31 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
27 const SkPaint& skPaint) : 32 const GrPaint& grPaint,
28 GrTextContext(context, paint, skPaint) { 33 const SkPaint& skPaint,
29 fAutoMatrix.setIdentity(fContext, &fPaint); 34 const SkDeviceProperties* properties)
30 35 : GrTextContext(context, grPaint, skPaint , properties) {
31 fStrike = NULL; 36 fStrike = NULL;
32 37
33 fCurrTexture = NULL; 38 fCurrTexture = NULL;
34 fCurrVertex = 0; 39 fCurrVertex = 0;
35 40
36 fVertices = NULL; 41 fVertices = NULL;
37 fMaxVertices = 0; 42 fMaxVertices = 0;
38 } 43 }
39 44
40 GrBitmapTextContext::~GrBitmapTextContext() { 45 GrBitmapTextContext::~GrBitmapTextContext() {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 4, 6); 105 4, 6);
101 106
102 fDrawTarget->resetVertexSource(); 107 fDrawTarget->resetVertexSource();
103 fVertices = NULL; 108 fVertices = NULL;
104 fMaxVertices = 0; 109 fMaxVertices = 0;
105 fCurrVertex = 0; 110 fCurrVertex = 0;
106 SkSafeSetNull(fCurrTexture); 111 SkSafeSetNull(fCurrTexture);
107 } 112 }
108 } 113 }
109 114
115 void GrBitmapTextContext::drawText(const char text[], size_t byteLength,
116 SkScalar x, SkScalar y) {
117 SkASSERT(byteLength == 0 || text != NULL);
118
119 // nothing to draw
120 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
121 return;
122 }
123
124 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
125
126 SkAutoGlyphCache autoCache(fSkPaint, fDeviceProperties, &fContext->getMat rix());
127 SkGlyphCache* cache = autoCache.getCache();
128 GrFontScaler* fontScaler = GetGrFontScaler(cache);
129
130 // transform our starting point
131 {
132 SkPoint loc;
133 fContext->getMatrix().mapXY(x, y, &loc);
134 x = loc.fX;
135 y = loc.fY;
136 }
137
138 // need to measure first
139 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
140 SkVector stop;
141
142 MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
143
144 SkScalar stopX = stop.fX;
145 SkScalar stopY = stop.fY;
146
147 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
148 stopX = SkScalarHalf(stopX);
149 stopY = SkScalarHalf(stopY);
150 }
151 x -= stopX;
152 y -= stopY;
153 }
154
155 const char* stop = text + byteLength;
156
157 SkAutoKern autokern;
158
159 SkFixed fxMask = ~0;
160 SkFixed fyMask = ~0;
161 SkFixed halfSampleX, halfSampleY;
162 if (cache->isSubpixel()) {
163 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
164 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getM atrix());
165 if (kX_SkAxisAlignment == baseline) {
166 fyMask = 0;
167 halfSampleY = SK_FixedHalf;
168 } else if (kY_SkAxisAlignment == baseline) {
169 fxMask = 0;
170 halfSampleX = SK_FixedHalf;
171 }
172 } else {
173 halfSampleX = halfSampleY = SK_FixedHalf;
174 }
175
176 SkFixed fx = SkScalarToFixed(x) + halfSampleX;
177 SkFixed fy = SkScalarToFixed(y) + halfSampleY;
178
179 GrContext::AutoMatrix autoMatrix;
180 autoMatrix.setIdentity(fContext, &fPaint);
181
182 while (text < stop) {
183 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy Mask);
184
185 fx += autokern.adjust(glyph);
186
187 if (glyph.fWidth) {
188 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
189 glyph.getSubXFixed(),
190 glyph.getSubYFixed()),
191 SkFixedFloorToFixed(fx),
192 SkFixedFloorToFixed(fy),
193 fontScaler);
194 }
195
196 fx += glyph.fAdvanceX;
197 fy += glyph.fAdvanceY;
198 }
199 }
200
201 ///////////////////////////////////////////////////////////////////////////////
202 // Copied from SkDraw
203
204 // last parameter is interpreted as SkFixed [x, y]
205 // return the fixed position, which may be rounded or not by the caller
206 // e.g. subpixel doesn't round
207 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
208
209 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* ds t) {
210 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
211 }
212
213 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
214 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
215 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
216 }
217
218 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* d st) {
219 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
220 SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
221 }
222
223 static AlignProc pick_align_proc(SkPaint::Align align) {
224 static const AlignProc gProcs[] = {
225 leftAlignProc, centerAlignProc, rightAlignProc
226 };
227
228 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
229
230 return gProcs[align];
231 }
232
233 typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
234
235 static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoi nt* dst) {
236 dst->set(loc.fX, loc.fY);
237 }
238
239 static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkP oint* dst) {
240 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
241 loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
242 }
243
244 static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPo int* dst) {
245 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
246 loc.fY - SkFixedToScalar(glyph.fAdvanceY));
247 }
248
249 static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
250 static const AlignProc_scalar gProcs[] = {
251 leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
252 };
253
254 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
255
256 return gProcs[align];
257 }
258
259 class BitmapTextMapState {
260 public:
261 mutable SkPoint fLoc;
262
263 BitmapTextMapState(const SkMatrix& matrix, SkScalar y)
264 : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
265
266 typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]);
267
268 Proc pickProc(int scalarsPerPosition);
269
270 private:
271 const SkMatrix& fMatrix;
272 SkMatrix::MapXYProc fProc;
273 SkScalar fY; // ignored by MapXYProc
274 // these are only used by Only... procs
275 SkScalar fScaleX, fTransX, fTransformedY;
276
277 static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[]) {
278 state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
279 }
280
281 static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[]) {
282 state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
283 }
284
285 static void MapOnlyScaleXProc(const BitmapTextMapState& state,
286 const SkScalar pos[]) {
287 state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
288 state.fTransformedY);
289 }
290
291 static void MapOnlyTransXProc(const BitmapTextMapState& state,
292 const SkScalar pos[]) {
293 state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
294 }
295 };
296
297 BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) {
298 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
299
300 if (1 == scalarsPerPosition) {
301 unsigned mtype = fMatrix.getType();
302 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
303 return MapXProc;
304 } else {
305 fScaleX = fMatrix.getScaleX();
306 fTransX = fMatrix.getTranslateX();
307 fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
308 fMatrix.getTranslateY();
309 return (mtype & SkMatrix::kScale_Mask) ?
310 MapOnlyScaleXProc : MapOnlyTransXProc;
311 }
312 } else {
313 return MapXYProc;
314 }
315 }
316
317 ///////////////////////////////////////////////////////////////////////////////
318
319 void GrBitmapTextContext::drawPosText(const char text[], size_t byteLength,
320 const SkScalar pos[], SkScalar constY,
321 int scalarsPerPosition) {
322 SkASSERT(byteLength == 0 || text != NULL);
323 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
324
325 // nothing to draw
326 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
327 return;
328 }
329
330 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
331
332 SkAutoGlyphCache autoCache(fSkPaint, fDeviceProperties, &fContext->getMat rix());
333 SkGlyphCache* cache = autoCache.getCache();
334 GrFontScaler* fontScaler = GetGrFontScaler(cache);
335
336 // store original matrix before we reset, so we can use it to transform posi tions
337 SkMatrix ctm = fContext->getMatrix();
338 GrContext::AutoMatrix autoMatrix;
339 autoMatrix.setIdentity(fContext, &fPaint);
340
341 const char* stop = text + byteLength;
342 AlignProc alignProc = pick_align_proc(fSkPaint.getTextAlign());
343 BitmapTextMapState tms(ctm, constY);
344 BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
345 SkFixed halfSampleX = 0, halfSampleY = 0;
346
347 if (cache->isSubpixel()) {
348 // maybe we should skip the rounding if linearText is set
349 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
350
351 SkFixed fxMask = ~0;
352 SkFixed fyMask = ~0;
353 if (kX_SkAxisAlignment == baseline) {
354 fyMask = 0;
355 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
356 halfSampleY = SK_FixedHalf;
357 #endif
358 } else if (kY_SkAxisAlignment == baseline) {
359 fxMask = 0;
360 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
361 halfSampleX = SK_FixedHalf;
362 #endif
363 }
364
365 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
366 while (text < stop) {
367 tmsProc(tms, pos);
368 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX;
369 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY;
370
371 const SkGlyph& glyph = glyphCacheProc(cache, &text,
372 fx & fxMask, fy & fyMask);
373
374 if (glyph.fWidth) {
375 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
376 glyph.getSubXFixed(),
377 glyph.getSubYFixed()),
378 SkFixedFloorToFixed(fx),
379 SkFixedFloorToFixed(fy),
380 fontScaler);
381 }
382 pos += scalarsPerPosition;
383 }
384 } else {
385 while (text < stop) {
386 const char* currentText = text;
387 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
388
389 if (metricGlyph.fWidth) {
390 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
391 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
392
393 tmsProc(tms, pos);
394 SkIPoint fixedLoc;
395 alignProc(tms.fLoc, metricGlyph, &fixedLoc);
396
397 SkFixed fx = fixedLoc.fX + halfSampleX;
398 SkFixed fy = fixedLoc.fY + halfSampleY;
399
400 // have to call again, now that we've been "aligned"
401 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
402 fx & fxMask, fy & fyMa sk);
403 // the assumption is that the metrics haven't changed
404 SkASSERT(prevAdvX == glyph.fAdvanceX);
405 SkASSERT(prevAdvY == glyph.fAdvanceY);
406 SkASSERT(glyph.fWidth);
407
408 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
409 glyph.getSubXFixed(),
410 glyph.getSubYFixed()),
411 SkFixedFloorToFixed(fx),
412 SkFixedFloorToFixed(fy),
413 fontScaler);
414 }
415 pos += scalarsPerPosition;
416 }
417 }
418 } else { // not subpixel
419
420 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
421 while (text < stop) {
422 // the last 2 parameters are ignored
423 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
424
425 if (glyph.fWidth) {
426 tmsProc(tms, pos);
427
428 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; // halfSampleX;
429 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; // halfSampleY;
430 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
431 glyph.getSubXFixed(),
432 glyph.getSubYFixed()),
433 SkFixedFloorToFixed(fx),
434 SkFixedFloorToFixed(fy),
435 fontScaler);
436 }
437 pos += scalarsPerPosition;
438 }
439 } else {
440 while (text < stop) {
441 // the last 2 parameters are ignored
442 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
443
444 if (glyph.fWidth) {
445 tmsProc(tms, pos);
446
447 SkIPoint fixedLoc;
448 alignProc(tms.fLoc, glyph, &fixedLoc);
449
450 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
451 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
452 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
453 glyph.getSubXFixed(),
454 glyph.getSubYFixed()),
455 SkFixedFloorToFixed(fx),
456 SkFixedFloorToFixed(fy),
457 fontScaler);
458 }
459 pos += scalarsPerPosition;
460 }
461 }
462 }
463 }
464
110 namespace { 465 namespace {
111 466
112 // position + texture coord 467 // position + texture coord
113 extern const GrVertexAttrib gTextVertexAttribs[] = { 468 extern const GrVertexAttrib gTextVertexAttribs[] = {
114 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 469 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
115 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 470 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
116 }; 471 };
117 472
118 }; 473 };
119 474
120 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, 475 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
121 GrFixed vx, GrFixed vy, 476 GrFixed vx, GrFixed vy,
122 GrFontScaler* scaler) { 477 GrFontScaler* scaler) {
123 if (NULL == fDrawTarget) { 478 if (NULL == fDrawTarget) {
124 return; 479 return;
125 } 480 }
481
126 if (NULL == fStrike) { 482 if (NULL == fStrike) {
127 #if SK_DISTANCEFIELD_FONTS 483 #if SK_DISTANCEFIELD_FONTS
128 fStrike = fContext->getFontCache()->getStrike(scaler, false); 484 fStrike = fContext->getFontCache()->getStrike(scaler, false);
129 #else 485 #else
130 fStrike = fContext->getFontCache()->getStrike(scaler); 486 fStrike = fContext->getFontCache()->getStrike(scaler);
131 #endif 487 #endif
132 } 488 }
133 489
134 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); 490 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
135 if (NULL == glyph || glyph->fBounds.isEmpty()) { 491 if (NULL == glyph || glyph->fBounds.isEmpty()) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 SkFixedToFloat(vx + width), 616 SkFixedToFloat(vx + width),
261 SkFixedToFloat(vy + height), 617 SkFixedToFloat(vy + height),
262 2 * sizeof(SkPoint)); 618 2 * sizeof(SkPoint));
263 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed X(tx)), 619 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed X(tx)),
264 SkFixedToFloat(texture->normalizeFixed Y(ty)), 620 SkFixedToFloat(texture->normalizeFixed Y(ty)),
265 SkFixedToFloat(texture->normalizeFixed X(tx + width)), 621 SkFixedToFloat(texture->normalizeFixed X(tx + width)),
266 SkFixedToFloat(texture->normalizeFixed Y(ty + height)), 622 SkFixedToFloat(texture->normalizeFixed Y(ty + height)),
267 2 * sizeof(SkPoint)); 623 2 * sizeof(SkPoint));
268 fCurrVertex += 4; 624 fCurrVertex += 4;
269 } 625 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698