[librsvg: 1/3] (#618) Implement context-fill and context-stroke
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/3] (#618) Implement context-fill and context-stroke
- Date: Mon, 28 Jun 2021 19:18:19 +0000 (UTC)
commit 1c1125829cde019804b85e6f39cbf37339e6eeaf
Author: Madds H <madds hollandart io>
Date: Fri Jun 25 16:59:00 2021 -0500
(#618) Implement context-fill and context-stroke
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/556>
src/drawing_ctx.rs | 14 ++++++++++++--
src/layout.rs | 12 +++++++++---
src/marker.rs | 26 +++++++++++++++++---------
src/node.rs | 16 ++++++++++++++++
src/paint_server.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++
src/shapes.rs | 41 +++++++++++++++++++++++++++++++----------
src/text.rs | 2 ++
7 files changed, 132 insertions(+), 24 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 573d33ce..5ea9e9a9 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -752,7 +752,12 @@ impl DrawingCtx {
values
.stroke()
.0
- .resolve(acquired_nodes, values.stroke_opacity().0, current_color)
+ .resolve(
+ acquired_nodes,
+ values.stroke_opacity().0,
+ current_color,
+ None,
+ )
.to_user_space(&bbox, ¶ms, values),
);
@@ -760,7 +765,12 @@ impl DrawingCtx {
values
.fill()
.0
- .resolve(acquired_nodes, values.fill_opacity().0, current_color)
+ .resolve(
+ acquired_nodes,
+ values.fill_opacity().0,
+ current_color,
+ None,
+ )
.to_user_space(&bbox, ¶ms, values),
);
diff --git a/src/layout.rs b/src/layout.rs
index 8d8088bc..189f0e00 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -73,9 +73,15 @@ pub struct Shape {
pub fill_rule: FillRule,
pub clip_rule: ClipRule,
pub shape_rendering: ShapeRendering,
- pub marker_start: Option<Node>,
- pub marker_mid: Option<Node>,
- pub marker_end: Option<Node>,
+ pub marker_start: Marker,
+ pub marker_mid: Marker,
+ pub marker_end: Marker,
+}
+
+pub struct Marker {
+ pub node_ref: Option<Node>,
+ pub context_stroke: PaintSource,
+ pub context_fill: PaintSource,
}
/// Image in user-space coordinates.
diff --git a/src/marker.rs b/src/marker.rs
index e06ff413..a27dad80 100644
--- a/src/marker.rs
+++ b/src/marker.rs
@@ -14,7 +14,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
-use crate::layout::{Shape, StackingContext};
+use crate::layout::{self, Shape, StackingContext};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
use crate::parsers::{Parse, ParseValue};
@@ -112,8 +112,12 @@ impl Marker {
line_width: f64,
clipping: bool,
marker_type: MarkerType,
+ marker: &layout::Marker,
) -> Result<BoundingBox, RenderingError> {
- let cascaded = CascadedValues::new_from_node(&node);
+ let mut cascaded = CascadedValues::new_from_node(&node);
+ cascaded.context_fill = Some(marker.context_fill.clone());
+ cascaded.context_stroke = Some(marker.context_stroke.clone());
+
let values = cascaded.get();
let view_params = draw_ctx.get_view_params();
@@ -569,7 +573,7 @@ enum MarkerType {
fn emit_marker_by_node(
draw_ctx: &mut DrawingCtx,
acquired_nodes: &mut AcquiredNodes<'_>,
- marker_node: &Node,
+ marker: &layout::Marker,
xpos: f64,
ypos: f64,
computed_angle: Angle,
@@ -577,13 +581,13 @@ fn emit_marker_by_node(
clipping: bool,
marker_type: MarkerType,
) -> Result<BoundingBox, RenderingError> {
- match acquired_nodes.acquire_ref(marker_node) {
+ match acquired_nodes.acquire_ref(marker.node_ref.as_ref().unwrap()) {
Ok(acquired) => {
let node = acquired.get();
- let marker = borrow_element_as!(marker_node, Marker);
+ let marker_elt = borrow_element_as!(node, Marker);
- marker.render(
+ marker_elt.render(
&node,
acquired_nodes,
draw_ctx,
@@ -593,6 +597,7 @@ fn emit_marker_by_node(
line_width,
clipping,
marker_type,
+ marker,
)
}
@@ -641,7 +646,10 @@ pub fn render_markers_for_shape(
return Ok(draw_ctx.empty_bbox());
}
- if shape.marker_start.is_none() && shape.marker_mid.is_none() && shape.marker_end.is_none() {
+ if shape.marker_start.node_ref.is_none()
+ && shape.marker_mid.node_ref.is_none()
+ && shape.marker_end.node_ref.is_none()
+ {
return Ok(draw_ctx.empty_bbox());
}
@@ -649,13 +657,13 @@ pub fn render_markers_for_shape(
&shape.path,
draw_ctx.empty_bbox(),
&mut |marker_type: MarkerType, x: f64, y: f64, computed_angle: Angle| {
- let marker_node = match marker_type {
+ let marker = match marker_type {
MarkerType::Start => &shape.marker_start,
MarkerType::Middle => &shape.marker_mid,
MarkerType::End => &shape.marker_end,
};
- if let Some(ref marker) = *marker_node {
+ if marker.node_ref.is_some() {
emit_marker_by_node(
draw_ctx,
acquired_nodes,
diff --git a/src/node.rs b/src/node.rs
index 0c61778b..c93fd714 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -16,6 +16,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::*;
use crate::error::*;
+use crate::paint_server::PaintSource;
use crate::properties::ComputedValues;
use crate::text::Chars;
use crate::xml::Attributes;
@@ -100,6 +101,8 @@ impl fmt::Display for NodeData {
/// `&ComputedValues` whose fields you can access.
pub struct CascadedValues<'a> {
inner: CascadedInner<'a>,
+ pub context_stroke: Option<PaintSource>,
+ pub context_fill: Option<PaintSource>,
}
enum CascadedInner<'a> {
@@ -117,6 +120,8 @@ impl<'a> CascadedValues<'a> {
match self.inner {
CascadedInner::FromNode(_) => CascadedValues {
inner: CascadedInner::FromNode(node.borrow_element()),
+ context_fill: self.context_fill.clone(),
+ context_stroke: self.context_stroke.clone(),
},
CascadedInner::FromValues(ref v) => CascadedValues::new_from_values(node, &*v),
@@ -131,6 +136,8 @@ impl<'a> CascadedValues<'a> {
pub fn new_from_node(node: &Node) -> CascadedValues<'_> {
CascadedValues {
inner: CascadedInner::FromNode(node.borrow_element()),
+ context_fill: None,
+ context_stroke: None,
}
}
@@ -147,6 +154,8 @@ impl<'a> CascadedValues<'a> {
CascadedValues {
inner: CascadedInner::FromValues(v),
+ context_fill: None,
+ context_stroke: None,
}
}
@@ -159,6 +168,13 @@ impl<'a> CascadedValues<'a> {
CascadedInner::FromNode(ref e) => e.get_computed_values(),
CascadedInner::FromValues(ref v) => &*v,
}
+
+ // if values.fill == "context-fill" {
+ // values.fill=self.context_fill
+ // }
+ // if values.stroke == "context-stroke" {
+ // values.stroke=self.context_stroke
+ // }
}
}
diff --git a/src/paint_server.rs b/src/paint_server.rs
index 3fe8805a..5ead5e6c 100644
--- a/src/paint_server.rs
+++ b/src/paint_server.rs
@@ -35,12 +35,19 @@ pub enum PaintServer {
/// For example, `fill="blue"`.
SolidColor(cssparser::Color),
+
+ /// For example, `fill="context-fill"`
+ ContextFill,
+
+ /// For example, `fill="context-stroke"`
+ ContextStroke,
}
/// Paint server with resolved references, with unnormalized lengths.
///
/// Use [`PaintSource.to_user_space`](#method.to_user_space) to turn this into a
/// [`UserSpacePaintSource`].
+#[derive(Clone)]
pub enum PaintSource {
None,
Gradient(ResolvedGradient, Option<cssparser::RGBA>),
@@ -65,6 +72,16 @@ impl Parse for PaintServer {
.is_ok()
{
Ok(PaintServer::None)
+ } else if parser
+ .try_parse(|i| i.expect_ident_matching("context-fill"))
+ .is_ok()
+ {
+ Ok(PaintServer::ContextFill)
+ } else if parser
+ .try_parse(|i| i.expect_ident_matching("context-stroke"))
+ .is_ok()
+ {
+ Ok(PaintServer::ContextStroke)
} else if let Ok(url) = parser.try_parse(|i| i.expect_url()) {
let loc = parser.current_source_location();
@@ -107,6 +124,7 @@ impl PaintServer {
acquired_nodes: &mut AcquiredNodes<'_>,
opacity: UnitInterval,
current_color: cssparser::RGBA,
+ context: Option<PaintSource>,
) -> PaintSource {
match self {
PaintServer::Iri {
@@ -182,6 +200,22 @@ impl PaintServer {
PaintSource::SolidColor(resolve_color(color, opacity, current_color))
}
+ PaintServer::ContextFill => {
+ if let Some(paint) = context {
+ paint
+ } else {
+ PaintSource::None
+ }
+ }
+
+ PaintServer::ContextStroke => {
+ if let Some(paint) = context {
+ paint
+ } else {
+ PaintSource::None
+ }
+ }
+
PaintServer::None => PaintSource::None,
}
}
@@ -246,6 +280,17 @@ pub fn resolve_color(
cssparser::RGBA { alpha, ..rgba }
}
+impl std::fmt::Debug for PaintSource {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ match *self {
+ PaintSource::None => f.write_str("PaintSource::None"),
+ PaintSource::Gradient(_, _) => f.write_str("PaintSource::Gradient"),
+ PaintSource::Pattern(_, _) => f.write_str("PaintSource::Pattern"),
+ PaintSource::SolidColor(_) => f.write_str("PaintSource::SolidColor"),
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/shapes.rs b/src/shapes.rs
index 5ac8a51e..bb6bf302 100644
--- a/src/shapes.rs
+++ b/src/shapes.rs
@@ -12,7 +12,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::iri::Iri;
-use crate::layout::{Shape, StackingContext, Stroke};
+use crate::layout::{Marker, Shape, StackingContext, Stroke};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::{optional_comma, Parse, ParseValue};
@@ -50,6 +50,7 @@ macro_rules! impl_draw {
cascaded: &CascadedValues<'_>,
draw_ctx: &mut DrawingCtx,
clipping: bool,
+ //context: &CascadedValues<'_>.inner::FromNode,
) -> Result<BoundingBox, RenderingError> {
let values = cascaded.get();
let view_params = draw_ctx.get_view_params();
@@ -65,32 +66,52 @@ macro_rules! impl_draw {
acquired_nodes,
values.stroke_opacity().0,
values.color().0,
+ cascaded.context_stroke.clone(),
);
let fill_paint = values.fill().0.resolve(
acquired_nodes,
values.fill_opacity().0,
values.color().0,
+ cascaded.context_fill.clone(),
);
let fill_rule = values.fill_rule();
let clip_rule = values.clip_rule();
let shape_rendering = values.shape_rendering();
- let marker_start;
- let marker_mid;
- let marker_end;
+ let marker_start_node;
+ let marker_mid_node;
+ let marker_end_node;
if shape_def.markers == Markers::Yes {
- marker_start = acquire_marker(acquired_nodes, &values.marker_start().0);
- marker_mid = acquire_marker(acquired_nodes, &values.marker_mid().0);
- marker_end = acquire_marker(acquired_nodes, &values.marker_end().0);
+ marker_start_node = acquire_marker(acquired_nodes, &values.marker_start().0);
+ marker_mid_node = acquire_marker(acquired_nodes, &values.marker_mid().0);
+ marker_end_node = acquire_marker(acquired_nodes, &values.marker_end().0);
} else {
- marker_start = None;
- marker_mid = None;
- marker_end = None;
+ marker_start_node = None;
+ marker_mid_node = None;
+ marker_end_node = None;
}
+ let marker_start = Marker {
+ node_ref: marker_start_node,
+ context_stroke: stroke_paint.clone(),
+ context_fill: fill_paint.clone(),
+ };
+
+ let marker_mid = Marker {
+ node_ref: marker_mid_node,
+ context_stroke: stroke_paint.clone(),
+ context_fill: fill_paint.clone(),
+ };
+
+ let marker_end = Marker {
+ node_ref: marker_end_node,
+ context_stroke: stroke_paint.clone(),
+ context_fill: fill_paint.clone(),
+ };
+
let shape = Shape {
path: shape_def.path,
is_visible,
diff --git a/src/text.rs b/src/text.rs
index 83b4daa1..f243587e 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -270,12 +270,14 @@ impl PositionedSpan {
acquired_nodes,
self.values.stroke_opacity().0,
self.values.color().0,
+ None,
);
let fill_paint = self.values.fill().0.resolve(
acquired_nodes,
self.values.fill_opacity().0,
self.values.color().0,
+ None,
);
let text_rendering = self.values.text_rendering();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]