19bd4c693020bb440464ae12ae05e8e8f97568ee0hstern/* 29bd4c693020bb440464ae12ae05e8e8f97568ee0hstern * Copyright 2016 Google Inc. 39bd4c693020bb440464ae12ae05e8e8f97568ee0hstern * 49bd4c693020bb440464ae12ae05e8e8f97568ee0hstern * Use of this source code is governed by a BSD-style license that can be 59bd4c693020bb440464ae12ae05e8e8f97568ee0hstern * found in the LICENSE file. 69bd4c693020bb440464ae12ae05e8e8f97568ee0hstern */ 79bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#include "SampleCode.h" 89bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#include "SkView.h" 99bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#include "SkCanvas.h" 109bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#include "SkPath.h" 119bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 12e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern#include <iostream> 139bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#include <cmath> 149bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 159bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#define PI SK_ScalarPI 169bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 179bd4c693020bb440464ae12ae05e8e8f97568ee0hstern#define LIN_SEGMENTS 10 189bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 199bd4c693020bb440464ae12ae05e8e8f97568ee0hsternclass OverstrokeView : public SampleView { 209bd4c693020bb440464ae12ae05e8e8f97568ee0hstern public: 219bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkScalar fStroke; 229bd4c693020bb440464ae12ae05e8e8f97568ee0hstern int fPathType; // super lazy enum 239bd4c693020bb440464ae12ae05e8e8f97568ee0hstern bool fClosePath; 249bd4c693020bb440464ae12ae05e8e8f97568ee0hstern bool fDrawFillPath; 25e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern bool fDumpHex; 269bd4c693020bb440464ae12ae05e8e8f97568ee0hstern OverstrokeView() { 279bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fStroke = 5; 289bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fPathType = 0; 299bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fClosePath = false; 309bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fDrawFillPath = false; 31e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern fDumpHex = false; 329bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->setBGColor(0xFFFFFFFF); 339bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 349bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 359bd4c693020bb440464ae12ae05e8e8f97568ee0hstern protected: 369bd4c693020bb440464ae12ae05e8e8f97568ee0hstern bool onQuery(SkEvent* evt) override { 379bd4c693020bb440464ae12ae05e8e8f97568ee0hstern if (SampleCode::TitleQ(*evt)) { 389bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SampleCode::TitleR(evt, "PathOverstroke"); 399bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 409bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 419bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkUnichar uni; 429bd4c693020bb440464ae12ae05e8e8f97568ee0hstern if (SampleCode::CharQ(*evt, &uni)) { 439bd4c693020bb440464ae12ae05e8e8f97568ee0hstern switch (uni) { 449bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case ',': 459bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fStroke += 1.0; 469bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->inval(nullptr); 479bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 489bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case '.': 499bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fStroke -= 1.0; 509bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->inval(nullptr); 519bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 529bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 'x': 53e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern fPathType = (fPathType + 1) % 4; 549bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->inval(nullptr); 559bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 569bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 'c': 579bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fClosePath = !fClosePath; 589bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->inval(nullptr); 599bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 609bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 'f': 619bd4c693020bb440464ae12ae05e8e8f97568ee0hstern fDrawFillPath = !fDrawFillPath; 629bd4c693020bb440464ae12ae05e8e8f97568ee0hstern this->inval(nullptr); 639bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return true; 64e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern case 'D': 65e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern fDumpHex = !fDumpHex; 66e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern this->inval(nullptr); 67e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern return true; 689bd4c693020bb440464ae12ae05e8e8f97568ee0hstern default: 699bd4c693020bb440464ae12ae05e8e8f97568ee0hstern break; 709bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 719bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 729bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return this->INHERITED::onQuery(evt); 739bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 749bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 759bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath quadPath(SkPoint p1, SkPoint p2) { 769bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkASSERT(p1.y() == p2.y()); 779bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 789bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath path; 799bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.moveTo(p1); 809bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.lineTo(p2); 819bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 829bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f); 839bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 849bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.quadTo(p3, p1); 859bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 869bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return path; 879bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 889bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 89e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkPath cubicPath(SkPoint p1, SkPoint p2) { 90e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkASSERT(p1.y() == p2.y()); 91e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 92e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkPath path; 93e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern path.moveTo(p1); 94e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 95e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f); 96e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f); 97e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 98e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern path.cubicTo(p3, p4, p2); 99e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 100e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern return path; 101e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern } 102e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 1039bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath linSemicirclePath(SkPoint p1, SkPoint p2) { 1049bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkASSERT(p1.y() == p2.y()); 1059bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1069bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath path; 1079bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.moveTo(p1); 1089bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.lineTo(p2); 1099bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1109bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPoint pt; 1119bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1129bd4c693020bb440464ae12ae05e8e8f97568ee0hstern for (int i = 0; i < LIN_SEGMENTS; i++) { 1139bd4c693020bb440464ae12ae05e8e8f97568ee0hstern float theta = i * PI / (LIN_SEGMENTS); 1149bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkScalar x = 65 + 15 * cos(theta); 1159bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkScalar y = 50 - 15 * sin(theta); 1169bd4c693020bb440464ae12ae05e8e8f97568ee0hstern pt = SkPoint::Make(x, y); 1179bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.lineTo(pt); 1189bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 1199bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.lineTo(p1); 1209bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1219bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return path; 1229bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 1239bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1249bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath rectPath(SkPoint p1) { 1259bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20); 1269bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath path; 1279bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.addRect(r); 1289bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1299bd4c693020bb440464ae12ae05e8e8f97568ee0hstern return path; 1309bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 1319bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1329bd4c693020bb440464ae12ae05e8e8f97568ee0hstern void onDrawContent(SkCanvas* canvas) override { 1339bd4c693020bb440464ae12ae05e8e8f97568ee0hstern const float SCALE = 1; 1349bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1359bd4c693020bb440464ae12ae05e8e8f97568ee0hstern canvas->translate(30, 40); 1369bd4c693020bb440464ae12ae05e8e8f97568ee0hstern canvas->scale(SCALE, SCALE); 1379bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1389bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPoint p1 = SkPoint::Make(50, 50); 1399bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPoint p2 = SkPoint::Make(80, 50); 1409bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1419bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath path; 1429bd4c693020bb440464ae12ae05e8e8f97568ee0hstern switch (fPathType) { 1439bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 0: 1449bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path = quadPath(p1, p2); 1459bd4c693020bb440464ae12ae05e8e8f97568ee0hstern break; 1469bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 1: 147e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern path = cubicPath(p1, p2); 1489bd4c693020bb440464ae12ae05e8e8f97568ee0hstern break; 1499bd4c693020bb440464ae12ae05e8e8f97568ee0hstern case 2: 1509bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path = rectPath(p1); 1519bd4c693020bb440464ae12ae05e8e8f97568ee0hstern break; 152e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern case 3: 153e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern path = linSemicirclePath(p1, p2); 154e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern break; 1559bd4c693020bb440464ae12ae05e8e8f97568ee0hstern default: 1569bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path = quadPath(p1, p2); 1579bd4c693020bb440464ae12ae05e8e8f97568ee0hstern break; 1589bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 1599bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1609bd4c693020bb440464ae12ae05e8e8f97568ee0hstern if (fClosePath) { 1619bd4c693020bb440464ae12ae05e8e8f97568ee0hstern path.close(); 1629bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 1639bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1649bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPaint p; 1659bd4c693020bb440464ae12ae05e8e8f97568ee0hstern p.setColor(SK_ColorRED); 1669bd4c693020bb440464ae12ae05e8e8f97568ee0hstern p.setAntiAlias(true); 1679bd4c693020bb440464ae12ae05e8e8f97568ee0hstern p.setStyle(SkPaint::kStroke_Style); 1689bd4c693020bb440464ae12ae05e8e8f97568ee0hstern p.setStrokeWidth(fStroke); 1699bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 1709bd4c693020bb440464ae12ae05e8e8f97568ee0hstern canvas->drawPath(path, p); 1719bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 172e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern if (fDumpHex) { 173e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern std::cerr << "path dumpHex" << std::endl; 174e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern path.dumpHex(); 175e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern } 176e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 177e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern SkPaint hairp; 178e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern hairp.setColor(SK_ColorBLACK); 179e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern hairp.setAntiAlias(true); 180e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern hairp.setStyle(SkPaint::kStroke_Style); 181e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 1829bd4c693020bb440464ae12ae05e8e8f97568ee0hstern if (fDrawFillPath) { 1839bd4c693020bb440464ae12ae05e8e8f97568ee0hstern SkPath fillpath; 1849bd4c693020bb440464ae12ae05e8e8f97568ee0hstern p.getFillPath(path, &fillpath); 1859bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 186e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern canvas->drawPath(fillpath, hairp); 1879bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 188e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern if (fDumpHex) { 189e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern std::cerr << "fillpath dumpHex" << std::endl; 190e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern fillpath.dumpHex(); 191e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern } 1929bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 193e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 194e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern if (fDumpHex) { 195e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern std::cerr << std::endl; 196e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 197e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern fDumpHex = false; 198e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern } 199e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern 200e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern // draw original path with green hairline 201e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern hairp.setColor(SK_ColorGREEN); 202e2463ed91ede5e6b38cf3f93205a59f8bc3f3b44hstern canvas->drawPath(path, hairp); 2039bd4c693020bb440464ae12ae05e8e8f97568ee0hstern } 2049bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 2059bd4c693020bb440464ae12ae05e8e8f97568ee0hstern private: 2069bd4c693020bb440464ae12ae05e8e8f97568ee0hstern typedef SampleView INHERITED; 2079bd4c693020bb440464ae12ae05e8e8f97568ee0hstern}; 2089bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 2099bd4c693020bb440464ae12ae05e8e8f97568ee0hstern/////////////////////////////////////////////////////////////////////////////// 2109bd4c693020bb440464ae12ae05e8e8f97568ee0hstern 2119bd4c693020bb440464ae12ae05e8e8f97568ee0hsternstatic SkView* MyFactory() { return new OverstrokeView; } 2129bd4c693020bb440464ae12ae05e8e8f97568ee0hsternstatic SkViewRegister reg(MyFactory); 213