@fluid-experimental/ink 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluid-experimental/ink
2
2
 
3
+ ## 2.3.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.2.0
4
8
 
5
9
  Dependency updates only.
@@ -1 +1 @@
1
- {"version":3,"file":"inkCanvas.d.ts","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAiD,MAAM,iBAAiB,CAAC;AA4G9F;;GAEG;AACH,qBAAa,SAAS;IAMpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IANvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkC;IACvE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,IAAI;IAwBtB,WAAW,CAAC,KAAK,EAAE,MAAM;IAIzB,MAAM;IAeN,KAAK;IAKL,sBAAsB;IAa7B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;CAWpB"}
1
+ {"version":3,"file":"inkCanvas.d.ts","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAiD,MAAM,iBAAiB,CAAC;AAyG9F;;GAEG;AACH,qBAAa,SAAS;IAMpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IANvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkC;IACvE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,IAAI;IAwBtB,WAAW,CAAC,KAAK,EAAE,MAAM;IAIzB,MAAM;IAYN,KAAK;IAKL,sBAAsB;IAa7B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,aAAa;IAiBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;CASpB"}
package/dist/inkCanvas.js CHANGED
@@ -28,21 +28,18 @@ class Vector {
28
28
  }
29
29
  }
30
30
  function drawPolygon(context, points) {
31
- const firstPoint = points[0];
32
- if (firstPoint === undefined) {
31
+ if (points.length === 0) {
33
32
  return;
34
33
  }
35
34
  context.beginPath();
36
35
  // Move to the first point
37
- context.moveTo(firstPoint.x, firstPoint.y);
36
+ context.moveTo(points[0].x, points[0].y);
38
37
  // Draw the rest of the segments
39
38
  for (let i = 1; i < points.length; i++) {
40
- // Non null asserting, this must exist because the we are iterating through the length of points
41
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
42
39
  context.lineTo(points[i].x, points[i].y);
43
40
  }
44
41
  // And then close the shape
45
- context.lineTo(firstPoint.x, firstPoint.y);
42
+ context.lineTo(points[0].x, points[0].y);
46
43
  context.closePath();
47
44
  context.fill();
48
45
  }
@@ -115,10 +112,7 @@ class InkCanvas {
115
112
  this.clearCanvas();
116
113
  const strokes = this.model.getStrokes();
117
114
  // Time of the first operation in stroke 0 is our starting time
118
- const startTime = strokes[0]?.points[0]?.time;
119
- if (startTime === undefined) {
120
- throw new Error("Couldn't get start time");
121
- }
115
+ const startTime = strokes[0].points[0].time;
122
116
  for (const stroke of strokes) {
123
117
  this.animateStroke(stroke, 0, startTime);
124
118
  }
@@ -179,11 +173,7 @@ class InkCanvas {
179
173
  return;
180
174
  }
181
175
  // Draw the requested stroke
182
- // Non null asserting, this must exist because the operationIndex must be less than the length of stroke.points
183
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
184
176
  const current = stroke.points[operationIndex];
185
- // Non null asserting, this must exist because its either the first index or operationIndex minus one which is less than the length of stroke.points
186
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
187
177
  const previous = stroke.points[Math.max(0, operationIndex - 1)];
188
178
  const time = operationIndex === 0 ? current.time - startTime : current.time - previous.time;
189
179
  setTimeout(() => {
@@ -201,8 +191,6 @@ class InkCanvas {
201
191
  this.clearCanvas();
202
192
  const strokes = this.model.getStrokes();
203
193
  for (const stroke of strokes) {
204
- // Non null asserting since previous would not be used if stroke.points is empty
205
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
206
194
  let previous = stroke.points[0];
207
195
  for (const current of stroke.points) {
208
196
  // For the down, current === previous === stroke.operations[0]
@@ -222,10 +210,7 @@ class InkCanvas {
222
210
  const dirtyStrokeId = operation.id;
223
211
  const stroke = this.model.getStroke(dirtyStrokeId);
224
212
  // If this is the only point in the stroke, we'll use it for both the start and end of the segment
225
- const prevPoint =
226
- // Non null asserting, this must exist its within the length of stroke.points
227
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
228
- stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];
213
+ const prevPoint = stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];
229
214
  this.drawStrokeSegment(stroke.pen, prevPoint, operation.point);
230
215
  }
231
216
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inkCanvas.js","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IColor, IInk, IInkPoint, IInkStroke, IPen, IStylusOperation } from \"./interfaces.js\";\n\ninterface IPoint {\n\tx: number;\n\ty: number;\n}\n\nclass Vector {\n\t/**\n\t * Returns the vector resulting from rotating vector by angle\n\t */\n\tpublic static rotate(vector: Vector, angle: number): Vector {\n\t\treturn new Vector(\n\t\t\tvector.x * Math.cos(angle) - vector.y * Math.sin(angle),\n\t\t\tvector.x * Math.sin(angle) + vector.y * Math.cos(angle),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the normalized form of the given vector\n\t */\n\tpublic static normalize(vector: Vector): Vector {\n\t\tconst length = vector.length();\n\t\treturn new Vector(vector.x / length, vector.y / length);\n\t}\n\n\tconstructor(\n\t\tpublic x: number,\n\t\tpublic y: number,\n\t) {}\n\n\tpublic length(): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t}\n}\n\nfunction drawPolygon(context: CanvasRenderingContext2D, points: IPoint[]) {\n\tconst firstPoint = points[0];\n\tif (firstPoint === undefined) {\n\t\treturn;\n\t}\n\n\tcontext.beginPath();\n\t// Move to the first point\n\tcontext.moveTo(firstPoint.x, firstPoint.y);\n\n\t// Draw the rest of the segments\n\tfor (let i = 1; i < points.length; i++) {\n\t\t// Non null asserting, this must exist because the we are iterating through the length of points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tcontext.lineTo(points[i]!.x, points[i]!.y);\n\t}\n\n\t// And then close the shape\n\tcontext.lineTo(firstPoint.x, firstPoint.y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawCircle(context: CanvasRenderingContext2D, center: IPoint, radius: number) {\n\tcontext.beginPath();\n\tcontext.moveTo(center.x, center.y);\n\tcontext.arc(center.x, center.y, radius, 0, Math.PI * 2);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawShapes(\n\tcontext: CanvasRenderingContext2D,\n\tstartPoint: IInkPoint,\n\tendPoint: IInkPoint,\n\tpen: IPen,\n): void {\n\tconst dirVector = new Vector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);\n\tconst len = dirVector.length();\n\n\tconst widthAtStart = pen.thickness * startPoint.pressure;\n\tconst widthAtEnd = pen.thickness * endPoint.pressure;\n\n\tif (len + Math.min(widthAtStart, widthAtEnd) > Math.max(widthAtStart, widthAtEnd)) {\n\t\t// Circles don't completely overlap, need a trapezoid\n\t\tconst normalizedLateralVector = new Vector(-dirVector.y / len, dirVector.x / len);\n\n\t\tconst trapezoidP0 = {\n\t\t\tx: startPoint.x + widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y + widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP1 = {\n\t\t\tx: startPoint.x - widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y - widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP2 = {\n\t\t\tx: endPoint.x - widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y - widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP3 = {\n\t\t\tx: endPoint.x + widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y + widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\n\t\tdrawPolygon(context, [trapezoidP0, trapezoidP1, trapezoidP2, trapezoidP3]);\n\t}\n\n\t// End circle\n\t// TODO should only draw if not eclipsed by the previous circle, be careful about single-point\n\tdrawCircle(context, { x: endPoint.x, y: endPoint.y }, widthAtEnd);\n}\n\n/**\n * @internal\n */\nexport class InkCanvas {\n\tprivate readonly context: CanvasRenderingContext2D;\n\tprivate readonly localActiveStrokeMap: Map<number, string> = new Map();\n\tprivate readonly currentPen: IPen;\n\n\tconstructor(\n\t\tprivate readonly canvas: HTMLCanvasElement,\n\t\tprivate readonly model: IInk,\n\t) {\n\t\tthis.model.on(\"clear\", this.redraw.bind(this));\n\t\tthis.model.on(\"stylus\", this.handleStylus.bind(this));\n\t\tthis.canvas.style.touchAction = \"none\";\n\n\t\tthis.canvas.addEventListener(\"pointerdown\", this.handlePointerDown.bind(this));\n\t\tthis.canvas.addEventListener(\"pointermove\", this.handlePointerMove.bind(this));\n\t\tthis.canvas.addEventListener(\"pointerup\", this.handlePointerUp.bind(this));\n\n\t\tconst context = this.canvas.getContext(\"2d\");\n\t\tif (context === null) {\n\t\t\tthrow new Error(\"InkCanvas requires a canvas with 2d rendering context\");\n\t\t}\n\t\tthis.context = context;\n\n\t\tthis.currentPen = {\n\t\t\tcolor: { r: 0, g: 161, b: 241, a: 0 },\n\t\t\tthickness: 7,\n\t\t};\n\n\t\tthis.sizeCanvasBackingStore();\n\t}\n\n\tpublic setPenColor(color: IColor) {\n\t\tthis.currentPen.color = color;\n\t}\n\n\tpublic replay() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\n\t\t// Time of the first operation in stroke 0 is our starting time\n\t\tconst startTime = strokes[0]?.points[0]?.time;\n\t\tif (startTime === undefined) {\n\t\t\tthrow new Error(\"Couldn't get start time\");\n\t\t}\n\t\tfor (const stroke of strokes) {\n\t\t\tthis.animateStroke(stroke, 0, startTime);\n\t\t}\n\t}\n\n\tpublic clear() {\n\t\tthis.model.clear();\n\t\tthis.redraw();\n\t}\n\n\tpublic sizeCanvasBackingStore() {\n\t\tconst canvasBoundingClientRect = this.canvas.getBoundingClientRect();\n\t\t// Scale the canvas size to match the physical pixel to avoid blurriness\n\t\tconst scale = window.devicePixelRatio;\n\t\tthis.canvas.width = Math.floor(canvasBoundingClientRect.width * scale);\n\t\tthis.canvas.height = Math.floor(canvasBoundingClientRect.height * scale);\n\t\t// Scale the context to bring back coordinate system in CSS pixels\n\t\tthis.context.setTransform(1, 0, 0, 1, 0, 0);\n\t\tthis.context.scale(scale, scale);\n\n\t\tthis.redraw();\n\t}\n\n\tprivate handlePointerDown(evt: PointerEvent) {\n\t\t// We will accept pen down or mouse left down as the start of a stroke.\n\t\tif (evt.pointerType === \"pen\" || (evt.pointerType === \"mouse\" && evt.button === 0)) {\n\t\t\tconst strokeId = this.model.createStroke(this.currentPen).id;\n\t\t\tthis.localActiveStrokeMap.set(evt.pointerId, strokeId);\n\n\t\t\tthis.appendPointerEventToStroke(evt);\n\n\t\t\tevt.preventDefault();\n\t\t}\n\t}\n\n\tprivate handlePointerMove(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tconst evts = (evt as any)?.getCoalescedEvents() ?? ([evt] as PointerEvent[]);\n\t\t\tfor (const e of evts) {\n\t\t\t\tthis.appendPointerEventToStroke(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePointerUp(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tthis.appendPointerEventToStroke(evt);\n\t\t\tthis.localActiveStrokeMap.delete(evt.pointerId);\n\t\t}\n\t}\n\n\tprivate appendPointerEventToStroke(evt: PointerEvent) {\n\t\tconst strokeId = this.localActiveStrokeMap.get(evt.pointerId);\n\t\tif (strokeId === undefined) {\n\t\t\tthrow new Error(\"Unexpected pointer ID trying to append to stroke\");\n\t\t}\n\t\tconst inkPt = {\n\t\t\tx: evt.offsetX,\n\t\t\ty: evt.offsetY,\n\t\t\ttime: Date.now(),\n\t\t\tpressure: evt.pressure,\n\t\t};\n\t\tthis.model.appendPointToStroke(inkPt, strokeId);\n\t}\n\n\tprivate animateStroke(stroke: IInkStroke, operationIndex: number, startTime: number) {\n\t\tif (operationIndex >= stroke.points.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Draw the requested stroke\n\t\t// Non null asserting, this must exist because the operationIndex must be less than the length of stroke.points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst current = stroke.points[operationIndex]!;\n\t\t// Non null asserting, this must exist because its either the first index or operationIndex minus one which is less than the length of stroke.points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst previous = stroke.points[Math.max(0, operationIndex - 1)]!;\n\t\tconst time =\n\t\t\toperationIndex === 0 ? current.time - startTime : current.time - previous.time;\n\n\t\tsetTimeout(() => {\n\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\tthis.animateStroke(stroke, operationIndex + 1, startTime);\n\t\t}, time);\n\t}\n\n\t/**\n\t * Clears the canvas\n\t */\n\tprivate clearCanvas() {\n\t\tthis.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t}\n\n\tprivate redraw() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\t\tfor (const stroke of strokes) {\n\t\t\t// Non null asserting since previous would not be used if stroke.points is empty\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tlet previous = stroke.points[0]!;\n\t\t\tfor (const current of stroke.points) {\n\t\t\t\t// For the down, current === previous === stroke.operations[0]\n\t\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\t\tprevious = current;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate drawStrokeSegment(pen: IPen, current: IInkPoint, previous: IInkPoint) {\n\t\t// TODO Consider save/restore context\n\t\t// TODO Consider half-pixel offset\n\t\tthis.context.fillStyle = `rgb(${pen.color.r}, ${pen.color.g}, ${pen.color.b})`;\n\t\tdrawShapes(this.context, previous, current, pen);\n\t}\n\n\tprivate handleStylus(operation: IStylusOperation) {\n\t\t// Render the dirty stroke\n\t\tconst dirtyStrokeId = operation.id;\n\t\tconst stroke = this.model.getStroke(dirtyStrokeId);\n\t\t// If this is the only point in the stroke, we'll use it for both the start and end of the segment\n\t\tconst prevPoint =\n\t\t\t// Non null asserting, this must exist its within the length of stroke.points\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tstroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)]!;\n\t\tthis.drawStrokeSegment(stroke.pen, prevPoint, operation.point);\n\t}\n}\n"]}
1
+ {"version":3,"file":"inkCanvas.js","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IColor, IInk, IInkPoint, IInkStroke, IPen, IStylusOperation } from \"./interfaces.js\";\n\ninterface IPoint {\n\tx: number;\n\ty: number;\n}\n\nclass Vector {\n\t/**\n\t * Returns the vector resulting from rotating vector by angle\n\t */\n\tpublic static rotate(vector: Vector, angle: number): Vector {\n\t\treturn new Vector(\n\t\t\tvector.x * Math.cos(angle) - vector.y * Math.sin(angle),\n\t\t\tvector.x * Math.sin(angle) + vector.y * Math.cos(angle),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the normalized form of the given vector\n\t */\n\tpublic static normalize(vector: Vector): Vector {\n\t\tconst length = vector.length();\n\t\treturn new Vector(vector.x / length, vector.y / length);\n\t}\n\n\tconstructor(\n\t\tpublic x: number,\n\t\tpublic y: number,\n\t) {}\n\n\tpublic length(): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t}\n}\n\nfunction drawPolygon(context: CanvasRenderingContext2D, points: IPoint[]) {\n\tif (points.length === 0) {\n\t\treturn;\n\t}\n\n\tcontext.beginPath();\n\t// Move to the first point\n\tcontext.moveTo(points[0].x, points[0].y);\n\n\t// Draw the rest of the segments\n\tfor (let i = 1; i < points.length; i++) {\n\t\tcontext.lineTo(points[i].x, points[i].y);\n\t}\n\n\t// And then close the shape\n\tcontext.lineTo(points[0].x, points[0].y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawCircle(context: CanvasRenderingContext2D, center: IPoint, radius: number) {\n\tcontext.beginPath();\n\tcontext.moveTo(center.x, center.y);\n\tcontext.arc(center.x, center.y, radius, 0, Math.PI * 2);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawShapes(\n\tcontext: CanvasRenderingContext2D,\n\tstartPoint: IInkPoint,\n\tendPoint: IInkPoint,\n\tpen: IPen,\n): void {\n\tconst dirVector = new Vector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);\n\tconst len = dirVector.length();\n\n\tconst widthAtStart = pen.thickness * startPoint.pressure;\n\tconst widthAtEnd = pen.thickness * endPoint.pressure;\n\n\tif (len + Math.min(widthAtStart, widthAtEnd) > Math.max(widthAtStart, widthAtEnd)) {\n\t\t// Circles don't completely overlap, need a trapezoid\n\t\tconst normalizedLateralVector = new Vector(-dirVector.y / len, dirVector.x / len);\n\n\t\tconst trapezoidP0 = {\n\t\t\tx: startPoint.x + widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y + widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP1 = {\n\t\t\tx: startPoint.x - widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y - widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP2 = {\n\t\t\tx: endPoint.x - widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y - widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP3 = {\n\t\t\tx: endPoint.x + widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y + widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\n\t\tdrawPolygon(context, [trapezoidP0, trapezoidP1, trapezoidP2, trapezoidP3]);\n\t}\n\n\t// End circle\n\t// TODO should only draw if not eclipsed by the previous circle, be careful about single-point\n\tdrawCircle(context, { x: endPoint.x, y: endPoint.y }, widthAtEnd);\n}\n\n/**\n * @internal\n */\nexport class InkCanvas {\n\tprivate readonly context: CanvasRenderingContext2D;\n\tprivate readonly localActiveStrokeMap: Map<number, string> = new Map();\n\tprivate readonly currentPen: IPen;\n\n\tconstructor(\n\t\tprivate readonly canvas: HTMLCanvasElement,\n\t\tprivate readonly model: IInk,\n\t) {\n\t\tthis.model.on(\"clear\", this.redraw.bind(this));\n\t\tthis.model.on(\"stylus\", this.handleStylus.bind(this));\n\t\tthis.canvas.style.touchAction = \"none\";\n\n\t\tthis.canvas.addEventListener(\"pointerdown\", this.handlePointerDown.bind(this));\n\t\tthis.canvas.addEventListener(\"pointermove\", this.handlePointerMove.bind(this));\n\t\tthis.canvas.addEventListener(\"pointerup\", this.handlePointerUp.bind(this));\n\n\t\tconst context = this.canvas.getContext(\"2d\");\n\t\tif (context === null) {\n\t\t\tthrow new Error(\"InkCanvas requires a canvas with 2d rendering context\");\n\t\t}\n\t\tthis.context = context;\n\n\t\tthis.currentPen = {\n\t\t\tcolor: { r: 0, g: 161, b: 241, a: 0 },\n\t\t\tthickness: 7,\n\t\t};\n\n\t\tthis.sizeCanvasBackingStore();\n\t}\n\n\tpublic setPenColor(color: IColor) {\n\t\tthis.currentPen.color = color;\n\t}\n\n\tpublic replay() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\n\t\t// Time of the first operation in stroke 0 is our starting time\n\t\tconst startTime = strokes[0].points[0].time;\n\t\tfor (const stroke of strokes) {\n\t\t\tthis.animateStroke(stroke, 0, startTime);\n\t\t}\n\t}\n\n\tpublic clear() {\n\t\tthis.model.clear();\n\t\tthis.redraw();\n\t}\n\n\tpublic sizeCanvasBackingStore() {\n\t\tconst canvasBoundingClientRect = this.canvas.getBoundingClientRect();\n\t\t// Scale the canvas size to match the physical pixel to avoid blurriness\n\t\tconst scale = window.devicePixelRatio;\n\t\tthis.canvas.width = Math.floor(canvasBoundingClientRect.width * scale);\n\t\tthis.canvas.height = Math.floor(canvasBoundingClientRect.height * scale);\n\t\t// Scale the context to bring back coordinate system in CSS pixels\n\t\tthis.context.setTransform(1, 0, 0, 1, 0, 0);\n\t\tthis.context.scale(scale, scale);\n\n\t\tthis.redraw();\n\t}\n\n\tprivate handlePointerDown(evt: PointerEvent) {\n\t\t// We will accept pen down or mouse left down as the start of a stroke.\n\t\tif (evt.pointerType === \"pen\" || (evt.pointerType === \"mouse\" && evt.button === 0)) {\n\t\t\tconst strokeId = this.model.createStroke(this.currentPen).id;\n\t\t\tthis.localActiveStrokeMap.set(evt.pointerId, strokeId);\n\n\t\t\tthis.appendPointerEventToStroke(evt);\n\n\t\t\tevt.preventDefault();\n\t\t}\n\t}\n\n\tprivate handlePointerMove(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tconst evts = (evt as any)?.getCoalescedEvents() ?? ([evt] as PointerEvent[]);\n\t\t\tfor (const e of evts) {\n\t\t\t\tthis.appendPointerEventToStroke(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePointerUp(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tthis.appendPointerEventToStroke(evt);\n\t\t\tthis.localActiveStrokeMap.delete(evt.pointerId);\n\t\t}\n\t}\n\n\tprivate appendPointerEventToStroke(evt: PointerEvent) {\n\t\tconst strokeId = this.localActiveStrokeMap.get(evt.pointerId);\n\t\tif (strokeId === undefined) {\n\t\t\tthrow new Error(\"Unexpected pointer ID trying to append to stroke\");\n\t\t}\n\t\tconst inkPt = {\n\t\t\tx: evt.offsetX,\n\t\t\ty: evt.offsetY,\n\t\t\ttime: Date.now(),\n\t\t\tpressure: evt.pressure,\n\t\t};\n\t\tthis.model.appendPointToStroke(inkPt, strokeId);\n\t}\n\n\tprivate animateStroke(stroke: IInkStroke, operationIndex: number, startTime: number) {\n\t\tif (operationIndex >= stroke.points.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Draw the requested stroke\n\t\tconst current = stroke.points[operationIndex];\n\t\tconst previous = stroke.points[Math.max(0, operationIndex - 1)];\n\t\tconst time =\n\t\t\toperationIndex === 0 ? current.time - startTime : current.time - previous.time;\n\n\t\tsetTimeout(() => {\n\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\tthis.animateStroke(stroke, operationIndex + 1, startTime);\n\t\t}, time);\n\t}\n\n\t/**\n\t * Clears the canvas\n\t */\n\tprivate clearCanvas() {\n\t\tthis.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t}\n\n\tprivate redraw() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\t\tfor (const stroke of strokes) {\n\t\t\tlet previous = stroke.points[0];\n\t\t\tfor (const current of stroke.points) {\n\t\t\t\t// For the down, current === previous === stroke.operations[0]\n\t\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\t\tprevious = current;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate drawStrokeSegment(pen: IPen, current: IInkPoint, previous: IInkPoint) {\n\t\t// TODO Consider save/restore context\n\t\t// TODO Consider half-pixel offset\n\t\tthis.context.fillStyle = `rgb(${pen.color.r}, ${pen.color.g}, ${pen.color.b})`;\n\t\tdrawShapes(this.context, previous, current, pen);\n\t}\n\n\tprivate handleStylus(operation: IStylusOperation) {\n\t\t// Render the dirty stroke\n\t\tconst dirtyStrokeId = operation.id;\n\t\tconst stroke = this.model.getStroke(dirtyStrokeId);\n\t\t// If this is the only point in the stroke, we'll use it for both the start and end of the segment\n\t\tconst prevPoint =\n\t\t\tstroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];\n\t\tthis.drawStrokeSegment(stroke.pen, prevPoint, operation.point);\n\t}\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluid-experimental/ink";
8
- export declare const pkgVersion = "2.2.0";
8
+ export declare const pkgVersion = "2.3.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluid-experimental/ink";
11
- exports.pkgVersion = "2.2.0";
11
+ exports.pkgVersion = "2.3.0";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,yBAAyB,CAAC;AACpC,QAAA,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/ink\";\nexport const pkgVersion = \"2.2.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,yBAAyB,CAAC;AACpC,QAAA,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/ink\";\nexport const pkgVersion = \"2.3.0\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,OAAO;IACnB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAe;IAE9B;;OAEG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACS,QAAQ,CAAC,EAAE,gBAAgB;IAKvC;;OAEG;IACI,UAAU,IAAI,UAAU,EAAE;IAIjC;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMzC;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAK1C;;;OAGG;IACI,eAAe,IAAI,gBAAgB;CAM1C"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,OAAO;IACnB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAe;IAE9B;;OAEG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACS,QAAQ,CAAC,EAAE,gBAAgB;IAKvC;;OAEG;IACI,UAAU,IAAI,UAAU,EAAE;IAIjC;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAIzC;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAK1C;;;OAGG;IACI,eAAe,IAAI,gBAAgB;CAM1C"}
package/dist/snapshot.js CHANGED
@@ -27,8 +27,6 @@ class InkData {
27
27
  * {@inheritDoc IInk.getStroke}
28
28
  */
29
29
  getStroke(key) {
30
- // Non null asserting, it should be okay that a bad key results in an error being thrown
31
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
32
30
  return this.strokes[this.strokeIndex[key]];
33
31
  }
34
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAoBH;;GAEG;AACH,MAAa,OAAO;IAWnB;;;OAGG;IACH,YAAY,QAA2B;QACtC,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAW;QAC3B,wFAAwF;QACxF,oEAAoE;QACpE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAE,CAAE,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,MAAkB;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACI,eAAe;QACrB,OAAO;YACN,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;CACD;AA/DD,0BA+DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IInkStroke } from \"./interfaces.js\";\n\n/**\n * Ink snapshot interface.\n */\nexport interface ISerializableInk {\n\t/**\n\t * Collection of ink strokes.\n\t */\n\tstrokes: IInkStroke[];\n\n\t/**\n\t * Stores a mapping from the provided key to its index in strokes. Since\n\t * ISerializableInk is serialized we need to use an index.\n\t */\n\tstrokeIndex: { [key: string]: number };\n}\n\n/**\n * Maintains a live record of the data that can be used for snapshotting.\n */\nexport class InkData {\n\t/**\n\t * {@inheritDoc ISerializableInk.strokes}\n\t */\n\tprivate strokes: IInkStroke[];\n\n\t/**\n\t * {@inheritDoc ISerializableInk.strokeIndex}\n\t */\n\tprivate strokeIndex: { [key: string]: number };\n\n\t/**\n\t * Construct a new InkData.\n\t * @param snapshot - Existing data to initialize with\n\t */\n\tconstructor(snapshot?: ISerializableInk) {\n\t\tthis.strokes = snapshot?.strokes ?? [];\n\t\tthis.strokeIndex = snapshot?.strokeIndex ?? {};\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStrokes}\n\t */\n\tpublic getStrokes(): IInkStroke[] {\n\t\treturn this.strokes;\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStroke}\n\t */\n\tpublic getStroke(key: string): IInkStroke {\n\t\t// Non null asserting, it should be okay that a bad key results in an error being thrown\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this.strokes[this.strokeIndex[key]!]!;\n\t}\n\n\t/**\n\t * Clear all stored data.\n\t */\n\tpublic clear(): void {\n\t\tthis.strokes = [];\n\t\tthis.strokeIndex = {};\n\t}\n\n\t/**\n\t * Add the given stroke to the stored data.\n\t * @param stroke - The stroke to add\n\t */\n\tpublic addStroke(stroke: IInkStroke): void {\n\t\tthis.strokes.push(stroke);\n\t\tthis.strokeIndex[stroke.id] = this.strokes.length - 1;\n\t}\n\n\t/**\n\t * Get a JSON-compatible representation of the stored data.\n\t * @returns The JSON-compatible object\n\t */\n\tpublic getSerializable(): ISerializableInk {\n\t\treturn {\n\t\t\tstrokes: this.strokes,\n\t\t\tstrokeIndex: this.strokeIndex,\n\t\t};\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAoBH;;GAEG;AACH,MAAa,OAAO;IAWnB;;;OAGG;IACH,YAAY,QAA2B;QACtC,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAW;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,MAAkB;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACI,eAAe;QACrB,OAAO;YACN,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;CACD;AA7DD,0BA6DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IInkStroke } from \"./interfaces.js\";\n\n/**\n * Ink snapshot interface.\n */\nexport interface ISerializableInk {\n\t/**\n\t * Collection of ink strokes.\n\t */\n\tstrokes: IInkStroke[];\n\n\t/**\n\t * Stores a mapping from the provided key to its index in strokes. Since\n\t * ISerializableInk is serialized we need to use an index.\n\t */\n\tstrokeIndex: { [key: string]: number };\n}\n\n/**\n * Maintains a live record of the data that can be used for snapshotting.\n */\nexport class InkData {\n\t/**\n\t * {@inheritDoc ISerializableInk.strokes}\n\t */\n\tprivate strokes: IInkStroke[];\n\n\t/**\n\t * {@inheritDoc ISerializableInk.strokeIndex}\n\t */\n\tprivate strokeIndex: { [key: string]: number };\n\n\t/**\n\t * Construct a new InkData.\n\t * @param snapshot - Existing data to initialize with\n\t */\n\tconstructor(snapshot?: ISerializableInk) {\n\t\tthis.strokes = snapshot?.strokes ?? [];\n\t\tthis.strokeIndex = snapshot?.strokeIndex ?? {};\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStrokes}\n\t */\n\tpublic getStrokes(): IInkStroke[] {\n\t\treturn this.strokes;\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStroke}\n\t */\n\tpublic getStroke(key: string): IInkStroke {\n\t\treturn this.strokes[this.strokeIndex[key]];\n\t}\n\n\t/**\n\t * Clear all stored data.\n\t */\n\tpublic clear(): void {\n\t\tthis.strokes = [];\n\t\tthis.strokeIndex = {};\n\t}\n\n\t/**\n\t * Add the given stroke to the stored data.\n\t * @param stroke - The stroke to add\n\t */\n\tpublic addStroke(stroke: IInkStroke): void {\n\t\tthis.strokes.push(stroke);\n\t\tthis.strokeIndex[stroke.id] = this.strokes.length - 1;\n\t}\n\n\t/**\n\t * Get a JSON-compatible representation of the stored data.\n\t * @returns The JSON-compatible object\n\t */\n\tpublic getSerializable(): ISerializableInk {\n\t\treturn {\n\t\t\tstrokes: this.strokes,\n\t\t\tstrokeIndex: this.strokeIndex,\n\t\t};\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"inkCanvas.d.ts","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAiD,MAAM,iBAAiB,CAAC;AA4G9F;;GAEG;AACH,qBAAa,SAAS;IAMpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IANvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkC;IACvE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,IAAI;IAwBtB,WAAW,CAAC,KAAK,EAAE,MAAM;IAIzB,MAAM;IAeN,KAAK;IAKL,sBAAsB;IAa7B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;CAWpB"}
1
+ {"version":3,"file":"inkCanvas.d.ts","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAiD,MAAM,iBAAiB,CAAC;AAyG9F;;GAEG;AACH,qBAAa,SAAS;IAMpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IANvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkC;IACvE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;gBAGhB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,IAAI;IAwBtB,WAAW,CAAC,KAAK,EAAE,MAAM;IAIzB,MAAM;IAYN,KAAK;IAKL,sBAAsB;IAa7B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,aAAa;IAiBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;CASpB"}
package/lib/inkCanvas.js CHANGED
@@ -25,21 +25,18 @@ class Vector {
25
25
  }
26
26
  }
27
27
  function drawPolygon(context, points) {
28
- const firstPoint = points[0];
29
- if (firstPoint === undefined) {
28
+ if (points.length === 0) {
30
29
  return;
31
30
  }
32
31
  context.beginPath();
33
32
  // Move to the first point
34
- context.moveTo(firstPoint.x, firstPoint.y);
33
+ context.moveTo(points[0].x, points[0].y);
35
34
  // Draw the rest of the segments
36
35
  for (let i = 1; i < points.length; i++) {
37
- // Non null asserting, this must exist because the we are iterating through the length of points
38
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
39
36
  context.lineTo(points[i].x, points[i].y);
40
37
  }
41
38
  // And then close the shape
42
- context.lineTo(firstPoint.x, firstPoint.y);
39
+ context.lineTo(points[0].x, points[0].y);
43
40
  context.closePath();
44
41
  context.fill();
45
42
  }
@@ -112,10 +109,7 @@ export class InkCanvas {
112
109
  this.clearCanvas();
113
110
  const strokes = this.model.getStrokes();
114
111
  // Time of the first operation in stroke 0 is our starting time
115
- const startTime = strokes[0]?.points[0]?.time;
116
- if (startTime === undefined) {
117
- throw new Error("Couldn't get start time");
118
- }
112
+ const startTime = strokes[0].points[0].time;
119
113
  for (const stroke of strokes) {
120
114
  this.animateStroke(stroke, 0, startTime);
121
115
  }
@@ -176,11 +170,7 @@ export class InkCanvas {
176
170
  return;
177
171
  }
178
172
  // Draw the requested stroke
179
- // Non null asserting, this must exist because the operationIndex must be less than the length of stroke.points
180
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
181
173
  const current = stroke.points[operationIndex];
182
- // Non null asserting, this must exist because its either the first index or operationIndex minus one which is less than the length of stroke.points
183
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
184
174
  const previous = stroke.points[Math.max(0, operationIndex - 1)];
185
175
  const time = operationIndex === 0 ? current.time - startTime : current.time - previous.time;
186
176
  setTimeout(() => {
@@ -198,8 +188,6 @@ export class InkCanvas {
198
188
  this.clearCanvas();
199
189
  const strokes = this.model.getStrokes();
200
190
  for (const stroke of strokes) {
201
- // Non null asserting since previous would not be used if stroke.points is empty
202
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
203
191
  let previous = stroke.points[0];
204
192
  for (const current of stroke.points) {
205
193
  // For the down, current === previous === stroke.operations[0]
@@ -219,10 +207,7 @@ export class InkCanvas {
219
207
  const dirtyStrokeId = operation.id;
220
208
  const stroke = this.model.getStroke(dirtyStrokeId);
221
209
  // If this is the only point in the stroke, we'll use it for both the start and end of the segment
222
- const prevPoint =
223
- // Non null asserting, this must exist its within the length of stroke.points
224
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
225
- stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];
210
+ const prevPoint = stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];
226
211
  this.drawStrokeSegment(stroke.pen, prevPoint, operation.point);
227
212
  }
228
213
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inkCanvas.js","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IColor, IInk, IInkPoint, IInkStroke, IPen, IStylusOperation } from \"./interfaces.js\";\n\ninterface IPoint {\n\tx: number;\n\ty: number;\n}\n\nclass Vector {\n\t/**\n\t * Returns the vector resulting from rotating vector by angle\n\t */\n\tpublic static rotate(vector: Vector, angle: number): Vector {\n\t\treturn new Vector(\n\t\t\tvector.x * Math.cos(angle) - vector.y * Math.sin(angle),\n\t\t\tvector.x * Math.sin(angle) + vector.y * Math.cos(angle),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the normalized form of the given vector\n\t */\n\tpublic static normalize(vector: Vector): Vector {\n\t\tconst length = vector.length();\n\t\treturn new Vector(vector.x / length, vector.y / length);\n\t}\n\n\tconstructor(\n\t\tpublic x: number,\n\t\tpublic y: number,\n\t) {}\n\n\tpublic length(): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t}\n}\n\nfunction drawPolygon(context: CanvasRenderingContext2D, points: IPoint[]) {\n\tconst firstPoint = points[0];\n\tif (firstPoint === undefined) {\n\t\treturn;\n\t}\n\n\tcontext.beginPath();\n\t// Move to the first point\n\tcontext.moveTo(firstPoint.x, firstPoint.y);\n\n\t// Draw the rest of the segments\n\tfor (let i = 1; i < points.length; i++) {\n\t\t// Non null asserting, this must exist because the we are iterating through the length of points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tcontext.lineTo(points[i]!.x, points[i]!.y);\n\t}\n\n\t// And then close the shape\n\tcontext.lineTo(firstPoint.x, firstPoint.y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawCircle(context: CanvasRenderingContext2D, center: IPoint, radius: number) {\n\tcontext.beginPath();\n\tcontext.moveTo(center.x, center.y);\n\tcontext.arc(center.x, center.y, radius, 0, Math.PI * 2);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawShapes(\n\tcontext: CanvasRenderingContext2D,\n\tstartPoint: IInkPoint,\n\tendPoint: IInkPoint,\n\tpen: IPen,\n): void {\n\tconst dirVector = new Vector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);\n\tconst len = dirVector.length();\n\n\tconst widthAtStart = pen.thickness * startPoint.pressure;\n\tconst widthAtEnd = pen.thickness * endPoint.pressure;\n\n\tif (len + Math.min(widthAtStart, widthAtEnd) > Math.max(widthAtStart, widthAtEnd)) {\n\t\t// Circles don't completely overlap, need a trapezoid\n\t\tconst normalizedLateralVector = new Vector(-dirVector.y / len, dirVector.x / len);\n\n\t\tconst trapezoidP0 = {\n\t\t\tx: startPoint.x + widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y + widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP1 = {\n\t\t\tx: startPoint.x - widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y - widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP2 = {\n\t\t\tx: endPoint.x - widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y - widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP3 = {\n\t\t\tx: endPoint.x + widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y + widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\n\t\tdrawPolygon(context, [trapezoidP0, trapezoidP1, trapezoidP2, trapezoidP3]);\n\t}\n\n\t// End circle\n\t// TODO should only draw if not eclipsed by the previous circle, be careful about single-point\n\tdrawCircle(context, { x: endPoint.x, y: endPoint.y }, widthAtEnd);\n}\n\n/**\n * @internal\n */\nexport class InkCanvas {\n\tprivate readonly context: CanvasRenderingContext2D;\n\tprivate readonly localActiveStrokeMap: Map<number, string> = new Map();\n\tprivate readonly currentPen: IPen;\n\n\tconstructor(\n\t\tprivate readonly canvas: HTMLCanvasElement,\n\t\tprivate readonly model: IInk,\n\t) {\n\t\tthis.model.on(\"clear\", this.redraw.bind(this));\n\t\tthis.model.on(\"stylus\", this.handleStylus.bind(this));\n\t\tthis.canvas.style.touchAction = \"none\";\n\n\t\tthis.canvas.addEventListener(\"pointerdown\", this.handlePointerDown.bind(this));\n\t\tthis.canvas.addEventListener(\"pointermove\", this.handlePointerMove.bind(this));\n\t\tthis.canvas.addEventListener(\"pointerup\", this.handlePointerUp.bind(this));\n\n\t\tconst context = this.canvas.getContext(\"2d\");\n\t\tif (context === null) {\n\t\t\tthrow new Error(\"InkCanvas requires a canvas with 2d rendering context\");\n\t\t}\n\t\tthis.context = context;\n\n\t\tthis.currentPen = {\n\t\t\tcolor: { r: 0, g: 161, b: 241, a: 0 },\n\t\t\tthickness: 7,\n\t\t};\n\n\t\tthis.sizeCanvasBackingStore();\n\t}\n\n\tpublic setPenColor(color: IColor) {\n\t\tthis.currentPen.color = color;\n\t}\n\n\tpublic replay() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\n\t\t// Time of the first operation in stroke 0 is our starting time\n\t\tconst startTime = strokes[0]?.points[0]?.time;\n\t\tif (startTime === undefined) {\n\t\t\tthrow new Error(\"Couldn't get start time\");\n\t\t}\n\t\tfor (const stroke of strokes) {\n\t\t\tthis.animateStroke(stroke, 0, startTime);\n\t\t}\n\t}\n\n\tpublic clear() {\n\t\tthis.model.clear();\n\t\tthis.redraw();\n\t}\n\n\tpublic sizeCanvasBackingStore() {\n\t\tconst canvasBoundingClientRect = this.canvas.getBoundingClientRect();\n\t\t// Scale the canvas size to match the physical pixel to avoid blurriness\n\t\tconst scale = window.devicePixelRatio;\n\t\tthis.canvas.width = Math.floor(canvasBoundingClientRect.width * scale);\n\t\tthis.canvas.height = Math.floor(canvasBoundingClientRect.height * scale);\n\t\t// Scale the context to bring back coordinate system in CSS pixels\n\t\tthis.context.setTransform(1, 0, 0, 1, 0, 0);\n\t\tthis.context.scale(scale, scale);\n\n\t\tthis.redraw();\n\t}\n\n\tprivate handlePointerDown(evt: PointerEvent) {\n\t\t// We will accept pen down or mouse left down as the start of a stroke.\n\t\tif (evt.pointerType === \"pen\" || (evt.pointerType === \"mouse\" && evt.button === 0)) {\n\t\t\tconst strokeId = this.model.createStroke(this.currentPen).id;\n\t\t\tthis.localActiveStrokeMap.set(evt.pointerId, strokeId);\n\n\t\t\tthis.appendPointerEventToStroke(evt);\n\n\t\t\tevt.preventDefault();\n\t\t}\n\t}\n\n\tprivate handlePointerMove(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tconst evts = (evt as any)?.getCoalescedEvents() ?? ([evt] as PointerEvent[]);\n\t\t\tfor (const e of evts) {\n\t\t\t\tthis.appendPointerEventToStroke(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePointerUp(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tthis.appendPointerEventToStroke(evt);\n\t\t\tthis.localActiveStrokeMap.delete(evt.pointerId);\n\t\t}\n\t}\n\n\tprivate appendPointerEventToStroke(evt: PointerEvent) {\n\t\tconst strokeId = this.localActiveStrokeMap.get(evt.pointerId);\n\t\tif (strokeId === undefined) {\n\t\t\tthrow new Error(\"Unexpected pointer ID trying to append to stroke\");\n\t\t}\n\t\tconst inkPt = {\n\t\t\tx: evt.offsetX,\n\t\t\ty: evt.offsetY,\n\t\t\ttime: Date.now(),\n\t\t\tpressure: evt.pressure,\n\t\t};\n\t\tthis.model.appendPointToStroke(inkPt, strokeId);\n\t}\n\n\tprivate animateStroke(stroke: IInkStroke, operationIndex: number, startTime: number) {\n\t\tif (operationIndex >= stroke.points.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Draw the requested stroke\n\t\t// Non null asserting, this must exist because the operationIndex must be less than the length of stroke.points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst current = stroke.points[operationIndex]!;\n\t\t// Non null asserting, this must exist because its either the first index or operationIndex minus one which is less than the length of stroke.points\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst previous = stroke.points[Math.max(0, operationIndex - 1)]!;\n\t\tconst time =\n\t\t\toperationIndex === 0 ? current.time - startTime : current.time - previous.time;\n\n\t\tsetTimeout(() => {\n\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\tthis.animateStroke(stroke, operationIndex + 1, startTime);\n\t\t}, time);\n\t}\n\n\t/**\n\t * Clears the canvas\n\t */\n\tprivate clearCanvas() {\n\t\tthis.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t}\n\n\tprivate redraw() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\t\tfor (const stroke of strokes) {\n\t\t\t// Non null asserting since previous would not be used if stroke.points is empty\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tlet previous = stroke.points[0]!;\n\t\t\tfor (const current of stroke.points) {\n\t\t\t\t// For the down, current === previous === stroke.operations[0]\n\t\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\t\tprevious = current;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate drawStrokeSegment(pen: IPen, current: IInkPoint, previous: IInkPoint) {\n\t\t// TODO Consider save/restore context\n\t\t// TODO Consider half-pixel offset\n\t\tthis.context.fillStyle = `rgb(${pen.color.r}, ${pen.color.g}, ${pen.color.b})`;\n\t\tdrawShapes(this.context, previous, current, pen);\n\t}\n\n\tprivate handleStylus(operation: IStylusOperation) {\n\t\t// Render the dirty stroke\n\t\tconst dirtyStrokeId = operation.id;\n\t\tconst stroke = this.model.getStroke(dirtyStrokeId);\n\t\t// If this is the only point in the stroke, we'll use it for both the start and end of the segment\n\t\tconst prevPoint =\n\t\t\t// Non null asserting, this must exist its within the length of stroke.points\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tstroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)]!;\n\t\tthis.drawStrokeSegment(stroke.pen, prevPoint, operation.point);\n\t}\n}\n"]}
1
+ {"version":3,"file":"inkCanvas.js","sourceRoot":"","sources":["../src/inkCanvas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,MAAM;IACX;;OAEG;IACI,MAAM,CAAC,MAAM,CAAC,MAAc,EAAE,KAAa;QACjD,OAAO,IAAI,MAAM,CAChB,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EACvD,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,SAAS,CAAC,MAAc;QACrC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,YACQ,CAAS,EACT,CAAS;QADT,MAAC,GAAD,CAAC,CAAQ;QACT,MAAC,GAAD,CAAC,CAAQ;IACd,CAAC;IAEG,MAAM;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;CACD;AAED,SAAS,WAAW,CAAC,OAAiC,EAAE,MAAgB;IACvE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;IACR,CAAC;IAED,OAAO,CAAC,SAAS,EAAE,CAAC;IACpB,0BAA0B;IAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzC,gCAAgC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,2BAA2B;IAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,SAAS,EAAE,CAAC;IACpB,OAAO,CAAC,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,OAAiC,EAAE,MAAc,EAAE,MAAc;IACpF,OAAO,CAAC,SAAS,EAAE,CAAC;IACpB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,SAAS,EAAE,CAAC;IACpB,OAAO,CAAC,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAClB,OAAiC,EACjC,UAAqB,EACrB,QAAmB,EACnB,GAAS;IAET,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;IAE/B,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC;IACzD,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAErD,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,CAAC;QACnF,qDAAqD;QACrD,MAAM,uBAAuB,GAAG,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QAElF,MAAM,WAAW,GAAG;YACnB,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,YAAY,GAAG,uBAAuB,CAAC,CAAC;YAC1D,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,YAAY,GAAG,uBAAuB,CAAC,CAAC;SAC1D,CAAC;QACF,MAAM,WAAW,GAAG;YACnB,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,YAAY,GAAG,uBAAuB,CAAC,CAAC;YAC1D,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,YAAY,GAAG,uBAAuB,CAAC,CAAC;SAC1D,CAAC;QACF,MAAM,WAAW,GAAG;YACnB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,GAAG,uBAAuB,CAAC,CAAC;YACtD,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,GAAG,uBAAuB,CAAC,CAAC;SACtD,CAAC;QACF,MAAM,WAAW,GAAG;YACnB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,GAAG,uBAAuB,CAAC,CAAC;YACtD,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,UAAU,GAAG,uBAAuB,CAAC,CAAC;SACtD,CAAC;QAEF,WAAW,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,aAAa;IACb,8FAA8F;IAC9F,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,SAAS;IAKrB,YACkB,MAAyB,EACzB,KAAW;QADX,WAAM,GAAN,MAAM,CAAmB;QACzB,UAAK,GAAL,KAAK,CAAM;QALZ,yBAAoB,GAAwB,IAAI,GAAG,EAAE,CAAC;QAOtE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;QAEvC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE3E,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,IAAI,CAAC,UAAU,GAAG;YACjB,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;YACrC,SAAS,EAAE,CAAC;SACZ,CAAC;QAEF,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAC/B,CAAC;IAEM,WAAW,CAAC,KAAa;QAC/B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;IAC/B,CAAC;IAEM,MAAM;QACZ,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QAExC,+DAA+D;QAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAEM,KAAK;QACX,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,EAAE,CAAC;IACf,CAAC;IAEM,sBAAsB;QAC5B,MAAM,wBAAwB,GAAG,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;QACrE,wEAAwE;QACxE,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QACzE,kEAAkE;QAClE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAEjC,IAAI,CAAC,MAAM,EAAE,CAAC;IACf,CAAC;IAEO,iBAAiB,CAAC,GAAiB;QAC1C,uEAAuE;QACvE,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,WAAW,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAEvD,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC;YAErC,GAAG,CAAC,cAAc,EAAE,CAAC;QACtB,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,GAAiB;QAC1C,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,GAAI,GAAW,EAAE,kBAAkB,EAAE,IAAK,CAAC,GAAG,CAAoB,CAAC;YAC7E,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACtB,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC;YACpC,CAAC;QACF,CAAC;IACF,CAAC;IAEO,eAAe,CAAC,GAAiB;QACxC,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,CAAC;IACF,CAAC;IAEO,0BAA0B,CAAC,GAAiB;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,KAAK,GAAG;YACb,CAAC,EAAE,GAAG,CAAC,OAAO;YACd,CAAC,EAAE,GAAG,CAAC,OAAO;YACd,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACtB,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAEO,aAAa,CAAC,MAAkB,EAAE,cAAsB,EAAE,SAAiB;QAClF,IAAI,cAAc,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5C,OAAO;QACR,CAAC;QAED,4BAA4B;QAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,IAAI,GACT,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAEhF,UAAU,CAAC,GAAG,EAAE;YACf,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YACtD,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC,EAAE,IAAI,CAAC,CAAC;IACV,CAAC;IAED;;OAEG;IACK,WAAW;QAClB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAEO,MAAM;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAChC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACrC,8DAA8D;gBAC9D,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACtD,QAAQ,GAAG,OAAO,CAAC;YACpB,CAAC;QACF,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,GAAS,EAAE,OAAkB,EAAE,QAAmB;QAC3E,qCAAqC;QACrC,kCAAkC;QAClC,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC;QAC/E,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAEO,YAAY,CAAC,SAA2B;QAC/C,0BAA0B;QAC1B,MAAM,aAAa,GAAG,SAAS,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACnD,kGAAkG;QAClG,MAAM,SAAS,GACd,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IColor, IInk, IInkPoint, IInkStroke, IPen, IStylusOperation } from \"./interfaces.js\";\n\ninterface IPoint {\n\tx: number;\n\ty: number;\n}\n\nclass Vector {\n\t/**\n\t * Returns the vector resulting from rotating vector by angle\n\t */\n\tpublic static rotate(vector: Vector, angle: number): Vector {\n\t\treturn new Vector(\n\t\t\tvector.x * Math.cos(angle) - vector.y * Math.sin(angle),\n\t\t\tvector.x * Math.sin(angle) + vector.y * Math.cos(angle),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the normalized form of the given vector\n\t */\n\tpublic static normalize(vector: Vector): Vector {\n\t\tconst length = vector.length();\n\t\treturn new Vector(vector.x / length, vector.y / length);\n\t}\n\n\tconstructor(\n\t\tpublic x: number,\n\t\tpublic y: number,\n\t) {}\n\n\tpublic length(): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t}\n}\n\nfunction drawPolygon(context: CanvasRenderingContext2D, points: IPoint[]) {\n\tif (points.length === 0) {\n\t\treturn;\n\t}\n\n\tcontext.beginPath();\n\t// Move to the first point\n\tcontext.moveTo(points[0].x, points[0].y);\n\n\t// Draw the rest of the segments\n\tfor (let i = 1; i < points.length; i++) {\n\t\tcontext.lineTo(points[i].x, points[i].y);\n\t}\n\n\t// And then close the shape\n\tcontext.lineTo(points[0].x, points[0].y);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawCircle(context: CanvasRenderingContext2D, center: IPoint, radius: number) {\n\tcontext.beginPath();\n\tcontext.moveTo(center.x, center.y);\n\tcontext.arc(center.x, center.y, radius, 0, Math.PI * 2);\n\tcontext.closePath();\n\tcontext.fill();\n}\n\nfunction drawShapes(\n\tcontext: CanvasRenderingContext2D,\n\tstartPoint: IInkPoint,\n\tendPoint: IInkPoint,\n\tpen: IPen,\n): void {\n\tconst dirVector = new Vector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);\n\tconst len = dirVector.length();\n\n\tconst widthAtStart = pen.thickness * startPoint.pressure;\n\tconst widthAtEnd = pen.thickness * endPoint.pressure;\n\n\tif (len + Math.min(widthAtStart, widthAtEnd) > Math.max(widthAtStart, widthAtEnd)) {\n\t\t// Circles don't completely overlap, need a trapezoid\n\t\tconst normalizedLateralVector = new Vector(-dirVector.y / len, dirVector.x / len);\n\n\t\tconst trapezoidP0 = {\n\t\t\tx: startPoint.x + widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y + widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP1 = {\n\t\t\tx: startPoint.x - widthAtStart * normalizedLateralVector.x,\n\t\t\ty: startPoint.y - widthAtStart * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP2 = {\n\t\t\tx: endPoint.x - widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y - widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\t\tconst trapezoidP3 = {\n\t\t\tx: endPoint.x + widthAtEnd * normalizedLateralVector.x,\n\t\t\ty: endPoint.y + widthAtEnd * normalizedLateralVector.y,\n\t\t};\n\n\t\tdrawPolygon(context, [trapezoidP0, trapezoidP1, trapezoidP2, trapezoidP3]);\n\t}\n\n\t// End circle\n\t// TODO should only draw if not eclipsed by the previous circle, be careful about single-point\n\tdrawCircle(context, { x: endPoint.x, y: endPoint.y }, widthAtEnd);\n}\n\n/**\n * @internal\n */\nexport class InkCanvas {\n\tprivate readonly context: CanvasRenderingContext2D;\n\tprivate readonly localActiveStrokeMap: Map<number, string> = new Map();\n\tprivate readonly currentPen: IPen;\n\n\tconstructor(\n\t\tprivate readonly canvas: HTMLCanvasElement,\n\t\tprivate readonly model: IInk,\n\t) {\n\t\tthis.model.on(\"clear\", this.redraw.bind(this));\n\t\tthis.model.on(\"stylus\", this.handleStylus.bind(this));\n\t\tthis.canvas.style.touchAction = \"none\";\n\n\t\tthis.canvas.addEventListener(\"pointerdown\", this.handlePointerDown.bind(this));\n\t\tthis.canvas.addEventListener(\"pointermove\", this.handlePointerMove.bind(this));\n\t\tthis.canvas.addEventListener(\"pointerup\", this.handlePointerUp.bind(this));\n\n\t\tconst context = this.canvas.getContext(\"2d\");\n\t\tif (context === null) {\n\t\t\tthrow new Error(\"InkCanvas requires a canvas with 2d rendering context\");\n\t\t}\n\t\tthis.context = context;\n\n\t\tthis.currentPen = {\n\t\t\tcolor: { r: 0, g: 161, b: 241, a: 0 },\n\t\t\tthickness: 7,\n\t\t};\n\n\t\tthis.sizeCanvasBackingStore();\n\t}\n\n\tpublic setPenColor(color: IColor) {\n\t\tthis.currentPen.color = color;\n\t}\n\n\tpublic replay() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\n\t\t// Time of the first operation in stroke 0 is our starting time\n\t\tconst startTime = strokes[0].points[0].time;\n\t\tfor (const stroke of strokes) {\n\t\t\tthis.animateStroke(stroke, 0, startTime);\n\t\t}\n\t}\n\n\tpublic clear() {\n\t\tthis.model.clear();\n\t\tthis.redraw();\n\t}\n\n\tpublic sizeCanvasBackingStore() {\n\t\tconst canvasBoundingClientRect = this.canvas.getBoundingClientRect();\n\t\t// Scale the canvas size to match the physical pixel to avoid blurriness\n\t\tconst scale = window.devicePixelRatio;\n\t\tthis.canvas.width = Math.floor(canvasBoundingClientRect.width * scale);\n\t\tthis.canvas.height = Math.floor(canvasBoundingClientRect.height * scale);\n\t\t// Scale the context to bring back coordinate system in CSS pixels\n\t\tthis.context.setTransform(1, 0, 0, 1, 0, 0);\n\t\tthis.context.scale(scale, scale);\n\n\t\tthis.redraw();\n\t}\n\n\tprivate handlePointerDown(evt: PointerEvent) {\n\t\t// We will accept pen down or mouse left down as the start of a stroke.\n\t\tif (evt.pointerType === \"pen\" || (evt.pointerType === \"mouse\" && evt.button === 0)) {\n\t\t\tconst strokeId = this.model.createStroke(this.currentPen).id;\n\t\t\tthis.localActiveStrokeMap.set(evt.pointerId, strokeId);\n\n\t\t\tthis.appendPointerEventToStroke(evt);\n\n\t\t\tevt.preventDefault();\n\t\t}\n\t}\n\n\tprivate handlePointerMove(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tconst evts = (evt as any)?.getCoalescedEvents() ?? ([evt] as PointerEvent[]);\n\t\t\tfor (const e of evts) {\n\t\t\t\tthis.appendPointerEventToStroke(e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handlePointerUp(evt: PointerEvent) {\n\t\tif (this.localActiveStrokeMap.has(evt.pointerId)) {\n\t\t\tthis.appendPointerEventToStroke(evt);\n\t\t\tthis.localActiveStrokeMap.delete(evt.pointerId);\n\t\t}\n\t}\n\n\tprivate appendPointerEventToStroke(evt: PointerEvent) {\n\t\tconst strokeId = this.localActiveStrokeMap.get(evt.pointerId);\n\t\tif (strokeId === undefined) {\n\t\t\tthrow new Error(\"Unexpected pointer ID trying to append to stroke\");\n\t\t}\n\t\tconst inkPt = {\n\t\t\tx: evt.offsetX,\n\t\t\ty: evt.offsetY,\n\t\t\ttime: Date.now(),\n\t\t\tpressure: evt.pressure,\n\t\t};\n\t\tthis.model.appendPointToStroke(inkPt, strokeId);\n\t}\n\n\tprivate animateStroke(stroke: IInkStroke, operationIndex: number, startTime: number) {\n\t\tif (operationIndex >= stroke.points.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Draw the requested stroke\n\t\tconst current = stroke.points[operationIndex];\n\t\tconst previous = stroke.points[Math.max(0, operationIndex - 1)];\n\t\tconst time =\n\t\t\toperationIndex === 0 ? current.time - startTime : current.time - previous.time;\n\n\t\tsetTimeout(() => {\n\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\tthis.animateStroke(stroke, operationIndex + 1, startTime);\n\t\t}, time);\n\t}\n\n\t/**\n\t * Clears the canvas\n\t */\n\tprivate clearCanvas() {\n\t\tthis.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\t}\n\n\tprivate redraw() {\n\t\tthis.clearCanvas();\n\n\t\tconst strokes = this.model.getStrokes();\n\t\tfor (const stroke of strokes) {\n\t\t\tlet previous = stroke.points[0];\n\t\t\tfor (const current of stroke.points) {\n\t\t\t\t// For the down, current === previous === stroke.operations[0]\n\t\t\t\tthis.drawStrokeSegment(stroke.pen, current, previous);\n\t\t\t\tprevious = current;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate drawStrokeSegment(pen: IPen, current: IInkPoint, previous: IInkPoint) {\n\t\t// TODO Consider save/restore context\n\t\t// TODO Consider half-pixel offset\n\t\tthis.context.fillStyle = `rgb(${pen.color.r}, ${pen.color.g}, ${pen.color.b})`;\n\t\tdrawShapes(this.context, previous, current, pen);\n\t}\n\n\tprivate handleStylus(operation: IStylusOperation) {\n\t\t// Render the dirty stroke\n\t\tconst dirtyStrokeId = operation.id;\n\t\tconst stroke = this.model.getStroke(dirtyStrokeId);\n\t\t// If this is the only point in the stroke, we'll use it for both the start and end of the segment\n\t\tconst prevPoint =\n\t\t\tstroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];\n\t\tthis.drawStrokeSegment(stroke.pen, prevPoint, operation.point);\n\t}\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluid-experimental/ink";
8
- export declare const pkgVersion = "2.2.0";
8
+ export declare const pkgVersion = "2.3.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluid-experimental/ink";
8
- export const pkgVersion = "2.2.0";
8
+ export const pkgVersion = "2.3.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,yBAAyB,CAAC;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/ink\";\nexport const pkgVersion = \"2.2.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,yBAAyB,CAAC;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/ink\";\nexport const pkgVersion = \"2.3.0\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,OAAO;IACnB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAe;IAE9B;;OAEG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACS,QAAQ,CAAC,EAAE,gBAAgB;IAKvC;;OAEG;IACI,UAAU,IAAI,UAAU,EAAE;IAIjC;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMzC;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAK1C;;;OAGG;IACI,eAAe,IAAI,gBAAgB;CAM1C"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,OAAO;IACnB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAe;IAE9B;;OAEG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;gBACS,QAAQ,CAAC,EAAE,gBAAgB;IAKvC;;OAEG;IACI,UAAU,IAAI,UAAU,EAAE;IAIjC;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAIzC;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAK1C;;;OAGG;IACI,eAAe,IAAI,gBAAgB;CAM1C"}
package/lib/snapshot.js CHANGED
@@ -24,8 +24,6 @@ export class InkData {
24
24
  * {@inheritDoc IInk.getStroke}
25
25
  */
26
26
  getStroke(key) {
27
- // Non null asserting, it should be okay that a bad key results in an error being thrown
28
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
29
27
  return this.strokes[this.strokeIndex[key]];
30
28
  }
31
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH;;GAEG;AACH,MAAM,OAAO,OAAO;IAWnB;;;OAGG;IACH,YAAY,QAA2B;QACtC,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAW;QAC3B,wFAAwF;QACxF,oEAAoE;QACpE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAE,CAAE,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,MAAkB;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACI,eAAe;QACrB,OAAO;YACN,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IInkStroke } from \"./interfaces.js\";\n\n/**\n * Ink snapshot interface.\n */\nexport interface ISerializableInk {\n\t/**\n\t * Collection of ink strokes.\n\t */\n\tstrokes: IInkStroke[];\n\n\t/**\n\t * Stores a mapping from the provided key to its index in strokes. Since\n\t * ISerializableInk is serialized we need to use an index.\n\t */\n\tstrokeIndex: { [key: string]: number };\n}\n\n/**\n * Maintains a live record of the data that can be used for snapshotting.\n */\nexport class InkData {\n\t/**\n\t * {@inheritDoc ISerializableInk.strokes}\n\t */\n\tprivate strokes: IInkStroke[];\n\n\t/**\n\t * {@inheritDoc ISerializableInk.strokeIndex}\n\t */\n\tprivate strokeIndex: { [key: string]: number };\n\n\t/**\n\t * Construct a new InkData.\n\t * @param snapshot - Existing data to initialize with\n\t */\n\tconstructor(snapshot?: ISerializableInk) {\n\t\tthis.strokes = snapshot?.strokes ?? [];\n\t\tthis.strokeIndex = snapshot?.strokeIndex ?? {};\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStrokes}\n\t */\n\tpublic getStrokes(): IInkStroke[] {\n\t\treturn this.strokes;\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStroke}\n\t */\n\tpublic getStroke(key: string): IInkStroke {\n\t\t// Non null asserting, it should be okay that a bad key results in an error being thrown\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this.strokes[this.strokeIndex[key]!]!;\n\t}\n\n\t/**\n\t * Clear all stored data.\n\t */\n\tpublic clear(): void {\n\t\tthis.strokes = [];\n\t\tthis.strokeIndex = {};\n\t}\n\n\t/**\n\t * Add the given stroke to the stored data.\n\t * @param stroke - The stroke to add\n\t */\n\tpublic addStroke(stroke: IInkStroke): void {\n\t\tthis.strokes.push(stroke);\n\t\tthis.strokeIndex[stroke.id] = this.strokes.length - 1;\n\t}\n\n\t/**\n\t * Get a JSON-compatible representation of the stored data.\n\t * @returns The JSON-compatible object\n\t */\n\tpublic getSerializable(): ISerializableInk {\n\t\treturn {\n\t\t\tstrokes: this.strokes,\n\t\t\tstrokeIndex: this.strokeIndex,\n\t\t};\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH;;GAEG;AACH,MAAM,OAAO,OAAO;IAWnB;;;OAGG;IACH,YAAY,QAA2B;QACtC,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;IAChD,CAAC;IAED;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAW;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,MAAkB;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACI,eAAe;QACrB,OAAO;YACN,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IInkStroke } from \"./interfaces.js\";\n\n/**\n * Ink snapshot interface.\n */\nexport interface ISerializableInk {\n\t/**\n\t * Collection of ink strokes.\n\t */\n\tstrokes: IInkStroke[];\n\n\t/**\n\t * Stores a mapping from the provided key to its index in strokes. Since\n\t * ISerializableInk is serialized we need to use an index.\n\t */\n\tstrokeIndex: { [key: string]: number };\n}\n\n/**\n * Maintains a live record of the data that can be used for snapshotting.\n */\nexport class InkData {\n\t/**\n\t * {@inheritDoc ISerializableInk.strokes}\n\t */\n\tprivate strokes: IInkStroke[];\n\n\t/**\n\t * {@inheritDoc ISerializableInk.strokeIndex}\n\t */\n\tprivate strokeIndex: { [key: string]: number };\n\n\t/**\n\t * Construct a new InkData.\n\t * @param snapshot - Existing data to initialize with\n\t */\n\tconstructor(snapshot?: ISerializableInk) {\n\t\tthis.strokes = snapshot?.strokes ?? [];\n\t\tthis.strokeIndex = snapshot?.strokeIndex ?? {};\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStrokes}\n\t */\n\tpublic getStrokes(): IInkStroke[] {\n\t\treturn this.strokes;\n\t}\n\n\t/**\n\t * {@inheritDoc IInk.getStroke}\n\t */\n\tpublic getStroke(key: string): IInkStroke {\n\t\treturn this.strokes[this.strokeIndex[key]];\n\t}\n\n\t/**\n\t * Clear all stored data.\n\t */\n\tpublic clear(): void {\n\t\tthis.strokes = [];\n\t\tthis.strokeIndex = {};\n\t}\n\n\t/**\n\t * Add the given stroke to the stored data.\n\t * @param stroke - The stroke to add\n\t */\n\tpublic addStroke(stroke: IInkStroke): void {\n\t\tthis.strokes.push(stroke);\n\t\tthis.strokeIndex[stroke.id] = this.strokes.length - 1;\n\t}\n\n\t/**\n\t * Get a JSON-compatible representation of the stored data.\n\t * @returns The JSON-compatible object\n\t */\n\tpublic getSerializable(): ISerializableInk {\n\t\treturn {\n\t\t\tstrokes: this.strokes,\n\t\t\tstrokeIndex: this.strokeIndex,\n\t\t};\n\t}\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.45.1"
8
+ "packageVersion": "7.47.8"
9
9
  }
10
10
  ]
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/ink",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Ink DDS",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -47,25 +47,25 @@
47
47
  "temp-directory": "nyc/.nyc_output"
48
48
  },
49
49
  "dependencies": {
50
- "@fluidframework/core-interfaces": "~2.2.0",
51
- "@fluidframework/datastore-definitions": "~2.2.0",
52
- "@fluidframework/driver-definitions": "~2.2.0",
53
- "@fluidframework/driver-utils": "~2.2.0",
54
- "@fluidframework/runtime-definitions": "~2.2.0",
55
- "@fluidframework/shared-object-base": "~2.2.0",
50
+ "@fluidframework/core-interfaces": "~2.3.0",
51
+ "@fluidframework/datastore-definitions": "~2.3.0",
52
+ "@fluidframework/driver-definitions": "~2.3.0",
53
+ "@fluidframework/driver-utils": "~2.3.0",
54
+ "@fluidframework/runtime-definitions": "~2.3.0",
55
+ "@fluidframework/shared-object-base": "~2.3.0",
56
56
  "uuid": "^9.0.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@arethetypeswrong/cli": "^0.15.2",
60
60
  "@biomejs/biome": "~1.8.3",
61
- "@fluid-internal/mocha-test-setup": "~2.2.0",
62
- "@fluid-tools/build-cli": "^0.43.0",
61
+ "@fluid-internal/mocha-test-setup": "~2.3.0",
62
+ "@fluid-tools/build-cli": "^0.46.0",
63
63
  "@fluidframework/build-common": "^2.0.3",
64
- "@fluidframework/build-tools": "^0.43.0",
65
- "@fluidframework/container-definitions": "~2.2.0",
66
- "@fluidframework/eslint-config-fluid": "^5.3.0",
67
- "@fluidframework/test-runtime-utils": "~2.2.0",
68
- "@microsoft/api-extractor": "^7.45.1",
64
+ "@fluidframework/build-tools": "^0.46.0",
65
+ "@fluidframework/container-definitions": "~2.3.0",
66
+ "@fluidframework/eslint-config-fluid": "^5.4.0",
67
+ "@fluidframework/test-runtime-utils": "~2.3.0",
68
+ "@microsoft/api-extractor": "7.47.8",
69
69
  "@types/mocha": "^9.1.1",
70
70
  "@types/node": "^18.19.0",
71
71
  "@types/uuid": "^9.0.2",
@@ -85,7 +85,8 @@
85
85
  },
86
86
  "typeValidation": {
87
87
  "disabled": true,
88
- "broken": {}
88
+ "broken": {},
89
+ "entrypoint": "internal"
89
90
  },
90
91
  "scripts": {
91
92
  "build": "fluid-build . --task build",
package/src/inkCanvas.ts CHANGED
@@ -40,24 +40,21 @@ class Vector {
40
40
  }
41
41
 
42
42
  function drawPolygon(context: CanvasRenderingContext2D, points: IPoint[]) {
43
- const firstPoint = points[0];
44
- if (firstPoint === undefined) {
43
+ if (points.length === 0) {
45
44
  return;
46
45
  }
47
46
 
48
47
  context.beginPath();
49
48
  // Move to the first point
50
- context.moveTo(firstPoint.x, firstPoint.y);
49
+ context.moveTo(points[0].x, points[0].y);
51
50
 
52
51
  // Draw the rest of the segments
53
52
  for (let i = 1; i < points.length; i++) {
54
- // Non null asserting, this must exist because the we are iterating through the length of points
55
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
56
- context.lineTo(points[i]!.x, points[i]!.y);
53
+ context.lineTo(points[i].x, points[i].y);
57
54
  }
58
55
 
59
56
  // And then close the shape
60
- context.lineTo(firstPoint.x, firstPoint.y);
57
+ context.lineTo(points[0].x, points[0].y);
61
58
  context.closePath();
62
59
  context.fill();
63
60
  }
@@ -155,10 +152,7 @@ export class InkCanvas {
155
152
  const strokes = this.model.getStrokes();
156
153
 
157
154
  // Time of the first operation in stroke 0 is our starting time
158
- const startTime = strokes[0]?.points[0]?.time;
159
- if (startTime === undefined) {
160
- throw new Error("Couldn't get start time");
161
- }
155
+ const startTime = strokes[0].points[0].time;
162
156
  for (const stroke of strokes) {
163
157
  this.animateStroke(stroke, 0, startTime);
164
158
  }
@@ -230,12 +224,8 @@ export class InkCanvas {
230
224
  }
231
225
 
232
226
  // Draw the requested stroke
233
- // Non null asserting, this must exist because the operationIndex must be less than the length of stroke.points
234
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
235
- const current = stroke.points[operationIndex]!;
236
- // Non null asserting, this must exist because its either the first index or operationIndex minus one which is less than the length of stroke.points
237
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
238
- const previous = stroke.points[Math.max(0, operationIndex - 1)]!;
227
+ const current = stroke.points[operationIndex];
228
+ const previous = stroke.points[Math.max(0, operationIndex - 1)];
239
229
  const time =
240
230
  operationIndex === 0 ? current.time - startTime : current.time - previous.time;
241
231
 
@@ -257,9 +247,7 @@ export class InkCanvas {
257
247
 
258
248
  const strokes = this.model.getStrokes();
259
249
  for (const stroke of strokes) {
260
- // Non null asserting since previous would not be used if stroke.points is empty
261
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
262
- let previous = stroke.points[0]!;
250
+ let previous = stroke.points[0];
263
251
  for (const current of stroke.points) {
264
252
  // For the down, current === previous === stroke.operations[0]
265
253
  this.drawStrokeSegment(stroke.pen, current, previous);
@@ -281,9 +269,7 @@ export class InkCanvas {
281
269
  const stroke = this.model.getStroke(dirtyStrokeId);
282
270
  // If this is the only point in the stroke, we'll use it for both the start and end of the segment
283
271
  const prevPoint =
284
- // Non null asserting, this must exist its within the length of stroke.points
285
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
286
- stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)]!;
272
+ stroke.points[stroke.points.length - (stroke.points.length >= 2 ? 2 : 1)];
287
273
  this.drawStrokeSegment(stroke.pen, prevPoint, operation.point);
288
274
  }
289
275
  }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluid-experimental/ink";
9
- export const pkgVersion = "2.2.0";
9
+ export const pkgVersion = "2.3.0";
package/src/snapshot.ts CHANGED
@@ -55,9 +55,7 @@ export class InkData {
55
55
  * {@inheritDoc IInk.getStroke}
56
56
  */
57
57
  public getStroke(key: string): IInkStroke {
58
- // Non null asserting, it should be okay that a bad key results in an error being thrown
59
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
60
- return this.strokes[this.strokeIndex[key]!]!;
58
+ return this.strokes[this.strokeIndex[key]];
61
59
  }
62
60
 
63
61
  /**
package/tsconfig.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "compilerOptions": {
6
6
  "rootDir": "./src",
7
7
  "outDir": "./lib",
8
+ "noUncheckedIndexedAccess": false,
8
9
  "exactOptionalPropertyTypes": false,
9
10
  },
10
11
  }