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"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkPath.h"
11
get_path()12 static SkPath get_path() {
13 SkPath path;
14 path.setFillType(SkPathFillType::kWinding);
15 path.moveTo(SkBits2Float(0x45034ec4), SkBits2Float(0x42e7fb80)); // 2100.92f, 115.991f
16 path.quadTo(SkBits2Float(0x4500f46c),
17 SkBits2Float(0x43333300),
18 SkBits2Float(0x4500f46c),
19 SkBits2Float(0x431f0ec0)); // 2063.28f, 179.199f, 2063.28f, 159.058f
20 path.quadTo(SkBits2Float(0x4500f46c),
21 SkBits2Float(0x430ad7c0),
22 SkBits2Float(0x45019462),
23 SkBits2Float(0x42fed580)); // 2063.28f, 138.843f, 2073.27f, 127.417f
24 path.quadTo(SkBits2Float(0x45023458),
25 SkBits2Float(0x42e7fb80),
26 SkBits2Float(0x45034ec4),
27 SkBits2Float(0x42e7fb80)); // 2083.27f, 115.991f, 2100.92f, 115.991f
28 path.close();
29 return path;
30 }
31
32 // Reproduces the underlying problem from skbug.com/12866.
33 // The path (part of a glyph) was being drawn stroked, and with a perspective matrix.
34 // The perspective matrix forces a very large resScale when stroking the path.
35 // The resulting filled path is incorrect. Note that stroking with a smaller resScale works fine.
36 DEF_SIMPLE_GM(bug12866, canvas, 128, 64) {
37 SkPaint strokePaint;
38 strokePaint.setAntiAlias(true);
39 strokePaint.setStyle(SkPaint::kStroke_Style);
40 strokePaint.setStrokeWidth(3);
41
42 SkPaint fillPaint;
43 fillPaint.setAntiAlias(true);
44
45 SkPath strokePath = get_path();
46 SkPath fillPath;
47 strokePaint.getFillPath(strokePath, &fillPath, nullptr, 1200.0f);
48
49 SkRect strokeBounds = strokePath.getBounds();
50 SkRect fillBounds = fillPath.getBounds();
51
52 // Draw the stroked path. This (internally) uses a resScale of 1.0, and looks good.
53 canvas->save();
54 canvas->translate(10 - strokeBounds.fLeft, 10 - strokeBounds.fTop);
55 canvas->drawPath(strokePath, strokePaint);
56 canvas->restore();
57
58 // With a perspective CTM, it's possible for resScale to become large. Draw the filled
59 // path produced by the stroker in that situation, which ends up being incorrect.
60 canvas->save();
61 canvas->translate(74 - fillBounds.fLeft, 10 - fillBounds.fTop);
62 canvas->drawPath(fillPath, fillPaint);
63 canvas->restore();
64 }
65