Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
bug12866.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm/gm.h"
10#include "include/core/SkPath.h"
13
14static SkPath get_path() {
15 SkPath path;
16 path.setFillType(SkPathFillType::kWinding);
17 path.moveTo(SkBits2Float(0x45034ec4), SkBits2Float(0x42e7fb80)); // 2100.92f, 115.991f
18 path.quadTo(SkBits2Float(0x4500f46c),
19 SkBits2Float(0x43333300),
20 SkBits2Float(0x4500f46c),
21 SkBits2Float(0x431f0ec0)); // 2063.28f, 179.199f, 2063.28f, 159.058f
22 path.quadTo(SkBits2Float(0x4500f46c),
23 SkBits2Float(0x430ad7c0),
24 SkBits2Float(0x45019462),
25 SkBits2Float(0x42fed580)); // 2063.28f, 138.843f, 2073.27f, 127.417f
26 path.quadTo(SkBits2Float(0x45023458),
27 SkBits2Float(0x42e7fb80),
28 SkBits2Float(0x45034ec4),
29 SkBits2Float(0x42e7fb80)); // 2083.27f, 115.991f, 2100.92f, 115.991f
30 path.close();
31 return path;
32}
33
34// Reproduces the underlying problem from skbug.com/12866.
35// The path (part of a glyph) was being drawn stroked, and with a perspective matrix.
36// The perspective matrix forces a very large resScale when stroking the path.
37// The resulting filled path is incorrect. Note that stroking with a smaller resScale works fine.
38DEF_SIMPLE_GM(bug12866, canvas, 128, 64) {
39 SkPaint strokePaint;
40 strokePaint.setAntiAlias(true);
42 strokePaint.setStrokeWidth(3);
43
44 SkPaint fillPaint;
45 fillPaint.setAntiAlias(true);
46
48 SkPath fillPath;
49 skpathutils::FillPathWithPaint(strokePath, strokePaint, &fillPath, nullptr, 1200.0f);
50
51 SkRect strokeBounds = strokePath.getBounds();
52 SkRect fillBounds = fillPath.getBounds();
53
54 // Draw the stroked path. This (internally) uses a resScale of 1.0, and looks good.
55 canvas->save();
56 canvas->translate(10 - strokeBounds.fLeft, 10 - strokeBounds.fTop);
57 canvas->drawPath(strokePath, strokePaint);
58 canvas->restore();
59
60 // With a perspective CTM, it's possible for resScale to become large. Draw the filled
61 // path produced by the stroker in that situation, which ends up being incorrect.
62 canvas->save();
63 canvas->translate(74 - fillBounds.fLeft, 10 - fillBounds.fTop);
64 canvas->drawPath(fillPath, fillPaint);
65 canvas->restore();
66}
67
68// This is another example of the same underlying bug (recursion limit in the stroker),
69// but with cubics, rather than quads.
70DEF_SIMPLE_GM(bug40810065, canvas, 256, 512) {
71 canvas->scale(2.f, 2.f);
72
74 path1.moveTo(108.87f, 3.78f);
75 path1.cubicTo(201.1f, -128.61f, 34.21f, 82.54f, 134.14f, 126.01f);
77 path2.moveTo(108.87f, 3.78f);
78 path2.cubicTo(201.f, -128.61f, 34.21f, 82.54f, 134.14f, 126.f);
79
80 SkPaint stroke;
81 stroke.setColor(SK_ColorBLACK);
82 stroke.setAntiAlias(true);
84 stroke.setStrokeWidth(1.f);
86
87 canvas->save();
88 canvas->translate(-75.f, 50.f);
89 canvas->drawPath(path1, stroke);
90 canvas->restore();
91
92 canvas->save();
93 canvas->translate(-20.f, 100.f);
94 canvas->drawPath(path2, stroke);
95 canvas->restore();
96}
97
98// Finally: A repro case that involves conics. This should draw NOTHING. When incorrect, it drew
99// a large black rectangle over half of the slide.
100DEF_SIMPLE_GM_BG(bug41422450, canvas, 863, 473, SK_ColorWHITE) {
101 SkM44 mat{1, -0.00000139566271f, 0, -2321738,
102 0.000113059919f, 0.0123444516f, 0, -353,
103 0, 0, 1, 0,
104 0, 0, 0, 1};
105 canvas->concat(mat);
106
108 SkRect circle = SkRect::MakeLTRB(-3299135.5f, -12312541.0f, 9897407.0f, 884000.812f);
109 strokePath.arcTo(circle, 59.9999962f, 59.9999962f, true);
110
111 SkPaint strokePaint;
112 strokePaint.setStyle(SkPaint::kStroke_Style);
113 strokePaint.setStrokeWidth(2);
114 canvas->drawPath(strokePath, strokePaint);
115}
static SkPath path1()
static SkPath path2()
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
static float SkBits2Float(uint32_t bits)
Definition SkFloatBits.h:48
static SkPath get_path()
Definition bug12866.cpp:14
Definition SkM44.h:150
@ kRound_Cap
adds circle
Definition SkPaint.h:335
void setStyle(Style style)
Definition SkPaint.cpp:105
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition SkPaint.h:170
void setStrokeCap(Cap cap)
Definition SkPaint.cpp:179
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
const SkRect & getBounds() const
Definition SkPath.cpp:420
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
static void strokePath(SkCanvas *canvas, const SkPath &path)
#define DEF_SIMPLE_GM_BG(NAME, CANVAS, W, H, BGCOLOR)
Definition gm.h:52
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15