diff --git a/experimental/pathkit/compile.sh b/experimental/pathkit/compile.sh
index 2f66588cc0..fc43301d9a 100755
--- a/experimental/pathkit/compile.sh
+++ b/experimental/pathkit/compile.sh
@@ -44,7 +44,7 @@ fi
# Use -O0 for larger builds (but generally quicker)
# Use -Oz for (much slower, but smaller/faster) production builds
export EMCC_CLOSURE_ARGS="--externs $BASE_DIR/helper_externs.js "
-RELEASE_CONF="-Oz --closure 1 -s EVAL_CTORS=1"
+RELEASE_CONF="-Oz --closure 1 -s EVAL_CTORS=1 --llvm-lto 3"
if [[ $@ == *test* ]]; then
echo "Building a Testing/Profiling build"
RELEASE_CONF="-O2 --profiling -DPATHKIT_TESTING -DSK_RELEASE"
@@ -73,12 +73,19 @@ mkdir -p $BUILD_DIR
em++ $RELEASE_CONF -std=c++14 \
-Iinclude/config \
-Iinclude/core \
+-Iinclude/effects \
+-Iinclude/gpu \
-Iinclude/pathops \
-Iinclude/private \
-Iinclude/utils \
-Isrc/core \
+-Isrc/gpu \
+-Isrc/shaders \
+-Isrc/opts \
+-Isrc/utils \
--bind \
--pre-js $BASE_DIR/helper.js \
+-DWEB_ASSEMBLY=1 \
-fno-rtti -fno-exceptions -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 \
$WASM_CONF \
-s MODULARIZE=1 \
@@ -91,22 +98,40 @@ $WASM_CONF \
-s STRICT=1 \
$OUTPUT \
$BASE_DIR/pathkit_wasm_bindings.cpp \
+src/core/SkAnalyticEdge.cpp \
src/core/SkArenaAlloc.cpp \
+src/core/SkEdge.cpp \
+src/core/SkEdgeBuilder.cpp \
+src/core/SkEdgeClipper.cpp \
+src/core/SkFDot6Constants.cpp \
+src/core/SkFlattenable.cpp \
src/core/SkGeometry.cpp \
+src/core/SkLineClipper.cpp \
src/core/SkMallocPixelRef.cpp \
src/core/SkMath.cpp \
src/core/SkMatrix.cpp \
+src/core/SkOpts.cpp \
+src/core/SkPaint.cpp \
src/core/SkPath.cpp \
+src/core/SkPathEffect.cpp \
+src/core/SkPathMeasure.cpp \
src/core/SkPathRef.cpp \
src/core/SkPoint.cpp \
+src/core/SkRRect.cpp \
src/core/SkRect.cpp \
src/core/SkStream.cpp \
src/core/SkString.cpp \
src/core/SkStringUtils.cpp \
+src/core/SkStroke.cpp \
+src/core/SkStrokeRec.cpp \
+src/core/SkStrokerPriv.cpp \
src/core/SkUtils.cpp \
+src/effects/SkDashPathEffect.cpp \
+src/effects/SkTrimPathEffect.cpp \
src/pathops/*.cpp \
src/ports/SkDebug_stdio.cpp \
src/ports/SkMemory_malloc.cpp \
+src/utils/SkDashPath.cpp \
src/utils/SkParse.cpp \
src/utils/SkParsePath.cpp \
src/utils/SkUTF.cpp
diff --git a/experimental/pathkit/karma-docker.conf.js b/experimental/pathkit/karma-docker.conf.js
index 50397cc6db..4695fd4dcd 100644
--- a/experimental/pathkit/karma-docker.conf.js
+++ b/experimental/pathkit/karma-docker.conf.js
@@ -14,6 +14,10 @@ module.exports = function(config) {
'tests/*.spec.js'
],
+ proxies: {
+ "/pathkit/": "/base/npm-wasm/bin/test/"
+ },
+
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
diff --git a/experimental/pathkit/karma.conf.js b/experimental/pathkit/karma.conf.js
index bbb5667676..c3104b44cd 100644
--- a/experimental/pathkit/karma.conf.js
+++ b/experimental/pathkit/karma.conf.js
@@ -14,6 +14,10 @@ module.exports = function(config) {
'tests/*.spec.js'
],
+ proxies: {
+ "/pathkit/": "/base/npm-wasm/bin/test/"
+ },
+
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
diff --git a/experimental/pathkit/npm-wasm/example.html b/experimental/pathkit/npm-wasm/example.html
index c1fa8272b4..ec097b947e 100644
--- a/experimental/pathkit/npm-wasm/example.html
+++ b/experimental/pathkit/npm-wasm/example.html
@@ -30,6 +30,14 @@
+
Has various Path Effects
+
+
+
+
+
+
+
diff --git a/experimental/pathkit/npm-wasm/package.json b/experimental/pathkit/npm-wasm/package.json
index daba5dbace..b3e42b439b 100644
--- a/experimental/pathkit/npm-wasm/package.json
+++ b/experimental/pathkit/npm-wasm/package.json
@@ -1,6 +1,6 @@
{
"name": "experimental-pathkit-wasm",
- "version": "0.1.4",
+ "version": "0.1.7",
"description": "A WASM version of Skia's PathOps toolkit",
"main": "bin/pathkit.js",
"homepage": "https://github.com/google/skia/tree/master/experimental/pathkit",
diff --git a/experimental/pathkit/pathkit_wasm_bindings.cpp b/experimental/pathkit/pathkit_wasm_bindings.cpp
index 5587cadc0d..5909e39f2d 100644
--- a/experimental/pathkit/pathkit_wasm_bindings.cpp
+++ b/experimental/pathkit/pathkit_wasm_bindings.cpp
@@ -5,14 +5,17 @@
* found in the LICENSE file.
*/
+#include "SkDashPathEffect.h"
#include "SkFloatBits.h"
#include "SkFloatingPoint.h"
#include "SkMatrix.h"
+#include "SkPaint.h"
#include "SkParsePath.h"
#include "SkPath.h"
#include "SkPathOps.h"
#include "SkRect.h"
#include "SkString.h"
+#include "SkTrimPathEffect.h"
#include
#include
@@ -22,13 +25,16 @@ using namespace emscripten;
static const int MOVE = 0;
static const int LINE = 1;
static const int QUAD = 2;
+static const int CONIC = 3;
static const int CUBIC = 4;
static const int CLOSE = 5;
// Just for self-documenting purposes where the main thing being returned is an
-// SkPath, but in an error case, something of type val (e.g. null) could also be
+// SkPath, but in an error case, something of type null (which is val) could also be
// returned;
-using SkPathOrVal = emscripten::val;
+using SkPathOrNull = emscripten::val;
+// Self-documenting for when we return a string
+using JSString = emscripten::val;
// =================================================================================
// Creating/Exporting Paths with cmd arrays
@@ -60,16 +66,9 @@ emscripten::val EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
cmd.call("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
break;
case SkPath::kConic_Verb:
- SkPoint quads[5];
- // approximate with 2^1=2 quads.
- SkPath::ConvertConicToQuads(pts[0], pts[1], pts[2], iter.conicWeight(), quads, 1);
- cmd.call("push", MOVE, quads[0].x(), quads[0].y());
- cmds.call("push", cmd);
- cmd = emscripten::val::array();
- cmd.call("push", QUAD, quads[1].x(), quads[1].y(), quads[2].x(), quads[2].y());
- cmds.call("push", cmd);
- cmd = emscripten::val::array();
- cmd.call("push", QUAD, quads[3].x(), quads[3].y(), quads[4].x(), quads[4].y());
+ cmd.call("push", CONIC,
+ pts[1].x(), pts[1].y(),
+ pts[2].x(), pts[2].y(), iter.conicWeight());
break;
case SkPath::kCubic_Verb:
cmd.call("push", CUBIC,
@@ -99,7 +98,7 @@ emscripten::val EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
// the compiler is happy.
-SkPathOrVal EMSCRIPTEN_KEEPALIVE FromCmds(uintptr_t /* float* */ cptr, int numCmds) {
+SkPathOrNull EMSCRIPTEN_KEEPALIVE FromCmds(uintptr_t /* float* */ cptr, int numCmds) {
const auto* cmds = reinterpret_cast(cptr);
SkPath path;
float x1, y1, x2, y2, x3, y3;
@@ -158,7 +157,7 @@ SkPath EMSCRIPTEN_KEEPALIVE NewPath() {
// SVG things
//========================================================================================
-emscripten::val EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
+JSString EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
SkString s;
SkParsePath::ToSVGString(path, &s);
// Wrapping it in val automatically turns it into a JS string.
@@ -169,7 +168,7 @@ emscripten::val EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
}
-SkPathOrVal EMSCRIPTEN_KEEPALIVE FromSVGString(std::string str) {
+SkPathOrNull EMSCRIPTEN_KEEPALIVE FromSVGString(std::string str) {
SkPath path;
if (SkParsePath::FromSVGString(str.c_str(), &path)) {
return emscripten::val(path);
@@ -181,7 +180,7 @@ SkPathOrVal EMSCRIPTEN_KEEPALIVE FromSVGString(std::string str) {
// PATHOP things
//========================================================================================
-SkPathOrVal EMSCRIPTEN_KEEPALIVE SimplifyPath(const SkPath& path) {
+SkPathOrNull EMSCRIPTEN_KEEPALIVE SimplifyPath(const SkPath& path) {
SkPath simple;
if (Simplify(path, &simple)) {
return emscripten::val(simple);
@@ -189,7 +188,7 @@ SkPathOrVal EMSCRIPTEN_KEEPALIVE SimplifyPath(const SkPath& path) {
return emscripten::val::null();
}
-SkPathOrVal EMSCRIPTEN_KEEPALIVE ApplyPathOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
+SkPathOrNull EMSCRIPTEN_KEEPALIVE ApplyPathOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
SkPath path;
if (Op(pathOne, pathTwo, op, &path)) {
return emscripten::val(path);
@@ -197,7 +196,7 @@ SkPathOrVal EMSCRIPTEN_KEEPALIVE ApplyPathOp(const SkPath& pathOne, const SkPath
return emscripten::val::null();
}
-SkPathOrVal EMSCRIPTEN_KEEPALIVE ResolveBuilder(SkOpBuilder& builder) {
+SkPathOrNull EMSCRIPTEN_KEEPALIVE ResolveBuilder(SkOpBuilder& builder) {
SkPath path;
if (builder.resolve(&path)) {
return emscripten::val(path);
@@ -228,7 +227,6 @@ void EMSCRIPTEN_KEEPALIVE ToCanvas(const SkPath& path, emscripten::val /* Path2D
SkPoint quads[5];
// approximate with 2^1=2 quads.
SkPath::ConvertConicToQuads(pts[0], pts[1], pts[2], iter.conicWeight(), quads, 1);
- ctx.call("moveTo", quads[0].x(), quads[0].y());
ctx.call("quadraticCurveTo", quads[1].x(), quads[1].y(), quads[2].x(), quads[2].y());
ctx.call("quadraticCurveTo", quads[3].x(), quads[3].y(), quads[4].x(), quads[4].y());
break;
@@ -326,6 +324,70 @@ void Path2DAddPath(SkPath& orig, const SkPath& newPath,
orig.addPath(newPath, m);
}
+JSString GetCanvasFillType(const SkPath& path) {
+ if (path.getFillType() == SkPath::FillType::kWinding_FillType) {
+ return emscripten::val("nonzero");
+ } else if (path.getFillType() == SkPath::FillType::kEvenOdd_FillType) {
+ return emscripten::val("evenodd");
+ } else {
+ SkDebugf("warning: can't translate inverted filltype to HTML Canvas\n");
+ return emscripten::val("nonzero"); //Use default
+ }
+}
+
+//========================================================================================
+// Path Effects
+//========================================================================================
+
+SkPathOrNull PathEffectDash(const SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
+ SkPath output;
+ SkScalar intervals[] = { on, off };
+ auto pe = SkDashPathEffect::Make(intervals, 2, phase);
+ if (!pe) {
+ SkDebugf("Invalid args to dash()\n");
+ return emscripten::val::null();
+ }
+ if (pe->filterPath(&output, path, nullptr, nullptr)) {
+ return emscripten::val(output);
+ }
+ SkDebugf("Could not make dashed path\n");
+ return emscripten::val::null();
+}
+
+SkPathOrNull PathEffectTrim(const SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
+ SkPath output;
+ auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal;
+ auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
+ if (!pe) {
+ SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
+ return emscripten::val::null();
+ }
+ if (pe->filterPath(&output, path, nullptr, nullptr)) {
+ return emscripten::val(output);
+ }
+ SkDebugf("Could not trim path\n");
+ return emscripten::val::null();
+}
+
+SkPathOrNull PathEffectTrim(const SkPath& path, SkScalar startT, SkScalar stopT) {
+ return PathEffectTrim(path, startT, stopT, false);
+}
+
+SkPathOrNull PathEffectStroke(const SkPath& path, SkScalar width, SkPaint::Join join, SkPaint::Cap cap) {
+ SkPath output;
+ SkPaint p;
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeCap(cap);
+ p.setStrokeJoin(join);
+ p.setStrokeWidth(width);
+
+ if (p.getFillPath(path, &output)) {
+ return emscripten::val(output);
+ }
+ SkDebugf("Could not stroke path\n");
+ return emscripten::val::null();
+}
+
//========================================================================================
// Testing things
//========================================================================================
@@ -384,6 +446,8 @@ EMSCRIPTEN_BINDINGS(skia) {
.function("addPath",
select_overload(&Path2DAddPath))
.function("close", &SkPath::close)
+ .function("conicTo",
+ select_overload(&SkPath::conicTo))
.function("cubicTo",
select_overload(&SkPath::cubicTo))
.function("quadTo",
@@ -392,9 +456,16 @@ EMSCRIPTEN_BINDINGS(skia) {
// Extra features
.function("setFillType", &SkPath::setFillType)
.function("getFillType", &SkPath::getFillType)
+ .function("getCanvasFillType", &GetCanvasFillType)
.function("getBounds", &SkPath::getBounds)
.function("computeTightBounds", &SkPath::computeTightBounds)
+ // PathEffects
+ .function("dash", &PathEffectDash)
+ .function("trim", select_overload(&PathEffectTrim))
+ .function("trim", select_overload(&PathEffectTrim))
+ .function("stroke", &PathEffectStroke)
+
// PathOps
.function("simplify", &SimplifyPath)
.function("op", &ApplyPathOp)
@@ -407,6 +478,7 @@ EMSCRIPTEN_BINDINGS(skia) {
#ifdef PATHKIT_TESTING
.function("dump", select_overload(&SkPath::dump))
+ .function("dumpHex", select_overload(&SkPath::dumpHex))
#endif
;
@@ -444,6 +516,7 @@ EMSCRIPTEN_BINDINGS(skia) {
constant("MOVE_VERB", MOVE);
constant("LINE_VERB", LINE);
constant("QUAD_VERB", QUAD);
+ constant("CONIC_VERB", CONIC);
constant("CUBIC_VERB", CUBIC);
constant("CLOSE_VERB", CLOSE);
@@ -458,12 +531,20 @@ EMSCRIPTEN_BINDINGS(skia) {
function("MakeLTRBRect", &SkRect::MakeLTRB);
- // coming soon - Stroke
+ // Stroke
+ enum_("StrokeJoin")
+ .value("MITER", SkPaint::Join::kMiter_Join)
+ .value("ROUND", SkPaint::Join::kRound_Join)
+ .value("BEVEL", SkPaint::Join::kBevel_Join);
+
+ enum_("StrokeCap")
+ .value("BUTT", SkPaint::Cap::kButt_Cap)
+ .value("ROUND", SkPaint::Cap::kRound_Cap)
+ .value("SQUARE", SkPaint::Cap::kSquare_Cap);
+
// coming soon - Matrix
- // coming soon - Trim
-
// Test Utils
function("SkBits2FloatUnsigned", &SkBits2FloatUnsigned);
}
diff --git a/experimental/pathkit/tests/path.spec.js b/experimental/pathkit/tests/path.spec.js
index 660ade5e70..0cafc384cf 100644
--- a/experimental/pathkit/tests/path.spec.js
+++ b/experimental/pathkit/tests/path.spec.js
@@ -2,12 +2,12 @@
describe('PathKit\'s Path Behavior', function() {
// Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
var PathKit = null;
- const LoadPathKit = new Promise(function(resolve, reject){
+ const LoadPathKit = new Promise(function(resolve, reject) {
if (PathKit) {
resolve();
} else {
PathKitInit({
- locateFile: (file) => '/base/npm-wasm/bin/test/'+file,
+ locateFile: (file) => '/pathkit/'+file,
}).then((_PathKit) => {
PathKit = _PathKit;
resolve();
@@ -31,6 +31,10 @@ describe('PathKit\'s Path Behavior', function() {
});
});
+ function bits2float(str) {
+ return PathKit.SkBits2FloatUnsigned(parseInt(str))
+ }
+
it('has getBounds() and computeTightBounds()', function(done){
LoadPathKit.then(() => {
// Based on PathOpsTightBoundsIllBehaved
@@ -39,12 +43,36 @@ describe('PathKit\'s Path Behavior', function() {
path.quadraticCurveTo(4, 3, 2, 2);
expect(path.getBounds()).toEqual(PathKit.MakeLTRBRect(1, 1, 4, 3));
expect(path.computeTightBounds()).toEqual(PathKit.MakeLTRBRect(1, 1,
- PathKit.SkBits2FloatUnsigned(parseInt("0x40333334")), // 2.8
- PathKit.SkBits2FloatUnsigned(parseInt("0x40155556")))); // 2.3333333
+ bits2float("0x40333334"), // 2.8
+ bits2float("0x40155556"))); // 2.3333333
path.delete();
done();
});
});
+ it('does NOT approximates conics when dumping as toCmds', function(done){
+ LoadPathKit.then(() => {
+ let path = PathKit.NewPath();
+ path.moveTo(20, 120);
+ path.arc(20, 120, 18, 0, 1.75 * Math.PI);
+ path.lineTo(20, 120);
+
+ let expectedCmds = [
+ [PathKit.MOVE_VERB, 20, 120],
+ [PathKit.LINE_VERB, 38, 120],
+ [PathKit.CONIC_VERB, 38, 138, 20, 138, bits2float("0x3f3504f3)")], // 0.707107f
+ [PathKit.CONIC_VERB, 2, 138, 2, 120, bits2float("0x3f3504f3)")], // 0.707107f
+ [PathKit.CONIC_VERB, 2, 102, 20, 102, bits2float("0x3f3504f3)")], // 0.707107f
+ [PathKit.CONIC_VERB, bits2float("0x41dba58e"), 102, bits2float("0x4202e962"), bits2float("0x42d68b4d"), bits2float("0x3f6c8361")], // 27.4558, 102, 32.7279, 107.272, 0.92388
+ [PathKit.LINE_VERB, 20, 120],
+ ];
+ let actual = path.toCmds();
+ expect(actual).toEqual(expectedCmds);
+
+ path.delete();
+ done();
+ });
+ });
+
});
diff --git a/experimental/pathkit/tests/path2d.spec.js b/experimental/pathkit/tests/path2d.spec.js
index 6e1cf95cb5..303bf879c9 100644
--- a/experimental/pathkit/tests/path2d.spec.js
+++ b/experimental/pathkit/tests/path2d.spec.js
@@ -10,12 +10,12 @@ describe('PathKit\'s Path2D API', function() {
// Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
var PathKit = null;
- const LoadPathKit = new Promise(function(resolve, reject){
+ const LoadPathKit = new Promise(function(resolve, reject) {
if (PathKit) {
resolve();
} else {
PathKitInit({
- locateFile: (file) => '/base/npm-wasm/bin/test/'+file,
+ locateFile: (file) => '/pathkit/'+file,
}).then((_PathKit) => {
PathKit = _PathKit;
resolve();
@@ -23,7 +23,7 @@ describe('PathKit\'s Path2D API', function() {
}
});
- it('can do everything in the Path2D API w/o crashing', function(done){
+ it('can do everything in the Path2D API w/o crashing', function(done) {
LoadPathKit.then(() => {
// This is taken from example.html
let path = PathKit.NewPath();
@@ -79,4 +79,29 @@ describe('PathKit\'s Path2D API', function() {
});
});
-});
\ No newline at end of file
+ it('approximates arcs (conics) with quads', function(done) {
+ LoadPathKit.then(() => {
+ let path = PathKit.NewPath();
+ path.moveTo(20, 120);
+ path.arc(20, 120, 18, 0, 1.75 * Math.PI);
+ path.lineTo(20, 120);
+
+ let canvas = document.createElement('canvas');
+ container.appendChild(canvas);
+ let canvasCtx = canvas.getContext('2d');
+
+ spyOn(canvasCtx, 'quadraticCurveTo');
+
+ canvasCtx.beginPath();
+ path.toCanvas(canvasCtx);
+ canvasCtx.stroke();
+ // No need to check the whole path, as that's more what the
+ // gold correctness tests are for (can account for changes we make
+ // to the approximation algorithms).
+ expect(canvasCtx.quadraticCurveTo).toHaveBeenCalled();
+ path.delete();
+ done();
+ });
+ });
+
+});
diff --git a/experimental/pathkit/tests/pathops.spec.js b/experimental/pathkit/tests/pathops.spec.js
index c9a3d54a35..3a9228ed53 100644
--- a/experimental/pathkit/tests/pathops.spec.js
+++ b/experimental/pathkit/tests/pathops.spec.js
@@ -77,12 +77,12 @@ describe('PathKit\'s PathOps Behavior', function() {
var PathKit = null;
var PATHOP_MAP = {};
var FILLTYPE_MAP = {};
- const LoadPathKit = new Promise(function(resolve, reject){
+ const LoadPathKit = new Promise(function(resolve, reject) {
if (PathKit) {
resolve();
} else {
PathKitInit({
- locateFile: (file) => '/base/npm-wasm/bin/test/'+file,
+ locateFile: (file) => '/pathkit/'+file,
}).then((_PathKit) => {
PathKit = _PathKit;
PATHOP_MAP = {
@@ -152,6 +152,9 @@ describe('PathKit\'s PathOps Behavior', function() {
// Do a tolerant match.
let diff = diffPaths(expected, combined);
if (test.expectMatch === 'yes'){
+ // Check fill type
+ expect(combined.getFillType().value).toEqual(getFillType(test.fillTypeOut).value);
+ // diff should be null if the paths are identical (modulo rounding)
if (diff) {
expect(`[${testName}] ${diff}`).toBe('');
addSVG('[PathOps] ' + testName, expected, combined, diff);
@@ -202,6 +205,9 @@ describe('PathKit\'s PathOps Behavior', function() {
// Do a tolerant match.
let diff = diffPaths(expected, simplified);
if (test.expectMatch === 'yes'){
+ // Check fill type
+ expect(simplified.getFillType().value).toEqual(getFillType(test.fillTypeOut).value);
+ // diff should be null if the paths are identical (modulo rounding)
if (diff) {
expect(`[${testName}] ${diff}`).toBe('');
addSVG('[Simplify] ' + testName, expected, simplified, diff);
@@ -223,4 +229,4 @@ describe('PathKit\'s PathOps Behavior', function() {
});
});
});
-});
\ No newline at end of file
+});
diff --git a/experimental/pathkit/tests/svg.spec.js b/experimental/pathkit/tests/svg.spec.js
index f9d1b02e13..f4c30077c4 100644
--- a/experimental/pathkit/tests/svg.spec.js
+++ b/experimental/pathkit/tests/svg.spec.js
@@ -2,12 +2,12 @@
describe('PathKit\'s SVG Behavior', function() {
// Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
var PathKit = null;
- const LoadPathKit = new Promise(function(resolve, reject){
+ const LoadPathKit = new Promise(function(resolve, reject) {
if (PathKit) {
resolve();
} else {
PathKitInit({
- locateFile: (file) => '/base/npm-wasm/bin/test/'+file,
+ locateFile: (file) => '/pathkit/'+file,
}).then((_PathKit) => {
PathKit = _PathKit;
resolve();
@@ -15,7 +15,7 @@ describe('PathKit\'s SVG Behavior', function() {
}
});
- it('can create a path from an SVG string', function(done){
+ it('can create a path from an SVG string', function(done) {
LoadPathKit.then(() => {
//.This is a parallelagram from
// https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg
@@ -37,7 +37,7 @@ describe('PathKit\'s SVG Behavior', function() {
});
});
- it('can create an SVG string from a path', function(done){
+ it('can create an SVG string from a path', function(done) {
LoadPathKit.then(() => {
let cmds = [[PathKit.MOVE_VERB, 205, 5],
[PathKit.LINE_VERB, 795, 5],
@@ -56,7 +56,7 @@ describe('PathKit\'s SVG Behavior', function() {
});
});
- it('can create an SVG string from hex values', function(done){
+ it('can create an SVG string from hex values', function(done) {
LoadPathKit.then(() => {
let cmds = [[PathKit.MOVE_VERB, "0x15e80300", "0x400004dc"], // 9.37088e-26f, 2.0003f
[PathKit.LINE_VERB, 795, 5],
@@ -74,7 +74,7 @@ describe('PathKit\'s SVG Behavior', function() {
});
});
- it('should have input and the output be the same', function(done){
+ it('should have input and the output be the same', function(done) {
LoadPathKit.then(() => {
let testCases = [
'M0 0L1075 0L1075 242L0 242L0 0Z'
@@ -92,4 +92,20 @@ describe('PathKit\'s SVG Behavior', function() {
});
});
+ it('approximates arcs (conics) with quads', function(done) {
+ LoadPathKit.then(() => {
+ let path = PathKit.NewPath();
+ path.moveTo(20, 120);
+ path.arc(20, 120, 18, 0, 1.75 * Math.PI);
+ path.lineTo(20, 120);
+ let svgStr = path.toSVGString();
+ // Q stands for quad. No need to check the whole path, as that's more
+ // what the gold correctness tests are for (can account for changes we make
+ // to the approximation algorithms).
+ expect(svgStr).toContain('Q');
+ path.delete();
+ done();
+ });
+ });
+
});
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index c8766f88be..3ccbadd20e 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -101,6 +101,11 @@ static void report_no_entries(const char* functionName) {
#endif
SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
+#ifdef WEB_ASSEMBLY
+ // Should not be reachable by WebAssembly Code.
+ SkASSERT(false);
+ return nullptr;
+#else
InitializeFlattenablesIfNeeded();
SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
#ifdef SK_DEBUG
@@ -110,9 +115,15 @@ SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
if (pair.first == pair.second)
return nullptr;
return pair.first->fFactory;
+#endif
}
bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) {
+#ifdef WEB_ASSEMBLY
+ // Should not be reachable by WebAssembly Code.
+ SkASSERT(false);
+ return false;
+#else
SkASSERT(type);
InitializeFlattenablesIfNeeded();
SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
@@ -124,9 +135,15 @@ bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) {
return false;
*type = pair.first->fType;
return true;
+#endif
}
const char* SkFlattenable::FactoryToName(Factory fact) {
+#ifdef WEB_ASSEMBLY
+ // Should not be reachable by WebAssembly Code.
+ SkASSERT(false);
+ return nullptr;
+#else
InitializeFlattenablesIfNeeded();
#ifdef SK_DEBUG
report_no_entries(__FUNCTION__);
@@ -138,6 +155,7 @@ const char* SkFlattenable::FactoryToName(Factory fact) {
}
}
return nullptr;
+#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp
index aa3803a95c..a2434099f6 100644
--- a/src/effects/SkDashPathEffect.cpp
+++ b/src/effects/SkDashPathEffect.cpp
@@ -374,6 +374,11 @@ void SkDashImpl::flatten(SkWriteBuffer& buffer) const {
}
sk_sp SkDashImpl::CreateProc(SkReadBuffer& buffer) {
+#ifdef WEB_ASSEMBLY
+ // Should not be reachable by WebAssembly Code.
+ SkASSERT(false);
+ return nullptr;
+#else
const SkScalar phase = buffer.readScalar();
uint32_t count = buffer.getArrayCount();
@@ -387,6 +392,7 @@ sk_sp SkDashImpl::CreateProc(SkReadBuffer& buffer) {
return SkDashPathEffect::Make(intervals.get(), SkToInt(count), phase);
}
return nullptr;
+#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkTrimPathEffect.cpp b/src/effects/SkTrimPathEffect.cpp
index 8c3f56e2ba..3a8d0944cb 100644
--- a/src/effects/SkTrimPathEffect.cpp
+++ b/src/effects/SkTrimPathEffect.cpp
@@ -89,12 +89,18 @@ void SkTrimPE::flatten(SkWriteBuffer& buffer) const {
}
sk_sp SkTrimPE::CreateProc(SkReadBuffer& buffer) {
+#ifdef WEB_ASSEMBLY
+ // Should not be reachable by WebAssembly Code.
+ SkASSERT(false);
+ return nullptr;
+#else
const auto start = buffer.readScalar(),
stop = buffer.readScalar();
const auto mode = buffer.readUInt();
return SkTrimPathEffect::Make(start, stop,
(mode & 1) ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal);
+#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////////