Web Inspector: Canvas: show warning when path moves offscreen
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 Oct 2018 00:10:53 +0000 (00:10 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 Oct 2018 00:10:53 +0000 (00:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191016

Reviewed by Joseph Pecoraro.

* UserInterface/Models/RecordingAction.js:
(WI.RecordingAction):
(WI.RecordingAction.deriveCurrentState):
(WI.RecordingAction.prototype.get isVisual):
(WI.RecordingAction.prototype.get warning): Added.
(WI.RecordingAction.prototype.process.checkInvalidCurrentAxisPoint): Added.
(WI.RecordingAction.prototype.process):
(WI.RecordingAction.prototype.get hasVisibleEffect): Deleted.
Replace `hasVisibleEffect` with a more general `warning` value, so that it can be used for
more types of warnings.

* UserInterface/Views/RecordingActionTreeElement.js:
(WI.RecordingActionTreeElement.prototype.onattach):
* UserInterface/Views/RecordingActionTreeElement.css:
(.item.action.visual.warning:not(.invalid) > .status > .warning): Added.
(.item.action.visual.no-visible-effect:not(.invalid) > .status > .warning): Deleted.

* Localizations/en.lproj/localizedStrings.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237574 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Models/RecordingAction.js
Source/WebInspectorUI/UserInterface/Views/RecordingActionTreeElement.css
Source/WebInspectorUI/UserInterface/Views/RecordingActionTreeElement.js

index 1f0de46..e377075 100644 (file)
@@ -1,5 +1,31 @@
 2018-10-29  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Canvas: show warning when path moves offscreen
+        https://bugs.webkit.org/show_bug.cgi?id=191016
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/Models/RecordingAction.js:
+        (WI.RecordingAction):
+        (WI.RecordingAction.deriveCurrentState):
+        (WI.RecordingAction.prototype.get isVisual):
+        (WI.RecordingAction.prototype.get warning): Added.
+        (WI.RecordingAction.prototype.process.checkInvalidCurrentAxisPoint): Added.
+        (WI.RecordingAction.prototype.process):
+        (WI.RecordingAction.prototype.get hasVisibleEffect): Deleted.
+        Replace `hasVisibleEffect` with a more general `warning` value, so that it can be used for
+        more types of warnings.
+
+        * UserInterface/Views/RecordingActionTreeElement.js:
+        (WI.RecordingActionTreeElement.prototype.onattach):
+        * UserInterface/Views/RecordingActionTreeElement.css:
+        (.item.action.visual.warning:not(.invalid) > .status > .warning): Added.
+        (.item.action.visual.no-visible-effect:not(.invalid) > .status > .warning): Deleted.
+
+        * Localizations/en.lproj/localizedStrings.js:
+
+2018-10-29  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: refactor code for getting properties via WI.RemoteObject
         https://bugs.webkit.org/show_bug.cgi?id=190989
 
index 506b853..359cfdc 100644 (file)
@@ -851,6 +851,7 @@ localizedStrings["Text Node"] = "Text Node";
 localizedStrings["The page's content has changed"] = "The page's content has changed";
 localizedStrings["The ā€œ%sā€\ntable is empty."] = "The ā€œ%sā€\ntable is empty.";
 localizedStrings["This action causes no visual change"] = "This action causes no visual change";
+localizedStrings["This action moves the path outside the visible area"] = "This action moves the path outside the visible area";
 localizedStrings["This object is a root"] = "This object is a root";
 localizedStrings["This object is referenced by internal objects"] = "This object is referenced by internal objects";
 localizedStrings["This text resource could benefit from compression"] = "This text resource could benefit from compression";
index f5fca9a..d186f3f 100644 (file)
@@ -44,11 +44,11 @@ WI.RecordingAction = class RecordingAction extends WI.Object
         this._isFunction = false;
         this._isGetter = false;
         this._isVisual = false;
-        this._hasVisibleEffect = undefined;
 
         this._states = [];
         this._stateModifiers = new Set;
 
+        this._warning = null;
         this._swizzled = false;
         this._processed = false;
     }
@@ -135,34 +135,37 @@ WI.RecordingAction = class RecordingAction extends WI.Object
         if (type === WI.Recording.Type.Canvas2D) {
             let matrix = context.getTransform();
 
-            let state = {
-                currentX: context.currentX,
-                currentY: context.currentY,
-                direction: context.direction,
-                fillStyle: context.fillStyle,
-                font: context.font,
-                globalAlpha: context.globalAlpha,
-                globalCompositeOperation: context.globalCompositeOperation,
-                imageSmoothingEnabled: context.imageSmoothingEnabled,
-                imageSmoothingQuality: context.imageSmoothingQuality,
-                lineCap: context.lineCap,
-                lineDash: context.getLineDash(),
-                lineDashOffset: context.lineDashOffset,
-                lineJoin: context.lineJoin,
-                lineWidth: context.lineWidth,
-                miterLimit: context.miterLimit,
-                shadowBlur: context.shadowBlur,
-                shadowColor: context.shadowColor,
-                shadowOffsetX: context.shadowOffsetX,
-                shadowOffsetY: context.shadowOffsetY,
-                strokeStyle: context.strokeStyle,
-                textAlign: context.textAlign,
-                textBaseline: context.textBaseline,
-                transform: [matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f],
-                webkitImageSmoothingEnabled: context.webkitImageSmoothingEnabled,
-                webkitLineDash: context.webkitLineDash,
-                webkitLineDashOffset: context.webkitLineDashOffset,
-            };
+            let state = {};
+
+            if (WI.ImageUtilities.supportsCanvasPathDebugging()) {
+                state.currentX = context.currentX;
+                state.currentY = context.currentY;
+            }
+
+            state.direction = context.direction;
+            state.fillStyle = context.fillStyle;
+            state.font = context.font;
+            state.globalAlpha = context.globalAlpha;
+            state.globalCompositeOperation = context.globalCompositeOperation;
+            state.imageSmoothingEnabled = context.imageSmoothingEnabled;
+            state.imageSmoothingQuality = context.imageSmoothingQuality;
+            state.lineCap = context.lineCap;
+            state.lineDash = context.getLineDash();
+            state.lineDashOffset = context.lineDashOffset;
+            state.lineJoin = context.lineJoin;
+            state.lineWidth = context.lineWidth;
+            state.miterLimit = context.miterLimit;
+            state.shadowBlur = context.shadowBlur;
+            state.shadowColor = context.shadowColor;
+            state.shadowOffsetX = context.shadowOffsetX;
+            state.shadowOffsetY = context.shadowOffsetY;
+            state.strokeStyle = context.strokeStyle;
+            state.textAlign = context.textAlign;
+            state.textBaseline = context.textBaseline;
+            state.transform = [matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f];
+            state.webkitImageSmoothingEnabled = context.webkitImageSmoothingEnabled;
+            state.webkitLineDash = context.webkitLineDash;
+            state.webkitLineDashOffset = context.webkitLineDashOffset;
 
             if (WI.ImageUtilities.supportsCanvasPathDebugging())
                 state.setPath = [context.getPath()];
@@ -195,9 +198,9 @@ WI.RecordingAction = class RecordingAction extends WI.Object
     get isFunction() { return this._isFunction; }
     get isGetter() { return this._isGetter; }
     get isVisual() { return this._isVisual; }
-    get hasVisibleEffect() { return this._hasVisibleEffect; }
     get states() { return this._states; }
     get stateModifiers() { return this._stateModifiers; }
+    get warning() { return this._warning; }
 
     get ready()
     {
@@ -215,7 +218,8 @@ WI.RecordingAction = class RecordingAction extends WI.Object
             // We add each RecordingAction to the list of visualActionIndexes after it is processed.
             if (this._valid && this._isVisual) {
                 let contentBefore = recording.visualActionIndexes.length ? recording.actions[recording.visualActionIndexes.lastValue].snapshot : recording.initialState.content;
-                this._hasVisibleEffect = this._snapshot !== contentBefore;
+                if (this._snapshot === contentBefore)
+                    this._warning = WI.UIString("This action causes no visual change");
             }
             return;
         }
@@ -244,8 +248,11 @@ WI.RecordingAction = class RecordingAction extends WI.Object
 
         this.apply(context);
 
-        if (shouldCheckHasVisualEffect)
-            this._hasVisibleEffect = !Array.shallowEqual(contentBefore, getContent());
+        if (shouldCheckHasVisualEffect) {
+            let contentAfter = getContent();
+            if (Array.shallowEqual(contentBefore, contentAfter))
+                this._warning = WI.UIString("This action causes no visual change");
+        }
 
         if (recording.type === WI.Recording.Type.Canvas2D) {
             let currentState = WI.RecordingAction.deriveCurrentState(recording.type, context);
@@ -259,13 +266,25 @@ WI.RecordingAction = class RecordingAction extends WI.Object
             this._states = states.slice();
             this._states.push(currentState);
 
+            let lastState = null;
             if (lastAction) {
-                let lastState = lastAction.states.lastValue;
+                lastState = lastAction.states.lastValue;
                 for (let key in currentState) {
                     if (!(key in lastState) || (currentState[key] !== lastState[key] && !Object.shallowEqual(currentState[key], lastState[key])))
                         this._stateModifiers.add(key);
                 }
             }
+
+            if (WI.ImageUtilities.supportsCanvasPathDebugging()) {
+                let currentX = currentState.currentX;
+                let invalidX = (currentX < 0 || currentX >= context.canvas.width) && (!lastState || currentX !== lastState.currentX);
+
+                let currentY = currentState.currentY;
+                let invalidY = (currentY < 0 || currentY >= context.canvas.height) && (!lastState || currentY !== lastState.currentY);
+
+                if (invalidX || invalidY)
+                    this._warning = WI.UIString("This action moves the path outside the visible area");
+            }
         }
     }
 
index a04fbf8..a1ab570 100644 (file)
@@ -220,7 +220,7 @@ body[dir=rtl] .tree-outline:not(.hide-disclosure-buttons) .item.action:not(.init
     content: url(../Images/Error.svg);
 }
 
-.item.action.visual.no-visible-effect:not(.invalid) > .status > .warning {
+.item.action.warning:not(.invalid) > .status > .warning {
     width: 12px;
     height: 12px;
     margin-top: 2px;
index 88ba84a..5c8c4d7 100644 (file)
@@ -407,11 +407,9 @@ WI.RecordingActionTreeElement = class RecordingActionTreeElement extends WI.Gene
 
         this.element.dataset.index = this._index.toLocaleString();
 
-        if (this.representedObject.valid && this.representedObject.isVisual && !this.representedObject.hasVisibleEffect) {
-            this.addClassName("no-visible-effect");
-
-            const title = WI.UIString("This action causes no visual change");
-            this.status = WI.ImageUtilities.useSVGSymbol("Images/Warning.svg", "warning", title);
+        if (this.representedObject.valid && this.representedObject.warning) {
+            this.addClassName("warning");
+            this.status = WI.ImageUtilities.useSVGSymbol("Images/Warning.svg", "warning", this.representedObject.warning);
         }
     }