use super::brush_stroke::*;
use super::distance_field::*;
use super::sampled_contour::*;
use super::scaled_distance_field::*;
pub struct ScaledBrush<TDistanceField> {
distance_field: TDistanceField,
center_x: f64,
center_y: f64,
radius_scale: f64,
}
impl<TDistanceField> ScaledBrush<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
{
pub fn from_distance_field(distance_field: TDistanceField) -> Self {
let size = distance_field.field_size();
let ContourSize(width, height) = size;
let center_x = (width as f64) / 2.0;
let center_y = (height as f64) / 2.0;
let radius = width.max(height);
let radius_scale = 1.0 / (radius as f64);
ScaledBrush {
distance_field, center_x, center_y, radius_scale
}
}
}
impl<'a, TDistanceField> DaubBrush for &'a ScaledBrush<TDistanceField>
where
TDistanceField: SampledSignedDistanceField,
{
type DaubDistanceField = ScaledDistanceField<&'a TDistanceField>;
#[inline]
fn create_daub(&self, pos: impl crate::Coordinate + crate::Coordinate2D, radius: f64) -> Option<(Self::DaubDistanceField, ContourPosition)> {
if radius > 0.0 {
let scale = radius * self.radius_scale;
let x = pos.x() - (self.center_x * scale) - 1.0;
let y = pos.y() - (self.center_y * scale) - 1.0;
if x < 0.0 || y < 0.0 { return None; }
let offset_x = x - x.floor();
let offset_y = y - y.floor();
let distance_field = ScaledDistanceField::from_distance_field(&self.distance_field, scale, (offset_x, offset_y));
let position = ContourPosition(x.floor() as usize, y.floor() as usize);
Some((distance_field, position))
} else {
None
}
}
}