Skip to content

Commit

Permalink
converted to JavaScript
Browse files Browse the repository at this point in the history
  • Loading branch information
arty-name committed Nov 21, 2014
1 parent 2ec08de commit 57a5bb8
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 115 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__pycache__
.idea
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# woff2otf

This is a small utility to convert WOFF files to the OTF font format. It uses Python 3, so you need to have it installed in order to run it.
This is a small utility to convert WOFF files to the OTF font format. It uses Javascript, so you can run it in the browser. It depends on the [port of zlib to javascript](https://github.com/nodeca/pako), you need to include [this file](https://github.com/nodeca/pako/blob/master/dist/pako_inflate.js) in your page. Or just [go to this page to convert WOFF to OTF online](https://arty.name/woff2otf/).

## Usage
To run the script, simply invoke it from the command line:

```
./woff2otf.py font.woff font.otf
convert_streams(<ArrayBuffer>) // returns <ArrayBuffer> containing OTF font
```

The first parameter is the source file (the WOFF) font, and the second parameter is the output file (in OTF format).
## Credits

Big thanks to Steffen Hanikel for his Python implementation of this script, which I later converted to Javascript.
Empty file removed __init__.py
Empty file.
151 changes: 151 additions & 0 deletions woff2otf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
Copyright 2012, Steffen Hanikel (https://github.com/hanikesn)
Modified by Artemy Tregubenko, 2014 (https://github.com/arty-name/woff2otf)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
A tool to convert a WOFF back to a TTF/OTF font file, in pure Javascript
*/

function zlib_decompress(buffer) {
var inflate = new pako.Inflate();
inflate.push(new Uint8Array(buffer), true);
if (inflate.err) {
throw new Error(inflate.err);
}
return inflate.result;
}

function convert_streams(bufferIn) {
var dataViewIn = new DataView(bufferIn);
var offsetIn = 0;

function read2() {
var uint16 = dataViewIn.getUint16(offsetIn);
offsetIn += 2;
return uint16;
}

function read4() {
var uint32 = dataViewIn.getUint32(offsetIn);
offsetIn += 4;
return uint32;
}

function write2(uint16) {
dataViewOut.setUint16(offsetOut, uint16);
offsetOut += 2;
}

function write4(uint32) {
dataViewOut.setUint32(offsetOut, uint32);
offsetOut += 4;
}

var WOFFHeader = {
signature: read4(),
flavor: read4(),
length: read4(),
numTables: read2(),
reserved: read2(),
totalSfntSize: read4(),
majorVersion: read2(),
minorVersion: read2(),
metaOffset: read4(),
metaLength: read4(),
metaOrigLength: read4(),
privOffset: read4(),
privLength: read4()
};

var entrySelector = 0;
while (Math.pow(2, entrySelector) <= WOFFHeader.numTables) {
entrySelector++;
}
entrySelector--;

var searchRange = Math.pow(2, entrySelector) * 16;
var rangeShift = WOFFHeader.numTables * 16 - searchRange;

var offset = 4 + 2 + 2 + 2 + 2;
var TableDirectoryEntries = [];
for (var i = 0; i < WOFFHeader.numTables; i++) {
TableDirectoryEntries.push({
tag: read4(),
offset: read4(),
compLength: read4(),
origLength: read4(),
origChecksum: read4()
});
offset += 4 * 4;
}

var arrayOut = new Uint8Array(
4 + 2 + 2 + 2 + 2 +
TableDirectoryEntries.length * (4 + 4 + 4 + 4) +
TableDirectoryEntries.reduce(function(acc, entry) { return acc + entry.origLength + 4; }, 0)
);
var bufferOut = arrayOut.buffer;
var dataViewOut = new DataView(bufferOut);
var offsetOut = 0;

write4(WOFFHeader.flavor);
write2(WOFFHeader.numTables);
write2(searchRange);
write2(entrySelector);
write2(rangeShift);

TableDirectoryEntries.forEach(function(TableDirectoryEntry) {
write4(TableDirectoryEntry.tag);
write4(TableDirectoryEntry.origChecksum);
write4(offset);
write4(TableDirectoryEntry.origLength);

TableDirectoryEntry.outOffset = offset;
offset += TableDirectoryEntry.origLength;
if ((offset % 4) != 0) {
offset += 4 - (offset % 4)
}
});

var size;

TableDirectoryEntries.forEach(function(TableDirectoryEntry) {
var compressedData = bufferIn.slice(
TableDirectoryEntry.offset,
TableDirectoryEntry.offset + TableDirectoryEntry.compLength
);

if (TableDirectoryEntry.compLength != TableDirectoryEntry.origLength) {
var uncompressedData = zlib_decompress(compressedData);
} else {
uncompressedData = new Uint8Array(compressedData);
}

arrayOut.set(uncompressedData, TableDirectoryEntry.outOffset);
offset = TableDirectoryEntry.outOffset + TableDirectoryEntry.origLength;

var padding = 0;
if ((offset % 4) != 0) {
padding = 4 - (offset % 4);
}
arrayOut.set(
new Uint8Array(padding).buffer,
TableDirectoryEntry.outOffset + TableDirectoryEntry.origLength
);

size = offset + padding;
});

return bufferOut.slice(0, size);
}
110 changes: 0 additions & 110 deletions woff2otf.py

This file was deleted.

0 comments on commit 57a5bb8

Please sign in to comment.