224 lines
6.5 KiB
C++
224 lines
6.5 KiB
C++
|
/*
|
||
|
* Copyright 2017 Google Inc.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license that can be
|
||
|
* found in the LICENSE file.
|
||
|
*/
|
||
|
|
||
|
#include "include/core/SkTypes.h"
|
||
|
|
||
|
#if SK_SUPPORT_GPU
|
||
|
|
||
|
#include "include/core/SkCanvas.h"
|
||
|
#include "include/core/SkFont.h"
|
||
|
#include "include/core/SkPaint.h"
|
||
|
#include "include/core/SkPath.h"
|
||
|
#include "samplecode/Sample.h"
|
||
|
#include "src/core/SkGeometry.h"
|
||
|
|
||
|
enum class VerbType {
|
||
|
kTriangles,
|
||
|
kQuadratics,
|
||
|
kCubics,
|
||
|
kConics
|
||
|
};
|
||
|
|
||
|
static const char* verb_type_name(VerbType verbType) {
|
||
|
switch (verbType) {
|
||
|
case VerbType::kTriangles: return "kTriangles";
|
||
|
case VerbType::kQuadratics: return "kQuadratics";
|
||
|
case VerbType::kCubics: return "kCubics";
|
||
|
case VerbType::kConics: return "kConics";
|
||
|
}
|
||
|
SkUNREACHABLE;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* This sample visualizes simple strokes.
|
||
|
*/
|
||
|
class CCPRGeometryView : public Sample {
|
||
|
void onOnceBeforeDraw() override { this->updatePath(); }
|
||
|
void onDrawContent(SkCanvas*) override;
|
||
|
|
||
|
Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
|
||
|
bool onClick(Sample::Click*) override;
|
||
|
bool onChar(SkUnichar) override;
|
||
|
SkString name() override { return SkString("StrokeVerb"); }
|
||
|
|
||
|
class Click;
|
||
|
|
||
|
void updateAndInval() { this->updatePath(); }
|
||
|
|
||
|
void updatePath();
|
||
|
|
||
|
VerbType fVerbType = VerbType::kCubics;
|
||
|
|
||
|
SkPoint fPoints[4] = {
|
||
|
{100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}};
|
||
|
|
||
|
float fConicWeight = .5;
|
||
|
float fStrokeWidth = 40;
|
||
|
SkPaint::Join fStrokeJoin = SkPaint::kMiter_Join;
|
||
|
SkPaint::Cap fStrokeCap = SkPaint::kButt_Cap;
|
||
|
|
||
|
SkPath fPath;
|
||
|
};
|
||
|
|
||
|
void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
|
||
|
canvas->clear(SK_ColorBLACK);
|
||
|
|
||
|
SkPaint outlinePaint;
|
||
|
outlinePaint.setColor(0xff808080);
|
||
|
outlinePaint.setStyle(SkPaint::kStroke_Style);
|
||
|
outlinePaint.setStrokeWidth(fStrokeWidth);
|
||
|
outlinePaint.setStrokeJoin(fStrokeJoin);
|
||
|
outlinePaint.setStrokeCap(fStrokeCap);
|
||
|
outlinePaint.setAntiAlias(true);
|
||
|
canvas->drawPath(fPath, outlinePaint);
|
||
|
|
||
|
SkString caption;
|
||
|
caption.appendf("VerbType_%s", verb_type_name(fVerbType));
|
||
|
if (VerbType::kCubics == fVerbType) {
|
||
|
caption.appendf(" (%s)", SkCubicTypeName(SkClassifyCubic(fPoints)));
|
||
|
} else if (VerbType::kConics == fVerbType) {
|
||
|
caption.appendf(" (w=%f)", fConicWeight);
|
||
|
}
|
||
|
|
||
|
caption.appendf(" (stroke_width=%f)", fStrokeWidth);
|
||
|
|
||
|
SkPaint pointsPaint;
|
||
|
pointsPaint.setColor(SK_ColorBLUE);
|
||
|
pointsPaint.setStrokeWidth(8);
|
||
|
pointsPaint.setAntiAlias(true);
|
||
|
|
||
|
if (VerbType::kCubics == fVerbType) {
|
||
|
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
|
||
|
} else {
|
||
|
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, fPoints, pointsPaint);
|
||
|
canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, fPoints + 3, pointsPaint);
|
||
|
}
|
||
|
|
||
|
SkFont font(nullptr, 20);
|
||
|
SkPaint captionPaint;
|
||
|
captionPaint.setColor(SK_ColorWHITE);
|
||
|
canvas->drawString(caption, 10, 30, font, captionPaint);
|
||
|
}
|
||
|
|
||
|
void CCPRGeometryView::updatePath() {
|
||
|
fPath.reset();
|
||
|
fPath.moveTo(fPoints[0]);
|
||
|
switch (fVerbType) {
|
||
|
case VerbType::kCubics:
|
||
|
fPath.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
|
||
|
break;
|
||
|
case VerbType::kQuadratics:
|
||
|
fPath.quadTo(fPoints[1], fPoints[3]);
|
||
|
break;
|
||
|
case VerbType::kConics:
|
||
|
fPath.conicTo(fPoints[1], fPoints[3], fConicWeight);
|
||
|
break;
|
||
|
case VerbType::kTriangles:
|
||
|
fPath.lineTo(fPoints[1]);
|
||
|
fPath.lineTo(fPoints[3]);
|
||
|
fPath.close();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class CCPRGeometryView::Click : public Sample::Click {
|
||
|
public:
|
||
|
Click(int ptIdx) : fPtIdx(ptIdx) {}
|
||
|
|
||
|
void doClick(SkPoint points[]) {
|
||
|
if (fPtIdx >= 0) {
|
||
|
points[fPtIdx] += fCurr - fPrev;
|
||
|
} else {
|
||
|
for (int i = 0; i < 4; ++i) {
|
||
|
points[i] += fCurr - fPrev;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
int fPtIdx;
|
||
|
};
|
||
|
|
||
|
Sample::Click* CCPRGeometryView::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
|
||
|
for (int i = 0; i < 4; ++i) {
|
||
|
if (VerbType::kCubics != fVerbType && 2 == i) {
|
||
|
continue;
|
||
|
}
|
||
|
if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) {
|
||
|
return new Click(i);
|
||
|
}
|
||
|
}
|
||
|
return new Click(-1);
|
||
|
}
|
||
|
|
||
|
bool CCPRGeometryView::onClick(Sample::Click* click) {
|
||
|
Click* myClick = (Click*)click;
|
||
|
myClick->doClick(fPoints);
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CCPRGeometryView::onChar(SkUnichar unichar) {
|
||
|
if (unichar >= '1' && unichar <= '4') {
|
||
|
fVerbType = VerbType(unichar - '1');
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
float* valueToScale = nullptr;
|
||
|
if (VerbType::kConics == fVerbType) {
|
||
|
valueToScale = &fConicWeight;
|
||
|
} else {
|
||
|
valueToScale = &fStrokeWidth;
|
||
|
}
|
||
|
if (valueToScale) {
|
||
|
if (unichar == '+') {
|
||
|
*valueToScale *= 2;
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
if (unichar == '+' || unichar == '=') {
|
||
|
*valueToScale *= 5/4.f;
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
if (unichar == '-') {
|
||
|
*valueToScale *= 4/5.f;
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
if (unichar == '_') {
|
||
|
*valueToScale *= .5f;
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
if (unichar == 'D') {
|
||
|
SkDebugf(" SkPoint fPoints[4] = {\n");
|
||
|
SkDebugf(" {%ff, %ff},\n", fPoints[0].x(), fPoints[0].y());
|
||
|
SkDebugf(" {%ff, %ff},\n", fPoints[1].x(), fPoints[1].y());
|
||
|
SkDebugf(" {%ff, %ff},\n", fPoints[2].x(), fPoints[2].y());
|
||
|
SkDebugf(" {%ff, %ff}\n", fPoints[3].x(), fPoints[3].y());
|
||
|
SkDebugf(" };\n");
|
||
|
return true;
|
||
|
}
|
||
|
if (unichar == 'J') {
|
||
|
fStrokeJoin = (SkPaint::Join)((fStrokeJoin + 1) % 3);
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
if (unichar == 'C') {
|
||
|
fStrokeCap = (SkPaint::Cap)((fStrokeCap + 1) % 3);
|
||
|
this->updateAndInval();
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
DEF_SAMPLE(return new CCPRGeometryView;)
|
||
|
|
||
|
#endif // SK_SUPPORT_GPU
|