1 /* 2 * Copyright 2017 Google Inc. 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.h" 9 #include "SkCanvas.h" 10 #include "SkPath.h" 11 12 namespace { 13 // Test thin stroked rect (stroked "by hand", not by stroking). 14 void draw_thin_stroked_rect(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 15 SkPath path; 16 path.moveTo(10 + width, 10 + width); 17 path.lineTo(40, 10 + width); 18 path.lineTo(40, 20); 19 path.lineTo(10 + width, 20); 20 path.moveTo(10, 10); 21 path.lineTo(10, 20 + width); 22 path.lineTo(40 + width, 20 + width); 23 path.lineTo(40 + width, 10); 24 canvas->drawPath(path, paint); 25 } 26 27 void draw_thin_right_angle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 28 SkPath path; 29 path.moveTo(10 + width, 10 + width); 30 path.lineTo(40, 10 + width); 31 path.lineTo(40, 20); 32 path.lineTo(40 + width, 20 + width); 33 path.lineTo(40 + width, 10); 34 path.lineTo(10, 10); 35 canvas->drawPath(path, paint); 36 } 37 38 // Test thin horizontal line (<1 pixel) which should give lower alpha. 39 void draw_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 40 SkPath path; 41 path.moveTo(20, 10); 42 path.lineTo(80, 10); 43 path.lineTo(80, 10 + width); 44 path.lineTo(30, 10 + width); 45 path.lineTo(30, 20); 46 path.lineTo(20, 20); 47 canvas->drawPath(path, paint); 48 } 49 50 // Test thin lines between two filled regions. The outer edges overlap, but 51 // there are no inverted edges to fix. 52 void draw_barbell(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 53 SkScalar offset = width * 0.5f; 54 SkPath path; 55 path.moveTo(30, 5); 56 path.lineTo(40 - offset, 15 - offset); 57 path.lineTo(60 + offset, 15 - offset); 58 path.lineTo(70, 5); 59 path.lineTo(70, 25); 60 path.lineTo(60 + offset, 15 + offset); 61 path.lineTo(40 - offset, 15 + offset); 62 path.lineTo(30, 25); 63 canvas->drawPath(path, paint); 64 } 65 66 // Test a thin rectangle and triangle. The top and bottom inner edges of the 67 // rectangle and all inner edges of the triangle invert on stroking. 68 void draw_thin_rect_and_triangle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 69 SkPath path; 70 path.moveTo(30, 5); 71 path.lineTo(30 + width, 5); 72 path.lineTo(30 + width, 25); 73 path.lineTo(30, 25); 74 path.moveTo(40, 5); 75 path.lineTo(40 + width, 5); 76 path.lineTo(40, 25); 77 canvas->drawPath(path, paint); 78 } 79 80 // Two triangles joined by a very thin bridge. The tiny triangle formed 81 // by the inner edges at the bridge is inverted. 82 // (These are actually now more phat pants than hipster pants.) 83 void draw_hipster_pants(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 84 SkPath path; 85 path.moveTo(10, 10); 86 path.lineTo(10, 20); 87 path.lineTo(50, 10 + width); 88 path.lineTo(90, 20); 89 path.lineTo(90, 10); 90 canvas->drawPath(path, paint); 91 } 92 93 // A thin z-shape whose interior inverts on stroking. The top and bottom inner edges invert, and 94 // the connector edges at the "elbows" intersect the inner edges. 95 void draw_skinny_snake(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 96 SkPath path; 97 path.moveTo(20 + width, 10); 98 path.lineTo(20 + width, 20); 99 path.lineTo(10 + width, 30); 100 path.lineTo(10 + width, 40); 101 path.lineTo(10 - width, 40); 102 path.lineTo(10 - width, 30); 103 path.lineTo(20 - width, 20); 104 path.lineTo(20 - width, 10); 105 canvas->drawPath(path, paint); 106 } 107 108 // Test pointy features whose outer edges extend far to the right on stroking. 109 void draw_pointy_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 110 SkPath path; 111 path.moveTo(20, 10); 112 path.lineTo(80, 10 + width * 0.5); 113 path.lineTo(30, 10 + width); 114 path.lineTo(30, 20); 115 path.lineTo(20, 20); 116 canvas->drawPath(path, paint); 117 } 118 119 void draw_small_i(SkCanvas* canvas, const SkPaint& paint, SkScalar width) { 120 SkPath path; 121 path.moveTo(1.25 - width, 18.75 + width); 122 path.lineTo(1.25 - width, 12.25 - width); 123 path.lineTo(2.50 + width, 12.25 - width); 124 path.lineTo(2.50 + width, 18.75 + width); 125 path.moveTo(1.25 - width, 11.75 + width); 126 path.lineTo(1.25 - width, 10.25 - width); 127 path.lineTo(2.50 + width, 10.25 - width); 128 path.lineTo(2.50 + width, 11.75 + width); 129 canvas->drawPath(path, paint); 130 } 131 132 133 134 }; 135 136 DEF_SIMPLE_GM(thinconcavepaths, canvas, 550, 400) { 137 SkPaint paint; 138 139 paint.setAntiAlias(true); 140 paint.setStyle(SkPaint::kFill_Style); 141 142 canvas->save(); 143 for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) { 144 draw_thin_stroked_rect(canvas, paint, width); 145 canvas->translate(0, 25); 146 } 147 canvas->restore(); 148 canvas->translate(50, 0); 149 canvas->save(); 150 for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) { 151 draw_thin_right_angle(canvas, paint, width); 152 canvas->translate(0, 25); 153 } 154 canvas->restore(); 155 canvas->translate(40, 0); 156 canvas->save(); 157 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 158 draw_golf_club(canvas, paint, width); 159 canvas->translate(0, 30); 160 } 161 canvas->restore(); 162 canvas->translate(70, 0); 163 canvas->save(); 164 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 165 draw_thin_rect_and_triangle(canvas, paint, width); 166 canvas->translate(0, 30); 167 } 168 canvas->restore(); 169 canvas->translate(30, 0); 170 canvas->save(); 171 172 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 173 draw_barbell(canvas, paint, width); 174 canvas->translate(0, 30); 175 } 176 canvas->restore(); 177 canvas->translate(80, 0); 178 canvas->save(); 179 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 180 draw_hipster_pants(canvas, paint, width); 181 canvas->translate(0, 30); 182 } 183 canvas->restore(); 184 canvas->translate(100, 0); 185 canvas->save(); 186 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 187 draw_skinny_snake(canvas, paint, width); 188 canvas->translate(0, 30); 189 } 190 canvas->restore(); 191 canvas->translate(30, 0); 192 canvas->save(); 193 for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) { 194 draw_pointy_golf_club(canvas, paint, width); 195 canvas->translate(0, 30); 196 } 197 canvas->restore(); 198 canvas->translate(100, 0); 199 canvas->save(); 200 for (SkScalar width = 0.0f; width < 0.5f; width += 0.05f) { 201 draw_small_i(canvas, paint, width); 202 canvas->translate(0, 30); 203 } 204 canvas->restore(); 205 canvas->translate(100, 0); 206 } 207