From 476887b06066e2fac020794e278c3d62da595308 Mon Sep 17 00:00:00 2001 From: Lasse Fister Date: Mon, 25 Mar 2024 23:32:59 +0100 Subject: [PATCH 1/9] Add woff-to-otf --- src/opentype.mjs | 8 ++- src/woff-to-otf.mjs | 131 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 src/woff-to-otf.mjs diff --git a/src/opentype.mjs b/src/opentype.mjs index 60e8eae2..73f2d161 100644 --- a/src/opentype.mjs +++ b/src/opentype.mjs @@ -38,6 +38,7 @@ import meta from './tables/meta.mjs'; import gasp from './tables/gasp.mjs'; import svg from './tables/svg.mjs'; import { PaletteManager } from './palettes.mjs'; +import { woff_to_otf } from './woff-to-otf.mjs'; /** * The opentype library. * @namespace opentype @@ -436,7 +437,7 @@ function parseBuffer(buffer, opt={}) { font.tables.meta = meta.parse(metaTable.data, metaTable.offset); font.metas = font.tables.meta; } - + font.palettes = new PaletteManager(font); return font; @@ -473,5 +474,8 @@ export { parse as _parse, parseBuffer as parse, load, - loadSync + loadSync, + parseWOFFTableEntries, + uncompressTable, + woff_to_otf }; diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs new file mode 100644 index 00000000..513145f9 --- /dev/null +++ b/src/woff-to-otf.mjs @@ -0,0 +1,131 @@ +// CAUTION this is a dependency cycle, but since the dependencies are +// on execution time of woff_to_otf it only looks statically like a problem. +// still, maybe parseWOFFTableEntries and uncompressTable should not be +// in opentype.js or maybe woff_to_otf could move into opentype.js +import { // eslint-disable-line + parseWOFFTableEntries, + uncompressTable +} from './opentype.mjs'; + +import parse from './parse.mjs'; +import { encode } from './types.mjs'; + +// I looked at https://github.com/mondeja/woff2otf/blob/master/src/woff2otf.js +// but I'm using opentype.js infrastructure. +function woff_to_otf(buffer) { + if (buffer.constructor !== ArrayBuffer) + buffer = new Uint8Array(buffer).buffer; + const data = new DataView(buffer, 0) + , out = [] + , signature = parse.getTag(data, 0) + ; + + if (signature !== 'wOFF') + throw new Error(`TYPE ERROR signature must be wOFF but is: "${signature}"`); + + // need flavour??? -> opentype header syff! + const flavor = parse.getTag(data, 4) + , numTables = parse.getUShort(data, 12) + , tableEntries = parseWOFFTableEntries(data, numTables) + , max = [] + ; + for (let n = 0; n < 64; n++) { + if (Math.pow(2, n) > numTables) + break; + max.splice(0, Infinity, n, Math.pow(2, n)); + } + const searchRange = max[1] * 16 + , entrySelector = max[0] + , rangeShift = numTables * 16 - searchRange + ; + + out.push( + ...encode.TAG(flavor) + , ...encode.USHORT(numTables) + , ...encode.USHORT(searchRange) + , ...encode.USHORT(entrySelector) + , ...encode.USHORT(rangeShift) + ); + let offset = out.length; + for (let i=0; i {data: view, offset: 0}; + // FIXME: we should rather just append the bytes to a new buffer + // no need to parse into an array ... + // , p = new parse.Parser(table.data, table.offset) + ; + + + offset = tableEntry.outOffset + tableEntry.length; + const padding = (offset % 4) !== 0 + ? 4 - (offset % 4) + : 0 + ; + // out.push( + // ...p.parseByteList(tableEntry.length) + // , ...Array(padding).fill(0) // new ArrayBuffer(padding) + // ); + buffers.push( + new DataView(table.data.buffer, table.offset, tableEntry.length) + , new ArrayBuffer(padding) + ); + } + + const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); + buffers.reduce((offset, buffer)=>{ + result.set(buffer, offset); + return offset + buffer.byteLength; + }, 0); + return result.buffer; + //const outArray = new Uint8Array(out.length); + //for (let i=0,l=out.length; i Date: Tue, 26 Mar 2024 01:23:43 +0100 Subject: [PATCH 2/9] Use array instead of trying to merge buffers. --- src/woff-to-otf.mjs | 54 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs index 513145f9..3e8f386d 100644 --- a/src/woff-to-otf.mjs +++ b/src/woff-to-otf.mjs @@ -32,7 +32,7 @@ function woff_to_otf(buffer) { for (let n = 0; n < 64; n++) { if (Math.pow(2, n) > numTables) break; - max.splice(0, Infinity, n, Math.pow(2, n)); + max.splice(0, Infinity, n, 2 ** n); } const searchRange = max[1] * 16 , entrySelector = max[0] @@ -65,9 +65,9 @@ function woff_to_otf(buffer) { // }); // p += 20; tableEntries[i].checksum = parse.getULong(data, pointerBase + 16); - // offset += 4 * 4; + offset += 4 * 4; } - offset += numTables * 16; + // offset += numTables * 16; for (let i=0; i {data: view, offset: 0}; // FIXME: we should rather just append the bytes to a new buffer // no need to parse into an array ... - // , p = new parse.Parser(table.data, table.offset) + , p = new parse.Parser(table.data, table.offset) ; @@ -104,26 +102,26 @@ function woff_to_otf(buffer) { ? 4 - (offset % 4) : 0 ; - // out.push( - // ...p.parseByteList(tableEntry.length) - // , ...Array(padding).fill(0) // new ArrayBuffer(padding) - // ); - buffers.push( - new DataView(table.data.buffer, table.offset, tableEntry.length) - , new ArrayBuffer(padding) + // buffers.push( + // new DataView(table.data.buffer, table.offset, tableEntry.length) + // , new ArrayBuffer(padding) + // ); + out.push( + ...p.parseByteList(tableEntry.length) + , ...Array(padding).fill(0) // new ArrayBuffer(padding) ); } - const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); - buffers.reduce((offset, buffer)=>{ - result.set(buffer, offset); - return offset + buffer.byteLength; - }, 0); - return result.buffer; - //const outArray = new Uint8Array(out.length); - //for (let i=0,l=out.length; iaccum+buffer.byteLength, 0)); + // buffers.reduce((offset, buffer)=>{ + // result.set(buffer, offset) + // return offset + buffer.byteLength + // }, 0) + // return result.buffer; + const outArray = new Uint8Array(out.length); + for (let i=0,l=out.length; i Date: Tue, 26 Mar 2024 01:31:45 +0100 Subject: [PATCH 3/9] fix: Error too many function arguments. --- src/woff-to-otf.mjs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs index 3e8f386d..abecd80b 100644 --- a/src/woff-to-otf.mjs +++ b/src/woff-to-otf.mjs @@ -107,10 +107,11 @@ function woff_to_otf(buffer) { // , new ArrayBuffer(padding) // ); out.push( - ...p.parseByteList(tableEntry.length) - , ...Array(padding).fill(0) // new ArrayBuffer(padding) + p.parseByteList(tableEntry.length) + , Array(padding).fill(0) // new ArrayBuffer(padding) ); } + const outFlat = out.flat(); // const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); // buffers.reduce((offset, buffer)=>{ @@ -118,9 +119,9 @@ function woff_to_otf(buffer) { // return offset + buffer.byteLength // }, 0) // return result.buffer; - const outArray = new Uint8Array(out.length); - for (let i=0,l=out.length; i Date: Tue, 26 Mar 2024 10:47:16 +0100 Subject: [PATCH 4/9] [woff-to-otf] copy tables directly from buffers not via an array of ints. --- src/woff-to-otf.mjs | 58 +++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs index abecd80b..3cbff343 100644 --- a/src/woff-to-otf.mjs +++ b/src/woff-to-otf.mjs @@ -10,8 +10,10 @@ import { // eslint-disable-line import parse from './parse.mjs'; import { encode } from './types.mjs'; -// I looked at https://github.com/mondeja/woff2otf/blob/master/src/woff2otf.js -// but I'm using opentype.js infrastructure. +// I looked at +// https://github.com/hanikesn/woff2otf +// and https://github.com/mondeja/woff2otf +// but I'm doing it using opentype.js infrastructure. function woff_to_otf(buffer) { if (buffer.constructor !== ArrayBuffer) buffer = new Uint8Array(buffer).buffer; @@ -82,47 +84,31 @@ function woff_to_otf(buffer) { if ((offset % 4) !== 0) offset += 4 - (offset % 4); } - // const initialData = new Uint8Array(out.length) - // , buffers = [initialData] - // ; - // for (let i=0,l=out.length; i {data: view, offset: 0}; - // FIXME: we should rather just append the bytes to a new buffer - // no need to parse into an array ... - , p = new parse.Parser(table.data, table.offset) - ; - - - offset = tableEntry.outOffset + tableEntry.length; - const padding = (offset % 4) !== 0 - ? 4 - (offset % 4) - : 0 + , offset = tableEntry.outOffset + tableEntry.length + , padding = (offset % 4) !== 0 + ? 4 - (offset % 4) + : 0 ; - // buffers.push( - // new DataView(table.data.buffer, table.offset, tableEntry.length) - // , new ArrayBuffer(padding) - // ); - out.push( - p.parseByteList(tableEntry.length) - , Array(padding).fill(0) // new ArrayBuffer(padding) + buffers.push( + new Uint8Array(table.data.buffer, table.offset, tableEntry.length) + , new Uint8Array(padding) ); } - const outFlat = out.flat(); - - // const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); - // buffers.reduce((offset, buffer)=>{ - // result.set(buffer, offset) - // return offset + buffer.byteLength - // }, 0) - // return result.buffer; - const outArray = new Uint8Array(outFlat.length); - for (let i=0,l=outFlat.length; iaccum+buffer.byteLength, 0)); + buffers.reduce((offset, buffer)=>{ + result.set(buffer, offset); + return offset + buffer.byteLength; + }, 0); + return result.buffer; } export { From eab791afa033faaa64fdd1ad78d427b2e3843600 Mon Sep 17 00:00:00 2001 From: Lasse Fister Date: Tue, 26 Mar 2024 10:48:54 +0100 Subject: [PATCH 5/9] [bin/ot] add woff_2_otf as subcommand --- bin/ot | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/bin/ot b/bin/ot index af990cd2..0f5dbf8f 100755 --- a/bin/ot +++ b/bin/ot @@ -1,9 +1,11 @@ #!/usr/bin/env node /* eslint no-console: off */ -import fs from 'fs'; -import path from 'path'; -import { load } from '../src/opentype'; +const process = require('process') + , fs = require('fs') + , path = require('path') + , { load, woff_to_otf } = require('../dist/opentype.js') + ; // Print out information about the font on the console. function printFontInfo(font) { @@ -30,11 +32,13 @@ function walk(dir, fn) { // Print out usage information. function printUsage() { - console.log('Usage: ot command [dir|file]'); + console.log('Usage: ot [...args]'); console.log(); console.log('Commands:'); console.log(); - console.log(' info Get information of specified font or fonts in the specified directory.'); + console.log(' info [dir|file] Get information of specified font or fonts in the specified directory.'); + console.log(); + console.log(' woff_2_otf [otf_font_file] Uncompress woff file into otf.'); console.log(); } @@ -65,7 +69,7 @@ if (process.argv.length < 3) { } else { var command = process.argv[2]; if (command === 'info') { - var fontpath = process.argv.length === 3 ? '.' : process.argv[3]; + var fontpath = process.argv.length === 4 ? '.' : process.argv[3]; if (fs.existsSync(fontpath)) { var ext = path.extname(fontpath).toLowerCase(); if (fs.statSync(fontpath).isDirectory()) { @@ -78,6 +82,24 @@ if (process.argv.length < 3) { } else { console.log('Path not found'); } + } + else if (command === 'woff_2_otf') { + if(process.argv.length < 4 ){ + printUsage(); + process.exit(1); + } + const fontpath = process.argv[3]; + if (!fs.existsSync(fontpath)) { + console.log(`Font file at path not found.`); + process.exit(1); + } + const targetPath = process.argv.length >= 5 + ? process.argv[4] + : `${path.join(path.dirname(fontpath), path.basename(fontpath, path.extname(fontpath)))}.otf` + , buffer = fs.readFileSync(fontpath) + , result = woff_to_otf(buffer) + ; + fs.writeFileSync(targetPath, new DataView(result)); } else { printUsage(); } From 505907dabdc97e9814d012241107d40115d85a7d Mon Sep 17 00:00:00 2001 From: Lasse Fister Date: Tue, 26 Mar 2024 11:02:31 +0100 Subject: [PATCH 6/9] Read checksum in parseWOFFTableEntries. --- src/opentype.mjs | 3 ++- src/woff-to-otf.mjs | 24 +----------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/opentype.mjs b/src/opentype.mjs index 73f2d161..9c1cae4e 100644 --- a/src/opentype.mjs +++ b/src/opentype.mjs @@ -80,6 +80,7 @@ function parseWOFFTableEntries(data, numTables) { const offset = parse.getULong(data, p + 4); const compLength = parse.getULong(data, p + 8); const origLength = parse.getULong(data, p + 12); + const checksum = parse.getULong(data, p + 16); let compression; if (compLength < origLength) { compression = 'WOFF'; @@ -88,7 +89,7 @@ function parseWOFFTableEntries(data, numTables) { } tableEntries.push({tag: tag, offset: offset, compression: compression, - compressedLength: compLength, length: origLength}); + compressedLength: compLength, length: origLength, checksum: checksum}); p += 20; } diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs index 3cbff343..51e9766f 100644 --- a/src/woff-to-otf.mjs +++ b/src/woff-to-otf.mjs @@ -25,7 +25,6 @@ function woff_to_otf(buffer) { if (signature !== 'wOFF') throw new Error(`TYPE ERROR signature must be wOFF but is: "${signature}"`); - // need flavour??? -> opentype header syff! const flavor = parse.getTag(data, 4) , numTables = parse.getUShort(data, 12) , tableEntries = parseWOFFTableEntries(data, numTables) @@ -48,28 +47,7 @@ function woff_to_otf(buffer) { , ...encode.USHORT(entrySelector) , ...encode.USHORT(rangeShift) ); - let offset = out.length; - for (let i=0; i Date: Tue, 26 Mar 2024 11:34:24 +0100 Subject: [PATCH 7/9] move woff_to_otf function into opentype.js --- src/opentype.mjs | 85 ++++++++++++++++++++++++++++++++++++++-- src/woff-to-otf.mjs | 94 --------------------------------------------- 2 files changed, 82 insertions(+), 97 deletions(-) delete mode 100644 src/woff-to-otf.mjs diff --git a/src/opentype.mjs b/src/opentype.mjs index 9c1cae4e..9ff1ba96 100644 --- a/src/opentype.mjs +++ b/src/opentype.mjs @@ -8,6 +8,7 @@ import Font from './font.mjs'; import Glyph from './glyph.mjs'; import { CmapEncoding, GlyphNames, addGlyphNames } from './encoding.mjs'; import parse from './parse.mjs'; +import { encode } from './types.mjs'; import BoundingBox from './bbox.mjs'; import Path from './path.mjs'; import cpal from './tables/cpal.mjs'; @@ -38,7 +39,6 @@ import meta from './tables/meta.mjs'; import gasp from './tables/gasp.mjs'; import svg from './tables/svg.mjs'; import { PaletteManager } from './palettes.mjs'; -import { woff_to_otf } from './woff-to-otf.mjs'; /** * The opentype library. * @namespace opentype @@ -467,6 +467,87 @@ function loadSync() { console.error('DEPRECATED! migrate to: opentype.parse(require("fs").readFileSync(url), opt)'); } +/** + * Convert/Uncompress a buffer of a woff font to otf/ttf without parsing + * table contents. + * @param {ArrayBuffer} + * @return {ArrayBuffer} + */ +function woff_to_otf(buffer) { + if (buffer.constructor !== ArrayBuffer) + buffer = new Uint8Array(buffer).buffer; + const data = new DataView(buffer, 0) + , out = [] + , signature = parse.getTag(data, 0) + ; + + if (signature !== 'wOFF') + throw new Error(`TYPE ERROR signature must be wOFF but is: "${signature}"`); + + const flavor = parse.getTag(data, 4) + , numTables = parse.getUShort(data, 12) + , tableEntries = parseWOFFTableEntries(data, numTables) + , max = [] + ; + for (let n = 0; n < 64; n++) { + if (Math.pow(2, n) > numTables) + break; + max.splice(0, Infinity, n, 2 ** n); + } + const searchRange = max[1] * 16 + , entrySelector = max[0] + , rangeShift = numTables * 16 - searchRange + ; + + out.push( + ...encode.TAG(flavor) + , ...encode.USHORT(numTables) + , ...encode.USHORT(searchRange) + , ...encode.USHORT(entrySelector) + , ...encode.USHORT(rangeShift) + ); + let offset = out.length + numTables * 16; + + for (let i=0; i {data: view, offset: 0}; + , offset = tableEntry.outOffset + tableEntry.length + , padding = (offset % 4) !== 0 + ? 4 - (offset % 4) + : 0 + ; + buffers.push( + new Uint8Array(table.data.buffer, table.offset, tableEntry.length) + , new Uint8Array(padding) + ); + } + const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); + buffers.reduce((offset, buffer)=>{ + result.set(buffer, offset); + return offset + buffer.byteLength; + }, 0); + return result.buffer; +} + export { Font, Glyph, @@ -476,7 +557,5 @@ export { parseBuffer as parse, load, loadSync, - parseWOFFTableEntries, - uncompressTable, woff_to_otf }; diff --git a/src/woff-to-otf.mjs b/src/woff-to-otf.mjs deleted file mode 100644 index 51e9766f..00000000 --- a/src/woff-to-otf.mjs +++ /dev/null @@ -1,94 +0,0 @@ -// CAUTION this is a dependency cycle, but since the dependencies are -// on execution time of woff_to_otf it only looks statically like a problem. -// still, maybe parseWOFFTableEntries and uncompressTable should not be -// in opentype.js or maybe woff_to_otf could move into opentype.js -import { // eslint-disable-line - parseWOFFTableEntries, - uncompressTable -} from './opentype.mjs'; - -import parse from './parse.mjs'; -import { encode } from './types.mjs'; - -// I looked at -// https://github.com/hanikesn/woff2otf -// and https://github.com/mondeja/woff2otf -// but I'm doing it using opentype.js infrastructure. -function woff_to_otf(buffer) { - if (buffer.constructor !== ArrayBuffer) - buffer = new Uint8Array(buffer).buffer; - const data = new DataView(buffer, 0) - , out = [] - , signature = parse.getTag(data, 0) - ; - - if (signature !== 'wOFF') - throw new Error(`TYPE ERROR signature must be wOFF but is: "${signature}"`); - - const flavor = parse.getTag(data, 4) - , numTables = parse.getUShort(data, 12) - , tableEntries = parseWOFFTableEntries(data, numTables) - , max = [] - ; - for (let n = 0; n < 64; n++) { - if (Math.pow(2, n) > numTables) - break; - max.splice(0, Infinity, n, 2 ** n); - } - const searchRange = max[1] * 16 - , entrySelector = max[0] - , rangeShift = numTables * 16 - searchRange - ; - - out.push( - ...encode.TAG(flavor) - , ...encode.USHORT(numTables) - , ...encode.USHORT(searchRange) - , ...encode.USHORT(entrySelector) - , ...encode.USHORT(rangeShift) - ); - let offset = out.length + numTables * 16; - - for (let i=0; i {data: view, offset: 0}; - , offset = tableEntry.outOffset + tableEntry.length - , padding = (offset % 4) !== 0 - ? 4 - (offset % 4) - : 0 - ; - buffers.push( - new Uint8Array(table.data.buffer, table.offset, tableEntry.length) - , new Uint8Array(padding) - ); - } - const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0)); - buffers.reduce((offset, buffer)=>{ - result.set(buffer, offset); - return offset + buffer.byteLength; - }, 0); - return result.buffer; -} - -export { - woff_to_otf -}; From e4a2406766f4e44fcbc19175d7c463aec239f8eb Mon Sep 17 00:00:00 2001 From: Lasse Fister Date: Tue, 26 Mar 2024 12:23:08 +0100 Subject: [PATCH 8/9] rename woff_to_of woffToOTF --- bin/ot | 4 ++-- src/opentype.mjs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/ot b/bin/ot index 0f5dbf8f..b649b8e8 100755 --- a/bin/ot +++ b/bin/ot @@ -4,7 +4,7 @@ const process = require('process') , fs = require('fs') , path = require('path') - , { load, woff_to_otf } = require('../dist/opentype.js') + , { load, woffToOTF } = require('../dist/opentype.js') ; // Print out information about the font on the console. @@ -97,7 +97,7 @@ if (process.argv.length < 3) { ? process.argv[4] : `${path.join(path.dirname(fontpath), path.basename(fontpath, path.extname(fontpath)))}.otf` , buffer = fs.readFileSync(fontpath) - , result = woff_to_otf(buffer) + , result = woffToOTF(buffer) ; fs.writeFileSync(targetPath, new DataView(result)); } else { diff --git a/src/opentype.mjs b/src/opentype.mjs index 9ff1ba96..f9bedd35 100644 --- a/src/opentype.mjs +++ b/src/opentype.mjs @@ -473,7 +473,7 @@ function loadSync() { * @param {ArrayBuffer} * @return {ArrayBuffer} */ -function woff_to_otf(buffer) { +function woffToOTF(buffer) { if (buffer.constructor !== ArrayBuffer) buffer = new Uint8Array(buffer).buffer; const data = new DataView(buffer, 0) @@ -557,5 +557,5 @@ export { parseBuffer as parse, load, loadSync, - woff_to_otf + woffToOTF }; From d0ffa7264b773a5e837486ef776199c784168ae4 Mon Sep 17 00:00:00 2001 From: Lasse Fister Date: Tue, 26 Mar 2024 12:35:05 +0100 Subject: [PATCH 9/9] make eslint happy --- bin/ot | 18 ++++++-------- src/opentype.mjs | 63 +++++++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/bin/ot b/bin/ot index b649b8e8..c710699a 100755 --- a/bin/ot +++ b/bin/ot @@ -1,11 +1,10 @@ #!/usr/bin/env node /* eslint no-console: off */ -const process = require('process') - , fs = require('fs') - , path = require('path') - , { load, woffToOTF } = require('../dist/opentype.js') - ; +const process = require('process'), + fs = require('fs'), + path = require('path'), + { load, woffToOTF } = require('../dist/opentype.js'); // Print out information about the font on the console. function printFontInfo(font) { @@ -90,15 +89,14 @@ if (process.argv.length < 3) { } const fontpath = process.argv[3]; if (!fs.existsSync(fontpath)) { - console.log(`Font file at path not found.`); + console.log('Font file at path not found.'); process.exit(1); } const targetPath = process.argv.length >= 5 ? process.argv[4] - : `${path.join(path.dirname(fontpath), path.basename(fontpath, path.extname(fontpath)))}.otf` - , buffer = fs.readFileSync(fontpath) - , result = woffToOTF(buffer) - ; + : `${path.join(path.dirname(fontpath), path.basename(fontpath, path.extname(fontpath)))}.otf`, + buffer = fs.readFileSync(fontpath), + result = woffToOTF(buffer); fs.writeFileSync(targetPath, new DataView(result)); } else { printUsage(); diff --git a/src/opentype.mjs b/src/opentype.mjs index f9bedd35..05084b2e 100644 --- a/src/opentype.mjs +++ b/src/opentype.mjs @@ -476,68 +476,65 @@ function loadSync() { function woffToOTF(buffer) { if (buffer.constructor !== ArrayBuffer) buffer = new Uint8Array(buffer).buffer; - const data = new DataView(buffer, 0) - , out = [] - , signature = parse.getTag(data, 0) - ; + + const data = new DataView(buffer, 0), + out = [], + signature = parse.getTag(data, 0); if (signature !== 'wOFF') throw new Error(`TYPE ERROR signature must be wOFF but is: "${signature}"`); - const flavor = parse.getTag(data, 4) - , numTables = parse.getUShort(data, 12) - , tableEntries = parseWOFFTableEntries(data, numTables) - , max = [] - ; + const flavor = parse.getTag(data, 4), + numTables = parse.getUShort(data, 12), + tableEntries = parseWOFFTableEntries(data, numTables), + max = []; for (let n = 0; n < 64; n++) { if (Math.pow(2, n) > numTables) break; max.splice(0, Infinity, n, 2 ** n); } - const searchRange = max[1] * 16 - , entrySelector = max[0] - , rangeShift = numTables * 16 - searchRange - ; + + const searchRange = max[1] * 16, + entrySelector = max[0], + rangeShift = numTables * 16 - searchRange; out.push( - ...encode.TAG(flavor) - , ...encode.USHORT(numTables) - , ...encode.USHORT(searchRange) - , ...encode.USHORT(entrySelector) - , ...encode.USHORT(rangeShift) + ...encode.TAG(flavor), + ...encode.USHORT(numTables), + ...encode.USHORT(searchRange), + ...encode.USHORT(entrySelector), + ...encode.USHORT(rangeShift) ); let offset = out.length + numTables * 16; for (let i=0; i {data: view, offset: 0}; - , offset = tableEntry.outOffset + tableEntry.length - , padding = (offset % 4) !== 0 + const tableEntry = tableEntries[i], + table = uncompressTable(data, tableEntry), // => {data: view, offset: 0}; + offset = tableEntry.outOffset + tableEntry.length, + padding = (offset % 4) !== 0 ? 4 - (offset % 4) - : 0 - ; + : 0; buffers.push( - new Uint8Array(table.data.buffer, table.offset, tableEntry.length) - , new Uint8Array(padding) + new Uint8Array(table.data.buffer, table.offset, tableEntry.length), + new Uint8Array(padding) ); } const result = new Uint8Array(buffers.reduce((accum, buffer)=>accum+buffer.byteLength, 0));