P.performFill = function (engine) {
const currentScale = this.currentScale || 0;
if (currentScale > 0) {
engine.save();
const composer = requestCell(),
compEngine = composer.engine,
compCanvas = composer.element;
const tileSources = this.tileSources,
tileFill = this.tileFill,
tilePaths = this.tilePaths,
tileRealCoords = this.tileRealCoordinates,
tileVirtualCoords = this.tileVirtualCoordinates,
winding = this.winding,
tileWidth = this.currentTileWidth,
tileHeight = this.currentTileHeight,
dims = this.currentDimensions,
applyGridGradient = this.applyGridGradient.bind(this);
const getGradientObject = function (source) {
return source && source.substring ? styles[source] : source;
};
const buildTileGradientIdentifier = (grad, index, lockedToEntity) => {
return [
this.name,
'grid-tile-gradient',
index,
lockedToEntity ? GRID_GRADIENT : CELL_GRADIENT,
grad.identifier,
this.currentScale,
this.currentRotation,
this.currentStampPosition.join(':'),
this.currentDimensions.join(':'),
this.columns,
this.rows,
tileFill.join(':'),
].join('-');
};
const buildGutterGradientIdentifier = (grad, lockedToEntity) => {
return [
this.name,
'grid-gutter-gradient',
lockedToEntity ? GRID_GRADIENT : CELL_GRADIENT,
grad.identifier,
this.currentScale,
this.currentRotation,
this.currentStampPosition.join(':'),
this.currentDimensions.join(':'),
this.columns,
this.rows,
this.rowGutterWidth,
this.columnGutterWidth,
].join('-');
};
const setClassicFillGradient = (grad, lockedToEntity) => {
const currentLock = this.lockFillStyleToEntity;
this.lockFillStyleToEntity = lockedToEntity;
engine.fillStyle = grad.getData(this, this.currentHost, FILL);
this.lockFillStyleToEntity = currentLock;
};
const setClassicStrokeGradient = (grad, lockedToEntity) => {
const currentLock = this.lockStrokeStyleToEntity;
this.lockStrokeStyleToEntity = lockedToEntity;
engine.strokeStyle = grad.getData(this, this.currentHost, DRAW);
this.lockStrokeStyleToEntity = currentLock;
};
let currentPicture;
tileSources.forEach((obj, index) => {
if (!obj || !obj.type) return;
const validTiles = tileFill.map(item => item === index ? true : false);
if (!validTiles.length) return;
switch (obj.type) {
case COLOR :
engine.fillStyle = obj.source;
validTiles.forEach((tile, pos) => tile && engine.fill(tilePaths[pos], winding));
break;
case CELL_GRADIENT :
case GRID_GRADIENT : {
const grad = getGradientObject(obj.source),
lockedToEntity = obj.type === GRID_GRADIENT;
if (!grad) break;
if (!grad.isClassic) {
const identifier = buildTileGradientIdentifier(grad, index, lockedToEntity);
applyGridGradient(engine, grad, function (maskEngine) {
validTiles.forEach((tile, pos) => {
if (tile) maskEngine.fill(tilePaths[pos], winding);
});
}, lockedToEntity, identifier);
}
else {
setClassicFillGradient(grad, lockedToEntity);
validTiles.forEach((tile, pos) => tile && engine.fill(tilePaths[pos], winding));
}
break;
}
case GRID_PICTURE : {
currentPicture = (obj.source.substring) ? entity[obj.source] : obj.source;
if (currentPicture.simpleStamp) {
const W = dims[0] * currentScale,
H = dims[1] * currentScale;
compCanvas.width = W;
compCanvas.height = H;
compEngine.globalCompositeOperation = SOURCE_OVER;
currentPicture.simpleStamp(composer, {
startX: 0,
startY: 0,
width: W,
height: H,
method: FILL,
});
const masker = requestCell(),
mEngine = masker.engine,
mCanvas = masker.element;
mCanvas.width = W;
mCanvas.height = H;
mEngine.fillStyle = WHITE;
let use, ux, uy;
for (let i = 0, iz = validTiles.length; i < iz; i++) {
use = validTiles[i];
if (use) {
[ux, uy] = tileVirtualCoords[i];
mEngine.fillRect(ux, uy, tileWidth, tileHeight);
}
}
compEngine.globalCompositeOperation = DESTINATION_IN;
compEngine.drawImage(mCanvas, 0, 0);
engine.drawImage(compCanvas, ~~tileRealCoords[0][0], ~~tileRealCoords[0][1]);
releaseCell(masker);
}
break;
}
case TILE_PICTURE :
currentPicture = (obj.source.substring) ? entity[obj.source] : obj.source;
if (currentPicture.simpleStamp) {
compCanvas.width = tileWidth;
compCanvas.height = tileHeight;
compEngine.globalCompositeOperation = SOURCE_OVER;
currentPicture.simpleStamp(composer, {
startX: 0,
startY: 0,
width: tileWidth,
height: tileHeight,
method: FILL,
});
validTiles.forEach((tile, pos) => tile && engine.drawImage(compCanvas, ~~tileRealCoords[pos][0], ~~tileRealCoords[pos][1]));
}
break;
}
});
const gColor = this.gutterColor,
gRow = this.rowGutterWidth,
gCol = this.columnGutterWidth;
let gObject;
if (xt(gColor)) {
if (gColor.substring) {
gObject = {
type: COLOR,
source: this.gutterColor
};
}
else if (isa_obj(gColor)) gObject = gColor;
else if (isa_number(gColor) && isa_obj(tileSources[gColor])) gObject = tileSources[gColor];
if (gObject && gObject.type) {
switch (gObject.type) {
case COLOR :
engine.strokeStyle = gObject.source;
if (gRow) {
engine.lineWidth = gRow;
engine.stroke(this.rowLines);
}
if (gCol) {
engine.lineWidth = gCol;
engine.stroke(this.columnLines);
}
break;
case CELL_GRADIENT :
case GRID_GRADIENT : {
const grad = getGradientObject(gObject.source),
lockedToEntity = gObject.type === GRID_GRADIENT;
if (!grad) break;
if (!grad.isClassic) {
const identifier = buildGutterGradientIdentifier(grad, lockedToEntity);
applyGridGradient(engine, grad, function (maskEngine) {
if (gRow) {
maskEngine.lineWidth = gRow;
maskEngine.stroke(this.rowLines);
}
if (gCol) {
maskEngine.lineWidth = gCol;
maskEngine.stroke(this.columnLines);
}
}.bind(this), lockedToEntity, identifier);
}
else {
setClassicStrokeGradient(grad, lockedToEntity);
if (gRow) {
engine.lineWidth = gRow;
engine.stroke(this.rowLines);
}
if (gCol) {
engine.lineWidth = gCol;
engine.stroke(this.columnLines);
}
}
break;
}
case GRID_PICTURE :
case TILE_PICTURE : {
if (gRow || gCol) {
currentPicture = (gObject.source.substring) ? entity[gObject.source] : gObject.source;
if (currentPicture.simpleStamp) {
const handle = this.currentStampHandlePosition,
x = handle[0] * currentScale,
y = handle[1] * currentScale,
W = dims[0] * currentScale,
H = dims[1] * currentScale;
compCanvas.width = W;
compCanvas.height = H;
compEngine.globalCompositeOperation = SOURCE_OVER;
currentPicture.simpleStamp(composer, {
startX: 0,
startY: 0,
width: W,
height: H,
method: FILL,
});
const masker = requestCell(),
mEngine = masker.engine,
mCanvas = masker.element;
mCanvas.width = W;
mCanvas.height = H;
mEngine.translate(x, y);
mEngine.strokeStyle = WHITE;
if (gRow) {
mEngine.lineWidth = gRow;
mEngine.stroke(this.rowLines);
}
if (gCol) {
mEngine.lineWidth = gCol;
mEngine.stroke(this.columnLines);
}
compEngine.globalCompositeOperation = DESTINATION_IN;
compEngine.drawImage(mCanvas, 0, 0);
engine.drawImage(compCanvas, ~~tileRealCoords[0][0], ~~tileRealCoords[0][1]);
releaseCell(masker);
}
}
break;
}
}
}
}
releaseCell(composer);
engine.restore();
}
};
P.applyGridGradient = function (engine, grad, maskStamp, lockedToEntity = false, identifier = ZERO_STR) {
if (!grad || !maskStamp) return false;
const refCell = this.currentHost;
if (!refCell) return false;
if (!identifier || identifier === ZERO_STR) identifier = generateIdForArtefact(this);
if (!checkForWorkstoreItem(identifier)) {
const myCell = requestCell(),
element = myCell.element,
maskEngine = myCell.engine;
const [width, height] = refCell.get('dimensions'),
[x, y] = this.currentStampPosition,
matrix = refCell.engine.getTransform();
element.width = width;
element.height = height;
myCell.rotateDestination(maskEngine, x, y, this);
myCell.setEngine(this);
maskEngine.shadowOffsetY = 0;
maskEngine.shadowOffsetX = 0;
maskEngine.shadowBlur = 0;
maskEngine.fillStyle = BLACK;
maskEngine.strokeStyle = BLACK;
maskStamp(maskEngine);
const data = maskEngine.getImageData(0, 0, width, height);
const success = gradientEngine.action({
fixedGradientData: this.getFixedGradientData(grad, FILL, lockedToEntity),
identifier,
imageData: data,
entity: this,
matrix,
});
releaseCell(myCell);
if (!success) return false;
}
this.applyFromWorkstore(engine, identifier);
return identifier;
};