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

Side by Side Diff: src/gpu/text/GrAtlasTextContext.cpp

Issue 1521633002: Move distance field text positioning into GrTextUtils (Closed) Base URL: https://skia.googlesource.com/skia.git@cleanuptext15
Patch Set: tweaks Created 4 years, 11 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
« no previous file with comments | « src/gpu/text/GrAtlasTextContext.h ('k') | src/gpu/text/GrTextUtils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 namespace {
38 static const int kMinDFFontSize = 18;
39 static const int kSmallDFFontSize = 32;
40 static const int kSmallDFFontLimit = 32;
41 static const int kMediumDFFontSize = 72;
42 static const int kMediumDFFontLimit = 72;
43 static const int kLargeDFFontSize = 162;
44 #ifdef SK_BUILD_FOR_ANDROID
45 static const int kLargeDFFontLimit = 384;
46 #else
47 static const int kLargeDFFontLimit = 2 * kLargeDFFontSize;
48 #endif
49 };
50
51 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps& surfaceProps) 37 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps& surfaceProps)
52 : INHERITED(context, surfaceProps) 38 : INHERITED(context, surfaceProps)
53 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { 39 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) {
54 // 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
55 // vertexStride 41 // vertexStride
56 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTex tVASize && 42 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTex tVASize &&
57 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextV ASize, 43 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextV ASize,
58 "vertex_attribute_changed"); 44 "vertex_attribute_changed");
59 fCurrStrike = nullptr; 45 fCurrStrike = nullptr;
60 fCache = context->getTextBlobCache(); 46 fCache = context->getTextBlobCache();
61 } 47 }
62 48
63 49
64 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context, 50 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
65 const SkSurfaceProps& surfaceProp s) { 51 const SkSurfaceProps& surfaceProp s) {
66 return new GrAtlasTextContext(context, surfaceProps); 52 return new GrAtlasTextContext(context, surfaceProps);
67 } 53 }
68 54
69 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, const SkMatrix& viewMat rix) { 55 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, const SkMatrix& viewMat rix) {
70 return this->canDrawAsDistanceFields(skPaint, viewMatrix) || 56 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfacePro ps,
57 *fContext->caps()->shaderCaps()) ||
71 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); 58 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
72 } 59 }
73 60
74 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd ) { 61 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd ) {
75 GrColor canonicalColor = paint.computeLuminanceColor(); 62 GrColor canonicalColor = paint.computeLuminanceColor();
76 if (lcd) { 63 if (lcd) {
77 // 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.
78 // 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.
79 // 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
80 // at a higher level *OR* use sRGB 67 // at a higher level *OR* use sRGB
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBlob::kGrayTextV ASize)); 179 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBlob::kGrayTextV ASize));
193 } 180 }
194 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat rix, 181 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat rix,
195 blob, x, y, drawFilter); 182 blob, x, y, drawFilter);
196 } 183 }
197 184
198 cacheBlob->flushCached(fContext, dc, blob, fSurfaceProps, fDistanceAdjustTab le, skPaint, 185 cacheBlob->flushCached(fContext, dc, blob, fSurfaceProps, fDistanceAdjustTab le, skPaint,
199 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY); 186 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY);
200 } 187 }
201 188
202 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint,
203 const SkMatrix& viewMatr ix) {
204 // TODO: support perspective (need getMaxScale replacement)
205 if (viewMatrix.hasPerspective()) {
206 return false;
207 }
208
209 SkScalar maxScale = viewMatrix.getMaxScale();
210 SkScalar scaledTextSize = maxScale*skPaint.getTextSize();
211 // Hinted text looks far better at small resolutions
212 // Scaling up beyond 2x yields undesireable artifacts
213 if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) {
214 return false;
215 }
216
217 bool useDFT = fSurfaceProps.isUseDeviceIndependentFonts();
218 #if SK_FORCE_DISTANCE_FIELD_TEXT
219 useDFT = true;
220 #endif
221
222 if (!useDFT && scaledTextSize < kLargeDFFontSize) {
223 return false;
224 }
225
226 // rasterizers and mask filters modify alpha, which doesn't
227 // translate well to distance
228 if (skPaint.getRasterizer() || skPaint.getMaskFilter() ||
229 !fContext->caps()->shaderCaps()->shaderDerivativeSupport()) {
230 return false;
231 }
232
233 // TODO: add some stroking support
234 if (skPaint.getStyle() != SkPaint::kFill_Style) {
235 return false;
236 }
237
238 return true;
239 }
240
241 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, 189 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
242 const SkPaint& skPaint, GrColor colo r, 190 const SkPaint& skPaint, GrColor colo r,
243 const SkMatrix& viewMatrix, 191 const SkMatrix& viewMatrix,
244 const SkTextBlob* blob, SkScalar x, SkScalar y, 192 const SkTextBlob* blob, SkScalar x, SkScalar y,
245 SkDrawFilter* drawFilter) { 193 SkDrawFilter* drawFilter) {
246 // The color here is the GrPaint color, and it is used to determine whether we 194 // The color here is the GrPaint color, and it is used to determine whether we
247 // have to regenerate LCD text blobs. 195 // have to regenerate LCD text blobs.
248 // We use this color vs the SkPaint color because it has the colorfilter app lied. 196 // We use this color vs the SkPaint color because it has the colorfilter app lied.
249 cacheBlob->fPaintColor = color; 197 cacheBlob->fPaintColor = color;
250 cacheBlob->fViewMatrix = viewMatrix; 198 cacheBlob->fViewMatrix = viewMatrix;
(...skipping 14 matching lines...) Expand all
265 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ e)) { 213 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ e)) {
266 // A false return from filter() means we should abort the current dr aw. 214 // A false return from filter() means we should abort the current dr aw.
267 runPaint = skPaint; 215 runPaint = skPaint;
268 continue; 216 continue;
269 } 217 }
270 218
271 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint)); 219 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint));
272 220
273 cacheBlob->push_back_run(run); 221 cacheBlob->push_back_run(run);
274 222
275 if (this->canDrawAsDistanceFields(runPaint, viewMatrix)) { 223 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, fSurfaceP rops,
224 *fContext->caps()->shaderCaps() )) {
276 switch (it.positioning()) { 225 switch (it.positioning()) {
277 case SkTextBlob::kDefault_Positioning: { 226 case SkTextBlob::kDefault_Positioning: {
278 this->internalDrawDFText(cacheBlob, run, runPaint, color, vi ewMatrix, 227 GrTextUtils::DrawDFText(cacheBlob, run, fContext->getBatchFo ntCache(),
279 (const char *)it.glyphs(), textLen, 228 fSurfaceProps, runPaint, color, view Matrix,
280 x + offset.x(), y + offset.y()); 229 (const char *)it.glyphs(), textLen,
230 x + offset.x(), y + offset.y());
281 break; 231 break;
282 } 232 }
283 case SkTextBlob::kHorizontal_Positioning: { 233 case SkTextBlob::kHorizontal_Positioning: {
284 SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); 234 SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
285 this->internalDrawDFPosText(cacheBlob, run, runPaint, color, viewMatrix, 235 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatc hFontCache(),
286 (const char*)it.glyphs(), textLe n, it.pos(), 236 fSurfaceProps, runPaint, color, v iewMatrix,
287 1, dfOffset); 237 (const char*)it.glyphs(), textLen , it.pos(),
238 1, dfOffset);
288 break; 239 break;
289 } 240 }
290 case SkTextBlob::kFull_Positioning: { 241 case SkTextBlob::kFull_Positioning: {
291 SkPoint dfOffset = SkPoint::Make(x, y); 242 SkPoint dfOffset = SkPoint::Make(x, y);
292 this->internalDrawDFPosText(cacheBlob, run, runPaint, color, viewMatrix, 243 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBat chFontCache(),
293 (const char*)it.glyphs(), textLe n, it.pos(), 244 fSurfaceProps, runPaint, color, v iewMatrix,
294 2, dfOffset); 245 (const char*)it.glyphs(), textLen , it.pos(),
246 2, dfOffset);
295 break; 247 break;
296 } 248 }
297 } 249 }
298 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { 250 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
299 cacheBlob->fRuns[run].fDrawAsPaths = true; 251 cacheBlob->fRuns[run].fDrawAsPaths = true;
300 } else { 252 } else {
301 switch (it.positioning()) { 253 switch (it.positioning()) {
302 case SkTextBlob::kDefault_Positioning: 254 case SkTextBlob::kDefault_Positioning:
303 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchF ontCache(), 255 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchF ontCache(),
304 fSurfaceProps, runPaint, color, vie wMatrix, 256 fSurfaceProps, runPaint, color, vie wMatrix,
(...skipping 15 matching lines...) Expand all
320 } 272 }
321 } 273 }
322 274
323 if (drawFilter) { 275 if (drawFilter) {
324 // A draw filter may change the paint arbitrarily, so we must re-see d in this case. 276 // A draw filter may change the paint arbitrarily, so we must re-see d in this case.
325 runPaint = skPaint; 277 runPaint = skPaint;
326 } 278 }
327 } 279 }
328 } 280 }
329 281
330 inline void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob,
331 SkPaint* skPaint,
332 SkScalar* textRatio,
333 const SkMatrix& viewMatri x) {
334 // getMaxScale doesn't support perspective, so neither do we at the moment
335 SkASSERT(!viewMatrix.hasPerspective());
336 SkScalar maxScale = viewMatrix.getMaxScale();
337 SkScalar textSize = skPaint->getTextSize();
338 SkScalar scaledTextSize = textSize;
339 // if we have non-unity scale, we need to choose our base text size
340 // based on the SkPaint's text size multiplied by the max scale factor
341 // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
342 if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
343 scaledTextSize *= maxScale;
344 }
345
346 // We have three sizes of distance field text, and within each size 'bucket' there is a floor
347 // and ceiling. A scale outside of this range would require regenerating th e distance fields
348 SkScalar dfMaskScaleFloor;
349 SkScalar dfMaskScaleCeil;
350 if (scaledTextSize <= kSmallDFFontLimit) {
351 dfMaskScaleFloor = kMinDFFontSize;
352 dfMaskScaleCeil = kSmallDFFontLimit;
353 *textRatio = textSize / kSmallDFFontSize;
354 skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize));
355 } else if (scaledTextSize <= kMediumDFFontLimit) {
356 dfMaskScaleFloor = kSmallDFFontLimit;
357 dfMaskScaleCeil = kMediumDFFontLimit;
358 *textRatio = textSize / kMediumDFFontSize;
359 skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize));
360 } else {
361 dfMaskScaleFloor = kMediumDFFontLimit;
362 dfMaskScaleCeil = kLargeDFFontLimit;
363 *textRatio = textSize / kLargeDFFontSize;
364 skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize));
365 }
366
367 // Because there can be multiple runs in the blob, we want the overall maxMi nScale, and
368 // minMaxScale to make regeneration decisions. Specifically, we want the ma ximum minimum scale
369 // we can tolerate before we'd drop to a lower mip size, and the minimum max imum scale we can
370 // tolerate before we'd have to move to a large mip size. When we actually test these values
371 // we look at the delta in scale between the new viewmatrix and the old view matrix, and test
372 // against these values to decide if we can reuse or not(ie, will a given sc ale change our mip
373 // level)
374 SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScale Ceil);
375 blob->fMaxMinScale = SkMaxScalar(dfMaskScaleFloor / scaledTextSize, blob->fM axMinScale);
376 blob->fMinMaxScale = SkMinScalar(dfMaskScaleCeil / scaledTextSize, blob->fMi nMaxScale);
377
378 skPaint->setLCDRenderText(false);
379 skPaint->setAutohinted(false);
380 skPaint->setHinting(SkPaint::kNormal_Hinting);
381 skPaint->setSubpixelText(true);
382 }
383
384 inline void GrAtlasTextContext::fallbackDrawPosText(GrAtlasTextBlob* blob,
385 int runIndex,
386 GrColor color,
387 const SkPaint& skPaint,
388 const SkMatrix& viewMatrix,
389 const SkTDArray<char>& fallb ackTxt,
390 const SkTDArray<SkScalar>& f allbackPos,
391 int scalarsPerPosition,
392 const SkPoint& offset) {
393 SkASSERT(fallbackTxt.count());
394 Run& run = blob->fRuns[runIndex];
395 // Push back a new subrun to fill and set the override descriptor
396 run.push_back();
397 run.fOverrideDescriptor.reset(new SkAutoDescriptor);
398 GrTextUtils::DrawBmpPosText(blob, runIndex, fContext->getBatchFontCache(), f SurfaceProps,
399 skPaint, color, viewMatrix, fallbackTxt.begin(), fallbackTxt.count(),
400 fallbackPos.begin(), scalarsPerPosition, offset) ;
401 }
402
403 inline GrAtlasTextBlob* 282 inline GrAtlasTextBlob*
404 GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, const SkPaint& skPa int, 283 GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, const SkPaint& skPa int,
405 const SkMatrix& viewMatrix, 284 const SkMatrix& viewMatrix,
406 const char text[], size_t byteLength, 285 const char text[], size_t byteLength,
407 SkScalar x, SkScalar y) { 286 SkScalar x, SkScalar y) {
408 int glyphCount = skPaint.countText(text, byteLength); 287 int glyphCount = skPaint.countText(text, byteLength);
409 288
410 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::k GrayTextVASize); 289 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::k GrayTextVASize);
411 blob->fViewMatrix = viewMatrix; 290 blob->fViewMatrix = viewMatrix;
412 291
413 if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) { 292 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps,
414 this->internalDrawDFText(blob, 0, skPaint, paint.getColor(), viewMatrix, text, 293 *fContext->caps()->shaderCaps())) {
415 byteLength, x, y); 294 GrTextUtils::DrawDFText(blob, 0, fContext->getBatchFontCache(), fSurface Props,
295 skPaint, paint.getColor(), viewMatrix, text,
296 byteLength, x, y);
416 } else { 297 } else {
417 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), fSurfac eProps, skPaint, 298 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), fSurfac eProps, skPaint,
418 paint.getColor(), viewMatrix, text, byteLength, x, y); 299 paint.getColor(), viewMatrix, text, byteLength, x, y);
419 } 300 }
420 return blob; 301 return blob;
421 } 302 }
422 303
423 inline GrAtlasTextBlob* 304 inline GrAtlasTextBlob*
424 GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& s kPaint, 305 GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& s kPaint,
425 const SkMatrix& viewMatrix, 306 const SkMatrix& viewMatrix,
426 const char text[], size_t byteLength, 307 const char text[], size_t byteLength,
427 const SkScalar pos[], int scalarsPerPo sition, 308 const SkScalar pos[], int scalarsPerPo sition,
428 const SkPoint& offset) { 309 const SkPoint& offset) {
429 int glyphCount = skPaint.countText(text, byteLength); 310 int glyphCount = skPaint.countText(text, byteLength);
430 311
431 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::k GrayTextVASize); 312 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::k GrayTextVASize);
432 blob->fViewMatrix = viewMatrix; 313 blob->fViewMatrix = viewMatrix;
433 314
434 if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) { 315 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps,
435 this->internalDrawDFPosText(blob, 0, skPaint, paint.getColor(), viewMatr ix, text, 316 *fContext->caps()->shaderCaps())) {
436 byteLength, pos, scalarsPerPosition, offset) ; 317 GrTextUtils::DrawDFPosText(blob, 0, fContext->getBatchFontCache(), fSurf aceProps,
318 skPaint, paint.getColor(), viewMatrix, text,
319 byteLength, pos, scalarsPerPosition, offset);
437 } else { 320 } else {
438 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), fSur faceProps, skPaint, 321 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), fSur faceProps, skPaint,
439 paint.getColor(), viewMatrix, text, 322 paint.getColor(), viewMatrix, text,
440 byteLength, pos, scalarsPerPosition, offset) ; 323 byteLength, pos, scalarsPerPosition, offset) ;
441 } 324 }
442 return blob; 325 return blob;
443 } 326 }
444 327
445 void GrAtlasTextContext::onDrawText(GrDrawContext* dc, 328 void GrAtlasTextContext::onDrawText(GrDrawContext* dc,
446 const GrClip& clip, 329 const GrClip& clip,
(...skipping 17 matching lines...) Expand all
464 SkAutoTUnref<GrAtlasTextBlob> blob( 347 SkAutoTUnref<GrAtlasTextBlob> blob(
465 this->createDrawPosTextBlob(paint, skPaint, viewMatrix, 348 this->createDrawPosTextBlob(paint, skPaint, viewMatrix,
466 text, byteLength, 349 text, byteLength,
467 pos, scalarsPerPosition, 350 pos, scalarsPerPosition,
468 offset)); 351 offset));
469 352
470 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPa int, paint, clip, 353 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPa int, paint, clip,
471 regionClipBounds); 354 regionClipBounds);
472 } 355 }
473 356
474 void GrAtlasTextContext::internalDrawDFText(GrAtlasTextBlob* blob, int runIndex,
475 const SkPaint& skPaint, GrColor colo r,
476 const SkMatrix& viewMatrix,
477 const char text[], size_t byteLength ,
478 SkScalar x, SkScalar y) {
479 SkASSERT(byteLength == 0 || text != nullptr);
480
481 // nothing to draw
482 if (text == nullptr || byteLength == 0) {
483 return;
484 }
485
486 SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
487 SkAutoDescriptor desc;
488 skPaint.getScalerContextDescriptor(&desc, fSurfaceProps, nullptr, true);
489 SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(skPaint.getTypeface (),
490 desc.getDesc());
491
492 SkTArray<SkScalar> positions;
493
494 const char* textPtr = text;
495 SkFixed stopX = 0;
496 SkFixed stopY = 0;
497 SkFixed origin = 0;
498 switch (skPaint.getTextAlign()) {
499 case SkPaint::kRight_Align: origin = SK_Fixed1; break;
500 case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
501 case SkPaint::kLeft_Align: origin = 0; break;
502 }
503
504 SkAutoKern autokern;
505 const char* stop = text + byteLength;
506 while (textPtr < stop) {
507 // don't need x, y here, since all subpixel variants will have the
508 // same advance
509 const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr, 0, 0);
510
511 SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
512 positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));
513
514 SkFixed height = glyph.fAdvanceY;
515 positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height))) ;
516
517 stopX += width;
518 stopY += height;
519 }
520 SkASSERT(textPtr == stop);
521
522 SkGlyphCache::AttachCache(origPaintCache);
523
524 // now adjust starting point depending on alignment
525 SkScalar alignX = SkFixedToScalar(stopX);
526 SkScalar alignY = SkFixedToScalar(stopY);
527 if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
528 alignX = SkScalarHalf(alignX);
529 alignY = SkScalarHalf(alignY);
530 } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
531 alignX = 0;
532 alignY = 0;
533 }
534 x -= alignX;
535 y -= alignY;
536 SkPoint offset = SkPoint::Make(x, y);
537
538 this->internalDrawDFPosText(blob, runIndex, skPaint, color, viewMatrix, text , byteLength,
539 positions.begin(), 2, offset);
540 }
541
542 void GrAtlasTextContext::internalDrawDFPosText(GrAtlasTextBlob* blob, int runInd ex,
543 const SkPaint& origPaint,
544 GrColor color,
545 const SkMatrix& viewMatrix,
546 const char text[], size_t byteLen gth,
547 const SkScalar pos[], int scalars PerPosition,
548 const SkPoint& offset) {
549
550 SkASSERT(byteLength == 0 || text != nullptr);
551 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
552
553 // nothing to draw
554 if (text == nullptr || byteLength == 0) {
555 return;
556 }
557
558 SkTDArray<char> fallbackTxt;
559 SkTDArray<SkScalar> fallbackPos;
560
561 // Setup distance field paint and text ratio
562 SkScalar textRatio;
563 SkPaint dfPaint(origPaint);
564 this->initDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix);
565 blob->setHasDistanceField();
566 blob->setSubRunHasDistanceFields(runIndex, origPaint.isLCDRenderText());
567
568 fCurrStrike = nullptr;
569
570 SkGlyphCache* cache = blob->setupCache(runIndex, fSurfaceProps, dfPaint, nul lptr, true);
571 SkDrawCacheProc glyphCacheProc = dfPaint.getDrawCacheProc();
572 GrFontScaler* fontScaler = GetGrFontScaler(cache);
573
574 const char* stop = text + byteLength;
575
576 if (SkPaint::kLeft_Align == dfPaint.getTextAlign()) {
577 while (text < stop) {
578 const char* lastText = text;
579 // the last 2 parameters are ignored
580 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
581
582 if (glyph.fWidth) {
583 SkScalar x = offset.x() + pos[0];
584 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
585
586 if (!this->dfAppendGlyph(blob,
587 runIndex,
588 glyph,
589 x, y, color, fontScaler,
590 textRatio, viewMatrix)) {
591 // couldn't append, send to fallback
592 fallbackTxt.append(SkToInt(text-lastText), lastText);
593 *fallbackPos.append() = pos[0];
594 if (2 == scalarsPerPosition) {
595 *fallbackPos.append() = pos[1];
596 }
597 }
598 }
599 pos += scalarsPerPosition;
600 }
601 } else {
602 SkScalar alignMul = SkPaint::kCenter_Align == dfPaint.getTextAlign() ? S K_ScalarHalf
603 : S K_Scalar1;
604 while (text < stop) {
605 const char* lastText = text;
606 // the last 2 parameters are ignored
607 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
608
609 if (glyph.fWidth) {
610 SkScalar x = offset.x() + pos[0];
611 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
612
613 SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX) * alignMul * textRatio;
614 SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY) * alignMul * textRatio;
615
616 if (!this->dfAppendGlyph(blob,
617 runIndex,
618 glyph,
619 x - advanceX, y - advanceY, color,
620 fontScaler,
621 textRatio,
622 viewMatrix)) {
623 // couldn't append, send to fallback
624 fallbackTxt.append(SkToInt(text-lastText), lastText);
625 *fallbackPos.append() = pos[0];
626 if (2 == scalarsPerPosition) {
627 *fallbackPos.append() = pos[1];
628 }
629 }
630 }
631 pos += scalarsPerPosition;
632 }
633 }
634
635 SkGlyphCache::AttachCache(cache);
636 if (fallbackTxt.count()) {
637 this->fallbackDrawPosText(blob, runIndex, origPaint.getColor(), origPain t, viewMatrix,
638 fallbackTxt, fallbackPos, scalarsPerPosition, offset);
639 }
640 }
641
642 bool GrAtlasTextContext::dfAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
643 const SkGlyph& skGlyph,
644 SkScalar sx, SkScalar sy, GrColor color,
645 GrFontScaler* scaler,
646 SkScalar textRatio, const SkMatrix& viewM atrix) {
647 if (!fCurrStrike) {
648 fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler);
649 }
650
651 GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(),
652 skGlyph.getSubXFixed(),
653 skGlyph.getSubYFixed(),
654 GrGlyph::kDistance_MaskStyle);
655 GrGlyph* glyph = fCurrStrike->getGlyph(skGlyph, id, scaler);
656 if (!glyph) {
657 return true;
658 }
659
660 // fallback to color glyph support
661 if (kA8_GrMaskFormat != glyph->fMaskFormat) {
662 return false;
663 }
664
665 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
666 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
667 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2 * SK_DistanceField Inset);
668 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2 * SK_DistanceFie ldInset);
669
670 SkScalar scale = textRatio;
671 dx *= scale;
672 dy *= scale;
673 width *= scale;
674 height *= scale;
675 sx += dx;
676 sy += dy;
677 SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height);
678
679 blob->appendGlyph(runIndex, glyphRect, color, fCurrStrike, glyph, scaler, sk Glyph,
680 sx - dx, sy - dy, scale, true);
681 return true;
682 }
683
684 //////////////////////////////////////////////////////////////////////////////// /////////////////// 357 //////////////////////////////////////////////////////////////////////////////// ///////////////////
685 358
686 #ifdef GR_TEST_UTILS 359 #ifdef GR_TEST_UTILS
687 360
688 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { 361 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
689 static uint32_t gContextID = SK_InvalidGenID; 362 static uint32_t gContextID = SK_InvalidGenID;
690 static GrAtlasTextContext* gTextContext = nullptr; 363 static GrAtlasTextContext* gTextContext = nullptr;
691 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType ); 364 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType );
692 365
693 if (context->uniqueID() != gContextID) { 366 if (context->uniqueID() != gContextID) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 401
729 SkScalar transX = static_cast<SkScalar>(random->nextU()); 402 SkScalar transX = static_cast<SkScalar>(random->nextU());
730 SkScalar transY = static_cast<SkScalar>(random->nextU()); 403 SkScalar transY = static_cast<SkScalar>(random->nextU());
731 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0] ; 404 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0] ;
732 return blob->createBatch(info, textLen, 0, 0, color, transX, transY, skPaint , 405 return blob->createBatch(info, textLen, 0, 0, color, transX, transY, skPaint ,
733 gSurfaceProps, gTextContext->dfAdjustTable(), 406 gSurfaceProps, gTextContext->dfAdjustTable(),
734 context->getBatchFontCache()); 407 context->getBatchFontCache());
735 } 408 }
736 409
737 #endif 410 #endif
OLDNEW
« no previous file with comments | « src/gpu/text/GrAtlasTextContext.h ('k') | src/gpu/text/GrTextUtils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698