Select Git revision
gunicorn.conf.py
bottom-slogan-gradient-vertical-logo.js 19.33 KiB
class BottomSloganGradientVerticalLogo extends Template {
description = "Určeno pro sociální sítě. <span style=\"color:red\">Pozor, některé koalice nemají vertikální logo!</span>";
changeableAttributes = [
"verticalLogoImage",
"primaryImage",
"primaryImagePosition",
"primaryColorScheme",
"primaryText",
"nameText"
];
primaryColorSchemes = [
"black-on-white",
"white-on-black"
];
// Colors
changeableColors = [
"backgroundGradientColor1",
"foregroundColor",
"primaryTextColor",
"nameBackgroundColor",
"nameTextColor"
];
lightLogoDefaultSource = "static/images/vertical-logos/default-light.png";
darkLogoDefaultSource = "static/images/vertical-logos/default-dark.png";
// Canvas
async redrawCanvas() {
if (this.redrawing) {
return;
}
this.redrawing = true;
// Background rectangle
let backgroundRectangleHeight = Math.ceil(this.canvas.height * 0.35);
// Foreground rectangle
const foregroundRectangleOffsetSides = Math.ceil(this.canvas.width * 0.1);
const foregroundRectanglePaddingSides = Math.ceil(this.canvas.width * 0.04);
const foregroundRectangleAngle = Math.ceil(this.canvas.height * 0.01);
const foregroundRectangleOffsetBottom = Math.ceil(this.canvas.height * 0.1);
const foregroundRectanglePaddingTop = Math.ceil(this.canvas.height * 0.02);
const foregroundRectanglePaddingTopWithNameOrDiacritics = Math.ceil(this.canvas.height * 0.02);
const foregroundRectanglePaddingBottom = Math.ceil(this.canvas.height * 0.05);
// Primary text
let primaryTextFontSize = Math.ceil(this.canvas.height * 0.09);
let primaryTextMaxLines = 3;
// Name text
let nameTextFontSize = Math.ceil(this.canvas.height * 0.03);
const nameTextMaxWidth = Math.ceil(this.canvas.width * 0.35);
// Name rectangle
const nameRectangleOffsetSide = Math.ceil(this.canvas.width * 0.025);
const nameRectangleOffsetTop = Math.ceil(this.canvas.height * 0.03);
const nameRectanglePaddingSides = Math.ceil(this.canvas.width * 0.025);
const nameRectanglePaddingTop = Math.ceil(this.canvas.height * 0.01);
const nameRectanglePaddingBottom = Math.ceil(this.canvas.height * 0.0175);
// Logo
let logoWidth = Math.ceil(this.canvas.width * 0.12) * this.logoImageZoom;
const logoOffsetSide = Math.ceil(this.canvas.width * 0.04);
const logoMaxHeightArea = 0.8;
// Clear the canvas
this.context.clearRect(
0, 0,
this.canvas.width, this.canvas.height
);
// Set image
if (this.primaryImage !== null) {
// https://github.com/DonkeyDushan/piratilol/blob/main/src/js/index.js
// Thanks to DonkeyDushan, the guy who made the joke 2021 campaign generator :D
const imageScaleX = this.canvas.width / this.primaryImage.width;
const imageScaleY = this.canvas.height / this.primaryImage.height;
const imageScale = Math.max(imageScaleX, imageScaleY) * this.primaryImageZoom;
// https://stackoverflow.com/a/8529655
// Thanks to alex!
this.context.setTransform(
imageScale,
0, 0,
imageScale,
(this.canvas.width - this.primaryImage.width * imageScale) / 2 + this.primaryImageX * this.primaryImageZoom,
(this.canvas.height - this.primaryImage.height * imageScale) / 2 + this.primaryImageY * this.primaryImageZoom,
);
this.context.drawImage(
this.primaryImage,
0, 0
);
this.context.setTransform(); // Reset transformation
}
// Create primary text
const primaryTextMaxWidth = (
this.canvas.width
- foregroundRectangleOffsetSides * 2
- foregroundRectanglePaddingSides * 2
- logoWidth
- logoOffsetSide
);
let primaryTextLines = null;
const originalPrimaryTextFontSize = primaryTextFontSize;
do {
this.context.font = `${this.primaryFontStyle} ${primaryTextFontSize}px ${this.primaryFont}`;
primaryTextLines = splitStringIntoLines(
this.context,
this.primaryText,
primaryTextMaxWidth,
primaryTextMaxLines,
true
);
if (
primaryTextLines.length > primaryTextMaxLines
&& (
primaryTextLines.length * primaryTextFontSize
> primaryTextMaxLines * originalPrimaryTextFontSize
)
) {
primaryTextFontSize -= 2;
}
} while (
primaryTextLines.length > primaryTextMaxLines
&& (
primaryTextLines.length * primaryTextFontSize
> primaryTextMaxLines * originalPrimaryTextFontSize
)
);
const firstPrimaryLine = primaryTextLines[0].toString();
let foregroundRectangleHeight = 0;
// Create background rectangle
if (primaryTextLines.length === 1) {
backgroundRectangleHeight = Math.ceil(backgroundRectangleHeight / 1.3);
}
// Helper canvas
const backgroundCanvas = document.createElement("canvas");
backgroundCanvas.width = this.canvas.width;
backgroundCanvas.height = backgroundRectangleHeight;
const backgroundCanvasContext = backgroundCanvas.getContext("2d");
const backgroundGradient = backgroundCanvasContext.createLinearGradient(
0, backgroundCanvas.height,
backgroundCanvas.width * 2, 0
);
backgroundGradient.addColorStop(0, this.backgroundGradientColor1);
backgroundGradient.addColorStop(1, "rgba(0, 0, 0, 0)");
backgroundCanvasContext.fillStyle = backgroundGradient;
backgroundCanvasContext.fillRect(
0, 0,
backgroundCanvas.width, backgroundCanvas.height
);
const backgroundTransparencyGradient = backgroundCanvasContext.createLinearGradient(
backgroundCanvas.width / 2, 0,
backgroundCanvas.width / 2, backgroundCanvas.height
);
backgroundTransparencyGradient.addColorStop(0, "rgba(0, 0, 0, 1)");
backgroundTransparencyGradient.addColorStop(1, "rgba(0, 0, 0, 0)");
backgroundCanvasContext.fillStyle = backgroundTransparencyGradient;
backgroundCanvasContext.globalCompositeOperation = "xor";
backgroundCanvasContext.fillRect(
0, 0,
backgroundCanvas.width, backgroundCanvas.height
);
this.context.drawImage(
backgroundCanvas,
0, this.canvas.height - backgroundCanvas.height,
);
// Create foreground rectangle
if (this.primaryText !== "") {
foregroundRectangleHeight = (
foregroundRectanglePaddingBottom
+ primaryTextLines.length * primaryTextFontSize
+ foregroundRectanglePaddingTop
+ (
(
this.nameText !== ""
|| (
firstPrimaryLine.replace(/[a-zA-Z0-9À-ž]+/g, "").length
!== firstPrimaryLine.replace(/[a-zA-Z0-9]+/g, "").length
)
) ?
foregroundRectanglePaddingTopWithNameOrDiacritics : 0
)
);
this.context.fillStyle = this.foregroundColor;
this.context.beginPath();
this.context.moveTo(
foregroundRectangleOffsetSides,
this.canvas.height - foregroundRectangleOffsetBottom
);
this.context.lineTo(
this.canvas.width - foregroundRectangleOffsetSides,
this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleAngle
);
this.context.lineTo(
this.canvas.width - foregroundRectangleOffsetSides,
this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleHeight - foregroundRectangleAngle
);
this.context.lineTo(
foregroundRectangleOffsetSides,
this.canvas.height - foregroundRectangleOffsetBottom - foregroundRectangleHeight
);
this.context.closePath();
this.context.fill();
this.context.font = `${this.primaryFontStyle} ${primaryTextFontSize}px ${this.primaryFont}`;
let currentPrimaryLineY = (
this.canvas.height
- foregroundRectangleOffsetBottom
- foregroundRectanglePaddingBottom
);
this.context.fillStyle = this.primaryTextColor;
for (const line of primaryTextLines.reverse()) {
this.context.fillText(
line.join(" "),
(
foregroundRectangleOffsetSides
+ foregroundRectanglePaddingSides
),
currentPrimaryLineY
);
currentPrimaryLineY -= primaryTextFontSize;
}
// Create name text
if (this.nameText !== "") {
do {
this.context.font = `${nameTextFontSize}px 'Roboto Condensed'`;
if (
this.context.measureText(this.nameText).width
> nameTextMaxWidth
) {
nameTextFontSize -= 2;
}
} while (this.context.measureText(this.nameText).width > nameTextMaxWidth);
this.context.fillStyle = this.nameBackgroundColor;
this.context.fillRect(
(
foregroundRectangleOffsetSides
+ nameRectangleOffsetSide
), (
this.canvas.height
- foregroundRectangleHeight
- foregroundRectangleOffsetBottom
- nameRectanglePaddingBottom
- nameRectanglePaddingTop
- nameTextFontSize
+ nameRectangleOffsetTop
),
(
nameRectanglePaddingSides * 2
+ this.context.measureText(this.nameText).width
),
(
nameRectanglePaddingBottom
+ nameRectanglePaddingTop
+ nameTextFontSize
)
);
this.context.fillStyle = this.nameTextColor;
this.context.fillText(
this.nameText,
(
foregroundRectangleOffsetSides
+ nameRectangleOffsetSide
+ nameRectanglePaddingSides
),
(
this.canvas.height
- foregroundRectangleHeight
- foregroundRectangleOffsetBottom
- nameRectanglePaddingBottom
+ nameRectangleOffsetTop
)
);
}
}
const classRef = this;
// Create logo image
function drawLogoImage(image) {
let logoHeight = image.height * (logoWidth / image.width);
if (logoHeight > foregroundRectangleHeight * logoMaxHeightArea) {
logoHeight = foregroundRectangleHeight * logoMaxHeightArea;
logoWidth = image.width * (logoHeight / image.height);
}
classRef.context.drawImage(
image,
(
classRef.canvas.width
- foregroundRectangleOffsetSides
- foregroundRectanglePaddingSides
- logoWidth
),
(
classRef.canvas.height
- foregroundRectangleOffsetBottom
- foregroundRectanglePaddingBottom
- primaryTextLines.length * primaryTextFontSize
- foregroundRectanglePaddingTop
- (
(
classRef.nameText !== ""
|| (
firstPrimaryLine.replace(/[a-zA-Z0-9À-ž]+/g, "").length
!== firstPrimaryLine.replace(/[a-zA-Z0-9]+/g, "").length
)
) ?
foregroundRectanglePaddingTopWithNameOrDiacritics : 0
)
- foregroundRectangleAngle
),
logoWidth, logoHeight
);
}
if (this.logoImage === null) {
const logoImageLoadPromise = new Promise(
resolve => {
let logoImage = new Image();
logoImage.onload = function() {
drawLogoImage(this);
resolve();
}
const foregroundRGB = hexToRgb(this.foregroundColor);
const foregroundLightness = (
0.2126 * foregroundRGB.r
+ 0.7152 * foregroundRGB.g
+ 0.0722 * foregroundRGB.b
);
const useLightLogo = (foregroundLightness < 207);
if (useLightLogo) {
logoImage.src = classRef.lightLogoDefaultSource;
} else {
logoImage.src = classRef.darkLogoDefaultSource;
}
}
);
await logoImageLoadPromise;
} else {
drawLogoImage(this.logoImage);
}
if (this.requesterText !== "") {
// https://newspaint.wordpress.com/2014/05/22/writing-rotated-text-on-a-javascript-canvas/
// Thanks to newspaint!
this.context.save();
this.context.translate(this.canvas.width - 1, 0);
this.context.rotate(3 * Math.PI / 2);
let requesterFontSize = Math.ceil(this.canvas.width * 0.015);
do {
this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
if (
this.context.measureText(this.requesterText).width
> this.canvas.height * 0.97
) {
requesterFontSize -= 2;
this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
}
} while (
this.context.measureText(this.requesterText).width
> this.canvas.height * 0.97
);
this.context.fillStyle = this.requesterTextColor;
this.context.textAlign = "left";
this.context.globalAlpha = 0.6;
this.context.fillText(
this.requesterText,
-this.canvas.height * 0.985, -this.canvas.width * 0.985 + requesterFontSize
);
this.context.globalAlpha = 1;
this.context.restore();
}
this.finalDrawHook();
this.stickerDrawHook();
this.redrawing = false;
}
// Color schemes
async setPrimaryColorScheme(scheme, skipRedraw = false) {
switch (scheme) {
case "black-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#000000";
this.nameTextColor = "#ffffff";
break;
case "white-on-black":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#ffffff";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "forum-black-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#962a51";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "forum-white-on-purple":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#962a51";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "zeleni-volary-bystrc-most-black-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#00ad43";
this.nameBackgroundColor = "#000000";
this.nameTextColor = "#ffffff";
break;
case "zeleni-volary-bystrc-most-white-on-green":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#00ad43";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "spolecne-s-piraty-black-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#21274e";
this.nameBackgroundColor = "#9796ca";
this.nameTextColor = "#000000";
break;
case "spolecne-s-piraty-white-on-blue":
this.foregroundColor = "#21274e";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#ffffff";
this.nameBackgroundColor = "#9796ca";
this.nameTextColor = "#000000";
break;
case "louny-spolecne-black-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#3e2a5b";
this.backgroundGradientColor1 = "#e2d7a9";
this.nameBackgroundColor = "#3e2a5b";
this.nameTextColor = "#ffffff";
break;
case "louny-spolecne-white-on-purple":
this.foregroundColor = "#3e2a5b";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#e2d7a9";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "litomerice-blue-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#123172";
this.backgroundGradientColor1 = "#123172";
this.nameBackgroundColor = "#cccccc";
this.nameTextColor = "#123172";
break;
case "litomerice-white-on-blue":
this.foregroundColor = "#123172";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#ffffff";
this.nameBackgroundColor = "#cccccc";
this.nameTextColor = "#123172";
break;
case "stranane-gray-on-yellow":
this.foregroundColor = "#ffd500";
this.primaryTextColor = "#4d4d4d";
this.backgroundGradientColor1 = "#ffffff";
this.nameBackgroundColor = "#4d4d4d";
this.nameTextColor = "#ffffff";
break;
case "stranane-yellow-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#4d4d4d";
this.backgroundGradientColor1 = "#ffd500";
this.nameBackgroundColor = "#4d4d4d";
this.nameTextColor = "#ffffff";
break;
case "stranane-white-on-yellow":
this.foregroundColor = "#4d4d4d";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#ffd500";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#4d4d4d";
break;
case "prusanky-black-on-yellow":
this.foregroundColor = "#ffd500";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#000000";
this.nameTextColor = "#ffffff";
break;
case "prusanky-yellow-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#ffd500";
this.nameBackgroundColor = "#000000";
this.nameTextColor = "#ffffff";
break;
case "prusanky-white-on-yellow":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#ffd500";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "ujezd-green-on-white":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#8ed4a3";
this.nameBackgroundColor = "#ffdd55";
this.nameTextColor = "#000000";
break;
case "ujezd-white-on-green":
this.foregroundColor = "#8ed4a3";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#ffdd55";
this.nameTextColor = "#000000";
break;
case "cssd-red-on-black":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#e63812";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "cssd-black-on-red":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "jilemnice-purple-on-black":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#6e1646";
this.nameBackgroundColor = "#000000";
this.nameTextColor = "#ffffff";
break;
case "jilemnice-black-on-purple":
this.foregroundColor = "#6e1646";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "novarole-white-on-green":
this.foregroundColor = "#ffffff";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#a9ce2d";
this.nameBackgroundColor = "#a9ce2d";
this.nameTextColor = "#000000";
break;
case "novarole-green-on-white":
this.foregroundColor = "#000000";
this.primaryTextColor = "#ffffff";
this.backgroundGradientColor1 = "#a9ce2d";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "novarole-green-on-black":
this.foregroundColor = "#a9ce2d";
this.primaryTextColor = "#000000";
this.backgroundGradientColor1 = "#000000";
this.nameBackgroundColor = "#ffffff";
this.nameTextColor = "#000000";
break;
case "zeleni-melnik-yellow-name-rect":
await this.setPrimaryColorScheme("white-on-black", true);
this.nameBackgroundColor = "#fde119";
this.nameTextColor = "#000000";
break;
default:
throw new Error("This scheme does not exist.");
break;
}
this.requesterTextColor = this.primaryTextColor;
if (!skipRedraw) {
await this.redrawCanvas();
}
}
}