From 41ba531175b12767d88174306adde57087348717 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1?= <tomas.vlt@pm.me>
Date: Fri, 11 Nov 2022 08:43:30 +0100
Subject: [PATCH] wip - new template

---
 .../templates/bottom-slogan-gradient-icon.js  | 887 ++++++++++++++++++
 generator/static/js/ui.js                     |   1 +
 generator/templates/generator.html            |   8 +
 3 files changed, 896 insertions(+)
 create mode 100644 generator/static/js/templates/bottom-slogan-gradient-icon.js

diff --git a/generator/static/js/templates/bottom-slogan-gradient-icon.js b/generator/static/js/templates/bottom-slogan-gradient-icon.js
new file mode 100644
index 00000000..1ba09c85
--- /dev/null
+++ b/generator/static/js/templates/bottom-slogan-gradient-icon.js
@@ -0,0 +1,887 @@
+class BottomSloganGradientIcon extends Template {
+	description = "Určeno pro sociální sítě.";
+	
+	changeableAttributes = [
+		"logoImage",
+		"primaryImage",
+		"primaryImagePosition",
+		"iconImage",
+		"iconText",
+		"primaryColorScheme",
+		"primaryText",
+		"nameText"
+	];
+
+	primaryColorSchemes = [
+		"black-on-white",
+		"white-on-black"
+	];
+
+	// Colors
+	changeableColors = [
+		"backgroundGradientColor1",
+		"backgroundGradientColor2",
+		"foregroundColor",
+		"primaryTextColor",
+		"iconColor",
+		"nameBackgroundColor",
+		"nameTextColor"
+	];
+
+	iconImage = null;
+	iconText = "";
+
+	// 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.025);
+		const foregroundRectangleAngle = Math.ceil(this.canvas.height * 0.01);
+		const foregroundRectangleOffsetBottom = Math.ceil(this.canvas.height * 0.17);
+		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
+		const logoWidth = Math.ceil(this.canvas.width * 0.2) * this.logoImageZoom;
+		const logoOffsetTop = Math.ceil(this.canvas.height * 0.07) * ((3 - this.logoImageZoom) / 2);
+		const logoOffsetSide = Math.ceil(this.canvas.width * 0.1) * ((3 - this.logoImageZoom) / 2);
+		
+		//// Icon
+		// Image
+		const iconBottomOffset = Math.ceil(this.canvas.height * 0.05);
+		const iconHeight = Math.ceil(this.canvas.width * 0.06);
+		// Text
+		const iconTextSideOffset = Math.ceil(this.canvas.width * 0.015);
+		const iconTextTopOffset = -(Math.ceil(this.canvas.height * 0.002)); // FIXME, if possible. I think this might just be the font's fault.
+		const iconTextMaxWidth = (this.canvas.width - 2 * foregroundRectangleOffsetSides) * 0.7;
+		let iconTextFontSize = Math.ceil(this.canvas.height * 0.027);
+		const iconTextFontLinePadding = Math.ceil(this.canvas.height * 0.003);
+		const iconTextMaxLines = 2;
+		
+		// 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
+		);
+		
+		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();
+		
+		// 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, 0
+		);
+		backgroundGradient.addColorStop(0, this.backgroundGradientColor1);
+		backgroundGradient.addColorStop(1, this.backgroundGradientColor2);
+		
+		backgroundCanvasContext.fillStyle = backgroundGradient;
+		backgroundCanvasContext.fillRect(
+			0, 0,
+			backgroundCanvas.width, backgroundCanvas.height
+		);
+		
+		const backgroundTransparencyGradient = backgroundCanvasContext.createLinearGradient(
+			backgroundCanvas.width / 2, 0,
+			backgroundCanvas.width / 2, backgroundCanvas.height * 1.35
+		);
+		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 !== "") {
+			const 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;
+			this.context.textAlign = "center";
+			
+			for (const line of primaryTextLines.reverse()) {
+				this.context.fillText(
+					line.join(" "),
+					this.canvas.width / 2,
+					currentPrimaryLineY
+				);
+				
+				currentPrimaryLineY -= primaryTextFontSize;
+			}
+			
+			this.context.textAlign = "left";
+			
+			// 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) {
+			classRef.context.drawImage(
+				image,
+				(
+					classRef.canvas.width
+					- logoWidth
+					- logoOffsetSide
+				),
+				logoOffsetTop,
+				logoWidth, image.height * (logoWidth / image.width)
+			);
+		}
+		
+		if (this.logoImage === null) {
+			const logoImageLoadPromise = new Promise(
+				resolve => {
+					let logoImage = new Image();
+					
+					logoImage.onload = function() {
+						drawLogoImage(this);
+						
+						resolve();
+					}
+					
+					// See if we're using the light or dark version
+					const logoBackgroundRGB = hexToRgb(
+						blendColors(
+							this.backgroundGradientColor1,
+							this.backgroundGradientColor2,
+							0.5
+						)
+					);
+					const backgroundLightness = (
+						0.2126 * logoBackgroundRGB.r
+						+ 0.7152 * logoBackgroundRGB.g
+						+ 0.0722 * logoBackgroundRGB.b
+					);
+					
+					const useLightLogo = (backgroundLightness < 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();
+		}
+		
+		// Draw icon
+		if (this.iconImage !== null) {
+			let iconTextLines = null;
+			const originalIconTextFontSize = iconTextFontSize;
+			
+			do {
+				classRef.context.font = `${iconTextFontSize}px 'Roboto Condensed'`;
+				
+				iconTextLines = splitStringIntoLines(
+					classRef.context,
+					classRef.iconText,
+					iconTextMaxWidth,
+					iconTextMaxLines,
+					true
+				);
+				
+				if (
+					iconTextLines.length > iconTextMaxLines
+					&& (
+						iconTextLines.length * iconTextFontSize
+						> iconTextMaxLines * originalIconTextFontSize
+					)
+				) {
+					iconTextFontSize -= 2;
+				}
+			} while (
+				iconTextLines.length > iconTextMaxLines
+				&& (
+					iconTextLines.length * iconTextFontSize
+					> iconTextMaxLines * originalIconTextFontSize
+				)
+			);
+			
+			let currentIconLineY = (
+				this.canvas.height
+				- iconBottomOffset
+				- iconHeight
+				+ iconTextFontSize
+				+ iconTextTopOffset
+			);
+			
+			this.context.textAlign = "left";
+			
+			for (const line of iconTextLines) {
+				
+			}
+		}
+		
+		this.finalDrawHook();
+		this.stickerDrawHook();
+		
+		this.redrawing = false;
+	}
+	
+	// Icon
+	async setIconText(text, skipRedraw = false) {
+		this.iconText = text;
+		
+		if (!skipRedraw) {
+			await this.redrawCanvas();
+		}
+	}
+
+	async setIconImageFromInput(imageInput, skipRedraw = false) {
+		if (imageInput.files.length == 0) {
+			return;
+		}
+		
+		const readPromise = new Promise(
+			resolve => {
+				const fileReader = new FileReader();
+				
+				let classRef = this;
+				
+				fileReader.onloadend = function(event) {
+					classRef.iconImage = new Image();
+					
+					classRef.iconImage.onload = function() {
+						if (!skipRedraw) {
+							classRef.redrawCanvas();
+						}
+						
+						resolve();
+					}
+					
+					classRef.iconImage.src = event.target.result;
+				}
+				
+				fileReader.readAsDataURL(imageInput.files[0]);
+			}
+		);
+		
+		await readPromise;
+	}
+	
+	// Color schemes
+	async setPrimaryColorScheme(scheme, skipRedraw = false) {
+		switch (scheme) {
+			case "black-on-white":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#999999";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "white-on-black":
+				this.backgroundGradientColor1 = "#ffffff";
+				this.backgroundGradientColor2 = "#999999";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "forum-black-on-white":
+				this.backgroundGradientColor1 = "#962a51";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "forum-white-on-purple":
+				this.backgroundGradientColor1 = "#962a51";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "zeleni-volary-bystrc-most-black-on-white":
+				this.backgroundGradientColor1 = "#00ad43";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "zeleni-volary-bystrc-most-white-on-green":
+				this.backgroundGradientColor1 = "#00ad43";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "spolecne-s-piraty-black-on-white":
+				this.backgroundGradientColor1 = "#21274e";
+				this.backgroundGradientColor2 = "#9796ca";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#9796ca";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "spolecne-s-piraty-white-on-blue":
+				this.backgroundGradientColor1 = "#ffffff";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#21274e";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#21274e";
+				
+				this.nameBackgroundColor = "#9796ca";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "louny-spolecne-black-on-white":
+				this.backgroundGradientColor1 = "#3e2a5b";
+				this.backgroundGradientColor2 = "#e2d7a9";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#3e2a5b";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#e2d7a9";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "louny-spolecne-white-on-purple":
+				this.backgroundGradientColor1 = "#9796ca";
+				this.backgroundGradientColor2 = "#e2d7a9";
+				
+				this.foregroundColor = "#3e2a5b";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#3e2a5b";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "litomerice-blue-on-white":
+				this.backgroundGradientColor1 = "#123172";
+				this.backgroundGradientColor2 = "#cccccc";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#123172";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#cccccc";
+				this.nameTextColor = "#123172";
+				
+				break;
+			case "litomerice-white-on-blue":
+				this.backgroundGradientColor1 = "#ffffff";
+				this.backgroundGradientColor2 = "#cccccc";
+				
+				this.foregroundColor = "#123172";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#123172";
+				
+				this.nameBackgroundColor = "#cccccc";
+				this.nameTextColor = "#123172";
+				
+				break;
+			case "stranane-gray-on-yellow":
+				this.backgroundGradientColor1 = "#ffffff";
+				this.backgroundGradientColor2 = "#4d4d4d";
+				
+				this.foregroundColor = "#ffd500";
+				this.primaryTextColor = "#4d4d4d";
+				
+				this.iconColor = "#ffd500";
+				
+				this.nameBackgroundColor = "#4d4d4d";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "stranane-yellow-on-white":
+				this.backgroundGradientColor1 = "#ffd500";
+				this.backgroundGradientColor2 = "#4d4d4d";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#4d4d4d";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#4d4d4d";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "stranane-white-on-yellow":
+				this.backgroundGradientColor1 = "#ffd500";
+				this.backgroundGradientColor2 = "#ffd500";
+				
+				this.foregroundColor = "#4d4d4d";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#4d4d4d";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#4d4d4d";
+				
+				break;
+			case "prusanky-black-on-yellow":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#ffd500";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffd500";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "prusanky-yellow-on-white":
+				this.backgroundGradientColor1 = "#ffd500";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "prusanky-white-on-yellow":
+				this.backgroundGradientColor1 = "#ffd500";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "ujezd-green-on-white":
+				this.backgroundGradientColor1 = "#8ed4a3";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#ffdd55";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "ujezd-white-on-green":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#8ed4a3";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#8ed4a3";
+				
+				this.nameBackgroundColor = "#ffdd55";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "cssd-red-on-black":
+				this.backgroundGradientColor1 = "#e63812";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "cssd-black-on-red":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#e63812";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "jilemnice-purple-on-black":
+				this.backgroundGradientColor1 = "#6e1646";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#000000";
+				this.nameTextColor = "#ffffff";
+				
+				break;
+			case "jilemnice-black-on-purple":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#6e1646";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#6e1646";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "novarole-white-on-green":
+				this.backgroundGradientColor1 = "#a9ce2d";
+				this.backgroundGradientColor2 = "#000000";
+				
+				this.foregroundColor = "#ffffff";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#ffffff";
+				
+				this.nameBackgroundColor = "#a9ce2d";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "novarole-green-on-white":
+				this.backgroundGradientColor1 = "#a9ce2d";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#000000";
+				this.primaryTextColor = "#ffffff";
+				
+				this.iconColor = "#000000";
+				
+				this.nameBackgroundColor = "#ffffff";
+				this.nameTextColor = "#000000";
+				
+				break;
+			case "novarole-green-on-black":
+				this.backgroundGradientColor1 = "#000000";
+				this.backgroundGradientColor2 = "#ffffff";
+				
+				this.foregroundColor = "#a9ce2d";
+				this.primaryTextColor = "#000000";
+				
+				this.iconColor = "#a9ce2d";
+				
+				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();
+		}
+	}
+}
diff --git a/generator/static/js/ui.js b/generator/static/js/ui.js
index 3743692f..5a689119 100644
--- a/generator/static/js/ui.js
+++ b/generator/static/js/ui.js
@@ -3,6 +3,7 @@ var template = null;
 const templateTypes = {
 	"bottom-slogan": BottomSloganTemplate,
 	"bottom-slogan-gradient": BottomSloganGradient,
+	"bottom-slogan-gradient-icon": BottomSloganGradientIcon,
 	"bottom-slogan-gradient-vertical-logo": BottomSloganGradientVerticalLogo,
 	"bottom-slogan-person": BottomSloganPerson,
 	"bottom-slogan-quote": BottomSloganQuote,
diff --git a/generator/templates/generator.html b/generator/templates/generator.html
index b4073532..412da903 100644
--- a/generator/templates/generator.html
+++ b/generator/templates/generator.html
@@ -47,6 +47,10 @@
 			type="text/javascript"
 			src="{{ url_for('static', filename='js/templates/bottom-slogan-gradient.js') }}"
 		></script>
+		<script
+			type="text/javascript"
+			src="{{ url_for('static', filename='js/templates/bottom-slogan-gradient-icon.js') }}"
+		></script>
 		<script
 			type="text/javascript"
 			src="{{ url_for('static', filename='js/templates/bottom-slogan-gradient-vertical-logo.js') }}"
@@ -492,6 +496,10 @@
 								data-image-source="static/images/examples/bottom-slogan-gradient.png"
 								data-template-type="bottom-slogan-gradient"
 							>Velký spodní slogan, gradient na pozadí</option>
+							<option
+								data-image-source="static/images/examples/bottom-slogan-gradient-icon.png"
+								data-template-type="bottom-slogan-gradient-icon"
+							>Velký spodní slogan, gradient na pozadí, ikona</option>
 							<option
 								data-image-source="static/images/examples/bottom-slogan-person.png"
 								data-template-type="bottom-slogan-person"
-- 
GitLab