Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useState, useRef } from 'react';
- const toHex = (code) => {
- let result = code.toString(16);
- if (result.length == 1) {
- return "0" + result;
- }
- return result;
- }
- const generateText = (data, startSpacing = 0) => {
- let result = "\"";
- const view = new DataView(data);
- let j = startSpacing;
- for (var i = 0; i < view.byteLength; i++) {
- if (i > 0 && 0 == (j % 80) && i < i < view.byteLength - 1) {
- result += "\"\r\n \"";
- }
- var charcode = view.getUint8(i);
- if (charcode < 0x80) {
- const ch = String.fromCharCode(charcode);
- switch (ch) {
- case '\r':
- result += "\\r";
- break;
- case '\n':
- result += "\\n";
- if (i < view.byteLength - 1) {
- result += "\"\r\n \"";
- }
- j = 0;
- break;
- case '\t':
- result += "\\t";
- break;
- case '"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- default:
- result += ch;
- break;
- }
- }
- else {
- result += `\\x${toHex(charcode)}`;
- }
- ++j;
- }
- return result + "\"";
- }
- const generateBinary = (data) => {
- let result = "";
- const view = new DataView(data);
- for (let i = 0; i < view.byteLength; ++i) {
- if (0 == (i % (30))) {
- if (i < view.byteLength - 1) {
- result += "\r\n ";
- } else {
- result += "\r\n";
- }
- }
- let append = ("0x" + toHex(view.getUint8(i)));
- if (i < view.byteLength - 1) {
- append += ", ";
- }
- result += append;
- }
- return result;
- }
- const generateStringLiteral = (name, data, isStatic) => {
- if (isStatic) {
- return `static const char* ${name} = ${generateText(data, 18 + name.length)};`;
- }
- return `const char* ${name} = ${generateText(data, 18 + name.length)};`;
- }
- const generateByteArrayLiteral = (name, data, isStatic) => {
- if (isStatic) {
- return `static const uint8_t ${name}[] = {${generateBinary(data)}};`;
- }
- return `const uint8_t ${name}[] = {${generateBinary(data)}};`;
- }
- const toIdentifier = (name) => {
- let result = "";
- if (name.length == 0) {
- return "_";
- }
- if (name[0] >= '0' && name[0] <= '9') {
- result = "_";
- }
- for (let i = 0; i < name.length; ++i) {
- if ((name[i] >= '0' && name[i] <= '9') || (name[i] >= 'A' && name[i] <= 'Z') || (name[i] >= 'a' && name[i] <= 'z')) {
- result += name[i];
- } else {
- result += "_";
- }
- }
- return result;
- }
- const checkWinFontMagic = (data) => {
- const view = new DataView(data);
- return view.byteLength > 2 && view.getUint8(0) == 77 && view.getUint8(1) == 90;
- }
- const isTrueType = (name) => {
- const n = name.toLowerCase();
- return n.endsWith(".ttf") || n.endsWith(".otf");
- }
- const generateHeader = (identifier, fileName, isText, fileType, size, units, outputType, data) => {
- let result = "";
- const isGfx = (outputType != undefined && outputType.length > 0 && outputType != "C");
- const guard = identifier.toUpperCase() + ((isGfx) ? "_HPP" : "_H");
- const impl = identifier.toUpperCase() + "_IMPLEMENTATION";
- result += "// Automatically generated by https://honeythecodewitch.com/gfx/header\r\n";
- result += `// #define ${impl} in exactly one translation unit (.c/.cpp file) before including this header\r\n`
- result += `#ifndef ${guard}\r\n`;
- result += `#define ${guard}\r\n`;
- if (!isText) {
- result += "#include <stdint.h>\r\n";
- }
- let isSpecialized = false;
- let isFon = false;
- let isTtf = false;
- let isVlw = false;
- let isJpg = false;
- let isPng = false;
- if (isGfx) {
- if (fileType == undefined || fileType == "" && fileName.toLowerCase().endsWith(".fon")) {
- isFon = checkWinFontMagic(data);
- isSpecialized = isFon;
- } else if (fileType == "image/jpeg") {
- isJpg = true;
- isSpecialized = true;
- } else if (fileType == "image/png") {
- isPng = true;
- isSpecialized = true;
- } else if (fileName.toLowerCase().endsWith(".vlw")) {
- isVlw = true;
- isSpecialized = true;
- } else if (isTrueType(fileName) && size && !isNaN(size) && size != 0 && units) {
- isTtf = true;
- isSpecialized = true;
- }
- if (isFon) {
- result += "#include \"gfx_win_font.hpp\"\r\n\r\n";
- result += `extern gfx::win_font ${identifier};\r\n`
- } else if (isVlw) {
- result += "#include \"gfx_vlw_font.hpp\"\r\n\r\n";
- result += `extern gfx::vlw_font ${identifier};\r\n`
- } else if (isJpg) {
- result += "#include \"gfx_jpg_image.hpp\"\r\n\r\n";
- result += `extern gfx::jpg_image ${identifier};\r\n`
- } else if (isPng) {
- result += "#include \"gfx_png_image.hpp\"\r\n\r\n";
- result += `extern gfx::png_image ${identifier};\r\n`
- } else if (isTtf) {
- result += "#include \"gfx_ttf_font.hpp\"\r\n\r\n";
- result += `extern gfx::ttf_font ${identifier};\r\n`
- } else {
- result += "#include \"gfx_core.hpp\"\r\n\r\n";
- result += `extern gfx::const_buffer_stream ${identifier};\r\n`;
- }
- } else {
- if (isText) {
- const view = new DataView(data);
- result += `#define ${identifier.toUpperCase()}_LENGTH (${view.byteLength})\r\n`;
- result += "#ifdef __cplusplus\r\nextern \"C\"\r\n#else\r\nextern\r\n#endif\r\n";
- result += `const char* ${identifier};\r\n`;
- } else {
- result += `const uint8_t ${identifier}[];\r\n`;
- }
- }
- result += `#endif // ${guard}\r\n\r\n`;
- result += `#ifdef ${impl}\r\n`;
- if (isGfx) {
- if (isText) {
- result += generateStringLiteral(identifier + "_data", data, true) + "\r\n\r\n";
- } else {
- result += generateByteArrayLiteral(identifier + "_data", data, true) + "\r\n\r\n";
- }
- if (isSpecialized) {
- result += `static gfx::const_buffer_stream ${identifier}_stream(${identifier}_data,sizeof(${identifier}_data));\r\n`;
- }
- if (isFon) {
- result += `gfx::win_font ${identifier}(${identifier}_stream);\r\n`;
- } else if (isVlw) {
- result += `gfx::vlw_font ${identifier}(${identifier}_stream);\r\n`;
- } else if (isJpg) {
- result += `gfx::jpg_image ${identifier}(${identifier}_stream);\r\n`;
- } else if (isPng) {
- result += `gfx::png_image ${identifier}(${identifier}_stream);\r\n`;
- } else if (isTtf) {
- result += `gfx::ttf_font ${identifier}(${identifier}_stream, ${size}, gfx::font_size_units::${units})\r\n`;
- } else {
- if (isText) {
- const view = new DataView(data);
- result += `gfx::const_buffer_stream ${identifier}((const uint8_t*)${identifier}_data,${view.byteLength});\r\n`;
- } else {
- result += `gfx::const_buffer_stream ${identifier}(${identifier}_data,sizeof(${identifier}_data));\r\n`;
- }
- }
- } else {
- if (isText) {
- result += generateStringLiteral(identifier, data, false) + "\r\n";
- } else {
- result += generateByteArrayLiteral(identifier, data, false) + "\r\n";
- }
- }
- result += `#endif // ${impl}\r\n`;
- return result;
- }
- const getDownloadName = (ident, genType) => {
- if (genType == "C" || genType == undefined || genType == "") {
- return `${ident}.h`;
- }
- return `${ident}.hpp`;
- }
- const HeaderGenerator = () => {
- var gencache;
- const [fileInfo, setFileInfo] = useState("");
- const [ident, setIdent] = useState("");
- const [fontSize, setFontSize] = useState("");
- const [fontUnits, setFontUnits] = useState("");
- const [genType, setGenType] = useState("");
- const [downloadUrl, setDownloadUrl] = useState("");
- const downloadLinkRef = useRef(null);
- const isText = (type) => {
- return (type.endsWith("/json") || type.endsWith("/xml") || type.endsWith("+xml") || type.startsWith("text/"));
- }
- const handleFileChange = (e) => {
- setFileInfo({ file: e.target.files[0], type: e.target.files[0].type });
- setIdent(toIdentifier(e.target.files[0].name));
- gencache = undefined;
- };
- const handleIdentChange = (e) => {
- if (ident != e.target.value) {
- setIdent(e.target.value);
- gencache = undefined;
- }
- }
- const handleFontSizeValueChange = (e) => {
- let n = Number.parseInt(e.target.value);
- if (isNaN(n)) {
- n = 0;
- }
- setFontSize(n);
- gencache = undefined;
- }
- const handleFontSizeUnitChange = (e) => {
- let u = e.target.value;
- if (u != "pt" && u != "px") {
- u = "pt";
- }
- setFontUnits(u);
- gencache = undefined;
- }
- const handleTypeChange = (e) => {
- if (genType != e.target.value) {
- setGenType(e.target.value);
- gencache = undefined;
- }
- }
- const getCreatedTypeName = () => {
- if (fileInfo) {
- if(!genType || genType=="" || genType=="C") {
- if(isText(fileInfo.type)) {
- return "const char*";
- } else {
- return "const uint8_t[]";
- }
- }
- const fileType = fileInfo.type;
- const fileName = fileInfo.file.name;
- const size = fontSize;
- const units = fontUnits;
- if (fileType == undefined || fileType == "" && fileName.toLowerCase().endsWith(".fon")) {
- return "gfx::win_font";
- } else if (fileType == "image/jpeg") {
- return "gfx::jpg_image";
- } else if (fileType == "image/png") {
- return "gfx::png_image";
- } else if (fileName.toLowerCase().endsWith(".vlw")) {
- return "gfx::vlw_font";
- } else if (isTrueType(fileName) && size && !isNaN(size) && size != 0 && units) {
- return "gfx::ttf_font";
- }
- return "gfx::const_buffer_stream";
- }
- return undefined;
- }
- const generateContentClip = () => {
- if (!gencache && fileInfo.file) {
- let reader = new FileReader();
- reader.readAsArrayBuffer(fileInfo.file);
- reader.onload = async function (evt) {
- console.log("generating content to clipboard");
- gencache = generateHeader(ident, fileInfo.file.name, isText(fileInfo.type), fileInfo.type, fontSize, fontUnits, genType, evt.target.result);
- await navigator.clipboard.writeText(gencache);
- }
- } else if (gencache) {
- console.log("writing content to clipboard");
- navigator.clipboard.writeText(gencache);
- }
- }
- const setGeneratedFileUrl = () => {
- const blb = new Blob([gencache], { type: "text/plain" });
- if (downloadUrl != undefined && downloadUrl.length > 0) {
- URL.revokeObjectURL(downloadUrl);
- }
- setDownloadUrl(URL.createObjectURL(blb));
- downloadLinkRef?.current.click();
- }
- const generateContentFile = () => {
- if (!gencache && fileInfo.file) {
- let reader = new FileReader();
- reader.readAsArrayBuffer(fileInfo.file);
- reader.onload = function (evt) {
- console.log("generating content to file");
- gencache = generateHeader(ident, fileInfo.file.name, isText(fileInfo.type), fileInfo.type, fontSize, fontUnits, genType, evt.target.result);
- setGeneratedFileUrl();
- }
- } else if (gencache) {
- console.log("writing content to file");
- setGeneratedFileUrl();
- }
- }
- const onDropFiles = (e) => {
- e.preventDefault();
- const inputFile = document.getElementById("file");
- inputFile.files = e.dataTransfer.files;
- setFileInfo({ file: e.dataTransfer.files[0], type: e.dataTransfer.files[0].type });
- setIdent(toIdentifier(e.dataTransfer.files[0].name));
- gencache = undefined;
- }
- return (
- <div id="drop-target" onDrop={onDropFiles} className={"border-drag"} onDragOver={(event) => event.preventDefault()}>
- <p>Select or drag a file here</p>
- <div className="input-group">
- <table border="0">
- <tbody>
- <tr>
- <td colSpan={2}><input id="file" type="file" onChange={handleFileChange} /></td>
- </tr>
- <tr>
- <td><label>Type</label></td>
- <td>
- <select id="type" value={genType} onChange={handleTypeChange}>
- <option value="C">Raw C/++</option>
- <option value="GFX2">GFX 2.x</option>
- </select>
- </td>
- </tr>
- <tr>
- <td><label>Identifier: </label></td><td><input type="text" id="identifier" value={ident} onChange={handleIdentChange} /></td>
- </tr>
- {fileInfo && isTrueType(fileInfo.file.name) && genType.startsWith("G") && (
- <tr>
- <td><label>Size: </label></td><td><input type="text" defaultValue={fontSize} onChange={handleFontSizeValueChange} /><select onChange={handleFontSizeUnitChange} defaultValue={fontUnits}><option value="pt">pt</option><option value="px">px</option></select></td>
- </tr>
- )}
- </tbody>
- </table>
- </div>
- {fileInfo && (
- <section>
- File details:
- <ul>
- <li>Name: {fileInfo.file.name}</li>
- {fileInfo.file.type && (
- <li>MIME: {fileInfo.file.type}</li>)}
- <li>Size: {fileInfo.file.size} bytes</li>
- <li>Type: {getCreatedTypeName()}</li>
- </ul>
- </section>
- )}
- {fileInfo && (
- <>
- <button onClick={generateContentFile}
- className="submit"
- >Download header file</button><br />
- <button
- onClick={generateContentClip}
- className="submit"
- >Copy to clipboard</button>
- <a ref={downloadLinkRef} href={downloadUrl} download={getDownloadName(ident, genType)} hidden></a>
- </>
- )}
- </div>
- );
- };
- export default HeaderGenerator;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement