-
Notifications
You must be signed in to change notification settings - Fork 0
/
hb-transform.js
95 lines (68 loc) · 2.86 KB
/
hb-transform.js
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
importScripts('https://harfbuzz.github.io/harfbuzzjs/hbjs.js');
var hb = null;
var font = null;
var encoding = {};
async function prepare() {
const wasm = await fetch("https://harfbuzz.github.io/harfbuzzjs/hb.wasm");
const wasmInstance = await WebAssembly.instantiate(await wasm.arrayBuffer());
hb = hbjs(wasmInstance.instance);
const rawFont = await fetch('https://wipfli.github.io/maplibre-feature-properties-transform-example/NotoSansDevanagari-Regular.ttf');
// const rawFont = await fetch('http://localhost:3000/Frutiger-Neue-Regular.ttf');
var fontBlob = new Uint8Array(await rawFont.arrayBuffer());
var blob = hb.createBlob(fontBlob);
var face = hb.createFace(blob, 0);
font = hb.createFont(face);
font.setScale(1000, 1000);
const encodingRaw = await fetch('https://wipfli.github.io/maplibre-feature-properties-transform-example/encoding.csv');
const encodingCSV = await encodingRaw.text();
const encodingLines = encodingCSV.split('\n');
for (var line of encodingLines.slice(1)) {
const [index, x_offset, y_offset, x_advance, y_advance, codepoint] = line.split(',');
encoding[`${index}/${x_offset}/${y_offset}/${x_advance}/${y_advance}`] = +codepoint;
}
self.setFeaturePropertiesTransform(featurePropertiesTransform);
}
prepare();
function getCodepoint(positionedGlyph) {
const index = positionedGlyph['g'];
const x_offset = Math.round(positionedGlyph['dx'] / 64);
const y_offset = Math.round(positionedGlyph['dy'] / 64);
const x_advance = Math.round(positionedGlyph['ax'] / 64);
const y_advance = Math.round(positionedGlyph['ay'] / 64);
var key = '';
key = `${index}/${x_offset}/${y_offset}/${x_advance}/${y_advance}`;
if (encoding[key] !== undefined) {
return encoding[key]
}
key = `${index}/${x_offset}/${y_offset}/${x_advance + 1}/${y_advance}`;
if (encoding[key] !== undefined) {
return encoding[key]
}
key = `${index}/${x_offset}/${y_offset}/${x_advance - 1}/${y_advance}`;
if (encoding[key] !== undefined) {
return encoding[key]
}
key = `${index}/${x_offset}/${y_offset}/${x_advance}/${y_advance}`;
console.log(key, 'not found');
return 65; // Capital A - means no codepoint found
}
function shape(text) {
var buffer = hb.createBuffer();
buffer.addText(text);
buffer.guessSegmentProperties();
hb.shape(font, buffer);
return buffer.json(font);
}
function encode(text) {
var result = ''
var glyphVector = shape(text);
for (var positionedGlyph of glyphVector) {
result += String.fromCharCode(getCodepoint(positionedGlyph));
}
return result;
}
const featurePropertiesTransform = (source, sourceLayer, tileID, geometryType, featureID, properties) => {
if ('name:hi' in properties) {
properties['name:hi'] = encode(properties['name:hi'])
}
};