1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use image::DynamicImage;
use crate::bridge::ffi;
use crate::{ImageId, ImageRenderer, Layer, LayerId, Source, SourceId, StyleError};
/// A mutable reference to the renderer's current map style.
#[derive(Debug)]
pub struct StyleRef<'a, S> {
image_renderer: &'a mut ImageRenderer<S>,
}
impl<'a, S> StyleRef<'a, S> {
pub(crate) fn new(image_renderer: &'a mut ImageRenderer<S>) -> Self {
Self { image_renderer }
}
/// Adds an image to the style with the given ID and options.
///
/// Pass `true` for `signed_distance_field` to register the image as an SDF (signed
/// distance field) icon; pass `false` for a regular bitmap icon.
///
/// # Errors
///
/// Returns an error if MapLibre Native rejects the image.
pub fn add_image(
&mut self,
id: impl AsRef<str>,
image: &DynamicImage,
signed_distance_field: bool,
) -> Result<ImageId, StyleError> {
use image::EncodableLayout;
let id = id.as_ref();
let image = image.to_rgba8();
self.image_renderer.instance.pin_mut().style_add_image(
id,
image.as_bytes(),
ffi::Size { width: image.width(), height: image.height() },
signed_distance_field,
)?;
Ok(ImageId::new(id.to_owned()))
}
/// Removes an image from the style by ID.
///
/// No-op if `id` does not match an existing image.
pub fn remove_image(&mut self, id: impl AsRef<str>) {
self.image_renderer.instance.pin_mut().style_remove_image(id.as_ref());
}
/// Adds a source to the current map style and returns its stable source ID.
///
/// # Errors
///
/// Returns an error if MapLibre Native rejects the source.
pub fn add_source<T: Source>(&mut self, source: T) -> Result<SourceId, StyleError> {
let source_id = SourceId::new(source.source_id().to_owned());
self.image_renderer.instance.pin_mut().style_add_source(source.into_source())?;
Ok(source_id)
}
/// Adds a new layer and returns its stable layer ID.
///
/// # Errors
///
/// Returns an error if MapLibre Native rejects the layer.
pub fn add_layer<T: Layer>(&mut self, layer: T) -> Result<LayerId, StyleError> {
let layer_id = LayerId::new(layer.layer_id().to_owned());
self.add_layer_inner(layer.into_layer(), None)?;
Ok(layer_id)
}
/// Adds a new layer before an existing layer.
///
/// `before_layer` is the ID of an existing layer; the new layer is inserted
/// directly below it. If `before_layer` does not match any existing layer,
/// the new layer is appended to the end of the style.
///
/// # Errors
///
/// Returns an error if MapLibre Native rejects the layer.
pub fn add_layer_before<T: Layer>(
&mut self,
layer: T,
before_layer: impl AsRef<str>,
) -> Result<LayerId, StyleError> {
let layer_id = LayerId::new(layer.layer_id().to_owned());
self.add_layer_inner(layer.into_layer(), Some(before_layer.as_ref()))?;
Ok(layer_id)
}
fn add_layer_inner(
&mut self,
layer: cxx::UniquePtr<ffi::CxxLayer>,
before_id: Option<&str>,
) -> Result<(), StyleError> {
// The C++ bridge encodes "append" as an empty string; that detail is
// contained here so the public API can use separate append/before methods.
let before_id = before_id.unwrap_or_default();
self.image_renderer.instance.pin_mut().style_add_layer(layer, before_id)?;
Ok(())
}
/// Removes a layer from the current map style by ID.
///
/// No-op if `layer_id` does not match an existing layer.
pub fn remove_layer(&mut self, layer_id: impl AsRef<str>) {
self.image_renderer.instance.pin_mut().style_remove_layer(layer_id.as_ref());
}
/// Removes a source from the current map style by ID.
///
/// No-op if `source_id` does not match an existing source.
pub fn remove_source(&mut self, source_id: impl AsRef<str>) {
self.image_renderer.instance.pin_mut().style_remove_source(source_id.as_ref());
}
}