xxxxxxxxxx
264
let font;
let outlineButton;
let isOutlineMode = false;
let fSize;
let msg;
let path;
let r = 90;
let x;
let y;
let o = 0;
let pointOffsets = [];
let fontIndex = 0;
let fonts = [
"DalaPrisma-Fat-Trial.otf",
"ABCGrow-DF.otf",
"Redaction20-Bold.otf",
"History_14.otf",
"KoperTrial-SemiBoldItalic.otf",
"History_12.otf",
];
let button;
let selectedPoint = null;
function setup() {
createCanvas(1900, 1000);
background(255);
noFill();
opentype.load(fonts[fontIndex], function (err, f) {
if (err) {
alert("Font could not be loaded: " + err);
} else {
font = f;
console.log("font ready");
fSize =550;
msg = "again";
x = 200;
y = 200;
path = font.getPath(msg, x, y, fSize);
console.log(path.commands);
let button = createButton('Change Font');
button.position(10, 10);
button.mousePressed(changeFont);
button.style('font-size', '30px');
outlineButton = createButton('Outline');
outlineButton.position(200, 10);
outlineButton.mousePressed(outlineMode);
outlineButton.style('font-size', '30px');
// Calculate bounding box after the path is defined
boundingBox = getBoundingBox(path.commands);
textWidth = boundingBox.maxX - boundingBox.minX;
textHeight = boundingBox.maxY - boundingBox.minY;
offsetX = (width - textWidth) / 2 - boundingBox.minX;
offsetY = (height - textHeight) / 2 - boundingBox.minY;
}
});
}
function outlineMode() {
isOutlineMode = !isOutlineMode;
}
function changeFont() {
boundingBox = getBoundingBox(path.commands);
textWidth = boundingBox.maxX - boundingBox.minX;
textHeight = boundingBox.maxY - boundingBox.minY;
offsetX = (width - textWidth) / 2 - boundingBox.minX;
offsetY = (height - textHeight) / 2 - boundingBox.minY;
fontIndex = (fontIndex + 1) % fonts.length;
opentype.load(fonts[fontIndex], function (err, f) {
if (err) {
alert("Font could not be loaded: " + err);
} else {
font = f;
console.log("font changed");
path = font.getPath(msg, x, y, fSize);
console.log(path.commands);
}
});
}
function pointInPolygon(point, vertices) {
let i, j;
let inside = false;
for (i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
let xi = vertices[i].x;
let yi = vertices[i].y;
let xj = vertices[j].x;
let yj = vertices[j].y;
let intersect = ((yi > point.y) !== (yj > point.y)) && (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi);
if (intersect) {
inside = !inside;
}
}
return inside;
}
function getBoundingBox(commands) {
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
for (const cmd of commands) {
if (cmd.x !== undefined && cmd.y !== undefined) {
minX = Math.min(minX, cmd.x);
minY = Math.min(minY, cmd.y);
maxX = Math.max(maxX, cmd.x);
maxY = Math.max(maxY, cmd.y);
}
}
return { minX, minY, maxX, maxY };
}
function isInside(point, path) {
let x = point.x;
let y = point.y;
let inside = false;
for (let i = 0, j = path.length - 1; i < path.length; j = i++) {
let xi = path[i].x;
let yi = path[i].y;
let xj = path[j].x;
let yj = path[j].y;
let intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
function processPathCommands(commands) {
let paths = [];
let currentPath = null;
let testPoints = [];
for (let cmd of commands) {
if (cmd.type === "M") {
if (currentPath) {
paths.push(currentPath);
}
currentPath = {
commands: [cmd],
vertices: [{x: cmd.x, y: cmd.y}],
isInner: false,
};
testPoints.push({x: cmd.x, y: cmd.y});
} else if (cmd.type === "L" || cmd.type === "C" || cmd.type === "Q") {
currentPath.commands.push(cmd);
currentPath.vertices.push({x: cmd.x, y: cmd.y});
} else if (cmd.type === "Z") {
// Do nothing
}
}
if (currentPath) {
paths.push(currentPath);
}
for (let i = 0; i < paths.length; i++) {
let pathA = paths[i];
for (let j = 0; j < paths.length; j++) {
if (i === j) continue;
let pathB = paths[j];
if (pointInPolygon(testPoints[i], pathB.vertices)) {
pathA.isInner = !pathA.isInner;
}
}
}
return paths;
}
function draw() {
if (!font) return;
let boundingBox = getBoundingBox(path.commands);
let textWidth = boundingBox.maxX - boundingBox.minX;
let textHeight = boundingBox.maxY - boundingBox.minY;
let offsetX = (width - textWidth) / 2 - boundingBox.minX;
let offsetY = (height - textHeight) / 2 - boundingBox.minY;
background(255);
noStroke();
let t = o;
push();
translate(offsetX, offsetY);
let shapeStarted = false;
let paths = processPathCommands(path.commands);
for (let pathObj of paths) {
for (let cmd of pathObj.commands) {
if (cmd.type === "M") {
if (shapeStarted) {
endShape(CLOSE);
}
shapeStarted = true;
if (pathObj.isInner) {
fill(255);
} else {
fill(0);
}
let n1 = map(noise(t, cmd.x / 5), 0, 1, -r/2, r/2);
let n2 = map(noise(t, cmd.y / 5), 0, 1, -r/2, r/2);
t += 0.05;
if (isOutlineMode) {
stroke(0);
noFill();
} else {
}
beginShape();
vertex(cmd.x + n1, cmd.y + n2);
} else if (cmd.type === "L") {
let n1 = map(noise(t, cmd.x / 5), 0, 1, -r, r);
let n2 = map(noise(t, cmd.y / 5), 0, 1, -r, r);
t += 0.05;
vertex(cmd.x + n1, cmd.y + n2);
} else if (cmd.type === "C") {
let n1 = map(noise(t, cmd.x1 / 5), 0, 1, -r / 2, r / 2);
let n2 = map(noise(t, cmd.y1 / 5), 0, 1, -r / 2, r / 2);
t += 0.05;
bezierVertex(cmd.x1 + n1, cmd.y1 + n2, cmd.x2 + n1, cmd.y2 + n2, cmd.x + n1, cmd.y + n2);
} else if (cmd.type === "Q") {
let n1 = map(noise(t, cmd.x1 / 5), 0, 1, -r / 2, r / 2);
let n2 = map(noise(t, cmd.y1 / 5), 0, 1, -r / 2, r / 2);
t += 0.05;
quadraticVertex(cmd.x1 + n1, cmd.y1 + n2, cmd.x, cmd.y);
} else if (cmd.type === "Z") {
}
}
if (shapeStarted) {
endShape(CLOSE);
shapeStarted = false;
}
}
pop();
o += 0.07;
}