import { isa_number, mergeOver, Ωempty } from '../helper/utilities.js';
import { cell } from '../core/library.js';Most of the code relating to the CanvasPattern API can be found here.
fillStyle or strokeStyle attribute by supplying the Pattern object or Cell wrapper’s String name to it.import { isa_number, mergeOver, Ωempty } from '../helper/utilities.js';
import { cell } from '../core/library.js';Shared constants
import { _isArray, BLANK, T_CELL, T_NOISE } from '../helper/shared-vars.js';Local constants
const _A = 'a',
_B = 'b',
_C = 'c',
_D = 'd',
_E = 'e',
_F = 'f',
MAT_POS = ['a', 'b', 'c', 'd', 'e', 'f'],
MAT_REPEAT = ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'],
REPEAT = 'repeat';export default function (P = Ωempty) { const defaultAttributes = {repeat - String indicating how to repeat the pattern’s image. Possible values are: repeat (default), repeat-x, repeat-y, no-repeat
repeat: REPEAT,patternMatrix - Scrawl-canvas will apply a 2d-style, 6 value DOMMatrix to the pattern each time it is recreated. Changing the values of the matrix will change the rotation, skew, etc of the pattern. Pseudo-attributes can be used to set individual elements of the matrix, as follows:
stretchX (or matrixA) - generally used for horizontal (x axis) scaleskewY (or matrixB) - generally used for horizontal (x axis) skewskewX (or matrixC) - generally used for vertical (y axis) skewstretchY (or matrixD) - generally used for vertical (y axis) scaleshiftX (or matrixE) - generally used for horizontal (x axis) positioningshiftY (or matrixF) - generally used for vertical (y axis) positioningTo rotate the pattern, update the B and C matrix values in tandem. Results will be dependent on the surrounding matrix values. See demo Canvas-035 to explore further.
patternMatrix: null,
};
P.defs = mergeOver(P.defs, defaultAttributes); const S = P.setters,
G = P.getters;repeat
S.repeat = function (item) {
if (MAT_REPEAT.includes(item)) this.repeat = item;
else this.repeat = this.defs.repeat;
};checkMatrixExists - internal helper function
P.checkMatrixExists = function () {
if (!this.patternMatrix) this.patternMatrix = new DOMMatrix();
};updateMatrixNumber - internal helper function
P.updateMatrixNumber = function (item, pos) {
this.checkMatrixExists();
item = (item.substring) ? parseFloat(item) : item;
const posCheck = MAT_POS.includes(pos);
if (isa_number(item) && posCheck) this.patternMatrix[pos] = item;
};matrixA, matrixB, matrixC, matrixD, matrixE, matrixF - these pseudo-attributes can be used to set individual attributes of the patternMatrix DOMMatrix object
S.matrixA = function (item) { this.updateMatrixNumber(item, _A); };
S.matrixB = function (item) { this.updateMatrixNumber(item, _B); };
S.matrixC = function (item) { this.updateMatrixNumber(item, _C); };
S.matrixD = function (item) { this.updateMatrixNumber(item, _D); };
S.matrixE = function (item) { this.updateMatrixNumber(item, _E); };
S.matrixF = function (item) { this.updateMatrixNumber(item, _F); };stretchX, skewY, skewX, stretchY, shiftX, shiftY - these pseudo-attributes can be used to set individual attributes of the patternMatrix DOMMatrix object
S.stretchX = function (item) { this.updateMatrixNumber(item, _A); };
S.skewY = function (item) { this.updateMatrixNumber(item, _B); };
S.skewX = function (item) { this.updateMatrixNumber(item, _C); };
S.stretchY = function (item) { this.updateMatrixNumber(item, _D); };
S.shiftX = function (item) { this.updateMatrixNumber(item, _E); };
S.shiftY = function (item) { this.updateMatrixNumber(item, _F); };retrieveMatrixNumber - internal helper function
P.retrieveMatrixNumber = function (pos) {
this.checkMatrixExists();
return this.patternMatrix[pos];
};
G.matrixA = function () { return this.retrieveMatrixNumber(_A); };
G.matrixB = function () { return this.retrieveMatrixNumber(_B); };
G.matrixC = function () { return this.retrieveMatrixNumber(_C); };
G.matrixD = function () { return this.retrieveMatrixNumber(_D); };
G.matrixE = function () { return this.retrieveMatrixNumber(_E); };
G.matrixF = function () { return this.retrieveMatrixNumber(_F); };
G.stretchX = function () { return this.retrieveMatrixNumber(_A); };
G.skewY = function () { return this.retrieveMatrixNumber(_B); };
G.skewX = function () { return this.retrieveMatrixNumber(_C); };
G.stretchY = function () { return this.retrieveMatrixNumber(_D); };
G.shiftX = function () { return this.retrieveMatrixNumber(_E); };
G.shiftY = function () { return this.retrieveMatrixNumber(_F); };patternMatrix - the argument must be an Array containing 6 Number elements in the form of [a, b, c, d, e, f]
S.patternMatrix = function (item) {
if (_isArray(item)) {
const update = this.updateMatrixNumber;
update(item[0], _A);
update(item[1], _B);
update(item[2], _C);
update(item[3], _D);
update(item[4], _E);
update(item[5], _F);
}
};buildStyle - internal function: creates the pattern on the Cell’s CanvasRenderingContext2D engine.
P.buildStyle = function (mycell) {
if (mycell) {
if (mycell.substring) mycell = cell[mycell];
let source = this.source,
loaded = this.sourceLoaded;
const repeat = this.repeat,
engine = mycell.engine;
if (this.type === T_CELL || this.type === T_NOISE) {
source = this.element;
loaded = true;
}
if (engine && loaded) {
const p = engine.createPattern(source, repeat);
p.setTransform(this.patternMatrix);
return p;
}
}
return BLANK;
};
}