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