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

Side by Side Diff: gm/texteffects.cpp

Issue 2186663004: SkPaint intercept API for SkTextBlob and horizontal text (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: GM size, comments Created 4 years, 4 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 | « no previous file | include/core/SkPaint.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 2011 Google Inc. 2 * Copyright 2011 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 "gm.h" 8 #include "gm.h"
9 #include "SkBlurMask.h" 9 #include "SkBlurMask.h"
10 #include "SkBlurMaskFilter.h" 10 #include "SkBlurMaskFilter.h"
11 #include "SkReadBuffer.h" 11 #include "SkReadBuffer.h"
12 #include "SkTextBlob.h"
12 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
13 #include "SkLayerRasterizer.h" 14 #include "SkLayerRasterizer.h"
14 15
15 static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) { 16 static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
16 p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 17 p.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
17 SkBlurMask::ConvertRadiusToSigma(SkIn tToScalar(3)))); 18 SkBlurMask::ConvertRadiusToSigma(SkIn tToScalar(3))));
18 rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3)); 19 rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
19 20
20 p.setMaskFilter(nullptr); 21 p.setMaskFilter(nullptr);
21 p.setStyle(SkPaint::kStroke_Style); 22 p.setStyle(SkPaint::kStroke_Style);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 paint.getTextIntercepts(test, len, x, y, bounds, intersections->begin()) ; 261 paint.getTextIntercepts(test, len, x, y, bounds, intersections->begin()) ;
261 } 262 }
262 } 263 }
263 264
264 DEF_SIMPLE_GM(fancyunderline, canvas, 900, 1350) { 265 DEF_SIMPLE_GM(fancyunderline, canvas, 900, 1350) {
265 SkPaint paint; 266 SkPaint paint;
266 paint.setAntiAlias(true); 267 paint.setAntiAlias(true);
267 const char* fam[] = { "sans-serif", "serif", "monospace" }; 268 const char* fam[] = { "sans-serif", "serif", "monospace" };
268 const char test[] = "aAjJgGyY_|{-(~[,]qQ}pP}zZ"; 269 const char test[] = "aAjJgGyY_|{-(~[,]qQ}pP}zZ";
269 SkPoint textPt = { 10, 80 }; 270 SkPoint textPt = { 10, 80 };
270 for (int font = 0; font < 3; ++font) { 271 for (size_t font = 0; font < SK_ARRAY_COUNT(fam); ++font) {
271 sk_tool_utils::set_portable_typeface(&paint, fam[font]); 272 sk_tool_utils::set_portable_typeface(&paint, fam[font]);
272 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) { 273 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) {
273 paint.setTextSize(textSize); 274 paint.setTextSize(textSize);
274 const SkScalar uWidth = textSize / 15; 275 const SkScalar uWidth = textSize / 15;
275 paint.setStrokeWidth(uWidth); 276 paint.setStrokeWidth(uWidth);
276 paint.setStyle(SkPaint::kFill_Style); 277 paint.setStyle(SkPaint::kFill_Style);
277 canvas->drawText(test, sizeof(test) - 1, textPt.fX, textPt.fY, paint ); 278 canvas->drawText(test, sizeof(test) - 1, textPt.fX, textPt.fY, paint );
278 279
279 SkTDArray<SkScalar> intersections; 280 SkTDArray<SkScalar> intersections;
280 find_intercepts(test, sizeof(test) - 1, textPt.fX, textPt.fY, paint, uWidth, 281 find_intercepts(test, sizeof(test) - 1, textPt.fX, textPt.fY, paint, uWidth,
(...skipping 23 matching lines...) Expand all
304 paint.getPosTextIntercepts(test, len, pos, bounds, intersections->begin( )); 305 paint.getPosTextIntercepts(test, len, pos, bounds, intersections->begin( ));
305 } 306 }
306 } 307 }
307 308
308 DEF_SIMPLE_GM(fancyposunderline, canvas, 900, 1350) { 309 DEF_SIMPLE_GM(fancyposunderline, canvas, 900, 1350) {
309 SkPaint paint; 310 SkPaint paint;
310 paint.setAntiAlias(true); 311 paint.setAntiAlias(true);
311 const char* fam[] = { "sans-serif", "serif", "monospace" }; 312 const char* fam[] = { "sans-serif", "serif", "monospace" };
312 const char test[] = "aAjJgGyY_|{-(~[,]qQ}pP}zZ"; 313 const char test[] = "aAjJgGyY_|{-(~[,]qQ}pP}zZ";
313 SkPoint textPt = { 10, 80 }; 314 SkPoint textPt = { 10, 80 };
314 for (int font = 0; font < 3; ++font) { 315 for (size_t font = 0; font < SK_ARRAY_COUNT(fam); ++font) {
315 sk_tool_utils::set_portable_typeface(&paint, fam[font]); 316 sk_tool_utils::set_portable_typeface(&paint, fam[font]);
316 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) { 317 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) {
317 paint.setTextSize(textSize); 318 paint.setTextSize(textSize);
318 const SkScalar uWidth = textSize / 15; 319 const SkScalar uWidth = textSize / 15;
319 paint.setStrokeWidth(uWidth); 320 paint.setStrokeWidth(uWidth);
320 paint.setStyle(SkPaint::kFill_Style); 321 paint.setStyle(SkPaint::kFill_Style);
321 int widthCount = paint.getTextWidths(test, sizeof(test) - 1, nullptr ); 322 int widthCount = paint.getTextWidths(test, sizeof(test) - 1, nullptr );
322 SkTDArray<SkScalar> widths; 323 SkTDArray<SkScalar> widths;
323 widths.setCount(widthCount); 324 widths.setCount(widthCount);
324 (void) paint.getTextWidths(test, sizeof(test) - 1, widths.begin()); 325 (void) paint.getTextWidths(test, sizeof(test) - 1, widths.begin());
(...skipping 16 matching lines...) Expand all
341 SkPath underline = create_underline(intersections, start, end, uPos, uWidth, textSize); 342 SkPath underline = create_underline(intersections, start, end, uPos, uWidth, textSize);
342 paint.setStyle(SkPaint::kStroke_Style); 343 paint.setStyle(SkPaint::kStroke_Style);
343 canvas->drawPath(underline, paint); 344 canvas->drawPath(underline, paint);
344 345
345 canvas->translate(0, textSize * 1.3f); 346 canvas->translate(0, textSize * 1.3f);
346 } 347 }
347 canvas->translate(0, 60); 348 canvas->translate(0, 60);
348 } 349 }
349 } 350 }
350 351
352 namespace {
353
354 sk_sp<const SkTextBlob> MakeFancyBlob(const SkPaint& paint, const char* text) {
355 SkPaint blobPaint(paint);
356
357 const size_t textLen = strlen(text);
358 const int glyphCount = blobPaint.textToGlyphs(text, textLen, nullptr);
359 SkAutoTArray<SkGlyphID> glyphs(glyphCount);
360 blobPaint.textToGlyphs(text, textLen, glyphs.get());
361
362 blobPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
363 const size_t glyphTextBytes = SkTo<uint32_t>(glyphCount) * sizeof(SkGlyphID) ;
364 const int widthCount = blobPaint.getTextWidths(glyphs.get(), glyphTextBytes, nullptr);
365 SkAssertResult(widthCount == glyphCount);
366
367 SkAutoTArray<SkScalar> widths(glyphCount);
368 blobPaint.getTextWidths(glyphs.get(), glyphTextBytes, widths.get());
369
370 SkTextBlobBuilder blobBuilder;
371 int glyphIndex = 0;
372 SkScalar advance = 0;
373
374 // Default-positioned run.
375 {
376 const int defaultRunLen = glyphCount / 3;
377 const SkTextBlobBuilder::RunBuffer& buf = blobBuilder.allocRun(blobPaint ,
378 defaultRu nLen,
379 advance, 0);
380 memcpy(buf.glyphs, glyphs.get(), SkTo<uint32_t>(defaultRunLen) * sizeof( SkGlyphID));
381
382 for (int i = 0; i < defaultRunLen; ++i) {
383 advance += widths[glyphIndex++];
384 }
385 }
386
387 // Horizontal-positioned run.
388 {
389 const int horizontalRunLen = glyphCount / 3;
390 const SkTextBlobBuilder::RunBuffer& buf = blobBuilder.allocRunPosH(blobP aint,
391 horiz ontalRunLen,
392 0);
393 memcpy(buf.glyphs, glyphs.get() + glyphIndex,
394 SkTo<uint32_t>(horizontalRunLen) * sizeof(SkGlyphID));
395 for (int i = 0; i < horizontalRunLen; ++i) {
396 buf.pos[i] = advance;
397 advance += widths[glyphIndex++];
398 }
399 }
400
401 // Full-positioned run.
402 {
403 const int fullRunLen = glyphCount - glyphIndex;
404 const SkTextBlobBuilder::RunBuffer& buf = blobBuilder.allocRunPos(blobPa int, fullRunLen);
405 memcpy(buf.glyphs, glyphs.get() + glyphIndex,
406 SkTo<uint32_t>(fullRunLen) * sizeof(SkGlyphID));
407 for (int i = 0; i < fullRunLen; ++i) {
408 buf.pos[i * 2 + 0] = advance; // x offset
409 buf.pos[i * 2 + 1] = 0; // y offset
410 advance += widths[glyphIndex++];
411 }
412 }
413
414 return sk_sp<const SkTextBlob>(blobBuilder.build());
415 }
416
417 } // anonymous ns
418
419 DEF_SIMPLE_GM(fancyblobunderline, canvas, 1480, 1380) {
420 SkPaint paint;
421 paint.setAntiAlias(true);
422 const char* fam[] = { "sans-serif", "serif", "monospace" };
423 const char test[] = "aAjJgGyY_|{-(~[,]qQ}pP}zZ";
424 const SkPoint blobOffset = { 10, 80 };
425
426 for (size_t font = 0; font < SK_ARRAY_COUNT(fam); ++font) {
427 sk_tool_utils::set_portable_typeface(&paint, fam[font]);
428 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) {
429 paint.setTextSize(textSize);
430 const SkScalar uWidth = textSize / 15;
431 paint.setStrokeWidth(uWidth);
432 paint.setStyle(SkPaint::kFill_Style);
433
434 sk_sp<const SkTextBlob> blob = MakeFancyBlob(paint, test);
435 canvas->drawTextBlob(blob.get(), blobOffset.x(), blobOffset.y(), pai nt);
436
437 const SkScalar uPos = uWidth;
438 const SkScalar bounds[2] = { uPos - uWidth / 2, uPos + uWidth / 2 };
439 const int interceptCount = paint.getTextBlobIntercepts(blob.get(), b ounds, nullptr);
440 SkASSERT(!(interceptCount % 2));
441
442 SkTDArray<SkScalar> intercepts;
443 intercepts.setCount(interceptCount);
444 paint.getTextBlobIntercepts(blob.get(), bounds, intercepts.begin());
445
446 const SkScalar start = blob->bounds().left();
447 const SkScalar end = blob->bounds().right();
448 SkPath underline = create_underline(intercepts, start, end, uPos, uW idth, textSize);
449 underline.offset(blobOffset.x(), blobOffset.y());
450 paint.setStyle(SkPaint::kStroke_Style);
451 canvas->drawPath(underline, paint);
452
453 canvas->translate(0, textSize * 1.3f);
454 }
455
456 canvas->translate(0, 60);
457 }
458 }
459
351 DEF_SIMPLE_GM(fancyunderlinebars, canvas, 1500, 460) { 460 DEF_SIMPLE_GM(fancyunderlinebars, canvas, 1500, 460) {
352 SkPaint paint; 461 SkPaint paint;
353 paint.setAntiAlias(true); 462 paint.setAntiAlias(true);
354 const char test[] = " .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_"; 463 const char test[] = " .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_ .}]_";
355 SkPoint textPt = { 10, 80 }; 464 SkPoint textPt = { 10, 80 };
356 sk_tool_utils::set_portable_typeface(&paint, "serif"); 465 sk_tool_utils::set_portable_typeface(&paint, "serif");
357 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) { 466 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) {
358 paint.setTextSize(textSize); 467 paint.setTextSize(textSize);
359 SkScalar uWidth = textSize / 15; 468 SkScalar uWidth = textSize / 15;
360 paint.setStrokeWidth(uWidth); 469 paint.setStrokeWidth(uWidth);
(...skipping 19 matching lines...) Expand all
380 489
381 SkScalar start = textPt.fX; 490 SkScalar start = textPt.fX;
382 SkScalar end = posX; 491 SkScalar end = posX;
383 SkScalar uPos = pos[0].fY + uWidth; 492 SkScalar uPos = pos[0].fY + uWidth;
384 SkPath underline = create_underline(intersections, start, end, uPos, uWi dth, textSize); 493 SkPath underline = create_underline(intersections, start, end, uPos, uWi dth, textSize);
385 paint.setStyle(SkPaint::kStroke_Style); 494 paint.setStyle(SkPaint::kStroke_Style);
386 canvas->drawPath(underline, paint); 495 canvas->drawPath(underline, paint);
387 canvas->translate(0, textSize * 1.3f); 496 canvas->translate(0, textSize * 1.3f);
388 } 497 }
389 } 498 }
OLDNEW
« no previous file with comments | « no previous file | include/core/SkPaint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698