<!DOCTYPE html>
<html>
    <head>
	<style>
	 form {
	     display: grid;
	     grid-template-columns: 30% 50%;
	 }
	 svg {
	     background: repeating-conic-gradient(#dddddd 0% 25%, #999999 0% 50%) 50% / 20px 20px;
	 }
	</style>
    </head>
    <body>
	<h1>Antifa Sticker Generator</h1>
        <p>
            A purely client-side sticker generator. <a href="https://git.kabelsalat.ch/s3lph/antifa-sticker-generator">Source Code.</a>
        </p>
	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500" id="svg">
	    <style>
	     text {
		 fill: white;
		 font-family: sans-serif;
		 font-weight: bold;
		 font-size: 40px;
		 text-align: center;
		 text-anchor: middle;
	     }
	    </style>
	    <defs>
		<filter id="black">
        	    <feColorMatrix in="SourceGraphic" type="matrix"
        			       values="1 0 0 0 0
        			       0 1 0 0 0
        			       0 0 1 0 0
        			       0 0 0 1 0" />
		</filter>
		<filter id="red">
        	    <feColorMatrix in="SourceGraphic" type="matrix"
        			       values="1 1 1 1 0
        			       0 0 0 0 0
        			       0 0 0 0 0
        			       0 0 0 1 0" />
		</filter>
		<path id="upper" stroke="red" fill="none" d="M 249.999 460 A 210 210 0 1 1 250.001 460" />
		<path id="lower" stroke="red" fill="none" d="M 249.999 10 A 240 240 0 1 0 250.001 10" />
	    </defs>
            <g id="svgroot" transform="scale(1, 1)">
	        <circle id="bleed" cx="250" cy="250" r="249" stroke="#ff00ff" fill="none" stroke-width="0" />
	        <circle cx="250" cy="250" r="225" stroke="black" fill="white" stroke-width="50" />
	        <g id="icon">
		    <image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconred" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik0xMjUuNjY3LDEyMi45MTdjMCwwLDI4LDMzLjA4Myw4OS4yNSwzNC4zMzNjNjEuMjUxLDEuMjUsOTUuOTE3LTM3LjkxNywxMzAuOTE3LTMzLjMzM3M2Myw0My4zMzMsNzcuNzUsNTAuMTY3TDMzMyw0MjUuNzUKICAgICAgICBjMCwwLTEuODMzLDEuMzM0LTExLDQuNjY3cy0xMS4zMzMsNC4zMzMtMTEuMzMzLDQuMzMzbDQwLjI1LTEyMi45MTdjMCwwLTM4Ljc1LTMyLjY4Ny03My43NS0zNQogICAgICAgIGMtMzUuMDAxLTIuMzEzLTUwLjkxNywyMy43NS0xMTAuMDgzLDEzLjc1QzEwNy45MTcsMjgwLjU4Myw2OS41LDI0My41LDY5LjUsMjQzLjVzLTEuNDE1LTIxLjA2NywxNC41LTU5LjgzMwogICAgICAgIEM5OS45MTQsMTQ0LjkwMiwxMjUuNjY3LDEyMi45MTcsMTI1LjY2NywxMjIuOTE3eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#red)" />
		    <image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconblack" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik02OS45MTcsMjUxLjI1YzAsMCw0MS4wODQsMzguNDE2LDEwMi40MTcsNDYuMDgzYzYxLjMzMiw3LjY2Nyw2Ny4wMzktMTQuNDkxLDEwMC45MTYtMTQuMjUKICAgICAgICBjMjEuNTQ4LDAuMTUzLDI5LjMzNCw5LjU4NCwyOS4zMzQsOS41ODRsLTUzLjUwNiwxNDkuNjdjMCwwLTQuMTgtMC4wNDQtMTAuMDkyLTAuNjkyYy01LjkxMS0wLjY0OC05LjU0MS0xLjI5NC05LjU0MS0xLjI5NAogICAgICAgIEwyNTcsMzU3LjVjMCwwLTEzLjU4NC04LjcwNy0yNy4yNS0xMC41Yy0xMy42NjgtMS43OTMtMjEuMDQyLDMtNDYuNSwyLjVjLTI0LjA3My0wLjQ3My03MS4yNS0xMi43NS05My4zMzMtNDUuNzUKICAgICAgICBTNjkuOTE3LDI1MS4yNSw2OS45MTcsMjUxLjI1eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#black)" />
	        </g>
	        <text><textPath id="uppertext" startOffset="50%" href="#upper">ANTIFASCHISTISCHE</textPath></text>
	        <text><textPath id="lowertext" startOffset="50%" href="#lower">AKTION</textPath></text>
            </g>
	</svg>
	<form>
	    <label for="input-text-upper">Upper text</label>
	    <input type="text" id="input-text-upper" name="upper" value="ANTIFASCHISTISCHE" />
	    <label for="input-text-lower">Lower text</label>
	    <input type="text" id="input-text-lower" name="lower" value="AKTION" />
	    <label for="input-range-shift-x">X Position</label>
	    <input type="range" id="input-range-position-x" name="position-x" value="-9" min="-500" max="500" />
	    <label for="input-range-shift-y">Y Position</label>
	    <input type="range" id="input-range-position-y" name="position-y" value="-2" min="-500" max="500" />
	    <label for="input-range-shift-x">X Shift</label>
	    <input type="range" id="input-range-shift-x" name="distance-x" value="0" min="-250" max="250" />
	    <label for="input-range-shift-y">Y Shift</label>
	    <input type="range" id="input-range-shift-y" name="distance-y" value="0" min="-250" max="250" />
	    <label for="input-range-scale-black">Black Scale</label>
	    <input type="range" id="input-range-scale-black" name="scale-black" value="0" min="-3" max="3" step="0.01" />
	    <label for="input-range-scale-red">Red Scale</label>
	    <input type="range" id="input-range-scale-red" name="scale-red" value="0" min="-3" max="3" step="0.01" />
	    <label for="input-file-icon">Black Icon (black+white+alpha only)</label>
	    <input type="file" id="input-file-icon-black" name="icon-black" accept="image/*" />
	    <label for="input-file-icon">Red Icon (black+white+alpha only)</label>
	    <input type="file" id="input-file-icon-red" name="icon-red" accept="image/*" />
	    <label for="input-range-bleed">Bleed (black in download)</label>
	    <input type="range" id="input-range-bleed" name="bleed" value="0" min="0" max="50" />
	    <div>
		<input type="checkbox" id="input-check-swap-red-black" name="swap-red-black" />
		<label for="input-check-swap-red-black">Red on top of black</label>
		<input type="checkbox" id="input-check-lock-scale" name="lock-scale" />
		<label for="input-check-lock-scale">Same scale for red and black</label>
	    </div>
            <div>
	        <input type="button" id="input-button-download" value="Download SVG" />
	        <input type="button" id="input-button-download-png" value="Download PNG" />
            </div>
	    <label for="input-file-import-svg">Import downloaded SVG</label>
	    <input type="file" id="input-file-import-svg" name="import-svg" accept="image/svg+xml" />
	</form>
	<a id="download" download="antifa.svg" filename="antifa.svg"></a>
	<a id="download-png" download="antifa.png" filename="antifa.png"></a>
	<script>
	 let doc = document.getElementById('svg');
	 let inputTextUpper = document.getElementById("input-text-upper");
	 let inputTextLower = document.getElementById("input-text-lower");
	 let inputRangePositionX = document.getElementById("input-range-position-x");
	 let inputRangePositionY = document.getElementById("input-range-position-y");
	 let inputRangeShiftX = document.getElementById("input-range-shift-x");
	 let inputRangeShiftY = document.getElementById("input-range-shift-y");
	 let inputRangeScaleBlack = document.getElementById("input-range-scale-black");
	 let inputRangeScaleRed = document.getElementById("input-range-scale-red");
	 let inputFileIconBlack = document.getElementById("input-file-icon-black");
	 let inputFileIconRed = document.getElementById("input-file-icon-red");
	 let inputCheckSwap = document.getElementById("input-check-swap-red-black");
	 let inputCheckLockScale = document.getElementById("input-check-lock-scale");
	 let inputRangeBleed = document.getElementById("input-range-bleed");
	 let inputButtonDownload = document.getElementById("input-button-download");
	 let inputButtonDownloadPng = document.getElementById("input-button-download-png");
	 let inputFileImportSvg = document.getElementById("input-file-import-svg");
	 inputTextUpper.oninput = (ev) => {
	     doc.getElementById("uppertext").textContent = inputTextUpper.value;
	 };
	 inputTextLower.oninput = (ev) => {
	     doc.getElementById("lowertext").textContent = inputTextLower.value;
	 };
	 inputRangePositionX.oninput = (ev) => {
	     doc.getElementById("iconblack").transform.baseVal[1].matrix.e = inputRangePositionX.value;
	     doc.getElementById("iconred").transform.baseVal[1].matrix.e = inputRangePositionX.value;
	 };
	 inputRangePositionY.oninput = (ev) => {
	     doc.getElementById("iconblack").transform.baseVal[1].matrix.f = inputRangePositionY.value;
	     doc.getElementById("iconred").transform.baseVal[1].matrix.f = inputRangePositionY.value;
	 };
	 inputRangeShiftX.oninput = (ev) => {
	     doc.getElementById("iconblack").transform.baseVal[0].matrix.e = inputRangeShiftX.value;
	     doc.getElementById("iconred").transform.baseVal[0].matrix.e = -inputRangeShiftX.value;
	 };
	 inputRangeShiftY.oninput = (ev) => {
	     doc.getElementById("iconblack").transform.baseVal[0].matrix.f = inputRangeShiftY.value;
	     doc.getElementById("iconred").transform.baseVal[0].matrix.f = -inputRangeShiftY.value;
	 };
	 inputRangeScaleBlack.oninput = (ev) => {
	     let iconblack = doc.getElementById("iconblack");
	     iconblack.transform.baseVal[2].matrix.a = Math.pow(10, inputRangeScaleBlack.value);
	     iconblack.transform.baseVal[2].matrix.d = Math.pow(10, inputRangeScaleBlack.value);
	     if (inputCheckLockScale.checked) {
		 let iconred = doc.getElementById("iconred");
		 iconred.transform.baseVal[2].matrix.a = Math.pow(10, inputRangeScaleBlack.value);
		 iconred.transform.baseVal[2].matrix.d = Math.pow(10, inputRangeScaleBlack.value);
	     }
	 };
	 inputRangeScaleRed.oninput = (ev) => {
	     let iconred = doc.getElementById("iconred");
	     iconred.transform.baseVal[2].matrix.a = Math.pow(10, inputRangeScaleRed.value);
	     iconred.transform.baseVal[2].matrix.d = Math.pow(10, inputRangeScaleRed.value);
	 };
	 inputFileIconBlack.onchange = (ev) => {
	     let file = ev.target.files[0];
	     let reader = new FileReader();
	     let iconblack = doc.getElementById("iconblack");
	     reader.onload = (re) => {
		 let img = new Image();
		 img.onload = (i) => {
		     iconblack.href.baseVal = re.target.result;
		     iconblack.width.baseVal.value = i.path[0].width;
		     iconblack.height.baseVal.value = i.path[0].height;
		 };
		 img.src = re.target.result;
	     };
	     reader.readAsDataURL(file);
	 };
	 inputFileIconRed.onchange = (ev) => {
	     let file = ev.target.files[0];
	     let reader = new FileReader();
	     let iconred = doc.getElementById("iconred");
	     reader.onload = (re) => {
		 let img = new Image();
		 img.onload = (i) => {
		     iconred.href.baseVal = re.target.result;
		     iconred.width.baseVal.value = i.path[0].width;
		     iconred.height.baseVal.value = i.path[0].height;
		 };
		 img.src = re.target.result;
	     };
	     reader.readAsDataURL(file);
	 };
	 inputCheckSwap.onchange = (ev) => {
	     if (ev.target.checked) {
		 doc.getElementById("icon").insertBefore(doc.getElementById("iconblack"), doc.getElementById("iconred"));
	     } else {
		 doc.getElementById("icon").insertBefore(doc.getElementById("iconred"), doc.getElementById("iconblack"));
	     }
	 };
	 inputCheckLockScale.onchange = (ev) => {
	     inputRangeScaleRed.disabled = ev.target.checked;
	     let iconred = doc.getElementById("iconred");
	     if (ev.target.checked) {
		 iconred.transform.baseVal[2].matrix.a = Math.pow(10, inputRangeScaleBlack.value);
		 iconred.transform.baseVal[2].matrix.d = Math.pow(10, inputRangeScaleBlack.value);
	     } else {
		 iconred.transform.baseVal[2].matrix.a = Math.pow(10, inputRangeScaleRed.value);
		 iconred.transform.baseVal[2].matrix.d = Math.pow(10, inputRangeScaleRed.value);		     
	     }
	 }
	 inputRangeBleed.oninput = (ev) => {
	     let bleed = doc.getElementById("bleed");
	     let bleedVal = parseInt(inputRangeBleed.value);
	     if (bleedVal == 0) {
		 bleed.style.strokeWidth = 0;
	     } else {
		 bleed.style.strokeWidth = bleedVal * 2 + 1;
	     }
	     doc.width.baseVal.value = 500 + bleedVal * 2;
	     doc.height.baseVal.value = 500 + bleedVal * 2;
	     doc.viewBox.baseVal.x = -bleedVal;
	     doc.viewBox.baseVal.y = -bleedVal;
	     doc.viewBox.baseVal.width = 500 + bleedVal * 2;
	     doc.viewBox.baseVal.height = 500 + bleedVal * 2;
	 };
	 inputButtonDownload.onclick = (ev) => {
	     doc.getElementById("bleed").style.stroke = 'black';
	     let serialized = new XMLSerializer().serializeToString(doc);
	     doc.getElementById("bleed").style.stroke = '#ff00ff';
	     let a = document.getElementById('download');
	     a.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(serialized));
	     a.click();
	 };
	 inputButtonDownloadPng.onclick = (ev) => {
             let svgSize = doc.width.baseVal.value;
             let svgOffset = doc.viewBox.baseVal.x;
             let imgSize = parseInt(prompt("Enter image size (e.g. 2048)", "2048"));
             let svgRoot = doc.getElementById("svgroot");
             if (Number.isNaN(imgSize)) {
                 return;
             }
             // Resize SVG to output size, then export as XML, and resize back to default size
	     doc.getElementById("bleed").style.stroke = 'black';
             doc.width.baseVal.value = imgSize;
             doc.height.baseVal.value = imgSize;
             doc.viewBox.baseVal.width = imgSize;
             doc.viewBox.baseVal.height = imgSize;
             doc.viewBox.baseVal.x = svgOffset * imgSize/svgSize;
             doc.viewBox.baseVal.y = svgOffset * imgSize/svgSize;
             svgRoot.transform.baseVal[0].matrix.a = imgSize/svgSize;
             svgRoot.transform.baseVal[0].matrix.d = imgSize/svgSize;
	     let serialized = new XMLSerializer().serializeToString(doc);
	     doc.getElementById("bleed").style.stroke = '#ff00ff';
             svgRoot.transform.baseVal[0].matrix.a = 1;
             svgRoot.transform.baseVal[0].matrix.d = 1;
             doc.viewBox.baseVal.width = svgSize;
             doc.viewBox.baseVal.height = svgSize;
             doc.viewBox.baseVal.x = svgOffset;
             doc.viewBox.baseVal.y = svgOffset;
             doc.width.baseVal.value = svgSize;
             doc.height.baseVal.value = svgSize;
             
             let canvas = document.createElement('canvas');
             canvas.width = imgSize;
             canvas.height = imgSize;
             let ctx = canvas.getContext("2d");
             let image = new Image();
             image.onload = () => {
                 ctx.drawImage(image, 0, 0);
	         let a = document.getElementById('download-png');
	         a.setAttribute('href', canvas.toDataURL());
	         a.click();
             };
             image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(serialized);
	 };
	 inputFileImportSvg.onchange = (ev) => {
	     let file = ev.target.files[0];
	     let reader = new FileReader();
	     reader.onload = (re) => {
		 let parser = new DOMParser();
		 let imp = parser.parseFromString(re.target.result, 'image/svg+xml');
		 let iconblack = doc.getElementById('iconblack');
		 let iconred = doc.getElementById('iconred');
		 // texts
		 inputTextUpper.value = imp.getElementById('uppertext').textContent;
		 inputTextLower.value = imp.getElementById('lowertext').textContent;
		 doc.getElementById('uppertext').textContent = inputTextUpper.value;
		 doc.getElementById('lowertext').textContent = inputTextLower.value;
		 // img href
		 iconblack.href.baseVal = imp.getElementById('iconblack').href.baseVal;
		 iconred.href.baseVal = imp.getElementById('iconred').href.baseVal;
		 // shift
		 inputRangeShiftX.value = imp.getElementById('iconblack').transform.baseVal[0].matrix.e;
		 inputRangeShiftY.value = imp.getElementById('iconblack').transform.baseVal[0].matrix.f;
		 iconblack.transform.baseVal[0].matrix.e = inputRangeShiftX.value;
		 iconred.transform.baseVal[0].matrix.e = -inputRangeShiftX.value;
		 iconblack.transform.baseVal[0].matrix.f = inputRangeShiftY.value;
		 iconred.transform.baseVal[0].matrix.f = -inputRangeShiftY.value;
		 // position
		 inputRangePositionX.value = imp.getElementById('iconblack').transform.baseVal[1].matrix.e;
		 inputRangePositionY.value = imp.getElementById('iconblack').transform.baseVal[1].matrix.f;
		 iconblack.transform.baseVal[1].matrix.e = inputRangePositionX.value;
		 iconred.transform.baseVal[1].matrix.e = inputRangePositionX.value;
		 iconblack.transform.baseVal[1].matrix.f = inputRangePositionY.value;
		 iconred.transform.baseVal[1].matrix.f = inputRangePositionY.value;
		 // scale
		 let scaleBlack = imp.getElementById('iconblack').transform.baseVal[2].matrix.a;
		 let scaleRed = imp.getElementById('iconred').transform.baseVal[2].matrix.a;
		 inputRangeScaleBlack.value = Math.log10(scaleBlack);
		 inputRangeScaleRed.value = Math.log10(scaleRed);
		 iconblack.transform.baseVal[2].matrix.a = scaleBlack;
		 iconblack.transform.baseVal[2].matrix.d = scaleBlack;
		 iconred.transform.baseVal[2].matrix.a = scaleRed;
		 iconred.transform.baseVal[2].matrix.d = scaleRed;
		 // swap
		 if (imp.getElementById('icon').children[0].id == 'iconblack') {
		     inputCheckSwap.checked = true;
		     doc.getElementById('icon').insertBefore(doc.getElementById('iconblack'), doc.getElementById('iconred'));
		 } else {
		     inputCheckSwap.checked = false;
		     doc.getElementById('icon').insertBefore(doc.getElementById('iconred'), doc.getElementById('iconblack'));
		 }
		 // bleed
		 inputRangeBleed.value = Math.max(imp.getElementById('bleed').style.strokeWidth - 1, 0);
		 let bleed = doc.getElementById("bleed");
		 let bleedVal = parseInt(inputRangeBleed.value);
		 if (bleedVal == 0) {
		     bleed.style.strokeWidth = 0;
		 } else {
		     bleed.style.strokeWidth = bleedVal * 2 + 1;
		 }
		 doc.width.baseVal.value = 500 + bleedVal * 2;
		 doc.height.baseVal.value = 500 + bleedVal * 2;
		 doc.viewBox.baseVal.x = -bleedVal;
		 doc.viewBox.baseVal.y = -bleedVal;
		 doc.viewBox.baseVal.width = 500 + bleedVal * 2;
		 doc.viewBox.baseVal.height = 500 + bleedVal * 2;
	     };
	     reader.readAsText(file);		 
	 };
	</script>
    </body>
</html>