240 lines
7.6 KiB
JavaScript
240 lines
7.6 KiB
JavaScript
import {
|
|
createTypedArray,
|
|
} from '../../utils/helpers/arrays';
|
|
import Matrix from '../../3rd_party/transformation-matrix';
|
|
|
|
function CanvasContext() {
|
|
this.opacity = -1;
|
|
this.transform = createTypedArray('float32', 16);
|
|
this.fillStyle = '';
|
|
this.strokeStyle = '';
|
|
this.lineWidth = '';
|
|
this.lineCap = '';
|
|
this.lineJoin = '';
|
|
this.miterLimit = '';
|
|
this.id = Math.random();
|
|
}
|
|
|
|
function CVContextData() {
|
|
this.stack = [];
|
|
this.cArrPos = 0;
|
|
this.cTr = new Matrix();
|
|
var i;
|
|
var len = 15;
|
|
for (i = 0; i < len; i += 1) {
|
|
var canvasContext = new CanvasContext();
|
|
this.stack[i] = canvasContext;
|
|
}
|
|
this._length = len;
|
|
this.nativeContext = null;
|
|
this.transformMat = new Matrix();
|
|
this.currentOpacity = 1;
|
|
//
|
|
this.currentFillStyle = '';
|
|
this.appliedFillStyle = '';
|
|
//
|
|
this.currentStrokeStyle = '';
|
|
this.appliedStrokeStyle = '';
|
|
//
|
|
this.currentLineWidth = '';
|
|
this.appliedLineWidth = '';
|
|
//
|
|
this.currentLineCap = '';
|
|
this.appliedLineCap = '';
|
|
//
|
|
this.currentLineJoin = '';
|
|
this.appliedLineJoin = '';
|
|
//
|
|
this.appliedMiterLimit = '';
|
|
this.currentMiterLimit = '';
|
|
}
|
|
|
|
CVContextData.prototype.duplicate = function () {
|
|
var newLength = this._length * 2;
|
|
var i = 0;
|
|
for (i = this._length; i < newLength; i += 1) {
|
|
this.stack[i] = new CanvasContext();
|
|
}
|
|
this._length = newLength;
|
|
};
|
|
|
|
CVContextData.prototype.reset = function () {
|
|
this.cArrPos = 0;
|
|
this.cTr.reset();
|
|
this.stack[this.cArrPos].opacity = 1;
|
|
};
|
|
|
|
CVContextData.prototype.restore = function (forceRestore) {
|
|
this.cArrPos -= 1;
|
|
var currentContext = this.stack[this.cArrPos];
|
|
var transform = currentContext.transform;
|
|
var i;
|
|
var arr = this.cTr.props;
|
|
for (i = 0; i < 16; i += 1) {
|
|
arr[i] = transform[i];
|
|
}
|
|
if (forceRestore) {
|
|
this.nativeContext.restore();
|
|
var prevStack = this.stack[this.cArrPos + 1];
|
|
this.appliedFillStyle = prevStack.fillStyle;
|
|
this.appliedStrokeStyle = prevStack.strokeStyle;
|
|
this.appliedLineWidth = prevStack.lineWidth;
|
|
this.appliedLineCap = prevStack.lineCap;
|
|
this.appliedLineJoin = prevStack.lineJoin;
|
|
this.appliedMiterLimit = prevStack.miterLimit;
|
|
}
|
|
this.nativeContext.setTransform(transform[0], transform[1], transform[4], transform[5], transform[12], transform[13]);
|
|
if (forceRestore || (currentContext.opacity !== -1 && this.currentOpacity !== currentContext.opacity)) {
|
|
this.nativeContext.globalAlpha = currentContext.opacity;
|
|
this.currentOpacity = currentContext.opacity;
|
|
}
|
|
this.currentFillStyle = currentContext.fillStyle;
|
|
this.currentStrokeStyle = currentContext.strokeStyle;
|
|
this.currentLineWidth = currentContext.lineWidth;
|
|
this.currentLineCap = currentContext.lineCap;
|
|
this.currentLineJoin = currentContext.lineJoin;
|
|
this.currentMiterLimit = currentContext.miterLimit;
|
|
};
|
|
|
|
CVContextData.prototype.save = function (saveOnNativeFlag) {
|
|
if (saveOnNativeFlag) {
|
|
this.nativeContext.save();
|
|
}
|
|
var props = this.cTr.props;
|
|
if (this._length <= this.cArrPos) {
|
|
this.duplicate();
|
|
}
|
|
|
|
var currentStack = this.stack[this.cArrPos];
|
|
var i;
|
|
for (i = 0; i < 16; i += 1) {
|
|
currentStack.transform[i] = props[i];
|
|
}
|
|
this.cArrPos += 1;
|
|
var newStack = this.stack[this.cArrPos];
|
|
newStack.opacity = currentStack.opacity;
|
|
newStack.fillStyle = currentStack.fillStyle;
|
|
newStack.strokeStyle = currentStack.strokeStyle;
|
|
newStack.lineWidth = currentStack.lineWidth;
|
|
newStack.lineCap = currentStack.lineCap;
|
|
newStack.lineJoin = currentStack.lineJoin;
|
|
newStack.miterLimit = currentStack.miterLimit;
|
|
};
|
|
|
|
CVContextData.prototype.setOpacity = function (value) {
|
|
this.stack[this.cArrPos].opacity = value;
|
|
};
|
|
|
|
CVContextData.prototype.setContext = function (value) {
|
|
this.nativeContext = value;
|
|
};
|
|
|
|
CVContextData.prototype.fillStyle = function (value) {
|
|
if (this.stack[this.cArrPos].fillStyle !== value) {
|
|
this.currentFillStyle = value;
|
|
this.stack[this.cArrPos].fillStyle = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.strokeStyle = function (value) {
|
|
if (this.stack[this.cArrPos].strokeStyle !== value) {
|
|
this.currentStrokeStyle = value;
|
|
this.stack[this.cArrPos].strokeStyle = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.lineWidth = function (value) {
|
|
if (this.stack[this.cArrPos].lineWidth !== value) {
|
|
this.currentLineWidth = value;
|
|
this.stack[this.cArrPos].lineWidth = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.lineCap = function (value) {
|
|
if (this.stack[this.cArrPos].lineCap !== value) {
|
|
this.currentLineCap = value;
|
|
this.stack[this.cArrPos].lineCap = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.lineJoin = function (value) {
|
|
if (this.stack[this.cArrPos].lineJoin !== value) {
|
|
this.currentLineJoin = value;
|
|
this.stack[this.cArrPos].lineJoin = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.miterLimit = function (value) {
|
|
if (this.stack[this.cArrPos].miterLimit !== value) {
|
|
this.currentMiterLimit = value;
|
|
this.stack[this.cArrPos].miterLimit = value;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.transform = function (props) {
|
|
this.transformMat.cloneFromProps(props);
|
|
// Taking the last transform value from the stored stack of transforms
|
|
var currentTransform = this.cTr;
|
|
// Applying the last transform value after the new transform to respect the order of transformations
|
|
this.transformMat.multiply(currentTransform);
|
|
// Storing the new transformed value in the stored transform
|
|
currentTransform.cloneFromProps(this.transformMat.props);
|
|
var trProps = currentTransform.props;
|
|
// Applying the new transform to the canvas
|
|
this.nativeContext.setTransform(trProps[0], trProps[1], trProps[4], trProps[5], trProps[12], trProps[13]);
|
|
};
|
|
|
|
CVContextData.prototype.opacity = function (op) {
|
|
var currentOpacity = this.stack[this.cArrPos].opacity;
|
|
currentOpacity *= op < 0 ? 0 : op;
|
|
if (this.stack[this.cArrPos].opacity !== currentOpacity) {
|
|
if (this.currentOpacity !== op) {
|
|
this.nativeContext.globalAlpha = op;
|
|
this.currentOpacity = op;
|
|
}
|
|
this.stack[this.cArrPos].opacity = currentOpacity;
|
|
}
|
|
};
|
|
|
|
CVContextData.prototype.fill = function (rule) {
|
|
if (this.appliedFillStyle !== this.currentFillStyle) {
|
|
this.appliedFillStyle = this.currentFillStyle;
|
|
this.nativeContext.fillStyle = this.appliedFillStyle;
|
|
}
|
|
this.nativeContext.fill(rule);
|
|
};
|
|
|
|
CVContextData.prototype.fillRect = function (x, y, w, h) {
|
|
if (this.appliedFillStyle !== this.currentFillStyle) {
|
|
this.appliedFillStyle = this.currentFillStyle;
|
|
this.nativeContext.fillStyle = this.appliedFillStyle;
|
|
}
|
|
this.nativeContext.fillRect(x, y, w, h);
|
|
};
|
|
|
|
CVContextData.prototype.stroke = function () {
|
|
if (this.appliedStrokeStyle !== this.currentStrokeStyle) {
|
|
this.appliedStrokeStyle = this.currentStrokeStyle;
|
|
this.nativeContext.strokeStyle = this.appliedStrokeStyle;
|
|
}
|
|
if (this.appliedLineWidth !== this.currentLineWidth) {
|
|
this.appliedLineWidth = this.currentLineWidth;
|
|
this.nativeContext.lineWidth = this.appliedLineWidth;
|
|
}
|
|
if (this.appliedLineCap !== this.currentLineCap) {
|
|
this.appliedLineCap = this.currentLineCap;
|
|
this.nativeContext.lineCap = this.appliedLineCap;
|
|
}
|
|
if (this.appliedLineJoin !== this.currentLineJoin) {
|
|
this.appliedLineJoin = this.currentLineJoin;
|
|
this.nativeContext.lineJoin = this.appliedLineJoin;
|
|
}
|
|
if (this.appliedMiterLimit !== this.currentMiterLimit) {
|
|
this.appliedMiterLimit = this.currentMiterLimit;
|
|
this.nativeContext.miterLimit = this.appliedMiterLimit;
|
|
}
|
|
this.nativeContext.stroke();
|
|
};
|
|
|
|
export default CVContextData;
|