diff --git a/.gitignore b/.gitignore index a23f41f..d6115cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /checkwave -/kemonogen /shape_shifter diff --git a/kemonogen/FileSaver.js b/kemonogen/FileSaver.js new file mode 100644 index 0000000..fb71494 --- /dev/null +++ b/kemonogen/FileSaver.js @@ -0,0 +1,188 @@ +/* FileSaver.js + * A saveAs() FileSaver implementation. + * 1.3.2 + * 2016-06-16 18:25:19 + * + * By Eli Grey, http://eligrey.com + * License: MIT + * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md + */ + +/*global self */ +/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ + +/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ + +var saveAs = saveAs || (function(view) { + "use strict"; + // IE <10 is explicitly unsupported + if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { + return; + } + var + doc = view.document + // only get URL when necessary in case Blob.js hasn't overridden it yet + , get_URL = function() { + return view.URL || view.webkitURL || view; + } + , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") + , can_use_save_link = "download" in save_link + , click = function(node) { + var event = new MouseEvent("click"); + node.dispatchEvent(event); + } + , is_safari = /constructor/i.test(view.HTMLElement) || view.safari + , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) + , throw_outside = function(ex) { + (view.setImmediate || view.setTimeout)(function() { + throw ex; + }, 0); + } + , force_saveable_type = "application/octet-stream" + // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to + , arbitrary_revoke_timeout = 1000 * 40 // in ms + , revoke = function(file) { + var revoker = function() { + if (typeof file === "string") { // file is an object URL + get_URL().revokeObjectURL(file); + } else { // file is a File + file.remove(); + } + }; + setTimeout(revoker, arbitrary_revoke_timeout); + } + , dispatch = function(filesaver, event_types, event) { + event_types = [].concat(event_types); + var i = event_types.length; + while (i--) { + var listener = filesaver["on" + event_types[i]]; + if (typeof listener === "function") { + try { + listener.call(filesaver, event || filesaver); + } catch (ex) { + throw_outside(ex); + } + } + } + } + , auto_bom = function(blob) { + // prepend BOM for UTF-8 XML and text/* types (including HTML) + // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF + if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { + return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); + } + return blob; + } + , FileSaver = function(blob, name, no_auto_bom) { + if (!no_auto_bom) { + blob = auto_bom(blob); + } + // First try a.download, then web filesystem, then object URLs + var + filesaver = this + , type = blob.type + , force = type === force_saveable_type + , object_url + , dispatch_all = function() { + dispatch(filesaver, "writestart progress write writeend".split(" ")); + } + // on any filesys errors revert to saving with object URLs + , fs_error = function() { + if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { + // Safari doesn't allow downloading of blob urls + var reader = new FileReader(); + reader.onloadend = function() { + var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); + var popup = view.open(url, '_blank'); + if(!popup) view.location.href = url; + url=undefined; // release reference before dispatching + filesaver.readyState = filesaver.DONE; + dispatch_all(); + }; + reader.readAsDataURL(blob); + filesaver.readyState = filesaver.INIT; + return; + } + // don't create more object URLs than needed + if (!object_url) { + object_url = get_URL().createObjectURL(blob); + } + if (force) { + view.location.href = object_url; + } else { + var opened = view.open(object_url, "_blank"); + if (!opened) { + // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html + view.location.href = object_url; + } + } + filesaver.readyState = filesaver.DONE; + dispatch_all(); + revoke(object_url); + } + ; + filesaver.readyState = filesaver.INIT; + + if (can_use_save_link) { + object_url = get_URL().createObjectURL(blob); + setTimeout(function() { + save_link.href = object_url; + save_link.download = name; + click(save_link); + dispatch_all(); + revoke(object_url); + filesaver.readyState = filesaver.DONE; + }); + return; + } + + fs_error(); + } + , FS_proto = FileSaver.prototype + , saveAs = function(blob, name, no_auto_bom) { + return new FileSaver(blob, name || blob.name || "download", no_auto_bom); + } + ; + // IE 10+ (native saveAs) + if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { + return function(blob, name, no_auto_bom) { + name = name || blob.name || "download"; + + if (!no_auto_bom) { + blob = auto_bom(blob); + } + return navigator.msSaveOrOpenBlob(blob, name); + }; + } + + FS_proto.abort = function(){}; + FS_proto.readyState = FS_proto.INIT = 0; + FS_proto.WRITING = 1; + FS_proto.DONE = 2; + + FS_proto.error = + FS_proto.onwritestart = + FS_proto.onprogress = + FS_proto.onwrite = + FS_proto.onabort = + FS_proto.onerror = + FS_proto.onwriteend = + null; + + return saveAs; +}( + typeof self !== "undefined" && self + || typeof window !== "undefined" && window + || this.content +)); +// `self` is undefined in Firefox for Android content script context +// while `this` is nsIContentFrameMessageManager +// with an attribute `content` that corresponds to the window + +if (typeof module !== "undefined" && module.exports) { + module.exports.saveAs = saveAs; +} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { + define("FileSaver.js", function() { + return saveAs; + }); +} diff --git a/kemonogen/background.jpg b/kemonogen/background.jpg new file mode 100644 index 0000000..3bf5ef3 Binary files /dev/null and b/kemonogen/background.jpg differ diff --git a/kemonogen/canvas-toBlob.js b/kemonogen/canvas-toBlob.js new file mode 100644 index 0000000..8c30156 --- /dev/null +++ b/kemonogen/canvas-toBlob.js @@ -0,0 +1,125 @@ +/* canvas-toBlob.js + * A canvas.toBlob() implementation. + * 2016-05-26 + * + * By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr + * License: MIT + * See https://github.com/eligrey/canvas-toBlob.js/blob/master/LICENSE.md + */ + +/*global self */ +/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + +/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */ + +(function(view) { +"use strict"; +var + Uint8Array = view.Uint8Array + , HTMLCanvasElement = view.HTMLCanvasElement + , canvas_proto = HTMLCanvasElement && HTMLCanvasElement.prototype + , is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i + , to_data_url = "toDataURL" + , base64_ranks + , decode_base64 = function(base64) { + var + len = base64.length + , buffer = new Uint8Array(len / 4 * 3 | 0) + , i = 0 + , outptr = 0 + , last = [0, 0] + , state = 0 + , save = 0 + , rank + , code + , undef + ; + while (len--) { + code = base64.charCodeAt(i++); + rank = base64_ranks[code-43]; + if (rank !== 255 && rank !== undef) { + last[1] = last[0]; + last[0] = code; + save = (save << 6) | rank; + state++; + if (state === 4) { + buffer[outptr++] = save >>> 16; + if (last[1] !== 61 /* padding character */) { + buffer[outptr++] = save >>> 8; + } + if (last[0] !== 61 /* padding character */) { + buffer[outptr++] = save; + } + state = 0; + } + } + } + // 2/3 chance there's going to be some null bytes at the end, but that + // doesn't really matter with most image formats. + // If it somehow matters for you, truncate the buffer up outptr. + return buffer; + } +; +if (Uint8Array) { + base64_ranks = new Uint8Array([ + 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1 + , -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 + , -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 + , 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + ]); +} +if (HTMLCanvasElement && (!canvas_proto.toBlob || !canvas_proto.toBlobHD)) { + if (!canvas_proto.toBlob) + canvas_proto.toBlob = function(callback, type /*, ...args*/) { + if (!type) { + type = "image/png"; + } if (this.mozGetAsFile) { + callback(this.mozGetAsFile("canvas", type)); + return; + } if (this.msToBlob && /^\s*image\/png\s*(?:$|;)/i.test(type)) { + callback(this.msToBlob()); + return; + } + + var + args = Array.prototype.slice.call(arguments, 1) + , dataURI = this[to_data_url].apply(this, args) + , header_end = dataURI.indexOf(",") + , data = dataURI.substring(header_end + 1) + , is_base64 = is_base64_regex.test(dataURI.substring(0, header_end)) + , blob + ; + if (Blob.fake) { + // no reason to decode a data: URI that's just going to become a data URI again + blob = new Blob + if (is_base64) { + blob.encoding = "base64"; + } else { + blob.encoding = "URI"; + } + blob.data = data; + blob.size = data.length; + } else if (Uint8Array) { + if (is_base64) { + blob = new Blob([decode_base64(data)], {type: type}); + } else { + blob = new Blob([decodeURIComponent(data)], {type: type}); + } + } + callback(blob); + }; + + if (!canvas_proto.toBlobHD && canvas_proto.toDataURLHD) { + canvas_proto.toBlobHD = function() { + to_data_url = "toDataURLHD"; + var blob = this.toBlob(); + to_data_url = "toDataURL"; + return blob; + } + } else { + canvas_proto.toBlobHD = canvas_proto.toBlob; + } +} +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); diff --git a/kemonogen/card.png b/kemonogen/card.png new file mode 100644 index 0000000..d76eb30 Binary files /dev/null and b/kemonogen/card.png differ diff --git a/kemonogen/fonts/Play-Bold.ttf b/kemonogen/fonts/Play-Bold.ttf new file mode 100644 index 0000000..628ecef Binary files /dev/null and b/kemonogen/fonts/Play-Bold.ttf differ diff --git a/kemonogen/fonts/dejima-mincho-r227.ttf b/kemonogen/fonts/dejima-mincho-r227.ttf new file mode 100644 index 0000000..b3259bd Binary files /dev/null and b/kemonogen/fonts/dejima-mincho-r227.ttf differ diff --git a/kemonogen/fonts/japarifont.woff b/kemonogen/fonts/japarifont.woff new file mode 100644 index 0000000..54ed8a6 Binary files /dev/null and b/kemonogen/fonts/japarifont.woff differ diff --git a/kemonogen/index.html b/kemonogen/index.html new file mode 100644 index 0000000..6fb51ac --- /dev/null +++ b/kemonogen/index.html @@ -0,0 +1,303 @@ + + + + + Kemono Friends Logo Generator + + + + + + + + + +
+
+ +
+
+
+
+
+ +
+

Kemono Friends Logo Generator

+ ↓ Gib hier deinen Text ein! + + + +

Wenn du fertig bist, klicke auf um dein Bild zu speichern!

+

Auf dem Smartphone kannst du das Logo auch durch langes Drücken teilen oder einen Screenshot machen.

+
+ + +
+ + diff --git a/kemonogen/index.js b/kemonogen/index.js new file mode 100644 index 0000000..050aff0 --- /dev/null +++ b/kemonogen/index.js @@ -0,0 +1,270 @@ +window.onload = function(){ + + var seed = { + x: (2147483648 * Math.random()) | 0, + y: (2147483648 * Math.random()) | 0, + z: (2147483648 * Math.random()) | 0, + w: (2147483648 * Math.random()) | 0 + }; + function randomInt(xors) { + var t = xors.x ^ (xors.x << 11); + xors.x = xors.y; + xors.y = xors.z; + xors.z = xors.w; + return xors.w = (xors.w^(xors.w>>>19))^(t^(t>>>8)); + } + function random(xors) { + return randomInt(xors) / 2147483648; + } + function shuffle(xs){ + var v = Object.assign({}, seed); + var xs = xs.slice(); + var ys = []; + while(0 < xs.length){ + var i = Math.abs(randomInt(v)) % xs.length; + ys.push(xs[i]); + xs.splice(i, 1); + } + return ys; + } + + var colorTuples = shuffle([ + ["#16ae67", "#90c31f"], + ["#ea5421", "#f39800"], + ["#00ac8e", "#e4007f"], + ["#227fc4", "#00a1e9"], + ["#9fa0a0", "#c9caca"], + ["#e60013", "#f39800"], + ["#c3d600", "#a42e8c"] + ]); + + var topColors = shuffle(["#04ad8f", "#a6ce48", "#f3a118", "#ea6435", "#17b297", "#e30983", "#2782c4", "#1aa6e7", "#b5b5b5", "#f29905", "#e50011", "#ccdc26", "#a5328d", "#0aaa60", "#91c423", "#f29300", "#ec5f69", "#22b69e", "#e63e9b", "#917220"]); + + + var topInput = document.querySelector("#top"); + var middleInput = document.querySelector("#middle"); + var bottomInput = document.querySelector("#bottom"); + + var top = document.querySelector(".top"); + var middle = document.querySelector(".middle"); + var bottom = document.querySelector(".bottom"); + + var foreground = document.getElementById("foreground"); + var image = document.getElementById("result"); + + var container = document.querySelector(".container"); + var download = document.getElementById("download"); + + var canvas = document.createElement("canvas"); + var g = canvas.getContext("2d"); + + + + function update(){ + setTimeout(function(){ + setText(topInput.value, middleInput.value, bottomInput.value); + }); + } + middleInput.addEventListener("change", update); + middleInput.addEventListener("keydown", update); + topInput.addEventListener("change", update); + topInput.addEventListener("keydown", update); + bottomInput.addEventListener("change", update); + bottomInput.addEventListener("keydown", update); + + function setText(topText, middleText, bottomText){ + + + + + var topTextSize = 30; + var topMiddlePadding = 30; + var middleTextSize = 120; + var middleBottomPadding = 20; + var bottomTextSize = 30; + var margin = 60; + var bottomTextLetterSpacing = 20; + + var topTextFont = `normal bold ${topTextSize}px/2 "Yu Mincho"`; + var middleTextFont = `normal 400 ${middleTextSize}px/2 japarifont`; + var bottomTextFont = `normal 400 ${bottomTextSize}px/2 PlayBold`; + + // resize canvas + g.font = topTextFont; + var topMetrics = g.measureText(topText); + g.font = middleTextFont; + var middleMetrics = g.measureText(middleText); + g.font = bottomTextFont; + var bottomMetrics = g.measureText(bottomText); + canvas.width = margin + Math.max( + topMetrics.width, + middleMetrics.width, + bottomMetrics.width + bottomTextLetterSpacing * (bottomText.length - 1) + ) + margin; + canvas.height = margin + topTextSize + topMiddlePadding + middleTextSize + middleBottomPadding + bottomTextSize + margin; + + // prepare canvas + g.save(); + g.clearRect(0, 0, canvas.width, canvas.height); + g.textBaseline = "top"; + + + + // stroke top text + function iterate(callback){ + var xors = Object.assign({}, seed); + g.save(); + + g.font = topTextFont; + g.fillStyle = "white"; + g.strokeStyle = "white"; + g.lineJoin = "round"; + g.lineWidth = 10.0; + var metrics = g.measureText(topText); + g.translate(margin + (canvas.width - metrics.width - margin * 2) * 0.5, margin); + var x = 0; + for(var i = 0; i < topText.length; i++){ + var c = topText.slice(i, i + 1); + var rot = random(xors) * 0.2; + var metrics = g.measureText(c); + g.save(); + g.translate(metrics.width * 0.5, topTextSize * 0.5); + g.rotate(rot); + g.translate(-metrics.width * 0.5, -topTextSize * 0.5); + callback(i, c); + g.restore(); + g.translate(metrics.width, 0); + } + g.restore(); + } + g.save(); + var xors = Object.assign({}, seed); + + + + var topColors = ["#04ad8f", "#a6ce48", "#f3a118", "#ea6435", "#17b297", "#e30983", "#2782c4", "#1aa6e7", "#b5b5b5", "#f29905", "#e50011", "#ccdc26", "#a5328d", "#0aaa60", "#91c423", "#f29300", "#ec5f69", "#22b69e", "#e63e9b", "#917220"]; + + + iterate(function(i, c){ + g.shadowColor = "transparent"; + + g.strokeText(c, 0, 0); + }); + iterate(function(i, c){ + g.shadowColor = "rgba(0, 0, 0, 0.3)"; + g.shadowBlur = 10; + g.fillStyle = topColors[i % topColors.length]; + g.fillText(c, 0, 0); + }); + + + + + + + // centerize + var metrics = g.measureText(middleText); + g.translate((canvas.width - middleMetrics.width) * 0.5, margin + topTextSize + topMiddlePadding); + + // stroke outline + g.font = middleTextFont; + g.strokeStyle = "white"; + g.lineWidth = 20.0; + g.shadowColor = "rgba(0, 0, 0, 0.3)"; + g.shadowBlur = 10; + g.lineCap = "round"; + g.lineJoin = "round"; + g.strokeText(middleText, 0, 0); + + // fill charactors + var x = 0; + var xors = Object.assign({}, seed); + for(var i = 0; i < middleText.length; i++){ + var c = middleText.slice(i, i + 1); + + // base color + g.shadowColor = "rgba(0, 0, 0, 0.6)"; + g.shadowBlur = 10; + g.fillStyle = colorTuples[i % colorTuples.length][0]; + g.fillText(c, 0, 0); + + g.save(); + + // clip + var rot = random(xors); + g.beginPath(); + g.save(); + g.translate(middleTextSize * 0.5, middleTextSize * 0.5); + g.rotate(rot); + g.translate(-middleTextSize * 0.5, -middleTextSize * 0.5); + g.moveTo(-middleTextSize * 2, middleTextSize * 0.5); + g.lineTo(middleTextSize * 2, middleTextSize * 0.5); + g.lineTo(middleTextSize * 2, middleTextSize * 2); + g.lineTo(-middleTextSize * 2, middleTextSize * 2); + g.closePath(); + g.restore(); + g.clip(); + + // upper color + g.shadowColor = "none"; + g.shadowBlur = 0; + g.fillStyle = colorTuples[i % colorTuples.length][1]; + g.fillText(c, 0, 0); + + g.restore(); + + // go to next + var metrics = g.measureText(c); + g.translate(metrics.width, 0); + } + + g.restore(); + + // bottom text + g.save(); + g.strokeStyle = "white"; + g.fillStyle = "#977a2d"; + g.lineWidth = 13.0; + g.lineCap = "round"; + g.lineJoin = "round"; + g.textBaseline = "top"; + g.font = bottomTextFont; + + var metrics = g.measureText(bottomText); + g.translate( + (canvas.width - metrics.width - (bottomText.length - 1) * bottomTextLetterSpacing) * 0.5, + margin + topTextSize + topMiddlePadding + middleTextSize + middleBottomPadding + ); + + for(var i = 0; i < bottomText.length; i++){ + var c = bottomText.slice(i, i + 1); + g.shadowColor = "rgba(0, 0, 0, 0.3)"; + g.shadowBlur = 10; + g.strokeText(c, 0, 0); + g.shadowColor = "transparent"; + g.fillText(c, 0, 0); + var metrics = g.measureText(c); + g.translate(metrics.width + bottomTextLetterSpacing, 0); + } + + g.restore(); + + + var url = canvas.toDataURL(); + image.src = url; + download.href = url; + + } + + topInput.value = "女の子の姿になった動物たちが繰り広げる大冒険!"; + middleInput.value = "けものフレンズ"; + bottomInput.value = "KEMONO FRIENDS"; + update(); + + download.addEventListener("click", function(){ + canvas.toBlob(function(blob) { + saveAs(blob, middleInput.value + ".png"); + }); + }); +}; +