mirror of
https://github.com/mapbox/node-fontnik.git
synced 2026-01-18 15:54:55 +00:00
re-add tests
This commit is contained in:
parent
03d5087b06
commit
360df418bf
341
test/expected/serialize.json
Normal file
341
test/expected/serialize.json
Normal file
@ -0,0 +1,341 @@
|
||||
{
|
||||
"layers": {
|
||||
"landuse": {
|
||||
"version": 1,
|
||||
"name": "landuse",
|
||||
"extent": 4096,
|
||||
"length": 3,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"osm_id"
|
||||
],
|
||||
"_values": [
|
||||
"park",
|
||||
0,
|
||||
0,
|
||||
"sand",
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
13,
|
||||
225,
|
||||
325
|
||||
]
|
||||
},
|
||||
"waterway": {
|
||||
"version": 1,
|
||||
"name": "waterway",
|
||||
"extent": 4096,
|
||||
"length": 11,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
102639147,
|
||||
"stream",
|
||||
28483936,
|
||||
28544165,
|
||||
28544279,
|
||||
28544488,
|
||||
28544489,
|
||||
28544658,
|
||||
28544491,
|
||||
28544660,
|
||||
28544661,
|
||||
28544659
|
||||
],
|
||||
"_features": [
|
||||
556,
|
||||
629,
|
||||
925,
|
||||
973,
|
||||
1049,
|
||||
1146,
|
||||
1193,
|
||||
1234,
|
||||
1272,
|
||||
1298,
|
||||
1357
|
||||
]
|
||||
},
|
||||
"water": {
|
||||
"version": 1,
|
||||
"name": "water",
|
||||
"extent": 4096,
|
||||
"length": 5,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"osm_id"
|
||||
],
|
||||
"_values": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
1555,
|
||||
2026,
|
||||
2107,
|
||||
2153,
|
||||
2201
|
||||
]
|
||||
},
|
||||
"road": {
|
||||
"version": 1,
|
||||
"name": "road",
|
||||
"extent": 4096,
|
||||
"length": 37,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"oneway",
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
"street_limited",
|
||||
0,
|
||||
12176014,
|
||||
"residential",
|
||||
"street",
|
||||
102638413,
|
||||
12190176,
|
||||
125871922,
|
||||
"unclassified",
|
||||
12172969,
|
||||
12171395,
|
||||
12172974,
|
||||
12171388,
|
||||
12176906,
|
||||
12184872,
|
||||
12188141,
|
||||
82660225,
|
||||
12185663,
|
||||
232292986,
|
||||
236784059,
|
||||
12187833,
|
||||
12180093,
|
||||
12181692,
|
||||
12179250,
|
||||
12182785,
|
||||
207142176,
|
||||
232292987,
|
||||
12181251,
|
||||
112429240,
|
||||
12172937,
|
||||
12178793,
|
||||
12184634,
|
||||
12175654,
|
||||
12187257,
|
||||
12183699,
|
||||
"main",
|
||||
112926169,
|
||||
"primary",
|
||||
239213058,
|
||||
174215004,
|
||||
157338248,
|
||||
174215024,
|
||||
88159974,
|
||||
"tertiary",
|
||||
12177297,
|
||||
12177319
|
||||
],
|
||||
"_features": [
|
||||
2402,
|
||||
2524,
|
||||
2619,
|
||||
2653,
|
||||
2767,
|
||||
2836,
|
||||
2870,
|
||||
2903,
|
||||
2981,
|
||||
3009,
|
||||
3042,
|
||||
3070,
|
||||
3107,
|
||||
3144,
|
||||
3214,
|
||||
3245,
|
||||
3367,
|
||||
3427,
|
||||
3470,
|
||||
3501,
|
||||
3546,
|
||||
3615,
|
||||
3660,
|
||||
3689,
|
||||
3719,
|
||||
3772,
|
||||
3822,
|
||||
3857,
|
||||
3889,
|
||||
3923,
|
||||
4101,
|
||||
4159,
|
||||
4281,
|
||||
4570,
|
||||
4611,
|
||||
4919,
|
||||
4958
|
||||
]
|
||||
},
|
||||
"bridge": {
|
||||
"version": 1,
|
||||
"name": "bridge",
|
||||
"extent": 4096,
|
||||
"length": 2,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"oneway",
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
"service",
|
||||
0,
|
||||
207142221,
|
||||
"track",
|
||||
"street",
|
||||
207142175,
|
||||
"residential"
|
||||
],
|
||||
"_features": [
|
||||
5723,
|
||||
5752
|
||||
]
|
||||
},
|
||||
"place_label": {
|
||||
"version": 1,
|
||||
"name": "place_label",
|
||||
"extent": 4096,
|
||||
"length": 3,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"type",
|
||||
"ldir",
|
||||
"scalerank"
|
||||
],
|
||||
"_values": [
|
||||
"Mill Valley",
|
||||
0,
|
||||
"town",
|
||||
"",
|
||||
"Tamalpais Valley",
|
||||
0,
|
||||
0,
|
||||
"hamlet",
|
||||
"Muir Beach",
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
6058,
|
||||
6096,
|
||||
6138
|
||||
]
|
||||
},
|
||||
"poi_label": {
|
||||
"version": 1,
|
||||
"name": "poi_label",
|
||||
"extent": 4096,
|
||||
"length": 1,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"localrank",
|
||||
"maki",
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"ref",
|
||||
"scalerank",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
1,
|
||||
"park",
|
||||
"Muir Woods National Monument",
|
||||
0,
|
||||
"",
|
||||
"Park"
|
||||
],
|
||||
"_features": [
|
||||
6406
|
||||
]
|
||||
},
|
||||
"road_label": {
|
||||
"version": 1,
|
||||
"name": "road_label",
|
||||
"extent": 4096,
|
||||
"length": 7,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"len",
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"ref",
|
||||
"reflen"
|
||||
],
|
||||
"_values": [
|
||||
"main",
|
||||
7396.168723572097,
|
||||
"Panoramic Hwy",
|
||||
"Panoramic Highway",
|
||||
88159974,
|
||||
"",
|
||||
0,
|
||||
4357.193150547803,
|
||||
"Shoreline Hwy",
|
||||
"Shoreline Highway",
|
||||
157338250,
|
||||
3528.44005555027,
|
||||
174215024,
|
||||
2928.2679350617123,
|
||||
125871918,
|
||||
7600.032638046431,
|
||||
12177319,
|
||||
2513.4221036393283,
|
||||
174215004,
|
||||
1716.9016582189813,
|
||||
12188378
|
||||
],
|
||||
"_features": [
|
||||
6622,
|
||||
6783,
|
||||
6879,
|
||||
7328,
|
||||
7512,
|
||||
8269,
|
||||
8570
|
||||
]
|
||||
}
|
||||
},
|
||||
"faces": {}
|
||||
}
|
||||
1137
test/expected/shape.json
Normal file
1137
test/expected/shape.json
Normal file
File diff suppressed because it is too large
Load Diff
337
test/expected/simplify.json
Normal file
337
test/expected/simplify.json
Normal file
@ -0,0 +1,337 @@
|
||||
{
|
||||
"layers": {
|
||||
"landuse": {
|
||||
"version": 2,
|
||||
"name": "landuse",
|
||||
"extent": 4096,
|
||||
"length": 3,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"osm_id"
|
||||
],
|
||||
"_values": [
|
||||
"park",
|
||||
0,
|
||||
0,
|
||||
"sand",
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
13,
|
||||
223,
|
||||
314
|
||||
]
|
||||
},
|
||||
"waterway": {
|
||||
"version": 2,
|
||||
"name": "waterway",
|
||||
"extent": 4096,
|
||||
"length": 11,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
102639147,
|
||||
"stream",
|
||||
28483936,
|
||||
28544165,
|
||||
28544279,
|
||||
28544488,
|
||||
28544489,
|
||||
28544658,
|
||||
28544491,
|
||||
28544660,
|
||||
28544661,
|
||||
28544659
|
||||
],
|
||||
"_features": [
|
||||
543,
|
||||
616,
|
||||
912,
|
||||
960,
|
||||
1036,
|
||||
1133,
|
||||
1180,
|
||||
1221,
|
||||
1259,
|
||||
1285,
|
||||
1344
|
||||
]
|
||||
},
|
||||
"water": {
|
||||
"version": 2,
|
||||
"name": "water",
|
||||
"extent": 4096,
|
||||
"length": 1,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"osm_id"
|
||||
],
|
||||
"_values": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
1542
|
||||
]
|
||||
},
|
||||
"road": {
|
||||
"version": 2,
|
||||
"name": "road",
|
||||
"extent": 4096,
|
||||
"length": 37,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"oneway",
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
"street_limited",
|
||||
0,
|
||||
12176014,
|
||||
"residential",
|
||||
"street",
|
||||
102638413,
|
||||
12190176,
|
||||
125871922,
|
||||
"unclassified",
|
||||
12172969,
|
||||
12171395,
|
||||
12172974,
|
||||
12171388,
|
||||
12176906,
|
||||
12184872,
|
||||
12188141,
|
||||
82660225,
|
||||
12185663,
|
||||
232292986,
|
||||
236784059,
|
||||
12187833,
|
||||
12180093,
|
||||
12181692,
|
||||
12179250,
|
||||
12182785,
|
||||
207142176,
|
||||
232292987,
|
||||
12181251,
|
||||
112429240,
|
||||
12172937,
|
||||
12178793,
|
||||
12184634,
|
||||
12175654,
|
||||
12187257,
|
||||
12183699,
|
||||
"main",
|
||||
112926169,
|
||||
"primary",
|
||||
239213058,
|
||||
174215004,
|
||||
157338248,
|
||||
174215024,
|
||||
88159974,
|
||||
"tertiary",
|
||||
12177297,
|
||||
12177319
|
||||
],
|
||||
"_features": [
|
||||
2190,
|
||||
2312,
|
||||
2407,
|
||||
2441,
|
||||
2555,
|
||||
2624,
|
||||
2658,
|
||||
2691,
|
||||
2769,
|
||||
2797,
|
||||
2830,
|
||||
2858,
|
||||
2895,
|
||||
2932,
|
||||
3002,
|
||||
3033,
|
||||
3155,
|
||||
3215,
|
||||
3258,
|
||||
3289,
|
||||
3334,
|
||||
3403,
|
||||
3448,
|
||||
3477,
|
||||
3507,
|
||||
3560,
|
||||
3610,
|
||||
3645,
|
||||
3677,
|
||||
3711,
|
||||
3889,
|
||||
3947,
|
||||
4069,
|
||||
4358,
|
||||
4399,
|
||||
4707,
|
||||
4746
|
||||
]
|
||||
},
|
||||
"bridge": {
|
||||
"version": 2,
|
||||
"name": "bridge",
|
||||
"extent": 4096,
|
||||
"length": 2,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"oneway",
|
||||
"osm_id",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
"service",
|
||||
0,
|
||||
207142221,
|
||||
"track",
|
||||
"street",
|
||||
207142175,
|
||||
"residential"
|
||||
],
|
||||
"_features": [
|
||||
5511,
|
||||
5540
|
||||
]
|
||||
},
|
||||
"place_label": {
|
||||
"version": 2,
|
||||
"name": "place_label",
|
||||
"extent": 4096,
|
||||
"length": 3,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"type",
|
||||
"ldir",
|
||||
"scalerank"
|
||||
],
|
||||
"_values": [
|
||||
"Mill Valley",
|
||||
0,
|
||||
"town",
|
||||
"",
|
||||
"Tamalpais Valley",
|
||||
0,
|
||||
0,
|
||||
"hamlet",
|
||||
"Muir Beach",
|
||||
0
|
||||
],
|
||||
"_features": [
|
||||
5682,
|
||||
5720,
|
||||
5762
|
||||
]
|
||||
},
|
||||
"poi_label": {
|
||||
"version": 2,
|
||||
"name": "poi_label",
|
||||
"extent": 4096,
|
||||
"length": 1,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"localrank",
|
||||
"maki",
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"ref",
|
||||
"scalerank",
|
||||
"type"
|
||||
],
|
||||
"_values": [
|
||||
1,
|
||||
"park",
|
||||
"Muir Woods National Monument",
|
||||
0,
|
||||
"",
|
||||
"Park"
|
||||
],
|
||||
"_features": [
|
||||
6010
|
||||
]
|
||||
},
|
||||
"road_label": {
|
||||
"version": 2,
|
||||
"name": "road_label",
|
||||
"extent": 4096,
|
||||
"length": 7,
|
||||
"shaping": {},
|
||||
"faces": [],
|
||||
"_keys": [
|
||||
"class",
|
||||
"len",
|
||||
"name",
|
||||
"name_de",
|
||||
"name_en",
|
||||
"name_es",
|
||||
"name_fr",
|
||||
"osm_id",
|
||||
"ref",
|
||||
"reflen"
|
||||
],
|
||||
"_values": [
|
||||
"main",
|
||||
7396.168723572097,
|
||||
"Panoramic Hwy",
|
||||
"Panoramic Highway",
|
||||
88159974,
|
||||
"",
|
||||
0,
|
||||
4357.193150547803,
|
||||
"Shoreline Hwy",
|
||||
"Shoreline Highway",
|
||||
157338250,
|
||||
3528.44005555027,
|
||||
174215024,
|
||||
2928.2679350617123,
|
||||
125871918,
|
||||
7600.032638046431,
|
||||
12177319,
|
||||
2513.4221036393283,
|
||||
174215004,
|
||||
1716.9016582189813,
|
||||
12188378
|
||||
],
|
||||
"_features": [
|
||||
6226,
|
||||
6387,
|
||||
6483,
|
||||
6932,
|
||||
7116,
|
||||
7873,
|
||||
8174
|
||||
]
|
||||
}
|
||||
},
|
||||
"faces": {}
|
||||
}
|
||||
BIN
test/fixtures/mapbox-streets-v4.13.1306.3163.vector.pbf
vendored
Normal file
BIN
test/fixtures/mapbox-streets-v4.13.1306.3163.vector.pbf
vendored
Normal file
Binary file not shown.
118
test/format/ieee754.js
Normal file
118
test/format/ieee754.js
Normal file
@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
// Copyright (c) 2008, Fair Oaks Labs, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// Modifications to writeIEEE754 to support negative zeroes made by Brian White
|
||||
|
||||
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
|
||||
var e, m,
|
||||
eLen = nBytes * 8 - mLen - 1,
|
||||
eMax = (1 << eLen) - 1,
|
||||
eBias = eMax >> 1,
|
||||
nBits = -7,
|
||||
i = isBE ? 0 : (nBytes - 1),
|
||||
d = isBE ? 1 : -1,
|
||||
s = buffer[offset + i];
|
||||
|
||||
i += d;
|
||||
|
||||
e = s & ((1 << (-nBits)) - 1);
|
||||
s >>= (-nBits);
|
||||
nBits += eLen;
|
||||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
|
||||
|
||||
m = e & ((1 << (-nBits)) - 1);
|
||||
e >>= (-nBits);
|
||||
nBits += mLen;
|
||||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
|
||||
|
||||
if (e === 0) {
|
||||
e = 1 - eBias;
|
||||
} else if (e === eMax) {
|
||||
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
||||
} else {
|
||||
m = m + Math.pow(2, mLen);
|
||||
e = e - eBias;
|
||||
}
|
||||
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
||||
};
|
||||
|
||||
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
|
||||
var e, m, c,
|
||||
eLen = nBytes * 8 - mLen - 1,
|
||||
eMax = (1 << eLen) - 1,
|
||||
eBias = eMax >> 1,
|
||||
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
|
||||
i = isBE ? (nBytes - 1) : 0,
|
||||
d = isBE ? -1 : 1,
|
||||
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
|
||||
|
||||
value = Math.abs(value);
|
||||
|
||||
if (isNaN(value) || value === Infinity) {
|
||||
m = isNaN(value) ? 1 : 0;
|
||||
e = eMax;
|
||||
} else {
|
||||
e = Math.floor(Math.log(value) / Math.LN2);
|
||||
if (value * (c = Math.pow(2, -e)) < 1) {
|
||||
e--;
|
||||
c *= 2;
|
||||
}
|
||||
if (e + eBias >= 1) {
|
||||
value += rt / c;
|
||||
} else {
|
||||
value += rt * Math.pow(2, 1 - eBias);
|
||||
}
|
||||
if (value * c >= 2) {
|
||||
e++;
|
||||
c /= 2;
|
||||
}
|
||||
|
||||
if (e + eBias >= eMax) {
|
||||
m = 0;
|
||||
e = eMax;
|
||||
} else if (e + eBias >= 1) {
|
||||
m = (value * c - 1) * Math.pow(2, mLen);
|
||||
e = e + eBias;
|
||||
} else {
|
||||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
||||
e = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
|
||||
|
||||
e = (e << mLen) | m;
|
||||
eLen += mLen;
|
||||
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
|
||||
|
||||
buffer[offset + i - d] |= s * 128;
|
||||
};
|
||||
116
test/format/protobuf.js
Normal file
116
test/format/protobuf.js
Normal file
@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
|
||||
var ieee754 = require('./ieee754.js');
|
||||
|
||||
module.exports = Protobuf;
|
||||
function Protobuf(buf) {
|
||||
this.buf = buf;
|
||||
this.length = buf.length;
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
Protobuf.prototype.destroy = function() {
|
||||
this.buf = null;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readUInt32 = function() {
|
||||
var val = this.readUInt32LE(this.pos);
|
||||
this.pos += 4;
|
||||
return val;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readUInt64 = function() {
|
||||
var val = this.readUInt64LE(this.pos);
|
||||
this.pos += 8;
|
||||
return val;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readDouble = function() {
|
||||
var val = ieee754.readIEEE754(this.buf, this.pos, false, 52, 8);
|
||||
this.pos += 8;
|
||||
return val;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readVarint = function() {
|
||||
// TODO: bounds checking
|
||||
var pos = this.pos;
|
||||
if (this.buf[pos] <= 0x7f) {
|
||||
this.pos++;
|
||||
return this.buf[pos];
|
||||
} else if (this.buf[pos + 1] <= 0x7f) {
|
||||
this.pos += 2;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] << 7);
|
||||
} else if (this.buf[pos + 2] <= 0x7f) {
|
||||
this.pos += 3;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2]) << 14;
|
||||
} else if (this.buf[pos + 3] <= 0x7f) {
|
||||
this.pos += 4;
|
||||
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21;
|
||||
} else if (this.buf[pos + 4] <= 0x7f) {
|
||||
this.pos += 5;
|
||||
return ((this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21) + (this.buf[pos + 4] * 268435456);
|
||||
} else {
|
||||
this.skip(0);
|
||||
return 0;
|
||||
// throw new Error("TODO: Handle 6+ byte varints");
|
||||
}
|
||||
};
|
||||
|
||||
Protobuf.prototype.readSVarint = function() {
|
||||
var num = this.readVarint();
|
||||
if (num > 2147483647) throw new Error('TODO: Handle numbers >= 2^30');
|
||||
// zigzag encoding
|
||||
return ((num >> 1) ^ -(num & 1));
|
||||
};
|
||||
|
||||
Protobuf.prototype.readString = function() {
|
||||
var bytes = this.readVarint();
|
||||
// TODO: bounds checking
|
||||
var chr = String.fromCharCode;
|
||||
var b = this.buf;
|
||||
var p = this.pos;
|
||||
var end = this.pos + bytes;
|
||||
var str = '';
|
||||
while (p < end) {
|
||||
if (b[p] <= 0x7F) str += chr(b[p++]);
|
||||
else if (b[p] <= 0xBF) throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
|
||||
else if (b[p] <= 0xDF) str += chr((b[p++] & 0x1F) << 6 | (b[p++] & 0x3F));
|
||||
else if (b[p] <= 0xEF) str += chr((b[p++] & 0x1F) << 12 | (b[p++] & 0x3F) << 6 | (b[p++] & 0x3F));
|
||||
else if (b[p] <= 0xF7) p += 4; // We can't handle these codepoints in JS, so skip.
|
||||
else if (b[p] <= 0xFB) p += 5;
|
||||
else if (b[p] <= 0xFD) p += 6;
|
||||
else throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
|
||||
}
|
||||
this.pos += bytes;
|
||||
return str;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readBuffer = function() {
|
||||
var bytes = this.readVarint();
|
||||
var buffer = this.buf.subarray(this.pos, this.pos + bytes);
|
||||
this.pos += bytes;
|
||||
return buffer;
|
||||
};
|
||||
|
||||
Protobuf.prototype.readPacked = function(type) {
|
||||
// TODO: bounds checking
|
||||
var bytes = this.readVarint();
|
||||
var end = this.pos + bytes;
|
||||
var array = [];
|
||||
while (this.pos < end) {
|
||||
array.push(this['read' + type]());
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
Protobuf.prototype.skip = function(val) {
|
||||
// TODO: bounds checking
|
||||
var type = val & 0x7;
|
||||
switch (type) {
|
||||
/* varint */ case 0: while (this.buf[this.pos++] > 0x7f); break;
|
||||
/* 64 bit */ case 1: this.pos += 8; break;
|
||||
/* length */ case 2: var bytes = this.readVarint(); this.pos += bytes; break;
|
||||
/* 32 bit */ case 5: this.pos += 4; break;
|
||||
default: throw new Error('Unimplemented type: ' + type);
|
||||
}
|
||||
};
|
||||
102
test/format/vectortile.js
Normal file
102
test/format/vectortile.js
Normal file
@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
|
||||
var VectorTileLayer = require('./vectortilelayer');
|
||||
|
||||
module.exports = VectorTile;
|
||||
function VectorTile(buffer, end) {
|
||||
// Public
|
||||
this.layers = {};
|
||||
this.faces = {};
|
||||
|
||||
// Private
|
||||
this._buffer = buffer;
|
||||
|
||||
var val, tag;
|
||||
if (typeof end === 'undefined') end = buffer.length;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
if (tag == 3) {
|
||||
var layer = this.readLayer();
|
||||
if (layer.length) {
|
||||
this.layers[layer.name] = layer;
|
||||
}
|
||||
} else if (tag == 4) {
|
||||
var face = this.readFace();
|
||||
this.faces[face.family + ' ' + face.style] = face;
|
||||
} else {
|
||||
// console.warn('skipping tile tag ' + tag);
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VectorTile.prototype.readLayer = function() {
|
||||
var buffer = this._buffer;
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var end = buffer.pos + bytes;
|
||||
var layer = new VectorTileLayer(buffer, end);
|
||||
buffer.pos = end;
|
||||
return layer;
|
||||
};
|
||||
|
||||
VectorTile.prototype.readFace = function() {
|
||||
var buffer = this._buffer;
|
||||
var face = { glyphs: {} };
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var val, tag;
|
||||
var end = buffer.pos + bytes;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
|
||||
if (tag == 1) {
|
||||
face.family = buffer.readString();
|
||||
} else if (tag == 2) {
|
||||
face.style = buffer.readString();
|
||||
} else if (tag == 5) {
|
||||
var glyph = this.readGlyph();
|
||||
face.glyphs[glyph.id] = glyph;
|
||||
} else {
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
return face;
|
||||
};
|
||||
|
||||
|
||||
VectorTile.prototype.readGlyph = function() {
|
||||
var buffer = this._buffer;
|
||||
var glyph = {};
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var val, tag;
|
||||
var end = buffer.pos + bytes;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
|
||||
if (tag == 1) {
|
||||
glyph.id = buffer.readVarint();
|
||||
} else if (tag == 2) {
|
||||
glyph.bitmap = buffer.readBuffer();
|
||||
} else if (tag == 3) {
|
||||
glyph.width = buffer.readVarint();
|
||||
} else if (tag == 4) {
|
||||
glyph.height = buffer.readVarint();
|
||||
} else if (tag == 5) {
|
||||
glyph.left = buffer.readSVarint();
|
||||
} else if (tag == 6) {
|
||||
glyph.top = buffer.readSVarint();
|
||||
} else if (tag == 7) {
|
||||
glyph.advance = buffer.readVarint();
|
||||
} else {
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
return glyph;
|
||||
};
|
||||
145
test/format/vectortilefeature.js
Normal file
145
test/format/vectortilefeature.js
Normal file
@ -0,0 +1,145 @@
|
||||
'use strict';
|
||||
|
||||
var VectorTilePoint = require('./vectortilepoint.js');
|
||||
|
||||
/*
|
||||
* Construct a new vector tile feature given a buffer.
|
||||
*
|
||||
* @param {object} buffer
|
||||
* @param {number} [end]
|
||||
* @param {extent}
|
||||
* @param {object} keys
|
||||
* @param {object} values
|
||||
*/
|
||||
module.exports = VectorTileFeature;
|
||||
function VectorTileFeature(buffer, end, extent, keys, values) {
|
||||
// Public
|
||||
this._extent = extent;
|
||||
this._type = 0;
|
||||
|
||||
// Private
|
||||
this._buffer = buffer;
|
||||
this._geometry = -1;
|
||||
|
||||
if (typeof end === 'undefined') {
|
||||
end = buffer.length;
|
||||
}
|
||||
|
||||
var val, tag;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
|
||||
if (tag == 1) {
|
||||
this._id = buffer.readVarint();
|
||||
} else if (tag == 2) {
|
||||
var tag_end = buffer.pos + buffer.readVarint();
|
||||
while (buffer.pos < tag_end) {
|
||||
var key = keys[buffer.readVarint()];
|
||||
var value = values[buffer.readVarint()];
|
||||
this[key] = value;
|
||||
}
|
||||
} else if (tag == 3) {
|
||||
this._type = buffer.readVarint();
|
||||
} else if (tag == 4) {
|
||||
this._geometry = buffer.pos;
|
||||
buffer.skip(val);
|
||||
} else {
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VectorTileFeature.Unknown = 0;
|
||||
VectorTileFeature.Point = 1;
|
||||
VectorTileFeature.LineString = 2;
|
||||
VectorTileFeature.Polygon = 3;
|
||||
|
||||
|
||||
VectorTileFeature.mapping = [];
|
||||
VectorTileFeature.mapping[VectorTileFeature.Point] = 'point';
|
||||
VectorTileFeature.mapping[VectorTileFeature.LineString] = 'line';
|
||||
VectorTileFeature.mapping[VectorTileFeature.Polygon] = 'fill';
|
||||
|
||||
|
||||
VectorTileFeature.prototype.loadGeometry = function() {
|
||||
var buffer = this._buffer;
|
||||
buffer.pos = this._geometry;
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var end = buffer.pos + bytes;
|
||||
var cmd = 1, length = 0, x = 0, y = 0;
|
||||
|
||||
var lines = [];
|
||||
var line = null;
|
||||
|
||||
while (buffer.pos < end) {
|
||||
if (!length) {
|
||||
var cmd_length = buffer.readVarint();
|
||||
cmd = cmd_length & 0x7;
|
||||
length = cmd_length >> 3;
|
||||
}
|
||||
|
||||
length--;
|
||||
|
||||
if (cmd == 1 || cmd == 2) {
|
||||
x += buffer.readSVarint();
|
||||
y += buffer.readSVarint();
|
||||
|
||||
if (cmd == 1) {
|
||||
// moveTo
|
||||
if (line) {
|
||||
lines.push(line);
|
||||
}
|
||||
line = [];
|
||||
}
|
||||
|
||||
line.push(new VectorTilePoint(x, y));
|
||||
} else if (cmd == 7) {
|
||||
// closePolygon
|
||||
line.push(line[0]);
|
||||
} else {
|
||||
throw new Error('unknown command ' + cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (line) {
|
||||
lines.push(line);
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
VectorTileFeature.prototype.bbox = function() {
|
||||
var buffer = this._buffer;
|
||||
buffer.pos = this._geometry;
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var end = buffer.pos + bytes;
|
||||
var cmd = 1, length = 0, x = 0, y = 0;
|
||||
|
||||
var x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity;
|
||||
|
||||
while (buffer.pos < end) {
|
||||
if (!length) {
|
||||
var cmd_length = buffer.readVarint();
|
||||
cmd = cmd_length & 0x7;
|
||||
length = cmd_length >> 3;
|
||||
}
|
||||
|
||||
length--;
|
||||
|
||||
if (cmd == 1 || cmd == 2) {
|
||||
x += buffer.readSVarint();
|
||||
y += buffer.readSVarint();
|
||||
if (x < x1) x1 = x;
|
||||
if (x > x2) x2 = x;
|
||||
if (y < y1) y1 = y;
|
||||
if (y > y2) y2 = y;
|
||||
} else if (cmd != 7) {
|
||||
throw new Error('unknown command ' + cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return { x1: x1, y1: y1, x2: x2, y2: y2 };
|
||||
};
|
||||
150
test/format/vectortilelayer.js
Normal file
150
test/format/vectortilelayer.js
Normal file
@ -0,0 +1,150 @@
|
||||
'use strict';
|
||||
|
||||
var VectorTileFeature = require('./vectortilefeature.js');
|
||||
|
||||
module.exports = VectorTileLayer;
|
||||
function VectorTileLayer(buffer, end) {
|
||||
// Public
|
||||
this.version = 1;
|
||||
this.name = null;
|
||||
this.extent = 4096;
|
||||
this.length = 0;
|
||||
this.shaping = {};
|
||||
this.faces = [];
|
||||
|
||||
// Private
|
||||
this._buffer = buffer;
|
||||
this._keys = [];
|
||||
this._values = [];
|
||||
this._features = [];
|
||||
|
||||
var stack_index = [];
|
||||
var labels = [];
|
||||
|
||||
var val, tag;
|
||||
if (typeof end === 'undefined') end = buffer.length;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
if (tag == 15) {
|
||||
this.version = buffer.readVarint();
|
||||
} else if (tag == 1) {
|
||||
this.name = buffer.readString();
|
||||
} else if (tag == 5) {
|
||||
this.extent = buffer.readVarint();
|
||||
} else if (tag == 2) {
|
||||
this.length++;
|
||||
this._features.push(buffer.pos);
|
||||
buffer.skip(val);
|
||||
} else if (tag == 3) {
|
||||
this._keys.push(buffer.readString());
|
||||
} else if (tag == 4) {
|
||||
this._values.push(this.readFeatureValue());
|
||||
} else if (tag == 7) {
|
||||
this.faces.push(buffer.readString());
|
||||
} else if (tag == 8) {
|
||||
labels.push(this.readLabel());
|
||||
} else if (tag == 9) {
|
||||
stack_index.push(buffer.readString());
|
||||
} else {
|
||||
console.warn('skipping layer tag ' + tag);
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
// Build index of [stack][text] => shaping information
|
||||
var shaping = this.shaping;
|
||||
for (var i = 0; i < labels.length; i++) {
|
||||
var label = labels[i];
|
||||
var text = this._values[label.text];
|
||||
var stack = stack_index[label.stack];
|
||||
|
||||
if (!(stack in shaping)) shaping[stack] = {};
|
||||
shaping[stack][text] = label.glyphs;
|
||||
}
|
||||
}
|
||||
|
||||
VectorTileLayer.prototype.readFeatureValue = function() {
|
||||
var buffer = this._buffer;
|
||||
var value = null;
|
||||
|
||||
var bytes = buffer.readVarint();
|
||||
var val, tag;
|
||||
var end = buffer.pos + bytes;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
|
||||
if (tag == 1) {
|
||||
value = buffer.readString();
|
||||
} else if (tag == 2) {
|
||||
throw new Error('read float');
|
||||
} else if (tag == 3) {
|
||||
value = buffer.readDouble();
|
||||
} else if (tag == 4) {
|
||||
value = buffer.readVarint();
|
||||
} else if (tag == 5) {
|
||||
throw new Error('read uint');
|
||||
} else if (tag == 6) {
|
||||
value = buffer.readSVarint();
|
||||
} else if (tag == 7) {
|
||||
value = Boolean(buffer.readVarint());
|
||||
} else {
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
VectorTileLayer.prototype.readLabel = function() {
|
||||
var label = { glyphs: [] };
|
||||
var faces, glyphs, x, y;
|
||||
|
||||
var buffer = this._buffer;
|
||||
var bytes = buffer.readVarint();
|
||||
var val, tag;
|
||||
var end = buffer.pos + bytes;
|
||||
while (buffer.pos < end) {
|
||||
val = buffer.readVarint();
|
||||
tag = val >> 3;
|
||||
|
||||
if (tag == 1) {
|
||||
label.text = buffer.readVarint();
|
||||
} else if (tag == 2) {
|
||||
label.stack = buffer.readVarint();
|
||||
} else if (tag == 3) {
|
||||
faces = buffer.readPacked('Varint');
|
||||
} else if (tag == 4) {
|
||||
glyphs = buffer.readPacked('Varint');
|
||||
} else if (tag == 5) {
|
||||
x = buffer.readPacked('Varint');
|
||||
} else if (tag == 6) {
|
||||
y = buffer.readPacked('Varint');
|
||||
} else {
|
||||
buffer.skip(val);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < glyphs.length; i++) {
|
||||
label.glyphs.push({ face: faces[i], glyph: glyphs[i], x: x[i], y: y[i] });
|
||||
}
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
/*
|
||||
* Return feature `i` from this layer as a `VectorTileFeature`
|
||||
*
|
||||
* @param {number} i
|
||||
* @returns {VectorTileFeature}
|
||||
*/
|
||||
VectorTileLayer.prototype.feature = function(i) {
|
||||
if (i < 0 || i >= this._features.length) {
|
||||
throw new Error('feature index out of bounds');
|
||||
}
|
||||
|
||||
this._buffer.pos = this._features[i];
|
||||
var end = this._buffer.readVarint() + this._buffer.pos;
|
||||
return new VectorTileFeature(this._buffer, end, this.extent, this._keys, this._values);
|
||||
};
|
||||
11
test/format/vectortilepoint.js
Normal file
11
test/format/vectortilepoint.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = VectorTilePoint;
|
||||
function VectorTilePoint(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
VectorTilePoint.prototype.toString = function() {
|
||||
return "Point(" + this.x + ", " + this.y + ")";
|
||||
};
|
||||
88
test/test.js
Normal file
88
test/test.js
Normal file
@ -0,0 +1,88 @@
|
||||
var fontserver = require('../index.js');
|
||||
var assert = require('assert');
|
||||
var zlib = require('zlib');
|
||||
var fs = require('fs');
|
||||
var zdata = fs.readFileSync(__dirname + '/fixtures/mapbox-streets-v4.13.1306.3163.vector.pbf');
|
||||
var Protobuf = require('./format/protobuf');
|
||||
var VectorTile = require('./format/vectortile');
|
||||
|
||||
function nobuffer(key, val) {
|
||||
return key !== '_buffer' && key !== 'bitmap' ? val : undefined;
|
||||
}
|
||||
|
||||
function jsonEqual(key, json) {
|
||||
fs.writeFileSync(__dirname + '/expected/'+key+'.json', JSON.stringify(json, null, 2));
|
||||
assert.deepEqual(json, require('./expected/'+key+'.json'));
|
||||
}
|
||||
|
||||
describe('convert', function() {
|
||||
var data;
|
||||
before(function(done) {
|
||||
zlib.inflate(zdata, function(err, d) {
|
||||
assert.ifError(err);
|
||||
data = d;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('serialize', function(done) {
|
||||
var tile = new fontserver.Tile(data);
|
||||
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
|
||||
var json = JSON.parse(JSON.stringify(vt, nobuffer));
|
||||
jsonEqual('serialize', json);
|
||||
done();
|
||||
});
|
||||
|
||||
it('simplify', function(done) {
|
||||
var tile = new fontserver.Tile(data);
|
||||
tile.simplify(function(err) {
|
||||
assert.ifError(err);
|
||||
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
|
||||
var json = JSON.parse(JSON.stringify(vt, nobuffer));
|
||||
jsonEqual('simplify', json);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('simplify (x10)', function(done) {
|
||||
this.timeout(10000);
|
||||
var remaining = 10;
|
||||
for (var i = 0; i < 10; i++) (function() {
|
||||
var tile = new fontserver.Tile(data);
|
||||
tile.simplify(function(err) {
|
||||
assert.ifError(err);
|
||||
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
|
||||
var json = JSON.parse(JSON.stringify(vt, nobuffer));
|
||||
jsonEqual('simplify', json);
|
||||
if (!--remaining) return done();
|
||||
});
|
||||
})();
|
||||
});
|
||||
|
||||
it('shape', function(done) {
|
||||
var tile = new fontserver.Tile(data);
|
||||
tile.shape('Open Sans', function(err) {
|
||||
assert.ifError(err);
|
||||
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
|
||||
var json = JSON.parse(JSON.stringify(vt, nobuffer));
|
||||
jsonEqual('shape', json);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('shape (x10)', function(done) {
|
||||
this.timeout(10000);
|
||||
var remaining = 10;
|
||||
for (var i = 0; i < 10; i++) (function() {
|
||||
var tile = new fontserver.Tile(data);
|
||||
tile.shape('Open Sans', function(err) {
|
||||
assert.ifError(err);
|
||||
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
|
||||
var json = JSON.parse(JSON.stringify(vt, nobuffer));
|
||||
jsonEqual('shape', json);
|
||||
if (!--remaining) return done();
|
||||
});
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user