Make Paint not implement Copy

This commit is contained in:
Laurenz 2023-03-31 16:31:21 +02:00
parent 00f11ae56d
commit 5f97e0a773
17 changed files with 103 additions and 74 deletions

View File

@ -383,7 +383,13 @@ impl Layout for BlockElem {
let outset = self.outset(styles);
let radius = self.radius(styles);
for frame in frames.iter_mut().skip(skip as usize) {
frame.fill_and_stroke(fill, stroke, outset, radius, self.span());
frame.fill_and_stroke(
fill.clone(),
stroke.clone(),
outset,
radius,
self.span(),
);
}
}

View File

@ -362,8 +362,8 @@ impl PageElem {
}
}
if let Some(fill) = fill {
frame.fill(fill);
if let Some(fill) = &fill {
frame.fill(fill.clone());
}
}

View File

@ -167,14 +167,14 @@ impl Layout for TableElem {
// Add lines and backgrounds.
for (frame, rows) in layout.fragment.iter_mut().zip(&layout.rows) {
// Render table lines.
if let Some(stroke) = stroke {
if let Some(stroke) = &stroke {
let thickness = stroke.thickness;
let half = thickness / 2.0;
// Render horizontal lines.
for offset in points(rows.iter().map(|piece| piece.height)) {
let target = Point::with_x(frame.width() + thickness);
let hline = Geometry::Line(target).stroked(stroke);
let hline = Geometry::Line(target).stroked(stroke.clone());
frame.prepend(
Point::new(-half, offset),
FrameItem::Shape(hline, self.span()),
@ -184,7 +184,7 @@ impl Layout for TableElem {
// Render vertical lines.
for offset in points(layout.cols.iter().copied()) {
let target = Point::with_y(frame.height() + thickness);
let vline = Geometry::Line(target).stroked(stroke);
let vline = Geometry::Line(target).stroked(stroke.clone());
frame.prepend(
Point::new(offset, -half),
FrameItem::Shape(vline, self.span()),

View File

@ -201,20 +201,20 @@ impl GlyphFragment {
self.ascent + self.descent
}
pub fn to_variant(&self) -> VariantFragment {
pub fn to_variant(self) -> VariantFragment {
VariantFragment {
c: self.c,
id: Some(self.id),
frame: self.to_frame(),
style: self.style,
font_size: self.font_size,
italics_correction: self.italics_correction,
class: self.class,
span: self.span,
frame: self.to_frame(),
}
}
pub fn to_frame(&self) -> Frame {
pub fn to_frame(self) -> Frame {
let item = TextItem {
font: self.font.clone(),
size: self.font_size,

View File

@ -268,8 +268,8 @@ pub(super) fn decorate(
};
let offset = deco.offset.unwrap_or(-metrics.position.at(text.size)) - shift;
let stroke = deco.stroke.unwrap_or(Stroke {
paint: text.fill,
let stroke = deco.stroke.clone().unwrap_or(Stroke {
paint: text.fill.clone(),
thickness: metrics.thickness.at(text.size),
});
@ -284,7 +284,7 @@ pub(super) fn decorate(
let target = Point::new(to - from, Abs::zero());
if target.x >= min_width || !deco.evade {
let shape = Geometry::Line(target).stroked(stroke);
let shape = Geometry::Line(target).stroked(stroke.clone());
frame.push(origin, FrameItem::Shape(shape, Span::detached()));
}
};

View File

@ -134,8 +134,7 @@ impl Show for RawElem {
.settings
.foreground
.map(to_typst)
.map_or(Color::BLACK, Color::from)
.into();
.map_or(Color::BLACK, Color::from);
let mut realized = if matches!(lang.as_deref(), Some("typ" | "typst" | "typc")) {
let root = match lang.as_deref() {
@ -150,7 +149,7 @@ impl Show for RawElem {
vec![],
&highlighter,
&mut |node, style| {
seq.push(styled(&text[node.range()], foreground, style));
seq.push(styled(&text[node.range()], foreground.into(), style));
},
);
@ -168,7 +167,7 @@ impl Show for RawElem {
for (style, piece) in
highlighter.highlight_line(line, &SYNTAXES).into_iter().flatten()
{
seq.push(styled(piece, foreground, style));
seq.push(styled(piece, foreground.into(), style));
}
}

View File

@ -122,7 +122,14 @@ impl<'a> ShapedText<'a> {
})
.collect();
let item = TextItem { font, size: self.size, lang, fill, glyphs };
let item = TextItem {
font,
size: self.size,
lang,
fill: fill.clone(),
glyphs,
};
let layer = frame.layer();
let width = item.width();

View File

@ -215,8 +215,8 @@ impl PageContext<'_, '_> {
}
}
fn set_fill(&mut self, fill: Paint) {
if self.state.fill != Some(fill) {
fn set_fill(&mut self, fill: &Paint) {
if self.state.fill.as_ref() != Some(fill) {
let f = |c| c as f32 / 255.0;
let Paint::Solid(color) = fill;
match color {
@ -233,7 +233,7 @@ impl PageContext<'_, '_> {
self.content.set_fill_cmyk(f(c.c), f(c.m), f(c.y), f(c.k));
}
}
self.state.fill = Some(fill);
self.state.fill = Some(fill.clone());
}
}
@ -248,8 +248,8 @@ impl PageContext<'_, '_> {
self.state.fill_space = None;
}
fn set_stroke(&mut self, stroke: Stroke) {
if self.state.stroke != Some(stroke) {
fn set_stroke(&mut self, stroke: &Stroke) {
if self.state.stroke.as_ref() != Some(stroke) {
let f = |c| c as f32 / 255.0;
let Paint::Solid(color) = stroke.paint;
match color {
@ -268,7 +268,7 @@ impl PageContext<'_, '_> {
}
self.content.set_line_width(stroke.thickness.to_f32());
self.state.stroke = Some(stroke);
self.state.stroke = Some(stroke.clone());
}
}
@ -335,7 +335,7 @@ fn write_text(ctx: &mut PageContext, x: f32, y: f32, text: &TextItem) {
.or_default()
.extend(text.glyphs.iter().map(|g| g.id));
ctx.set_fill(text.fill);
ctx.set_fill(&text.fill);
ctx.set_font(&text.font, text.size);
ctx.content.begin_text();
@ -386,11 +386,11 @@ fn write_shape(ctx: &mut PageContext, x: f32, y: f32, shape: &Shape) {
return;
}
if let Some(fill) = shape.fill {
if let Some(fill) = &shape.fill {
ctx.set_fill(fill);
}
if let Some(stroke) = shape.stroke {
if let Some(stroke) = &shape.stroke {
ctx.set_stroke(stroke);
}
@ -413,7 +413,7 @@ fn write_shape(ctx: &mut PageContext, x: f32, y: f32, shape: &Shape) {
}
}
match (shape.fill, shape.stroke) {
match (&shape.fill, &shape.stroke) {
(None, None) => unreachable!(),
(Some(_), None) => ctx.content.fill_nonzero(),
(None, Some(_)) => ctx.content.stroke(),

View File

@ -223,7 +223,7 @@ fn render_outline_glyph(
builder.0.finish()?
};
let paint = text.fill.into();
let paint = (&text.fill).into();
let rule = sk::FillRule::default();
// Flip vertically because font design coordinate
@ -302,7 +302,7 @@ fn render_shape(
Geometry::Path(ref path) => convert_path(path)?,
};
if let Some(fill) = shape.fill {
if let Some(fill) = &shape.fill {
let mut paint: sk::Paint = fill.into();
if matches!(shape.geometry, Geometry::Rect(_)) {
paint.anti_alias = false;
@ -312,7 +312,7 @@ fn render_shape(
canvas.fill_path(&path, &paint, rule, ts, mask);
}
if let Some(Stroke { paint, thickness }) = shape.stroke {
if let Some(Stroke { paint, thickness }) = &shape.stroke {
let paint = paint.into();
let stroke = sk::Stroke { width: thickness.to_f32(), ..Default::default() };
canvas.stroke_path(&path, &paint, &stroke, ts, mask);
@ -428,10 +428,10 @@ impl From<Transform> for sk::Transform {
}
}
impl From<Paint> for sk::Paint<'static> {
fn from(paint: Paint) -> Self {
impl From<&Paint> for sk::Paint<'static> {
fn from(paint: &Paint) -> Self {
let mut sk_paint = sk::Paint::default();
let Paint::Solid(color) = paint;
let Paint::Solid(color) = *paint;
sk_paint.set_color(color.into());
sk_paint.anti_alias = true;
sk_paint

View File

@ -120,10 +120,10 @@ impl<T: Ord> Axes<T> {
impl<T> Get<Axis> for Axes<T> {
type Component = T;
fn get(self, axis: Axis) -> T {
fn get_ref(&self, axis: Axis) -> &T {
match axis {
Axis::X => self.x,
Axis::Y => self.y,
Axis::X => &self.x,
Axis::Y => &self.y,
}
}

View File

@ -76,12 +76,12 @@ impl<T> Corners<T> {
impl<T> Get<Corner> for Corners<T> {
type Component = T;
fn get(self, corner: Corner) -> T {
fn get_ref(&self, corner: Corner) -> &T {
match corner {
Corner::TopLeft => self.top_left,
Corner::TopRight => self.top_right,
Corner::BottomRight => self.bottom_right,
Corner::BottomLeft => self.bottom_left,
Corner::TopLeft => &self.top_left,
Corner::TopRight => &self.top_right,
Corner::BottomRight => &self.bottom_right,
Corner::BottomLeft => &self.bottom_left,
}
}
@ -110,7 +110,7 @@ pub enum Corner {
impl<T> Cast for Corners<Option<T>>
where
T: Cast + Copy,
T: Cast + Clone,
{
fn is(value: &Value) -> bool {
matches!(value, Value::Dict(_)) || T::is(value)
@ -121,15 +121,23 @@ where
let mut take = |key| dict.take(key).ok().map(T::cast).transpose();
let rest = take("rest")?;
let left = take("left")?.or(rest);
let top = take("top")?.or(rest);
let right = take("right")?.or(rest);
let bottom = take("bottom")?.or(rest);
let left = take("left")?.or_else(|| rest.clone());
let top = take("top")?.or_else(|| rest.clone());
let right = take("right")?.or_else(|| rest.clone());
let bottom = take("bottom")?.or_else(|| rest.clone());
let corners = Corners {
top_left: take("top-left")?.or(top).or(left),
top_right: take("top-right")?.or(top).or(right),
bottom_right: take("bottom-right")?.or(bottom).or(right),
bottom_left: take("bottom-left")?.or(bottom).or(left),
top_left: take("top-left")?
.or_else(|| top.clone())
.or_else(|| left.clone()),
top_right: take("top-right")?
.or_else(|| top.clone())
.or_else(|| right.clone()),
bottom_right: take("bottom-right")?
.or_else(|| bottom.clone())
.or_else(|| right.clone()),
bottom_left: take("bottom-left")?
.or_else(|| bottom.clone())
.or_else(|| left.clone()),
};
dict.finish(&[

View File

@ -66,12 +66,21 @@ pub trait Get<Index> {
/// The structure's component type.
type Component;
/// Return the component for the specified index.
fn get(self, index: Index) -> Self::Component;
/// Borrow the component for the specified index.
fn get_ref(&self, index: Index) -> &Self::Component;
/// Borrow the component for the specified index mutably.
fn get_mut(&mut self, index: Index) -> &mut Self::Component;
/// Convenience method for getting a copy of a component.
fn get(self, index: Index) -> Self::Component
where
Self: Sized,
Self::Component: Copy,
{
*self.get_ref(index)
}
/// Convenience method for setting a component.
fn set(&mut self, index: Index, component: Self::Component) {
*self.get_mut(index) = component;

View File

@ -3,7 +3,7 @@ use std::str::FromStr;
use super::*;
/// How a fill or stroke should be painted.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Clone, Eq, PartialEq, Hash)]
pub enum Paint {
/// A solid color.
Solid(Color),

View File

@ -72,10 +72,10 @@ impl Numeric for Point {
impl Get<Axis> for Point {
type Component = Abs;
fn get(self, axis: Axis) -> Abs {
fn get_ref(&self, axis: Axis) -> &Abs {
match axis {
Axis::X => self.x,
Axis::Y => self.y,
Axis::X => &self.x,
Axis::Y => &self.y,
}
}

View File

@ -14,7 +14,7 @@ pub fn rounded_rect(
res.push(Shape {
geometry: fill_geometry(size, radius),
fill,
stroke: if stroke.is_uniform() { stroke.top } else { None },
stroke: if stroke.is_uniform() { stroke.top.clone() } else { None },
});
}
@ -55,7 +55,7 @@ fn stroke_segments(
let max_radius = size.x.min(size.y) / 2.0;
for side in [Side::Top, Side::Right, Side::Bottom, Side::Left] {
let continuous = stroke.get(side) == stroke.get(side.next_cw());
let continuous = stroke.get_ref(side) == stroke.get_ref(side.next_cw());
connection = connection.advance(continuous && side != Side::Left);
always_continuous &= continuous;
@ -69,7 +69,7 @@ fn stroke_segments(
);
if !continuous {
res.push((mem::take(&mut path), stroke.get(side)));
res.push((mem::take(&mut path), stroke.get_ref(side).clone()));
}
}

View File

@ -91,12 +91,12 @@ impl Sides<Rel<Abs>> {
impl<T> Get<Side> for Sides<T> {
type Component = T;
fn get(self, side: Side) -> T {
fn get_ref(&self, side: Side) -> &T {
match side {
Side::Left => self.left,
Side::Top => self.top,
Side::Right => self.right,
Side::Bottom => self.bottom,
Side::Left => &self.left,
Side::Top => &self.top,
Side::Right => &self.right,
Side::Bottom => &self.bottom,
}
}
@ -180,7 +180,7 @@ impl Side {
impl<T> Cast for Sides<Option<T>>
where
T: Default + Cast + Copy,
T: Default + Cast + Clone,
{
fn is(value: &Value) -> bool {
matches!(value, Value::Dict(_)) || T::is(value)
@ -191,13 +191,13 @@ where
let mut take = |key| dict.take(key).ok().map(T::cast).transpose();
let rest = take("rest")?;
let x = take("x")?.or(rest);
let y = take("y")?.or(rest);
let x = take("x")?.or_else(|| rest.clone());
let y = take("y")?.or_else(|| rest.clone());
let sides = Sides {
left: take("left")?.or(x),
top: take("top")?.or(y),
right: take("right")?.or(x),
bottom: take("bottom")?.or(y),
left: take("left")?.or_else(|| x.clone()),
top: take("top")?.or_else(|| y.clone()),
right: take("right")?.or_else(|| x.clone()),
bottom: take("bottom")?.or_else(|| y.clone()),
};
dict.finish(&["left", "top", "right", "bottom", "x", "y", "rest"])?;

View File

@ -1,7 +1,7 @@
use super::*;
/// A stroke of a geometric shape.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Stroke {
/// The stroke's paint.
pub paint: Paint,
@ -23,7 +23,7 @@ impl Default for Stroke {
/// In this representation, both fields are optional so that you can pass either
/// just a paint (`red`), just a thickness (`0.1em`) or both (`2pt + red`) where
/// this is expected.
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct PartialStroke<T = Length> {
/// The stroke's paint.
pub paint: Smart<Paint>,
@ -48,7 +48,7 @@ impl PartialStroke<Abs> {
impl<T: Debug> Debug for PartialStroke<T> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match (self.paint, &self.thickness) {
match (&self.paint, &self.thickness) {
(Smart::Custom(paint), Smart::Custom(thickness)) => {
write!(f, "{thickness:?} + {paint:?}")
}