Home | History | Annotate | Download | only in gm
      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