From 7304217fd9559c35e34c16d5e4e025875adc3252 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 2 Apr 2019 20:59:10 -0400
Subject: put in a patch for inking up to canvas limit of 8192

---
 src/client/views/InkingStroke.tsx | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'src/client/views/InkingStroke.tsx')

diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 52111c711..44048f377 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -48,9 +48,10 @@ export class InkingStroke extends React.Component<StrokeProps> {
         let pathStyle = this.createStyle();
         let pathData = this.parseData(this.props.line);
 
+        let pointerEvents: any = InkingControl.Instance.selectedTool == InkTool.Eraser ? "all" : "none";
         return (
-            <path className={(this._strokeTool === InkTool.Highlighter) ? "highlight" : ""}
-                d={pathData} style={{ ...pathStyle, pointerEvents: "all" }} strokeLinejoin="round" strokeLinecap="round"
+            <path className={(this._strokeTool === InkTool.Highlighter) ? "highlight" : "normal"}
+                d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
                 onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
         )
     }
-- 
cgit v1.2.3-70-g09d2


From c406c8d123ce0aa9d63fb8a4dd90adfe83d2889d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 2 Apr 2019 23:38:59 -0400
Subject: fixed inking to have a moving 8192 window to maximize drawing area

---
 src/client/views/InkingCanvas.scss | 13 ++++-----
 src/client/views/InkingCanvas.tsx  | 54 ++++++++++++++++++++++++++------------
 src/client/views/InkingStroke.tsx  |  8 +++---
 3 files changed, 48 insertions(+), 27 deletions(-)

(limited to 'src/client/views/InkingStroke.tsx')

diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index 2128401b8..35c8ee942 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -2,18 +2,19 @@
 
 .inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect {
     position: absolute;
-    top: -4096px;
-    left: -4096px;
     width: 8192px;
     height: 8192px;
-    .inkingCanvas-children {
-      transform: translate(4096px, 4096px);
-      pointer-events: none;
-    }
     cursor:"crosshair";
     pointer-events: auto;
     
 }
+.inkingCanvas-canSelect, 
+.inkingCanvas-noSelect    {
+    top:-50000px;
+    left:-50000px;
+    width: 100000px;
+    height: 100000px;
+}
 .inkingCanvas-noSelect  {
     pointer-events: none;
     cursor: "arrow";
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index fcf6db390..cad4b74b1 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -1,4 +1,4 @@
-import { action, computed, trace } from "mobx";
+import { action, computed, trace, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../fields/Document";
 import { FieldWaiting } from "../../fields/Field";
@@ -14,26 +14,40 @@ import React = require("react");
 interface InkCanvasProps {
     getScreenTransform: () => Transform;
     Document: Document;
+    children: () => JSX.Element[];
 }
 
 @observer
 export class InkingCanvas extends React.Component<InkCanvasProps> {
-    static InkOffset: number = 4096;
+    maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome
+    @observable inkMidX: number = 0;
+    @observable inkMidY: number = 0;
     private _currentStrokeId: string = "";
     public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean {
-        return stroke.pathData.reduce((inside, val) => inside ||
-            (selRect.left < val.x - InkingCanvas.InkOffset && selRect.left + selRect.width > val.x - InkingCanvas.InkOffset &&
-                selRect.top < val.y - InkingCanvas.InkOffset && selRect.top + selRect.height > val.y - InkingCanvas.InkOffset)
+        return stroke.pathData.reduce((inside: boolean, val) => inside ||
+            (selRect.left < val.x && selRect.left + selRect.width > val.x &&
+                selRect.top < val.y && selRect.top + selRect.height > val.y)
             , false);
     }
 
+    componentDidMount() {
+        this.props.Document.GetTAsync(KeyStore.Ink, InkField, ink => runInAction(() => {
+            if (ink) {
+                let bounds = Array.from(ink.Data).reduce(([mix, max, miy, may], [id, strokeData]) =>
+                    strokeData.pathData.reduce(([mix, max, miy, may], p) =>
+                        [Math.min(mix, p.x), Math.max(max, p.x), Math.min(miy, p.y), Math.max(may, p.y)],
+                        [mix, max, miy, may]),
+                    [Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_VALUE, Number.MIN_VALUE]);
+                this.inkMidX = (bounds[0] + bounds[1]) / 2;
+                this.inkMidY = (bounds[2] + bounds[3]) / 2;
+            }
+        }));
+    }
+
     @computed
     get inkData(): StrokeMap {
         let map = this.props.Document.GetT(KeyStore.Ink, InkField);
-        if (!map || map === FieldWaiting) {
-            return new Map;
-        }
-        return new Map(map.Data);
+        return !map || map === FieldWaiting ? new Map : new Map(map.Data);
     }
 
     set inkData(value: StrokeMap) {
@@ -63,9 +77,15 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         }
     }
 
+    @action
     onPointerUp = (e: PointerEvent): void => {
         document.removeEventListener("pointermove", this.onPointerMove, true);
         document.removeEventListener("pointerup", this.onPointerUp, true);
+        let coord = this.relativeCoordinatesForEvent(e.clientX, e.clientY);
+        if (Math.abs(coord.x - this.inkMidX) > 500 || Math.abs(coord.y - this.inkMidY) > 500) {
+            this.inkMidX = coord.x;
+            this.inkMidY = coord.y;
+        }
         e.stopPropagation();
         e.preventDefault();
     }
@@ -87,8 +107,6 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => {
         let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey);
-        x += InkingCanvas.InkOffset;
-        y += InkingCanvas.InkOffset;
         return { x, y };
     }
 
@@ -101,30 +119,32 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     @computed
     get drawnPaths() {
-        // parse data from server
         let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1)
         let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
             if (strokeData.page == -1 || strokeData.page == curPage)
                 paths.push(<InkingStroke key={id} id={id} line={strokeData.pathData}
+                    offsetX={this.maxCanvasDim - this.inkMidX}
+                    offsetY={this.maxCanvasDim - this.inkMidY}
                     color={strokeData.color} width={strokeData.width}
                     tool={strokeData.tool} deleteCallback={this.removeLine} />)
             return paths;
         }, [] as JSX.Element[]);
