2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
13 // Test how short paths are stroked with various caps
14 class StrokeZeroGM : public skiagm::GM {
16 SkPath fClipL, fClipR, fClipS;
19 void onOnceBeforeDraw() override {
22 fClipL.lineTo(2.5f, 1);
23 fClipL.lineTo(3.5f, 2.5f);
24 fClipL.lineTo(2.5f, 4);
32 fClipR.lineTo(30.5, 4);
33 fClipR.lineTo(31.5, 2.5);
34 fClipR.lineTo(30.5, 1);
38 fClipS.addRect(SkRect::MakeIWH(4, 5));
40 fPaths[0].moveTo(30, 0); // single line segment
41 fPaths[0].rLineTo(30, 0);
43 fPaths[1].moveTo(90, 0); // single line segment with close (does not draw caps)
44 fPaths[1].rLineTo(30, 0);
47 fPaths[2].moveTo(150, 0); // zero-length line
48 fPaths[2].rLineTo(0, 0);
50 fPaths[3].moveTo(180, 0); // zero-length line with close (expected not to draw)
51 fPaths[3].rLineTo(0, 0);
54 fPaths[4].moveTo(210, 0); // close only, no line
57 fPaths[5].moveTo(30, 90); // all combos below should draw two caps
58 fPaths[5].rLineTo(0, 0);
59 fPaths[5].moveTo(60, 90);
60 fPaths[5].rLineTo(0, 0);
62 fPaths[6].moveTo(90, 90);
64 fPaths[6].moveTo(120, 90);
67 fPaths[7].moveTo(150, 90);
68 fPaths[7].rLineTo(0, 0);
69 fPaths[7].moveTo(180, 90);
74 SkString onShortName() override {
75 return SkString("path_stroke_with_zero_length");
78 SkISize onISize() override {
79 return SkISize::Make(1120, 840);
82 void onDraw(SkCanvas* canvas) override {
84 bkgrnd.setColor(SK_ColorWHITE);
85 canvas->drawRect(SkRect::MakeIWH(onISize().fWidth, onISize().fHeight), bkgrnd);
87 auto drawPaths = [&](SkPaint& paint, int indexMask) {
88 canvas->translate(0, 30.0f);
90 for (const SkPath& path : fPaths) {
91 if (indexMask & (1 << index)) {
92 canvas->drawPath(path, paint);
94 if (this->getMode() == skiagm::GM::kSample_Mode && paint.getStrokeWidth() < 2) {
95 drawFat(canvas, path, paint, index);
101 if (false) { // debugging variant that draws a single element
103 bool antialias = true;
106 butt.setAntiAlias(antialias);
107 butt.setStyle(SkPaint::kStroke_Style);
108 butt.setStrokeWidth(width);
111 round.setStrokeCap(SkPaint::kRound_Cap);
112 drawPaths(round, 1 << 7);
116 SkScalar widths[] = { 0, .999f, 1, 1.001f, 20 };
117 bool aliases[] = { false, true };
118 for (bool antialias : aliases) {
120 for (SkScalar width : widths) {
123 butt.setAntiAlias(antialias);
124 butt.setStyle(SkPaint::kStroke_Style);
125 butt.setStrokeWidth(width);
129 round.setStrokeCap(SkPaint::kRound_Cap);
130 drawPaths(round, -1);
132 SkPaint square(butt);
133 square.setStrokeCap(SkPaint::kSquare_Cap);
134 drawPaths(square, -1);
136 canvas->translate(220, 0);
139 canvas->translate(0, 210);
144 void drawFat(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, int index) {
145 const SkScalar scale = 10;
146 SkRect bounds = path.getBounds();
148 offscreen.allocN32Pixels(SkScalarRoundToInt(bounds.width() + 4),
149 SkScalarRoundToInt(bounds.height() + 4));
150 offscreen.eraseColor(SK_ColorWHITE);
151 SkScalar pathX = bounds.fLeft - 2;
152 SkScalar pathY = bounds.fTop - 2;
153 SkMatrix cMatrix = canvas->getTotalMatrix();
154 if (!canvas->readPixels(offscreen, SkScalarRoundToInt(pathX + cMatrix.getTranslateX()),
155 SkScalarRoundToInt(pathY + cMatrix.getTranslateY()))) {
162 clipM.preScale(scale, scale);
163 clipM.postTranslate(bounds.fLeft - 17, bounds.fTop - 24.5f + 420);
166 fClipL.transform(clipM, &clip);
168 fClipS.transform(clipM, &clip);
170 canvas->clipPath(clip, true);
171 canvas->scale(scale, scale);
172 canvas->drawBitmap(offscreen, (bounds.fLeft - 17) / scale,
173 (bounds.fTop - 20 + 420) / scale);
176 if (bounds.width() > 20) {
179 clipM.preScale(scale, scale);
180 clipM.postTranslate(bounds.fLeft - 17 - 275, bounds.fTop - 24.5f + 420);
182 fClipR.transform(clipM, &clip);
183 canvas->clipPath(clip, true);
184 canvas->scale(10.f, 10.f);
185 canvas->drawBitmap(offscreen, (bounds.fLeft - 17 - 275
186 + (index >= 5 ? 5 : 0)) / scale, (bounds.fTop - 20 + 420) / scale);
193 ///////////////////////////////////////////////////////////////////////////////
195 DEF_GM( return new StrokeZeroGM(); )