Merge branch 'stylesource' into fuzz-pipe

Conflicts:
	src/map/source.cpp
	src/style/style_layer.cpp
This commit is contained in:
Mike Morris
2014-07-10 17:24:50 -07:00
49 changed files with 418 additions and 276 deletions

View File

@@ -14,6 +14,7 @@ env:
global:
- secure: "bG4YYWMfl9API0MSRgmOaJrlGLv06tRg9KJNawBieZvBJbITPpxVGJZT3/l/SEJ+Rl15e2dRex4k+MGQlmT2SqPQxTEYWv1qxNigKPPcla7IWeNmWWqW8uVvFjdglojgBOK2k/xErVQtA4zDfi3mwSXH4DKwquXWsoEKmX2SV7M="
- secure: "Cbvap9ubVKgjPe3hUhI6JGeDZzBXHpOG9RaYKh+SdoIPhKnlJiNOYm1egomi+e4uqJInlFKuVHTw7Ng9Cun6Zm0jIxpkSchv1GpsR7hmB3UGnGed19Dw8121FwuUaktN+4YnbVlsyd+u8EHD3+h58t4eELrLrZolM4rS7DL6caA="
- secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
before_install:
- ./scripts/setup_travis.sh

View File

@@ -27,9 +27,18 @@ First off: if you hit problems during development try:
This will clear cached build data and update to the latest versions of dependencies.
### Mapbox API access tokens
The demo applications use Mapbox vector tiles, which **require a Mapbox account and API access token**. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/account/apps/).
## OS X
First run:
in the Xcode project, click on the Target icon next to the Run/Stop button, and then "Edit Scheme". In the screen, add an environment variable with the name `MAPBOX_ACCESS_TOKEN` to the targets you want to run.
![Setting the access token](https://cloud.githubusercontent.com/assets/52399/3543326/9e7cfbb8-0860-11e4-8def-3684a9028b61.png)
Run:
make setup
@@ -52,6 +61,8 @@ First, pull down the submodule(s):
git submodule init
git submodule update
Insert your access token into `MBXViewController.h`.
Then run:
make setup
@@ -64,6 +75,8 @@ Target devices: iPhone 4 and above (4S, 5, 5c, 5s) and iPad 2 and above (3, 4, m
## Ubuntu
Set the environment variable `MAPBOX_ACCESS_TOKEN` to your token.
Ensure you have git and other build essentials:
sudo apt-get update

View File

@@ -6,7 +6,6 @@
"mapbox": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
"tileSize": 512,
"maxZoom": 14
}
},
@@ -66,124 +65,124 @@
"@contour_night": "#ffff80",
"@river_canal_width": {
"fn": "stops",
"stops": [[11, 0.5], [12, 1], [14, 2], [16, 3]]
"stops": [[10, 0.5], [11, 1], [13, 2], [15, 3]]
},
"@stream_width": {
"fn": "stops",
"stops": [[13, 0.25], [14, 0.5], [16, 1.5], [18, 2]]
"stops": [[12, 0.25], [13, 0.5], [15, 1.5], [17, 2]]
},
"@motorway_width": {
"fn": "stops",
"stops": [[5, 0], [6, 0.5], [8, 0.8], [10, 1], [11, 1.2], [12, 2], [13, 3], [14, 4], [15, 6], [16, 9], [17, 12], [18, 14]]
"stops": [[4, 0], [5, 0.5], [7, 0.8], [9, 1], [10, 1.2], [11, 2], [12, 3], [13, 4], [14, 6], [15, 9], [16, 12], [17, 14]]
},
"@motorway_casing_width": {
"fn": "stops",
"stops": [[7.5, 0.6], [8, 0.8], [10, 2.8], [11, 3], [12, 4], [13, 5], [14, 6.5], [15, 9], [16, 12], [17, 15], [18, 17]]
"stops": [[6.5, 0.6], [7, 0.8], [9, 2.8], [10, 3], [11, 4], [12, 5], [13, 6.5], [14, 9], [15, 12], [16, 15], [17, 17]]
},
"@motorway_link_width": {
"fn": "stops",
"stops": [[12, 1.2], [14, 2], [16, 3], [18, 4]]
"stops": [[11, 1.2], [13, 2], [15, 3], [17, 4]]
},
"@motorway_link_casing_width": {
"fn": "stops",
"stops": [[12, 2.8], [14, 3.5], [16, 5], [18, 6]]
"stops": [[11, 2.8], [13, 3.5], [15, 5], [17, 6]]
},
"@main_width": {
"fn": "stops",
"stops": [[5, 1], [12, 1], [13, 1.5], [14, 2], [15, 3], [16, 6], [17, 10], [18, 12]]
"stops": [[4, 1], [11, 1], [12, 1.5], [13, 2], [14, 3], [15, 6], [16, 10], [17, 12]]
},
"@main_casing_width": {
"fn": "stops",
"stops": [[9, 2.9], [12, 2.9], [13, 3.5], [14, 4], [15, 5.5], [16, 9], [17, 12], [18, 14]]
"stops": [[8, 2.9], [11, 2.9], [12, 3.5], [13, 4], [14, 5.5], [15, 9], [16, 12], [17, 14]]
},
"@street_width": {
"fn": "stops",
"stops": [[14.5, 0], [15, 1.5], [16, 3], [17, 8]]
"stops": [[13.5, 0], [14, 1.5], [15, 3], [16, 8]]
},
"@street_casing_width": {
"fn": "stops",
"stops": [[13, 0.4], [14, 1], [15, 2.5], [16, 4], [17, 10]]
"stops": [[12, 0.4], [13, 1], [14, 2.5], [15, 4], [16, 10]]
},
"@street_casing_opacity": {
"fn": "stops",
"stops": [[14, 0], [14.5, 1]]
"stops": [[13, 0], [13.5, 1]]
},
"@service_casing_width": {
"fn": "stops",
"stops": [[14, 0.5], [15, 3], [16, 3.5], [17, 4], [18, 5], [19, 6]]
"stops": [[13, 0.5], [14, 3], [15, 3.5], [16, 4], [17, 5], [18, 6]]
},
"@runway_width": {
"fn": "stops",
"stops": [[10, 1], [11, 2], [12, 3], [13, 5], [14, 7], [15, 11], [16, 15], [17, 19], [18, 23]]
"stops": [[9, 1], [10, 2], [11, 3], [12, 5], [13, 7], [14, 11], [15, 15], [16, 19], [17, 23]]
},
"@taxiway_width": {
"fn": "stops",
"stops": [[10, 0.2], [12, 0.2], [13, 1], [14, 1.5], [15, 2], [16, 3], [17, 4], [18, 5]]
"stops": [[9, 0.2], [11, 0.2], [12, 1], [13, 1.5], [14, 2], [15, 3], [16, 4], [17, 5]]
},
"@aerialway_width": {
"fn": "stops",
"stops": [[13.5, 0.8], [14, 1.4], [15, 1.6], [16, 2], [17, 2.4], [18, 3]]
"stops": [[12.5, 0.8], [13, 1.4], [14, 1.6], [15, 2], [16, 2.4], [17, 3]]
},
"@aerialway_casing_width": {
"fn": "stops",
"stops": [[13.5, 2], [14, 2.5], [15, 3], [16, 3.5], [17, 4], [22, 5]]
"stops": [[12.5, 2], [13, 2.5], [14, 3], [15, 3.5], [16, 4], [21, 5]]
},
"@path_width": {
"fn": "stops",
"stops": [[14, 1.2], [15, 1.5], [16, 1.8]]
"stops": [[13, 1.2], [14, 1.5], [15, 1.8]]
},
"@admin_l2_width": {
"fn": "stops",
"stops": [[2, 0.5], [3, 0.7], [4, 0.7], [5, 0.8], [6, 1], [8, 2], [10, 3]]
"stops": [[1, 0.5], [2, 0.7], [3, 0.7], [4, 0.8], [5, 1], [7, 2], [9, 3]]
},
"@admin_l3_width": {
"fn": "stops",
"stops": [[6, 0.6], [8, 1], [12, 2]]
"stops": [[5, 0.6], [7, 1], [11, 2]]
},
"@road_label_1_size": {
"fn": "stops",
"stops": [[13, 11], [14, 12], [15, 13], [16, 14], [17, 16], [18, 18]]
"stops": [[12, 11], [13, 12], [14, 13], [15, 14], [16, 16], [17, 18]]
},
"@road_label_2_size": {
"fn": "stops",
"stops": [[13, 11], [14, 12], [16, 14], [18, 16]]
"stops": [[12, 11], [13, 12], [15, 14], [17, 16]]
},
"@road_label_3_size": {
"fn": "stops",
"stops": [[15, 10], [16, 12], [18, 14]]
"stops": [[14, 10], [15, 12], [17, 14]]
},
"@fence_width": {
"fn": "stops",
"stops": [[17, 0.6], [19, 1]]
"stops": [[16, 0.6], [18, 1]]
},
"@hedge_width": {
"fn": "stops",
"stops": [[16, 0.6], [17, 1.2], [19, 1.6]]
"stops": [[15, 0.6], [16, 1.2], [18, 1.6]]
},
"@barrier_line_land_width": {
"fn": "stops",
"stops": [[14, 0.4], [15, 0.75], [16, 1.5], [17, 3], [18, 6], [19, 12], [20, 24], [21, 48]]
"stops": [[13, 0.4], [14, 0.75], [15, 1.5], [16, 3], [17, 6], [18, 12], [19, 24], [20, 48]]
},
"@country_label_size": {
"fn": "stops",
"stops": [[1, 14], [12, 24]]
"stops": [[0, 14], [11, 24]]
},
"@poi_label_1-2_size": {
"fn": "stops",
"stops": [[15, 10], [16, 11], [17, 12]]
"stops": [[14, 10], [15, 11], [16, 12]]
},
"@poi_label_3_size": {
"fn": "stops",
"stops": [[16, 10], [17, 11]]
"stops": [[15, 10], [16, 11]]
},
"@hillshade_rasterize": {
"enabled": {
"fn": "stops",
"stops": [[11, false], [12, true]]
"stops": [[10, false], [11, true]]
},
"size": {
"fn": "stops",
"stops": [[11, 1024], [12, 512], [13, 256]]
"stops": [[10, 1024], [11, 512], [12, 256]]
},
"blur": 1
}
@@ -231,14 +230,14 @@
"fill-color": "@grass",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@grass_night",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
}, {
@@ -251,14 +250,14 @@
"fill-color": "@scrub",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@scrub_night",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
}, {
@@ -271,14 +270,14 @@
"fill-color": "@wood",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
},
"style.night": {
"fill-color": "@wood_night",
"fill-opacity": {
"fn": "stops",
"stops": [[13, 1], [14, 0.8], [17, 0.2]]
"stops": [[12, 1], [13, 0.8], [16, 0.2]]
}
}
}, {
@@ -516,7 +515,7 @@
"fill-translate": [1, 1],
"fill-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [17, 1]]
"stops": [[15.5, 0], [16, 1]]
},
"fill-outline-color": "#d5d1c6"
},
@@ -525,7 +524,7 @@
"fill-translate": [1, 1],
"fill-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [17, 1]]
"stops": [[15.5, 0], [16, 1]]
},
"fill-outline-color": "#026688"
}
@@ -545,7 +544,7 @@
"fill-color": "#ebe7db",
"fill-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [17, 0.7]]
"stops": [[15.5, 0], [16, 0.7]]
},
"fill-outline-color": "#d5d1c6"
},
@@ -553,7 +552,7 @@
"fill-color": "#027797",
"fill-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [17, 0.7]]
"stops": [[15.5, 0], [16, 0.7]]
},
"fill-outline-color": "#026688"
}
@@ -569,7 +568,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[15, 0.3], [16, 0.3], [17, 0.2], [18, 0.2], [19, 0.1]]
"stops": [[14, 0.3], [15, 0.3], [16, 0.2], [17, 0.2], [18, 0.1]]
}
},
"style.night": {
@@ -577,7 +576,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[14, 0.4], [15, 0.3], [17, 0.2], [18, 0.1], [19, 0.05]]
"stops": [[13, 0.4], [14, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
}, {
@@ -592,7 +591,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[15, 0.3], [16, 0.3], [17, 0.2], [18, 0.2], [19, 0.1]]
"stops": [[14, 0.3], [15, 0.3], [16, 0.2], [17, 0.2], [18, 0.1]]
}
},
"style.night": {
@@ -600,7 +599,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[15, 0.3], [17, 0.2], [18, 0.15], [19, 0.05]]
"stops": [[14, 0.3], [16, 0.2], [17, 0.15], [18, 0.05]]
}
}
}, {
@@ -615,7 +614,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[15, 0.08], [16, 0.075], [17, 0.05], [18, 0.05], [19, 0.025]]
"stops": [[14, 0.08], [15, 0.075], [16, 0.05], [17, 0.05], [18, 0.025]]
}
},
"style.night": {
@@ -623,7 +622,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[16, 0.3], [17, 0.2], [18, 0.1], [19, 0.05]]
"stops": [[15, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
}, {
@@ -638,7 +637,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[15, 0.08], [16, 0.075], [17, 0.05], [18, 0.05], [19, 0.025]]
"stops": [[14, 0.08], [15, 0.075], [16, 0.05], [17, 0.05], [18, 0.025]]
}
},
"style.night": {
@@ -646,7 +645,7 @@
"fill-antialias": false,
"fill-opacity": {
"fn": "stops",
"stops": [[16, 0.3], [17, 0.2], [18, 0.1], [19, 0.05]]
"stops": [[15, 0.3], [16, 0.2], [17, 0.1], [18, 0.05]]
}
}
}, {
@@ -663,7 +662,7 @@
"line-width": 0.9,
"line-opacity": {
"fn": "stops",
"stops": [[12, 0.05], [13, 0.11]]
"stops": [[11, 0.05], [12, 0.11]]
}
},
"style.night": {
@@ -671,7 +670,7 @@
"line-width": 0.9,
"line-opacity": {
"fn": "stops",
"stops": [[12, 0.1], [13, 0.2]]
"stops": [[11, 0.1], [12, 0.2]]
}
}
}, {
@@ -687,7 +686,7 @@
"line-width": 0.5,
"line-opacity": {
"fn": "stops",
"stops": [[12, 0.05], [13, 0.11]]
"stops": [[11, 0.05], [12, 0.11]]
}
},
"style.night": {
@@ -695,7 +694,7 @@
"line-width": 0.5,
"line-opacity": {
"fn": "stops",
"stops": [[12, 0.1], [13, 0.4]]
"stops": [[11, 0.1], [12, 0.4]]
}
}
}, {
@@ -878,7 +877,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
},
"style.night": {
@@ -887,7 +886,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
}
}, {
@@ -947,7 +946,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -955,7 +954,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -970,7 +969,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
},
"style.night": {
@@ -979,7 +978,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
}
}, {
@@ -990,7 +989,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -998,7 +997,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -1012,7 +1011,7 @@
"line-opacity": 0.4,
"line-width": {
"fn": "stops",
"stops": [[15, 3], [16, 4]]
"stops": [[14, 3], [15, 4]]
}
},
"style.night": {
@@ -1047,7 +1046,7 @@
"line-opacity": 0.8,
"line-width": {
"fn": "stops",
"stops": [[14, 0.8], [15, 0.9], [16, 1.2]]
"stops": [[13, 0.8], [14, 0.9], [15, 1.2]]
}
},
"style.night": {
@@ -1056,7 +1055,7 @@
"line-opacity": 0.8,
"line-width": {
"fn": "stops",
"stops": [[14, 0.8], [15, 0.9], [16, 1.2]]
"stops": [[13, 0.8], [14, 0.9], [15, 1.2]]
}
}
}, {
@@ -1191,7 +1190,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
},
"style.night": {
@@ -1199,7 +1198,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
}
}, {
@@ -1263,7 +1262,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -1271,7 +1270,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -1289,7 +1288,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
},
"style.night": {
@@ -1297,7 +1296,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
}
}, {
@@ -1308,7 +1307,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -1316,7 +1315,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -1373,7 +1372,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
},
"style.night": {
@@ -1381,7 +1380,7 @@
"line-width": "@main_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9, 0], [10, 1]]
"stops": [[8, 0], [9, 1]]
}
}
}, {
@@ -1441,7 +1440,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -1449,7 +1448,7 @@
"line-width": "@main_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -1463,7 +1462,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
},
"style.night": {
@@ -1471,7 +1470,7 @@
"line-width": "@motorway_casing_width",
"line-opacity": {
"fn": "stops",
"stops": [[9.5, 0], [10, 1]]
"stops": [[8.5, 0], [9, 1]]
}
}
}, {
@@ -1482,7 +1481,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
},
"style.night": {
@@ -1490,7 +1489,7 @@
"line-width": "@motorway_width",
"line-opacity": {
"fn": "stops",
"stops": [[6.5, 0], [7, 1]]
"stops": [[5.5, 0], [6, 1]]
}
}
}, {
@@ -1536,7 +1535,7 @@
"line-dasharray": [60, 20],
"line-opacity": {
"fn": "stops",
"stops": [[4, 0], [6, 1]]
"stops": [[3, 0], [5, 1]]
},
"line-width": "@admin_l3_width"
},
@@ -1545,7 +1544,7 @@
"line-dasharray": [60, 20],
"line-opacity": {
"fn": "stops",
"stops": [[4, 0], [6, 1]]
"stops": [[3, 0], [5, 1]]
},
"line-width": "@admin_l3_width"
}
@@ -1592,14 +1591,14 @@
"line-color": "#c0d6d6",
"line-width": {
"fn": "stops",
"stops": [[6, 1], [8, 2], [12, 3]]
"stops": [[5, 1], [7, 2], [11, 3]]
}
},
"style.night": {
"line-color": "#0a1347",
"line-width": {
"fn": "stops",
"stops": [[6, 1], [8, 2], [12, 3]]
"stops": [[5, 1], [7, 2], [11, 3]]
}
}
}, {
@@ -1663,7 +1662,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 20], [4, 25], [5, 30], [22, 30]]
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water"
},
@@ -1671,7 +1670,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 20], [4, 25], [5, 30], [22, 30]]
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water_night"
}
@@ -1692,7 +1691,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 13], [4, 14], [5, 20], [6, 24], [22, 24]]
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water"
},
@@ -1700,7 +1699,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 13], [4, 14], [5, 20], [6, 24], [22, 24]]
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water_night"
}
@@ -1721,7 +1720,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 12], [4, 13], [5, 15], [6, 18], [22, 18]]
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water"
},
@@ -1729,7 +1728,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 12], [4, 13], [5, 15], [6, 18], [22, 18]]
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water_night"
}
@@ -1750,7 +1749,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[4, 12], [5, 14], [6, 16], [22, 16]]
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water"
},
@@ -1758,7 +1757,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[4, 12], [5, 14], [6, 16], [22, 16]]
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water_night"
}
@@ -1781,7 +1780,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 20], [4, 25], [5, 30], [22, 30]]
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water"
},
@@ -1789,7 +1788,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 20], [4, 25], [5, 30], [22, 30]]
"stops": [[2, 20], [3, 25], [4, 30], [21, 30]]
},
"text-halo-color": "@water_night"
}
@@ -1812,7 +1811,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 13], [4, 14], [5, 20], [6, 24], [22, 24]]
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water"
},
@@ -1820,7 +1819,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 13], [4, 14], [5, 20], [6, 24], [22, 24]]
"stops": [[2, 13], [3, 14], [4, 20], [5, 24], [21, 24]]
},
"text-halo-color": "@water_night"
}
@@ -1843,7 +1842,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[3, 12], [4, 13], [5, 15], [6, 18], [22, 18]]
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water"
},
@@ -1851,7 +1850,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[3, 12], [4, 13], [5, 15], [6, 18], [22, 18]]
"stops": [[2, 12], [3, 13], [4, 15], [5, 18], [21, 18]]
},
"text-halo-color": "@water_night"
}
@@ -1874,7 +1873,7 @@
"text-color": "@marine_text",
"text-size": {
"fn": "stops",
"stops": [[4, 12], [5, 14], [6, 16], [22, 16]]
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water"
},
@@ -1882,7 +1881,7 @@
"text-color": "@water_dark_night",
"text-size": {
"fn": "stops",
"stops": [[4, 12], [5, 14], [6, 16], [22, 16]]
"stops": [[3, 12], [4, 14], [5, 16], [21, 16]]
},
"text-halo-color": "@water_night"
}
@@ -1905,7 +1904,7 @@
"text-halo-color": "rgba(244,239,225,0.8)",
"text-size": {
"fn": "stops",
"stops": [[3.99, 0], [4, 10], [9.99, 16], [10, 0]]
"stops": [[2.99, 0], [3, 10], [8.99, 16], [9, 0]]
}
},
"style.night": {
@@ -1914,7 +1913,7 @@
"text-halo-color": "@land_night",
"text-size": {
"fn": "stops",
"stops": [[3.99, 0], [4, 10], [9.99, 16], [10, 0]]
"stops": [[2.99, 0], [3, 10], [8.99, 16], [9, 0]]
}
}
}, {
@@ -1936,7 +1935,7 @@
"text-halo-color": "@text_stroke",
"text-size": {
"fn": "stops",
"stops": [[3.99, 0], [4, 10], [7, 14], [14.99, 20], [15, 0]]
"stops": [[2.99, 0], [3, 10], [6, 14], [13.99, 20], [14, 0]]
}
},
"style.night": {
@@ -1945,7 +1944,7 @@
"text-halo-color": "@text2_stroke_night",
"text-size": {
"fn": "stops",
"stops": [[3.99, 0], [4, 10], [7, 14], [14.99, 20], [15, 0]]
"stops": [[2.99, 0], [3, 10], [6, 14], [13.99, 20], [14, 0]]
}
}
}, {
@@ -1967,7 +1966,7 @@
"text-halo-color": "@text_stroke",
"text-size": {
"fn": "stops",
"stops": [[9, 10], [12, 13], [14, 17], [16, 22]]
"stops": [[8, 10], [11, 13], [13, 17], [15, 22]]
}
},
"style.night": {
@@ -1976,7 +1975,7 @@
"text-halo-color": "@text2_stroke_night",
"text-size": {
"fn": "stops",
"stops": [[9, 10], [12, 13], [14, 17], [16, 22]]
"stops": [[8, 10], [11, 13], [13, 17], [15, 22]]
}
}
}, {
@@ -1998,7 +1997,7 @@
"text-halo-color": "@text_stroke",
"text-size": {
"fn": "stops",
"stops": [[9, 8], [12, 10], [14, 14], [16, 16], [17, 20]]
"stops": [[8, 8], [11, 10], [13, 14], [15, 16], [16, 20]]
}
},
"style.night": {
@@ -2007,7 +2006,7 @@
"text-halo-color": "@text2_stroke_night",
"text-size": {
"fn": "stops",
"stops": [[9, 8], [12, 10], [14, 14], [16, 16], [17, 20]]
"stops": [[8, 8], [11, 10], [13, 14], [15, 16], [16, 20]]
}
}
}, {
@@ -2028,7 +2027,7 @@
"text-halo-color": "@text_stroke",
"text-size": {
"fn": "stops",
"stops": [[13, 11], [14, 12], [16, 14], [18, 18]]
"stops": [[12, 11], [13, 12], [15, 14], [17, 18]]
}
},
"style.night": {
@@ -2037,7 +2036,7 @@
"text-halo-width": 0.3,
"text-size": {
"fn": "stops",
"stops": [[13, 11], [14, 12], [16, 14], [18, 18]]
"stops": [[12, 11], [13, 12], [15, 14], [17, 18]]
}
}
}, {
@@ -2237,13 +2236,13 @@
"style": {
"icon-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [16.75, 1]]
"stops": [[15.5, 0], [15.75, 1]]
}
},
"style.night": {
"icon-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [16.75, 1]]
"stops": [[15.5, 0], [15.75, 1]]
}
}
}, {
@@ -2268,7 +2267,7 @@
"text-halo-width": 0.3,
"text-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [16.75, 1]]
"stops": [[15.5, 0], [15.75, 1]]
}
},
"style.night": {
@@ -2278,7 +2277,7 @@
"text-halo-width": 0.3,
"text-opacity": {
"fn": "stops",
"stops": [[16.5, 0], [16.75, 1]]
"stops": [[15.5, 0], [15.75, 1]]
}
}
}, {
@@ -2294,13 +2293,13 @@
"style": {
"icon-opacity": {
"fn": "stops",
"stops": [[18.5, 0], [18.75, 1]]
"stops": [[17.5, 0], [17.75, 1]]
}
},
"style.night": {
"icon-opacity": {
"fn": "stops",
"stops": [[18.5, 0], [18.75, 1]]
"stops": [[17.5, 0], [17.75, 1]]
}
}
}, {
@@ -2323,7 +2322,7 @@
"text-size": 10,
"text-opacity": {
"fn": "stops",
"stops": [[18.5, 0], [18.75, 1]]
"stops": [[17.5, 0], [17.75, 1]]
},
"text-halo-color": "@land",
"text-halo-width": 0.3
@@ -2333,7 +2332,7 @@
"text-size": 10,
"text-opacity": {
"fn": "stops",
"stops": [[18.5, 0], [18.75, 1]]
"stops": [[17.5, 0], [17.75, 1]]
},
"text-halo-color": "@text2_stroke_night",
"text-halo-width": 0.3
@@ -2351,13 +2350,13 @@
"style": {
"icon-opacity": {
"fn": "stops",
"stops": [[13, 0], [13.25, 1]]
"stops": [[12, 0], [12.25, 1]]
}
},
"style.night": {
"icon-opacity": {
"fn": "stops",
"stops": [[13, 0], [13.25, 1]]
"stops": [[12, 0], [12.25, 1]]
}
}
}]

