Skip to content
Snippets Groups Projects
Select Git revision
  • 07a873702a303d8ccfd028e8279df5bd3b993580
  • master default protected
2 results

komise.js

Blame
  • user avatar
    Tomáš Hozman authored
    07a87370
    History
    komise.js 22.81 KiB
    class Komise extends Template {
    	description = "Určeno pro sociální sítě.";
    	
    	changeableAttributes = [
    		"logoImage",
    		"logoIsCenter",
    		"primaryImage",
    		"primaryText",
    		"secondaryText",
    		"nameText",
    		"underNameText",
    		"primaryColorScheme",
    		"primaryImagePosition",
    		"iconImage"
    	];
    
    	primaryColorSchemes = [
    		"black-on-white",
    		"white-on-black"
    	];
    	
    	primaryTextHighlightColorSchemes = [
    		"black-on-gold"
    	];
    	
    	changeableColors = [
    		"primaryTextColor",
    		"foregroundColor",
    		"primaryTextHighlightColor",
    		"requesterTextColor"
    	];
    	
    	iconImage = null;
    	iconSource = "";
    	
    	logoIsCenter = false;
    	
    	aspectRatio = 1;
    	defaultResolution = 2000;
    	
    	secondaryText = "";
    	underNameText = "";
    
    	// Canvas
    	async redrawCanvas() {
    		if (this.redrawing) {
    			return;
    		}
    
    		this.redrawing = true;
    		
    		const primaryRectangleAngle = Math.ceil(this.canvas.height * 0.015);
    		const primaryRectanglePaddingBottom = Math.ceil(this.canvas.height * 0.01);
    		const primaryRectanglePaddingTop = 0;
    		const primaryRectangleAdditionalPaddingWithDiacritics = Math.ceil(this.canvas.height * 0.01);
    		const primaryRectanglePaddingSides = Math.ceil(this.canvas.width * 0.1);
    
    		const highlightPaddingSides = Math.ceil(this.canvas.width * 0.01);
    		const highlightPaddingBottom = Math.ceil(this.canvas.height * 0.0125);
    		const highlightPaddingTop = Math.ceil(this.canvas.height * -0.01); // It is, it's how Roboto works.
    
    		const logoHeight = Math.ceil(this.canvas.height * 0.055) * this.logoImageZoom;
    		const logoBottomOffset = Math.ceil(this.canvas.height * 0.06) - (
    			logoHeight / this.logoImageZoom * (this.logoImageZoom - 1) / 2
    		);
    		
    		const logoTextOffsetSide = Math.ceil(this.canvas.width * 0.1);
    		
    		const nameTextOffsetBottom = Math.ceil(this.canvas.height * 0.08);
    		
    		let primaryFontSize = Math.ceil(this.canvas.height * 0.13);
    		const primaryFontLinePadding = 0;
    		const primaryTextMaxLines = 3;
    		const primaryTextPaddingBottom = Math.ceil(this.canvas.height * 0.17);
    		
    		let secondaryFontSize = Math.ceil(this.canvas.height * 0.06);
    		const secondaryTextPaddingBottom = Math.ceil(this.canvas.height * 0.04);
    		
    		let nameFontSize = Math.ceil(this.canvas.height * 0.028);
    		let underNameFontSize = Math.ceil(this.canvas.height * 0.018);
    		const nameMaxArea = Math.ceil(this.canvas.width * 0.24);
    		
    		const iconImageOffset = Math.ceil(this.canvas.height * 0.03);
    		const iconOpacity = 0.125;
    		
    		// Get primary text split into lines, no more than ``primaryTextMaxLines`` of them
    		
    		let primaryTextLines = null;
    		
    		do {
    			this.context.font = `${this.primaryFontStyle} ${primaryFontSize}px ${this.primaryFont}`;
    
    			primaryTextLines = splitStringIntoLines(
    				this.context,
    				this.primaryText,
    				this.canvas.width - primaryRectanglePaddingSides * 2,
    				primaryTextMaxLines,
    				true
    			).reverse();
    
    			if (primaryTextLines.length > primaryTextMaxLines) {
    				primaryFontSize -= 2;
    			}
    		} while (primaryTextLines.length > primaryTextMaxLines);
    
    		// 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
    		}
    		
    		const firstPrimaryLine = primaryTextLines[primaryTextLines.length - 1].join(" ");
    		
    		// Create rectangle behind the primary text
    		const primaryRectangleHeight = (
    			primaryTextLines.length * (primaryFontSize + primaryFontLinePadding)
    			+ primaryRectanglePaddingTop
    			+ primaryRectanglePaddingBottom
    			+ primaryTextPaddingBottom
    			+ (
    				(
    					firstPrimaryLine.replace(/[a-zA-Z0-9À-ž]+/g, "").length
    					!== firstPrimaryLine.replace(/[a-zA-Z0-9]+/g, "").length
    				) ?
    				primaryRectangleAdditionalPaddingWithDiacritics :
    				0
    			)
    		);
    		
    		const classRef = this;
    		
    		// Create background gradient
    		const gradientLoadPromise = new Promise(
    			resolve => {
    				const gradientImage = new Image();
    				
    				gradientImage.onload = function() {
    					classRef.context.drawImage(
    						this,
    						0, 0,
    						classRef.canvas.width, classRef.canvas.height - primaryRectangleHeight
    					);
    					
    					resolve();
    				}
    				
    				gradientImage.src = "static/images/gradient.png";
    			}
    		);
    		
    		await gradientLoadPromise;
    		
    		if (this.secondaryText !== "") {
    			this.context.textAlign = "center";
    			this.context.font = `${secondaryFontSize}px ${this.primaryFont}`;
    			
    			while (
    				this.context.measureText(this.secondaryText).width
    				> (this.canvas.width - 2 * primaryRectanglePaddingSides)
    			) {
    				secondaryFontSize -= 2;
    				this.context.font = `${secondaryFontSize}px ${this.primaryFont}`;
    			}
    			
    			this.context.fillStyle = this.secondaryTextColor;
    			
    			this.context.fillText(
    				this.secondaryText,
    				this.canvas.width / 2, this.canvas.height - primaryRectangleHeight - secondaryTextPaddingBottom
    			);
    		}
    		
    		this.context.font = `${this.primaryFontStyle} ${primaryFontSize}px ${this.primaryFont}`;
    		
    		const foregroundRGB = hexToRgb(this.foregroundColor);
    		const foregroundLightness = (
    			0.2126 * foregroundRGB.r
    			+ 0.7152 * foregroundRGB.g
    			+ 0.0722 * foregroundRGB.b
    		)
    		
    		this.context.beginPath();
    		
    		const primaryRectangleStartingX = 0;
    		const primaryRectangleEndingX = this.canvas.width;
    		
    		this.context.fillStyle = this.foregroundColor;
    		
    		this.context.moveTo(
    			0,
    			this.canvas.height
    		);
    		this.context.lineTo(
    			this.canvas.width,
    			this.canvas.height
    		);
    		this.context.lineTo(
    			this.canvas.width,
    			this.canvas.height - primaryRectangleHeight - primaryRectangleAngle
    		);
    		this.context.lineTo(
    			0,
    			this.canvas.height - primaryRectangleHeight
    		);
    		
    		this.context.closePath();
    		
    		this.context.fill();
    		
    		function drawIconImage(image) {
    			const iconHeight = primaryRectangleHeight - 2 * iconImageOffset;
    			const iconWidth = (image.width * (iconHeight / image.height));
    			
    			classRef.context.globalAlpha = iconOpacity;
    			
    			const primaryTextRGB = hexToRgb(classRef.primaryTextColor);
    			
    			classRef.context.drawImage(
    				colorizeImage(
    					image,
    					iconWidth, iconHeight,
    					primaryTextRGB.r,
    					primaryTextRGB.g,
    					primaryTextRGB.b
    				),
    				iconImageOffset, classRef.canvas.height - iconImageOffset - iconHeight,
    				iconWidth, iconHeight
    			);
    			
    			classRef.context.globalAlpha = 1;
    		}
    		
    		// Create icon, if there is one
    		if (this.iconImage !== null) {
    			drawIconImage(this.iconImage);
    		} else if (this.iconSource !== null) {
    			const iconImageLoadPromise = new Promise(
    				resolve => {
    					const iconImage = new Image();
    					
    					iconImage.onload = function() {
    						drawIconImage(this);
    						
    						resolve();
    					}
    					
    					iconImage.src = this.iconSource;
    				}
    			);
    			
    			await iconImageLoadPromise;
    		}
    		
    		// Create primary text
    		this.context.textAlign = "left";
    		
    		const useLightHighlightAndUseDarkLogo = (foregroundLightness > 207);
    		
    		const primaryLineX = this.canvas.width / 2;
    		let currentPrimaryLineY = (
    			this.canvas.height
    			- primaryRectanglePaddingBottom
    			- primaryFontLinePadding
    			- primaryTextPaddingBottom
    		);
    		
    		let primaryTextHighlightedColor = null;
    		
    		const lowercasePrimaryTextHighlightColor = this.primaryTextHighlightColor.toLowerCase();
    		const hasColorOverride = (
    			lowercasePrimaryTextHighlightColor === "#209a37" ||
    			lowercasePrimaryTextHighlightColor === "#e63812"
    		);
    		
    		if (hasColorOverride) {
    			if (useLightHighlightAndUseDarkLogo) {
    				primaryTextHighlightedColor = this.foregroundColor;
    			} else {
    				primaryTextHighlightedColor = this.primaryTextColor;
    			}
    		} else if (!useLightHighlightAndUseDarkLogo) {
    			primaryTextHighlightedColor = this.foregroundColor;
    		} else {
    			primaryTextHighlightedColor = this.primaryTextColor;
    		}
    		
    		this.context.fillStyle = this.primaryTextColor;
    		
    		for (let line of primaryTextLines) {
    			let wordPosition = 0;
    			
    			for (let word of line) {
    				const previousWords = line.slice(0, wordPosition).join(" ");
    				const previousWordsWidth = this.context.measureText(
    					previousWords
    					+ (
    						(previousWords.length !== 0) ?
    						" " : ""
    					)
    				).width;
    				
    				const nextWords = line.slice(wordPosition + 1, line.length).join(" ")
    				const nextWordsWidth = this.context.measureText(
    					nextWords
    					+ (
    						(nextWords.length !== 0) ?
    						" " : ""
    					)
    				).width;
    				
    				let currentWordWidth = this.context.measureText(word).width;
    				
    				for (const word of line.slice(wordPosition + 1, line.length)) {
    					if (word.isHighlighted) {
    						currentWordWidth += this.context.measureText(word.toString() + " ").width;
    					} else {
    						break;
    					}
    				}
    				
    				if (word.isHighlighted) {
    					if (
    						wordPosition === 0 ||
    						!line[wordPosition - 1].isHighlighted
    					) {
    						this.context.fillStyle = this.primaryTextHighlightColor;
    						this.context.beginPath();
    						
    						const startingHighlightLineX = (
    							primaryLineX
    							+ Math.ceil(previousWordsWidth / 2)
    							- Math.ceil(nextWordsWidth / 2)
    							- Math.ceil(this.context.measureText(word).width / 2)
    						);
    						
    						this.context.moveTo(
    							startingHighlightLineX - highlightPaddingSides,
    							currentPrimaryLineY + highlightPaddingBottom
    						);
    						this.context.lineTo(
    							(
    								startingHighlightLineX
    								+ currentWordWidth
    								+ highlightPaddingSides
    							),
    							(
    								currentPrimaryLineY
    								+ highlightPaddingBottom
    								- Math.max(
    									(currentWordWidth * primaryRectangleAngle)
    									/ (this.canvas.width - 2 * primaryRectanglePaddingSides)
    								)
    							)
    						);
    						this.context.lineTo(
    							(
    								startingHighlightLineX
    								+ currentWordWidth
    								+ highlightPaddingSides
    							),
    							(
    								currentPrimaryLineY
    								- primaryFontSize
    								- highlightPaddingTop
    								- Math.max(
    									(currentWordWidth * primaryRectangleAngle)
    									/ (this.canvas.width - 2 * primaryRectanglePaddingSides)
    								)
    							)
    						);
    						this.context.lineTo(
    							startingHighlightLineX - highlightPaddingSides,
    							(
    								currentPrimaryLineY
    								- primaryFontSize
    								- highlightPaddingTop
    							)
    						);
    						
    						this.context.closePath();
    						
    						this.context.fill();
    					}
    					
    					this.context.fillStyle = primaryTextHighlightedColor;
    				}
    				
    				this.context.fillText(
    					word + " ",
    					(
    						primaryLineX
    						+ Math.ceil(previousWordsWidth / 2)
    						- Math.ceil(nextWordsWidth / 2)
    						- Math.ceil(this.context.measureText(word).width / 2)
    					),
    					currentPrimaryLineY
    				);
    				
    				wordPosition++;
    				
    				this.context.fillStyle = this.primaryTextColor;
    			}
    			
    			currentPrimaryLineY -= (primaryFontSize + primaryFontLinePadding);
    		}
    		
    		this.context.textAlign = "center";
    		
    		// Create name, if not empty
    		if (this.nameText !== "") {
    			// Create rectangle for name text
    			this.context.font = `bold ${nameFontSize}px 'Roboto Condensed'`;
    			
    			while (this.context.measureText(this.nameText).width > nameMaxArea) {
    				nameFontSize -= 2;
    				this.context.font = `bold ${nameFontSize}px 'Roboto Condensed'`;
    			}
    			
    			this.context.textAlign = "left";
    			
    			// Create name text itself
    			this.context.fillStyle = this.primaryTextColor;
    			this.context.fillText(
    				this.nameText,
    				logoTextOffsetSide, this.canvas.height - nameTextOffsetBottom
    			);
    			
    			if (this.underNameText !== "") {
    				this.context.font = `${underNameFontSize}px 'Roboto Condensed'`;
    				
    				while (this.context.measureText(this.underNameText).width > nameMaxArea) {
    					underNameFontSize -= 2;
    					this.context.font = `${underNameFontSize}px 'Roboto Condensed'`;
    				}
    				
    				this.context.fillText(
    					this.underNameText,
    					logoTextOffsetSide, this.canvas.height - nameTextOffsetBottom + nameFontSize
    				);
    			}
    		}
    
    		function drawLogoImage(image) {
    			const logoWidth = Math.ceil(image.width * (logoHeight / image.height));
    
    			classRef.context.drawImage(
    				image,
    				(
    					(!classRef.logoIsCenter) ?
    					classRef.canvas.width - logoWidth - logoTextOffsetSide :
    					(classRef.canvas.width - logoWidth) / 2
    				), classRef.canvas.height - logoHeight - logoBottomOffset,
    				logoWidth, logoHeight
    			);
    		}
    
    		if (this.logoImage === null) {
    			const logoImageLoadPromise = new Promise(
    				resolve => {
    					let logoImage = new Image();
    					
    					logoImage.onload = function() {
    						drawLogoImage(this);
    						
    						resolve();
    					}
    					
    					if (!useLightHighlightAndUseDarkLogo) {
    						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.0175);
    			
    			do {
    				this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
    				
    				if (
    					this.context.measureText(this.requesterText).width
    					> primaryRectangleHeight - (this.canvas.height * 0.03)
    				) {
    					requesterFontSize -= 2;
    					this.context.font = `${this.primaryFontStyle} ${requesterFontSize}px ${this.primaryFont}`;
    				}
    			} while (
    				this.context.measureText(this.requesterText).width
    				> primaryRectangleHeight - (this.canvas.height * 0.03)
    			);
    			
    			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.99 + requesterFontSize
    			);
    			this.context.globalAlpha = 1;
    			
    			this.context.restore();
    		}
    		this.finalDrawHook();
    		this.stickerDrawHook();
    		
    		this.redrawing = false;
    	}
    	
    	// Text
    	async setSecondaryText(text, skipRedraw = false) {
    		this.secondaryText = text;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	async setUnderNameText(text, skipRedraw = false) {
    		this.underNameText = text;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	// Icon
    	async setIconSource(url, skipRedraw = false) {
    		this.iconSource = url;
    		
    		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;
    	}
    	
    	async resetIconImage(skipRedraw = false) {
    		this.iconImage = null;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	// Color schemes
    	async setPrimaryColorScheme(scheme, skipRedraw = false) {
    		switch (scheme) {
    			case "black-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "white-on-black":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor ="#000000";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "forum-black-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "forum-white-on-purple":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#962a51";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "zeleni-volary-bystrc-most-black-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "zeleni-volary-bystrc-most-white-on-green":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#00ad43";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "spolecne-s-piraty-black-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "spolecne-s-piraty-white-on-blue":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#21274e";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "louny-spolecne-black-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "louny-spolecne-white-on-purple":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#3e2a5b";
    				
    				this.setPrimaryTextHighlightColorScheme("gold", true);
    				
    				break;
    			case "litomerice-blue-on-white":
    				this.primaryTextColor = "#123172";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				
    				this.setPrimaryTextHighlightColorScheme("litomerice", true);
    				
    				break;
    			case "litomerice-white-on-blue":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#123172";
    				
    				this.setPrimaryTextHighlightColorScheme("litomerice", true);
    				
    				break;
    			case "stranane-gray-on-yellow":
    				this.primaryTextColor = "#4d4d4d";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffd500";
    				
    				break;
    			case "stranane-yellow-on-white":
    				this.primaryTextColor = "#4d4d4d";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffd500";
    				this.primaryTextHighlightColor = "#4d4d4d";
    				
    				break;
    			case "stranane-white-on-yellow":
    				this.primaryTextColor = "#4d4d4d";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				this.primaryTextHighlightColor = "#ffd500";
    				
    				break;
    			case "prusanky-black-on-yellow":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffd500";
    				
    				break;
    			case "prusanky-yellow-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffd500";
    				this.primaryTextHighlightColor = "#000000";
    				
    				break;
    			case "prusanky-white-on-yellow":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				this.primaryTextHighlightColor = "#ffd500";
    				
    				break;
    			case "ujezd-green-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#8ed4a3";
    				this.primaryTextHighlightColor = "#ffdd55";
    				
    				break;
    			case "ujezd-white-on-green":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				this.primaryTextHighlightColor = "#8ed4a3";
    				
    				break;
    			case "cssd-red-on-black":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#e63812";
    				
    				break;
    			case "cssd-black-on-red":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#000000";
    				
    				break;
    			case "jilemnice-purple-on-black":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#6e1646";
    				
    				break;
    			case "jilemnice-black-on-purple":
    				this.primaryTextColor = "#ffffff";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#000000";
    				
    				break;
    			case "novarole-white-on-green":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#ffffff";
    				this.primaryTextHighlightColor = "#a9ce2d";
    				
    				break;
    			case "novarole-green-on-white":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#a9ce2d";
    				
    				this.primaryTextHighlightColor = "#ffcc00";
    				
    				break;
    			case "novarole-green-on-black":
    				this.primaryTextColor = "#000000";
    				this.secondaryTextColor = "#ffffff";
    				this.foregroundColor = "#a9ce2d";
    				
    				this.primaryTextHighlightColor = "#ffcc00";
    				
    				break;
    			case "zeleni-melnik-yellow-name-rect":
    				await this.setPrimaryColorScheme("white-on-black", true);
    				
    				break;
    			default:
    				throw new Error("This scheme does not exist.");
    				break;
    		}
    		
    		this.requesterTextColor = this.primaryTextColor;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    
    	async setPrimaryTextHighlightColorScheme(scheme, skipRedraw = false) {
    		switch(scheme) {
    			case "gold":
    				this.primaryTextHighlightColor = "#ffcc00";
    				break;
    			case "litomerice":
    				this.primaryTextHighlightColor = "#afe87e";
    				break;
    			default:
    				throw new Error("This scheme does not exist.");
    				break;
    		}
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	async setPrimaryTextHighlightColor(color, skipRedraw = false) {
    		this.primaryTextHighlightColor = color;
    		
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	async setLogoIsCenter(isCenter, skipRedraw = false) {
    		this.logoIsCenter = isCenter;
    
    		if (!skipRedraw) {
    			await this.redrawCanvas();
    		}
    	}
    	
    	async loadData(
    		primaryImageInput = null,
    		primaryText = "",
    		nameText = "",
    		primaryColorScheme = "",
    		resultion = 2000,
    		skipRedraw = false
    	) {
    		await super.loadData(
    			primaryImageInput,
    			primaryText,
    			nameText,
    			primaryColorScheme,
    			resultion,
    			skipRedraw
    		);
    		
    		$("#icon-image-selection").val("Otevřená radnice 1");
    		$("#icon-image-selection").trigger("change");
    	}
    }