Skip to content

Commit a3f710a

Browse files
committed
editoast: host fonts for the map in editoast
The glyphs are generated during the build step Closes #10627 Signed-off-by: Tristram Gräbener <tristram+git@tristramg.eu>
1 parent f1b10fb commit a3f710a

15 files changed

+106
-2
lines changed

editoast/.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
target
22
*.snap.new
3-
assets/sprites/*/sprites*
3+
assets/sprites/*/sprites.*
4+
assets/fonts/glyphs/*

editoast/Dockerfile

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ COPY --from=static_assets . /assets
2323
#######################
2424
# Build assets #
2525
#######################
26-
FROM alpine:latest AS editoast_assets
26+
FROM ubuntu:latest AS editoast_assets
27+
RUN apt update && apt install --yes wget
2728
RUN wget https://github.com/flother/spreet/releases/download/v0.11.0/spreet-x86_64-unknown-linux-musl.tar.gz
2829
RUN tar xvf spreet-x86_64-unknown-linux-musl.tar.gz --directory /usr/bin
30+
RUN wget http://github.com/stadiamaps/sdf_font_tools/releases/download/cli-v1.4.2/build_pbf_glyphs.x86_64-unknown-linux-gnu -O /usr/bin/build_pbf_glyphs
31+
RUN chmod +x /usr/bin/build_pbf_glyphs
2932
COPY ./assets /assets
3033
RUN /assets/sprites/generate-atlas.sh
34+
RUN /assets/fonts/generate-glyphs.sh
3135

3236
######################
3337
# Testing env: build #
@@ -44,6 +48,7 @@ ENV RUSTFLAGS="-Cinstrument-coverage -C target-feature=-crt-static -C link-arg=-
4448
ENV LLVM_PROFILE_FILE="editoast-%p-%m.profraw"
4549
RUN cargo chef cook --tests --recipe-path recipe.json
4650
COPY . .
51+
COPY --from=editoast_assets /assets /editoast/assets
4752

4853
#######################
4954
# Running env : build #

editoast/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ $ diesel migration run
2424
# build the assets
2525
$ cargo install spreet
2626
$ ./assets/sprites/generate-atlas.sh
27+
$ cargo install build_pbf_glyphs
28+
$ ./assets/fonts/generate-glyphs.sh
2729
# Build and run
2830
$ cargo build
2931
$ cargo run -- runserver

editoast/assets/fonts/Roboto Bold.ttf

160 KB
Binary file not shown.
Binary file not shown.
155 KB
Binary file not shown.
157 KB
Binary file not shown.
157 KB
Binary file not shown.
155 KB
Binary file not shown.

editoast/assets/fonts/SNCF.ttf

13.7 KB
Binary file not shown.
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
3+
# This script should be used to generate glyphs from ttf fonts.
4+
# Those glyphs are used to display text on the map
5+
# You will need build_pbf_glyphs, you can install it with:
6+
# `$ cargo install build_pbf_glyphs`
7+
set -e
8+
9+
fonts_directory=$(dirname "$(realpath "$0")")
10+
echo "Converting fonts in ${fonts_directory} to glyphs"
11+
build_pbf_glyphs "${fonts_directory}" "${fonts_directory}"/glyphs/

editoast/src/views/fonts.rs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use axum::extract::Path;
2+
use axum::extract::Request;
3+
use axum::response::IntoResponse;
4+
use editoast_derive::EditoastError;
5+
use thiserror::Error;
6+
use tower::ServiceExt;
7+
use tower_http::services::ServeFile;
8+
9+
use crate::client::get_dynamic_assets_path;
10+
use crate::error::Result;
11+
12+
crate::routes! {
13+
"/fonts/{font}/{glyph}" => fonts,
14+
}
15+
16+
#[derive(Debug, Error, EditoastError)]
17+
#[editoast_error(base_id = "fonts")]
18+
enum FontErrors {
19+
#[error("File '{file}' not found")]
20+
#[editoast_error(status = 404)]
21+
FileNotFound { file: String },
22+
}
23+
24+
/// This endpoint is used by map libre to retrieve the fonts. They are separated by font and unicode block
25+
#[utoipa::path(
26+
get, path = "",
27+
tag = "fonts",
28+
params(
29+
("font" = String, Path, description = "Requested font"),
30+
("glyph" = String, Path, description = "Requested unicode block"),
31+
),
32+
responses(
33+
(status = 200, description = "Glyphs in PBF format of the font at the requested unicode block"),
34+
(status = 404, description = "Font not found"),
35+
),
36+
)]
37+
async fn fonts(
38+
Path((font, file_name)): Path<(String, String)>,
39+
request: Request,
40+
) -> Result<impl IntoResponse> {
41+
let path = get_dynamic_assets_path().join(format!("fonts/glyphs/{font}/{file_name}"));
42+
43+
if !path.is_file() {
44+
return Err(FontErrors::FileNotFound { file: file_name }.into());
45+
}
46+
47+
Ok(ServeFile::new(&path).oneshot(request).await)
48+
}
49+
50+
#[cfg(test)]
51+
mod tests {
52+
use crate::views::test_app::TestAppBuilder;
53+
54+
use super::*;
55+
use axum::http::StatusCode;
56+
use rstest::rstest;
57+
58+
#[rstest]
59+
async fn test_font() {
60+
let app = TestAppBuilder::default_app();
61+
let request = app.get("/fonts/Roboto%20Bold/0-255.pbf");
62+
let response = app.fetch(request).assert_status(StatusCode::OK);
63+
assert_eq!("application/octet-stream", response.content_type());
64+
let response = response.bytes();
65+
let expected =
66+
std::fs::read(get_dynamic_assets_path().join("fonts/glyphs/Roboto Bold/0-255.pbf"))
67+
.unwrap();
68+
assert_eq!(response, expected);
69+
}
70+
71+
#[rstest]
72+
async fn test_font_not_found() {
73+
let app = TestAppBuilder::default_app();
74+
let request = app.get("/fonts/Comic%20Sans/0-255.pbf");
75+
app.fetch(request).assert_status(StatusCode::NOT_FOUND);
76+
}
77+
}

editoast/src/views/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod authz;
22
mod documents;
33
pub mod electrical_profiles;
4+
pub mod fonts;
45
pub mod infra;
56
mod layers;
67
mod openapi;
@@ -99,6 +100,7 @@ crate::routes! {
99100
&authz,
100101
&documents,
101102
&electrical_profiles,
103+
&fonts,
102104
&infra,
103105
&layers,
104106
&projects,

front/public/locales/en/errors.json

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
"electrical_profiles": {
6262
"NotFound": "Electrical Profile Set '{{electrical_profile_set_id}}', could not be found"
6363
},
64+
"fonts": {
65+
"FileNotFound": "File for the requested font not found"
66+
},
6467
"geometry": {
6568
"UnexpectedGeometry": "Expected geometry {{expected}} but got {{actual}}"
6669
},

front/public/locales/fr/errors.json

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
"electrical_profiles": {
6262
"NotFound": "Profil électrique '{{electrical_profile_set_id}}' non trouvé"
6363
},
64+
"fonts": {
65+
"FileNotFound": "Fichier pour la police de charactère demandée non trouvé"
66+
},
6467
"geometry": {
6568
"UnexpectedGeometry": "Géometrie {{expected}} attendue mais {{actual}} reçue"
6669
},

0 commit comments

Comments
 (0)