190 lines
6.6 KiB
JavaScript
190 lines
6.6 KiB
JavaScript
/*
|
|
* Copyright (C) 2018 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
WI.RecordingState = class RecordingState
|
|
{
|
|
constructor(data, {source} = {})
|
|
{
|
|
this._data = data;
|
|
this._source = source || null;
|
|
}
|
|
|
|
// Static
|
|
|
|
static fromContext(type, context, options = {})
|
|
{
|
|
if (type !== WI.Recording.Type.Canvas2D)
|
|
return null;
|
|
|
|
let matrix = context.getTransform();
|
|
|
|
let data = {};
|
|
|
|
data.direction = context.direction;
|
|
data.fillStyle = context.fillStyle;
|
|
data.font = context.font;
|
|
data.globalAlpha = context.globalAlpha;
|
|
data.globalCompositeOperation = context.globalCompositeOperation;
|
|
data.imageSmoothingEnabled = context.imageSmoothingEnabled;
|
|
data.imageSmoothingQuality = context.imageSmoothingQuality;
|
|
data.lineCap = context.lineCap;
|
|
data.lineDash = context.getLineDash();
|
|
data.lineDashOffset = context.lineDashOffset;
|
|
data.lineJoin = context.lineJoin;
|
|
data.lineWidth = context.lineWidth;
|
|
data.miterLimit = context.miterLimit;
|
|
data.shadowBlur = context.shadowBlur;
|
|
data.shadowColor = context.shadowColor;
|
|
data.shadowOffsetX = context.shadowOffsetX;
|
|
data.shadowOffsetY = context.shadowOffsetY;
|
|
data.strokeStyle = context.strokeStyle;
|
|
data.textAlign = context.textAlign;
|
|
data.textBaseline = context.textBaseline;
|
|
data.transform = [matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f];
|
|
data.webkitImageSmoothingEnabled = context.webkitImageSmoothingEnabled;
|
|
data.webkitLineDash = context.webkitLineDash;
|
|
data.webkitLineDashOffset = context.webkitLineDashOffset;
|
|
|
|
data.currentX = context.currentX;
|
|
data.currentY = context.currentY;
|
|
data.setPath = [context.getPath()];
|
|
|
|
return new WI.RecordingState(data, options);
|
|
}
|
|
|
|
static async swizzleInitialState(recording, initialState)
|
|
{
|
|
if (recording.type === WI.Recording.Type.Canvas2D) {
|
|
let swizzledState = {};
|
|
|
|
for (let [name, value] of Object.entries(initialState)) {
|
|
// COMPATIBILITY (iOS 12.0): Recording.InitialState.states did not exist yet
|
|
let nameIndex = parseInt(name);
|
|
if (!isNaN(nameIndex))
|
|
name = await recording.swizzle(nameIndex, WI.Recording.Swizzle.String);
|
|
|
|
switch (name) {
|
|
case "setTransform":
|
|
value = [await recording.swizzle(value, WI.Recording.Swizzle.DOMMatrix)];
|
|
break;
|
|
|
|
case "fillStyle":
|
|
case "strokeStyle":
|
|
var [gradient, pattern, string] = await Promise.all([
|
|
recording.swizzle(value, WI.Recording.Swizzle.CanvasGradient),
|
|
recording.swizzle(value, WI.Recording.Swizzle.CanvasPattern),
|
|
recording.swizzle(value, WI.Recording.Swizzle.String),
|
|
]);
|
|
if (gradient && !pattern)
|
|
value = gradient;
|
|
else if (pattern && !gradient)
|
|
value = pattern;
|
|
else
|
|
value = string;
|
|
break;
|
|
|
|
case "direction":
|
|
case "font":
|
|
case "globalCompositeOperation":
|
|
case "imageSmoothingQuality":
|
|
case "lineCap":
|
|
case "lineJoin":
|
|
case "shadowColor":
|
|
case "textAlign":
|
|
case "textBaseline":
|
|
value = await recording.swizzle(value, WI.Recording.Swizzle.String);
|
|
break;
|
|
|
|
case "globalAlpha":
|
|
case "lineWidth":
|
|
case "miterLimit":
|
|
case "shadowOffsetX":
|
|
case "shadowOffsetY":
|
|
case "shadowBlur":
|
|
case "lineDashOffset":
|
|
value = await recording.swizzle(value, WI.Recording.Swizzle.Number);
|
|
break;
|
|
|
|
case "setPath":
|
|
value = [await recording.swizzle(value[0], WI.Recording.Swizzle.Path2D)];
|
|
break;
|
|
}
|
|
|
|
if (value === undefined || (Array.isArray(value) && value.includes(undefined)))
|
|
continue;
|
|
|
|
swizzledState[name] = value;
|
|
}
|
|
|
|
return new WI.RecordingState(swizzledState);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// Public
|
|
|
|
get source() { return this._source; }
|
|
|
|
has(name)
|
|
{
|
|
return name in this._data;
|
|
}
|
|
|
|
get(name)
|
|
{
|
|
return this._data[name];
|
|
}
|
|
|
|
apply(type, context)
|
|
{
|
|
for (let [name, value] of this) {
|
|
if (!(name in context))
|
|
continue;
|
|
|
|
// Skip internal state used for path debugging.
|
|
if (name === "currentX" || name === "currentY")
|
|
continue;
|
|
|
|
try {
|
|
if (WI.RecordingAction.isFunctionForType(type, name))
|
|
context[name](...value);
|
|
else
|
|
context[name] = value;
|
|
} catch { }
|
|
}
|
|
}
|
|
|
|
toJSON()
|
|
{
|
|
return this._data;
|
|
}
|
|
|
|
[Symbol.iterator]()
|
|
{
|
|
return Object.entries(this._data)[Symbol.iterator]();
|
|
}
|
|
};
|