b2c4ea6219
What is left of the SkView system is used only by samples or viewer. As a result, move it out of the Skia source tree and re-organize so it is a bit easier to understand and use more shared code. Move samplecode/ClockFaceView.cpp to samplecode/SampleTextEffects.cpp, sice that's what's actually in it. Move SkAnimTimer.h to tools/timer, since it's actually shared between gm and samples. Change-Id: I55dafd94c64e4f930ddbd19168e0f812af86c455 Reviewed-on: https://skia-review.googlesource.com/146161 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ben Wagner <bungeman@google.com>
205 lines
4.9 KiB
C++
205 lines
4.9 KiB
C++
/*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
#include "Sample.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkPath.h"
|
|
|
|
#include <iostream>
|
|
#include <cmath>
|
|
|
|
#define PI SK_ScalarPI
|
|
|
|
#define LIN_SEGMENTS 10
|
|
|
|
class OverstrokeView : public Sample {
|
|
public:
|
|
SkScalar fStroke;
|
|
int fPathType; // super lazy enum
|
|
bool fClosePath;
|
|
bool fDrawFillPath;
|
|
bool fDumpHex;
|
|
OverstrokeView() {
|
|
fStroke = 5;
|
|
fPathType = 0;
|
|
fClosePath = false;
|
|
fDrawFillPath = false;
|
|
fDumpHex = false;
|
|
this->setBGColor(0xFFFFFFFF);
|
|
}
|
|
|
|
protected:
|
|
bool onQuery(Sample::Event* evt) override {
|
|
if (Sample::TitleQ(*evt)) {
|
|
Sample::TitleR(evt, "PathOverstroke");
|
|
return true;
|
|
}
|
|
SkUnichar uni;
|
|
if (Sample::CharQ(*evt, &uni)) {
|
|
switch (uni) {
|
|
case ',':
|
|
fStroke += 1.0;
|
|
return true;
|
|
case '.':
|
|
fStroke -= 1.0;
|
|
return true;
|
|
case 'x':
|
|
fPathType = (fPathType + 1) % 4;
|
|
return true;
|
|
case 'c':
|
|
fClosePath = !fClosePath;
|
|
return true;
|
|
case 'f':
|
|
fDrawFillPath = !fDrawFillPath;
|
|
return true;
|
|
case 'D':
|
|
fDumpHex = !fDumpHex;
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return this->INHERITED::onQuery(evt);
|
|
}
|
|
|
|
SkPath quadPath(SkPoint p1, SkPoint p2) {
|
|
SkASSERT(p1.y() == p2.y());
|
|
|
|
SkPath path;
|
|
path.moveTo(p1);
|
|
path.lineTo(p2);
|
|
|
|
SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);
|
|
|
|
path.quadTo(p3, p1);
|
|
|
|
return path;
|
|
}
|
|
|
|
SkPath cubicPath(SkPoint p1, SkPoint p2) {
|
|
SkASSERT(p1.y() == p2.y());
|
|
|
|
SkPath path;
|
|
path.moveTo(p1);
|
|
|
|
SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f);
|
|
SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f);
|
|
|
|
path.cubicTo(p3, p4, p2);
|
|
|
|
return path;
|
|
}
|
|
|
|
SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
|
|
SkASSERT(p1.y() == p2.y());
|
|
|
|
SkPath path;
|
|
path.moveTo(p1);
|
|
path.lineTo(p2);
|
|
|
|
SkPoint pt;
|
|
|
|
for (int i = 0; i < LIN_SEGMENTS; i++) {
|
|
float theta = i * PI / (LIN_SEGMENTS);
|
|
SkScalar x = 65 + 15 * cos(theta);
|
|
SkScalar y = 50 - 15 * sin(theta);
|
|
pt = SkPoint::Make(x, y);
|
|
path.lineTo(pt);
|
|
}
|
|
path.lineTo(p1);
|
|
|
|
return path;
|
|
}
|
|
|
|
SkPath rectPath(SkPoint p1) {
|
|
SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
|
|
SkPath path;
|
|
path.addRect(r);
|
|
|
|
return path;
|
|
}
|
|
|
|
void onDrawContent(SkCanvas* canvas) override {
|
|
const float SCALE = 1;
|
|
|
|
canvas->translate(30, 40);
|
|
canvas->scale(SCALE, SCALE);
|
|
|
|
SkPoint p1 = SkPoint::Make(50, 50);
|
|
SkPoint p2 = SkPoint::Make(80, 50);
|
|
|
|
SkPath path;
|
|
switch (fPathType) {
|
|
case 0:
|
|
path = quadPath(p1, p2);
|
|
break;
|
|
case 1:
|
|
path = cubicPath(p1, p2);
|
|
break;
|
|
case 2:
|
|
path = rectPath(p1);
|
|
break;
|
|
case 3:
|
|
path = linSemicirclePath(p1, p2);
|
|
break;
|
|
default:
|
|
path = quadPath(p1, p2);
|
|
break;
|
|
}
|
|
|
|
if (fClosePath) {
|
|
path.close();
|
|
}
|
|
|
|
SkPaint p;
|
|
p.setColor(SK_ColorRED);
|
|
p.setAntiAlias(true);
|
|
p.setStyle(SkPaint::kStroke_Style);
|
|
p.setStrokeWidth(fStroke);
|
|
|
|
canvas->drawPath(path, p);
|
|
|
|
if (fDumpHex) {
|
|
std::cerr << "path dumpHex" << std::endl;
|
|
path.dumpHex();
|
|
}
|
|
|
|
SkPaint hairp;
|
|
hairp.setColor(SK_ColorBLACK);
|
|
hairp.setAntiAlias(true);
|
|
hairp.setStyle(SkPaint::kStroke_Style);
|
|
|
|
if (fDrawFillPath) {
|
|
SkPath fillpath;
|
|
p.getFillPath(path, &fillpath);
|
|
|
|
canvas->drawPath(fillpath, hairp);
|
|
|
|
if (fDumpHex) {
|
|
std::cerr << "fillpath dumpHex" << std::endl;
|
|
fillpath.dumpHex();
|
|
}
|
|
}
|
|
|
|
if (fDumpHex) {
|
|
std::cerr << std::endl;
|
|
|
|
fDumpHex = false;
|
|
}
|
|
|
|
// draw original path with green hairline
|
|
hairp.setColor(SK_ColorGREEN);
|
|
canvas->drawPath(path, hairp);
|
|
}
|
|
|
|
private:
|
|
typedef Sample INHERITED;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
DEF_SAMPLE( return new OverstrokeView(); )
|