OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2015 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 |
| 11 #define WIDTH 400 |
| 12 #define HEIGHT 600 |
| 13 |
| 14 namespace { |
| 15 // Concave test |
| 16 void test_concave(SkCanvas* canvas, const SkPaint& paint) { |
| 17 SkPath path; |
| 18 canvas->translate(0, 0); |
| 19 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 20 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 21 path.lineTo(SkIntToScalar(30), SkIntToScalar(30)); |
| 22 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 23 canvas->drawPath(path, paint); |
| 24 } |
| 25 |
| 26 // Reverse concave test |
| 27 void test_reverse_concave(SkCanvas* canvas, const SkPaint& paint) { |
| 28 SkPath path; |
| 29 canvas->save(); |
| 30 canvas->translate(100, 0); |
| 31 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 32 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 33 path.lineTo(SkIntToScalar(30), SkIntToScalar(30)); |
| 34 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 35 canvas->drawPath(path, paint); |
| 36 canvas->restore(); |
| 37 } |
| 38 |
| 39 // Bowtie (intersection) |
| 40 void test_bowtie(SkCanvas* canvas, const SkPaint& paint) { |
| 41 SkPath path; |
| 42 canvas->save(); |
| 43 canvas->translate(200, 0); |
| 44 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 45 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 46 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 47 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 48 canvas->drawPath(path, paint); |
| 49 canvas->restore(); |
| 50 } |
| 51 |
| 52 // "fake" bowtie (concave, but no intersection) |
| 53 void test_fake_bowtie(SkCanvas* canvas, const SkPaint& paint) { |
| 54 SkPath path; |
| 55 canvas->save(); |
| 56 canvas->translate(300, 0); |
| 57 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 58 path.lineTo(SkIntToScalar(50), SkIntToScalar(40)); |
| 59 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 60 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 61 path.lineTo(SkIntToScalar(50), SkIntToScalar(60)); |
| 62 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 63 canvas->drawPath(path, paint); |
| 64 canvas->restore(); |
| 65 } |
| 66 |
| 67 // Fish test (intersection/concave) |
| 68 void test_fish(SkCanvas* canvas, const SkPaint& paint) { |
| 69 SkPath path; |
| 70 canvas->save(); |
| 71 canvas->translate(0, 100); |
| 72 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 73 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 74 path.lineTo(SkIntToScalar(70), SkIntToScalar(50)); |
| 75 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 76 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 77 path.lineTo(SkIntToScalar(0), SkIntToScalar(50)); |
| 78 canvas->drawPath(path, paint); |
| 79 canvas->restore(); |
| 80 } |
| 81 |
| 82 // Collinear edges |
| 83 void test_collinear_edges(SkCanvas* canvas, const SkPaint& paint) { |
| 84 SkPath path; |
| 85 canvas->save(); |
| 86 canvas->translate(100, 100); |
| 87 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 88 path.lineTo(SkIntToScalar(50), SkIntToScalar(20)); |
| 89 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 90 path.lineTo(SkIntToScalar(50), SkIntToScalar(80)); |
| 91 canvas->drawPath(path, paint); |
| 92 canvas->restore(); |
| 93 } |
| 94 |
| 95 // Square polygon with a square hole. |
| 96 void test_hole(SkCanvas* canvas, const SkPaint& paint) { |
| 97 SkPath path; |
| 98 canvas->save(); |
| 99 canvas->translate(200, 100); |
| 100 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 101 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 102 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 103 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 104 path.moveTo(SkIntToScalar(30), SkIntToScalar(30)); |
| 105 path.lineTo(SkIntToScalar(30), SkIntToScalar(70)); |
| 106 path.lineTo(SkIntToScalar(70), SkIntToScalar(70)); |
| 107 path.lineTo(SkIntToScalar(70), SkIntToScalar(30)); |
| 108 canvas->drawPath(path, paint); |
| 109 canvas->restore(); |
| 110 } |
| 111 |
| 112 // Star test (self-intersecting) |
| 113 void test_star(SkCanvas* canvas, const SkPaint& paint) { |
| 114 SkPath path; |
| 115 canvas->save(); |
| 116 canvas->translate(300, 100); |
| 117 path.moveTo(30, 20); |
| 118 path.lineTo(50, 80); |
| 119 path.lineTo(70, 20); |
| 120 path.lineTo(20, 57); |
| 121 path.lineTo(80, 57); |
| 122 path.close(); |
| 123 canvas->drawPath(path, paint); |
| 124 canvas->restore(); |
| 125 } |
| 126 |
| 127 // Stairstep with repeated vert (intersection) |
| 128 void test_stairstep(SkCanvas* canvas, const SkPaint& paint) { |
| 129 SkPath path; |
| 130 canvas->save(); |
| 131 canvas->translate(0, 200); |
| 132 path.moveTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 133 path.lineTo(SkIntToScalar(50), SkIntToScalar(20)); |
| 134 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 135 path.lineTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 136 path.lineTo(SkIntToScalar(20), SkIntToScalar(50)); |
| 137 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 138 canvas->drawPath(path, paint); |
| 139 canvas->restore(); |
| 140 } |
| 141 |
| 142 void test_stairstep2(SkCanvas* canvas, const SkPaint& paint) { |
| 143 SkPath path; |
| 144 canvas->save(); |
| 145 canvas->translate(100, 200); |
| 146 path.moveTo(20, 60); |
| 147 path.lineTo(35, 80); |
| 148 path.lineTo(50, 60); |
| 149 path.lineTo(65, 80); |
| 150 path.lineTo(80, 60); |
| 151 canvas->drawPath(path, paint); |
| 152 canvas->restore(); |
| 153 } |
| 154 |
| 155 // Overlapping segments |
| 156 void test_overlapping(SkCanvas* canvas, const SkPaint& paint) { |
| 157 SkPath path; |
| 158 canvas->save(); |
| 159 canvas->translate(200, 200); |
| 160 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 161 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 162 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 163 path.lineTo(SkIntToScalar(80), SkIntToScalar(30)); |
| 164 canvas->drawPath(path, paint); |
| 165 canvas->restore(); |
| 166 } |
| 167 |
| 168 // Monotone test 1 (point in the middle) |
| 169 void test_monotone_1(SkCanvas* canvas, const SkPaint& paint) { |
| 170 SkPath path; |
| 171 canvas->save(); |
| 172 canvas->translate(0, 300); |
| 173 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 174 path.quadTo(SkIntToScalar(20), SkIntToScalar(50), |
| 175 SkIntToScalar(80), SkIntToScalar(50)); |
| 176 path.quadTo(SkIntToScalar(20), SkIntToScalar(50), |
| 177 SkIntToScalar(20), SkIntToScalar(80)); |
| 178 canvas->drawPath(path, paint); |
| 179 canvas->restore(); |
| 180 } |
| 181 |
| 182 // Monotone test 2 (point at the top) |
| 183 void test_monotone_2(SkCanvas* canvas, const SkPaint& paint) { |
| 184 SkPath path; |
| 185 canvas->save(); |
| 186 canvas->translate(100, 300); |
| 187 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 188 path.lineTo(SkIntToScalar(80), SkIntToScalar(30)); |
| 189 path.quadTo(SkIntToScalar(20), SkIntToScalar(20), |
| 190 SkIntToScalar(20), SkIntToScalar(80)); |
| 191 canvas->drawPath(path, paint); |
| 192 canvas->restore(); |
| 193 } |
| 194 |
| 195 // Monotone test 3 (point at the bottom) |
| 196 void test_monotone_3(SkCanvas* canvas, const SkPaint& paint) { |
| 197 SkPath path; |
| 198 canvas->save(); |
| 199 canvas->translate(200, 300); |
| 200 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 201 path.lineTo(SkIntToScalar(80), SkIntToScalar(70)); |
| 202 path.quadTo(SkIntToScalar(20), SkIntToScalar(80), |
| 203 SkIntToScalar(20), SkIntToScalar(20)); |
| 204 canvas->drawPath(path, paint); |
| 205 canvas->restore(); |
| 206 } |
| 207 |
| 208 // Monotone test 4 (merging of two monotones) |
| 209 void test_monotone_4(SkCanvas* canvas, const SkPaint& paint) { |
| 210 SkPath path; |
| 211 canvas->save(); |
| 212 canvas->translate(300, 300); |
| 213 path.moveTo(80, 25); |
| 214 path.lineTo(50, 39); |
| 215 path.lineTo(20, 25); |
| 216 path.lineTo(40, 45); |
| 217 path.lineTo(70, 50); |
| 218 path.lineTo(80, 80); |
| 219 canvas->drawPath(path, paint); |
| 220 canvas->restore(); |
| 221 } |
| 222 |
| 223 // Monotone test 5 (aborted merging of two monotones) |
| 224 void test_monotone_5(SkCanvas* canvas, const SkPaint& paint) { |
| 225 SkPath path; |
| 226 canvas->save(); |
| 227 canvas->translate(0, 400); |
| 228 path.moveTo(50, 20); |
| 229 path.lineTo(80, 80); |
| 230 path.lineTo(50, 50); |
| 231 path.lineTo(20, 80); |
| 232 canvas->drawPath(path, paint); |
| 233 canvas->restore(); |
| 234 } |
| 235 // Degenerate intersection test |
| 236 void test_degenerate(SkCanvas* canvas, const SkPaint& paint) { |
| 237 SkPath path; |
| 238 canvas->save(); |
| 239 canvas->translate(100, 400); |
| 240 path.moveTo(50, 20); |
| 241 path.lineTo(70, 30); |
| 242 path.lineTo(20, 50); |
| 243 path.moveTo(50, 20); |
| 244 path.lineTo(80, 80); |
| 245 path.lineTo(50, 80); |
| 246 canvas->drawPath(path, paint); |
| 247 canvas->restore(); |
| 248 } |
| 249 // Two triangles with a coincident edge. |
| 250 void test_coincident_edge(SkCanvas* canvas, const SkPaint& paint) { |
| 251 SkPath path; |
| 252 canvas->save(); |
| 253 canvas->translate(200, 400); |
| 254 |
| 255 path.moveTo(80, 20); |
| 256 path.lineTo(80, 80); |
| 257 path.lineTo(20, 80); |
| 258 |
| 259 path.moveTo(20, 20); |
| 260 path.lineTo(80, 80); |
| 261 path.lineTo(20, 80); |
| 262 |
| 263 canvas->drawPath(path, paint); |
| 264 canvas->restore(); |
| 265 } |
| 266 // Bowtie with a coincident triangle (one triangle vertex coincident with the |
| 267 // bowtie's intersection). |
| 268 void test_bowtie_coincident_triangle(SkCanvas* canvas, const SkPaint& paint) { |
| 269 SkPath path; |
| 270 canvas->save(); |
| 271 canvas->translate(300, 400); |
| 272 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 273 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 274 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 275 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 276 path.moveTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 277 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 278 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 279 canvas->drawPath(path, paint); |
| 280 canvas->restore(); |
| 281 } |
| 282 |
| 283 // Coincident edges (big ones first, coincident vert on top). |
| 284 void test_coincident_edges_1(SkCanvas* canvas, const SkPaint& paint) { |
| 285 SkPath path; |
| 286 canvas->save(); |
| 287 canvas->translate(0, 500); |
| 288 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 289 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 290 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 291 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 292 path.lineTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 293 path.lineTo(SkIntToScalar(20), SkIntToScalar(50)); |
| 294 canvas->drawPath(path, paint); |
| 295 canvas->restore(); |
| 296 } |
| 297 // Coincident edges (small ones first, coincident vert on top). |
| 298 void test_coincident_edges_2(SkCanvas* canvas, const SkPaint& paint) { |
| 299 SkPath path; |
| 300 canvas->save(); |
| 301 canvas->translate(100, 500); |
| 302 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 303 path.lineTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 304 path.lineTo(SkIntToScalar(20), SkIntToScalar(50)); |
| 305 path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 306 path.lineTo(SkIntToScalar(80), SkIntToScalar(80)); |
| 307 path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 308 canvas->drawPath(path, paint); |
| 309 canvas->restore(); |
| 310 } |
| 311 // Coincident edges (small ones first, coincident vert on bottom). |
| 312 void test_coincident_edges_3(SkCanvas* canvas, const SkPaint& paint) { |
| 313 SkPath path; |
| 314 canvas->save(); |
| 315 canvas->translate(200, 500); |
| 316 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 317 path.lineTo(SkIntToScalar(20), SkIntToScalar(50)); |
| 318 path.lineTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 319 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 320 path.lineTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 321 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 322 canvas->drawPath(path, paint); |
| 323 canvas->restore(); |
| 324 } |
| 325 // Coincident edges (big ones first, coincident vert on bottom). |
| 326 void test_coincident_edges_4(SkCanvas* canvas, const SkPaint& paint) { |
| 327 SkPath path; |
| 328 canvas->save(); |
| 329 canvas->translate(300, 500); |
| 330 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 331 path.lineTo(SkIntToScalar(20), SkIntToScalar(20)); |
| 332 path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); |
| 333 path.moveTo(SkIntToScalar(20), SkIntToScalar(80)); |
| 334 path.lineTo(SkIntToScalar(20), SkIntToScalar(50)); |
| 335 path.lineTo(SkIntToScalar(50), SkIntToScalar(50)); |
| 336 canvas->drawPath(path, paint); |
| 337 canvas->restore(); |
| 338 } |
| 339 |
| 340 }; |
| 341 |
| 342 class ConcavePathsGM : public skiagm::GM { |
| 343 public: |
| 344 ConcavePathsGM() {} |
| 345 |
| 346 protected: |
| 347 SkString onShortName() SK_OVERRIDE { |
| 348 return SkString("concavepaths"); |
| 349 } |
| 350 |
| 351 SkISize onISize() SK_OVERRIDE { |
| 352 return SkISize::Make(WIDTH, HEIGHT); |
| 353 } |
| 354 |
| 355 void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
| 356 SkPaint paint; |
| 357 |
| 358 paint.setAntiAlias(true); |
| 359 paint.setStyle(SkPaint::kFill_Style); |
| 360 |
| 361 test_concave(canvas, paint); |
| 362 test_reverse_concave(canvas, paint); |
| 363 test_bowtie(canvas, paint); |
| 364 test_fake_bowtie(canvas, paint); |
| 365 test_fish(canvas, paint); |
| 366 test_collinear_edges(canvas, paint); |
| 367 test_hole(canvas, paint); |
| 368 test_star(canvas, paint); |
| 369 test_stairstep(canvas, paint); |
| 370 test_stairstep2(canvas, paint); |
| 371 test_overlapping(canvas, paint); |
| 372 test_monotone_1(canvas, paint); |
| 373 test_monotone_2(canvas, paint); |
| 374 test_monotone_3(canvas, paint); |
| 375 test_monotone_4(canvas, paint); |
| 376 test_monotone_5(canvas, paint); |
| 377 test_degenerate(canvas, paint); |
| 378 test_coincident_edge(canvas, paint); |
| 379 test_bowtie_coincident_triangle(canvas, paint); |
| 380 test_coincident_edges_1(canvas, paint); |
| 381 test_coincident_edges_2(canvas, paint); |
| 382 test_coincident_edges_3(canvas, paint); |
| 383 test_coincident_edges_4(canvas, paint); |
| 384 } |
| 385 |
| 386 private: |
| 387 typedef skiagm::GM INHERITED; |
| 388 }; |
| 389 |
| 390 static skiagm::GM* F0(void*) { return new ConcavePathsGM; } |
| 391 static skiagm::GMRegistry R0(F0); |
OLD | NEW |