-        return [<svg className={`inkingCanvas-paths-markers`} key="Markers"  >
+        return [<svg className={`inkingCanvas-paths-markers`} key="Markers"
+            style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
             {paths.filter(path => path.props.tool == InkTool.Highlighter)}
         </svg>,
-        <svg className={`inkingCanvas-paths-ink`} key="Pens" >
+        <svg className={`inkingCanvas-paths-ink`} key="Pens"
+            style={{ left: `-${this.inkMidX - this.maxCanvasDim}px`, top: `-${this.inkMidY - this.maxCanvasDim}px` }}>
             {paths.filter(path => path.props.tool != InkTool.Highlighter)}
         </svg>];
     }
 
     render() {
         let svgCanvasStyle = InkingControl.Instance.selectedTool != InkTool.None ? "canSelect" : "noSelect";
-
         return (
             <div className="inkingCanvas" >
-                <svg className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
-                {(this.props.children as any)() /* bcz: is there a better way to know that children is a function? */}
+                <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
+                {this.props.children()}
                 {this.drawnPaths}
             </div >
         )
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 44048f377..615f8af7e 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -6,6 +6,8 @@ import React = require("react");
 
 
 interface StrokeProps {
+    offsetX: number;
+    offsetY: number;
     id: string;
     line: Array<{ x: number, y: number }>;
     color: string;
@@ -28,7 +30,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
     }
 
     parseData = (line: Array<{ x: number, y: number }>): string => {
-        return !line.length ? "" : "M " + line.map(p => p.x + " " + p.y).join(" L ");
+        return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ");
     }
 
     createStyle() {
@@ -43,15 +45,13 @@ export class InkingStroke extends React.Component<StrokeProps> {
         }
     }
 
-
     render() {
         let pathStyle = this.createStyle();
         let pathData = this.parseData(this.props.line);
 
         let pointerEvents: any = InkingControl.Instance.selectedTool == InkTool.Eraser ? "all" : "none";
         return (
-            <path className={(this._strokeTool === InkTool.Highlighter) ? "highlight" : "normal"}
-                d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
+            <path d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
                 onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
         )
     }
-- 
cgit v1.2.3-70-g09d2

