summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/src/backend.rs48
-rw-r--r--tiny_skia/src/geometry.rs131
-rw-r--r--tiny_skia/src/primitive.rs4
-rw-r--r--tiny_skia/src/text.rs43
4 files changed, 155 insertions, 71 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index 3e9bd2a5..d1393b4d 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -1,5 +1,6 @@
use crate::core::{Background, Color, Gradient, Rectangle, Vector};
use crate::graphics::backend;
+use crate::graphics::text;
use crate::graphics::Viewport;
use crate::primitive::{self, Primitive};
@@ -444,6 +445,35 @@ impl Backend {
clip_mask,
);
}
+ Primitive::RawText(text::Raw {
+ buffer,
+ position,
+ color,
+ clip_bounds: text_clip_bounds,
+ }) => {
+ let Some(buffer) = buffer.upgrade() else {
+ return;
+ };
+
+ let physical_bounds =
+ (*text_clip_bounds + translation) * scale_factor;
+
+ if !clip_bounds.intersects(&physical_bounds) {
+ return;
+ }
+
+ let clip_mask = (!physical_bounds.is_within(&clip_bounds))
+ .then_some(clip_mask as &_);
+
+ self.text_pipeline.draw_raw(
+ &buffer,
+ *position + translation,
+ *color,
+ scale_factor,
+ pixels,
+ clip_mask,
+ );
+ }
#[cfg(feature = "image")]
Primitive::Image {
handle,
@@ -513,7 +543,6 @@ impl Backend {
path,
paint,
rule,
- transform,
}) => {
let bounds = path.bounds();
@@ -536,9 +565,11 @@ impl Backend {
path,
paint,
*rule,
- transform
- .post_translate(translation.x, translation.y)
- .post_scale(scale_factor, scale_factor),
+ tiny_skia::Transform::from_translate(
+ translation.x,
+ translation.y,
+ )
+ .post_scale(scale_factor, scale_factor),
clip_mask,
);
}
@@ -546,7 +577,6 @@ impl Backend {
path,
paint,
stroke,
- transform,
}) => {
let bounds = path.bounds();
@@ -569,9 +599,11 @@ impl Backend {
path,
paint,
stroke,
- transform
- .post_translate(translation.x, translation.y)
- .post_scale(scale_factor, scale_factor),
+ tiny_skia::Transform::from_translate(
+ translation.x,
+ translation.y,
+ )
+ .post_scale(scale_factor, scale_factor),
clip_mask,
);
}
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index 5f28b737..74a08d38 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -1,4 +1,5 @@
-use crate::core::{Point, Rectangle, Size, Vector};
+use crate::core::text::LineHeight;
+use crate::core::{Pixels, Point, Rectangle, Size, Vector};
use crate::graphics::geometry::fill::{self, Fill};
use crate::graphics::geometry::stroke::{self, Stroke};
use crate::graphics::geometry::{Path, Style, Text};
@@ -39,17 +40,22 @@ impl Frame {
}
pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) {
- let Some(path) = convert_path(path) else {
+ let Some(path) =
+ convert_path(path).and_then(|path| path.transform(self.transform))
+ else {
return;
};
+
let fill = fill.into();
+ let mut paint = into_paint(fill.style);
+ paint.shader.transform(self.transform);
+
self.primitives
.push(Primitive::Custom(primitive::Custom::Fill {
path,
- paint: into_paint(fill.style),
+ paint,
rule: into_fill_rule(fill.rule),
- transform: self.transform,
}));
}
@@ -59,76 +65,111 @@ impl Frame {
size: Size,
fill: impl Into<Fill>,
) {
- let Some(path) = convert_path(&Path::rectangle(top_left, size)) else {
+ let Some(path) = convert_path(&Path::rectangle(top_left, size))
+ .and_then(|path| path.transform(self.transform))
+ else {
return;
};
+
let fill = fill.into();
+ let mut paint = tiny_skia::Paint {
+ anti_alias: false,
+ ..into_paint(fill.style)
+ };
+ paint.shader.transform(self.transform);
+
self.primitives
.push(Primitive::Custom(primitive::Custom::Fill {
path,
- paint: tiny_skia::Paint {
- anti_alias: false,
- ..into_paint(fill.style)
- },
+ paint,
rule: into_fill_rule(fill.rule),
- transform: self.transform,
}));
}
pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
- let Some(path) = convert_path(path) else {
+ let Some(path) =
+ convert_path(path).and_then(|path| path.transform(self.transform))
+ else {
return;
};
let stroke = stroke.into();
let skia_stroke = into_stroke(&stroke);
+ let mut paint = into_paint(stroke.style);
+ paint.shader.transform(self.transform);
+
self.primitives
.push(Primitive::Custom(primitive::Custom::Stroke {
path,
- paint: into_paint(stroke.style),
+ paint,
stroke: skia_stroke,
- transform: self.transform,
}));
}
pub fn fill_text(&mut self, text: impl Into<Text>) {
let text = text.into();
- let position = if self.transform.is_identity() {
- text.position
+ let (scale_x, scale_y) = self.transform.get_scale();
+
+ if self.transform.is_scale_translate()
+ && scale_x == scale_y
+ && scale_x > 0.0
+ && scale_y > 0.0
+ {
+ let (position, size, line_height) = if self.transform.is_identity()
+ {
+ (text.position, text.size, text.line_height)
+ } else {
+ let mut position = [tiny_skia::Point {
+ x: text.position.x,
+ y: text.position.y,
+ }];
+
+ self.transform.map_points(&mut position);
+
+ let size = 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(position[0].x, position[0].y),
+ size.into(),
+ line_height,
+ )
+ };
+
+ let bounds = Rectangle {
+ x: position.x,
+ y: position.y,
+ width: f32::INFINITY,
+ height: f32::INFINITY,
+ };
+
+ // 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 {
- let mut transformed = [tiny_skia::Point {
- x: text.position.x,
- y: text.position.y,
- }];
-
- self.transform.map_points(&mut transformed);
-
- Point::new(transformed[0].x, transformed[0].y)
- };
-
- let bounds = Rectangle {
- x: position.x,
- y: position.y,
- width: f32::INFINITY,
- height: f32::INFINITY,
- };
-
- // TODO: Use vectorial text instead of primitive
- self.primitives.push(Primitive::Text {
- content: text.content,
- bounds,
- 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,
- clip_bounds: Rectangle::with_size(Size::INFINITY),
- });
+ text.draw_with(|path, color| self.fill(&path, color));
+ }
}
pub fn push_transform(&mut self) {
diff --git a/tiny_skia/src/primitive.rs b/tiny_skia/src/primitive.rs
index 0ed24969..7718d542 100644
--- a/tiny_skia/src/primitive.rs
+++ b/tiny_skia/src/primitive.rs
@@ -13,8 +13,6 @@ pub enum Custom {
paint: tiny_skia::Paint<'static>,
/// The fill rule to follow.
rule: tiny_skia::FillRule,
- /// The transform to apply to the path.
- transform: tiny_skia::Transform,
},
/// A path stroked with some paint.
Stroke {
@@ -24,8 +22,6 @@ pub enum Custom {
paint: tiny_skia::Paint<'static>,
/// The stroke settings.
stroke: tiny_skia::Stroke,
- /// The transform to apply to the path.
- transform: tiny_skia::Transform,
},
}
diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs
index 70e95d01..9413e311 100644
--- a/tiny_skia/src/text.rs
+++ b/tiny_skia/src/text.rs
@@ -1,7 +1,6 @@
use crate::core::alignment;
use crate::core::text::{LineHeight, Shaping};
-use crate::core::{Color, Font, Pixels, Point, Rectangle};
-use crate::graphics::color;
+use crate::core::{Color, Font, Pixels, Point, Rectangle, Size};
use crate::graphics::text::cache::{self, Cache};
use crate::graphics::text::editor;
use crate::graphics::text::font_system;
@@ -149,6 +148,33 @@ impl Pipeline {
);
}
+ pub fn draw_raw(
+ &mut self,
+ buffer: &cosmic_text::Buffer,
+ position: Point,
+ color: Color,
+ scale_factor: f32,
+ pixels: &mut tiny_skia::PixmapMut<'_>,
+ clip_mask: Option<&tiny_skia::Mask>,
+ ) {
+ let mut font_system = font_system().write().expect("Write font system");
+
+ let (width, height) = buffer.size();
+
+ draw(
+ font_system.raw(),
+ &mut self.glyph_cache,
+ buffer,
+ Rectangle::new(position, Size::new(width, height)),
+ color,
+ alignment::Horizontal::Left,
+ alignment::Vertical::Top,
+ scale_factor,
+ pixels,
+ clip_mask,
+ );
+ }
+
pub fn trim_cache(&mut self) {
self.cache.get_mut().trim();
self.glyph_cache.trim();
@@ -217,18 +243,7 @@ fn draw(
fn from_color(color: cosmic_text::Color) -> Color {
let [r, g, b, a] = color.as_rgba();
- if color::GAMMA_CORRECTION {
- // `cosmic_text::Color` is linear RGB in this case, so we
- // need to convert back to sRGB
- Color::from_linear_rgba(
- r as f32 / 255.0,
- g as f32 / 255.0,
- b as f32 / 255.0,
- a as f32 / 255.0,
- )
- } else {
- Color::from_rgba8(r, g, b, a as f32 / 255.0)
- }
+ Color::from_rgba8(r, g, b, a as f32 / 255.0)
}
#[derive(Debug, Clone, Default)]