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