1 /* 2 * Copyright 2016 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 #include "SampleCode.h" 8 #include "SkView.h" 9 #include "SkCanvas.h" 10 #include "SkPath.h" 11 12 #include <iostream> 13 #include <cmath> 14 15 #define PI SK_ScalarPI 16 17 #define LIN_SEGMENTS 10 18 19 class OverstrokeView : public SampleView { 20 public: 21 SkScalar fStroke; 22 int fPathType; // super lazy enum 23 bool fClosePath; 24 bool fDrawFillPath; 25 bool fDumpHex; 26 OverstrokeView() { 27 fStroke = 5; 28 fPathType = 0; 29 fClosePath = false; 30 fDrawFillPath = false; 31 fDumpHex = false; 32 this->setBGColor(0xFFFFFFFF); 33 } 34 35 protected: 36 bool onQuery(SkEvent* evt) override { 37 if (SampleCode::TitleQ(*evt)) { 38 SampleCode::TitleR(evt, "PathOverstroke"); 39 return true; 40 } 41 SkUnichar uni; 42 if (SampleCode::CharQ(*evt, &uni)) { 43 switch (uni) { 44 case ',': 45 fStroke += 1.0; 46 this->inval(nullptr); 47 return true; 48 case '.': 49 fStroke -= 1.0; 50 this->inval(nullptr); 51 return true; 52 case 'x': 53 fPathType = (fPathType + 1) % 4; 54 this->inval(nullptr); 55 return true; 56 case 'c': 57 fClosePath = !fClosePath; 58 this->inval(nullptr); 59 return true; 60 case 'f': 61 fDrawFillPath = !fDrawFillPath; 62 this->inval(nullptr); 63 return true; 64 case 'D': 65 fDumpHex = !fDumpHex; 66 this->inval(nullptr); 67 return true; 68 default: 69 break; 70 } 71 } 72 return this->INHERITED::onQuery(evt); 73 } 74 75 SkPath quadPath(SkPoint p1, SkPoint p2) { 76 SkASSERT(p1.y() == p2.y()); 77 78 SkPath path; 79 path.moveTo(p1); 80 path.lineTo(p2); 81 82 SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f); 83 84 path.quadTo(p3, p1); 85 86 return path; 87 } 88 89 SkPath cubicPath(SkPoint p1, SkPoint p2) { 90 SkASSERT(p1.y() == p2.y()); 91 92 SkPath path; 93 path.moveTo(p1); 94 95 SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f); 96 SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f); 97 98 path.cubicTo(p3, p4, p2); 99 100 return path; 101 } 102 103 SkPath linSemicirclePath(SkPoint p1, SkPoint p2) { 104 SkASSERT(p1.y() == p2.y()); 105 106 SkPath path; 107 path.moveTo(p1); 108 path.lineTo(p2); 109 110 SkPoint pt; 111 112 for (int i = 0; i < LIN_SEGMENTS; i++) { 113 float theta = i * PI / (LIN_SEGMENTS); 114 SkScalar x = 65 + 15 * cos(theta); 115 SkScalar y = 50 - 15 * sin(theta); 116 pt = SkPoint::Make(x, y); 117 path.lineTo(pt); 118 } 119 path.lineTo(p1); 120 121 return path; 122 } 123 124 SkPath rectPath(SkPoint p1) { 125 SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20); 126 SkPath path; 127 path.addRect(r); 128 129 return path; 130 } 131 132 void onDrawContent(SkCanvas* canvas) override { 133 const float SCALE = 1; 134 135 canvas->translate(30, 40); 136 canvas->scale(SCALE, SCALE); 137 138 SkPoint p1 = SkPoint::Make(50, 50); 139 SkPoint p2 = SkPoint::Make(80, 50); 140 141 SkPath path; 142 switch (fPathType) { 143 case 0: 144 path = quadPath(p1, p2); 145 break; 146 case 1: 147 path = cubicPath(p1, p2); 148 break; 149 case 2: 150 path = rectPath(p1); 151 break; 152 case 3: 153 path = linSemicirclePath(p1, p2); 154 break; 155 default: 156 path = quadPath(p1, p2); 157 break; 158 } 159 160 if (fClosePath) { 161 path.close(); 162 } 163 164 SkPaint p; 165 p.setColor(SK_ColorRED); 166 p.setAntiAlias(true); 167 p.setStyle(SkPaint::kStroke_Style); 168 p.setStrokeWidth(fStroke); 169 170 canvas->drawPath(path, p); 171 172 if (fDumpHex) { 173 std::cerr << "path dumpHex" << std::endl; 174 path.dumpHex(); 175 } 176 177 SkPaint hairp; 178 hairp.setColor(SK_ColorBLACK); 179 hairp.setAntiAlias(true); 180 hairp.setStyle(SkPaint::kStroke_Style); 181 182 if (fDrawFillPath) { 183 SkPath fillpath; 184 p.getFillPath(path, &fillpath); 185 186 canvas->drawPath(fillpath, hairp); 187 188 if (fDumpHex) { 189 std::cerr << "fillpath dumpHex" << std::endl; 190 fillpath.dumpHex(); 191 } 192 } 193 194 if (fDumpHex) { 195 std::cerr << std::endl; 196 197 fDumpHex = false; 198 } 199 200 // draw original path with green hairline 201 hairp.setColor(SK_ColorGREEN); 202 canvas->drawPath(path, hairp); 203 } 204 205 private: 206 typedef SampleView INHERITED; 207 }; 208 209 /////////////////////////////////////////////////////////////////////////////// 210 211 static SkView* MyFactory() { return new OverstrokeView; } 212 static SkViewRegister reg(MyFactory); 213