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 };
    120 
    121 DEF_SIMPLE_GM(thinconcavepaths, canvas, 550, 400) {
    122     SkPaint paint;
    123 
    124     paint.setAntiAlias(true);
    125     paint.setStyle(SkPaint::kFill_Style);
    126 
    127     canvas->save();
    128     for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
    129         draw_thin_stroked_rect(canvas, paint, width);
    130         canvas->translate(0, 25);
    131     }
    132     canvas->restore();
    133     canvas->translate(50, 0);
    134     canvas->save();
    135     for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
    136         draw_thin_right_angle(canvas, paint, width);
    137         canvas->translate(0, 25);
    138     }
    139     canvas->restore();
    140     canvas->translate(40, 0);
    141     canvas->save();
    142     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    143         draw_golf_club(canvas, paint, width);
    144         canvas->translate(0, 30);
    145     }
    146     canvas->restore();
    147     canvas->translate(70, 0);
    148     canvas->save();
    149     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    150         draw_thin_rect_and_triangle(canvas, paint, width);
    151         canvas->translate(0, 30);
    152     }
    153     canvas->restore();
    154     canvas->translate(30, 0);
    155     canvas->save();
    156 
    157     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    158         draw_barbell(canvas, paint, width);
    159         canvas->translate(0, 30);
    160     }
    161     canvas->restore();
    162     canvas->translate(80, 0);
    163     canvas->save();
    164     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    165         draw_hipster_pants(canvas, paint, width);
    166         canvas->translate(0, 30);
    167     }
    168     canvas->restore();
    169     canvas->translate(100, 0);
    170     canvas->save();
    171     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    172         draw_skinny_snake(canvas, paint, width);
    173         canvas->translate(0, 30);
    174     }
    175     canvas->restore();
    176     canvas->translate(30, 0);
    177     canvas->save();
    178     for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
    179         draw_pointy_golf_club(canvas, paint, width);
    180         canvas->translate(0, 30);
    181     }
    182     canvas->restore();
    183     canvas->translate(100, 0);
    184 }
    185