mirror of
https://fietkau.software/QRSVG.git
synced 2024-10-06 19:41:17 -05:00
Add confetti shape style
This commit is contained in:
parent
a072d608c0
commit
59c0d2d5cd
114
qrsvg-v1.0.1.js
114
qrsvg-v1.0.1.js
|
@ -230,6 +230,10 @@ function compactPathSpec(oldPathSpec) {
|
||||||
if((step[0] == 'h' || step[0] == 'v') && step[0] == prev[0]) {
|
if((step[0] == 'h' || step[0] == 'v') && step[0] == prev[0]) {
|
||||||
let distance = parseInt(prev.substring(1), 10) + parseInt(step.substring(1), 10);
|
let distance = parseInt(prev.substring(1), 10) + parseInt(step.substring(1), 10);
|
||||||
newPathSpec[newPathSpec.length - 1] = step[0] + distance;
|
newPathSpec[newPathSpec.length - 1] = step[0] + distance;
|
||||||
|
} else if(step[0] == 'm' && (prev[0] == 'm' || prev[0] == 'M')) {
|
||||||
|
let prevPos = prev.substring(1).split(' ').map(c => parseFloat(c));
|
||||||
|
let newDelta = step.substring(1).split(' ').map(c => parseFloat(c));
|
||||||
|
newPathSpec[newPathSpec.length - 1] = prev[0] + (prevPos[0] + newDelta[0]).toPrecision(3) + ' ' + (prevPos[1] + newDelta[1]).toPrecision(3);
|
||||||
} else {
|
} else {
|
||||||
newPathSpec.push(step);
|
newPathSpec.push(step);
|
||||||
}
|
}
|
||||||
|
@ -243,8 +247,62 @@ function calculateTileStyleContour(bitmask, margin, style) {
|
||||||
if(!['dots', 'mosaic', 'confetti'].includes(style)) {
|
if(!['dots', 'mosaic', 'confetti'].includes(style)) {
|
||||||
throw Error('Unsupported tiled render style: ' + style);
|
throw Error('Unsupported tiled render style: ' + style);
|
||||||
}
|
}
|
||||||
|
let confettiShapes = [
|
||||||
|
[ // circle
|
||||||
|
'M 0.5 0.1',
|
||||||
|
'A 0.4 0.4 0 0 1 0.5 0.9',
|
||||||
|
'A 0.4 0.4 0 0 1 0.5 0.1',
|
||||||
|
],
|
||||||
|
[ // rectangle
|
||||||
|
'M 0.1 0.15',
|
||||||
|
'L 0.9 0.15',
|
||||||
|
'L 0.9 0.85',
|
||||||
|
'L 0.1 0.85',
|
||||||
|
'L 0.1 0.15',
|
||||||
|
],
|
||||||
|
[ // star
|
||||||
|
'M 0.68 0.254',
|
||||||
|
'Q 1.21 0.284 0.786 0.58',
|
||||||
|
'Q 0.9275 1.0925 0.498 0.801',
|
||||||
|
'Q 0.0545 1.1 0.212 0.606',
|
||||||
|
'Q -0.208 0.269 0.312 0.259',
|
||||||
|
'Q 0.5 -0.25 0.68 0.254',
|
||||||
|
],
|
||||||
|
[ // heart
|
||||||
|
'M 0.5 0.3',
|
||||||
|
'C 1.2 -0.1 1 0.7 0.5 1',
|
||||||
|
'C 0 0.7 -0.2 -0.1 0.5 0.3',
|
||||||
|
],
|
||||||
|
[ // diamond
|
||||||
|
'M 0.5 0',
|
||||||
|
'Q 0.65 0.35 1 0.5',
|
||||||
|
'Q 0.65 0.65 0.5 1',
|
||||||
|
'Q 0.35 0.65 0 0.5',
|
||||||
|
'Q 0.35 0.35 0.5 0',
|
||||||
|
],
|
||||||
|
[ // shamrock
|
||||||
|
'M 0.45 0.45',
|
||||||
|
'A 0.23 0.23 0 1 1 0.55 0.45',
|
||||||
|
'A 0.23 0.23 0 1 1 0.54 0.48',
|
||||||
|
'L 0.7 0.95',
|
||||||
|
'L 0.3 0.95',
|
||||||
|
'L 0.46 0.48',
|
||||||
|
'A 0.23 0.23 0 1 1 0.45 0.45',
|
||||||
|
],
|
||||||
|
[ // lemon
|
||||||
|
'M 0.5 0',
|
||||||
|
'Q 1.5 0.5 0.5 1',
|
||||||
|
'Q -0.5 0.5 0.5 0',
|
||||||
|
],
|
||||||
|
];
|
||||||
let contour = new Contour();
|
let contour = new Contour();
|
||||||
let prng = new PRNG(1);
|
let prng = new PRNG(1);
|
||||||
|
// Rotate a point around (0.5, 0.5) by angle in radians
|
||||||
|
let rotatePoint = (x, y, angle) => {
|
||||||
|
let rotatedX = 0.5 + (x - 0.5) * Math.cos(angle) - (y - 0.5) * Math.sin(angle);
|
||||||
|
let rotatedY = 0.5 + (x - 0.5) * Math.sin(angle) + (y - 0.5) * Math.cos(angle);
|
||||||
|
return [rotatedX, rotatedY];
|
||||||
|
};
|
||||||
for(let y = 0; y < bitmask.height; y++) {
|
for(let y = 0; y < bitmask.height; y++) {
|
||||||
for(let x = 0; x < bitmask.width; x++) {
|
for(let x = 0; x < bitmask.width; x++) {
|
||||||
if(bitmask.width > 16 && bitmask.height > 16) {
|
if(bitmask.width > 16 && bitmask.height > 16) {
|
||||||
|
@ -269,22 +327,48 @@ function calculateTileStyleContour(bitmask, margin, style) {
|
||||||
let size = 0.9; // relative to grid size
|
let size = 0.9; // relative to grid size
|
||||||
let maxAngle = Math.PI * 0.03;
|
let maxAngle = Math.PI * 0.03;
|
||||||
let angle = (prng.next() * 2 - 1) * maxAngle;
|
let angle = (prng.next() * 2 - 1) * maxAngle;
|
||||||
// |------ middle of the pixel ------| |-north displacement-| |-west displacement-|
|
newPathSpec.push('M' + (x + 1) + ' ' + (y + 1));
|
||||||
let topLeftX = x + margin + 0.5 + ((1 - size) / 2) - 0.5 * Math.cos(angle) + 0.5 * Math.sin(angle);
|
let tileCorners = [
|
||||||
let topLeftY = y + margin + 0.5 + ((1 - size) / 2) + 0.5 * Math.cos(angle) - 0.5 * Math.sin(angle) - 1;
|
rotatePoint(0.5 - (size / 2), 0.5 - (size / 2), angle),
|
||||||
newPathSpec.push('M' + topLeftX.toPrecision(3) + ' ' + topLeftY.toPrecision(3));
|
rotatePoint(0.5 + (size / 2), 0.5 - (size / 2), angle),
|
||||||
newPathSpec.push('l' + (size * Math.cos(angle)).toPrecision(3) + ' ' + (size * Math.sin(angle)).toPrecision(3));
|
rotatePoint(0.5 + (size / 2), 0.5 + (size / 2), angle),
|
||||||
newPathSpec.push(('l-' + (size * Math.sin(angle)).toPrecision(3) + ' ' + (size * Math.cos(angle)).toPrecision(3)).replaceAll('--', ''));
|
rotatePoint(0.5 - (size / 2), 0.5 + (size / 2), angle),
|
||||||
newPathSpec.push(('l-' + (size * Math.cos(angle)).toPrecision(3) + ' -' + (size * Math.sin(angle)).toPrecision(3)).replaceAll('--', ''));
|
];
|
||||||
newPathSpec.push(('l' + (size * Math.sin(angle)).toPrecision(3) + ' -' + (size * Math.cos(angle)).toPrecision(3)).replaceAll('--', ''));
|
newPathSpec.push('m' + tileCorners[0][0].toPrecision(3) + ' ' + tileCorners[0][1].toPrecision(3));
|
||||||
|
newPathSpec.push('l' + (tileCorners[1][0] - tileCorners[0][0]).toPrecision(3) + ' ' + (tileCorners[1][1] - tileCorners[0][1]).toPrecision(3));
|
||||||
|
newPathSpec.push('l' + (tileCorners[2][0] - tileCorners[1][0]).toPrecision(3) + ' ' + (tileCorners[2][1] - tileCorners[1][1]).toPrecision(3));
|
||||||
|
newPathSpec.push('l' + (tileCorners[3][0] - tileCorners[2][0]).toPrecision(3) + ' ' + (tileCorners[3][1] - tileCorners[2][1]).toPrecision(3));
|
||||||
newPathSpec.push('z');
|
newPathSpec.push('z');
|
||||||
} else if(style == 'confetti') {
|
} else if(style == 'confetti') {
|
||||||
// TODO
|
newPathSpec.push('M' + (x + margin) + ' ' + (y + margin));
|
||||||
newPathSpec.push('M' + (x + margin + 0.5) + ' ' + (y + margin));
|
let currentShape = confettiShapes[Math.floor(prng.next() * confettiShapes.length)];
|
||||||
newPathSpec.push('a0.5 0.5 0 0 1 0.5 0.5');
|
let previousPoint = [0, 0];
|
||||||
newPathSpec.push('a0.5 0.5 0 0 1 -0.5 0.5');
|
let angle = prng.next() * Math.PI * 2;
|
||||||
newPathSpec.push('a0.5 0.5 0 0 1 -0.5 -0.5');
|
for(let segment of currentShape) {
|
||||||
newPathSpec.push('a0.5 0.5 0 0 1 0.5 -0.5');
|
segment = segment.split(' ');
|
||||||
|
let formatRotatedPoint = (i, j) => {
|
||||||
|
let rotated = rotatePoint(segment[i], segment[j], angle);
|
||||||
|
return (rotated[0] - previousPoint[0]).toPrecision(3) + ' ' + (rotated[1] - previousPoint[1]).toPrecision(3);
|
||||||
|
}
|
||||||
|
if(segment[0] == 'M') {
|
||||||
|
let rotated = rotatePoint(segment[1], segment[2], angle);
|
||||||
|
newPathSpec.push('m' + formatRotatedPoint(1, 2));
|
||||||
|
previousPoint = rotated;
|
||||||
|
} else if(segment[0] == 'L') {
|
||||||
|
let rotated = rotatePoint(segment[1], segment[2], angle);
|
||||||
|
newPathSpec.push('l' + formatRotatedPoint(1, 2));
|
||||||
|
previousPoint = rotated;
|
||||||
|
} else if(segment[0] == 'Q') {
|
||||||
|
newPathSpec.push('q' + formatRotatedPoint(1, 2) + ' ' + formatRotatedPoint(3, 4));
|
||||||
|
previousPoint = rotatePoint(segment[3], segment[4], angle)
|
||||||
|
} else if(segment[0] == 'C') {
|
||||||
|
newPathSpec.push('c' + formatRotatedPoint(1, 2) + ' ' + formatRotatedPoint(3, 4) + ' ' + formatRotatedPoint(5, 6));
|
||||||
|
previousPoint = rotatePoint(segment[5], segment[6], angle);
|
||||||
|
} else if(segment[0] == 'A') {
|
||||||
|
newPathSpec.push('a' + segment.slice(1, 6).join(' ') + ' ' + formatRotatedPoint(6, 7));
|
||||||
|
previousPoint = rotatePoint(segment[6], segment[7], angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
newPathSpec.push('z');
|
newPathSpec.push('z');
|
||||||
}
|
}
|
||||||
if(!bitmask.get(x - 1, y) && !bitmask.get(x + 1, y) && !bitmask.get(x, y - 1) && !bitmask.get(x, y + 1)) {
|
if(!bitmask.get(x - 1, y) && !bitmask.get(x + 1, y) && !bitmask.get(x, y - 1) && !bitmask.get(x, y + 1)) {
|
||||||
|
@ -466,7 +550,7 @@ function calculateContour(bitmask, margin = 1, style = 'basic') {
|
||||||
contour.pdpInner.push(...Array(3).fill('v-1'));
|
contour.pdpInner.push(...Array(3).fill('v-1'));
|
||||||
contour.pdpInner.push('z');
|
contour.pdpInner.push('z');
|
||||||
}
|
}
|
||||||
if(style == 'dots' || style == 'rounded') {
|
if(['dots', 'rounded', 'confetti'].includes(style)) {
|
||||||
contour.pdpInner = makePathSpecRound(contour.pdpInner);
|
contour.pdpInner = makePathSpecRound(contour.pdpInner);
|
||||||
contour.pdpOuter = makePathSpecRound(contour.pdpOuter);
|
contour.pdpOuter = makePathSpecRound(contour.pdpOuter);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user