From 529eb5b3509c88ce766ac163e4b336bbf3435323 Mon Sep 17 00:00:00 2001 From: Shawn Date: Tue, 13 Nov 2018 16:12:27 -0600 Subject: [PATCH] Fix rasterization --- .../Creatify/EditableFontface/index.js | 4 +- .../Creatify/FontFaces/OceanWave.js | 21 ----- .../Creatify/FontFaces/RetroRainbow.js | 4 + .../Creatify/FontFaces/VaporWave.js | 37 ++++++++ .../Creatify/RichDraggable/index.js | 2 +- client/src/components/Creatify/index.js | 94 ++++++++++++++++--- 6 files changed, 123 insertions(+), 39 deletions(-) delete mode 100644 client/src/components/Creatify/FontFaces/OceanWave.js create mode 100644 client/src/components/Creatify/FontFaces/VaporWave.js diff --git a/client/src/components/Creatify/EditableFontface/index.js b/client/src/components/Creatify/EditableFontface/index.js index 92f298fa..603cb8dd 100644 --- a/client/src/components/Creatify/EditableFontface/index.js +++ b/client/src/components/Creatify/EditableFontface/index.js @@ -26,7 +26,7 @@ export default class EditableFontface extends Component { const textRender = fontFace.textRender || DEFAULT_TEXT_RENDER; const textStyles = Object.assign({ - minHeight: '30px', + minHeight: '20px', WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', }, fontFace.text); @@ -67,5 +67,5 @@ export default class EditableFontface extends Component { export const PRESETS = { 'Retro Rainbow': require('../FontFaces/RetroRainbow'), 'Green Machine': require('../FontFaces/GreenMachine'), - 'Ocean Wave': require('../FontFaces/OceanWave'), + 'vapor wave': require('../FontFaces/VaporWave'), } diff --git a/client/src/components/Creatify/FontFaces/OceanWave.js b/client/src/components/Creatify/FontFaces/OceanWave.js deleted file mode 100644 index 4519c945..00000000 --- a/client/src/components/Creatify/FontFaces/OceanWave.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -module.exports = { - container: {}, - editorStyle: {}, - text: {}, - textRender: (text) => { - // TODO: Inline the path - const id = `curve-${text.replace(/[^A-Za-z0-9]/g, '')}-oceanwave` - return ( - - - - - {text} - - - - ); - }, -}; diff --git a/client/src/components/Creatify/FontFaces/RetroRainbow.js b/client/src/components/Creatify/FontFaces/RetroRainbow.js index c1dd4d8d..833c9671 100644 --- a/client/src/components/Creatify/FontFaces/RetroRainbow.js +++ b/client/src/components/Creatify/FontFaces/RetroRainbow.js @@ -3,6 +3,7 @@ module.exports = { editorStyle: { fontFamily: 'Arial, sans-serif', fontWeight: 'bold', + fontSize: '1.2em', transform: 'scale(1, 1.5)', }, text: { @@ -10,8 +11,11 @@ module.exports = { fontWeight: 'bold', backgroundImage: 'linear-gradient(to right, #b306a9, #ef2667, #f42e2c, #ffa509, #fdfc00, #55ac2f, #0b13fd, #a804af)', backgroundClip: 'text', + fontSize: '1.2em', transform: 'scale(1, 1.5)', color: 'transparent', + paddingBottom: '.25em', + paddingTop: '.1em', WebkitBackgroundClip: 'text', }, }; diff --git a/client/src/components/Creatify/FontFaces/VaporWave.js b/client/src/components/Creatify/FontFaces/VaporWave.js new file mode 100644 index 00000000..f45f2897 --- /dev/null +++ b/client/src/components/Creatify/FontFaces/VaporWave.js @@ -0,0 +1,37 @@ +import React from 'react'; + +const charToFullWidth = char => { + const c = char.charCodeAt( 0 ) + return c >= 33 && c <= 126 + ? String.fromCharCode( ( c - 33 ) + 65281 ) + : char +} + +const stringToFullWidth = + +module.exports = { + container: {}, + editorStyle: {}, + text: { + fontFamily: 'Segoe UI,Helvetica,Arial', + }, + textRender: (text) => { + const formattedText = text.toLowerCase().split('').map((char) => { + const c = char.charCodeAt( 0 ) + return (c >= 33 && c <= 126) ? String.fromCharCode(c + 65248) : char + }).join(''); + + // TODO: Inline the path + const id = `curve-${text.replace(/[^A-Za-z0-9]/g, '')}-oceanwave` + return ( + + + + + {formattedText} + + + + ); + }, +}; diff --git a/client/src/components/Creatify/RichDraggable/index.js b/client/src/components/Creatify/RichDraggable/index.js index 8fab5159..a4097085 100644 --- a/client/src/components/Creatify/RichDraggable/index.js +++ b/client/src/components/Creatify/RichDraggable/index.js @@ -49,7 +49,7 @@ export default class RichDraggable extends Component { return ( -
+
{props.children}
diff --git a/client/src/components/Creatify/index.js b/client/src/components/Creatify/index.js index 86f96904..9d35e5e6 100644 --- a/client/src/components/Creatify/index.js +++ b/client/src/components/Creatify/index.js @@ -12,20 +12,89 @@ try { } } catch(e) {} +const getRasterizedCanvas = (contents, width, height) => { + return new Promise((resolve) => { + // Resolves a bug in Chrome where it renders correctly, but + // replaces the inline styles with an invalid `background-clip`. + if(/Chrome/.test(navigator.userAgent)) { + contents = contents.replace(/background\-clip:(.*)[;$]/g, + (match, group) => (`-webkit-background-clip:${group};${match}`) + ); + } + + // Attempt to match font kerning with the DOM. + contents = '' + contents; + + rasterizeHTML.drawHTML(contents, document.createElement('canvas'), { + width, + height, + }).then((renderResult) => { + const pixelRatio = 2; + + // Why do this? Because Firefox doesn't always give us what we expect + // `background-clip: text` is very broken and does not always render in time. + let img = document.createElement('img'); + let canvas = document.createElement('canvas'); + + img.height = canvas.height = height * pixelRatio; + img.width = canvas.width = width * pixelRatio; + canvas.style.height = `${height}px`; + canvas.style.width = `${width}px`; + + let shadowNode = document.createElement('div'); + Object.assign(shadowNode.style, { + height: 0, + overflow: 'hidden', + width: 0, + }); + document.body.appendChild(shadowNode); + + shadowNode.appendChild(img); + //document.body.appendChild(canvas); + + var svg64 = btoa(unescape(encodeURIComponent(renderResult.svg))); + var b64Start = 'data:image/svg+xml;base64,'; + var image64 = b64Start + svg64; + img.addEventListener('load', () => { + window.requestAnimationFrame(() => { + // We still can't trust Firefox's %$%&* engine, add another 5ms timeout + setTimeout(() => { + let context = canvas.getContext('2d', { alpha: false }); + context.clearRect(0, 0, canvas.width, canvas.height); + context.fillStyle = 'white'; + context.imageSmoothingEnabled = false; + context.scale(pixelRatio, pixelRatio); + context.fillRect(0, 0, canvas.width, canvas.height); + context.drawImage(img, 0, 0); + + document.body.removeChild(shadowNode); + + resolve(canvas); + }, 10); + }); + }); + img.src = image64; + }); + }); +}; + export default class Creatify extends Component { constructor(props) { super(props); const fontKeys = Object.keys(FontPresets); - this.canvas = React.createRef(); this.contents = React.createRef(); const fontOptions = fontKeys.map( (fontName) => ( { value: fontName, - label: , + label: ( +
+ +
+ ), fontName, } ) @@ -49,19 +118,15 @@ export default class Creatify extends Component { renderContents() { const me = this; - const canvas = me.canvas.current; - let contents = me.contents.current.innerHTML; + let contents = me.contents.current.outerHTML; - // Resolves a bug in Chrome where it renders correctly, but - // replaces the inline styles with an invalid `background-clip` - contents = contents.replace(/background\-clip:(.*)[;$]/g, - (match, group) => (`-webkit-background-clip:${group};${match}`) - ); - - rasterizeHTML.drawHTML(contents, canvas).then((renderResult) => { - - }, (error) => { + console.log(contents) + // Cheap border/handles removal + contents = `` + contents; + getRasterizedCanvas(contents, 600, 500).then((element) => { + console.log(element); + document.body.appendChild(element); }); } @@ -76,10 +141,9 @@ export default class Creatify extends Component {
-