summaryrefslogtreecommitdiffstats
path: root/wgpu/src/geometry.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-19 20:41:52 +0100
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-19 20:41:52 +0100
commit1781068e1c3a65551db1e832fdbaddba99124051 (patch)
tree60e0b3854cc0541712572fbb0e56f14435951ea9 /wgpu/src/geometry.rs
parent41dec5bd203ff5b1574a33a17d5f7358ae1beea2 (diff)
parent7ae7fcb89855002519bab752fd3686106ce448db (diff)
downloadiced-1781068e1c3a65551db1e832fdbaddba99124051.tar.gz
iced-1781068e1c3a65551db1e832fdbaddba99124051.tar.bz2
iced-1781068e1c3a65551db1e832fdbaddba99124051.zip
Merge branch 'master' into remove-vertex-indexing
Diffstat (limited to 'wgpu/src/geometry.rs')
-rw-r--r--wgpu/src/geometry.rs154
1 files changed, 93 insertions, 61 deletions
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs
index 655362b7..4d7f443e 100644
--- a/wgpu/src/geometry.rs
+++ b/wgpu/src/geometry.rs
@@ -1,5 +1,6 @@
//! Build and draw geometry.
-use crate::core::{Point, Rectangle, Size, Vector};
+use crate::core::text::LineHeight;
+use crate::core::{Pixels, Point, Rectangle, Size, Vector};
use crate::graphics::color;
use crate::graphics::geometry::fill::{self, Fill};
use crate::graphics::geometry::{
@@ -115,19 +116,31 @@ struct Transforms {
}
#[derive(Debug, Clone, Copy)]
-struct Transform {
- raw: lyon::math::Transform,
- is_identity: bool,
-}
+struct Transform(lyon::math::Transform);
impl Transform {
- /// Transforms the given [Point] by the transformation matrix.
- fn transform_point(&self, point: &mut Point) {
+ fn is_identity(&self) -> bool {
+ self.0 == lyon::math::Transform::identity()
+ }
+
+ fn is_scale_translation(&self) -> bool {
+ self.0.m12.abs() < 2.0 * f32::EPSILON
+ && self.0.m21.abs() < 2.0 * f32::EPSILON
+ }
+
+ fn scale(&self) -> (f32, f32) {
+ (self.0.m11, self.0.m22)
+ }
+
+ fn transform_point(&self, point: Point) -> Point {
let transformed = self
- .raw
+ .0
.transform_point(euclid::Point2D::new(point.x, point.y));
- point.x = transformed.x;
- point.y = transformed.y;
+
+ Point {
+ x: transformed.x,
+ y: transformed.y,
+ }
}
fn transform_style(&self, style: Style) -> Style {
@@ -142,8 +155,8 @@ impl Transform {
fn transform_gradient(&self, mut gradient: Gradient) -> Gradient {
match &mut gradient {
Gradient::Linear(linear) => {
- self.transform_point(&mut linear.start);
- self.transform_point(&mut linear.end);
+ linear.start = self.transform_point(linear.start);
+ linear.end = self.transform_point(linear.end);
}
}
@@ -163,10 +176,7 @@ impl Frame {
primitives: Vec::new(),
transforms: Transforms {
previous: Vec::new(),
- current: Transform {
- raw: lyon::math::Transform::identity(),
- is_identity: true,
- },
+ current: Transform(lyon::math::Transform::identity()),
},
fill_tessellator: tessellation::FillTessellator::new(),
stroke_tessellator: tessellation::StrokeTessellator::new(),
@@ -209,14 +219,14 @@ impl Frame {
let options = tessellation::FillOptions::default()
.with_fill_rule(into_fill_rule(rule));
- if self.transforms.current.is_identity {
+ if self.transforms.current.is_identity() {
self.fill_tessellator.tessellate_path(
path.raw(),
&options,
buffer.as_mut(),
)
} else {
- let path = path.transform(&self.transforms.current.raw);
+ let path = path.transform(&self.transforms.current.0);
self.fill_tessellator.tessellate_path(
path.raw(),
@@ -241,13 +251,14 @@ impl Frame {
.buffers
.get_fill(&self.transforms.current.transform_style(style));
- let top_left =
- self.transforms.current.raw.transform_point(
- lyon::math::Point::new(top_left.x, top_left.y),
- );
+ let top_left = self
+ .transforms
+ .current
+ .0
+ .transform_point(lyon::math::Point::new(top_left.x, top_left.y));
let size =
- self.transforms.current.raw.transform_vector(
+ self.transforms.current.0.transform_vector(
lyon::math::Vector::new(size.width, size.height),
);
@@ -284,14 +295,14 @@ impl Frame {
Cow::Owned(dashed(path, stroke.line_dash))
};
- if self.transforms.current.is_identity {
+ if self.transforms.current.is_identity() {
self.stroke_tessellator.tessellate_path(
path.raw(),
&options,
buffer.as_mut(),
)
} else {
- let path = path.transform(&self.transforms.current.raw);
+ let path = path.transform(&self.transforms.current.0);
self.stroke_tessellator.tessellate_path(
path.raw(),
@@ -318,33 +329,57 @@ impl Frame {
pub fn fill_text(&mut self, text: impl Into<Text>) {
let text = text.into();
- let position = if self.transforms.current.is_identity {
- text.position
- } else {
- let transformed = self.transforms.current.raw.transform_point(
- lyon::math::Point::new(text.position.x, text.position.y),
- );
+ let (scale_x, scale_y) = self.transforms.current.scale();
+
+ if self.transforms.current.is_scale_translation()
+ && scale_x == scale_y
+ && scale_x > 0.0
+ && scale_y > 0.0
+ {
+ let (position, size, line_height) =
+ if self.transforms.current.is_identity() {
+ (text.position, text.size, text.line_height)
+ } else {
+ let position =
+ self.transforms.current.transform_point(text.position);
+
+ let size = Pixels(text.size.0 * scale_y);
+
+ let line_height = match text.line_height {
+ LineHeight::Absolute(size) => {
+ LineHeight::Absolute(Pixels(size.0 * scale_y))
+ }
+ LineHeight::Relative(factor) => {
+ LineHeight::Relative(factor)
+ }
+ };
- Point::new(transformed.x, transformed.y)
- };
+ (position, size, line_height)
+ };
- // TODO: Use vectorial text instead of primitive
- self.primitives.push(Primitive::Text {
- content: text.content,
- bounds: Rectangle {
+ let bounds = Rectangle {
x: position.x,
y: position.y,
width: f32::INFINITY,
height: f32::INFINITY,
- },
- color: text.color,
- size: text.size,
- line_height: text.line_height,
- font: text.font,
- horizontal_alignment: text.horizontal_alignment,
- vertical_alignment: text.vertical_alignment,
- shaping: text.shaping,
- });
+ };
+
+ // TODO: Honor layering!
+ self.primitives.push(Primitive::Text {
+ content: text.content,
+ bounds,
+ color: text.color,
+ size,
+ line_height,
+ font: text.font,
+ horizontal_alignment: text.horizontal_alignment,
+ vertical_alignment: text.vertical_alignment,
+ shaping: text.shaping,
+ clip_bounds: Rectangle::with_size(Size::INFINITY),
+ });
+ } else {
+ text.draw_with(|path, color| self.fill(&path, color));
+ }
}
/// Stores the current transform of the [`Frame`] and executes the given
@@ -420,26 +455,24 @@ impl Frame {
/// Applies a translation to the current transform of the [`Frame`].
#[inline]
pub fn translate(&mut self, translation: Vector) {
- self.transforms.current.raw = self
- .transforms
- .current
- .raw
- .pre_translate(lyon::math::Vector::new(
- translation.x,
- translation.y,
- ));
- self.transforms.current.is_identity = false;
+ self.transforms.current.0 =
+ self.transforms
+ .current
+ .0
+ .pre_translate(lyon::math::Vector::new(
+ translation.x,
+ translation.y,
+ ));
}
/// Applies a rotation in radians to the current transform of the [`Frame`].
#[inline]
pub fn rotate(&mut self, angle: f32) {
- self.transforms.current.raw = self
+ self.transforms.current.0 = self
.transforms
.current
- .raw
+ .0
.pre_rotate(lyon::math::Angle::radians(angle));
- self.transforms.current.is_identity = false;
}
/// Applies a uniform scaling to the current transform of the [`Frame`].
@@ -455,9 +488,8 @@ impl Frame {
pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
let scale = scale.into();
- self.transforms.current.raw =
- self.transforms.current.raw.pre_scale(scale.x, scale.y);
- self.transforms.current.is_identity = false;
+ self.transforms.current.0 =
+ self.transforms.current.0.pre_scale(scale.x, scale.y);
}
/// Produces the [`Primitive`] representing everything drawn on the [`Frame`].