diff --git a/modules/pathkit/CHANGELOG.md b/modules/pathkit/CHANGELOG.md index 5d7192e4f4..d04fe47c43 100644 --- a/modules/pathkit/CHANGELOG.md +++ b/modules/pathkit/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + - `res_scale` expoed in StrokeOpts object. (skbug.com/13301) + ## [1.0.0] 2022-02-03 ### Changed diff --git a/modules/pathkit/chaining.js b/modules/pathkit/chaining.js index c181e44f8d..6fc8c8f4e4 100644 --- a/modules/pathkit/chaining.js +++ b/modules/pathkit/chaining.js @@ -145,10 +145,11 @@ * @type {StrokeOpts} */ opts = opts || {}; - opts.width = opts.width || 1; - opts.miter_limit = opts.miter_limit || 4; - opts.cap = opts.cap || PathKit.StrokeCap.BUTT; - opts.join = opts.join || PathKit.StrokeJoin.MITER; + opts['width'] = opts['width'] || 1; + opts['miter_limit'] = opts['miter_limit'] || 4; + opts['cap'] = opts['cap'] || PathKit.StrokeCap.BUTT; + opts['join'] = opts['join'] || PathKit.StrokeJoin.MITER; + opts['res_scale'] = opts['res_scale'] || 1; if (this._stroke(opts)) { return this; } diff --git a/modules/pathkit/pathkit_wasm_bindings.cpp b/modules/pathkit/pathkit_wasm_bindings.cpp index 30ecd21ffd..827e664903 100644 --- a/modules/pathkit/pathkit_wasm_bindings.cpp +++ b/modules/pathkit/pathkit_wasm_bindings.cpp @@ -393,6 +393,7 @@ struct StrokeOpts { // any are omitted. SkScalar width; SkScalar miter_limit; + SkScalar res_scale; SkPaint::Join join; SkPaint::Cap cap; }; @@ -404,8 +405,11 @@ bool ApplyStroke(SkPath& path, StrokeOpts opts) { p.setStrokeJoin(opts.join); p.setStrokeWidth(opts.width); p.setStrokeMiter(opts.miter_limit); - - return p.getFillPath(path, &path); + // Default to 1.0 if 0 (or an invalid negative number) + if (opts.res_scale <= 0) { + opts.res_scale = 1.0; + } + return p.getFillPath(path, &path, nullptr, opts.res_scale); } //======================================================================================== @@ -589,6 +593,7 @@ EMSCRIPTEN_BINDINGS(skia) { value_object("StrokeOpts") .field("width", &StrokeOpts::width) .field("miter_limit", &StrokeOpts::miter_limit) + .field("res_scale", &StrokeOpts::res_scale) .field("join", &StrokeOpts::join) .field("cap", &StrokeOpts::cap); diff --git a/modules/pathkit/tests/effects.spec.js b/modules/pathkit/tests/effects.spec.js index 575c95a559..6e19833645 100644 --- a/modules/pathkit/tests/effects.spec.js +++ b/modules/pathkit/tests/effects.spec.js @@ -117,6 +117,62 @@ describe('PathKit\'s Path Behavior', function() { }); })); }); + + it('can use res_scale for more precision', function(done) { + LoadPathKit.then(catchException(done, () => { + let canvas = document.createElement('canvas'); + let ctx = canvas.getContext('2d'); + // Set canvas size and make it a bit bigger to zoom in on the lines + standardizedCanvasSize(ctx); + + const circle = PathKit.NewPath(); + circle.ellipse(0, 0, 1, 1, 0, 0, Math.PI * 2); + + let scales = [1, 3, 5, + 10, 30, 100]; + + // White background + ctx.fillStyle = 'white'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + for (let i = 0; i < scales.length; i++) { + ctx.save(); + const row = Math.floor(i / 3); + const col = i % 3; + ctx.translate(100 * col + 50, 100 * row + 50); + ctx.scale(30, 30); + + // Grey circle + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.beginPath(); + circle.toCanvas(ctx); + ctx.fill(); + + // Pink stroke, with given res_scale option + const line = circle.copy().stroke({ + width: 0.5, + res_scale: scales[i], + }); + ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; + ctx.beginPath(); + line.toCanvas(ctx); + ctx.fill(); + + line.delete(); + ctx.restore(); + } + ctx.fillStyle = 'black'; + ctx.font = '14px serif'; + ctx.fillText('notice for lower res_scale values, the stroked circles ' + + '(pink) are not round', + 10, 200); + + circle.delete(); + reportCanvas(canvas, 'res_scale').then(() => { + done(); + }).catch(reportError(done)); + })); + }); }); });