View File

@@ -56,10 +56,11 @@ public:
void setAppliedClasses(const std::vector<std::string> &classes);
void toggleClass(const std::string &name);
const std::vector<std::string> &getAppliedClasses() const;
void setAppliedClasses(std::vector<std::string> &class_names);
void setDefaultTransitionDuration(uint64_t duration_milliseconds = 0);
void setStyleJSON(std::string newStyleJSON);
std::string getStyleJSON() const;
void setAccessToken(std::string access_token);
std::string getAccessToken() const;
// Transition
void cancelTransitions();
@@ -170,6 +171,7 @@ private:
Painter painter;
std::string styleJSON = "";
std::string accessToken = "";
bool debug = false;
timestamp animationTime = 0;

View File

@@ -25,7 +25,8 @@ class Source : public std::enable_shared_from_this<Source>, private util::noncop
public:
Source(StyleSource style_source, const std::string &access_token = "");
Source(SourceType type = SourceType::Vector, const std::string &url = "",
uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22);
uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22,
const std::string &access_token = "");
bool update(Map &map);
void updateMatrices(const mat4 &projMatrix, const TransformState &transform);
@@ -37,7 +38,7 @@ public:
std::forward_list<Tile::ID> getIDs() const;
void updateClipIDs(const std::map<Tile::ID, ClipID> &mapping);
static std::string normalizeSourceURL(const std::string &url);
static std::string normalizeSourceURL(const std::string &url, const std::string &access_token);
public:
const SourceType type;

