skia2/gm/stroketext.cpp
Ben Wagner d38f00a12a Skip degenerate contours in glyphs.
Stroking in Skia follows the SVG rules of adding end caps to degenerate
contours. Skip all degenerate contours and degenerate curves on contours
to avoid this.

Bug: skia:9820
Change-Id: I320beeeb3728f39c764729454dcb128a05524d35
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268166
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
2020-02-13 16:22:42 +00:00

145 lines
4.8 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkDashPathEffect.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
static void test_nulldev(SkCanvas* canvas) {
SkBitmap bm;
bm.setInfo(SkImageInfo::MakeN32Premul(30, 30));
// notice: no pixels mom! be sure we don't crash
// https://code.google.com/p/chromium/issues/detail?id=352616
SkCanvas c(bm);
SkBitmap src;
src.allocN32Pixels(10, 10);
src.eraseColor(SK_ColorRED);
// ensure we don't crash
c.writePixels(src, 0, 0);
}
static void draw_text_stroked(SkCanvas* canvas, const SkPaint& paint, const SkFont& font,
SkScalar strokeWidth) {
SkPaint p(paint);
SkPoint loc = { 20, 435 };
if (strokeWidth > 0) {
p.setStyle(SkPaint::kFill_Style);
canvas->drawSimpleText("P", 1, SkTextEncoding::kUTF8, loc.fX, loc.fY - 225, font, p);
canvas->drawTextBlob(SkTextBlob::MakeFromPosText("P", 1, &loc, font), 0, 0, p);
}
p.setColor(SK_ColorRED);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(strokeWidth);
canvas->drawSimpleText("P", 1, SkTextEncoding::kUTF8, loc.fX, loc.fY - 225, font, p);
canvas->drawTextBlob(SkTextBlob::MakeFromPosText("P", 1, &loc, font), 0, 0, p);
}
static void draw_text_set(SkCanvas* canvas, const SkPaint& paint, const SkFont& font) {
SkAutoCanvasRestore acr(canvas, true);
draw_text_stroked(canvas, paint, font, 10);
canvas->translate(200, 0);
draw_text_stroked(canvas, paint, font, 0);
const SkScalar intervals[] = { 20, 10, 5, 10 };
const SkScalar phase = 0;
canvas->translate(200, 0);
SkPaint p(paint);
p.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), phase));
draw_text_stroked(canvas, p, font, 10);
}
namespace {
enum {
kBelowThreshold_TextSize = 255,
kAboveThreshold_TextSize = 257
};
}
DEF_SIMPLE_GM(stroketext, canvas, 1200, 480) {
if (true) { test_nulldev(canvas); }
SkPaint paint;
paint.setAntiAlias(true);
SkFont font(ToolUtils::create_portable_typeface(), kBelowThreshold_TextSize);
draw_text_set(canvas, paint, font);
canvas->translate(600, 0);
font.setSize(kAboveThreshold_TextSize);
draw_text_set(canvas, paint, font);
}
DEF_SIMPLE_GM_CAN_FAIL(stroketext_native, canvas, msg, 650, 320) {
sk_sp<SkTypeface> ttf = MakeResourceAsTypeface("fonts/Stroking.ttf");
sk_sp<SkTypeface> otf = MakeResourceAsTypeface("fonts/Stroking.otf");
if (!ttf && !otf) {
msg->append("No support for ttf or otf.");
return skiagm::DrawResult::kSkip;
}
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(10);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setStrokeJoin(SkPaint::kRound_Join);
p.setARGB(0xff, 0xbb, 0x00, 0x00);
if (ttf) {
/* Stroking.ttf is structured like:
nothing U+25CB ○ (nothing inside)
something U+25C9 ◉ (a tiny thing inside)
- off (point off / empty quad with implicit end) (before U+207B ⁻ / after U+208B ₋)
+ on (point on / empty line) (before U+207A ⁺ / after U+208A ₊)
0 off off (two implicit quads) (before U+2070 ⁰ / after U+2080 ₀)
1 off on (quad with implicit close around) (before U+00B9 ¹ / after U+2081 ₁)
2 on off (quad with implicit close) (before U+00B2 ² / after U+2082 ₂)
3 on on (empty line) (before U+00B3 ³ / after U+2083 ₃)
*/
SkFont font(ttf, 100);
canvas->drawString("○◉ ⁻₋⁺₊", 10, 100, font, p);
canvas->drawString("⁰₀¹₁²₂³₃", 10, 200, font, p);
}
if (otf) {
/* Stroking.otf is structured like:
nothing U+25CB ○
something U+25C9 ◉
0 moveto, moveto (before U+2070 ⁰) (nothing there, FreeType ignores these)
1 moveto, empty line, moveto (before U+00B9 ¹) (degenerate lineto)
3 moveto, empty cubic, moveto (before U+00B3 ³) (degenerate cubicto)
f moveto, empty flex, moveto (before U+1DA0 ᶠ) (degenerate flex)
*/
SkFont font(otf, 100);
canvas->drawString("○◉ ⁰¹³ᶠ", 10, 300, font, p);
}
return skiagm::DrawResult::kOk;
}