-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathindex.html
146 lines (134 loc) · 4.67 KB
/
index.html
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<meta charset="utf-8">
<p><a href="https://github.com/harfbuzz/harfbuzzjs">harfbuzzjs</a> demo. Supports font drag and drop.</p>
<p><input type="text" value="abc" id="text"></p>
<p><a id="svgResult" href="#" title="Click to download"></a></p>
<p>Result:<div id="shapeResult"></div></p>
<script src="hbjs.js"></script> <!-- Wrapper, can be used without -->
<script>
'use strict';
var hb, fontBlob;
function updateResult() {
var blob = hb.createBlob(fontBlob);
var face = hb.createFace(blob, 0);
var font = hb.createFont(face);
font.setScale(1000, 1000); // Optional, if not given will be in font upem
var buffer = hb.createBuffer();
buffer.addText(text.value);
buffer.guessSegmentProperties();
// buffer.setDirection('ltr'); // optional as can be by guessSegmentProperties also
hb.shape(font, buffer); // features are not supported yet
var result = buffer.json(font);
// returns glyphs paths, totally optional
var glyphs = {};
result.forEach(function (x) {
if (glyphs[x.g]) return;
glyphs[x.g] = font.glyphToJson(x.g);
});
buffer.destroy();
font.destroy();
face.destroy();
blob.destroy();
var xmin = 10000;
var xmax = -10000;
var ymin = 10000;
var ymax = -10000;
var ax = 0;
var ay = 0;
var path = pathToRelative(result.map(function (x) {
var result = glyphs[x.g].filter(function (command) {
return command.type !== 'Z';
}).map(function (command) {
var result = command.values.map(function (p, i) {
// apply ax/ay/dx/dy to coords
return i % 2 ? -(p + ay + x.dy) : p + ax + x.dx;
}).map(function (x, i) {
// bbox calc
if (i % 2) {
if (x < ymin) ymin = x;
if (x > ymax) ymax = x;
} else {
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
return x;
});
return [command.type].concat(result);
});
ax += x.ax; ay += x.ay;
return result;
}).reduce((acc, val) => acc.concat(val), [])).map(x => x[0] + x.slice(1).join(' ')).join('').replace(/ -/g, '-');
var width = xmax - xmin;
var height = ymax - ymin;
// pad it a bit
var pad = Math.round(Math.min(width / 10, height / 10));
xmin -= pad;
ymin -= pad;
width += pad * 2;
height += pad * 2;
var bbox = xmin + ' ' + ymin + ' ' + width + ' ' + height;
svgResult.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="128" viewBox="' + bbox + '">' +
'<path d="' + path + '" /></svg>';
svgResult.download = text.value + '.svg';
// revoke previous URL
if (svgResult.href) URL.revokeObjectURL(svgResult.href);
svgResult.href = URL.createObjectURL(new Blob([svgResult.innerHTML.replace(' height="128"', '')], { type: 'text/plain' }));
shapeResult.innerText = JSON.stringify(result);
}
// We could use instantiateStreaming but it's not supported in Safari yet
// https://bugs.webkit.org/show_bug.cgi?id=173105
fetch("hb.wasm").then(function (x) {
return x.arrayBuffer();
}).then(function (wasm) {
return WebAssembly.instantiate(wasm);
}).then(function (result) {
result.instance.exports.memory.grow(400); // each page is 64kb in size
window.hb = hbjs(result.instance);
fetch('Roboto.abc.ttf').then(function (res) {
return res.arrayBuffer();
}).then(function (blob) { // can be used without our wrapper
window.fontBlob = new Uint8Array(blob);
updateResult();
});
});
document.getElementById('text').addEventListener('keyup', function(e) {
updateResult();
});
document.addEventListener('dragover', function (e) {
e.stopPropagation(); e.preventDefault();
}, false);
document.addEventListener('dragleave', function (e) {
e.stopPropagation(); e.preventDefault();
}, false);
document.addEventListener('drop', function (e) {
e.stopPropagation(); e.preventDefault();
handleFontUpdate(e.dataTransfer.files[0]);
});
// document.addEventListener('paste', function (e) {
// handleFontUpdate(e.clipboardData.files[0]);
// });
function handleFontUpdate(file) {
if (!file) return;
var reader = new FileReader();
reader.addEventListener("load", function () {
window.fontBlob = new Uint8Array(reader.result);
updateResult();
});
reader.readAsArrayBuffer(file);
}
// Totally optional, https://github.com/adobe-webplatform/Snap.svg/blob/7abe4d1/src/path.js#L532
function pathToRelative(pathArray) {
if (!pathArray.length) return [];
var x = pathArray[0][1], y = pathArray[0][2];
var prevCmd = '';
return [["M", x, y]].concat(pathArray.slice(1).map(function (pa) {
var r = [prevCmd === pa[0] ? ' ' : pa[0].toLowerCase()].concat(pa.slice(1).map(function (z, i) {
return z - ((i % 2) ? y : x);
}));
var lastPoint = r.slice(-2);
x += lastPoint[0];
y += lastPoint[1];
prevCmd = pa[0];
return r;
}));
}
</script>