View File

@@ -29,14 +29,14 @@ private:
template <typename T>
struct ExponentialFunction {
inline ExponentialFunction(const T &value, float z_base, float slope, const T &min,
inline ExponentialFunction(const T &value, float z_base, float exp_base, float slope, const T &min,
const T &max)
: value(value), min(min), max(max), z_base(z_base), slope(slope) {}
: value(value), min(min), max(max), z_base(z_base), exp_base(exp_base), slope(slope) {}
T evaluate(float z) const;
private:
const T value, min, max;
const float z_base, slope;
const float z_base, exp_base, slope;
};
template <typename T>

View File

@@ -4,7 +4,6 @@
namespace llmr {
enum class PropertyKey {
FillEnabled,
FillAntialias,
FillOpacity,
FillColor,
@@ -15,7 +14,6 @@ enum class PropertyKey {
FillTranslateAnchor,
FillImage,
LineEnabled,
LineOpacity,
LineColor,
LineTranslate, // for transitions only
@@ -30,12 +28,10 @@ enum class PropertyKey {
LineDashGap,
LineImage,
IconEnabled,
IconOpacity,
IconRotate,
IconRotateAnchor,
TextEnabled,
TextOpacity,
TextSize,
TextColor,
@@ -43,10 +39,8 @@ enum class PropertyKey {
TextHaloWidth,
TextHaloBlur,
CompositeEnabled,
CompositeOpacity,
RasterEnabled,
RasterOpacity,
RasterSpin,
RasterBrightnessLow,

View File

@@ -14,7 +14,6 @@ namespace llmr {
struct FillProperties {
FillProperties() {}
bool enabled = true;
bool antialias = true;
float opacity = 1.0f;
Color fill_color = {{ 0, 0, 0, 1 }};
@@ -24,13 +23,12 @@ struct FillProperties {
std::string image;
inline bool isVisible() const {
return enabled && opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
}
};
struct LineProperties {
inline LineProperties() {}
bool enabled = true;
float opacity = 1.0f;
Color color = {{ 0, 0, 0, 1 }};
std::array<float, 2> translate = {{ 0, 0 }};
@@ -42,25 +40,23 @@ struct LineProperties {
std::string image;
inline bool isVisible() const {
return enabled && opacity > 0 && color[3] > 0 && width > 0;
return opacity > 0 && color[3] > 0 && width > 0;
}
};
struct IconProperties {
inline IconProperties() {}
bool enabled = true;
float opacity = 1.0f;
float rotate = 0.0f;
RotateAnchorType rotate_anchor = RotateAnchorType::Default;
inline bool isVisible() const {
return enabled && opacity > 0;
return opacity > 0;
}
};
struct TextProperties {
inline TextProperties() {}
bool enabled = true;
float opacity = 1.0f;
float size = 12.0f;
Color color = {{ 0, 0, 0, 1 }};
@@ -69,23 +65,21 @@ struct TextProperties {
float halo_blur = 1.0f;
inline bool isVisible() const {
return enabled && opacity > 0 && (color[3] > 0 || halo_color[3] > 0) && size > 0;
return opacity > 0 && (color[3] > 0 || halo_color[3] > 0) && size > 0;
}
};
struct CompositeProperties {
inline CompositeProperties() {}
bool enabled = true;
float opacity = 1.0f;
inline bool isVisible() const {
return enabled && opacity > 0;
return opacity > 0;
}
};
struct RasterProperties {
inline RasterProperties() {}
bool enabled = true;
float opacity = 1.0f;
float spin = 0.0f;
std::array<float, 2> brightness = {{ 0, 1 }};
@@ -94,7 +88,7 @@ struct RasterProperties {
float fade = 0.0f;
inline bool isVisible() const {
return enabled && opacity > 0;
return opacity > 0;
}
};

View File

@@ -60,6 +60,14 @@ int main(int argc, char *argv[]) {
map.setAngle(settings.angle);
map.setDebug(settings.debug);
// Set access token if present
const char *token = getenv("MAPBOX_ACCESS_TOKEN");
if (token == nullptr) {
fprintf(stderr, "[WARNING] no access token set. mapbox.com tiles won't work.\n");
} else {
map.setAccessToken(std::string(token));
}
// Load style
map.setStyleJSON(stylejson.str());

View File

@@ -13,6 +13,14 @@ int main() {
map.setAngle(settings.angle);
map.setDebug(settings.debug);
// Set access token if present
const char *token = getenv("MAPBOX_ACCESS_TOKEN");
if (token == nullptr) {
fprintf(stderr, "[WARNING] no access token set. mapbox.com tiles won't work.\n");
} else {
map.setAccessToken(std::string(token));
}
// Load style
NSString *path = [[NSBundle mainBundle] pathForResource:@"style.min" ofType:@"js"];
NSString *json = [NSString stringWithContentsOfFile:path

View File

@@ -33,33 +33,45 @@ function processFiles() {
var name = files.shift();
var info = require(path.join(base_dir, name));
var base = path.basename(name, '.info.json');
var actual = path.join(base_dir, base + '.actual.png');
var expected = path.join(base_dir, base + '.expected.png');
var diff = path.join(base_dir, base + '.diff.png');
var keys = Object.keys(info);
var compare = spawn('compare', ['-metric', 'MAE', actual, expected, diff ]);
var error = '';
compare.stderr.on('data', function(data) {
error += data.toString();
});
compare.on('exit', function(code, signal) {
// The compare program returns 2 on error otherwise 0 if the images are similar or 1 if they are dissimilar.
if (code == 2) {
writeResult(base, info, error.trim(), Infinity);
exitCode = 2;
} else {
var difference = parseFloat(error.match(/^\d+(?:\.\d+)?\s+\(([^\)]+)\)\s*$/)[1]);
writeResult(base, info, '', difference);
processFileTest();
}
return processFiles();
});
compare.stdin.end();
function processFileTest() {
if (!keys.length) return processFiles();
var key = keys.shift();
var base = path.basename(name, '.info.json');
var actual = path.join(base_dir, base + '/' + key + '.actual.png');
var expected = path.join(base_dir, base + '/' + key + '.expected.png');
var diff = path.join(base_dir, base + '/' + key + '.diff.png');
var compare = spawn('compare', ['-metric', 'MAE', actual, expected, diff ]);
var error = '';
compare.stderr.on('data', function(data) {
error += data.toString();
});
compare.on('exit', function(code, signal) {
// The compare program returns 2 on error otherwise 0 if the images are similar or 1 if they are dissimilar.
if (code == 2) {
writeResult(base, key, info[key], error.trim(), Infinity);
exitCode = 2;
} else {
var match = error.match(/^\d+(?:\.\d+)?\s+\(([^\)]+)\)\s*$/);
var difference = match ? parseFloat(match[1]) : Infinity;
writeResult(base, key, info[key], match ? '' : error, difference);
}
processFileTest();
});
compare.stdin.end();
}
}
function writeResult(base, info, error, difference) {
function writeResult(base, key, info, error, difference) {
var color = 'green';
var allowedDifference = ('diff' in info) ? info.diff : 0.01;
if (difference > allowedDifference) {
@@ -72,19 +84,18 @@ function writeResult(base, info, error, difference) {
html +=
'<tr>\n' +
' <td><img src="' + base + '.actual.png" onmouseover="this.src=\'' + base + '.expected.png\'" onmouseout="this.src=\'' + base + '.actual.png\'"></td>\n' +
' <td><img src="' + base + '.expected.png" onmouseover="this.src=\'' + base + '.diff.png\'" onmouseout="this.src=\'' + base + '.expected.png\'"></td>\n' +
' <td><img src="' + base + '/' + key + '.actual.png" onmouseover="this.src=\'' + base + '/' + key + '.expected.png\'" onmouseout="this.src=\'' + base + '/' + key + '.actual.png\'"></td>\n' +
' <td><img src="' + base + '/' + key + '.expected.png" onmouseover="this.src=\'' + base + '/' + key + '.diff.png\'" onmouseout="this.src=\'' + base + '/' + key + '.expected.png\'"></td>\n' +
' <td>\n' +
' <h2 style="text-align:center; background:' + color + '"><a href="' + base + '.style.json">' + base + '</a></h2>\n' +
' <h2 style="text-align:center; background:' + color + '"><a href="' + base + '.style.json">' + base + '/' + key + '</a></h2>\n' +
(error ? ' <p>' + error + '</p>\n' : '') +
' <ul>\n' +
' <li>diff: <strong>' + difference + '</strong></li>\n' +
' <li>zoom: <strong>' + (info.zoom || 0) + '</strong></li>\n' +
' <li>latitude: <strong>' + (info.latitude || 0) + '</strong></li>\n' +
' <li>longitude: <strong>' + (info.longitude || 0) + '</strong></li>\n' +
' <li>angle: <strong>' + (info.angle || 0) + '</strong></li>\n' +
' <li>width: <strong>' + (info.width || 0) + '</strong></li>\n' +
' <li>height: <strong>' + (info.height || 0) + '</strong></li>\n' +
' <li>center: <strong>' + (info.center || [0, 0]) + '</strong></li>\n' +
' <li>bearing: <strong>' + (info.bearing || 0) + '</strong></li>\n' +
' <li>width: <strong>' + (info.width || 512) + '</strong></li>\n' +
' <li>height: <strong>' + (info.height || 512) + '</strong></li>\n' +
' </ul>\n' +
' </td>\n' +
'</tr>\n'

View File

@@ -183,6 +183,14 @@ std::string Map::getStyleJSON() const {
return styleJSON;
}
void Map::setAccessToken( std::string access_token) {
accessToken.swap(access_token);
}
std::string Map::getAccessToken() const {
return accessToken;
}
#pragma mark - Size
// Note: This function is called from another thread. Make sure you only call threadsafe functions!
@@ -397,10 +405,6 @@ const std::vector<std::string> &Map::getAppliedClasses() const {
return style->getAppliedClasses();
}
void Map::setAppliedClasses(std::vector<std::string> &class_names) {
style->setAppliedClasses(class_names);
}
void Map::setDefaultTransitionDuration(uint64_t duration_milliseconds) {
style->setDefaultTransitionDuration(duration_milliseconds);
}

View File

@@ -26,21 +26,25 @@ Source::Source(StyleSource style_source, const std::string &access_token)
max_zoom(style_source.max_zoom) {}
Source::Source(SourceType type, const std::string &url,
uint32_t tile_size, uint32_t min_zoom, uint32_t max_zoom)
uint32_t tile_size, uint32_t min_zoom, uint32_t max_zoom,
const std::string &access_token)
: type(type),
url(normalizeSourceURL(url)),
url(normalizeSourceURL(url, access_token)),
tile_size(tile_size),
min_zoom(min_zoom),
max_zoom(max_zoom) {}
std::string Source::normalizeSourceURL(const std::string &url) {
std::string Source::normalizeSourceURL(const std::string &url, const std::string &access_token) {
const std::string t = "mapbox://";
if (url.compare(0, t.length(), t) == 0) {
return std::string("http://api.tiles.mapbox.com/v3/") + url.substr(t.length()) + "/{z}/{x}/{y}.vector.pbf";
if (access_token.empty()) {
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
}
return std::string("https://api.tiles.mapbox.com/v4/") + url.substr(t.length()) + "/{z}/{x}/{y}.vector.pbf?access_token=" + access_token;
} else {
return url;
}
};
}
bool Source::update(Map &map) {
if (map.getTime() > updated) {

View File

@@ -92,7 +92,7 @@ float TransformState::getPixelRatio() const {
#pragma mark - Zoom
float TransformState::getNormalizedZoom() const {
return std::log(scale * util::tileSize / 256.0f) / M_LN2;
return std::log(scale * util::tileSize / 512.0f) / M_LN2;
}
int32_t TransformState::getIntegerZoom() const {

View File

@@ -150,7 +150,6 @@ void Painter::renderFill(FillBucket& bucket, std::shared_ptr<StyleLayer> layer_d
if (!bucket.hasData()) return;
const FillProperties &properties = layer_desc->getProperties<FillProperties>();
if (!properties.enabled) return;
if (layer_desc->rasterize && layer_desc->rasterize->isEnabled(id.z)) {
if (pass == Translucent) {

View File

@@ -14,7 +14,6 @@ void Painter::renderIcon(IconBucket& bucket, std::shared_ptr<StyleLayer> layer_d
if (pass == Opaque) return;
const IconProperties &properties = layer_desc->getProperties<IconProperties>();
if (!properties.enabled) return;
// TODO: when translating icon, are we doing this in the bucket already?
// const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);

View File

@@ -11,7 +11,6 @@ void Painter::renderLine(LineBucket& bucket, std::shared_ptr<StyleLayer> layer_d
if (!bucket.hasData()) return;
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
if (!properties.enabled) return;
float width = properties.width;
float offset = properties.offset / 2;

View File

@@ -9,7 +9,6 @@ void Painter::renderRaster(RasterBucket& bucket, std::shared_ptr<StyleLayer> lay
if (pass == Translucent) return;
const RasterProperties &properties = layer_desc->getProperties<RasterProperties>();
if (!properties.enabled) return;
depthMask(false);

View File

@@ -12,7 +12,6 @@ void Painter::renderText(TextBucket& bucket, std::shared_ptr<StyleLayer> layer_d
if (!bucket.hasData()) return;
const TextProperties &properties = layer_desc->getProperties<TextProperties>();
if (!properties.enabled) return;
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);

View File

@@ -34,16 +34,16 @@ bool ExponentialFunction<bool>::evaluate(float z) const {
template <>
float ExponentialFunction<float>::evaluate(float z) const {
return std::fmin(std::fmax(min, value + std::pow(1.75, (z - z_base)) * slope), max);
return std::fmin(std::fmax(min, value + std::pow(exp_base, (z - z_base)) * slope), max);
}
template <>
Color ExponentialFunction<Color>::evaluate(float z) const {
return {{
std::fmin(std::fmax(min[0], value[0] + float(std::pow(1.75, (z - z_base))) * slope), max[0]),
std::fmin(std::fmax(min[1], value[1] + float(std::pow(1.75, (z - z_base))) * slope), max[1]),
std::fmin(std::fmax(min[2], value[2] + float(std::pow(1.75, (z - z_base))) * slope), max[2]),
std::fmin(std::fmax(min[3], value[3] + float(std::pow(1.75, (z - z_base))) * slope), max[3])
std::fmin(std::fmax(min[0], value[0] + float(std::pow(exp_base, (z - z_base))) * slope), max[0]),
std::fmin(std::fmax(min[1], value[1] + float(std::pow(exp_base, (z - z_base))) * slope), max[1]),
std::fmin(std::fmax(min[2], value[2] + float(std::pow(exp_base, (z - z_base))) * slope), max[2]),
std::fmin(std::fmax(min[3], value[3] + float(std::pow(exp_base, (z - z_base))) * slope), max[3])
}};
}

View File

@@ -3,7 +3,6 @@
namespace llmr {
const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::FillEnabled, true },
{ PropertyKey::FillAntialias, true },
{ PropertyKey::FillOpacity, 1.0f },
{ PropertyKey::FillColor, Color({{ 0, 0, 0, 1 }}) },
@@ -11,7 +10,6 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::FillTranslateY, 0.0f },
{ PropertyKey::FillTranslateAnchor, TranslateAnchorType::Map },
{ PropertyKey::LineEnabled, true },
{ PropertyKey::LineOpacity, 1.0f },
{ PropertyKey::LineColor, Color({{ 0, 0, 0, 1 }}) },
{ PropertyKey::LineTranslateX, 0.0f },
@@ -23,12 +21,10 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::LineDashLand, 1.0f },
{ PropertyKey::LineDashGap, -1.0f },
{ PropertyKey::IconEnabled, true },
{ PropertyKey::IconOpacity, 1.0f },
{ PropertyKey::IconRotate, 0.0f },
{ PropertyKey::IconRotateAnchor, RotateAnchorType::Viewport },
{ PropertyKey::TextEnabled, true },
{ PropertyKey::TextOpacity, 1.0f },
{ PropertyKey::TextSize, 16.0f },
{ PropertyKey::TextColor, Color({{ 0, 0, 0, 1 }}) },
@@ -36,10 +32,8 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::TextHaloWidth, 0.25f },
{ PropertyKey::TextHaloBlur, 1.0f },
{ PropertyKey::CompositeEnabled, true },
{ PropertyKey::CompositeOpacity, 1.0f },
{ PropertyKey::RasterEnabled, true },
{ PropertyKey::RasterOpacity, 1.0f },
{ PropertyKey::RasterSpin, 0.0f },
{ PropertyKey::RasterBrightnessLow, 0.0f },

View File

@@ -163,7 +163,6 @@ template <>
void StyleLayer::applyStyleProperties<FillProperties>(const float z, const timestamp now) {
properties.set<FillProperties>();
FillProperties &fill = properties.get<FillProperties>();
applyStyleProperty(PropertyKey::FillEnabled, fill.enabled, z, now);
applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now);
applyStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now);
applyStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now);
@@ -178,7 +177,6 @@ template <>
void StyleLayer::applyStyleProperties<LineProperties>(const float z, const timestamp now) {
properties.set<LineProperties>();
LineProperties &line = properties.get<LineProperties>();
applyStyleProperty(PropertyKey::LineEnabled, line.enabled, z, now);
applyStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now);
applyStyleProperty(PropertyKey::LineColor, line.color, z, now);
applyStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now);
@@ -196,7 +194,6 @@ template <>
void StyleLayer::applyStyleProperties<IconProperties>(const float z, const timestamp now) {
properties.set<IconProperties>();
IconProperties &icon = properties.get<IconProperties>();
applyStyleProperty(PropertyKey::IconEnabled, icon.enabled, z, now);
applyStyleProperty(PropertyKey::IconOpacity, icon.opacity, z, now);
applyStyleProperty(PropertyKey::IconRotate, icon.rotate, z, now);
applyStyleProperty(PropertyKey::IconRotateAnchor, icon.rotate_anchor, z, now);
@@ -206,7 +203,6 @@ template <>
void StyleLayer::applyStyleProperties<TextProperties>(const float z, const timestamp now) {
properties.set<TextProperties>();
TextProperties &text = properties.get<TextProperties>();
applyStyleProperty(PropertyKey::TextEnabled, text.enabled, z, now);
applyStyleProperty(PropertyKey::TextOpacity, text.opacity, z, now);
applyStyleProperty(PropertyKey::TextSize, text.size, z, now);
applyStyleProperty(PropertyKey::TextColor, text.color, z, now);
@@ -219,7 +215,6 @@ template <>
void StyleLayer::applyStyleProperties<CompositeProperties>(const float z, const timestamp now) {
properties.set<CompositeProperties>();
CompositeProperties &composite = properties.get<CompositeProperties>();
applyStyleProperty(PropertyKey::CompositeEnabled, composite.enabled, z, now);
applyStyleProperty(PropertyKey::CompositeOpacity, composite.opacity, z, now);
}
@@ -227,7 +222,6 @@ template <>
void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const timestamp now) {
properties.set<RasterProperties>();
RasterProperties &raster = properties.get<RasterProperties>();
applyStyleProperty(PropertyKey::RasterEnabled, raster.enabled, z, now);
applyStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now);
applyStyleProperty(PropertyKey::RasterSpin, raster.spin, z, now);
applyStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now);
@@ -249,11 +243,6 @@ void StyleLayer::updateProperties(float z, const timestamp now) {
layers->updateProperties(z, now);
}
// Accomodate for different tile size.
if (bucket && bucket->style_source) {
z += std::log(bucket->style_source->tile_size / 256.0f) / M_LN2;
}
cleanupAppliedStyleProperties(now);
switch (type) {

View File

@@ -168,7 +168,9 @@ void StyleParser::parseSources(JSVal value) {
parseRenderProperty(itr->value, type, "type", parseSourceType);
parseRenderProperty(itr->value, url, "url");
parseRenderProperty(itr->value, tile_size, "tileSize");
if (type == SourceType::Raster) {
parseRenderProperty(itr->value, tile_size, "tileSize");
}
parseRenderProperty(itr->value, min_zoom, "minZoom");
parseRenderProperty(itr->value, max_zoom, "maxZoom");
@@ -269,11 +271,12 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
}
const float z_base = parseFunctionArgument<float>(value["z"]);
const float exp_base = value.HasMember("base") ? parseFunctionArgument<float>(value["base"]) : 1.75;
const T val = parseFunctionArgument<T>(value["val"]);
const float slope = value.HasMember("slope") ? parseFunctionArgument<float>(value["slope"]) : 1;
const T min = value.HasMember("min") ? parseFunctionArgument<T>(value["min"]) : T();
const T max = value.HasMember("max") ? parseFunctionArgument<T>(value["max"]) : T();
return std::tuple<bool, Function<T>> { true, ExponentialFunction<T>(val, z_base, slope, min, max) };
return std::tuple<bool, Function<T>> { true, ExponentialFunction<T>(val, z_base, exp_base, slope, min, max) };
}
else if (type == "stops") {
if (!value.HasMember("stops")) {
@@ -595,8 +598,6 @@ void StyleParser::parseStyles(JSVal value, std::map<ClassID, ClassProperties> &s
void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
using Key = PropertyKey;
parseOptionalProperty<Function<bool>>("fill-enabled", Key::FillEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-fill-enabled", Key::FillEnabled, klass, value);
parseOptionalProperty<Function<bool>>("fill-antialias", Key::FillAntialias, klass, value);
parseOptionalProperty<Function<float>>("fill-opacity", Key::FillOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-fill-opacity", Key::FillOpacity, klass, value);
@@ -609,8 +610,6 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
parseOptionalProperty<TranslateAnchorType>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
parseOptionalProperty<std::string>("fill-image", Key::FillImage, klass, value);
parseOptionalProperty<Function<bool>>("line-enabled", Key::LineEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-line-enabled", Key::LineEnabled, klass, value);
parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-line-opacity", Key::LineOpacity, klass, value);
parseOptionalProperty<Function<Color>>("line-color", Key::LineColor, klass, value);
@@ -628,15 +627,11 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("transition-line-dasharray", Key::LineDashArray, klass, value);
parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value);
parseOptionalProperty<Function<bool>>("icon-enabled", Key::IconEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-icon-enabled", Key::IconEnabled, klass, value);
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-icon-opacity", Key::IconOpacity, klass, value);
parseOptionalProperty<Function<float>>("icon-rotate", Key::IconRotate, klass, value);
parseOptionalProperty<RotateAnchorType>("icon-rotate-anchor", Key::IconRotateAnchor, klass, value);
parseOptionalProperty<Function<bool>>("text-enabled", Key::TextEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-text-enabled", Key::TextEnabled, klass, value);
parseOptionalProperty<Function<float>>("text-opacity", Key::TextOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-text-opacity", Key::TextOpacity, klass, value);
parseOptionalProperty<Function<float>>("text-size", Key::TextSize, klass, value);
@@ -650,13 +645,9 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
parseOptionalProperty<Function<float>>("text-halo-blur", Key::TextHaloBlur, klass, value);
parseOptionalProperty<PropertyTransition>("transition-text-halo-blur", Key::TextHaloBlur, klass, value);
parseOptionalProperty<Function<bool>>("composite-enabled", Key::CompositeEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-composite-enabled", Key::CompositeEnabled, klass, value);
parseOptionalProperty<Function<float>>("composite-opacity", Key::CompositeOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-composite-opacity", Key::CompositeOpacity, klass, value);
parseOptionalProperty<Function<bool>>("raster-enabled", Key::RasterEnabled, klass, value);
parseOptionalProperty<PropertyTransition>("transition-raster-enabled", Key::RasterEnabled, klass, value);
parseOptionalProperty<Function<float>>("raster-opacity", Key::RasterOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("transition-raster-opacity", Key::RasterOpacity, klass, value);
parseOptionalProperty<Function<float>>("raster-spin", Key::RasterSpin, klass, value);

View File

@@ -40,6 +40,7 @@ platform::request_http(const std::string &url,
if (err < 0) {
req->res->code = err;
req->res->error_message = uv_strerror(err);
fprintf(stderr, "[WARNING] fixture request: %s\n", uv_strerror(err));
req->complete();
return req;
}
@@ -52,6 +53,7 @@ platform::request_http(const std::string &url,
if (err < 0) {
req->res->code = err;
req->res->error_message = uv_strerror(err);
fprintf(stderr, "[WARNING] fixture request: %s\n", uv_strerror(err));
req->complete();
return req;
}
@@ -69,6 +71,7 @@ platform::request_http(const std::string &url,
if (err < 0) {
req->res->code = err;
req->res->error_message = uv_strerror(err);
fprintf(stderr, "[WARNING] fixture request: %s\n", uv_strerror(err));
req->complete();
return req;
}
@@ -80,12 +83,14 @@ platform::request_http(const std::string &url,
if (err < 0) {
req->res->code = err;
req->res->error_message = uv_strerror(err);
fprintf(stderr, "[WARNING] fixture request: %s\n", uv_strerror(err));
req->complete();
return req;
}
req->res->body.swap(body);
req->res->code = 200;
fprintf(stderr, "[INFO] fixture request completed: %s\n", clean_url.c_str());
req->complete();
return req;

View File

@@ -1,8 +0,0 @@
{
"zoom": 0,
"latitude": 0,
"longitude": 0,
"angle": 0,
"width": 512,
"height": 512
}

View File

@@ -1,8 +0,0 @@
{
"zoom": 0,
"latitude": 0,
"longitude": 0,
"angle": 0,
"width": 512,
"height": 512
}

View File

@@ -0,0 +1,13 @@
{
"default": {
"zoom": 14,
"center": [52.499167, 13.418056],
"height": 256
},
"colored": {
"zoom": 14,
"center": [52.499167, 13.418056],
"height": 256,
"classes": ["colored"]
}
}

View File

@@ -0,0 +1,33 @@
{
"version": 3,
"sources": {
"mapbox": {
"type": "vector",
"url": "tiles/{z}-{x}-{y}.vector.pbf",
"tileSize": 512,
"maxZoom": 14
}
},
"layers": [
{
"id": "background",
"type": "background",
"style": {
"background-color": "white"
}
},
{
"id": "road",
"source": "mapbox",
"source-layer": "road",
"type": "line",
"style": {
"line-width": 2,
"line-color": "#3590db"
},
"style.colored": {
"line-color": "#222222"
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -0,0 +1,22 @@
{
"z13.9": {
"zoom": 13.9,
"center": [52.499167, 13.418056],
"height": 256
},
"z14.0": {
"zoom": 14,
"center": [52.499167, 13.418056],
"height": 256
},
"z14.1": {
"zoom": 14.1,
"center": [52.499167, 13.418056],
"height": 256
},
"z14.2": {
"zoom": 14.2,
"center": [52.499167, 13.418056],
"height": 256
}
}

View File

@@ -0,0 +1,32 @@
{
"version": 3,
"sources": {
"mapbox": {
"type": "vector",
"url": "tiles/{z}-{x}-{y}.vector.pbf",
"tileSize": 512,
"maxZoom": 14
}
},
"layers": [
{
"id": "background",
"type": "background",
"style": {
"background-color": "white"
}
},
{
"id": "road",
"source": "mapbox",
"source-layer": "road",
"type": "line",
"style": {
"line-width": {
"fn": "stops",
"stops": [[13, 0], [13.999, 0], [14, 4], [14.1, 10], [14.2, 20]]
}
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,6 @@
{
"plain": {
"center": [0, 0],
"zoom": 0
}
}

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -0,0 +1,6 @@
{
"plain": {
"center": [0, 0],
"zoom": 0
}
}

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -63,7 +63,7 @@ TEST(Function, Linear) {
TEST(Function, Exponential) {
llmr::ExponentialFunction<float> slope_1(/* val */ 7.5, /* z_base */ 4, /* slope */ 2, /* min */ 7.5, /* max */ 20);
llmr::ExponentialFunction<float> slope_1(/* val */ 7.5, /* z_base */ 4, /* exp_base */ 1.75, /* slope */ 2, /* min */ 7.5, /* max */ 20);
ASSERT_FLOAT_EQ(8.6428576, slope_1.evaluate(3)); // 7.5 + 1.75^(3 - 4) * 2
ASSERT_FLOAT_EQ(9.5, slope_1.evaluate(4)); // 7.5 + 1.75^(4 - 4) * 2
ASSERT_FLOAT_EQ(10.145751, slope_1.evaluate(4.5)); // 7.5 + 1.75^(4.5 - 4) * 2

View File

@@ -9,61 +9,94 @@
#include "../common/headless_view.hpp"
#include <dirent.h>
const std::string base_directory = []{
std::string fn = __FILE__;
fn.erase(fn.find_last_of("/"));
return fn;
return fn + "/fixtures/styles";
}();
class HeadlessTest : public ::testing::TestWithParam<const char *> {};
class HeadlessTest : public ::testing::TestWithParam<std::string> {};
TEST_P(HeadlessTest, render) {
const char *base = GetParam();
const std::string &base = GetParam();
const std::string style = llmr::util::read_file(base_directory + "/fixtures/styles/" + base + ".style.json");
const std::string info = llmr::util::read_file(base_directory + "/fixtures/styles/" + base + ".info.json");
const std::string expected_image = base_directory + "/fixtures/styles/" + base + ".expected.png";
const std::string actual_image = base_directory + "/fixtures/styles/" + base + ".actual.png";
const std::string style = llmr::util::read_file(base_directory + "/" + base + ".style.json");
const std::string info = llmr::util::read_file(base_directory + "/" + base + ".info.json");
// Parse settings.
rapidjson::Document doc;
doc.Parse<0>((const char *const)info.c_str());
ASSERT_EQ(false, doc.HasParseError());
const double zoom = doc.HasMember("zoom") ? doc["zoom"].GetDouble() : 0;
const double angle = doc.HasMember("angle") ? doc["angle"].GetDouble() : 0;
const double longitude = doc.HasMember("longitude") ? doc["longitude"].GetDouble() : 0;
const double latitude = doc.HasMember("latitude") ? doc["latitude"].GetDouble() : 0;
const unsigned int width = doc.HasMember("width") ? doc["width"].GetUint() : 0;
const unsigned int height = doc.HasMember("height") ? doc["height"].GetUint() : 0;
ASSERT_EQ(true, doc.IsObject());
// Setup OpenGL
llmr::HeadlessView view;
llmr::Map map(view);
view.resize(width, height);
map.resize(width, height);
for (auto it = doc.MemberBegin(), end = doc.MemberEnd(); it != end; it++) {
const std::string name { it->name.GetString(), it->name.GetStringLength() };
const rapidjson::Value &value = it->value;
ASSERT_EQ(true, value.IsObject());
if (value.HasMember("center")) ASSERT_EQ(true, value["center"].IsArray());
map.setStyleJSON(style);
const std::string actual_image = base_directory + "/" + base + "/" + name + ".actual.png";
map.setLonLatZoom(longitude, latitude, zoom);
map.setAngle(angle);
map.setDebug(false);
const double zoom = value.HasMember("zoom") ? value["zoom"].GetDouble() : 0;
const double bearing = value.HasMember("bearing") ? value["bearing"].GetDouble() : 0;
const double latitude = value.HasMember("center") ? value["center"][rapidjson::SizeType(0)].GetDouble() : 0;
const double longitude = value.HasMember("center") ? value["center"][rapidjson::SizeType(1)].GetDouble() : 0;
const unsigned int width = value.HasMember("width") ? value["width"].GetUint() : 512;
const unsigned int height = value.HasMember("height") ? value["height"].GetUint() : 512;
std::vector<std::string> classes;
if (value.HasMember("classes")) {
const rapidjson::Value &js_classes = value["classes"];
ASSERT_EQ(true, js_classes.IsArray());
for (rapidjson::SizeType i = 0; i < js_classes.Size(); i++) {
const rapidjson::Value &js_class = js_classes[i];
ASSERT_EQ(true, js_class.IsString());
classes.push_back({ js_class.GetString(), js_class.GetStringLength() });
}
}
// Run the loop. It will terminate when we don't have any further listeners.
map.run();
map.setStyleJSON(style);
map.setAppliedClasses(classes);
const std::unique_ptr<uint32_t[]> pixels(new uint32_t[width * height]);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
view.resize(width, height);
map.resize(width, height);
map.setLonLatZoom(longitude, latitude, zoom);
map.setAngle(bearing);
const std::string image = llmr::util::compress_png(width, height, pixels.get(), true);
llmr::util::write_file(actual_image, image);
// Run the loop. It will terminate when we don't have any further listeners.
map.run();
const std::unique_ptr<uint32_t[]> pixels(new uint32_t[width * height]);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
const std::string image = llmr::util::compress_png(width, height, pixels.get(), true);
llmr::util::write_file(actual_image, image);
}
const std::string expected_image_data(llmr::util::read_file(expected_image));
const llmr::util::Image expected(expected_image_data, true);
ASSERT_EQ(width, expected.getWidth());
ASSERT_EQ(height, expected.getHeight());
}
INSTANTIATE_TEST_CASE_P(Headless, HeadlessTest,
::testing::Values("0", "1"));
INSTANTIATE_TEST_CASE_P(Headless, HeadlessTest, ::testing::ValuesIn([] {
std::vector<std::string> names;
const std::string ending = ".info.json";
DIR *dir = opendir(base_directory.c_str());
if (dir == nullptr) {
return names;
}
for (dirent *dp = nullptr; (dp = readdir(dir)) != nullptr;) {
const std::string name = dp->d_name;
if (name.length() >= ending.length() && name.compare(name.length() - ending.length(), ending.length(), ending) == 0) {
names.push_back(name.substr(0, name.length() - ending.length()));
}
}
closedir(dir);
return names;
}()));