1 /* 2 * Copyright 2013 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/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkColor.h" 11 #include "include/core/SkPaint.h" 12 #include "include/core/SkPathBuilder.h" 13 #include "include/core/SkPoint.h" 14 #include "include/core/SkScalar.h" 15 #include "include/core/SkSize.h" 16 #include "include/core/SkString.h" 17 #include "include/core/SkTypes.h" 18 #include "include/private/SkTArray.h" 19 #include "include/utils/SkRandom.h" 20 21 namespace skiagm { 22 23 // This GM tests a grab-bag of convex and concave polygons. They are triangles, 24 // trapezoid, diamond, polygons with lots of edges, several concave polygons... 25 // But rectangles are excluded. 26 class PolygonsGM: public GM { 27 public: PolygonsGM()28 PolygonsGM() {} 29 30 protected: 31 onShortName()32 SkString onShortName() override { 33 return SkString("polygons"); 34 } 35 onISize()36 SkISize onISize() override { 37 int width = kNumPolygons * kCellSize + 40; 38 int height = (kNumJoins * kNumStrokeWidths + kNumExtraStyles) * kCellSize + 40; 39 return SkISize::Make(width, height); 40 } 41 42 // Construct all polygons onOnceBeforeDraw()43 void onOnceBeforeDraw() override { 44 SkPoint p0[] = {{0, 0}, {60, 0}, {90, 40}}; // triangle 45 SkPoint p1[] = {{0, 0}, {0, 40}, {60, 40}, {40, 0}}; // trapezoid 46 SkPoint p2[] = {{0, 0}, {40, 40}, {80, 40}, {40, 0}}; // diamond 47 SkPoint p3[] = {{10, 0}, {50, 0}, {60, 10}, {60, 30}, {50, 40}, 48 {10, 40}, {0, 30}, {0, 10}}; // octagon 49 SkPoint p4[32]; // circle-like polygons with 32-edges. 50 SkPoint p5[] = {{0, 0}, {20, 20}, {0, 40}, {60, 20}}; // concave polygon with 4 edges 51 SkPoint p6[] = {{0, 40}, {0, 30}, {15, 30}, {15, 20}, {30, 20}, 52 {30, 10}, {45, 10}, {45, 0}, {60, 0}, {60, 40}}; // stairs-like polygon 53 SkPoint p7[] = {{0, 20}, {20, 20}, {30, 0}, {40, 20}, {60, 20}, 54 {45, 30}, {55, 50}, {30, 40}, {5, 50}, {15, 30}}; // five-point stars 55 56 for (size_t i = 0; i < SK_ARRAY_COUNT(p4); ++i) { 57 SkScalar angle = 2 * SK_ScalarPI * i / SK_ARRAY_COUNT(p4); 58 p4[i].set(20 * SkScalarCos(angle) + 20, 20 * SkScalarSin(angle) + 20); 59 } 60 61 struct Polygons { 62 SkPoint* fPoints; 63 size_t fPointNum; 64 } pgs[] = { 65 { p0, SK_ARRAY_COUNT(p0) }, 66 { p1, SK_ARRAY_COUNT(p1) }, 67 { p2, SK_ARRAY_COUNT(p2) }, 68 { p3, SK_ARRAY_COUNT(p3) }, 69 { p4, SK_ARRAY_COUNT(p4) }, 70 { p5, SK_ARRAY_COUNT(p5) }, 71 { p6, SK_ARRAY_COUNT(p6) }, 72 { p7, SK_ARRAY_COUNT(p7) } 73 }; 74 75 SkASSERT(SK_ARRAY_COUNT(pgs) == kNumPolygons); 76 for (size_t pgIndex = 0; pgIndex < SK_ARRAY_COUNT(pgs); ++pgIndex) { 77 SkPathBuilder b; 78 b.moveTo(pgs[pgIndex].fPoints[0].fX, 79 pgs[pgIndex].fPoints[0].fY); 80 for (size_t ptIndex = 1; ptIndex < pgs[pgIndex].fPointNum; ++ptIndex) { 81 b.lineTo(pgs[pgIndex].fPoints[ptIndex].fX, 82 pgs[pgIndex].fPoints[ptIndex].fY); 83 } 84 b.close(); 85 fPolygons.push_back(b.detach()); 86 } 87 } 88 89 // Set the location for the current test on the canvas SetLocation(SkCanvas * canvas,int counter,int lineNum)90 static void SetLocation(SkCanvas* canvas, int counter, int lineNum) { 91 SkScalar x = SK_Scalar1 * kCellSize * (counter % lineNum) + 30 + SK_Scalar1 / 4; 92 SkScalar y = SK_Scalar1 * kCellSize * (counter / lineNum) + 30 + 3 * SK_Scalar1 / 4; 93 canvas->translate(x, y); 94 } 95 SetColorAndAlpha(SkPaint * paint,SkRandom * rand)96 static void SetColorAndAlpha(SkPaint* paint, SkRandom* rand) { 97 SkColor color = rand->nextU(); 98 color |= 0xff000000; 99 paint->setColor(color); 100 if (40 == paint->getStrokeWidth()) { 101 paint->setAlpha(0xA0); 102 } 103 } 104 onDraw(SkCanvas * canvas)105 void onDraw(SkCanvas* canvas) override { 106 // Stroke widths are: 107 // 0(may use hairline rendering), 10(common case for stroke-style) 108 // 40(>= geometry width/height, make the contour filled in fact) 109 constexpr int kStrokeWidths[] = {0, 10, 40}; 110 SkASSERT(kNumStrokeWidths == SK_ARRAY_COUNT(kStrokeWidths)); 111 112 constexpr SkPaint::Join kJoins[] = { 113 SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join 114 }; 115 SkASSERT(kNumJoins == SK_ARRAY_COUNT(kJoins)); 116 117 int counter = 0; 118 SkPaint paint; 119 paint.setAntiAlias(true); 120 121 SkRandom rand; 122 // For stroke style painter 123 paint.setStyle(SkPaint::kStroke_Style); 124 for (int join = 0; join < kNumJoins; ++join) { 125 for (int width = 0; width < kNumStrokeWidths; ++width) { 126 for (int i = 0; i < fPolygons.count(); ++i) { 127 canvas->save(); 128 SetLocation(canvas, counter, fPolygons.count()); 129 130 SetColorAndAlpha(&paint, &rand); 131 paint.setStrokeJoin(kJoins[join]); 132 paint.setStrokeWidth(SkIntToScalar(kStrokeWidths[width])); 133 134 canvas->drawPath(fPolygons[i], paint); 135 canvas->restore(); 136 ++counter; 137 } 138 } 139 } 140 141 // For stroke-and-fill style painter and fill style painter 142 constexpr SkPaint::Style kStyles[] = { 143 SkPaint::kStrokeAndFill_Style, SkPaint::kFill_Style 144 }; 145 SkASSERT(kNumExtraStyles == SK_ARRAY_COUNT(kStyles)); 146 147 paint.setStrokeJoin(SkPaint::kMiter_Join); 148 paint.setStrokeWidth(SkIntToScalar(20)); 149 for (int style = 0; style < kNumExtraStyles; ++style) { 150 paint.setStyle(kStyles[style]); 151 for (int i = 0; i < fPolygons.count(); ++i) { 152 canvas->save(); 153 SetLocation(canvas, counter, fPolygons.count()); 154 SetColorAndAlpha(&paint, &rand); 155 canvas->drawPath(fPolygons[i], paint); 156 canvas->restore(); 157 ++counter; 158 } 159 } 160 } 161 162 private: 163 static constexpr int kNumPolygons = 8; 164 static constexpr int kCellSize = 100; 165 static constexpr int kNumExtraStyles = 2; 166 static constexpr int kNumStrokeWidths = 3; 167 static constexpr int kNumJoins = 3; 168 169 SkTArray<SkPath> fPolygons; 170 using INHERITED = GM; 171 }; 172 173 ////////////////////////////////////////////////////////////////////////////// 174 175 DEF_GM(return new PolygonsGM;) 176 177 // see crbug.com/1197461 178 DEF_SIMPLE_GM(conjoined_polygons, canvas, 400, 400) { 179 SkPathBuilder b; 180 b.moveTo(0.f, 120.f); 181 b.lineTo(0.f, 0.f); 182 b.lineTo(50.f, 330.f); 183 b.lineTo(90.f, 0.f); 184 b.lineTo(340.f, 0.f); 185 b.lineTo(90.f, 330.f); 186 b.lineTo(50.f, 330.f); 187 b.close(); 188 189 SkPaint paint; 190 paint.setAntiAlias(true); 191 canvas->drawPath(b.detach(), paint); 192 } 193 194 } // namespace skiagm 195