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