Skip to content

Commit 9205c29

Browse files
committed
Step 4.6: Create font parser so we can convert 'xml' font format to 'json'
1 parent 6db3b1b commit 9205c29

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

helpers/font_parser.js

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
const _ = require("underscore");
2+
const Async = require("async");
3+
const Fs = require("fs");
4+
const Path = require("path");
5+
const { DOMParser } = require("xmldom");
6+
7+
if (module === require.main) {
8+
let fonstDir = Path.resolve(__dirname, "../resources/assets/fonts");
9+
xmlsToJsons(fonstDir, err => { if (err) throw err });
10+
}
11+
12+
// Gets a dir path containing font xmls and converts them all to jsons
13+
function xmlsToJsons(path, callback = _.noop) {
14+
Fs.readdir(path, (err, files) => {
15+
if (err) return callback(err);
16+
17+
// Remove all extensions
18+
fileNames = _.uniq(files.map(file => file.split(".")[0]));
19+
20+
// Convert each xml individually
21+
Async.each(fileNames, (fileName, next) => {
22+
xmlToJson(`${path}/${fileName}`, next);
23+
},
24+
(err) => {
25+
if (!err) console.log(
26+
'All fonts have been successfully parsed!'
27+
);
28+
29+
callback(err);
30+
});
31+
});
32+
}
33+
34+
// Gets a font xml and converts it to json
35+
function xmlToJson(path, callback = _.noop) {
36+
Async.waterfall([
37+
(next) => {
38+
Fs.readFile(`${path}.xml`, function(err, xmlBuffer) {
39+
if (err) return next(err);
40+
41+
let json = {
42+
chars: {}
43+
};
44+
45+
let xml = xmlBuffer.toString();
46+
let doc = new DOMParser().parseFromString(xml);
47+
let fontDoc = doc.getElementsByTagName("Font")[0];
48+
let charsDoc = fontDoc.getElementsByTagName("Char");
49+
50+
// Compose meta-data about font like size and family
51+
_.each(fontDoc.attributes, (attr) => {
52+
json[attr.name] = parseInt(attr.value) || attr.value;
53+
});
54+
55+
// Compose data about each character in font
56+
_.each(charsDoc, (charDoc) => {
57+
let charCode = charDoc.getAttribute("code");
58+
59+
let char = json.chars[charCode] = {
60+
rect: rect = {},
61+
offset: offset = {},
62+
width: parseInt(charDoc.getAttribute("width"))
63+
};
64+
65+
[
66+
rect.x,
67+
rect.y,
68+
rect.width,
69+
rect.height
70+
] = extractIntegers(charDoc.getAttribute("rect"));
71+
72+
[offset.x, offset.y] = extractIntegers(charDoc.getAttribute("offset"));
73+
});
74+
75+
next(null, JSON.stringify(json, null, 2));
76+
});
77+
},
78+
(json, next) => {
79+
// Once finished, write json into file
80+
Fs.writeFile(path + ".json", json, (err) => {
81+
next(err);
82+
});
83+
}
84+
], (err) => {
85+
if (!err) console.log(
86+
`Font ${path} has been successfully parsed...`
87+
);
88+
89+
callback(err);
90+
});
91+
};
92+
93+
// Converts an string of numbers to array of numbers
94+
// e.g. extractIntegers("1 2 3") -> [1, 2, 3]
95+
function extractIntegers(srcstr) {
96+
return srcstr.split(" ").map((substr) => parseInt(substr));
97+
}
98+
99+
module.exports = {
100+
xmlToJson,
101+
xmlsToJsons
102+
};

0 commit comments

Comments
 (0)