[librsvg: 1/2] Attach link target to text span, not text chunk
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/2] Attach link target to text span, not text chunk
- Date: Thu, 21 Oct 2021 21:58:36 +0000 (UTC)
commit 4ebe578d6a050a996b71144705765f5199301602
Author: Michael Howell <michael notriddle com>
Date: Wed Oct 20 19:11:25 2021 -0500
Attach link target to text span, not text chunk
New chunks are only created when the layout changes. We don't want that.
Fixes #807
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/618>
src/text.rs | 51 ++++++++++++++++++++++------------
tests/fixtures/cmdline/text-a-link.svg | 14 ++++++++++
tests/src/cmdline/rsvg_convert.rs | 16 +++++++++++
3 files changed, 63 insertions(+), 18 deletions(-)
---
diff --git a/src/text.rs b/src/text.rs
index f717852f..1c0c11a7 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -41,7 +41,6 @@ struct Chunk {
x: Option<f64>,
y: Option<f64>,
spans: Vec<Span>,
- link: Option<String>,
}
struct MeasuredChunk {
@@ -51,14 +50,12 @@ struct MeasuredChunk {
dx: f64,
dy: f64,
spans: Vec<MeasuredSpan>,
- link: Option<String>,
}
struct PositionedChunk {
next_chunk_x: f64,
next_chunk_y: f64,
spans: Vec<PositionedSpan>,
- link: Option<String>,
}
struct Span {
@@ -67,6 +64,7 @@ struct Span {
dx: f64,
dy: f64,
_depth: usize,
+ link_target: Option<String>,
}
struct MeasuredSpan {
@@ -76,6 +74,7 @@ struct MeasuredSpan {
advance: (f64, f64),
dx: f64,
dy: f64,
+ link_target: Option<String>,
}
struct PositionedSpan {
@@ -83,6 +82,7 @@ struct PositionedSpan {
values: Rc<ComputedValues>,
rendered_position: (f64, f64),
next_span_position: (f64, f64),
+ link_target: Option<String>,
}
/// A laid-out and resolved text span.
@@ -107,12 +107,11 @@ struct LayoutSpan {
}
impl Chunk {
- fn new(values: &ComputedValues, x: Option<f64>, y: Option<f64>, link: Option<String>) -> Chunk {
+ fn new(values: &ComputedValues, x: Option<f64>, y: Option<f64>) -> Chunk {
Chunk {
values: Rc::new(values.clone()),
x,
y,
- link,
spans: Vec::new(),
}
}
@@ -151,7 +150,6 @@ impl MeasuredChunk {
dx: chunk_dx,
dy: chunk_dy,
spans: measured_spans,
- link: chunk.link.clone(),
}
}
}
@@ -222,6 +220,7 @@ impl PositionedChunk {
values,
rendered_position,
next_span_position: (x, y),
+ link_target: mspan.link_target.clone(),
};
positioned.push(positioned_span);
@@ -257,7 +256,6 @@ impl PositionedChunk {
next_chunk_x,
next_chunk_y,
spans: positioned,
- link: measured.link.clone(),
}
}
}
@@ -306,13 +304,21 @@ fn text_anchor_offset(
}
impl Span {
- fn new(text: &str, values: Rc<ComputedValues>, dx: f64, dy: f64, depth: usize) -> Span {
+ fn new(
+ text: &str,
+ values: Rc<ComputedValues>,
+ dx: f64,
+ dy: f64,
+ depth: usize,
+ link_target: Option<String>,
+ ) -> Span {
Span {
values,
text: text.to_string(),
dx,
dy,
_depth: depth,
+ link_target,
}
}
}
@@ -352,6 +358,7 @@ impl MeasuredSpan {
advance,
dx: span.dx,
dy: span.dy,
+ link_target: span.link_target.clone(),
}
}
}
@@ -412,7 +419,6 @@ impl PositionedSpan {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
view_params: &ViewParams,
- link_target: Option<String>,
) -> LayoutSpan {
let params = NormalizeParams::new(&self.values, view_params);
@@ -457,8 +463,8 @@ impl PositionedSpan {
stroke_paint,
fill_paint,
text_rendering,
- link_target,
values: self.values.clone(),
+ link_target: self.link_target.clone(),
}
}
}
@@ -483,9 +489,15 @@ fn children_to_chunks(
for child in node.children() {
if child.is_chars() {
let values = cascaded.get();
- child
- .borrow_chars()
- .to_chunks(&child, Rc::new(values.clone()), chunks, dx, dy, depth);
+ child.borrow_chars().to_chunks(
+ &child,
+ Rc::new(values.clone()),
+ chunks,
+ dx,
+ dy,
+ depth,
+ link.clone(),
+ );
} else {
assert!(child.is_element());
@@ -608,6 +620,7 @@ impl Chars {
dx: f64,
dy: f64,
depth: usize,
+ link_target: Option<String>,
) -> Span {
self.ensure_normalized_string(node, &*values);
@@ -617,6 +630,7 @@ impl Chars {
dx,
dy,
depth,
+ link_target,
)
}
@@ -628,8 +642,9 @@ impl Chars {
dx: f64,
dy: f64,
depth: usize,
+ link_target: Option<String>,
) {
- let span = self.make_span(node, values, dx, dy, depth);
+ let span = self.make_span(node, values, dx, dy, depth, link_target);
let num_chunks = chunks.len();
assert!(num_chunks > 0);
@@ -665,7 +680,7 @@ impl Text {
let view_params = draw_ctx.get_view_params();
let params = NormalizeParams::new(values, &view_params);
- chunks.push(Chunk::new(values, Some(x), Some(y), None));
+ chunks.push(Chunk::new(values, Some(x), Some(y)));
let dx = self.dx.to_user(¶ms);
let dy = self.dy.to_user(¶ms);
@@ -761,7 +776,7 @@ impl Draw for Text {
let mut layout_spans = Vec::new();
for chunk in &positioned_chunks {
for span in &chunk.spans {
- layout_spans.push(span.layout(an, dc, &view_params, chunk.link.clone()));
+ layout_spans.push(span.layout(an, dc, &view_params));
}
}
@@ -858,7 +873,7 @@ fn extract_chars_children_to_chunks_recursively(
if child.is_chars() {
child
.borrow_chars()
- .to_chunks(&child, values, chunks, 0.0, 0.0, depth)
+ .to_chunks(&child, values, chunks, 0.0, 0.0, depth, None)
} else {
extract_chars_children_to_chunks_recursively(chunks, &child, values, depth + 1)
}
@@ -917,7 +932,7 @@ impl TSpan {
let span_dy = dy + self.dy.to_user(¶ms);
if x.is_some() || y.is_some() {
- chunks.push(Chunk::new(values, x, y, link.clone()));
+ chunks.push(Chunk::new(values, x, y));
}
children_to_chunks(
diff --git a/tests/fixtures/cmdline/text-a-link.svg b/tests/fixtures/cmdline/text-a-link.svg
new file mode 100644
index 00000000..d205c768
--- /dev/null
+++ b/tests/fixtures/cmdline/text-a-link.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
+ <text x="100" y="100">
+ <a href="https://example.com">
+ This is a link to example.com
+ </a>
+
+ <tspan x="100" dy="2em">
+ <a href="https://another.example.com">
+ This is a link to another.example.com
+ </a>
+ </tspan>
+ </text>
+</svg>
diff --git a/tests/src/cmdline/rsvg_convert.rs b/tests/src/cmdline/rsvg_convert.rs
index 78c7c625..9b57fd8a 100644
--- a/tests/src/cmdline/rsvg_convert.rs
+++ b/tests/src/cmdline/rsvg_convert.rs
@@ -337,6 +337,22 @@ fn pdf_has_link() {
.stdout(file::is_pdf().with_link("https://example.com"));
}
+#[cfg(system_deps_have_cairo_pdf)]
+#[test]
+fn pdf_has_link_inside_text() {
+ let input = Path::new("tests/fixtures/cmdline/text-a-link.svg");
+ RsvgConvert::new()
+ .arg("--format=pdf")
+ .arg(input)
+ .assert()
+ .success()
+ .stdout(
+ file::is_pdf()
+ .with_link("https://example.com")
+ .and(file::is_pdf().with_link("https://another.example.com")),
+ );
+}
+
#[cfg(system_deps_have_cairo_pdf)]
#[test]
fn env_source_data_epoch_controls_pdf_creation_date() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]