From af96adb338456f02a21bbd8553343512244d31ca Mon Sep 17 00:00:00 2001 From: jamsch Date: Sun, 30 May 2021 19:26:25 +1200 Subject: [PATCH 1/6] feat: Canvas & SVG renderers will no longer will invert characters This is in anticipation of an update to the hanzi-writer-data & hanzi-writer-data-jp packages to fix a core issue with path layouts being horizontally flipped. BREAKING CHANGE: Users will need to update their hanzi-writer-data & hanzi-writer-data-jp character packages --- src/HanziWriter.ts | 4 +- src/Positioner.ts | 22 +- src/__tests__/HanziWriter-test.ts | 8 +- src/__tests__/Positioner-test.ts | 4 +- .../__snapshots__/HanziWriter-test.ts.snap | 756 ++++---- src/renderers/canvas/HanziWriterRenderer.ts | 17 +- .../HanziWriterRenderer-test.ts.snap | 1606 ++++++++--------- src/renderers/svg/HanziWriterRenderer.ts | 8 +- 8 files changed, 1164 insertions(+), 1261 deletions(-) diff --git a/src/HanziWriter.ts b/src/HanziWriter.ts index 69c66cdbf..731b3cca8 100644 --- a/src/HanziWriter.ts +++ b/src/HanziWriter.ts @@ -94,8 +94,8 @@ export default class HanziWriter { y: positioner.yOffset, scale: positioner.scale, transform: trim(` - translate(${positioner.xOffset}, ${positioner.height - positioner.yOffset}) - scale(${positioner.scale}, ${-1 * positioner.scale}) + translate(${positioner.xOffset}, ${positioner.yOffset}) + scale(${positioner.scale}) `).replace(/\s+/g, ' '), }; } diff --git a/src/Positioner.ts b/src/Positioner.ts index fce376c04..c916efcba 100644 --- a/src/Positioner.ts +++ b/src/Positioner.ts @@ -1,13 +1,7 @@ import { Point } from './typings/types'; // All makemeahanzi characters have the same bounding box -const CHARACTER_BOUNDS = [ - { x: 0, y: -124 }, - { x: 1024, y: 900 }, -]; -const [from, to] = CHARACTER_BOUNDS; -const preScaledWidth = to.x - from.x; -const preScaledHeight = to.y - from.y; +const BOUNDING_BOX = 1024; export type PositionerOptions = { /** Default: 0 */ @@ -34,22 +28,16 @@ export default class Positioner { const effectiveWidth = width - 2 * padding; const effectiveHeight = height - 2 * padding; - const scaleX = effectiveWidth / preScaledWidth; - const scaleY = effectiveHeight / preScaledHeight; - this.scale = Math.min(scaleX, scaleY); + this.scale = Math.min(effectiveWidth / BOUNDING_BOX, effectiveHeight / BOUNDING_BOX); - const xCenteringBuffer = padding + (effectiveWidth - this.scale * preScaledWidth) / 2; - const yCenteringBuffer = - padding + (effectiveHeight - this.scale * preScaledHeight) / 2; - - this.xOffset = -1 * from.x * this.scale + xCenteringBuffer; - this.yOffset = -1 * from.y * this.scale + yCenteringBuffer; + this.xOffset = padding + (effectiveWidth - this.scale * BOUNDING_BOX) / 2; + this.yOffset = padding + (effectiveHeight - this.scale * BOUNDING_BOX) / 2; } convertExternalPoint(point: Point) { const x = (point.x - this.xOffset) / this.scale; - const y = (this.height - this.yOffset - point.y) / this.scale; + const y = (point.y - this.yOffset) / this.scale; return { x, y }; } } diff --git a/src/__tests__/HanziWriter-test.ts b/src/__tests__/HanziWriter-test.ts index 2a0861fdc..6140558cd 100644 --- a/src/__tests__/HanziWriter-test.ts +++ b/src/__tests__/HanziWriter-test.ts @@ -1079,18 +1079,18 @@ describe('HanziWriter', () => { it('returns an object with info that can be used for scaling a makemeahanzi character in SVG', () => { expect(HanziWriter.getScalingTransform(100, 120, 10)).toEqual({ scale: 0.078125, - transform: 'translate(10, 90.3125) scale(0.078125, -0.078125)', + transform: 'translate(10, 20) scale(0.078125)', x: 10, - y: 29.6875, + y: 20, }); }); it('uses 0 as the default padding', () => { expect(HanziWriter.getScalingTransform(100, 100)).toEqual({ scale: 0.09765625, - transform: 'translate(0, 87.890625) scale(0.09765625, -0.09765625)', + transform: 'translate(0, 0) scale(0.09765625)', x: 0, - y: 12.109375, + y: 0, }); }); }); diff --git a/src/__tests__/Positioner-test.ts b/src/__tests__/Positioner-test.ts index b0d32c177..1ae017230 100644 --- a/src/__tests__/Positioner-test.ts +++ b/src/__tests__/Positioner-test.ts @@ -5,7 +5,7 @@ describe('Positioner', () => { const positioner = new Positioner({ width: 400, height: 400, padding: 20 }); expect(positioner.xOffset).toBe(20); - expect(positioner.yOffset).toBe(63.59375); + expect(positioner.yOffset).toBe(20); expect(positioner.scale).toBe(0.3515625); expect(positioner.height).toBe(400); }); @@ -14,7 +14,7 @@ describe('Positioner', () => { const positioner = new Positioner({ width: 400, height: 400, padding: 20 }); expect(positioner.convertExternalPoint({ x: 30, y: 50 })).toEqual({ x: 28.444444444444443, - y: 814.6666666666666, + y: 85.33333333333333, }); }); }); diff --git a/src/__tests__/__snapshots__/HanziWriter-test.ts.snap b/src/__tests__/__snapshots__/HanziWriter-test.ts.snap index 8ea496722..a2e241408 100644 --- a/src/__tests__/__snapshots__/HanziWriter-test.ts.snap +++ b/src/__tests__/__snapshots__/HanziWriter-test.ts.snap @@ -36,9 +36,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -51,9 +51,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -66,9 +66,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -81,9 +81,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -96,9 +96,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -111,9 +111,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -126,9 +126,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -141,9 +141,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -156,9 +156,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -171,9 +171,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -183,9 +183,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -198,9 +198,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -213,9 +213,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -228,9 +228,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -243,9 +243,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -258,9 +258,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -273,9 +273,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -288,9 +288,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -303,9 +303,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -318,9 +318,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -330,9 +330,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -345,9 +345,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -360,9 +360,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -375,9 +375,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -390,9 +390,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -405,9 +405,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -420,9 +420,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -435,9 +435,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -450,9 +450,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -465,9 +465,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -480,9 +480,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -492,9 +492,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -507,9 +507,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -522,9 +522,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -537,9 +537,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -552,9 +552,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -567,9 +567,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -582,9 +582,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -597,9 +597,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -612,9 +612,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -627,9 +627,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -639,9 +639,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -679,7 +679,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 20, - "y": -15.15625, + "y": 20, }, "transform": Array [ 1, @@ -687,28 +687,9 @@ CanvasRenderingContext2D { 0, 1, 20, - -15.15625, - ], - "type": "translate", - }, - Object { - "props": Object { - "a": 1, - "b": 0, - "c": 0, - "d": -1, - "e": 0, - "f": 0, - }, - "transform": Array [ - 1, - 0, - 0, - -1, 20, - -15.15625, ], - "type": "transform", + "type": "translate", }, Object { "props": Object { @@ -719,9 +700,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "scale", }, @@ -731,9 +712,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "save", }, @@ -746,9 +727,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "clip", }, @@ -760,9 +741,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "globalAlpha", }, @@ -774,9 +755,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "strokeStyle", }, @@ -788,9 +769,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "fillStyle", }, @@ -802,9 +783,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineWidth", }, @@ -816,9 +797,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineCap", }, @@ -830,9 +811,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineJoin", }, @@ -847,9 +828,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "setLineDash", }, @@ -861,9 +842,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineDashOffset", }, @@ -873,9 +854,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -888,9 +869,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -903,9 +884,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -918,9 +899,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -933,9 +914,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -948,9 +929,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -963,9 +944,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -978,9 +959,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -993,9 +974,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1008,9 +989,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1023,9 +1004,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -1038,9 +1019,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -1053,9 +1034,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1068,9 +1049,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1083,9 +1064,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1098,9 +1079,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1113,9 +1094,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1128,9 +1109,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1143,9 +1124,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1158,9 +1139,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1170,9 +1151,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -1182,9 +1163,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "restore", }, @@ -1194,9 +1175,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "save", }, @@ -1209,9 +1190,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "clip", }, @@ -1223,9 +1204,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "globalAlpha", }, @@ -1237,9 +1218,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "strokeStyle", }, @@ -1251,9 +1232,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "fillStyle", }, @@ -1265,9 +1246,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineWidth", }, @@ -1279,9 +1260,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineCap", }, @@ -1293,9 +1274,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineJoin", }, @@ -1310,9 +1291,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "setLineDash", }, @@ -1324,9 +1305,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineDashOffset", }, @@ -1336,9 +1317,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -1351,9 +1332,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -1366,9 +1347,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1381,9 +1362,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1396,9 +1377,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1411,9 +1392,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1426,9 +1407,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1441,9 +1422,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1456,9 +1437,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1471,9 +1452,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -1486,9 +1467,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -1501,9 +1482,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1516,9 +1497,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1531,9 +1512,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1546,9 +1527,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1561,9 +1542,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1576,9 +1557,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1591,9 +1572,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1603,9 +1584,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -1615,9 +1596,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "restore", }, @@ -1627,9 +1608,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "save", }, @@ -1642,9 +1623,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "clip", }, @@ -1656,9 +1637,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "globalAlpha", }, @@ -1670,9 +1651,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "strokeStyle", }, @@ -1684,9 +1665,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "fillStyle", }, @@ -1698,9 +1679,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineWidth", }, @@ -1712,9 +1693,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineCap", }, @@ -1726,9 +1707,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineJoin", }, @@ -1743,9 +1724,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "setLineDash", }, @@ -1757,9 +1738,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineDashOffset", }, @@ -1769,9 +1750,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -1784,9 +1765,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -1799,9 +1780,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1814,9 +1795,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1829,9 +1810,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1844,9 +1825,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1859,9 +1840,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1874,9 +1855,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1889,9 +1870,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1904,9 +1885,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1919,9 +1900,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -1934,9 +1915,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -1949,9 +1930,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1964,9 +1945,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1979,9 +1960,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -1994,9 +1975,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2009,9 +1990,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2024,9 +2005,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2039,9 +2020,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2054,9 +2035,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2066,9 +2047,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -2078,9 +2059,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "restore", }, @@ -2090,9 +2071,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "save", }, @@ -2105,9 +2086,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "clip", }, @@ -2119,9 +2100,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "globalAlpha", }, @@ -2133,9 +2114,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "strokeStyle", }, @@ -2147,9 +2128,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "fillStyle", }, @@ -2161,9 +2142,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineWidth", }, @@ -2175,9 +2156,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineCap", }, @@ -2189,9 +2170,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineJoin", }, @@ -2206,9 +2187,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "setLineDash", }, @@ -2220,9 +2201,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineDashOffset", }, @@ -2232,9 +2213,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -2247,9 +2228,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -2262,9 +2243,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2277,9 +2258,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2292,9 +2273,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2307,9 +2288,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2322,9 +2303,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2337,9 +2318,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2352,9 +2333,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2367,9 +2348,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -2382,9 +2363,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -2397,9 +2378,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2412,9 +2393,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2427,9 +2408,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2442,9 +2423,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2457,9 +2438,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2472,9 +2453,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2487,9 +2468,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2499,9 +2480,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "stroke", }, @@ -2511,9 +2492,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "restore", }, @@ -2523,9 +2504,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "restore", }, @@ -2576,9 +2557,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "beginPath", }, @@ -2591,9 +2572,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "moveTo", }, @@ -2606,9 +2587,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2621,9 +2602,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2636,9 +2617,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2651,9 +2632,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2666,9 +2647,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2681,9 +2662,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2696,9 +2677,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], "type": "lineTo", }, @@ -2730,9 +2711,9 @@ CanvasRenderingContext2D { -0.0390625, -0, -0, - 0.0390625, + -0.0390625, + 20, 20, - -15.15625, ], ], "addHitRegion": [MockFunction], @@ -3375,29 +3356,12 @@ CanvasRenderingContext2D { }, "strokeRect": [MockFunction], "strokeText": [MockFunction], - "transform": [MockFunction] { - "calls": Array [ - Array [ - 1, - 0, - 0, - -1, - 0, - 0, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - }, + "transform": [MockFunction], "translate": [MockFunction] { "calls": Array [ Array [ 20, - -15.15625, + 20, ], ], "results": Array [ diff --git a/src/renderers/canvas/HanziWriterRenderer.ts b/src/renderers/canvas/HanziWriterRenderer.ts index 15505eb87..b32106558 100644 --- a/src/renderers/canvas/HanziWriterRenderer.ts +++ b/src/renderers/canvas/HanziWriterRenderer.ts @@ -35,16 +35,12 @@ export default class HanziWriterRenderer const ctx = this._target!.getContext()!; ctx.clearRect(0, 0, width, height); ctx.save(); - ctx.translate(xOffset, height - yOffset); - ctx.transform(1, 0, 0, -1, 0, 0); + ctx.translate(xOffset, yOffset); ctx.scale(scale, scale); cb(ctx); ctx.restore(); // @ts-expect-error Verify if this is still needed for the "wechat miniprogram". - if (ctx.draw) { - // @ts-expect-error - ctx.draw(); - } + ctx.draw?.(); } render(props: RenderStateObject) { @@ -60,19 +56,16 @@ export default class HanziWriterRenderer this._animationFrame((ctx) => { this._outlineCharRenderer.render(ctx, { - opacity: outline.opacity, - strokes: outline.strokes, + ...outline, strokeColor: outlineColor, }); this._mainCharRenderer.render(ctx, { - opacity: main.opacity, - strokes: main.strokes, + ...main, strokeColor: strokeColor, radicalColor: radicalColor, }); this._highlightCharRenderer.render(ctx, { - opacity: highlight.opacity, - strokes: highlight.strokes, + ...highlight, strokeColor: highlightColor, }); diff --git a/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap b/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap index 1ce5af86b..8c5194f9a 100644 --- a/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap +++ b/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap @@ -34,7 +34,7 @@ Array [ Object { "props": Object { "x": 10, - "y": 80.3125, + "y": 10, }, "transform": Array [ 1, @@ -42,28 +42,9 @@ Array [ 0, 1, 10, - 80.3125, - ], - "type": "translate", - }, - Object { - "props": Object { - "a": 1, - "b": 0, - "c": 0, - "d": -1, - "e": 0, - "f": 0, - }, - "transform": Array [ - 1, - 0, - 0, - -1, 10, - 80.3125, ], - "type": "transform", + "type": "translate", }, Object { "props": Object { @@ -74,9 +55,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "scale", }, @@ -86,9 +67,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -101,9 +82,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -115,9 +96,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -129,9 +110,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -143,9 +124,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -157,9 +138,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -171,9 +152,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -185,9 +166,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -202,9 +183,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -216,9 +197,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -228,9 +209,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -243,9 +224,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -258,9 +239,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -273,9 +254,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -288,9 +269,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -303,9 +284,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -318,9 +299,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -333,9 +314,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -348,9 +329,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -363,9 +344,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -378,9 +359,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -393,9 +374,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -408,9 +389,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -423,9 +404,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -438,9 +419,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -453,9 +434,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -468,9 +449,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -483,9 +464,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -498,9 +479,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -513,9 +494,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -525,9 +506,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -537,9 +518,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -549,9 +530,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -564,9 +545,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -578,9 +559,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -592,9 +573,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -606,9 +587,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -620,9 +601,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -634,9 +615,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -648,9 +629,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -665,9 +646,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -679,9 +660,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -691,9 +672,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -706,9 +687,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -721,9 +702,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -736,9 +717,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -751,9 +732,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -766,9 +747,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -781,9 +762,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -796,9 +777,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -811,9 +792,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -826,9 +807,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -841,9 +822,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -856,9 +837,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -871,9 +852,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -886,9 +867,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -901,9 +882,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -916,9 +897,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -931,9 +912,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -946,9 +927,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -958,9 +939,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -970,9 +951,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -982,9 +963,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -997,9 +978,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -1011,9 +992,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -1025,9 +1006,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -1039,9 +1020,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -1053,9 +1034,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -1067,9 +1048,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -1081,9 +1062,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -1098,9 +1079,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -1112,9 +1093,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -1124,9 +1105,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -1139,9 +1120,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -1154,9 +1135,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1169,9 +1150,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1184,9 +1165,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1199,9 +1180,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1214,9 +1195,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1229,9 +1210,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1244,9 +1225,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1259,9 +1240,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1274,9 +1255,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -1289,9 +1270,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -1304,9 +1285,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1319,9 +1300,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1334,9 +1315,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1349,9 +1330,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1364,9 +1345,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1379,9 +1360,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1394,9 +1375,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1409,9 +1390,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1421,9 +1402,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -1433,9 +1414,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -1445,9 +1426,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -1460,9 +1441,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -1474,9 +1455,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -1488,9 +1469,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -1502,9 +1483,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -1516,9 +1497,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -1530,9 +1511,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -1544,9 +1525,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -1561,9 +1542,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -1575,9 +1556,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -1587,9 +1568,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -1602,9 +1583,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -1617,9 +1598,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1632,9 +1613,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1647,9 +1628,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1662,9 +1643,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1677,9 +1658,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1692,9 +1673,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1707,9 +1688,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1722,9 +1703,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -1737,9 +1718,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -1752,9 +1733,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1767,9 +1748,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1782,9 +1763,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1797,9 +1778,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1812,9 +1793,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1827,9 +1808,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1842,9 +1823,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -1854,9 +1835,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -1866,9 +1847,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -1878,9 +1859,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -1893,9 +1874,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -1907,9 +1888,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -1921,9 +1902,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -1935,9 +1916,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -1949,9 +1930,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -1963,9 +1944,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -1977,9 +1958,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -1994,9 +1975,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -2008,9 +1989,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -2020,9 +2001,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -2035,9 +2016,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -2050,9 +2031,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2065,9 +2046,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2080,9 +2061,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2095,9 +2076,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2110,9 +2091,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2125,9 +2106,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2140,9 +2121,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2155,9 +2136,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2170,9 +2151,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -2185,9 +2166,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -2200,9 +2181,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2215,9 +2196,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2230,9 +2211,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2245,9 +2226,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2260,9 +2241,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2275,9 +2256,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2290,9 +2271,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2305,9 +2286,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2317,9 +2298,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -2329,9 +2310,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -2341,9 +2322,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -2356,9 +2337,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -2370,9 +2351,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -2384,9 +2365,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -2398,9 +2379,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -2412,9 +2393,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -2426,9 +2407,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -2440,9 +2421,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -2457,9 +2438,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -2471,9 +2452,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -2483,9 +2464,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -2498,9 +2479,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -2513,9 +2494,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2528,9 +2509,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2543,9 +2524,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2558,9 +2539,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2573,9 +2554,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2588,9 +2569,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2603,9 +2584,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2618,9 +2599,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -2633,9 +2614,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -2648,9 +2629,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2663,9 +2644,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2678,9 +2659,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2693,9 +2674,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2708,9 +2689,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2723,9 +2704,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2738,9 +2719,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -2750,9 +2731,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -2762,9 +2743,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -2774,9 +2755,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -2817,7 +2798,7 @@ Array [ Object { "props": Object { "x": 10, - "y": 80.3125, + "y": 10, }, "transform": Array [ 1, @@ -2825,28 +2806,9 @@ Array [ 0, 1, 10, - 80.3125, - ], - "type": "translate", - }, - Object { - "props": Object { - "a": 1, - "b": 0, - "c": 0, - "d": -1, - "e": 0, - "f": 0, - }, - "transform": Array [ - 1, - 0, - 0, - -1, 10, - 80.3125, ], - "type": "transform", + "type": "translate", }, Object { "props": Object { @@ -2857,9 +2819,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "scale", }, @@ -2869,9 +2831,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -2884,9 +2846,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -2898,9 +2860,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -2912,9 +2874,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -2926,9 +2888,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -2940,9 +2902,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -2954,9 +2916,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -2968,9 +2930,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -2985,9 +2947,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -2999,9 +2961,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -3011,9 +2973,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -3026,9 +2988,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -3041,9 +3003,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3056,9 +3018,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3071,9 +3033,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3086,9 +3048,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3101,9 +3063,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3116,9 +3078,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3131,9 +3093,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3146,9 +3108,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3161,9 +3123,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -3176,9 +3138,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -3191,9 +3153,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3206,9 +3168,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3221,9 +3183,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3236,9 +3198,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3251,9 +3213,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3266,9 +3228,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3281,9 +3243,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3296,9 +3258,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3308,9 +3270,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -3320,9 +3282,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -3332,9 +3294,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -3347,9 +3309,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -3361,9 +3323,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -3375,9 +3337,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -3389,9 +3351,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -3403,9 +3365,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -3417,9 +3379,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -3431,9 +3393,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -3448,9 +3410,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -3462,9 +3424,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -3474,9 +3436,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -3489,9 +3451,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -3504,9 +3466,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3519,9 +3481,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3534,9 +3496,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3549,9 +3511,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3564,9 +3526,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3579,9 +3541,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3594,9 +3556,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3609,9 +3571,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -3624,9 +3586,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -3639,9 +3601,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3654,9 +3616,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3669,9 +3631,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3684,9 +3646,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3699,9 +3661,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3714,9 +3676,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3729,9 +3691,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3741,9 +3703,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -3753,9 +3715,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -3765,9 +3727,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -3780,9 +3742,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -3794,9 +3756,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -3808,9 +3770,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -3822,9 +3784,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -3836,9 +3798,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -3850,9 +3812,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -3864,9 +3826,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -3881,9 +3843,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -3895,9 +3857,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -3907,9 +3869,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -3922,9 +3884,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -3937,9 +3899,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3952,9 +3914,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3967,9 +3929,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3982,9 +3944,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -3997,9 +3959,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4012,9 +3974,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4027,9 +3989,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4042,9 +4004,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4057,9 +4019,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -4072,9 +4034,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -4087,9 +4049,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4102,9 +4064,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4117,9 +4079,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4132,9 +4094,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4147,9 +4109,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4162,9 +4124,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4177,9 +4139,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4192,9 +4154,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4204,9 +4166,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -4216,9 +4178,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -4228,9 +4190,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -4243,9 +4205,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -4257,9 +4219,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -4271,9 +4233,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -4285,9 +4247,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -4299,9 +4261,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -4313,9 +4275,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -4327,9 +4289,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -4344,9 +4306,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -4358,9 +4320,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -4370,9 +4332,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -4385,9 +4347,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -4400,9 +4362,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4415,9 +4377,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4430,9 +4392,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4445,9 +4407,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4460,9 +4422,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4475,9 +4437,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4490,9 +4452,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4505,9 +4467,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -4520,9 +4482,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -4535,9 +4497,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4550,9 +4512,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4565,9 +4527,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4580,9 +4542,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4595,9 +4557,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4610,9 +4572,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4625,9 +4587,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4637,9 +4599,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -4649,9 +4611,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -4661,9 +4623,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -4676,9 +4638,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -4690,9 +4652,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -4704,9 +4666,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -4718,9 +4680,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -4732,9 +4694,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -4746,9 +4708,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -4760,9 +4722,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -4777,9 +4739,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -4791,9 +4753,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -4803,9 +4765,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -4818,9 +4780,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -4833,9 +4795,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4848,9 +4810,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4863,9 +4825,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4878,9 +4840,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4893,9 +4855,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4908,9 +4870,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4923,9 +4885,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4938,9 +4900,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4953,9 +4915,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -4968,9 +4930,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -4983,9 +4945,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -4998,9 +4960,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5013,9 +4975,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5028,9 +4990,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5043,9 +5005,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5058,9 +5020,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5073,9 +5035,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5088,9 +5050,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5100,9 +5062,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -5112,9 +5074,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -5124,9 +5086,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -5139,9 +5101,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "clip", }, @@ -5153,9 +5115,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -5167,9 +5129,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -5181,9 +5143,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "fillStyle", }, @@ -5195,9 +5157,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -5209,9 +5171,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -5223,9 +5185,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -5240,9 +5202,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "setLineDash", }, @@ -5254,9 +5216,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineDashOffset", }, @@ -5266,9 +5228,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -5281,9 +5243,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -5296,9 +5258,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5311,9 +5273,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5326,9 +5288,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5341,9 +5303,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5356,9 +5318,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5371,9 +5333,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5386,9 +5348,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5401,9 +5363,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -5416,9 +5378,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -5431,9 +5393,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5446,9 +5408,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5461,9 +5423,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5476,9 +5438,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5491,9 +5453,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5506,9 +5468,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5521,9 +5483,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5533,9 +5495,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -5545,9 +5507,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -5557,9 +5519,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "save", }, @@ -5571,9 +5533,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "globalAlpha", }, @@ -5585,9 +5547,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineWidth", }, @@ -5599,9 +5561,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "strokeStyle", }, @@ -5613,9 +5575,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineCap", }, @@ -5627,9 +5589,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineJoin", }, @@ -5639,9 +5601,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -5654,9 +5616,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -5669,9 +5631,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5684,9 +5646,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "beginPath", }, @@ -5699,9 +5661,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "moveTo", }, @@ -5714,9 +5676,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "lineTo", }, @@ -5726,9 +5688,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "stroke", }, @@ -5738,9 +5700,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, @@ -5750,9 +5712,9 @@ Array [ 0.078125, 0, 0, - -0.078125, + 0.078125, + 10, 10, - 80.3125, ], "type": "restore", }, diff --git a/src/renderers/svg/HanziWriterRenderer.ts b/src/renderers/svg/HanziWriterRenderer.ts index a13116ba1..73403458d 100644 --- a/src/renderers/svg/HanziWriterRenderer.ts +++ b/src/renderers/svg/HanziWriterRenderer.ts @@ -29,13 +29,9 @@ export default class HanziWriterRenderer mount(target: SVGRenderTarget) { const positionedTarget = target.createSubRenderTarget(); const group = positionedTarget.svg; - const { xOffset, yOffset, height, scale } = this._positioner; + const { xOffset, yOffset, scale } = this._positioner; - svg.attr( - group, - 'transform', - `translate(${xOffset}, ${height - yOffset}) scale(${scale}, ${-1 * scale})`, - ); + svg.attr(group, 'transform', `translate(${xOffset}, ${yOffset}) scale(${scale})`); this._outlineCharRenderer.mount(positionedTarget); this._mainCharRenderer.mount(positionedTarget); this._highlightCharRenderer.mount(positionedTarget); From 7abbf1203c7d8109996e748ce6f64f3bfac294ee Mon Sep 17 00:00:00 2001 From: jamsch Date: Tue, 14 Jun 2022 08:12:57 +1200 Subject: [PATCH 2/6] feat: add `processCharData` option to allow transforms to character data once downloaded. Note: by exposing this option, this removes the "transformY(-1)" style on SVG/Canvas renderers and instead applies a "900-Y" transform. --- src/HanziWriter.ts | 26 +- src/Mutation.ts | 15 +- src/Quiz.ts | 10 +- src/__tests__/Character-test.ts | 52 + src/__tests__/HanziWriter-test.ts | 52 +- src/__tests__/Quiz-test.ts | 18 +- src/__tests__/RenderState-test.ts | 5 +- .../__snapshots__/HanziWriter-test.ts.snap | 288 +-- src/__tests__/parseCharData-test.ts | 14 - src/__tests__/strokeMatches-test.ts | 1991 ++++++++--------- src/__tests__/utils-test.ts | 34 - src/characterActions.ts | 5 +- src/geometry.ts | 4 +- src/models/Character.ts | 62 + src/parseCharData.ts | 19 - .../__tests__/CharacterRenderer-test.ts | 4 +- .../__tests__/HanziWriterRenderer-test.ts | 5 +- .../canvas/__tests__/StrokeRenderer-test.ts | 4 +- .../CharacterRenderer-test.ts.snap | 68 +- .../HanziWriterRenderer-test.ts.snap | 408 ++-- .../__snapshots__/StrokeRenderer-test.ts.snap | 106 +- src/renderers/canvas/canvasUtils.ts | 15 +- .../svg/__tests__/CharacterRenderer-test.ts | 4 +- .../svg/__tests__/HanziWriterRenderer-test.ts | 5 +- .../svg/__tests__/StrokeRenderer-test.ts | 4 +- .../__snapshots__/StrokeRenderer-test.ts.snap | 2 +- src/typings/types.ts | 11 +- src/utils.ts | 57 +- 28 files changed, 1688 insertions(+), 1600 deletions(-) create mode 100644 src/__tests__/Character-test.ts delete mode 100644 src/__tests__/parseCharData-test.ts delete mode 100644 src/parseCharData.ts diff --git a/src/HanziWriter.ts b/src/HanziWriter.ts index cdcc27933..3ef92f546 100644 --- a/src/HanziWriter.ts +++ b/src/HanziWriter.ts @@ -1,5 +1,4 @@ import RenderState from './RenderState'; -import parseCharData from './parseCharData'; import Positioner from './Positioner'; import Quiz from './Quiz'; import svgRenderer from './renderers/svg'; @@ -7,7 +6,7 @@ import canvasRenderer from './renderers/canvas'; import defaultOptions from './defaultOptions'; import LoadingManager from './LoadingManager'; import * as characterActions from './characterActions'; -import { trim, colorStringToVals } from './utils'; +import { colorStringToVals } from './utils'; import Character from './models/Character'; import HanziWriterRendererBase, { HanziWriterRendererConstructor, @@ -90,14 +89,12 @@ export default class HanziWriter { static getScalingTransform(width: number, height: number, padding = 0) { const positioner = new Positioner({ width, height, padding }); + const { xOffset: x, yOffset: y, scale } = positioner; return { - x: positioner.xOffset, - y: positioner.yOffset, - scale: positioner.scale, - transform: trim(` - translate(${positioner.xOffset}, ${positioner.yOffset}) - scale(${positioner.scale}) - `).replace(/\s+/g, ' '), + x, + y, + scale, + transform: `translate(${x}, ${y}) scale(${scale})`, }; } @@ -424,13 +421,18 @@ export default class HanziWriter { this._hanziWriterRenderer = null; this._withDataPromise = this._loadingManager .loadCharData(char) - .then((pathStrings) => { + .then((characterJson) => { // if "pathStrings" isn't set, ".catch()"" was probably called and loading likely failed - if (!pathStrings || this._loadingManager.loadingFailed) { + if (!characterJson || this._loadingManager.loadingFailed) { return; } - this._character = parseCharData(char, pathStrings); + this._character = Character.fromObject( + char, + characterJson, + this._options.processCharData, + ); + this._renderState = new RenderState(this._character, this._options, (nextState) => hanziWriterRenderer.render(nextState), ); diff --git a/src/Mutation.ts b/src/Mutation.ts index fe45f9952..284f2775b 100644 --- a/src/Mutation.ts +++ b/src/Mutation.ts @@ -29,7 +29,7 @@ class Delay implements GenericMutation { _duration: number; _startTime: number | null; _paused: boolean; - _timeout!: NodeJS.Timeout; + _timeout!: ReturnType; _resolve: (() => void) | undefined; constructor(duration: number) { @@ -43,7 +43,6 @@ class Delay implements GenericMutation { this._startTime = performanceNow(); this._runningPromise = new Promise((resolve) => { this._resolve = resolve; - // @ts-ignore return type of "setTimeout" in builds is parsed as `number` instead of `Timeout` this._timeout = setTimeout(() => this.cancel(), this._duration); }) as Promise; return this._runningPromise; @@ -61,13 +60,12 @@ class Delay implements GenericMutation { resume() { if (!this._paused) return; this._startTime = performance.now(); - // @ts-ignore return type of "setTimeout" in builds is parsed as `number` instead of `Timeout` this._timeout = setTimeout(() => this.cancel(), this._duration); this._paused = false; } cancel() { - clearTimeout(this._timeout!); + clearTimeout(this._timeout); if (this._resolve) { this._resolve(); } @@ -140,10 +138,11 @@ export default class Mutation< } private _inflateValues(renderState: TRenderStateClass) { - let values = this._valuesOrCallable; - if (typeof this._valuesOrCallable === 'function') { - values = this._valuesOrCallable(renderState.state); - } + const values = + typeof this._valuesOrCallable === 'function' + ? this._valuesOrCallable(renderState.state) + : this._valuesOrCallable; + this._values = inflate(this.scope, values); } diff --git a/src/Quiz.ts b/src/Quiz.ts index b53b0f3b3..05834c01e 100644 --- a/src/Quiz.ts +++ b/src/Quiz.ts @@ -6,6 +6,7 @@ import * as quizActions from './quizActions'; import * as geometry from './geometry'; import * as characterActions from './characterActions'; import Character from './models/Character'; +import Stroke from './models/Stroke'; import { ParsedHanziWriterOptions, Point, StrokeData } from './typings/types'; import RenderState from './RenderState'; import { MutationChain } from './Mutation'; @@ -112,11 +113,8 @@ export default class Quiz { } else { this._handleFailure(meta); - const { - showHintAfterMisses, - highlightColor, - strokeHighlightSpeed, - } = this._options!; + const { showHintAfterMisses, highlightColor, strokeHighlightSpeed } = + this._options!; if ( showHintAfterMisses !== false && @@ -219,7 +217,7 @@ export default class Quiz { this._options!.onMistake?.(this._getStrokeData({ isCorrect: false, meta })); } - _getCurrentStroke() { + _getCurrentStroke(): Stroke { return this._character.strokes[this._currentStrokeIndex]; } } diff --git a/src/__tests__/Character-test.ts b/src/__tests__/Character-test.ts new file mode 100644 index 000000000..742dde15e --- /dev/null +++ b/src/__tests__/Character-test.ts @@ -0,0 +1,52 @@ +import ta from 'hanzi-writer-data/他.json'; +import { CharacterJson } from 'typings/types'; +import Character from '../models/Character'; + +describe('Character', () => { + describe('fromObject', () => { + it("does not transform stroke paths if 'null' is provided in the 'processCharacter' param", () => { + const character = Character.fromObject('他', ta, null); + for (let i = 0; i < ta.strokes.length; i++) { + expect(character.strokes[i].path).toEqual(ta.strokes[i]); + } + }); + it('correctly parses a given object', () => { + const res = Character.fromObject('他', ta); + expect(res.strokes).toHaveLength(5); + expect(res.strokes[0].isInRadical).toBe(true); + expect(res.strokes[1].isInRadical).toBe(true); + expect(res.strokes[2].isInRadical).toBe(false); + expect(res.strokes[3].isInRadical).toBe(false); + expect(res.strokes[4].isInRadical).toBe(false); + }); + it("applies 'scaleX(-1)' transform to path strings by default", () => { + const strokeTransforms = [ + { + before: 'L 400 500 C 100 200 100 300 100 400 Q 100 200 100 300 Z', + after: `L 400 400 C 100 700 100 600 100 500 Q 100 700 100 600 Z`, + }, + { + before: 'L 1 150 M 1 250 C 1 350 3 450 5 650 Q 1 750 3 850 Z', + after: 'L 1 750 M 1 650 C 1 550 3 450 5 250 Q 1 150 3 50 Z', + }, + // Verify paths with commas also get correctly scaled + { + before: 'L 1,150 M 1,250 C 1,350,3,450,5,650 Q 1,750,3,850 Z', + after: 'L 1 750 M 1 650 C 1 550 3 450 5 250 Q 1 150 3 50 Z', + }, + ]; + + const basicCharJson: CharacterJson = { + strokes: strokeTransforms.map((transform) => transform.before), + medians: [[], [], []], + radStrokes: undefined, + }; + + const res = Character.fromObject('他', basicCharJson); + + for (let i = 0; i < strokeTransforms.length; i++) { + expect(res.strokes[i].path).toEqual(strokeTransforms[i].after); + } + }); + }); +}); diff --git a/src/__tests__/HanziWriter-test.ts b/src/__tests__/HanziWriter-test.ts index 7bc009bfb..abe656b0e 100644 --- a/src/__tests__/HanziWriter-test.ts +++ b/src/__tests__/HanziWriter-test.ts @@ -9,7 +9,7 @@ import HanziWriter from '../HanziWriter'; import { timeout } from '../utils'; import { resolvePromises } from '../testUtils'; import Quiz from '../Quiz'; -import parseCharData from '../parseCharData'; +import Character from '../models/Character'; const charDataLoader = () => ren; @@ -309,7 +309,7 @@ describe('HanziWriter', () => { charDataLoader, }); const character = await writer.getCharacterData(); - expect(character).toEqual(parseCharData('人', ren)); + expect(character).toEqual(Character.fromObject('人', ren)); }); it('returns a promise with the loaded character after initial loading is done', async () => { @@ -318,7 +318,7 @@ describe('HanziWriter', () => { }); await writer._withDataPromise; const character = await writer.getCharacterData(); - expect(character).toEqual(parseCharData('人', ren)); + expect(character).toEqual(Character.fromObject('人', ren)); }); it('errors if no character has been set yet', async () => { @@ -526,8 +526,8 @@ describe('HanziWriter', () => { clock.tick(50); await resolvePromises(); - const pausedDisplayPortion = writer._renderState!.state.character.main.strokes[1] - .displayPortion; + const pausedDisplayPortion = + writer._renderState!.state.character.main.strokes[1].displayPortion; expect(pausedDisplayPortion).toBeGreaterThan(0); expect(pausedDisplayPortion).toBeLessThan(1); expect(isResolved).toBe(false); @@ -549,8 +549,8 @@ describe('HanziWriter', () => { clock.tick(50); await resolvePromises(); - const newDisplayPortion = writer._renderState!.state.character.main.strokes[1] - .displayPortion; + const newDisplayPortion = + writer._renderState!.state.character.main.strokes[1].displayPortion; expect(newDisplayPortion).not.toBe(pausedDisplayPortion); expect(newDisplayPortion).toBeGreaterThan(0); expect(newDisplayPortion).toBeLessThan(1); @@ -618,6 +618,18 @@ describe('HanziWriter', () => { expect(onComplete).toHaveBeenCalledTimes(1); expect(onComplete).toHaveBeenCalledWith({ canceled: false }); }); + + it('resolves with undefined if no character has been set', async () => { + document.body.innerHTML = '
'; + + const writer = new HanziWriter('target', { charDataLoader }); + const onComplete = jest.fn(); + + const returnValue = await writer.highlightStroke(1, { onComplete }); + + expect(onComplete).toHaveBeenCalledTimes(0); + expect(returnValue).toBeUndefined(); + }); }); describe('loopCharacterAnimation', () => { @@ -690,10 +702,12 @@ describe('HanziWriter', () => { }); }); - ([ - { methodLabel: 'Character', stateLabel: 'main' }, - { methodLabel: 'Outline', stateLabel: 'outline' }, - ] as const).forEach(({ methodLabel, stateLabel }) => { + ( + [ + { methodLabel: 'Character', stateLabel: 'main' }, + { methodLabel: 'Outline', stateLabel: 'outline' }, + ] as const + ).forEach(({ methodLabel, stateLabel }) => { const hideMethod = methodLabel === 'Character' ? 'hideCharacter' : 'hideOutline'; const showMethod = methodLabel === 'Character' ? 'showCharacter' : 'showOutline'; @@ -992,9 +1006,10 @@ describe('HanziWriter', () => { writer._positioner, ); expect(writer._quiz!.startQuiz).toHaveBeenCalledTimes(1); - expect(writer._quiz!.startQuiz).toHaveBeenCalledWith( - Object.assign({}, writer._options, { onComplete }), - ); + expect(writer._quiz!.startQuiz).toHaveBeenCalledWith({ + ...writer._options, + onComplete, + }); }); }); @@ -1106,6 +1121,15 @@ describe('HanziWriter', () => { }); describe('loadCharacterData', () => { + it('avoids creating a new "LoadingManager" instance if options and character dont change', async () => { + const options = { + charDataLoader: () => ren, + }; + HanziWriter.loadCharacterData('人', options); + const instance = HanziWriter._loadingManager; + HanziWriter.loadCharacterData('人', options); + expect(instance).toStrictEqual(HanziWriter._loadingManager); + }); it('calls onLoadCharDataError if provided on loading failure', async () => { const onLoadCharDataError = jest.fn(); const loadingPromise = HanziWriter.loadCharacterData('人', { diff --git a/src/__tests__/Quiz-test.ts b/src/__tests__/Quiz-test.ts index a1d045eac..a69993f69 100644 --- a/src/__tests__/Quiz-test.ts +++ b/src/__tests__/Quiz-test.ts @@ -3,12 +3,12 @@ jest.mock('../Positioner'); import ren from 'hanzi-writer-data/人.json'; import Quiz from '../Quiz'; -import parseCharData from '../parseCharData'; import RenderState from '../RenderState'; import Positioner from '../Positioner'; import { resolvePromises } from '../testUtils'; import strokeMatches from '../strokeMatches'; import { Point } from '../typings/types'; +import Character from '../models/Character'; (Positioner as any).mockImplementation(() => ({ convertExternalPoint: (point: Point) => ({ x: point.x + 5, y: point.y + 5 }), @@ -19,7 +19,7 @@ beforeEach(() => { (Positioner as any).mockClear(); }); -const char = parseCharData('人', ren); +const char = Character.fromObject('人', ren); const opts: any = { onLoadCharDataError: null, onLoadCharDataSuccess: null, @@ -151,6 +151,20 @@ describe('Quiz', () => { }); describe('startUserStroke', () => { + it('returns null if the quiz hasnt started', async () => { + const renderState = createRenderState(); + const quiz = new Quiz( + char, + renderState, + new Positioner({ padding: 20, width: 200, height: 200 }), + ); + const returnValue = quiz.startUserStroke({ x: 10, y: 20 }); + expect(returnValue).toBe(null); + + await resolvePromises(); + + expect(renderState.state.userStrokes).toBe(null); + }); it('begins a stroke with the provided point', async () => { const renderState = createRenderState(); const quiz = new Quiz( diff --git a/src/__tests__/RenderState-test.ts b/src/__tests__/RenderState-test.ts index 4e6ad7812..1f3d05650 100644 --- a/src/__tests__/RenderState-test.ts +++ b/src/__tests__/RenderState-test.ts @@ -1,9 +1,10 @@ import ren from 'hanzi-writer-data/人.json'; +import Character from '../models/Character'; import Mutation from '../Mutation'; import RenderState from '../RenderState'; -import parseCharData from '../parseCharData'; -const char = parseCharData('人', ren); +const char = Character.fromObject('人', ren); + const opts = { strokeColor: '#555', radicalColor: '#123', diff --git a/src/__tests__/__snapshots__/HanziWriter-test.ts.snap b/src/__tests__/__snapshots__/HanziWriter-test.ts.snap index a2e241408..995144761 100644 --- a/src/__tests__/__snapshots__/HanziWriter-test.ts.snap +++ b/src/__tests__/__snapshots__/HanziWriter-test.ts.snap @@ -45,7 +45,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -60,7 +60,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -75,7 +75,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -90,7 +90,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -105,7 +105,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -120,7 +120,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -135,7 +135,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -150,7 +150,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -165,7 +165,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -207,7 +207,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -222,7 +222,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -237,7 +237,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -252,7 +252,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -267,7 +267,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -282,7 +282,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -297,7 +297,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -312,7 +312,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -354,7 +354,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -369,7 +369,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -384,7 +384,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -399,7 +399,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -414,7 +414,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -429,7 +429,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -444,7 +444,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -459,7 +459,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -474,7 +474,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -516,7 +516,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -531,7 +531,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -546,7 +546,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -561,7 +561,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -576,7 +576,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -591,7 +591,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -606,7 +606,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -621,7 +621,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -863,7 +863,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -878,7 +878,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -893,7 +893,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -908,7 +908,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -923,7 +923,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -938,7 +938,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -953,7 +953,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -968,7 +968,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -983,7 +983,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -1013,7 +1013,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -1028,7 +1028,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -1043,7 +1043,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -1058,7 +1058,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -1073,7 +1073,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -1088,7 +1088,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -1103,7 +1103,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -1118,7 +1118,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -1133,7 +1133,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -1326,7 +1326,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -1341,7 +1341,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -1356,7 +1356,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -1371,7 +1371,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -1386,7 +1386,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -1401,7 +1401,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -1416,7 +1416,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -1431,7 +1431,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -1461,7 +1461,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -1476,7 +1476,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -1491,7 +1491,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -1506,7 +1506,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -1521,7 +1521,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -1536,7 +1536,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -1551,7 +1551,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -1566,7 +1566,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -1759,7 +1759,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -1774,7 +1774,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -1789,7 +1789,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -1804,7 +1804,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -1819,7 +1819,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -1834,7 +1834,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -1849,7 +1849,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -1864,7 +1864,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -1879,7 +1879,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -1909,7 +1909,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ -0.0390625, @@ -1924,7 +1924,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ -0.0390625, @@ -1939,7 +1939,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ -0.0390625, @@ -1954,7 +1954,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ -0.0390625, @@ -1969,7 +1969,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ -0.0390625, @@ -1984,7 +1984,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ -0.0390625, @@ -1999,7 +1999,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ -0.0390625, @@ -2014,7 +2014,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ -0.0390625, @@ -2029,7 +2029,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ -0.0390625, @@ -2222,7 +2222,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -2237,7 +2237,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -2252,7 +2252,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -2267,7 +2267,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -2282,7 +2282,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -2297,7 +2297,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -2312,7 +2312,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -2327,7 +2327,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -2357,7 +2357,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -2372,7 +2372,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -2387,7 +2387,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -2402,7 +2402,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -2417,7 +2417,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -2432,7 +2432,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -2447,7 +2447,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -2462,7 +2462,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -2566,7 +2566,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ -0.0390625, @@ -2581,7 +2581,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ -0.0390625, @@ -2596,7 +2596,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ -0.0390625, @@ -2611,7 +2611,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ -0.0390625, @@ -2626,7 +2626,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ -0.0390625, @@ -2641,7 +2641,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ -0.0390625, @@ -2656,7 +2656,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ -0.0390625, @@ -2671,7 +2671,7 @@ CanvasRenderingContext2D { Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ -0.0390625, @@ -2913,123 +2913,123 @@ CanvasRenderingContext2D { "calls": Array [ Array [ 508, - 702, + 198, ], Array [ 511, - 678, + 222, ], Array [ 473, - 552, + 348, ], Array [ 408, - 416, + 484, ], Array [ 328, - 303, + 597, ], Array [ 271, - 244, + 656, ], Array [ 144, - 139, + 761, ], Array [ 72, - 95, + 805, ], Array [ 477, - 459, + 441, ], Array [ 490, - 439, + 461, ], Array [ 571, - 333, + 567, ], Array [ 691, - 200, + 700, ], Array [ 753, - 145, + 755, ], Array [ 798, - 119, + 781, ], Array [ 986, - 90, + 810, ], Array [ 508, - 702, + 198, ], Array [ 511, - 678, + 222, ], Array [ 473, - 552, + 348, ], Array [ 408, - 416, + 484, ], Array [ 328, - 303, + 597, ], Array [ 271, - 244, + 656, ], Array [ 144, - 139, + 761, ], Array [ 72, - 95, + 805, ], Array [ 477, - 459, + 441, ], Array [ 490, - 439, + 461, ], Array [ 571, - 333, + 567, ], Array [ 691, - 200, + 700, ], Array [ 753, - 145, + 755, ], Array [ 798, - 119, + 781, ], Array [ 986, - 90, + 810, ], ], "results": Array [ @@ -3160,19 +3160,19 @@ CanvasRenderingContext2D { "calls": Array [ Array [ 423.7609549522482, - 816.5651012649424, + 83.43489873505753, ], Array [ 457.56010126946427, - 575.6393923832144, + 324.3606076167856, ], Array [ 423.7609549522482, - 816.5651012649424, + 83.43489873505753, ], Array [ 457.56010126946427, - 575.6393923832144, + 324.3606076167856, ], ], "results": Array [ diff --git a/src/__tests__/parseCharData-test.ts b/src/__tests__/parseCharData-test.ts deleted file mode 100644 index 7a743be05..000000000 --- a/src/__tests__/parseCharData-test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import ta from 'hanzi-writer-data/他.json'; -import parseCharData from '../parseCharData'; - -describe('parseCharData', () => { - it('creates a Character object from character json', () => { - const res = parseCharData('他', ta); - expect(res.strokes).toHaveLength(5); - expect(res.strokes[0].isInRadical).toBe(true); - expect(res.strokes[1].isInRadical).toBe(true); - expect(res.strokes[2].isInRadical).toBe(false); - expect(res.strokes[3].isInRadical).toBe(false); - expect(res.strokes[4].isInRadical).toBe(false); - }); -}); diff --git a/src/__tests__/strokeMatches-test.ts b/src/__tests__/strokeMatches-test.ts index 15f5ae88c..c08dd59bf 100644 --- a/src/__tests__/strokeMatches-test.ts +++ b/src/__tests__/strokeMatches-test.ts @@ -1,14 +1,13 @@ import strokeMatches from '../strokeMatches'; import Stroke from '../models/Stroke'; import UserStroke from '../models/UserStroke'; -import parseCharData from '../parseCharData'; import { Point } from '../typings/types'; import Character from '../models/Character'; const getChar = (charStr: string): Character => { // eslint-disable-next-line @typescript-eslint/no-var-requires const charJson = require(`hanzi-writer-data/${charStr}.json`); - return parseCharData(charStr, charJson); + return Character.fromObject(charStr, charJson); }; const assertMatches = ( @@ -144,262 +143,262 @@ describe('strokeMatches', () => { it('matches using real data 1', () => { assertMatches('人', 0, [ - { x: 409.6, y: 746.4 }, - { x: 409.6, y: 746.4 }, - { x: 409.6, y: 746.4 }, - { x: 409.6, y: 743.5555555555555 }, - { x: 409.6, y: 735.0222222222222 }, - { x: 409.6, y: 723.6444444444444 }, - { x: 406.75555555555553, y: 709.4222222222222 }, - { x: 401.06666666666666, y: 695.2 }, - { x: 395.3777777777778, y: 675.2888888888889 }, - { x: 392.53333333333336, y: 658.2222222222222 }, - { x: 384, y: 635.4666666666667 }, - { x: 378.31111111111113, y: 615.5555555555555 }, - { x: 372.6222222222222, y: 592.8 }, - { x: 366.93333333333334, y: 570.0444444444445 }, - { x: 358.4, y: 547.2888888888889 }, - { x: 347.02222222222224, y: 516 }, - { x: 338.4888888888889, y: 498.93333333333334 }, - { x: 335.64444444444445, y: 487.55555555555554 }, - { x: 329.9555555555556, y: 476.1777777777778 }, - { x: 324.26666666666665, y: 464.8 }, - { x: 318.5777777777778, y: 450.5777777777778 }, - { x: 312.8888888888889, y: 433.5111111111111 }, - { x: 304.35555555555555, y: 422.1333333333333 }, - { x: 295.8222222222222, y: 405.06666666666666 }, - { x: 290.1333333333333, y: 393.68888888888887 }, - { x: 287.2888888888889, y: 388 }, - { x: 275.9111111111111, y: 370.93333333333334 }, - { x: 273.06666666666666, y: 362.4 }, - { x: 267.3777777777778, y: 353.8666666666667 }, - { x: 261.68888888888887, y: 348.1777777777778 }, - { x: 258.84444444444443, y: 342.4888888888889 }, - { x: 256, y: 336.8 }, - { x: 253.15555555555557, y: 333.9555555555556 }, - { x: 247.46666666666667, y: 328.26666666666665 }, - { x: 244.62222222222223, y: 325.4222222222222 }, - { x: 241.77777777777777, y: 319.73333333333335 }, - { x: 236.0888888888889, y: 314.0444444444444 }, - { x: 233.24444444444444, y: 311.2 }, - { x: 227.55555555555554, y: 305.5111111111111 }, - { x: 224.7111111111111, y: 299.8222222222222 }, - { x: 219.0222222222222, y: 294.1333333333333 }, - { x: 210.48888888888888, y: 285.6 }, - { x: 204.8, y: 279.9111111111111 }, - { x: 196.26666666666668, y: 268.53333333333336 }, - { x: 193.42222222222222, y: 265.68888888888887 }, - { x: 182.04444444444445, y: 254.3111111111111 }, - { x: 173.51111111111112, y: 245.77777777777777 }, - { x: 167.82222222222222, y: 237.24444444444444 }, - { x: 164.9777777777778, y: 234.4 }, - { x: 156.44444444444446, y: 225.86666666666667 }, - { x: 147.9111111111111, y: 220.17777777777778 }, - { x: 142.22222222222223, y: 214.48888888888888 }, - { x: 139.37777777777777, y: 211.64444444444445 }, - { x: 130.84444444444443, y: 205.95555555555555 }, - { x: 122.31111111111112, y: 200.26666666666668 }, - { x: 119.46666666666667, y: 197.42222222222222 }, - { x: 113.77777777777777, y: 194.57777777777778 }, - { x: 110.93333333333334, y: 191.73333333333332 }, - { x: 105.24444444444444, y: 188.88888888888889 }, - { x: 99.55555555555556, y: 186.04444444444445 }, - { x: 93.86666666666666, y: 180.35555555555555 }, - { x: 88.17777777777778, y: 177.51111111111112 }, - { x: 82.4888888888889, y: 171.82222222222222 }, - { x: 76.8, y: 168.9777777777778 }, - { x: 71.11111111111111, y: 166.13333333333333 }, - { x: 68.26666666666667, y: 163.2888888888889 }, - { x: 65.42222222222222, y: 157.6 }, - { x: 62.577777777777776, y: 154.75555555555556 }, - { x: 56.888888888888886, y: 154.75555555555556 }, - { x: 56.888888888888886, y: 151.9111111111111 }, - { x: 54.044444444444444, y: 151.9111111111111 }, + { x: 409.6, y: 153.6 }, + { x: 409.6, y: 153.6 }, + { x: 409.6, y: 153.6 }, + { x: 409.6, y: 156.4 }, + { x: 409.6, y: 165 }, + { x: 409.6, y: 176.4 }, + { x: 406.8, y: 190.58 }, + { x: 401.1, y: 204.8 }, + { x: 395.4, y: 224.7 }, + { x: 392.5, y: 241.83 }, + { x: 384, y: 264.5 }, + { x: 378.3, y: 284.4 }, + { x: 372.6, y: 307.2 }, + { x: 366.94, y: 329.9 }, + { x: 358.4, y: 352.7 }, + { x: 347.1, y: 384 }, + { x: 338.5, y: 401.1 }, + { x: 335.64, y: 412.4 }, + { x: 329.9, y: 423.8 }, + { x: 324.3, y: 435.2 }, + { x: 318.6, y: 449.4 }, + { x: 312.9, y: 466.5 }, + { x: 304.36, y: 477.9 }, + { x: 295.8, y: 494.94 }, + { x: 290.1, y: 506.3 }, + { x: 287.3, y: 512 }, + { x: 275.9, y: 529.1 }, + { x: 273.1, y: 537.6 }, + { x: 267.4, y: 546.1 }, + { x: 261.7, y: 551.8 }, + { x: 258.8, y: 557.5 }, + { x: 256, y: 563.2 }, + { x: 253.2, y: 566.1 }, + { x: 247.5, y: 571.7 }, + { x: 244.63, y: 574.6 }, + { x: 241.8, y: 580.3 }, + { x: 236.1, y: 585.9 }, + { x: 233.24, y: 588.8 }, + { x: 227.64, y: 594.5 }, + { x: 224.7, y: 600.2 }, + { x: 219.1, y: 605.9 }, + { x: 210.58, y: 614.4 }, + { x: 204.8, y: 620.1 }, + { x: 196.3, y: 631.5 }, + { x: 193.42, y: 634.3 }, + { x: 182.04, y: 645.7 }, + { x: 173.5, y: 654.2 }, + { x: 167.82, y: 662.8 }, + { x: 164.9, y: 665.6 }, + { x: 156.4, y: 674.1 }, + { x: 147.9, y: 679.8 }, + { x: 142.23, y: 685.5 }, + { x: 139.4, y: 688.4 }, + { x: 130.8, y: 694.1 }, + { x: 122.3, y: 699.7 }, + { x: 119.5, y: 702.6 }, + { x: 113.8, y: 705.4 }, + { x: 110.94, y: 708.3 }, + { x: 105.24, y: 711.1 }, + { x: 99.66, y: 713.9 }, + { x: 93.9, y: 719.6 }, + { x: 88.18, y: 722.5 }, + { x: 82.5, y: 728.2 }, + { x: 76.8, y: 731.1 }, + { x: 71.11, y: 733.9 }, + { x: 68.3, y: 736.7 }, + { x: 65.42, y: 742.4 }, + { x: 62.6, y: 745.2 }, + { x: 56.9, y: 745.2 }, + { x: 56.9, y: 748.1 }, + { x: 54.1, y: 748.1 }, ]); }); it('matches using real data 2', () => { assertMatches('人', 1, [ - { x: 583.1111111111111, y: 516 }, - { x: 583.1111111111111, y: 516 }, - { x: 583.1111111111111, y: 516 }, - { x: 585.9555555555555, y: 513.1555555555556 }, - { x: 594.4888888888889, y: 501.77777777777777 }, - { x: 620.0888888888888, y: 473.3333333333333 }, - { x: 648.5333333333333, y: 436.35555555555555 }, - { x: 691.2, y: 388 }, - { x: 736.7111111111111, y: 333.9555555555556 }, - { x: 790.7555555555556, y: 279.9111111111111 }, - { x: 850.4888888888889, y: 217.33333333333334 }, - { x: 890.3111111111111, y: 180.35555555555555 }, - { x: 938.6666666666666, y: 137.6888888888889 }, - { x: 975.6444444444444, y: 109.24444444444444 }, - { x: 992.7111111111111, y: 97.86666666666666 }, - { x: 998.4, y: 95.02222222222223 }, - { x: 998.4, y: 95.02222222222223 }, + { x: 583.1, y: 384 }, + { x: 583.1, y: 384 }, + { x: 583.1, y: 384 }, + { x: 585.9, y: 386.8 }, + { x: 594.5, y: 398.23 }, + { x: 620.1, y: 426.6666666666667 }, + { x: 648.5, y: 463.64 }, + { x: 691.2, y: 512 }, + { x: 736.7, y: 566.1 }, + { x: 790.8, y: 620.1 }, + { x: 850.5, y: 682.6666666666666 }, + { x: 890.3, y: 719.6 }, + { x: 938.6666666666666, y: 762.3 }, + { x: 975.6, y: 790.8 }, + { x: 992.7, y: 802.1 }, + { x: 998.4, y: 804.9 }, + { x: 998.4, y: 804.9 }, ]); }); it('does not match using real data 1', () => { assertNotMatches('人', 0, [ - { x: 133.6888888888889, y: 595.6444444444444 }, - { x: 133.6888888888889, y: 595.6444444444444 }, - { x: 136.53333333333333, y: 595.6444444444444 }, - { x: 150.75555555555556, y: 595.6444444444444 }, - { x: 199.11111111111111, y: 595.6444444444444 }, - { x: 281.6, y: 595.6444444444444 }, - { x: 392.53333333333336, y: 595.6444444444444 }, - { x: 475.02222222222224, y: 595.6444444444444 }, - { x: 546.1333333333333, y: 595.6444444444444 }, - { x: 588.8, y: 595.6444444444444 }, - { x: 608.7111111111111, y: 595.6444444444444 }, - { x: 614.4, y: 595.6444444444444 }, - { x: 617.2444444444444, y: 595.6444444444444 }, - { x: 620.0888888888888, y: 595.6444444444444 }, - { x: 620.0888888888888, y: 595.6444444444444 }, - { x: 620.0888888888888, y: 595.6444444444444 }, - { x: 620.0888888888888, y: 595.6444444444444 }, + { x: 133.7, y: 304.4 }, + { x: 133.7, y: 304.4 }, + { x: 136.53, y: 304.4 }, + { x: 150.8, y: 304.4 }, + { x: 199.11, y: 304.4 }, + { x: 281.6, y: 304.4 }, + { x: 392.5, y: 304.4 }, + { x: 475.1, y: 304.4 }, + { x: 546.1, y: 304.4 }, + { x: 588.8, y: 304.4 }, + { x: 608.7, y: 304.4 }, + { x: 614.4, y: 304.4 }, + { x: 617.2, y: 304.4 }, + { x: 620.1, y: 304.4 }, + { x: 620.1, y: 304.4 }, + { x: 620.1, y: 304.4 }, + { x: 620.1, y: 304.4 }, ]); }); it('does not match using real data 2', () => { assertNotMatches('人', 0, [ - { x: 31.288888888888888, y: 285.6 }, - { x: 28.444444444444443, y: 285.6 }, - { x: 34.13333333333333, y: 288.44444444444446 }, - { x: 54.044444444444444, y: 302.6666666666667 }, - { x: 102.4, y: 333.9555555555556 }, - { x: 201.95555555555555, y: 393.68888888888887 }, - { x: 287.2888888888889, y: 450.5777777777778 }, - { x: 386.84444444444443, y: 516 }, - { x: 452.26666666666665, y: 555.8222222222222 }, - { x: 506.31111111111113, y: 584.2666666666667 }, - { x: 560.3555555555556, y: 612.7111111111111 }, - { x: 603.0222222222222, y: 635.4666666666667 }, - { x: 642.8444444444444, y: 658.2222222222222 }, - { x: 676.9777777777778, y: 678.1333333333333 }, - { x: 705.4222222222222, y: 692.3555555555556 }, - { x: 719.6444444444444, y: 698.0444444444445 }, - { x: 725.3333333333334, y: 700.8888888888889 }, - { x: 728.1777777777778, y: 703.7333333333333 }, - { x: 733.8666666666667, y: 706.5777777777778 }, - { x: 733.8666666666667, y: 706.5777777777778 }, + { x: 31.3, y: 614.4 }, + { x: 28.4, y: 614.4 }, + { x: 34.1, y: 611.6 }, + { x: 54.1, y: 597.3 }, + { x: 102.4, y: 566.1 }, + { x: 202, y: 506.3 }, + { x: 287.3, y: 449.4 }, + { x: 386.8, y: 384 }, + { x: 452.3, y: 344.2 }, + { x: 506.3, y: 315.75 }, + { x: 560.4, y: 287.3 }, + { x: 603.1, y: 264.5 }, + { x: 642.8444444444444, y: 241.83 }, + { x: 676.9, y: 221.9 }, + { x: 705.4, y: 207.6 }, + { x: 719.6, y: 201.92 }, + { x: 725.3333333333334, y: 199.1 }, + { x: 728.2, y: 196.3 }, + { x: 733.9, y: 193.42 }, + { x: 733.9, y: 193.42 }, ]); }); it('does not match using real data 3', () => { assertNotMatches('人', 0, [ - { x: 395.3777777777778, y: 712.2666666666667 }, - { x: 395.3777777777778, y: 712.2666666666667 }, - { x: 395.3777777777778, y: 703.7333333333333 }, - { x: 395.3777777777778, y: 692.3555555555556 }, - { x: 395.3777777777778, y: 686.6666666666666 }, - { x: 392.53333333333336, y: 672.4444444444445 }, - { x: 386.84444444444443, y: 658.2222222222222 }, - { x: 384, y: 646.8444444444444 }, - { x: 381.15555555555557, y: 635.4666666666667 }, - { x: 378.31111111111113, y: 626.9333333333333 }, - { x: 375.46666666666664, y: 621.2444444444444 }, - { x: 372.6222222222222, y: 615.5555555555555 }, - { x: 372.6222222222222, y: 615.5555555555555 }, - { x: 372.6222222222222, y: 612.7111111111111 }, - { x: 369.77777777777777, y: 612.7111111111111 }, - { x: 369.77777777777777, y: 612.7111111111111 }, + { x: 395.4, y: 187.7 }, + { x: 395.4, y: 187.7 }, + { x: 395.4, y: 196.3 }, + { x: 395.4, y: 207.6 }, + { x: 395.4, y: 213.3 }, + { x: 392.5, y: 227.6 }, + { x: 386.8, y: 241.8 }, + { x: 384, y: 253.2 }, + { x: 381.2, y: 264.5 }, + { x: 378.3, y: 273 }, + { x: 375.5, y: 278.8 }, + { x: 372.6, y: 284.4 }, + { x: 372.6, y: 284.4 }, + { x: 372.6, y: 287.3 }, + { x: 369.8, y: 287.3 }, + { x: 369.8, y: 287.3 }, ]); }); it('does not match using real data 4', () => { assertNotMatches('人', 0, [ - { x: 961.4222222222222, y: 680.9777777777778 }, - { x: 961.4222222222222, y: 680.9777777777778 }, - { x: 961.4222222222222, y: 680.9777777777778 }, - { x: 961.4222222222222, y: 678.1333333333333 }, - { x: 961.4222222222222, y: 675.2888888888889 }, - { x: 961.4222222222222, y: 669.6 }, - { x: 955.7333333333333, y: 655.3777777777777 }, - { x: 952.8888888888889, y: 638.3111111111111 }, - { x: 944.3555555555556, y: 615.5555555555555 }, - { x: 935.8222222222222, y: 587.1111111111111 }, - { x: 924.4444444444445, y: 555.8222222222222 }, - { x: 913.0666666666667, y: 524.5333333333333 }, - { x: 896, y: 473.3333333333333 }, - { x: 881.7777777777778, y: 427.8222222222222 }, - { x: 873.2444444444444, y: 393.68888888888887 }, - { x: 864.7111111111111, y: 368.0888888888889 }, - { x: 844.8, y: 305.5111111111111 }, - { x: 836.2666666666667, y: 268.53333333333336 }, - { x: 822.0444444444445, y: 231.55555555555554 }, - { x: 810.6666666666666, y: 203.11111111111111 }, - { x: 802.1333333333333, y: 177.51111111111112 }, - { x: 790.7555555555556, y: 154.75555555555556 }, - { x: 782.2222222222222, y: 134.84444444444443 }, - { x: 773.6888888888889, y: 117.77777777777777 }, - { x: 765.1555555555556, y: 103.55555555555556 }, - { x: 756.6222222222223, y: 86.4888888888889 }, - { x: 750.9333333333333, y: 77.95555555555555 }, - { x: 745.2444444444444, y: 69.42222222222222 }, - { x: 742.4, y: 63.733333333333334 }, - { x: 739.5555555555555, y: 63.733333333333334 }, - { x: 739.5555555555555, y: 60.888888888888886 }, - { x: 739.5555555555555, y: 60.888888888888886 }, - { x: 736.7111111111111, y: 60.888888888888886 }, - { x: 736.7111111111111, y: 60.888888888888886 }, - { x: 736.7111111111111, y: 60.888888888888886 }, - { x: 733.8666666666667, y: 60.888888888888886 }, - { x: 733.8666666666667, y: 60.888888888888886 }, - { x: 733.8666666666667, y: 60.888888888888886 }, - { x: 733.8666666666667, y: 60.888888888888886 }, - { x: 733.8666666666667, y: 63.733333333333334 }, - { x: 733.8666666666667, y: 63.733333333333334 }, - { x: 733.8666666666667, y: 63.733333333333334 }, - { x: 733.8666666666667, y: 66.57777777777778 }, - { x: 733.8666666666667, y: 66.57777777777778 }, + { x: 961.4, y: 219 }, + { x: 961.4, y: 219 }, + { x: 961.4, y: 219 }, + { x: 961.4, y: 221.9 }, + { x: 961.4, y: 224.7 }, + { x: 961.4, y: 230.4 }, + { x: 955.7, y: 244.6 }, + { x: 952.9, y: 261.7 }, + { x: 944.4, y: 284.4 }, + { x: 935.8, y: 312.9 }, + { x: 924.4, y: 344.2 }, + { x: 913.1, y: 375.5 }, + { x: 896, y: 426.6666666666667 }, + { x: 881.8, y: 472.2 }, + { x: 873.2, y: 506.3 }, + { x: 864.7, y: 531.911111111111 }, + { x: 844.8, y: 594.5 }, + { x: 836.3, y: 631.5 }, + { x: 822.1, y: 668.4 }, + { x: 810.6666666666666, y: 696.9 }, + { x: 802.1, y: 722.5 }, + { x: 790.8, y: 745.2 }, + { x: 782.2, y: 765.6 }, + { x: 773.7, y: 782.2 }, + { x: 765.6, y: 796.4 }, + { x: 756.6, y: 813.5111111111111 }, + { x: 750.9, y: 822.1 }, + { x: 745.2, y: 830.6 }, + { x: 742.4, y: 836.3 }, + { x: 739.6, y: 836.3 }, + { x: 739.6, y: 839.1 }, + { x: 739.6, y: 839.1 }, + { x: 736.7, y: 839.1 }, + { x: 736.7, y: 839.1 }, + { x: 736.7, y: 839.1 }, + { x: 733.9, y: 839.1 }, + { x: 733.9, y: 839.1 }, + { x: 733.9, y: 839.1 }, + { x: 733.9, y: 839.1 }, + { x: 733.9, y: 836.3 }, + { x: 733.9, y: 836.3 }, + { x: 733.9, y: 836.3 }, + { x: 733.9, y: 833.4 }, + { x: 733.9, y: 833.4 }, ]); }); it('matches using real data 5', () => { assertMatches('国', 1, [ - { x: 337.2, y: 717 }, - { x: 347.5, y: 717 }, - { x: 378.2, y: 717 }, - { x: 408.9, y: 720.4 }, - { x: 484, y: 720.4 }, - { x: 521.6, y: 723.8 }, - { x: 600.1, y: 737.5 }, - { x: 695.6, y: 751.1 }, - { x: 740, y: 761.4 }, - { x: 852.7, y: 764.8 }, - { x: 907.3, y: 764.8 }, - { x: 931.2, y: 764.8 }, - { x: 955.1, y: 747.7 }, - { x: 958.5, y: 740.9 }, - { x: 958.5, y: 717 }, - { x: 958.5, y: 696.5 }, - { x: 958.5, y: 669.2 }, - { x: 958.5, y: 628.2 }, - { x: 927.7, y: 556.6 }, - { x: 927.7, y: 556.6 }, - { x: 924.3, y: 457.6 }, - { x: 866.3, y: 252.8 }, - { x: 866.3, y: 208.4 }, - { x: 866.3, y: 99.2 }, - { x: 866.3, y: 54.8 }, - { x: 849.2, y: -3.2 }, - { x: 842.4, y: -78.3 }, - { x: 839, y: -92 }, - { x: 828.8, y: -105.6 }, + { x: 337.2, y: 183 }, + { x: 347.5, y: 183 }, + { x: 378.2, y: 183 }, + { x: 408.9, y: 179.6 }, + { x: 484, y: 179.6 }, + { x: 521.6, y: 176.2 }, + { x: 600.1, y: 162.5 }, + { x: 695.6, y: 148.9 }, + { x: 740, y: 138.6 }, + { x: 852.7, y: 135.2 }, + { x: 907.3, y: 135.2 }, + { x: 931.2, y: 135.2 }, + { x: 955.1, y: 152.3 }, + { x: 958.5, y: 159.1 }, + { x: 958.5, y: 183 }, + { x: 958.5, y: 203.5 }, + { x: 958.5, y: 230.8 }, + { x: 958.5, y: 271.8 }, + { x: 927.7, y: 343.4 }, + { x: 927.7, y: 343.4 }, + { x: 924.3, y: 442.4 }, + { x: 866.3, y: 647.2 }, + { x: 866.3, y: 691.6 }, + { x: 866.3, y: 800.8 }, + { x: 866.3, y: 845.2 }, + { x: 849.2, y: 903.2 }, + { x: 842.4, y: 978.3 }, + { x: 839, y: 992 }, + { x: 828.8, y: 1005.6 }, ]); }); it('matches using real data 6', () => { const points = [ - { x: 412.3, y: 423.4 }, - { x: 463.5, y: 423.4 }, - { x: 501.1, y: 423.4 }, - { x: 518.1, y: 423.4 }, - { x: 528.4, y: 423.4 }, - { x: 562.5, y: 423.4 }, - { x: 576.2, y: 423.4 }, + { x: 412.3, y: 476.6 }, + { x: 463.5, y: 476.6 }, + { x: 501.1, y: 476.6 }, + { x: 518.1, y: 476.6 }, + { x: 528.4, y: 476.6 }, + { x: 562.5, y: 476.6 }, + { x: 576.2, y: 476.6 }, ]; assertNotMatches('国', 2, points, { isOutlineVisible: true }); assertMatches('国', 3, points, { isOutlineVisible: true }); @@ -409,14 +408,14 @@ describe('strokeMatches', () => { it('matches using real data 7', () => { const points = [ - { x: 197.3, y: 568.8 }, - { x: 201.1, y: 561.2 }, - { x: 348, y: 579 }, - { x: 557.8, y: 605.6 }, - { x: 768.2, y: 630.1 }, - { x: 840.5, y: 633.6 }, - { x: 807.1, y: 524 }, - { x: 722.1, y: 197.1 }, + { x: 197.3, y: 331.2 }, + { x: 201.1, y: 338.8 }, + { x: 348, y: 321 }, + { x: 557.8, y: 294.4 }, + { x: 768.2, y: 269.9 }, + { x: 840.5, y: 266.4 }, + { x: 807.1, y: 376 }, + { x: 722.1, y: 702.9 }, ]; assertNotMatches('中', 0, points); assertMatches('中', 1, points); @@ -425,9 +424,9 @@ describe('strokeMatches', () => { it('matches using real data 8', () => { const points = [ - { x: 234.8, y: 433.4 }, - { x: 161.3, y: 325.5 }, - { x: 43.9, y: 119.7 }, + { x: 234.8, y: 466.6 }, + { x: 161.3, y: 574.5 }, + { x: 43.9, y: 780.3 }, ]; assertNotMatches('小', 0, points); assertMatches('小', 1, points); @@ -436,12 +435,12 @@ describe('strokeMatches', () => { it('matches using real data 9', () => { const points = [ - { x: 618.7, y: 378.9 }, - { x: 659.7, y: 385.7 }, - { x: 704.1, y: 402.8 }, - { x: 717.7, y: 413 }, - { x: 758.7, y: 430.1 }, - { x: 772.3, y: 433.5 }, + { x: 618.7, y: 521.1 }, + { x: 659.7, y: 514.3 }, + { x: 704.1, y: 497.2 }, + { x: 717.7, y: 487 }, + { x: 758.7, y: 469.9 }, + { x: 772.3, y: 466.5 }, ]; assertNotMatches('谁', 5, points); assertMatches('谁', 6, points); @@ -449,30 +448,30 @@ describe('strokeMatches', () => { it('matches using real data 10', () => { const points = [ - { x: 239.8, y: 717.5 }, - { x: 263.7, y: 717.5 }, - { x: 403.7, y: 755 }, - { x: 441.2, y: 765.3 }, - { x: 499.3, y: 785.8 }, - { x: 509.5, y: 792.6 }, - { x: 512.9, y: 792.6 }, - { x: 489, y: 734.6 }, - { x: 472, y: 710.7 }, - { x: 441.2, y: 669.7 }, - { x: 424.2, y: 635.6 }, - { x: 410.5, y: 533.2 }, - { x: 390, y: 400.1 }, - { x: 355.9, y: 290.8 }, - { x: 352.5, y: 273.8 }, - { x: 345.7, y: 263.5 }, - { x: 342.2, y: 249.9 }, - { x: 335.4, y: 239.6 }, - { x: 335.4, y: 232.8 }, - { x: 325.2, y: 232.8 }, - { x: 321.8, y: 239.6 }, - { x: 274, y: 284 }, - { x: 239.8, y: 311.3 }, - { x: 226.2, y: 342 }, + { x: 239.8, y: 182.5 }, + { x: 263.7, y: 182.5 }, + { x: 403.7, y: 145 }, + { x: 441.2, y: 134.7 }, + { x: 499.3, y: 114.2 }, + { x: 509.5, y: 107.4 }, + { x: 512.9, y: 107.4 }, + { x: 489, y: 165.4 }, + { x: 472, y: 189.3 }, + { x: 441.2, y: 230.3 }, + { x: 424.2, y: 264.4 }, + { x: 410.5, y: 366.8 }, + { x: 390, y: 499.9 }, + { x: 355.9, y: 609.2 }, + { x: 352.5, y: 626.2 }, + { x: 345.7, y: 636.5 }, + { x: 342.2, y: 650.1 }, + { x: 335.4, y: 660.4 }, + { x: 335.4, y: 667.2 }, + { x: 325.2, y: 667.2 }, + { x: 321.8, y: 660.4 }, + { x: 274, y: 616 }, + { x: 239.8, y: 588.7 }, + { x: 226.2, y: 558 }, ]; assertMatches('那', 0, points); assertNotMatches('那', 1, points); @@ -480,26 +479,26 @@ describe('strokeMatches', () => { it('matches using real data 11', () => { const points = [ - { x: 40.7, y: 425.9 }, - { x: 47.6, y: 425.9 }, - { x: 163.6, y: 484 }, - { x: 194.3, y: 490.8 }, - { x: 303.6, y: 538.6 }, - { x: 344.5, y: 548.8 }, - { x: 347.9, y: 548.8 }, - { x: 347.9, y: 538.6 }, - { x: 303.6, y: 367.9 }, - { x: 255.8, y: 268.9 }, - { x: 248.9, y: 241.6 }, - { x: 228.5, y: 156.3 }, - { x: 225.1, y: 129 }, - { x: 225.1, y: 129 }, - { x: 228.5, y: 129 }, - { x: 293.3, y: 187 }, - { x: 310.4, y: 210.9 }, - { x: 351.3, y: 251.9 }, - { x: 382.1, y: 272.3 }, - { x: 392.3, y: 286 }, + { x: 40.7, y: 474.1 }, + { x: 47.6, y: 474.1 }, + { x: 163.6, y: 416 }, + { x: 194.3, y: 409.2 }, + { x: 303.6, y: 361.4 }, + { x: 344.5, y: 351.2 }, + { x: 347.9, y: 351.2 }, + { x: 347.9, y: 361.4 }, + { x: 303.6, y: 532.1 }, + { x: 255.8, y: 631.1 }, + { x: 248.9, y: 658.4 }, + { x: 228.5, y: 743.7 }, + { x: 225.1, y: 771 }, + { x: 225.1, y: 771 }, + { x: 228.5, y: 771 }, + { x: 293.3, y: 713 }, + { x: 310.4, y: 689.1 }, + { x: 351.3, y: 648.1 }, + { x: 382.1, y: 627.7 }, + { x: 392.3, y: 614 }, ]; assertNotMatches('语', 0, points); assertMatches('语', 1, points); @@ -508,52 +507,52 @@ describe('strokeMatches', () => { it('matches using real data 12', () => { const points = [ - { x: 512, y: 735.7 }, - { x: 512, y: 732.2 }, - { x: 512, y: 732.2 }, - { x: 522.2, y: 732.2 }, - { x: 525.7, y: 735.7 }, - { x: 539.3, y: 739.1 }, - { x: 553, y: 742.5 }, - { x: 566.6, y: 749.3 }, - { x: 587.1, y: 752.7 }, - { x: 600.7, y: 756.1 }, - { x: 611, y: 759.6 }, - { x: 631.5, y: 759.6 }, - { x: 645.1, y: 763 }, - { x: 658.8, y: 763 }, - { x: 669, y: 763 }, - { x: 669, y: 763 }, - { x: 672.4, y: 763 }, - { x: 675.8, y: 763 }, - { x: 679.3, y: 763 }, - { x: 682.7, y: 763 }, - { x: 682.7, y: 759.6 }, - { x: 682.7, y: 756.1 }, - { x: 689.5, y: 752.7 }, - { x: 689.5, y: 749.3 }, - { x: 689.5, y: 742.5 }, - { x: 689.5, y: 742.5 }, - { x: 692.9, y: 739.1 }, - { x: 692.9, y: 735.7 }, - { x: 692.9, y: 728.8 }, - { x: 692.9, y: 722 }, - { x: 692.9, y: 708.4 }, - { x: 692.9, y: 691.3 }, - { x: 689.5, y: 674.2 }, - { x: 689.5, y: 664 }, - { x: 682.7, y: 636.7 }, - { x: 682.7, y: 619.6 }, - { x: 672.4, y: 599.1 }, - { x: 669, y: 578.6 }, - { x: 669, y: 565 }, - { x: 662.2, y: 551.3 }, - { x: 662.2, y: 537.7 }, - { x: 658.8, y: 524 }, - { x: 648.5, y: 517.2 }, - { x: 645.1, y: 503.6 }, - { x: 645.1, y: 503.6 }, - { x: 641.7, y: 500.1 }, + { x: 512, y: 164.3 }, + { x: 512, y: 167.8 }, + { x: 512, y: 167.8 }, + { x: 522.2, y: 167.8 }, + { x: 525.7, y: 164.3 }, + { x: 539.3, y: 160.9 }, + { x: 553, y: 157.5 }, + { x: 566.6, y: 150.7 }, + { x: 587.1, y: 147.3 }, + { x: 600.7, y: 143.9 }, + { x: 611, y: 140.4 }, + { x: 631.5, y: 140.4 }, + { x: 645.1, y: 137 }, + { x: 658.8, y: 137 }, + { x: 669, y: 137 }, + { x: 669, y: 137 }, + { x: 672.4, y: 137 }, + { x: 675.8, y: 137 }, + { x: 679.3, y: 137 }, + { x: 682.7, y: 137 }, + { x: 682.7, y: 140.4 }, + { x: 682.7, y: 143.9 }, + { x: 689.5, y: 147.3 }, + { x: 689.5, y: 150.7 }, + { x: 689.5, y: 157.5 }, + { x: 689.5, y: 157.5 }, + { x: 692.9, y: 160.9 }, + { x: 692.9, y: 164.3 }, + { x: 692.9, y: 171.2 }, + { x: 692.9, y: 178 }, + { x: 692.9, y: 191.6 }, + { x: 692.9, y: 208.7 }, + { x: 689.5, y: 225.8 }, + { x: 689.5, y: 236 }, + { x: 682.7, y: 263.3 }, + { x: 682.7, y: 280.4 }, + { x: 672.4, y: 300.9 }, + { x: 669, y: 321.4 }, + { x: 669, y: 335 }, + { x: 662.2, y: 348.7 }, + { x: 662.2, y: 362.3 }, + { x: 658.8, y: 376 }, + { x: 648.5, y: 382.8 }, + { x: 645.1, y: 396.4 }, + { x: 645.1, y: 396.4 }, + { x: 641.7, y: 399.9 }, ]; assertNotMatches('很', 2, points); assertMatches('很', 3, points); @@ -564,34 +563,34 @@ describe('strokeMatches', () => { it('matches using real data 13', () => { const points = [ - { x: 325, y: 684.3 }, - { x: 325, y: 687.7 }, - { x: 328.4, y: 691.1 }, - { x: 331.8, y: 694.6 }, - { x: 366, y: 704.8 }, - { x: 403.5, y: 708.2 }, - { x: 461.5, y: 718.5 }, - { x: 533.2, y: 725.3 }, - { x: 604.9, y: 738.9 }, - { x: 697.1, y: 752.6 }, - { x: 741.4, y: 762.8 }, - { x: 765.3, y: 773.1 }, - { x: 775.6, y: 776.5 }, - { x: 779, y: 776.5 }, - { x: 782.4, y: 779.9 }, - { x: 789.2, y: 779.9 }, - { x: 799.5, y: 779.9 }, - { x: 826.8, y: 779.9 }, - { x: 840.4, y: 779.9 }, - { x: 843.8, y: 779.9 }, - { x: 847.3, y: 776.5 }, - { x: 847.3, y: 773.1 }, - { x: 840.4, y: 762.8 }, - { x: 833.6, y: 749.2 }, - { x: 823.4, y: 742.3 }, - { x: 802.9, y: 725.3 }, - { x: 775.6, y: 701.4 }, - { x: 738, y: 684.3 }, + { x: 325, y: 215.7 }, + { x: 325, y: 212.3 }, + { x: 328.4, y: 208.9 }, + { x: 331.8, y: 205.4 }, + { x: 366, y: 195.2 }, + { x: 403.5, y: 191.8 }, + { x: 461.5, y: 181.5 }, + { x: 533.2, y: 174.7 }, + { x: 604.9, y: 161.1 }, + { x: 697.1, y: 147.4 }, + { x: 741.4, y: 137.2 }, + { x: 765.3, y: 126.9 }, + { x: 775.6, y: 123.5 }, + { x: 779, y: 123.5 }, + { x: 782.4, y: 120.1 }, + { x: 789.2, y: 120.1 }, + { x: 799.5, y: 120.1 }, + { x: 826.8, y: 120.1 }, + { x: 840.4, y: 120.1 }, + { x: 843.8, y: 120.1 }, + { x: 847.3, y: 123.5 }, + { x: 847.3, y: 126.9 }, + { x: 840.4, y: 137.2 }, + { x: 833.6, y: 150.8 }, + { x: 823.4, y: 157.7 }, + { x: 802.9, y: 174.7 }, + { x: 775.6, y: 198.6 }, + { x: 738, y: 215.7 }, ]; assertNotMatches('写', 0, points); assertMatches('写', 1, points); @@ -600,52 +599,52 @@ describe('strokeMatches', () => { it('matches using real data 14', () => { const points = [ - { x: 55.4, y: 497.6 }, - { x: 62.2, y: 504.4 }, - { x: 96.3, y: 511.3 }, - { x: 195.3, y: 524.9 }, - { x: 280.6, y: 535.1 }, - { x: 362.6, y: 535.1 }, - { x: 434.2, y: 538.6 }, - { x: 502.5, y: 542 }, - { x: 560.5, y: 545.4 }, - { x: 591.3, y: 545.4 }, - { x: 604.9, y: 545.4 }, - { x: 608.3, y: 545.4 }, - { x: 615.1, y: 538.6 }, - { x: 615.1, y: 535.1 }, - { x: 615.1, y: 528.3 }, - { x: 615.1, y: 514.7 }, - { x: 615.1, y: 494.2 }, - { x: 615.1, y: 463.5 }, - { x: 601.5, y: 429.3 }, - { x: 584.4, y: 381.5 }, - { x: 567.4, y: 344 }, - { x: 546.9, y: 289.4 }, - { x: 526.4, y: 241.6 }, - { x: 502.5, y: 190.4 }, - { x: 492.3, y: 149.4 }, - { x: 482, y: 101.7 }, - { x: 482, y: 74.3 }, - { x: 485.4, y: 53.9 }, - { x: 495.7, y: 36.8 }, - { x: 512.7, y: 19.7 }, - { x: 543.5, y: 2.7 }, - { x: 601.5, y: -11 }, - { x: 676.6, y: -17.8 }, - { x: 758.5, y: -28.1 }, - { x: 826.8, y: -28.1 }, - { x: 874.6, y: -28.1 }, - { x: 918.9, y: -28.1 }, - { x: 942.8, y: -17.8 }, - { x: 963.3, y: -4.2 }, - { x: 977, y: 9.5 }, - { x: 987.2, y: 23.1 }, - { x: 990.6, y: 40.2 }, - { x: 990.6, y: 57.3 }, - { x: 990.6, y: 88 }, - { x: 990.6, y: 115.3 }, - { x: 990.6, y: 135.8 }, + { x: 55.4, y: 402.4 }, + { x: 62.2, y: 395.6 }, + { x: 96.3, y: 388.7 }, + { x: 195.3, y: 375.1 }, + { x: 280.6, y: 364.9 }, + { x: 362.6, y: 364.9 }, + { x: 434.2, y: 361.4 }, + { x: 502.5, y: 358 }, + { x: 560.5, y: 354.6 }, + { x: 591.3, y: 354.6 }, + { x: 604.9, y: 354.6 }, + { x: 608.3, y: 354.6 }, + { x: 615.1, y: 361.4 }, + { x: 615.1, y: 364.9 }, + { x: 615.1, y: 371.7 }, + { x: 615.1, y: 385.3 }, + { x: 615.1, y: 405.8 }, + { x: 615.1, y: 436.5 }, + { x: 601.5, y: 470.7 }, + { x: 584.4, y: 518.5 }, + { x: 567.4, y: 556 }, + { x: 546.9, y: 610.6 }, + { x: 526.4, y: 658.4 }, + { x: 502.5, y: 709.6 }, + { x: 492.3, y: 750.6 }, + { x: 482, y: 798.3 }, + { x: 482, y: 825.7 }, + { x: 485.4, y: 846.1 }, + { x: 495.7, y: 863.2 }, + { x: 512.7, y: 880.3 }, + { x: 543.5, y: 897.3 }, + { x: 601.5, y: 911 }, + { x: 676.6, y: 917.8 }, + { x: 758.5, y: 928.1 }, + { x: 826.8, y: 928.1 }, + { x: 874.6, y: 928.1 }, + { x: 918.9, y: 928.1 }, + { x: 942.8, y: 917.8 }, + { x: 963.3, y: 904.2 }, + { x: 977, y: 890.5 }, + { x: 987.2, y: 876.9 }, + { x: 990.6, y: 859.8 }, + { x: 990.6, y: 842.7 }, + { x: 990.6, y: 812 }, + { x: 990.6, y: 784.7 }, + { x: 990.6, y: 764.2 }, ]; assertNotMatches('九', 0, points); assertMatches('九', 1, points); @@ -653,58 +652,58 @@ describe('strokeMatches', () => { it('matches using real data 15', () => { const points = [ - { x: 455.1, y: 681 }, - { x: 455.1, y: 683.8 }, - { x: 458, y: 683.8 }, - { x: 463.6, y: 683.8 }, - { x: 483.6, y: 683.8 }, - { x: 503.5, y: 683.8 }, - { x: 531.9, y: 686.7 }, - { x: 563.2, y: 686.7 }, - { x: 594.5, y: 689.5 }, - { x: 620.1, y: 692.4 }, - { x: 637.2, y: 692.4 }, - { x: 648.5, y: 692.4 }, - { x: 657.1, y: 692.4 }, - { x: 662.8, y: 692.4 }, - { x: 662.8, y: 692.4 }, - { x: 665.6, y: 692.4 }, - { x: 665.6, y: 689.5 }, - { x: 665.6, y: 683.8 }, - { x: 665.6, y: 678.1 }, - { x: 665.6, y: 669.6 }, - { x: 665.6, y: 661.1 }, - { x: 662.8, y: 644 }, - { x: 659.9, y: 626.9 }, - { x: 648.5, y: 590 }, - { x: 640, y: 570 }, - { x: 634.3, y: 550.1 }, - { x: 628.6, y: 535.9 }, - { x: 622.9, y: 527.4 }, - { x: 620.1, y: 521.7 }, - { x: 617.2, y: 516 }, - { x: 617.2, y: 513.2 }, - { x: 617.2, y: 510.3 }, - { x: 617.2, y: 510.3 }, - { x: 622.9, y: 507.5 }, - { x: 628.6, y: 501.8 }, - { x: 637.2, y: 498.9 }, - { x: 642.8, y: 493.2 }, - { x: 645.7, y: 487.6 }, - { x: 648.5, y: 484.7 }, - { x: 651.4, y: 476.2 }, - { x: 651.4, y: 464.8 }, - { x: 654.2, y: 450.6 }, - { x: 654.2, y: 430.7 }, - { x: 654.2, y: 410.8 }, - { x: 648.5, y: 393.7 }, - { x: 640, y: 379.5 }, - { x: 625.8, y: 365.2 }, - { x: 597.3, y: 342.5 }, - { x: 571.7, y: 328.3 }, - { x: 551.8, y: 322.6 }, - { x: 531.9, y: 316.9 }, - { x: 526.2, y: 314 }, + { x: 455.1, y: 219 }, + { x: 455.1, y: 216.2 }, + { x: 458, y: 216.2 }, + { x: 463.6, y: 216.2 }, + { x: 483.6, y: 216.2 }, + { x: 503.5, y: 216.2 }, + { x: 531.9, y: 213.3 }, + { x: 563.2, y: 213.3 }, + { x: 594.5, y: 210.5 }, + { x: 620.1, y: 207.6 }, + { x: 637.2, y: 207.6 }, + { x: 648.5, y: 207.6 }, + { x: 657.1, y: 207.6 }, + { x: 662.8, y: 207.6 }, + { x: 662.8, y: 207.6 }, + { x: 665.6, y: 207.6 }, + { x: 665.6, y: 210.5 }, + { x: 665.6, y: 216.2 }, + { x: 665.6, y: 221.9 }, + { x: 665.6, y: 230.4 }, + { x: 665.6, y: 238.9 }, + { x: 662.8, y: 256 }, + { x: 659.9, y: 273.1 }, + { x: 648.5, y: 310 }, + { x: 640, y: 330 }, + { x: 634.3, y: 349.9 }, + { x: 628.6, y: 364.1 }, + { x: 622.9, y: 372.6 }, + { x: 620.1, y: 378.3 }, + { x: 617.2, y: 384 }, + { x: 617.2, y: 386.8 }, + { x: 617.2, y: 389.7 }, + { x: 617.2, y: 389.7 }, + { x: 622.9, y: 392.5 }, + { x: 628.6, y: 398.2 }, + { x: 637.2, y: 401.1 }, + { x: 642.8, y: 406.8 }, + { x: 645.7, y: 412.4 }, + { x: 648.5, y: 415.3 }, + { x: 651.4, y: 423.8 }, + { x: 651.4, y: 435.2 }, + { x: 654.2, y: 449.4 }, + { x: 654.2, y: 469.3 }, + { x: 654.2, y: 489.2 }, + { x: 648.5, y: 506.3 }, + { x: 640, y: 520.5 }, + { x: 625.8, y: 534.8 }, + { x: 597.3, y: 557.5 }, + { x: 571.7, y: 571.7 }, + { x: 551.8, y: 577.4 }, + { x: 531.9, y: 583.1 }, + { x: 526.2, y: 586 }, ]; assertMatches('阝', 0, points); assertNotMatches('阝', 1, points); @@ -712,93 +711,93 @@ describe('strokeMatches', () => { it('matches using real data 16', () => { const points = [ - { x: 386.8, y: 743.4 }, - { x: 390.3, y: 740 }, - { x: 407.3, y: 740 }, - { x: 424.4, y: 740 }, - { x: 441.5, y: 740 }, - { x: 458.5, y: 740 }, - { x: 479, y: 740 }, - { x: 496.1, y: 740 }, - { x: 516.6, y: 740 }, - { x: 530.2, y: 740 }, - { x: 540.4, y: 740 }, - { x: 550.7, y: 740 }, - { x: 564.3, y: 740 }, - { x: 574.6, y: 740 }, - { x: 581.4, y: 740 }, - { x: 588.2, y: 740 }, - { x: 595.1, y: 740 }, - { x: 598.5, y: 740 }, - { x: 605.3, y: 740 }, - { x: 612.1, y: 740 }, - { x: 619, y: 740 }, - { x: 625.8, y: 740 }, - { x: 632.6, y: 740 }, - { x: 639.4, y: 740 }, - { x: 639.4, y: 743.4 }, - { x: 642.8, y: 743.4 }, - { x: 646.3, y: 743.4 }, - { x: 646.3, y: 746.8 }, - { x: 649.7, y: 750.2 }, - { x: 653.1, y: 750.2 }, - { x: 659.9, y: 753.6 }, - { x: 663.3, y: 753.6 }, - { x: 666.7, y: 753.6 }, - { x: 666.7, y: 757 }, - { x: 666.7, y: 753.6 }, - { x: 666.7, y: 746.8 }, - { x: 666.7, y: 736.6 }, - { x: 666.7, y: 722.9 }, - { x: 666.7, y: 719.5 }, - { x: 666.7, y: 716.1 }, - { x: 666.7, y: 702.4 }, - { x: 663.3, y: 678.5 }, - { x: 659.9, y: 647.8 }, - { x: 656.5, y: 606.9 }, - { x: 653.1, y: 576.1 }, - { x: 649.7, y: 552.2 }, - { x: 649.7, y: 538.6 }, - { x: 649.7, y: 524.9 }, - { x: 649.7, y: 524.9 }, - { x: 646.3, y: 524.9 }, - { x: 646.3, y: 524.9 }, - { x: 642.8, y: 524.9 }, - { x: 639.4, y: 524.9 }, - { x: 636, y: 528.3 }, - { x: 636, y: 531.8 }, - { x: 632.6, y: 531.8 }, - { x: 632.6, y: 535.2 }, - { x: 629.2, y: 538.6 }, - { x: 629.2, y: 542 }, - { x: 619, y: 545.4 }, - { x: 608.7, y: 552.2 }, - { x: 598.5, y: 555.7 }, - { x: 584.8, y: 555.7 }, - { x: 574.6, y: 555.7 }, - { x: 564.3, y: 555.7 }, - { x: 554.1, y: 555.7 }, - { x: 547.3, y: 555.7 }, - { x: 537, y: 555.7 }, - { x: 526.8, y: 555.7 }, - { x: 516.6, y: 555.7 }, - { x: 509.7, y: 555.7 }, - { x: 499.5, y: 555.7 }, - { x: 489.2, y: 555.7 }, - { x: 479, y: 555.7 }, - { x: 468.8, y: 555.7 }, - { x: 465.4, y: 555.7 }, - { x: 461.9, y: 555.7 }, - { x: 458.5, y: 555.7 }, - { x: 455.1, y: 555.7 }, - { x: 451.7, y: 555.7 }, - { x: 444.9, y: 555.7 }, - { x: 438, y: 555.7 }, - { x: 427.8, y: 552.2 }, - { x: 417.6, y: 552.2 }, - { x: 417.6, y: 552.2 }, - { x: 414.2, y: 552.2 }, - { x: 410.7, y: 552.2 }, + { x: 386.8, y: 156.6 }, + { x: 390.3, y: 160 }, + { x: 407.3, y: 160 }, + { x: 424.4, y: 160 }, + { x: 441.5, y: 160 }, + { x: 458.5, y: 160 }, + { x: 479, y: 160 }, + { x: 496.1, y: 160 }, + { x: 516.6, y: 160 }, + { x: 530.2, y: 160 }, + { x: 540.4, y: 160 }, + { x: 550.7, y: 160 }, + { x: 564.3, y: 160 }, + { x: 574.6, y: 160 }, + { x: 581.4, y: 160 }, + { x: 588.2, y: 160 }, + { x: 595.1, y: 160 }, + { x: 598.5, y: 160 }, + { x: 605.3, y: 160 }, + { x: 612.1, y: 160 }, + { x: 619, y: 160 }, + { x: 625.8, y: 160 }, + { x: 632.6, y: 160 }, + { x: 639.4, y: 160 }, + { x: 639.4, y: 156.6 }, + { x: 642.8, y: 156.6 }, + { x: 646.3, y: 156.6 }, + { x: 646.3, y: 153.2 }, + { x: 649.7, y: 149.8 }, + { x: 653.1, y: 149.8 }, + { x: 659.9, y: 146.4 }, + { x: 663.3, y: 146.4 }, + { x: 666.7, y: 146.4 }, + { x: 666.7, y: 143 }, + { x: 666.7, y: 146.4 }, + { x: 666.7, y: 153.2 }, + { x: 666.7, y: 163.4 }, + { x: 666.7, y: 177.1 }, + { x: 666.7, y: 180.5 }, + { x: 666.7, y: 183.9 }, + { x: 666.7, y: 197.6 }, + { x: 663.3, y: 221.5 }, + { x: 659.9, y: 252.2 }, + { x: 656.5, y: 293.1 }, + { x: 653.1, y: 323.9 }, + { x: 649.7, y: 347.8 }, + { x: 649.7, y: 361.4 }, + { x: 649.7, y: 375.1 }, + { x: 649.7, y: 375.1 }, + { x: 646.3, y: 375.1 }, + { x: 646.3, y: 375.1 }, + { x: 642.8, y: 375.1 }, + { x: 639.4, y: 375.1 }, + { x: 636, y: 371.7 }, + { x: 636, y: 368.2 }, + { x: 632.6, y: 368.2 }, + { x: 632.6, y: 364.8 }, + { x: 629.2, y: 361.4 }, + { x: 629.2, y: 358 }, + { x: 619, y: 354.6 }, + { x: 608.7, y: 347.8 }, + { x: 598.5, y: 344.3 }, + { x: 584.8, y: 344.3 }, + { x: 574.6, y: 344.3 }, + { x: 564.3, y: 344.3 }, + { x: 554.1, y: 344.3 }, + { x: 547.3, y: 344.3 }, + { x: 537, y: 344.3 }, + { x: 526.8, y: 344.3 }, + { x: 516.6, y: 344.3 }, + { x: 509.7, y: 344.3 }, + { x: 499.5, y: 344.3 }, + { x: 489.2, y: 344.3 }, + { x: 479, y: 344.3 }, + { x: 468.8, y: 344.3 }, + { x: 465.4, y: 344.3 }, + { x: 461.9, y: 344.3 }, + { x: 458.5, y: 344.3 }, + { x: 455.1, y: 344.3 }, + { x: 451.7, y: 344.3 }, + { x: 444.9, y: 344.3 }, + { x: 438, y: 344.3 }, + { x: 427.8, y: 347.8 }, + { x: 417.6, y: 347.8 }, + { x: 417.6, y: 347.8 }, + { x: 414.2, y: 347.8 }, + { x: 410.7, y: 347.8 }, ]; assertNotMatches('弓', 0, points); assertNotMatches('弓', 1, points); @@ -820,11 +819,11 @@ describe('strokeMatches', () => { it('matches using real data 18', () => { const points = [ - { x: 553.9, y: 708.6 }, - { x: 547, y: 691.6 }, - { x: 540.2, y: 681.3 }, - { x: 540.2, y: 677.9 }, - { x: 540.2, y: 674.5 }, + { x: 553.9, y: 191.4 }, + { x: 547, y: 208.4 }, + { x: 540.2, y: 218.7 }, + { x: 540.2, y: 222.1 }, + { x: 540.2, y: 225.5 }, ]; assertNotMatches('犭', 0, points); assertNotMatches('犭', 1, points); @@ -833,56 +832,56 @@ describe('strokeMatches', () => { it('matches using real data 19', () => { const points = [ - { x: 139.5, y: 456.5 }, - { x: 142.9, y: 453.1 }, - { x: 146.3, y: 449.7 }, - { x: 149.7, y: 446.3 }, - { x: 163.4, y: 446.3 }, - { x: 173.6, y: 446.3 }, - { x: 183.8, y: 446.3 }, - { x: 197.5, y: 446.3 }, - { x: 207.7, y: 446.3 }, - { x: 224.8, y: 453.1 }, - { x: 235, y: 463.4 }, - { x: 252.1, y: 477 }, - { x: 272.6, y: 490.7 }, - { x: 276, y: 494.1 }, - { x: 282.8, y: 494.1 }, - { x: 286.2, y: 490.7 }, - { x: 289.7, y: 483.8 }, - { x: 289.7, y: 466.8 }, - { x: 289.7, y: 453.1 }, - { x: 289.7, y: 432.6 }, - { x: 289.7, y: 415.6 }, - { x: 286.2, y: 391.7 }, - { x: 286.2, y: 381.4 }, - { x: 286.2, y: 364.4 }, - { x: 286.2, y: 354.1 }, - { x: 286.2, y: 337.1 }, - { x: 286.2, y: 326.8 }, - { x: 286.2, y: 320 }, - { x: 289.7, y: 316.6 }, - { x: 293.1, y: 313.2 }, - { x: 303.3, y: 309.8 }, - { x: 320.4, y: 296.1 }, - { x: 334, y: 282.5 }, - { x: 351.1, y: 272.2 }, - { x: 357.9, y: 265.4 }, - { x: 357.9, y: 262 }, - { x: 357.9, y: 258.6 }, - { x: 361.3, y: 251.7 }, - { x: 361.3, y: 248.3 }, - { x: 361.3, y: 241.5 }, - { x: 361.3, y: 234.7 }, - { x: 361.3, y: 224.4 }, - { x: 361.3, y: 214.2 }, - { x: 351.1, y: 197.1 }, - { x: 337.4, y: 186.9 }, - { x: 313.5, y: 173.2 }, - { x: 282.8, y: 156.2 }, - { x: 252.1, y: 139.1 }, - { x: 228.2, y: 122 }, - { x: 214.6, y: 111.8 }, + { x: 139.5, y: 443.5 }, + { x: 142.9, y: 446.9 }, + { x: 146.3, y: 450.3 }, + { x: 149.7, y: 453.7 }, + { x: 163.4, y: 453.7 }, + { x: 173.6, y: 453.7 }, + { x: 183.8, y: 453.7 }, + { x: 197.5, y: 453.7 }, + { x: 207.7, y: 453.7 }, + { x: 224.8, y: 446.9 }, + { x: 235, y: 436.6 }, + { x: 252.1, y: 423 }, + { x: 272.6, y: 409.3 }, + { x: 276, y: 405.9 }, + { x: 282.8, y: 405.9 }, + { x: 286.2, y: 409.3 }, + { x: 289.7, y: 416.2 }, + { x: 289.7, y: 433.2 }, + { x: 289.7, y: 446.9 }, + { x: 289.7, y: 467.4 }, + { x: 289.7, y: 484.4 }, + { x: 286.2, y: 508.3 }, + { x: 286.2, y: 518.6 }, + { x: 286.2, y: 535.6 }, + { x: 286.2, y: 545.9 }, + { x: 286.2, y: 562.9 }, + { x: 286.2, y: 573.2 }, + { x: 286.2, y: 580 }, + { x: 289.7, y: 583.4 }, + { x: 293.1, y: 586.8 }, + { x: 303.3, y: 590.2 }, + { x: 320.4, y: 603.9 }, + { x: 334, y: 617.5 }, + { x: 351.1, y: 627.8 }, + { x: 357.9, y: 634.6 }, + { x: 357.9, y: 638 }, + { x: 357.9, y: 641.4 }, + { x: 361.3, y: 648.3 }, + { x: 361.3, y: 651.7 }, + { x: 361.3, y: 658.5 }, + { x: 361.3, y: 665.3 }, + { x: 361.3, y: 675.6 }, + { x: 361.3, y: 685.8 }, + { x: 351.1, y: 702.9 }, + { x: 337.4, y: 713.1 }, + { x: 313.5, y: 726.8 }, + { x: 282.8, y: 743.8 }, + { x: 252.1, y: 760.9 }, + { x: 228.2, y: 778 }, + { x: 214.6, y: 788.2 }, ]; assertNotMatches('这', 4, points); assertMatches('这', 5, points); @@ -891,9 +890,9 @@ describe('strokeMatches', () => { it('matches using real data 20', () => { const points = [ - { x: 483, y: 468.2 }, - { x: 472.7, y: 440.9 }, - { x: 462.5, y: 423.8 }, + { x: 483, y: 431.8 }, + { x: 472.7, y: 459.1 }, + { x: 462.5, y: 476.2 }, ]; assertNotMatches('您', 4, points); assertMatches('您', 5, points); @@ -902,11 +901,11 @@ describe('strokeMatches', () => { it('matches using real data 21', () => { const points = [ - { x: 184.1, y: 534.7 }, - { x: 214.8, y: 545 }, - { x: 320.6, y: 575.7 }, - { x: 371.8, y: 596.2 }, - { x: 375.2, y: 599.6 }, + { x: 184.1, y: 365.3 }, + { x: 214.8, y: 355 }, + { x: 320.6, y: 324.3 }, + { x: 371.8, y: 303.8 }, + { x: 375.2, y: 300.4 }, ]; assertNotMatches('吗', 0, points); assertNotMatches('吗', 1, points); @@ -915,17 +914,17 @@ describe('strokeMatches', () => { it('matches using real data 22', () => { const points = [ - { x: 496.6, y: 555.4 }, - { x: 500.1, y: 551.9 }, - { x: 513.7, y: 558.8 }, - { x: 534.2, y: 569 }, - { x: 551.3, y: 575.8 }, - { x: 571.7, y: 586.1 }, - { x: 592.2, y: 589.5 }, - { x: 609.3, y: 592.9 }, - { x: 633.2, y: 603.1 }, - { x: 640, y: 603.1 }, - { x: 643.4, y: 603.1 }, + { x: 496.6, y: 344.6 }, + { x: 500.1, y: 348.1 }, + { x: 513.7, y: 341.2 }, + { x: 534.2, y: 331 }, + { x: 551.3, y: 324.2 }, + { x: 571.7, y: 313.9 }, + { x: 592.2, y: 310.5 }, + { x: 609.3, y: 307.1 }, + { x: 633.2, y: 296.9 }, + { x: 640, y: 296.9 }, + { x: 643.4, y: 296.9 }, ]; assertNotMatches('得', 5, points); assertMatches('得', 5, points, { leniency: 2 }); @@ -934,376 +933,376 @@ describe('strokeMatches', () => { it('matches using real data 23', () => { const points = [ - { x: 500.6, y: 624.1 }, - { x: 500.6, y: 624.1 }, - { x: 500.6, y: 612.7 }, - { x: 492.1, y: 598.5 }, - { x: 480.7, y: 578.6 }, - { x: 466.5, y: 555.8 }, - { x: 452.3, y: 530.2 }, - { x: 429.5, y: 493.2 }, - { x: 415.3, y: 470.5 }, - { x: 403.9, y: 444.9 }, - { x: 389.7, y: 425 }, - { x: 378.3, y: 405.1 }, - { x: 369.8, y: 390.8 }, - { x: 361.2, y: 373.8 }, - { x: 349.9, y: 359.6 }, - { x: 341.3, y: 342.5 }, - { x: 332.8, y: 325.4 }, - { x: 324.3, y: 314 }, - { x: 318.6, y: 302.7 }, - { x: 310, y: 288.4 }, - { x: 301.5, y: 277.1 }, - { x: 293, y: 265.7 }, - { x: 287.3, y: 251.5 }, - { x: 281.6, y: 240.1 }, - { x: 273.1, y: 231.6 }, - { x: 270.2, y: 223 }, - { x: 264.5, y: 214.5 }, - { x: 261.7, y: 208.8 }, - { x: 258.8, y: 203.1 }, - { x: 256, y: 197.4 }, - { x: 253.2, y: 194.6 }, - { x: 253.2, y: 191.7 }, - { x: 253.2, y: 191.7 }, - { x: 253.2, y: 191.7 }, - { x: 253.2, y: 191.7 }, - { x: 253.2, y: 191.7 }, - { x: 253.2, y: 191.7 }, - { x: 258.8, y: 194.6 }, - { x: 264.5, y: 194.6 }, - { x: 273.1, y: 194.6 }, - { x: 287.3, y: 194.6 }, - { x: 301.5, y: 194.6 }, - { x: 315.7, y: 197.4 }, - { x: 332.8, y: 197.4 }, - { x: 349.9, y: 197.4 }, - { x: 364.1, y: 200.3 }, - { x: 378.3, y: 200.3 }, - { x: 392.5, y: 203.1 }, - { x: 403.9, y: 206 }, - { x: 415.3, y: 208.8 }, - { x: 426.7, y: 211.6 }, - { x: 435.2, y: 211.6 }, - { x: 449.4, y: 214.5 }, - { x: 460.8, y: 217.3 }, - { x: 472.2, y: 217.3 }, - { x: 489.2, y: 223 }, - { x: 497.8, y: 225.9 }, - { x: 506.3, y: 228.7 }, - { x: 514.8, y: 228.7 }, - { x: 523.4, y: 231.6 }, - { x: 531.9, y: 234.4 }, - { x: 540.4, y: 237.2 }, - { x: 549, y: 240.1 }, - { x: 563.2, y: 248.6 }, - { x: 571.7, y: 254.3 }, - { x: 583.1, y: 260 }, - { x: 591.6, y: 262.8 }, - { x: 600.2, y: 268.5 }, - { x: 611.6, y: 277.1 }, - { x: 620.1, y: 279.9 }, - { x: 628.6, y: 285.6 }, - { x: 637.2, y: 294.1 }, - { x: 645.7, y: 299.8 }, - { x: 654.2, y: 305.5 }, - { x: 659.9, y: 314 }, - { x: 665.6, y: 319.7 }, - { x: 674.1, y: 328.3 }, - { x: 679.8, y: 331.1 }, - { x: 682.7, y: 336.8 }, - { x: 688.4, y: 342.5 }, - { x: 691.2, y: 345.3 }, - { x: 694, y: 348.2 }, - { x: 696.9, y: 351 }, - { x: 699.7, y: 353.9 }, - { x: 702.6, y: 353.9 }, - { x: 702.6, y: 353.9 }, + { x: 500.6, y: 275.9 }, + { x: 500.6, y: 275.9 }, + { x: 500.6, y: 287.3 }, + { x: 492.1, y: 301.5 }, + { x: 480.7, y: 321.4 }, + { x: 466.5, y: 344.2 }, + { x: 452.3, y: 369.8 }, + { x: 429.5, y: 406.8 }, + { x: 415.3, y: 429.5 }, + { x: 403.9, y: 455.1 }, + { x: 389.7, y: 475 }, + { x: 378.3, y: 494.9 }, + { x: 369.8, y: 509.2 }, + { x: 361.2, y: 526.2 }, + { x: 349.9, y: 540.4 }, + { x: 341.3, y: 557.5 }, + { x: 332.8, y: 574.6 }, + { x: 324.3, y: 586 }, + { x: 318.6, y: 597.3 }, + { x: 310, y: 611.6 }, + { x: 301.5, y: 622.9 }, + { x: 293, y: 634.3 }, + { x: 287.3, y: 648.5 }, + { x: 281.6, y: 659.9 }, + { x: 273.1, y: 668.4 }, + { x: 270.2, y: 677 }, + { x: 264.5, y: 685.5 }, + { x: 261.7, y: 691.2 }, + { x: 258.8, y: 696.9 }, + { x: 256, y: 702.6 }, + { x: 253.2, y: 705.4 }, + { x: 253.2, y: 708.3 }, + { x: 253.2, y: 708.3 }, + { x: 253.2, y: 708.3 }, + { x: 253.2, y: 708.3 }, + { x: 253.2, y: 708.3 }, + { x: 253.2, y: 708.3 }, + { x: 258.8, y: 705.4 }, + { x: 264.5, y: 705.4 }, + { x: 273.1, y: 705.4 }, + { x: 287.3, y: 705.4 }, + { x: 301.5, y: 705.4 }, + { x: 315.7, y: 702.6 }, + { x: 332.8, y: 702.6 }, + { x: 349.9, y: 702.6 }, + { x: 364.1, y: 699.7 }, + { x: 378.3, y: 699.7 }, + { x: 392.5, y: 696.9 }, + { x: 403.9, y: 694 }, + { x: 415.3, y: 691.2 }, + { x: 426.7, y: 688.4 }, + { x: 435.2, y: 688.4 }, + { x: 449.4, y: 685.5 }, + { x: 460.8, y: 682.7 }, + { x: 472.2, y: 682.7 }, + { x: 489.2, y: 677 }, + { x: 497.8, y: 674.1 }, + { x: 506.3, y: 671.3 }, + { x: 514.8, y: 671.3 }, + { x: 523.4, y: 668.4 }, + { x: 531.9, y: 665.6 }, + { x: 540.4, y: 662.8 }, + { x: 549, y: 659.9 }, + { x: 563.2, y: 651.4 }, + { x: 571.7, y: 645.7 }, + { x: 583.1, y: 640 }, + { x: 591.6, y: 637.2 }, + { x: 600.2, y: 631.5 }, + { x: 611.6, y: 622.9 }, + { x: 620.1, y: 620.1 }, + { x: 628.6, y: 614.4 }, + { x: 637.2, y: 605.9 }, + { x: 645.7, y: 600.2 }, + { x: 654.2, y: 594.5 }, + { x: 659.9, y: 586 }, + { x: 665.6, y: 580.3 }, + { x: 674.1, y: 571.7 }, + { x: 679.8, y: 568.9 }, + { x: 682.7, y: 563.2 }, + { x: 688.4, y: 557.5 }, + { x: 691.2, y: 554.7 }, + { x: 694, y: 551.8 }, + { x: 696.9, y: 549 }, + { x: 699.7, y: 546.1 }, + { x: 702.6, y: 546.1 }, + { x: 702.6, y: 546.1 }, ]; assertMatches('厶', 0, points); }); it('matches using real data 24', () => { const points = [ - { x: 708.3, y: 749.2 }, - { x: 711.1, y: 749.2 }, - { x: 714, y: 749.2 }, - { x: 716.8, y: 749.2 }, - { x: 733.9, y: 749.2 }, - { x: 745.2, y: 749.2 }, - { x: 779.4, y: 749.2 }, - { x: 807.8, y: 752.1 }, - { x: 836.3, y: 754.9 }, - { x: 861.9, y: 757.8 }, - { x: 887.5, y: 757.8 }, - { x: 913.1, y: 760.6 }, - { x: 927.3, y: 760.6 }, - { x: 944.4, y: 760.6 }, - { x: 958.6, y: 760.6 }, - { x: 981.3, y: 763.5 }, - { x: 995.6, y: 763.5 }, - { x: 1006.9, y: 763.5 }, - { x: 1012.6, y: 763.5 }, - { x: 1018.3, y: 763.5 }, - { x: 1021.2, y: 763.5 }, - { x: 1021.2, y: 763.5 }, - { x: 1024, y: 760.6 }, - { x: 1024, y: 760.6 }, - { x: 1024, y: 757.8 }, - { x: 1024, y: 754.9 }, - { x: 1024, y: 749.2 }, - { x: 1024, y: 746.4 }, - { x: 1021.2, y: 737.9 }, - { x: 1015.5, y: 729.3 }, - { x: 1006.9, y: 709.4 }, - { x: 992.7, y: 681 }, - { x: 975.6, y: 652.5 }, - { x: 961.4, y: 621.2 }, - { x: 944.4, y: 592.8 }, - { x: 924.4, y: 550.1 }, - { x: 915.9, y: 535.9 }, - { x: 901.7, y: 504.6 }, - { x: 896, y: 487.6 }, - { x: 887.5, y: 470.5 }, - { x: 881.8, y: 459.1 }, - { x: 876.1, y: 444.9 }, - { x: 870.4, y: 436.4 }, - { x: 864.7, y: 427.8 }, - { x: 861.9, y: 422.1 }, - { x: 861.9, y: 419.3 }, - { x: 859, y: 416.4 }, - { x: 859, y: 413.6 }, - { x: 859, y: 413.6 }, - { x: 859, y: 410.8 }, - { x: 859, y: 410.8 }, - { x: 859, y: 405.1 }, - { x: 859, y: 396.5 }, - { x: 859, y: 390.8 }, - { x: 859, y: 382.3 }, - { x: 859, y: 379.5 }, - { x: 859, y: 376.6 }, - { x: 859, y: 373.8 }, - { x: 859, y: 373.8 }, - { x: 859, y: 370.9 }, - { x: 856.2, y: 370.9 }, + { x: 708.3, y: 150.8 }, + { x: 711.1, y: 150.8 }, + { x: 714, y: 150.8 }, + { x: 716.8, y: 150.8 }, + { x: 733.9, y: 150.8 }, + { x: 745.2, y: 150.8 }, + { x: 779.4, y: 150.8 }, + { x: 807.8, y: 147.9 }, + { x: 836.3, y: 145.1 }, + { x: 861.9, y: 142.2 }, + { x: 887.5, y: 142.2 }, + { x: 913.1, y: 139.4 }, + { x: 927.3, y: 139.4 }, + { x: 944.4, y: 139.4 }, + { x: 958.6, y: 139.4 }, + { x: 981.3, y: 136.5 }, + { x: 995.6, y: 136.5 }, + { x: 1006.9, y: 136.5 }, + { x: 1012.6, y: 136.5 }, + { x: 1018.3, y: 136.5 }, + { x: 1021.2, y: 136.5 }, + { x: 1021.2, y: 136.5 }, + { x: 1024, y: 139.4 }, + { x: 1024, y: 139.4 }, + { x: 1024, y: 142.2 }, + { x: 1024, y: 145.1 }, + { x: 1024, y: 150.8 }, + { x: 1024, y: 153.6 }, + { x: 1021.2, y: 162.1 }, + { x: 1015.5, y: 170.7 }, + { x: 1006.9, y: 190.6 }, + { x: 992.7, y: 219 }, + { x: 975.6, y: 247.5 }, + { x: 961.4, y: 278.8 }, + { x: 944.4, y: 307.2 }, + { x: 924.4, y: 349.9 }, + { x: 915.9, y: 364.1 }, + { x: 901.7, y: 395.4 }, + { x: 896, y: 412.4 }, + { x: 887.5, y: 429.5 }, + { x: 881.8, y: 440.9 }, + { x: 876.1, y: 455.1 }, + { x: 870.4, y: 463.6 }, + { x: 864.7, y: 472.2 }, + { x: 861.9, y: 477.9 }, + { x: 861.9, y: 480.7 }, + { x: 859, y: 483.6 }, + { x: 859, y: 486.4 }, + { x: 859, y: 486.4 }, + { x: 859, y: 489.2 }, + { x: 859, y: 489.2 }, + { x: 859, y: 494.9 }, + { x: 859, y: 503.5 }, + { x: 859, y: 509.2 }, + { x: 859, y: 517.7 }, + { x: 859, y: 520.5 }, + { x: 859, y: 523.4 }, + { x: 859, y: 526.2 }, + { x: 859, y: 526.2 }, + { x: 859, y: 529.1 }, + { x: 856.2, y: 529.1 }, ]; assertNotMatches('那', 4, points); }); it('matches using real data 25', () => { const points = [ - { x: 662.8, y: 726.5 }, - { x: 662.8, y: 726.5 }, - { x: 668.4, y: 726.5 }, - { x: 699.7, y: 729.3 }, - { x: 708.3, y: 729.3 }, - { x: 731, y: 732.2 }, - { x: 762.3, y: 737.9 }, - { x: 787.9, y: 740.7 }, - { x: 816.4, y: 743.6 }, - { x: 839.1, y: 746.4 }, - { x: 856.2, y: 749.2 }, - { x: 876.1, y: 749.2 }, - { x: 890.3, y: 749.2 }, - { x: 904.5, y: 749.2 }, - { x: 910.2, y: 749.2 }, - { x: 913.1, y: 749.2 }, - { x: 915.9, y: 749.2 }, - { x: 915.9, y: 749.2 }, - { x: 918.8, y: 749.2 }, - { x: 918.8, y: 746.4 }, - { x: 918.8, y: 746.4 }, - { x: 921.6, y: 746.4 }, - { x: 921.6, y: 746.4 }, - { x: 924.4, y: 746.4 }, - { x: 924.4, y: 746.4 }, - { x: 927.3, y: 746.4 }, - { x: 927.3, y: 743.6 }, - { x: 930.1, y: 743.6 }, - { x: 930.1, y: 737.9 }, - { x: 930.1, y: 735 }, - { x: 930.1, y: 729.3 }, - { x: 927.3, y: 726.5 }, - { x: 924.4, y: 720.8 }, - { x: 918.8, y: 715.1 }, - { x: 907.4, y: 703.7 }, - { x: 896, y: 689.5 }, - { x: 881.8, y: 675.3 }, - { x: 864.7, y: 661.1 }, - { x: 853.3, y: 649.7 }, - { x: 839.1, y: 635.5 }, - { x: 824.9, y: 624.1 }, - { x: 816.4, y: 615.6 }, - { x: 807.8, y: 607 }, - { x: 802.1, y: 601.3 }, - { x: 793.6, y: 592.8 }, - { x: 790.8, y: 592.8 }, - { x: 787.9, y: 590 }, - { x: 785.1, y: 587.1 }, - { x: 785.1, y: 587.1 }, - { x: 785.1, y: 587.1 }, - { x: 785.1, y: 587.1 }, - { x: 785.1, y: 587.1 }, - { x: 787.9, y: 587.1 }, - { x: 787.9, y: 587.1 }, - { x: 793.6, y: 587.1 }, - { x: 796.4, y: 587.1 }, - { x: 807.8, y: 584.3 }, - { x: 819.2, y: 575.7 }, - { x: 836.3, y: 564.4 }, - { x: 853.3, y: 553 }, - { x: 864.7, y: 541.6 }, - { x: 884.6, y: 527.4 }, - { x: 893.2, y: 521.7 }, - { x: 898.8, y: 513.2 }, - { x: 904.5, y: 507.5 }, - { x: 910.2, y: 501.8 }, - { x: 915.9, y: 496.1 }, - { x: 915.9, y: 490.4 }, - { x: 918.8, y: 484.7 }, - { x: 921.6, y: 481.9 }, - { x: 921.6, y: 479 }, - { x: 921.6, y: 476.2 }, - { x: 921.6, y: 473.3 }, - { x: 921.6, y: 467.6 }, - { x: 921.6, y: 462 }, - { x: 921.6, y: 456.3 }, - { x: 918.8, y: 444.9 }, - { x: 915.9, y: 430.7 }, - { x: 910.2, y: 413.6 }, - { x: 907.4, y: 393.7 }, - { x: 898.8, y: 376.6 }, - { x: 893.2, y: 356.7 }, - { x: 887.5, y: 342.5 }, - { x: 881.8, y: 325.4 }, - { x: 876.1, y: 314 }, - { x: 870.4, y: 305.5 }, - { x: 867.6, y: 299.8 }, - { x: 864.7, y: 294.1 }, - { x: 861.9, y: 288.4 }, - { x: 859, y: 285.6 }, - { x: 856.2, y: 279.9 }, - { x: 853.3, y: 271.4 }, - { x: 850.5, y: 268.5 }, - { x: 850.5, y: 268.5 }, - { x: 850.5, y: 265.7 }, - { x: 847.6, y: 265.7 }, - { x: 847.6, y: 265.7 }, - { x: 847.6, y: 265.7 }, - { x: 844.8, y: 265.7 }, - { x: 836.3, y: 265.7 }, - { x: 822, y: 268.5 }, - { x: 796.4, y: 274.2 }, - { x: 782.2, y: 277.1 }, - { x: 773.7, y: 279.9 }, - { x: 768, y: 282.8 }, - { x: 765.2, y: 285.6 }, - { x: 765.2, y: 288.4 }, + { x: 662.8, y: 173.5 }, + { x: 662.8, y: 173.5 }, + { x: 668.4, y: 173.5 }, + { x: 699.7, y: 170.7 }, + { x: 708.3, y: 170.7 }, + { x: 731, y: 167.8 }, + { x: 762.3, y: 162.1 }, + { x: 787.9, y: 159.3 }, + { x: 816.4, y: 156.4 }, + { x: 839.1, y: 153.6 }, + { x: 856.2, y: 150.8 }, + { x: 876.1, y: 150.8 }, + { x: 890.3, y: 150.8 }, + { x: 904.5, y: 150.8 }, + { x: 910.2, y: 150.8 }, + { x: 913.1, y: 150.8 }, + { x: 915.9, y: 150.8 }, + { x: 915.9, y: 150.8 }, + { x: 918.8, y: 150.8 }, + { x: 918.8, y: 153.6 }, + { x: 918.8, y: 153.6 }, + { x: 921.6, y: 153.6 }, + { x: 921.6, y: 153.6 }, + { x: 924.4, y: 153.6 }, + { x: 924.4, y: 153.6 }, + { x: 927.3, y: 153.6 }, + { x: 927.3, y: 156.4 }, + { x: 930.1, y: 156.4 }, + { x: 930.1, y: 162.1 }, + { x: 930.1, y: 165 }, + { x: 930.1, y: 170.7 }, + { x: 927.3, y: 173.5 }, + { x: 924.4, y: 179.2 }, + { x: 918.8, y: 184.9 }, + { x: 907.4, y: 196.3 }, + { x: 896, y: 210.5 }, + { x: 881.8, y: 224.7 }, + { x: 864.7, y: 238.9 }, + { x: 853.3, y: 250.3 }, + { x: 839.1, y: 264.5 }, + { x: 824.9, y: 275.9 }, + { x: 816.4, y: 284.4 }, + { x: 807.8, y: 293 }, + { x: 802.1, y: 298.7 }, + { x: 793.6, y: 307.2 }, + { x: 790.8, y: 307.2 }, + { x: 787.9, y: 310 }, + { x: 785.1, y: 312.9 }, + { x: 785.1, y: 312.9 }, + { x: 785.1, y: 312.9 }, + { x: 785.1, y: 312.9 }, + { x: 785.1, y: 312.9 }, + { x: 787.9, y: 312.9 }, + { x: 787.9, y: 312.9 }, + { x: 793.6, y: 312.9 }, + { x: 796.4, y: 312.9 }, + { x: 807.8, y: 315.7 }, + { x: 819.2, y: 324.3 }, + { x: 836.3, y: 335.6 }, + { x: 853.3, y: 347 }, + { x: 864.7, y: 358.4 }, + { x: 884.6, y: 372.6 }, + { x: 893.2, y: 378.3 }, + { x: 898.8, y: 386.8 }, + { x: 904.5, y: 392.5 }, + { x: 910.2, y: 398.2 }, + { x: 915.9, y: 403.9 }, + { x: 915.9, y: 409.6 }, + { x: 918.8, y: 415.3 }, + { x: 921.6, y: 418.1 }, + { x: 921.6, y: 421 }, + { x: 921.6, y: 423.8 }, + { x: 921.6, y: 426.7 }, + { x: 921.6, y: 432.4 }, + { x: 921.6, y: 438 }, + { x: 921.6, y: 443.7 }, + { x: 918.8, y: 455.1 }, + { x: 915.9, y: 469.3 }, + { x: 910.2, y: 486.4 }, + { x: 907.4, y: 506.3 }, + { x: 898.8, y: 523.4 }, + { x: 893.2, y: 543.3 }, + { x: 887.5, y: 557.5 }, + { x: 881.8, y: 574.6 }, + { x: 876.1, y: 586 }, + { x: 870.4, y: 594.5 }, + { x: 867.6, y: 600.2 }, + { x: 864.7, y: 605.9 }, + { x: 861.9, y: 611.6 }, + { x: 859, y: 614.4 }, + { x: 856.2, y: 620.1 }, + { x: 853.3, y: 628.6 }, + { x: 850.5, y: 631.5 }, + { x: 850.5, y: 631.5 }, + { x: 850.5, y: 634.3 }, + { x: 847.6, y: 634.3 }, + { x: 847.6, y: 634.3 }, + { x: 847.6, y: 634.3 }, + { x: 844.8, y: 634.3 }, + { x: 836.3, y: 634.3 }, + { x: 822, y: 631.5 }, + { x: 796.4, y: 625.8 }, + { x: 782.2, y: 622.9 }, + { x: 773.7, y: 620.1 }, + { x: 768, y: 617.2 }, + { x: 765.2, y: 614.4 }, + { x: 765.2, y: 611.6 }, ]; assertMatches('那', 4, points); }); it('matches using real data 26', () => { const points = [ - { x: 674.1, y: 749.2 }, - { x: 674.1, y: 749.2 }, - { x: 677, y: 749.2 }, - { x: 685.5, y: 749.2 }, - { x: 699.7, y: 749.2 }, - { x: 722.5, y: 749.2 }, - { x: 753.8, y: 749.2 }, - { x: 785.1, y: 749.2 }, - { x: 810.7, y: 749.2 }, - { x: 836.3, y: 746.4 }, - { x: 847.6, y: 740.7 }, - { x: 861.9, y: 735 }, - { x: 876.1, y: 723.6 }, - { x: 887.5, y: 715.1 }, - { x: 896, y: 703.7 }, - { x: 907.4, y: 692.4 }, - { x: 913.1, y: 683.8 }, - { x: 927.3, y: 663.9 }, - { x: 935.8, y: 649.7 }, - { x: 941.5, y: 632.6 }, - { x: 950, y: 615.6 }, - { x: 958.6, y: 598.5 }, - { x: 961.4, y: 584.3 }, - { x: 967.1, y: 564.4 }, - { x: 970, y: 538.8 }, - { x: 972.8, y: 518.8 }, - { x: 972.8, y: 496.1 }, - { x: 964.3, y: 459.1 }, - { x: 952.9, y: 433.5 }, - { x: 944.4, y: 407.9 }, - { x: 933, y: 382.3 }, - { x: 918.8, y: 356.7 }, - { x: 910.2, y: 334 }, - { x: 901.7, y: 316.9 }, - { x: 890.3, y: 297 }, - { x: 884.6, y: 282.8 }, - { x: 876.1, y: 268.5 }, - { x: 873.2, y: 260 }, - { x: 861.9, y: 251.5 }, - { x: 850.5, y: 248.6 }, + { x: 674.1, y: 150.8 }, + { x: 674.1, y: 150.8 }, + { x: 677, y: 150.8 }, + { x: 685.5, y: 150.8 }, + { x: 699.7, y: 150.8 }, + { x: 722.5, y: 150.8 }, + { x: 753.8, y: 150.8 }, + { x: 785.1, y: 150.8 }, + { x: 810.7, y: 150.8 }, + { x: 836.3, y: 153.6 }, + { x: 847.6, y: 159.3 }, + { x: 861.9, y: 165 }, + { x: 876.1, y: 176.4 }, + { x: 887.5, y: 184.9 }, + { x: 896, y: 196.3 }, + { x: 907.4, y: 207.6 }, + { x: 913.1, y: 216.2 }, + { x: 927.3, y: 236.1 }, + { x: 935.8, y: 250.3 }, + { x: 941.5, y: 267.4 }, + { x: 950, y: 284.4 }, + { x: 958.6, y: 301.5 }, + { x: 961.4, y: 315.7 }, + { x: 967.1, y: 335.6 }, + { x: 970, y: 361.2 }, + { x: 972.8, y: 381.2 }, + { x: 972.8, y: 403.9 }, + { x: 964.3, y: 440.9 }, + { x: 952.9, y: 466.5 }, + { x: 944.4, y: 492.1 }, + { x: 933, y: 517.7 }, + { x: 918.8, y: 543.3 }, + { x: 910.2, y: 566 }, + { x: 901.7, y: 583.1 }, + { x: 890.3, y: 603 }, + { x: 884.6, y: 617.2 }, + { x: 876.1, y: 631.5 }, + { x: 873.2, y: 640 }, + { x: 861.9, y: 648.5 }, + { x: 850.5, y: 651.4 }, ]; assertNotMatches('那', 4, points); }); it('matches using real data 27', () => { const points = [ - { x: 455.1, y: 681 }, - { x: 455.1, y: 683.8 }, - { x: 458, y: 683.8 }, - { x: 463.6, y: 683.8 }, - { x: 483.6, y: 683.8 }, - { x: 503.5, y: 683.8 }, - { x: 531.9, y: 686.7 }, - { x: 563.2, y: 686.7 }, - { x: 594.5, y: 689.5 }, - { x: 620.1, y: 692.4 }, - { x: 637.2, y: 692.4 }, - { x: 648.5, y: 692.4 }, - { x: 657.1, y: 692.4 }, - { x: 662.8, y: 692.4 }, - { x: 662.8, y: 692.4 }, - { x: 665.6, y: 692.4 }, - { x: 665.6, y: 689.5 }, - { x: 665.6, y: 683.8 }, - { x: 665.6, y: 678.1 }, - { x: 665.6, y: 669.6 }, - { x: 665.6, y: 661.1 }, - { x: 662.8, y: 644 }, - { x: 659.9, y: 626.9 }, - { x: 648.5, y: 590 }, - { x: 640, y: 570 }, - { x: 634.3, y: 550.1 }, - { x: 628.6, y: 535.9 }, - { x: 622.9, y: 527.4 }, - { x: 620.1, y: 521.7 }, - { x: 617.2, y: 516 }, - { x: 617.2, y: 513.2 }, - { x: 617.2, y: 510.3 }, - { x: 617.2, y: 510.3 }, - { x: 622.9, y: 507.5 }, - { x: 628.6, y: 501.8 }, - { x: 637.2, y: 498.9 }, - { x: 642.8, y: 493.2 }, - { x: 645.7, y: 487.6 }, - { x: 648.5, y: 484.7 }, - { x: 651.4, y: 476.2 }, - { x: 651.4, y: 464.8 }, - { x: 654.2, y: 450.6 }, - { x: 654.2, y: 430.7 }, - { x: 654.2, y: 410.8 }, - { x: 648.5, y: 393.7 }, - { x: 640, y: 379.5 }, - { x: 625.8, y: 365.2 }, - { x: 597.3, y: 342.5 }, - { x: 571.7, y: 328.3 }, - { x: 551.8, y: 322.6 }, - { x: 531.9, y: 316.9 }, - { x: 526.2, y: 314 }, + { x: 455.1, y: 219 }, + { x: 455.1, y: 216.2 }, + { x: 458, y: 216.2 }, + { x: 463.6, y: 216.2 }, + { x: 483.6, y: 216.2 }, + { x: 503.5, y: 216.2 }, + { x: 531.9, y: 213.3 }, + { x: 563.2, y: 213.3 }, + { x: 594.5, y: 210.5 }, + { x: 620.1, y: 207.6 }, + { x: 637.2, y: 207.6 }, + { x: 648.5, y: 207.6 }, + { x: 657.1, y: 207.6 }, + { x: 662.8, y: 207.6 }, + { x: 662.8, y: 207.6 }, + { x: 665.6, y: 207.6 }, + { x: 665.6, y: 210.5 }, + { x: 665.6, y: 216.2 }, + { x: 665.6, y: 221.9 }, + { x: 665.6, y: 230.4 }, + { x: 665.6, y: 238.9 }, + { x: 662.8, y: 256 }, + { x: 659.9, y: 273.1 }, + { x: 648.5, y: 310 }, + { x: 640, y: 330 }, + { x: 634.3, y: 349.9 }, + { x: 628.6, y: 364.1 }, + { x: 622.9, y: 372.6 }, + { x: 620.1, y: 378.3 }, + { x: 617.2, y: 384 }, + { x: 617.2, y: 386.8 }, + { x: 617.2, y: 389.7 }, + { x: 617.2, y: 389.7 }, + { x: 622.9, y: 392.5 }, + { x: 628.6, y: 398.2 }, + { x: 637.2, y: 401.1 }, + { x: 642.8, y: 406.8 }, + { x: 645.7, y: 412.4 }, + { x: 648.5, y: 415.3 }, + { x: 651.4, y: 423.8 }, + { x: 651.4, y: 435.2 }, + { x: 654.2, y: 449.4 }, + { x: 654.2, y: 469.3 }, + { x: 654.2, y: 489.2 }, + { x: 648.5, y: 506.3 }, + { x: 640, y: 520.5 }, + { x: 625.8, y: 534.8 }, + { x: 597.3, y: 557.5 }, + { x: 571.7, y: 571.7 }, + { x: 551.8, y: 577.4 }, + { x: 531.9, y: 583.1 }, + { x: 526.2, y: 586 }, ]; assertMatches('阝', 0, points); assertNotMatches('阝', 1, points); @@ -1311,39 +1310,39 @@ describe('strokeMatches', () => { it('matches using real data 28', () => { const points = [ - { x: 494.9, y: 726.5 }, - { x: 497.8, y: 726.5 }, - { x: 509.2, y: 726.5 }, - { x: 537.6, y: 726.5 }, - { x: 583.1, y: 726.5 }, - { x: 620.1, y: 726.5 }, - { x: 654.2, y: 720.8 }, - { x: 671.3, y: 715.1 }, - { x: 682.7, y: 706.6 }, - { x: 688.4, y: 695.2 }, - { x: 688.4, y: 686.7 }, - { x: 671.3, y: 661.1 }, - { x: 654.2, y: 641.2 }, - { x: 628.6, y: 612.7 }, - { x: 617.2, y: 595.6 }, - { x: 605.9, y: 584.3 }, - { x: 600.2, y: 578.6 }, - { x: 600.2, y: 578.6 }, - { x: 600.2, y: 578.6 }, - { x: 605.9, y: 575.7 }, - { x: 617.2, y: 570 }, - { x: 625.8, y: 561.5 }, - { x: 637.2, y: 547.3 }, - { x: 648.5, y: 530.2 }, - { x: 657.1, y: 516 }, - { x: 665.6, y: 496.1 }, - { x: 668.4, y: 470.5 }, - { x: 668.4, y: 439.2 }, - { x: 648.5, y: 402.2 }, - { x: 617.2, y: 368.1 }, - { x: 583.1, y: 342.5 }, - { x: 546.1, y: 319.7 }, - { x: 526.2, y: 311.2 }, + { x: 494.9, y: 173.5 }, + { x: 497.8, y: 173.5 }, + { x: 509.2, y: 173.5 }, + { x: 537.6, y: 173.5 }, + { x: 583.1, y: 173.5 }, + { x: 620.1, y: 173.5 }, + { x: 654.2, y: 179.2 }, + { x: 671.3, y: 184.9 }, + { x: 682.7, y: 193.4 }, + { x: 688.4, y: 204.8 }, + { x: 688.4, y: 213.3 }, + { x: 671.3, y: 238.9 }, + { x: 654.2, y: 258.8 }, + { x: 628.6, y: 287.3 }, + { x: 617.2, y: 304.4 }, + { x: 605.9, y: 315.7 }, + { x: 600.2, y: 321.4 }, + { x: 600.2, y: 321.4 }, + { x: 600.2, y: 321.4 }, + { x: 605.9, y: 324.3 }, + { x: 617.2, y: 330 }, + { x: 625.8, y: 338.5 }, + { x: 637.2, y: 352.7 }, + { x: 648.5, y: 369.8 }, + { x: 657.1, y: 384 }, + { x: 665.6, y: 403.9 }, + { x: 668.4, y: 429.5 }, + { x: 668.4, y: 460.8 }, + { x: 648.5, y: 497.8 }, + { x: 617.2, y: 531.9 }, + { x: 583.1, y: 557.5 }, + { x: 546.1, y: 580.3 }, + { x: 526.2, y: 588.8 }, ]; assertMatches('阝', 0, points); assertNotMatches('阝', 1, points); diff --git a/src/__tests__/utils-test.ts b/src/__tests__/utils-test.ts index c333167fc..86143cf73 100644 --- a/src/__tests__/utils-test.ts +++ b/src/__tests__/utils-test.ts @@ -1,40 +1,6 @@ import * as utils from '../utils'; describe('utils', () => { - describe('assign', () => { - it('should make a copy of the object passed in', () => { - const original = { a: { b: 7 }, c: 8 }; - const copy = utils.assign({}, original); - expect(copy).toEqual(original); - expect(copy).not.toBe(original); - }); - - it('should allow overwriting parts of the original object', () => { - const original = { a: { b: 7 }, c: 8 }; - const copy = utils.assign({}, original, { c: 9, d: 15 }, { d: 17 }); - expect(copy).not.toEqual(original); - expect(copy.c).toBe(9); - expect(copy.d).toBe(17); - }); - }); - - describe('assign polyfill', () => { - it('should make a copy of the object passed in', () => { - const original = { a: { b: 7 }, c: 8 }; - const copy = utils._assign({}, original); - expect(copy).toEqual(original); - expect(copy).not.toBe(original); - }); - - it('should allow overwriting parts of the original object', () => { - const original = { a: { b: 7 }, c: 8 }; - const copy = utils._assign({}, original, { c: 9, d: 15 }, { d: 17 }); - expect(copy).not.toEqual(original); - expect(copy.c).toBe(9); - expect(copy.d).toBe(17); - }); - }); - describe('copyAndMergeDeep', () => { it('should nested merge properties of both objects', () => { const base = { diff --git a/src/characterActions.ts b/src/characterActions.ts index aec9f51d9..9ced97167 100644 --- a/src/characterActions.ts +++ b/src/characterActions.ts @@ -13,10 +13,7 @@ export const showStrokes = ( return [ new Mutation( `character.${charName}.strokes`, - objRepeat( - { opacity: 1, displayPortion: 1 }, - character.strokes.length, - ) as CharacterRenderState['strokes'], + objRepeat({ opacity: 1, displayPortion: 1 }, character.strokes.length), { duration, force: true }, ), ]; diff --git a/src/geometry.ts b/src/geometry.ts index 07bfe7797..86942084e 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -201,8 +201,8 @@ export function getPathString(points: Point[], close = false) { const remainingPoints = points.slice(1); let pathString = `M ${start.x} ${start.y}`; remainingPoints.forEach((point) => { - const roundedPoint = round(point); - pathString += ` L ${roundedPoint.x} ${roundedPoint.y}`; + const { x, y } = round(point); + pathString += ` L ${x} ${y}`; }); if (close) { pathString += 'Z'; diff --git a/src/models/Character.ts b/src/models/Character.ts index e165d2a72..c2b03cfba 100644 --- a/src/models/Character.ts +++ b/src/models/Character.ts @@ -1,11 +1,73 @@ import Stroke from './Stroke'; +import type { CharacterJson } from '../typings/types'; +import { getPathCommands, getPathCommandParams } from '../utils'; export default class Character { symbol: string; strokes: Stroke[]; + /** Parses a given object and creates a new Character */ + static fromObject( + symbol: string, + charJson: CharacterJson, + /** Function that transforms the character's data before generating strokes & creating the character */ + processCharacter: + | ((charData: CharacterJson) => CharacterJson) + | null = defaultProcessCharData, + ) { + const newCharJson = processCharacter?.(charJson) || charJson; + const strokes = generateStrokes(newCharJson); + return new Character(symbol, strokes); + } + constructor(symbol: string, strokes: Stroke[]) { this.symbol = symbol; this.strokes = strokes; } } + +const generateStrokes = ({ radStrokes, strokes, medians }: CharacterJson) => { + const isInRadical = (strokeNum: number) => (radStrokes?.indexOf(strokeNum) ?? -1) >= 0; + return strokes.map((path, index) => { + const points = medians[index].map((pointData) => { + const [x, y] = pointData; + return { x, y }; + }); + return new Stroke(path, points, index, isInRadical(index)); + }); +}; + +/** Inverts the Y axis. This is for backwards compatibility with "hanzi-writer-data@v2" */ +const defaultProcessCharData = (charData: CharacterJson): CharacterJson => { + const newStrokes = charData.strokes.map((stroke) => { + const newStroke = getPathCommands(stroke).reduce((acc, command) => { + const { cmd, values } = getPathCommandParams(command); + if (cmd === 'M' || cmd === 'L') { + const [x, y] = values; + return acc + `${cmd} ${x} ${900 - y} `; + } + if (cmd === 'Q') { + const [x1, y1, x2, y2] = values; + return acc + `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} `; + } + if (cmd === 'C') { + const [x1, y1, x2, y2, x, y] = values; + return acc + `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} ${x} ${900 - y} `; + } + if (cmd === 'Z') { + return acc + 'Z'; + } + return acc + `${cmd} ${values.join(' ')}`; + }, ''); + + return newStroke; + }); + + return { + ...charData, + strokes: newStrokes, + medians: charData.medians.map((median) => { + return median.map(([x, y]) => [x, 900 - y]); + }), + }; +}; diff --git a/src/parseCharData.ts b/src/parseCharData.ts deleted file mode 100644 index af7a4c443..000000000 --- a/src/parseCharData.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Stroke from './models/Stroke'; -import Character from './models/Character'; -import { CharacterJson } from './typings/types'; - -function generateStrokes({ radStrokes, strokes, medians }: CharacterJson) { - const isInRadical = (strokeNum: number) => (radStrokes?.indexOf(strokeNum) ?? -1) >= 0; - return strokes.map((path, index) => { - const points = medians[index].map((pointData) => { - const [x, y] = pointData; - return { x, y }; - }); - return new Stroke(path, points, index, isInRadical(index)); - }); -} - -export default function parseCharData(symbol: string, charJson: CharacterJson) { - const strokes = generateStrokes(charJson); - return new Character(symbol, strokes); -} diff --git a/src/renderers/canvas/__tests__/CharacterRenderer-test.ts b/src/renderers/canvas/__tests__/CharacterRenderer-test.ts index 057be04bf..272a6b0fe 100644 --- a/src/renderers/canvas/__tests__/CharacterRenderer-test.ts +++ b/src/renderers/canvas/__tests__/CharacterRenderer-test.ts @@ -1,8 +1,8 @@ import ren from 'hanzi-writer-data/人.json'; +import Character from '../../../models/Character'; import CharacterRenderer from '../CharacterRenderer'; -import parseCharData from '../../../parseCharData'; -const char = parseCharData('人', ren); +const char = Character.fromObject('人', ren); describe('CharacterRenderer', () => { let ctx; diff --git a/src/renderers/canvas/__tests__/HanziWriterRenderer-test.ts b/src/renderers/canvas/__tests__/HanziWriterRenderer-test.ts index 93d0fff36..5d6b31188 100644 --- a/src/renderers/canvas/__tests__/HanziWriterRenderer-test.ts +++ b/src/renderers/canvas/__tests__/HanziWriterRenderer-test.ts @@ -2,10 +2,11 @@ import ren from 'hanzi-writer-data/人.json'; import HanziWriterRenderer from '../HanziWriterRenderer'; import RenderTarget from '../RenderTarget'; import Positioner from '../../../Positioner'; -import parseCharData from '../../../parseCharData'; import { RenderStateObject } from '../../../RenderState'; +import Character from '../../../models/Character'; + +const char = Character.fromObject('人', ren); -const char = parseCharData('人', ren); const positioner = new Positioner({ width: 100, height: 100, diff --git a/src/renderers/canvas/__tests__/StrokeRenderer-test.ts b/src/renderers/canvas/__tests__/StrokeRenderer-test.ts index 24b51f2ae..fbfbf3f8d 100644 --- a/src/renderers/canvas/__tests__/StrokeRenderer-test.ts +++ b/src/renderers/canvas/__tests__/StrokeRenderer-test.ts @@ -1,8 +1,8 @@ import yi from 'hanzi-writer-data/一.json'; +import Character from '../../../models/Character'; import StrokeRenderer from '../StrokeRenderer'; -import parseCharData from '../../../parseCharData'; -const char = parseCharData('一', yi); +const char = Character.fromObject('一', yi); describe('StrokeRenderer', () => { let ctx; diff --git a/src/renderers/canvas/__tests__/__snapshots__/CharacterRenderer-test.ts.snap b/src/renderers/canvas/__tests__/__snapshots__/CharacterRenderer-test.ts.snap index a064f1699..656e24f7f 100644 --- a/src/renderers/canvas/__tests__/__snapshots__/CharacterRenderer-test.ts.snap +++ b/src/renderers/canvas/__tests__/__snapshots__/CharacterRenderer-test.ts.snap @@ -159,7 +159,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 1, @@ -174,7 +174,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 1, @@ -189,7 +189,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 1, @@ -204,7 +204,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 1, @@ -219,7 +219,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 1, @@ -234,7 +234,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 1, @@ -249,7 +249,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 1, @@ -264,7 +264,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 1, @@ -279,7 +279,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 1, @@ -309,7 +309,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 1, @@ -324,7 +324,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 1, @@ -339,7 +339,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 1, @@ -354,7 +354,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 1, @@ -369,7 +369,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 1, @@ -384,7 +384,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 1, @@ -399,7 +399,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 1, @@ -414,7 +414,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 1, @@ -429,7 +429,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 1, @@ -622,7 +622,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 1, @@ -637,7 +637,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 1, @@ -652,7 +652,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 1, @@ -667,7 +667,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 1, @@ -682,7 +682,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 1, @@ -697,7 +697,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 1, @@ -712,7 +712,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 1, @@ -727,7 +727,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 1, @@ -757,7 +757,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 1, @@ -772,7 +772,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 1, @@ -787,7 +787,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 1, @@ -802,7 +802,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 1, @@ -817,7 +817,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 1, @@ -832,7 +832,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 1, @@ -847,7 +847,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 1, @@ -862,7 +862,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 1, diff --git a/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap b/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap index 8c5194f9a..16ace8844 100644 --- a/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap +++ b/src/renderers/canvas/__tests__/__snapshots__/HanziWriterRenderer-test.ts.snap @@ -218,7 +218,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -233,7 +233,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -248,7 +248,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -263,7 +263,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -278,7 +278,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -293,7 +293,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -308,7 +308,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -323,7 +323,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -338,7 +338,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -368,7 +368,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -383,7 +383,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -398,7 +398,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -413,7 +413,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -428,7 +428,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -443,7 +443,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -458,7 +458,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -473,7 +473,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -488,7 +488,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -681,7 +681,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -696,7 +696,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -711,7 +711,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -726,7 +726,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -741,7 +741,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -756,7 +756,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -771,7 +771,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -786,7 +786,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -816,7 +816,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -831,7 +831,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -846,7 +846,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -861,7 +861,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -876,7 +876,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -891,7 +891,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -906,7 +906,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -921,7 +921,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -1114,7 +1114,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -1129,7 +1129,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -1144,7 +1144,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -1159,7 +1159,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -1174,7 +1174,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -1189,7 +1189,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -1204,7 +1204,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -1219,7 +1219,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -1234,7 +1234,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -1264,7 +1264,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -1279,7 +1279,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -1294,7 +1294,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -1309,7 +1309,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -1324,7 +1324,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -1339,7 +1339,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -1354,7 +1354,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -1369,7 +1369,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -1384,7 +1384,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -1577,7 +1577,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -1592,7 +1592,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -1607,7 +1607,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -1622,7 +1622,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -1637,7 +1637,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -1652,7 +1652,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -1667,7 +1667,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -1682,7 +1682,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -1712,7 +1712,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -1727,7 +1727,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -1742,7 +1742,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -1757,7 +1757,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -1772,7 +1772,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -1787,7 +1787,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -1802,7 +1802,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -1817,7 +1817,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -2010,7 +2010,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -2025,7 +2025,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -2040,7 +2040,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -2055,7 +2055,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -2070,7 +2070,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -2085,7 +2085,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -2100,7 +2100,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -2115,7 +2115,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -2130,7 +2130,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -2160,7 +2160,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -2175,7 +2175,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -2190,7 +2190,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -2205,7 +2205,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -2220,7 +2220,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -2235,7 +2235,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -2250,7 +2250,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -2265,7 +2265,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -2280,7 +2280,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -2473,7 +2473,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -2488,7 +2488,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -2503,7 +2503,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -2518,7 +2518,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -2533,7 +2533,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -2548,7 +2548,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -2563,7 +2563,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -2578,7 +2578,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -2608,7 +2608,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -2623,7 +2623,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -2638,7 +2638,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -2653,7 +2653,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -2668,7 +2668,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -2683,7 +2683,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -2698,7 +2698,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -2713,7 +2713,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -2982,7 +2982,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -2997,7 +2997,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -3012,7 +3012,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -3027,7 +3027,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -3042,7 +3042,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -3057,7 +3057,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -3072,7 +3072,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -3087,7 +3087,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -3102,7 +3102,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -3132,7 +3132,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -3147,7 +3147,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -3162,7 +3162,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -3177,7 +3177,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -3192,7 +3192,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -3207,7 +3207,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -3222,7 +3222,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -3237,7 +3237,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -3252,7 +3252,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -3445,7 +3445,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -3460,7 +3460,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -3475,7 +3475,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -3490,7 +3490,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -3505,7 +3505,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -3520,7 +3520,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -3535,7 +3535,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -3550,7 +3550,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -3580,7 +3580,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -3595,7 +3595,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -3610,7 +3610,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -3625,7 +3625,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -3640,7 +3640,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -3655,7 +3655,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -3670,7 +3670,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -3685,7 +3685,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -3878,7 +3878,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -3893,7 +3893,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -3908,7 +3908,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -3923,7 +3923,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -3938,7 +3938,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -3953,7 +3953,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -3968,7 +3968,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -3983,7 +3983,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -3998,7 +3998,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -4028,7 +4028,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -4043,7 +4043,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -4058,7 +4058,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -4073,7 +4073,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -4088,7 +4088,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -4103,7 +4103,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -4118,7 +4118,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -4133,7 +4133,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -4148,7 +4148,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -4341,7 +4341,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -4356,7 +4356,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -4371,7 +4371,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -4386,7 +4386,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -4401,7 +4401,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -4416,7 +4416,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -4431,7 +4431,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -4446,7 +4446,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -4476,7 +4476,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -4491,7 +4491,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -4506,7 +4506,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -4521,7 +4521,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -4536,7 +4536,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -4551,7 +4551,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -4566,7 +4566,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -4581,7 +4581,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -4774,7 +4774,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -4789,7 +4789,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -4804,7 +4804,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -4819,7 +4819,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -4834,7 +4834,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -4849,7 +4849,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -4864,7 +4864,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -4879,7 +4879,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -4894,7 +4894,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -4924,7 +4924,7 @@ Array [ Object { "props": Object { "x": 423.7609549522482, - "y": 816.5651012649424, + "y": 83.43489873505753, }, "transform": Array [ 0.078125, @@ -4939,7 +4939,7 @@ Array [ Object { "props": Object { "x": 508, - "y": 702, + "y": 198, }, "transform": Array [ 0.078125, @@ -4954,7 +4954,7 @@ Array [ Object { "props": Object { "x": 511, - "y": 678, + "y": 222, }, "transform": Array [ 0.078125, @@ -4969,7 +4969,7 @@ Array [ Object { "props": Object { "x": 473, - "y": 552, + "y": 348, }, "transform": Array [ 0.078125, @@ -4984,7 +4984,7 @@ Array [ Object { "props": Object { "x": 408, - "y": 416, + "y": 484, }, "transform": Array [ 0.078125, @@ -4999,7 +4999,7 @@ Array [ Object { "props": Object { "x": 328, - "y": 303, + "y": 597, }, "transform": Array [ 0.078125, @@ -5014,7 +5014,7 @@ Array [ Object { "props": Object { "x": 271, - "y": 244, + "y": 656, }, "transform": Array [ 0.078125, @@ -5029,7 +5029,7 @@ Array [ Object { "props": Object { "x": 144, - "y": 139, + "y": 761, }, "transform": Array [ 0.078125, @@ -5044,7 +5044,7 @@ Array [ Object { "props": Object { "x": 72, - "y": 95, + "y": 805, }, "transform": Array [ 0.078125, @@ -5237,7 +5237,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -5252,7 +5252,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -5267,7 +5267,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -5282,7 +5282,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -5297,7 +5297,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -5312,7 +5312,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -5327,7 +5327,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -5342,7 +5342,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, @@ -5372,7 +5372,7 @@ Array [ Object { "props": Object { "x": 457.56010126946427, - "y": 575.6393923832144, + "y": 324.3606076167856, }, "transform": Array [ 0.078125, @@ -5387,7 +5387,7 @@ Array [ Object { "props": Object { "x": 477, - "y": 459, + "y": 441, }, "transform": Array [ 0.078125, @@ -5402,7 +5402,7 @@ Array [ Object { "props": Object { "x": 490, - "y": 439, + "y": 461, }, "transform": Array [ 0.078125, @@ -5417,7 +5417,7 @@ Array [ Object { "props": Object { "x": 571, - "y": 333, + "y": 567, }, "transform": Array [ 0.078125, @@ -5432,7 +5432,7 @@ Array [ Object { "props": Object { "x": 691, - "y": 200, + "y": 700, }, "transform": Array [ 0.078125, @@ -5447,7 +5447,7 @@ Array [ Object { "props": Object { "x": 753, - "y": 145, + "y": 755, }, "transform": Array [ 0.078125, @@ -5462,7 +5462,7 @@ Array [ Object { "props": Object { "x": 798, - "y": 119, + "y": 781, }, "transform": Array [ 0.078125, @@ -5477,7 +5477,7 @@ Array [ Object { "props": Object { "x": 986, - "y": 90, + "y": 810, }, "transform": Array [ 0.078125, diff --git a/src/renderers/canvas/__tests__/__snapshots__/StrokeRenderer-test.ts.snap b/src/renderers/canvas/__tests__/__snapshots__/StrokeRenderer-test.ts.snap index bc64d3ff3..0e0fcbe28 100644 --- a/src/renderers/canvas/__tests__/__snapshots__/StrokeRenderer-test.ts.snap +++ b/src/renderers/canvas/__tests__/__snapshots__/StrokeRenderer-test.ts.snap @@ -159,7 +159,7 @@ Array [ Object { "props": Object { "x": 25, - "y": 421, + "y": 479, }, "transform": Array [ 1, @@ -174,7 +174,7 @@ Array [ Object { "props": Object { "x": 193, - "y": 372, + "y": 528, }, "transform": Array [ 1, @@ -189,7 +189,7 @@ Array [ Object { "props": Object { "x": 417, - "y": 402, + "y": 498, }, "transform": Array [ 1, @@ -204,7 +204,7 @@ Array [ Object { "props": Object { "x": 827, - "y": 434, + "y": 466, }, "transform": Array [ 1, @@ -219,7 +219,7 @@ Array [ Object { "props": Object { "x": 920, - "y": 401, + "y": 499, }, "transform": Array [ 1, @@ -249,7 +249,7 @@ Array [ Object { "props": Object { "x": 25, - "y": 421, + "y": 479, }, "transform": Array [ 1, @@ -264,7 +264,7 @@ Array [ Object { "props": Object { "x": 193, - "y": 372, + "y": 528, }, "transform": Array [ 1, @@ -279,7 +279,7 @@ Array [ Object { "props": Object { "x": 417, - "y": 402, + "y": 498, }, "transform": Array [ 1, @@ -294,7 +294,7 @@ Array [ Object { "props": Object { "x": 827, - "y": 434, + "y": 466, }, "transform": Array [ 1, @@ -309,7 +309,7 @@ Array [ Object { "props": Object { "x": 920, - "y": 401, + "y": 499, }, "transform": Array [ 1, @@ -377,7 +377,7 @@ Array [ Object { "props": Object { "x": 518, - "y": 382, + "y": 518, }, "transform": Array [ 1, @@ -392,9 +392,9 @@ Array [ Object { "props": Object { "cpx": 572, - "cpy": 385, + "cpy": 515, "x": 623, - "y": 389, + "y": 511, }, "transform": Array [ 1, @@ -409,9 +409,9 @@ Array [ Object { "props": Object { "cpx": 758, - "cpy": 399, + "cpy": 501, "x": 900, - "y": 383, + "y": 517, }, "transform": Array [ 1, @@ -426,9 +426,9 @@ Array [ Object { "props": Object { "cpx": 928, - "cpy": 379, + "cpy": 521, "x": 935, - "y": 390, + "y": 510, }, "transform": Array [ 1, @@ -443,9 +443,9 @@ Array [ Object { "props": Object { "cpx": 944, - "cpy": 405, + "cpy": 495, "x": 930, - "y": 419, + "y": 481, }, "transform": Array [ 1, @@ -460,9 +460,9 @@ Array [ Object { "props": Object { "cpx": 896, - "cpy": 452, + "cpy": 448, "x": 845, - "y": 475, + "y": 425, }, "transform": Array [ 1, @@ -477,9 +477,9 @@ Array [ Object { "props": Object { "cpx": 829, - "cpy": 482, + "cpy": 418, "x": 798, - "y": 473, + "y": 427, }, "transform": Array [ 1, @@ -494,9 +494,9 @@ Array [ Object { "props": Object { "cpx": 723, - "cpy": 460, + "cpy": 440, "x": 480, - "y": 434, + "y": 466, }, "transform": Array [ 1, @@ -511,9 +511,9 @@ Array [ Object { "props": Object { "cpx": 180, - "cpy": 409, + "cpy": 491, "x": 137, - "y": 408, + "y": 492, }, "transform": Array [ 1, @@ -528,9 +528,9 @@ Array [ Object { "props": Object { "cpx": 130, - "cpy": 408, + "cpy": 492, "x": 124, - "y": 408, + "y": 492, }, "transform": Array [ 1, @@ -545,9 +545,9 @@ Array [ Object { "props": Object { "cpx": 108, - "cpy": 408, + "cpy": 492, "x": 106, - "y": 395, + "y": 505, }, "transform": Array [ 1, @@ -562,9 +562,9 @@ Array [ Object { "props": Object { "cpx": 105, - "cpy": 380, + "cpy": 520, "x": 127, - "y": 363, + "y": 537, }, "transform": Array [ 1, @@ -579,9 +579,9 @@ Array [ Object { "props": Object { "cpx": 146, - "cpy": 348, + "cpy": 552, "x": 183, - "y": 334, + "y": 566, }, "transform": Array [ 1, @@ -596,9 +596,9 @@ Array [ Object { "props": Object { "cpx": 195, - "cpy": 330, + "cpy": 570, "x": 216, - "y": 338, + "y": 562, }, "transform": Array [ 1, @@ -613,9 +613,9 @@ Array [ Object { "props": Object { "cpx": 232, - "cpy": 344, + "cpy": 556, "x": 306, - "y": 354, + "y": 546, }, "transform": Array [ 1, @@ -630,9 +630,9 @@ Array [ Object { "props": Object { "cpx": 400, - "cpy": 373, + "cpy": 527, "x": 518, - "y": 382, + "y": 518, }, "transform": Array [ 1, @@ -676,7 +676,7 @@ Array [ Object { "props": Object { "x": 518, - "y": 382, + "y": 518, }, "transform": Array [ 1, @@ -719,7 +719,7 @@ Array [ Object { "props": Object { "x": 518, - "y": 382, + "y": 518, }, "transform": Array [ 1, @@ -873,7 +873,7 @@ Array [ Object { "props": Object { "x": 25, - "y": 421, + "y": 479, }, "transform": Array [ 1, @@ -888,7 +888,7 @@ Array [ Object { "props": Object { "x": 193, - "y": 372, + "y": 528, }, "transform": Array [ 1, @@ -903,7 +903,7 @@ Array [ Object { "props": Object { "x": 417, - "y": 402, + "y": 498, }, "transform": Array [ 1, @@ -918,7 +918,7 @@ Array [ Object { "props": Object { "x": 827, - "y": 434, + "y": 466, }, "transform": Array [ 1, @@ -933,7 +933,7 @@ Array [ Object { "props": Object { "x": 920, - "y": 401, + "y": 499, }, "transform": Array [ 1, @@ -963,7 +963,7 @@ Array [ Object { "props": Object { "x": 25, - "y": 421, + "y": 479, }, "transform": Array [ 1, @@ -978,7 +978,7 @@ Array [ Object { "props": Object { "x": 193, - "y": 372, + "y": 528, }, "transform": Array [ 1, @@ -993,7 +993,7 @@ Array [ Object { "props": Object { "x": 417, - "y": 402, + "y": 498, }, "transform": Array [ 1, @@ -1008,7 +1008,7 @@ Array [ Object { "props": Object { "x": 827, - "y": 434, + "y": 466, }, "transform": Array [ 1, @@ -1023,7 +1023,7 @@ Array [ Object { "props": Object { "x": 920, - "y": 401, + "y": 499, }, "transform": Array [ 1, diff --git a/src/renderers/canvas/canvasUtils.ts b/src/renderers/canvas/canvasUtils.ts index 9887db751..df373e71c 100644 --- a/src/renderers/canvas/canvasUtils.ts +++ b/src/renderers/canvas/canvasUtils.ts @@ -1,3 +1,4 @@ +import { getPathCommandParams, getPathCommands } from '../../utils'; import { Point } from '../../typings/types'; export const drawPath = (ctx: CanvasRenderingContext2D, points: Point[]) => { @@ -18,22 +19,20 @@ export const drawPath = (ctx: CanvasRenderingContext2D, points: Point[]) => { * @param pathString */ export const pathStringToCanvas = (pathString: string) => { - const pathParts = pathString.split(/(^|\s+)(?=[A-Z])/).filter((part) => part !== ' '); const commands = [(ctx: CanvasRenderingContext2D) => ctx.beginPath()]; - for (const part of pathParts) { - const [cmd, ...rawParams] = part.split(/\s+/); - const params = rawParams.map((param) => parseFloat(param)) as any[]; + for (const command of getPathCommands(pathString)) { + const { cmd, values } = getPathCommandParams(command); if (cmd === 'M') { - commands.push((ctx) => ctx.moveTo(...(params as [number, number]))); + commands.push((ctx) => ctx.moveTo(...(values as [number, number]))); } else if (cmd === 'L') { - commands.push((ctx) => ctx.lineTo(...(params as [number, number]))); + commands.push((ctx) => ctx.lineTo(...(values as [number, number]))); } else if (cmd === 'C') { commands.push((ctx) => - ctx.bezierCurveTo(...(params as Parameters)), + ctx.bezierCurveTo(...(values as Parameters)), ); } else if (cmd === 'Q') { commands.push((ctx) => - ctx.quadraticCurveTo(...(params as Parameters)), + ctx.quadraticCurveTo(...(values as Parameters)), ); } else if (cmd === 'Z') { // commands.push((ctx) => ctx.closePath()); diff --git a/src/renderers/svg/__tests__/CharacterRenderer-test.ts b/src/renderers/svg/__tests__/CharacterRenderer-test.ts index 8c74dcb52..49ac35fc8 100644 --- a/src/renderers/svg/__tests__/CharacterRenderer-test.ts +++ b/src/renderers/svg/__tests__/CharacterRenderer-test.ts @@ -2,9 +2,9 @@ import ren from 'hanzi-writer-data/人.json'; import CharacterRenderer from '../CharacterRenderer'; import RenderTarget from '../RenderTarget'; import { copyAndMergeDeep } from '../../../utils'; -import parseCharData from '../../../parseCharData'; +import Character from '../../../models/Character'; -const char = parseCharData('人', ren); +const char = Character.fromObject('人', ren); describe('CharacterRenderer', () => { let target; diff --git a/src/renderers/svg/__tests__/HanziWriterRenderer-test.ts b/src/renderers/svg/__tests__/HanziWriterRenderer-test.ts index e47e2ed3b..0307cc616 100644 --- a/src/renderers/svg/__tests__/HanziWriterRenderer-test.ts +++ b/src/renderers/svg/__tests__/HanziWriterRenderer-test.ts @@ -3,10 +3,11 @@ import HanziWriterRenderer from '../HanziWriterRenderer'; import RenderTarget from '../RenderTarget'; import { copyAndMergeDeep } from '../../../utils'; import Positioner from '../../../Positioner'; -import parseCharData from '../../../parseCharData'; import { RenderStateObject } from '../../../RenderState'; +import Character from '../../../models/Character'; + +const char = Character.fromObject('人', ren); -const char = parseCharData('人', ren); const positioner = new Positioner({ width: 100, height: 100, diff --git a/src/renderers/svg/__tests__/StrokeRenderer-test.ts b/src/renderers/svg/__tests__/StrokeRenderer-test.ts index dbd478793..9f244b47c 100644 --- a/src/renderers/svg/__tests__/StrokeRenderer-test.ts +++ b/src/renderers/svg/__tests__/StrokeRenderer-test.ts @@ -1,9 +1,9 @@ import yi from 'hanzi-writer-data/一.json'; import StrokeRenderer from '../StrokeRenderer'; import RenderTarget from '../RenderTarget'; -import parseCharData from '../../../parseCharData'; +import Character from '../../../models/Character'; -const char = parseCharData('一', yi); +const char = Character.fromObject('一', yi); describe('StrokeRenderer', () => { let target: RenderTarget; diff --git a/src/renderers/svg/__tests__/__snapshots__/StrokeRenderer-test.ts.snap b/src/renderers/svg/__tests__/__snapshots__/StrokeRenderer-test.ts.snap index 60b9658dd..1379a0d48 100644 --- a/src/renderers/svg/__tests__/__snapshots__/StrokeRenderer-test.ts.snap +++ b/src/renderers/svg/__tests__/__snapshots__/StrokeRenderer-test.ts.snap @@ -2,6 +2,6 @@ exports[`StrokeRenderer renders a path and clipPath 1`] = ` `; diff --git a/src/typings/types.ts b/src/typings/types.ts index 19a6b8b4b..d0113ded1 100644 --- a/src/typings/types.ts +++ b/src/typings/types.ts @@ -39,7 +39,7 @@ export type OnCompleteFunction = (res: { canceled: boolean }) => void; /** Creates a render target (e.g. svg, canvas) */ export type RenderTargetInitFunction< - TElement extends HTMLElement | SVGElement | SVGSVGElement | HTMLCanvasElement + TElement extends HTMLElement | SVGElement | SVGSVGElement | HTMLCanvasElement, > = ( elmOrId: string | TElement, width?: string | number | null, @@ -86,6 +86,15 @@ type BaseHanziWriterOptions = { /** Default: svg */ renderer: 'svg' | 'canvas'; + /** + * Post process the character data after loading from server. + * + * Provide `null` for no post-processing. + * + * Default: applies a "900-Y" transform to strokes/medians for `hanzi-writer-data@v2` characters + */ + processCharData?: (charData: CharacterJson) => CharacterJson; + // Animation options /** Default: 1 */ diff --git a/src/utils.ts b/src/utils.ts index fd5de4f33..41b37ac59 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,30 +3,12 @@ import { ColorObject, RecursivePartial } from './typings/types'; // hacky way to get around rollup not properly setting `global` to `window` in browser const globalObj = typeof window === 'undefined' ? global : window; -export const performanceNow = - (globalObj.performance && (() => globalObj.performance.now())) || (() => Date.now()); +export const performanceNow = () => (globalObj?.performance || Date).now(); export const requestAnimationFrame = globalObj.requestAnimationFrame || ((callback) => setTimeout(() => callback(performanceNow()), 1000 / 60)); export const cancelAnimationFrame = globalObj.cancelAnimationFrame || clearTimeout; -// Object.assign polyfill, because IE :/ -export const _assign = function (target: any, ...overrides: any[]) { - const overrideTarget = Object(target); - overrides.forEach((override) => { - if (override != null) { - for (const key in override) { - if (Object.prototype.hasOwnProperty.call(override, key)) { - overrideTarget[key] = override[key]; - } - } - } - }); - return overrideTarget; -}; - -export const assign = Object.assign || _assign; - export function arrLast(arr: Array) { return arr[arr.length - 1]; } @@ -122,17 +104,13 @@ export function colorStringToVals(colorString: string): ColorObject { throw new Error(`Invalid color: ${colorString}`); } -export const trim = (string: string) => string.replace(/^\s+/, '').replace(/\s+$/, ''); - -// return a new array-like object with int keys where each key is item -// ex: objRepeat({x: 8}, 3) === {0: {x: 8}, 1: {x: 8}, 2: {x: 8}} -export function objRepeat(item: T, times: number) { - const obj: Record = {}; - for (let i = 0; i < times; i++) { - obj[i] = item; - } - return obj; -} +/** + * Creates a new array with a given value and fills the array with the value a given number of times. + * + * e.g. objRepeat({x: 8}, 3) === [{x: 8}, {x: 8}, {x: 8}] + */ +export const objRepeat = (value: T, times: number): T[] => + new Array(times).fill(value); const ua = globalObj.navigator?.userAgent || ''; @@ -141,3 +119,22 @@ export const isMsBrowser = // eslint-disable-next-line @typescript-eslint/no-empty-function export const noop = () => {}; + +/** + * Parses a given SVG path string and returns an array of path commands + */ +export const getPathCommands = (pathString: string): string[] => { + return pathString.split(/(^|\s+)(?=[A-Z])/).filter((part) => part !== ' '); +}; + +const pathCommandSeparatorRegex = /\s+|[, ]+/; + +export const getPathCommandParams = ( + pathCommand: string, +): { + cmd: string; + values: number[]; +} => { + const [cmd, ...params] = pathCommand.split(pathCommandSeparatorRegex); + return { cmd, values: params.map((param) => parseFloat(param)) }; +}; From 6765f02fd66e788f13cfe9a43393a9a1b10c9637 Mon Sep 17 00:00:00 2001 From: jamsch Date: Fri, 25 Nov 2022 16:03:53 +1300 Subject: [PATCH 3/6] feat: implement `pathCommandGenerator` to generate svg path commands + args --- src/models/Character.ts | 22 +++++++------ src/renderers/canvas/canvasUtils.ts | 5 ++- src/typings/types.ts | 4 +-- src/utils.ts | 48 ++++++++++++++++++++++++++--- tsconfig.json | 2 +- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/models/Character.ts b/src/models/Character.ts index c2b03cfba..3cec97c6c 100644 --- a/src/models/Character.ts +++ b/src/models/Character.ts @@ -1,6 +1,6 @@ import Stroke from './Stroke'; import type { CharacterJson } from '../typings/types'; -import { getPathCommands, getPathCommandParams } from '../utils'; +import { pathCommandGenerator } from '../utils'; export default class Character { symbol: string; @@ -40,25 +40,29 @@ const generateStrokes = ({ radStrokes, strokes, medians }: CharacterJson) => { /** Inverts the Y axis. This is for backwards compatibility with "hanzi-writer-data@v2" */ const defaultProcessCharData = (charData: CharacterJson): CharacterJson => { const newStrokes = charData.strokes.map((stroke) => { - const newStroke = getPathCommands(stroke).reduce((acc, command) => { - const { cmd, values } = getPathCommandParams(command); + let newStroke = ''; + for (const [cmd, values] of pathCommandGenerator(stroke)) { if (cmd === 'M' || cmd === 'L') { const [x, y] = values; - return acc + `${cmd} ${x} ${900 - y} `; + newStroke += `${cmd} ${x} ${900 - y} `; + continue; } if (cmd === 'Q') { const [x1, y1, x2, y2] = values; - return acc + `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} `; + newStroke += `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} `; + continue; } if (cmd === 'C') { const [x1, y1, x2, y2, x, y] = values; - return acc + `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} ${x} ${900 - y} `; + newStroke += `${cmd} ${x1} ${900 - y1} ${x2} ${900 - y2} ${x} ${900 - y} `; + continue; } if (cmd === 'Z') { - return acc + 'Z'; + newStroke += 'Z'; + continue; } - return acc + `${cmd} ${values.join(' ')}`; - }, ''); + newStroke += `${cmd} ${values.join(' ')}`; + } return newStroke; }); diff --git a/src/renderers/canvas/canvasUtils.ts b/src/renderers/canvas/canvasUtils.ts index df373e71c..21e1bc2c1 100644 --- a/src/renderers/canvas/canvasUtils.ts +++ b/src/renderers/canvas/canvasUtils.ts @@ -1,4 +1,4 @@ -import { getPathCommandParams, getPathCommands } from '../../utils'; +import { pathCommandGenerator } from '../../utils'; import { Point } from '../../typings/types'; export const drawPath = (ctx: CanvasRenderingContext2D, points: Point[]) => { @@ -20,8 +20,7 @@ export const drawPath = (ctx: CanvasRenderingContext2D, points: Point[]) => { */ export const pathStringToCanvas = (pathString: string) => { const commands = [(ctx: CanvasRenderingContext2D) => ctx.beginPath()]; - for (const command of getPathCommands(pathString)) { - const { cmd, values } = getPathCommandParams(command); + for (const [cmd, values] of pathCommandGenerator(pathString)) { if (cmd === 'M') { commands.push((ctx) => ctx.moveTo(...(values as [number, number]))); } else if (cmd === 'L') { diff --git a/src/typings/types.ts b/src/typings/types.ts index a02a4735d..ad67863bb 100644 --- a/src/typings/types.ts +++ b/src/typings/types.ts @@ -39,7 +39,7 @@ export type OnCompleteFunction = (res: { canceled: boolean }) => void; /** Creates a render target (e.g. svg, canvas) */ export type RenderTargetInitFunction< - TElement extends HTMLElement | SVGElement | SVGSVGElement | HTMLCanvasElement, + TElement extends HTMLElement | SVGElement | SVGSVGElement | HTMLCanvasElement > = ( elmOrId: string | TElement, width?: string | number | null, @@ -95,7 +95,7 @@ type BaseHanziWriterOptions = { * * Default: applies a "900-Y" transform to strokes/medians for `hanzi-writer-data@v2` characters */ - processCharData?: (charData: CharacterJson) => CharacterJson; + processCharData?: ((charData: CharacterJson) => CharacterJson) | null; // Animation options diff --git a/src/utils.ts b/src/utils.ts index 3dd7ffee0..3e7053470 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -143,11 +143,51 @@ export const isMsBrowser = export const noop = () => {}; /** - * Parses a given SVG path string and returns an array of path commands + * A generator function to parse a given SVG path string and yield each command with its arguments + * + * This algo runs in O(n) time, which should be faster than applying regex parsing, splitting, filtering, and trimming */ -export const getPathCommands = (pathString: string): string[] => { - return pathString.split(/(^|\s+)(?=[A-Z])/).filter((part) => part !== ' '); -}; +export function* pathCommandGenerator(pathString: string): Generator<[string, number[]]> { + let activeCommand = ''; + let args: number[] = []; + let chars = ''; + + for (let i = 0; i < pathString.length; i++) { + const char = pathString[i]; + + // New command + if (char === 'M' || char === 'C' || char === 'Q' || char === 'L' || char === 'Z') { + // If we have a pending command, yield it along with its arguments + if (activeCommand) { + if (chars) { + args.push(parseFloat(chars)); + chars = ''; + } + yield [activeCommand, args]; + } + // End path and break the loop + if (char === 'Z') { + yield ['Z', []]; + break; + } + // Else, start a new command + activeCommand = char; + args = []; + continue; + } + + // Numbers are separated by spaces or commas + if (char === ' ' || char === ',') { + if (chars) { + args.push(parseFloat(chars)); + } + chars = ''; + continue; + } + + chars += char; + } +} const pathCommandSeparatorRegex = /\s+|[, ]+/; diff --git a/tsconfig.json b/tsconfig.json index 7e6055dd1..227dccced 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "baseUrl": "src", /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, "resolveJsonModule": true, "lib": [ From c93df3eb64e9dc47a23986a6c305672767cc1fcb Mon Sep 17 00:00:00 2001 From: jamsch Date: Fri, 25 Nov 2022 16:04:39 +1300 Subject: [PATCH 4/6] feat: update demo to include a character set picker --- .eslintrc | 1 + demo/index.html | 14 ++++++++---- demo/styles.css | 11 ++++----- demo/test.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 +- 5 files changed, 74 insertions(+), 15 deletions(-) diff --git a/.eslintrc b/.eslintrc index ae1f49794..d22afc991 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,6 +6,7 @@ "dist/*", "build/*", "examples/*", + "demo/*", "babel.config.js", "rollup.config.js", "jest-setup.js" diff --git a/demo/index.html b/demo/index.html index 1ff55a6f9..2deabdcff 100644 --- a/demo/index.html +++ b/demo/index.html @@ -8,12 +8,11 @@ -

