use super::mark::{Context, Drawing, GEOMETRY, MarkKind, Style, mark, style_methods};
use crate::expr::compile::{Compiler, Store};
use crate::gpu::shaders as wgsl;
use crate::{Error, Kind, Name, Result};
mark!(
Areas {
geometry: Option<Name>,
});
impl Areas {
pub fn of(data: impl Into<Name>, table: impl Into<Name>) -> Areas {
Areas { style: Style::new(data.into(), table.into()), geometry: None }
}
#[must_use]
pub fn geometry(mut self, field: impl Into<Name>) -> Areas {
self.geometry = Some(field.into());
self
}
pub(crate) fn field(&self) -> Name {
self.geometry.clone().unwrap_or_else(|| GEOMETRY.into())
}
pub(crate) fn compile(&self, c: &mut Compiler<'_>, _: Context<'_>) -> Result<Drawing> {
let field = self.field();
match c.kind(&field) {
Some(Kind::Parts | Kind::Polygons) => {}
Some(_) => return Err(Error::invalid("not a polygon field").at(&field).at("geometry")),
None if self.geometry.is_some() => return Err(Error::invalid("no such field").at(&field).at("geometry")),
None => return Err(Error::invalid("name the polygon field each row fills").at("geometry")),
}
let color = Store::Color { word: wgsl::AREA_COLOR, fallback: wgsl::THEME_AREA };
match &self.style.color {
Some(expr) => c.channel("color", expr, color)?,
None => c.theme("color", wgsl::THEME_AREA, color)?,
}
c.channel("visible", &self.style.visible, Store::Flag { word: wgsl::AREA_FLAGS, bit: wgsl::VISIBLE })?;
let mut drawing = Drawing::new(MarkKind::Areas, wgsl::AREA_WORDS);
drawing.geometry = c.derived_path(&triangles_of(&field));
Ok(drawing)
}
}
pub(crate) fn triangles_of(field: &str) -> Name {
format!("{field}.triangles").into()
}
style_methods!(Areas);