Add sdf
sprite support with /sdf_sprite/...
endpoint (#1492)
Given a set of SVGs as a sprite source X, Martin will now generate two endpoints: `/sprite/X` and `/sdf_sprite/X`, with the second endpoint serving [signed distance field](https://en.wikipedia.org/wiki/Signed_distance_function) images. Closes #1075
@ -1,6 +1,7 @@
|
||||
## Sprite Sources
|
||||
|
||||
Given a directory with SVG images, Martin will generate a sprite -- a JSON index and a PNG image, for both low and highresolution displays. The SVG filenames without extension will be used as the sprites' image IDs (remember that one sprite and thus `sprite_id` contains multiple images).
|
||||
Given a directory with SVG images, Martin will generate a sprite -- a JSON index and a PNG image, for both low and highresolution displays.
|
||||
The SVG filenames without extension will be used as the sprites' image IDs (remember that one sprite and thus `sprite_id` contains multiple images).
|
||||
The images are searched recursively in the given directory, so subdirectory names will be used as prefixes for the image IDs.
|
||||
For example `icons/bicycle.svg` will be available as `icons/bicycle` sprite image.
|
||||
|
||||
@ -40,6 +41,19 @@ the PNG, there is a high DPI version available at `/sprite/<sprite_id>@2x.json`.
|
||||
}
|
||||
```
|
||||
|
||||
##### Coloring at runtime via Signed Distance Fields (SDFs)
|
||||
|
||||
If you want to set the color of a sprite at runtime, you will need use the [Signed Distance Fields (SDFs)](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf)-endpoints.
|
||||
For example, maplibre does support the image being modified via the [`icon-color`](https://maplibre.org/maplibre-style-spec/layers/#icon-color) and [`icon-halo-color`](https://maplibre.org/maplibre-style-spec/layers/#icon-halo-color) properties if using SDFs.
|
||||
|
||||
SDFs have the significant **downside of only allowing one color**.
|
||||
If you want multiple colors, you will need to layer icons on top of each other.
|
||||
|
||||
The following APIs are available:
|
||||
|
||||
- `/sdf_sprite/<sprite_id>.json` for getting a sprite index as SDF and
|
||||
- `/sdf_sprite/<sprite_id>.png` for getting sprite PNGs as SDF
|
||||
|
||||
#### Combining Multiple Sprites
|
||||
|
||||
Multiple `sprite_id` values can be combined into one sprite with the same pattern as for tile
|
||||
|
@ -2,18 +2,19 @@
|
||||
|
||||
Martin data is available via the HTTP `GET` endpoints:
|
||||
|
||||
| URL | Description |
|
||||
|-----------------------------------------|------------------------------------------------|
|
||||
| `/` | Web UI |
|
||||
| `/catalog` | [List of all sources](#catalog) |
|
||||
| `/{sourceID}` | [Source TileJSON](#source-tilejson) |
|
||||
| `/{sourceID}/{z}/{x}/{y}` | Map Tiles |
|
||||
| `/{source1},…,{sourceN}` | [Composite Source TileJSON](#source-tilejson) |
|
||||
| `/{source1},…,{sourceN}/{z}/{x}/{y}` | [Composite Source Tiles](sources-composite.md) |
|
||||
| `/sprite/{spriteID}[@2x].{json,png}` | [Sprite sources](sources-sprites.md) |
|
||||
| `/font/{font}/{start}-{end}` | [Font source](sources-fonts.md) |
|
||||
| `/font/{font1},…,{fontN}/{start}-{end}` | [Composite Font source](sources-fonts.md) |
|
||||
| `/health` | Martin server health check: returns 200 `OK` |
|
||||
| URL | Description |
|
||||
|------------------------------------------|------------------------------------------------|
|
||||
| `/` | Web UI |
|
||||
| `/catalog` | [List of all sources](#catalog) |
|
||||
| `/{sourceID}` | [Source TileJSON](#source-tilejson) |
|
||||
| `/{sourceID}/{z}/{x}/{y}` | Map Tiles |
|
||||
| `/{source1},…,{sourceN}` | [Composite Source TileJSON](#source-tilejson) |
|
||||
| `/{source1},…,{sourceN}/{z}/{x}/{y}` | [Composite Source Tiles](sources-composite.md) |
|
||||
| `/sprite/{spriteID}[@2x].{json,png}` | [Sprite sources](sources-sprites.md) |
|
||||
| `/sdf_sprite/{spriteID}[@2x].{json,png}` | [SDF Sprite sources](sources-sprites.md) |
|
||||
| `/font/{font}/{start}-{end}` | [Font source](sources-fonts.md) |
|
||||
| `/font/{font1},…,{fontN}/{start}-{end}` | [Composite Font source](sources-fonts.md) |
|
||||
| `/health` | Martin server health check: returns 200 `OK` |
|
||||
|
||||
### Duplicate Source ID
|
||||
|
||||
|
@ -146,7 +146,7 @@ impl SpriteSources {
|
||||
|
||||
/// Given a list of IDs in a format "id1,id2,id3", return a spritesheet with them all.
|
||||
/// `ids` may optionally end with "@2x" to request a high-DPI spritesheet.
|
||||
pub async fn get_sprites(&self, ids: &str) -> SpriteResult<Spritesheet> {
|
||||
pub async fn get_sprites(&self, ids: &str, as_sdf: bool) -> SpriteResult<Spritesheet> {
|
||||
let (ids, dpi) = if let Some(ids) = ids.strip_suffix("@2x") {
|
||||
(ids, 2)
|
||||
} else {
|
||||
@ -162,7 +162,7 @@ impl SpriteSources {
|
||||
})
|
||||
.collect::<SpriteResult<Vec<_>>>()?;
|
||||
|
||||
get_spritesheet(sprite_ids.into_iter(), dpi).await
|
||||
get_spritesheet(sprite_ids.into_iter(), dpi, as_sdf).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +175,7 @@ async fn parse_sprite(
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
pixel_ratio: u8,
|
||||
as_sdf: bool,
|
||||
) -> SpriteResult<(String, Sprite)> {
|
||||
let on_err = |e| SpriteError::IoError(e, path.clone());
|
||||
|
||||
@ -186,7 +187,12 @@ async fn parse_sprite(
|
||||
let tree = Tree::from_data(&buffer, &Options::default())
|
||||
.map_err(|e| SpriteParsingError(e, path.clone()))?;
|
||||
|
||||
let sprite = Sprite::new(tree, pixel_ratio).ok_or_else(|| SpriteInstError(path.clone()))?;
|
||||
let sprite = if as_sdf {
|
||||
Sprite::new_sdf(tree, pixel_ratio)
|
||||
} else {
|
||||
Sprite::new(tree, pixel_ratio)
|
||||
};
|
||||
let sprite = sprite.ok_or_else(|| SpriteInstError(path.clone()))?;
|
||||
|
||||
Ok((name, sprite))
|
||||
}
|
||||
@ -194,6 +200,7 @@ async fn parse_sprite(
|
||||
pub async fn get_spritesheet(
|
||||
sources: impl Iterator<Item = &SpriteSource>,
|
||||
pixel_ratio: u8,
|
||||
as_sdf: bool,
|
||||
) -> SpriteResult<Spritesheet> {
|
||||
// Asynchronously load all SVG files from the given sources
|
||||
let mut futures = Vec::new();
|
||||
@ -203,11 +210,14 @@ pub async fn get_spritesheet(
|
||||
for path in paths {
|
||||
let name = sprite_name(&path, &source.path)
|
||||
.map_err(|e| SpriteProcessingError(e, source.path.clone()))?;
|
||||
futures.push(parse_sprite(name, path, pixel_ratio));
|
||||
futures.push(parse_sprite(name, path, pixel_ratio, as_sdf));
|
||||
}
|
||||
}
|
||||
let sprites = try_join_all(futures).await?;
|
||||
let mut builder = SpritesheetBuilder::new();
|
||||
if as_sdf {
|
||||
builder.make_sdf();
|
||||
}
|
||||
builder.sprites(sprites.into_iter().collect());
|
||||
|
||||
// TODO: decide if this is needed and/or configurable
|
||||
@ -234,24 +244,32 @@ mod tests {
|
||||
let sprites = SpriteSources::resolve(&mut cfg).unwrap().0;
|
||||
assert_eq!(sprites.len(), 2);
|
||||
|
||||
test_src(sprites.values(), 1, "all_1").await;
|
||||
test_src(sprites.values(), 2, "all_2").await;
|
||||
//.sdf => generate sdf from png, add sdf == true
|
||||
//- => does not generate sdf, omits sdf == true
|
||||
for extension in ["_sdf", ""] {
|
||||
test_src(sprites.values(), 1, "all_1", extension).await;
|
||||
test_src(sprites.values(), 2, "all_2", extension).await;
|
||||
|
||||
test_src(sprites.get("src1").into_iter(), 1, "src1_1").await;
|
||||
test_src(sprites.get("src1").into_iter(), 2, "src1_2").await;
|
||||
test_src(sprites.get("src1").into_iter(), 1, "src1_1", extension).await;
|
||||
test_src(sprites.get("src1").into_iter(), 2, "src1_2", extension).await;
|
||||
|
||||
test_src(sprites.get("src2").into_iter(), 1, "src2_1").await;
|
||||
test_src(sprites.get("src2").into_iter(), 2, "src2_2").await;
|
||||
test_src(sprites.get("src2").into_iter(), 1, "src2_1", extension).await;
|
||||
test_src(sprites.get("src2").into_iter(), 2, "src2_2", extension).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn test_src(
|
||||
sources: impl Iterator<Item = &SpriteSource>,
|
||||
pixel_ratio: u8,
|
||||
filename: &str,
|
||||
extension: &str,
|
||||
) {
|
||||
let path = PathBuf::from(format!("../tests/fixtures/sprites/expected/{filename}"));
|
||||
|
||||
let sprites = get_spritesheet(sources, pixel_ratio).await.unwrap();
|
||||
let path = PathBuf::from(format!(
|
||||
"../tests/fixtures/sprites/expected/{filename}{extension}"
|
||||
));
|
||||
let sprites = get_spritesheet(sources, pixel_ratio, extension == "_sdf")
|
||||
.await
|
||||
.unwrap();
|
||||
let mut json = serde_json::to_string_pretty(sprites.get_index()).unwrap();
|
||||
json.push('\n');
|
||||
let png = sprites.encode_png().unwrap();
|
||||
|
@ -114,7 +114,9 @@ pub fn router(cfg: &mut web::ServiceConfig, #[allow(unused_variables)] usr_cfg:
|
||||
.service(get_tile);
|
||||
|
||||
#[cfg(feature = "sprites")]
|
||||
cfg.service(crate::srv::sprites::get_sprite_json)
|
||||
cfg.service(crate::srv::sprites::get_sprite_sdf_json)
|
||||
.service(crate::srv::sprites::get_sprite_json)
|
||||
.service(crate::srv::sprites::get_sprite_sdf_png)
|
||||
.service(crate::srv::sprites::get_sprite_png);
|
||||
|
||||
#[cfg(feature = "fonts")]
|
||||
|
@ -15,7 +15,18 @@ async fn get_sprite_png(
|
||||
path: Path<SourceIDsRequest>,
|
||||
sprites: Data<SpriteSources>,
|
||||
) -> ActixResult<HttpResponse> {
|
||||
let sheet = get_sprite(&path, &sprites).await?;
|
||||
let sheet = get_sprite(&path, &sprites, false).await?;
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(ContentType::png())
|
||||
.body(sheet.encode_png().map_err(map_internal_error)?))
|
||||
}
|
||||
|
||||
#[route("/sdf_sprite/{source_ids}.png", method = "GET", method = "HEAD")]
|
||||
async fn get_sprite_sdf_png(
|
||||
path: Path<SourceIDsRequest>,
|
||||
sprites: Data<SpriteSources>,
|
||||
) -> ActixResult<HttpResponse> {
|
||||
let sheet = get_sprite(&path, &sprites, true).await?;
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(ContentType::png())
|
||||
.body(sheet.encode_png().map_err(map_internal_error)?))
|
||||
@ -31,13 +42,31 @@ async fn get_sprite_json(
|
||||
path: Path<SourceIDsRequest>,
|
||||
sprites: Data<SpriteSources>,
|
||||
) -> ActixResult<HttpResponse> {
|
||||
let sheet = get_sprite(&path, &sprites).await?;
|
||||
let sheet = get_sprite(&path, &sprites, false).await?;
|
||||
Ok(HttpResponse::Ok().json(sheet.get_index()))
|
||||
}
|
||||
|
||||
async fn get_sprite(path: &SourceIDsRequest, sprites: &SpriteSources) -> ActixResult<Spritesheet> {
|
||||
#[route(
|
||||
"/sdf_sprite/{source_ids}.json",
|
||||
method = "GET",
|
||||
method = "HEAD",
|
||||
wrap = "middleware::Compress::default()"
|
||||
)]
|
||||
async fn get_sprite_sdf_json(
|
||||
path: Path<SourceIDsRequest>,
|
||||
sprites: Data<SpriteSources>,
|
||||
) -> ActixResult<HttpResponse> {
|
||||
let sheet = get_sprite(&path, &sprites, true).await?;
|
||||
Ok(HttpResponse::Ok().json(sheet.get_index()))
|
||||
}
|
||||
|
||||
async fn get_sprite(
|
||||
path: &SourceIDsRequest,
|
||||
sprites: &SpriteSources,
|
||||
as_sdf: bool,
|
||||
) -> ActixResult<Spritesheet> {
|
||||
sprites
|
||||
.get_sprites(&path.source_ids)
|
||||
.get_sprites(&path.source_ids, as_sdf)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
SpriteError::SpriteNotFound(_) => ErrorNotFound(e.to_string()),
|
||||
|
34
tests/expected/configured/sdf_spr_cmp.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 26,
|
||||
"y": 22,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 22,
|
||||
"pixelRatio": 1,
|
||||
"width": 22,
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 0,
|
||||
"y": 26,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 26,
|
||||
"pixelRatio": 1,
|
||||
"width": 26,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/expected/configured/sdf_spr_cmp.png
Normal file
After Width: | Height: | Size: 945 B |
1
tests/expected/configured/sdf_spr_cmp.png.txt
Normal file
@ -0,0 +1 @@
|
||||
tests/output/configured/sdf_spr_cmp.png: PNG image data, 48 x 47, 8-bit gray+alpha, non-interlaced
|
34
tests/expected/configured/sdf_spr_cmp_2.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 38,
|
||||
"pixelRatio": 2,
|
||||
"width": 38,
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 36,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 46,
|
||||
"pixelRatio": 2,
|
||||
"width": 46,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/expected/configured/sdf_spr_cmp_2.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
1
tests/expected/configured/sdf_spr_cmp_2.png.txt
Normal file
@ -0,0 +1 @@
|
||||
tests/output/configured/sdf_spr_cmp_2.png: PNG image data, 120 x 72, 8-bit gray+alpha, non-interlaced
|
10
tests/expected/configured/sdf_spr_mysrc.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/expected/configured/sdf_spr_mysrc.png
Normal file
After Width: | Height: | Size: 675 B |
1
tests/expected/configured/sdf_spr_mysrc.png.txt
Normal file
@ -0,0 +1 @@
|
||||
tests/output/configured/sdf_spr_mysrc.png: PNG image data, 36 x 36, 8-bit gray+alpha, non-interlaced
|
26
tests/expected/configured/sdf_spr_src1.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 26,
|
||||
"y": 22,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 22,
|
||||
"pixelRatio": 1,
|
||||
"width": 22,
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 26,
|
||||
"pixelRatio": 1,
|
||||
"width": 26,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/expected/configured/sdf_spr_src1.png
Normal file
After Width: | Height: | Size: 900 B |
1
tests/expected/configured/sdf_spr_src1.png.txt
Normal file
@ -0,0 +1 @@
|
||||
tests/output/configured/sdf_spr_src1.png: PNG image data, 48 x 43, 8-bit gray+alpha, non-interlaced
|
26
tests/expected/configured/sdf_spr_src1_.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 38,
|
||||
"pixelRatio": 2,
|
||||
"width": 38,
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 46,
|
||||
"pixelRatio": 2,
|
||||
"width": 46,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/expected/configured/sdf_spr_src1_.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
1
tests/expected/configured/sdf_spr_src1_.png.txt
Normal file
@ -0,0 +1 @@
|
||||
tests/output/configured/sdf_spr_src1_.png: PNG image data, 120 x 46, 8-bit gray+alpha, non-interlaced
|
34
tests/fixtures/sprites/expected/all_1_sdf.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 26,
|
||||
"y": 22,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 22,
|
||||
"pixelRatio": 1,
|
||||
"width": 22,
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 0,
|
||||
"y": 26,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 26,
|
||||
"pixelRatio": 1,
|
||||
"width": 26,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/all_1_sdf.png
vendored
Normal file
After Width: | Height: | Size: 945 B |
34
tests/fixtures/sprites/expected/all_2_sdf.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 38,
|
||||
"pixelRatio": 2,
|
||||
"width": 38,
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 36,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 46,
|
||||
"pixelRatio": 2,
|
||||
"width": 46,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/all_2_sdf.png
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
26
tests/fixtures/sprites/expected/src1_1_sdf.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 26,
|
||||
"y": 22,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 22,
|
||||
"pixelRatio": 1,
|
||||
"width": 22,
|
||||
"x": 26,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 26,
|
||||
"pixelRatio": 1,
|
||||
"width": 26,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/src1_1_sdf.png
vendored
Normal file
After Width: | Height: | Size: 900 B |
26
tests/fixtures/sprites/expected/src1_2_sdf.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"another_bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 84,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"bear": {
|
||||
"height": 38,
|
||||
"pixelRatio": 2,
|
||||
"width": 38,
|
||||
"x": 46,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
},
|
||||
"sub/circle": {
|
||||
"height": 46,
|
||||
"pixelRatio": 2,
|
||||
"width": 46,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/src1_2_sdf.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
10
tests/fixtures/sprites/expected/src2_1_sdf.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"bicycle": {
|
||||
"height": 21,
|
||||
"pixelRatio": 1,
|
||||
"width": 21,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/src2_1_sdf.png
vendored
Normal file
After Width: | Height: | Size: 377 B |
10
tests/fixtures/sprites/expected/src2_2_sdf.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"bicycle": {
|
||||
"height": 36,
|
||||
"pixelRatio": 2,
|
||||
"width": 36,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"sdf": true
|
||||
}
|
||||
}
|
BIN
tests/fixtures/sprites/expected/src2_2_sdf.png
vendored
Normal file
After Width: | Height: | Size: 675 B |
@ -351,18 +351,30 @@ test_png pmt_0_0_0 pmt/0/0/0
|
||||
test_png pmt2_0_0_0 pmt2/0/0/0 # HTTP pmtiles
|
||||
|
||||
# Test sprites
|
||||
test_jsn spr_src1 sprite/src1.json
|
||||
test_png spr_src1 sprite/src1.png
|
||||
test_jsn spr_src1_2x sprite/src1@2x.json
|
||||
test_png spr_src1_2x sprite/src1@2x.png
|
||||
test_jsn spr_mysrc sprite/mysrc.json
|
||||
test_png spr_mysrc sprite/mysrc.png
|
||||
test_jsn spr_mysrc_2x sprite/mysrc@2x.json
|
||||
test_png spr_mysrc_2x sprite/mysrc@2x.png
|
||||
test_jsn spr_cmp sprite/src1,mysrc.json
|
||||
test_png spr_cmp sprite/src1,mysrc.png
|
||||
test_jsn spr_cmp_2x sprite/src1,mysrc@2x.json
|
||||
test_png spr_cmp_2x sprite/src1,mysrc@2x.png
|
||||
test_jsn spr_src1 sprite/src1.json
|
||||
test_jsn sdf_spr_src1 sdf_sprite/src1.json
|
||||
test_png spr_src1 sprite/src1.png
|
||||
test_png sdf_spr_src1 sdf_sprite/src1.png
|
||||
test_jsn spr_src1_2x sprite/src1@2x.json
|
||||
test_jsn sdf_spr_src1_ sdf_sprite/src1@2x.json
|
||||
test_png spr_src1_2x sprite/src1@2x.png
|
||||
test_png sdf_spr_src1_ sdf_sprite/src1@2x.png
|
||||
test_jsn spr_mysrc sprite/mysrc.json
|
||||
test_jsn sdf_spr_mysrc sdf_sprite/mysrc.json
|
||||
test_png spr_mysrc sprite/mysrc.png
|
||||
test_png sdf_spr_mysrc sdf_sprite/mysrc.png
|
||||
test_jsn spr_mysrc_2x sprite/mysrc@2x.json
|
||||
test_jsn sdf_spr_mysrc sdf_sprite/mysrc@2x.json
|
||||
test_png spr_mysrc_2x sprite/mysrc@2x.png
|
||||
test_png sdf_spr_mysrc sdf_sprite/mysrc@2x.png
|
||||
test_jsn spr_cmp sprite/src1,mysrc.json
|
||||
test_jsn sdf_spr_cmp sdf_sprite/src1,mysrc.json
|
||||
test_png spr_cmp sprite/src1,mysrc.png
|
||||
test_png sdf_spr_cmp sdf_sprite/src1,mysrc.png
|
||||
test_jsn spr_cmp_2x sprite/src1,mysrc@2x.json
|
||||
test_jsn sdf_spr_cmp_2 sdf_sprite/src1,mysrc@2x.json
|
||||
test_png spr_cmp_2x sprite/src1,mysrc@2x.png
|
||||
test_png sdf_spr_cmp_2 sdf_sprite/src1,mysrc@2x.png
|
||||
|
||||
# Test fonts
|
||||
test_font font_1 font/Overpass%20Mono%20Light/0-255
|
||||
|