Hanzi Writer

@@ -24,11 +23,16 @@

Hanzi Writer

-
- +
+
+
- diff --git a/demo/styles.css b/demo/styles.css index 8358177d8..7bab2414a 100644 --- a/demo/styles.css +++ b/demo/styles.css @@ -62,15 +62,12 @@ button, #target { .actions { width: 400px; margin: 0 auto; + display: flex; + gap: 4px; + margin: 4px auto; + justify-content: center; } -.actions button { - display: block; - width: 97px; - float: left; - margin-right: 4px; - margin-bottom: 4px; -} .actions button:last-child { margin-right: 0; } diff --git a/demo/test.js b/demo/test.js index 7416245a9..a80e237fe 100644 --- a/demo/test.js +++ b/demo/test.js @@ -1,6 +1,8 @@ var writer; var isCharVisible; var isOutlineVisible; +var processCharData; +var charDataLoader; function printStrokePoints(data) { var pointStrs = data.drawnPath.points.map((point) => `{x: ${point.x}, y: ${point.y}}`); @@ -12,7 +14,8 @@ function updateCharacter() { var character = document.querySelector('.js-char').value; window.location.hash = character; - writer = HanziWriter.create('target', character, { + + const options = { width: 400, height: 400, renderer: 'svg', @@ -20,7 +23,13 @@ function updateCharacter() { onCorrectStroke: printStrokePoints, onMistake: printStrokePoints, showCharacter: false, - }); + processCharData, + }; + if (charDataLoader) { + options.charDataLoader = charDataLoader; + } + + writer = HanziWriter.create('target', character, options); isCharVisible = true; isOutlineVisible = true; window.writer = writer; @@ -55,4 +64,52 @@ window.onload = function () { showOutline: true, }); }); + + document.querySelector('.char-selection').addEventListener('input', (ev) => { + const value = ev.target.value; // "hanzi-writer-data" | "hanzi-writer-data-fixed" | "hanzi-writer-data-jp" + const char = document.querySelector('.js-char').value; + + switch (value) { + case 'hanzi-writer-data': + charDataLoader = undefined; + processCharData = undefined; + break; + case 'hanzi-writer-data-fixed': { + charDataLoader = createCharDataLoader( + (char) => + `https://raw.githubusercontent.com/jamsch/hanzi-writer-data/fixed-set/data/${char}.json`, + ); + processCharData = null; // We don't need to process the character data + break; + } + case 'hanzi-writer-data-jp': { + charDataLoader = createCharDataLoader( + (char) => + `https://raw.githubusercontent.com/jamsch/hanzi-writer-data-jp/master/data/${char}.json`, + ); + processCharData = undefined; // We need to process the character data + break; + } + case 'hanzi-writer-data-jp-fixed': { + charDataLoader = createCharDataLoader( + (char) => + `https://raw.githubusercontent.com/jamsch/hanzi-writer-data-jp/fixed-set/data/${char}.json`, + ); + processCharData = null; // We don't need to process the character data + break; + } + default: + break; + } + + updateCharacter(); + }); +}; + +const createCharDataLoader = (getUrl) => { + return (char, onLoad, onError) => + fetch(getUrl(char)) + .then((res) => res.json()) + .then(onLoad) + .catch(onError); }; diff --git a/package.json b/package.json index 00246adff..6f1a23fb9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "test": "jest", "lint-test": "eslint -c .eslintrc src", "lint-fix": "eslint --fix --ext .tsx,.ts .", - "build": "rm -rf dist && rollup -c", + "build": "rollup -c", "prepublishOnly": "rollup -c", "semantic-release": "semantic-release", "prettier": "prettier -w src", From 71ec087ed023a3953f6e2afd50c0a2c446bd2292 Mon Sep 17 00:00:00 2001 From: jamsch Date: Fri, 25 Nov 2022 16:25:47 +1300 Subject: [PATCH 5/6] fix(pathCommandGenerator): account for lowercase commands --- src/utils.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 3e7053470..25c488434 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -153,7 +153,7 @@ export function* pathCommandGenerator(pathString: string): Generator<[string, nu let chars = ''; for (let i = 0; i < pathString.length; i++) { - const char = pathString[i]; + const char = pathString[i].toUpperCase(); // New command if (char === 'M' || char === 'C' || char === 'Q' || char === 'L' || char === 'Z') { @@ -173,19 +173,16 @@ export function* pathCommandGenerator(pathString: string): Generator<[string, nu // Else, start a new command activeCommand = char; args = []; - continue; - } - - // Numbers are separated by spaces or commas - if (char === ' ' || char === ',') { + } else if (char === ' ' || char === ',') { + // Numbers are separated by spaces or commas if (chars) { args.push(parseFloat(chars)); } chars = ''; - continue; + } else { + // This *should* be a number or a decimal point + chars += char; } - - chars += char; } } From 4bc8a4700e7a2459e7c3f7e2f15efbdfd2e6f64a Mon Sep 17 00:00:00 2001 From: jamsch Date: Fri, 25 Nov 2022 16:39:40 +1300 Subject: [PATCH 6/6] refactor: remove unused `getPathCommandParams` --- src/utils.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 25c488434..a1bdf2195 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -185,15 +185,3 @@ export function* pathCommandGenerator(pathString: string): Generator<[string, nu } } } - -const pathCommandSeparatorRegex = /\s+|[, ]+/; - -export const getPathCommandParams = ( - pathCommand: string, -): { - cmd: string; - values: number[]; -} => { - const [cmd, ...params] = pathCommand.split(pathCommandSeparatorRegex); - return { cmd, values: params.map((param) => parseFloat(param)) }; -};