[librsvg: 1/4] Render and style text links
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/4] Render and style text links
- Date: Tue, 12 Oct 2021 23:34:09 +0000 (UTC)
commit 195b58c84285eab8769a5bc17e99ebac8328990a
Author: Michael Howell <michael notriddle com>
Date: Fri Oct 8 15:29:56 2021 -0700
Render and style text links
Fixes #738
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/601>
src/structure.rs | 18 ++++++++--
src/text.rs | 40 ++++++++++++++++++---
.../bugs/a-inside-text-content-738-ref.png | Bin 0 -> 2493 bytes
.../reftests/bugs/a-inside-text-content-738.svg | 24 +++++++++++++
4 files changed, 76 insertions(+), 6 deletions(-)
---
diff --git a/src/structure.rs b/src/structure.rs
index 9facec72..8d47197d 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -7,7 +7,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
-use crate::element::{Draw, ElementResult, SetAttributes};
+use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::layout::StackingContext;
@@ -15,6 +15,7 @@ use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
use crate::parsers::{Parse, ParseValue};
use crate::rect::Rect;
+use crate::text::TSpan;
use crate::viewbox::*;
use crate::xml::Attributes;
@@ -511,7 +512,9 @@ impl Draw for Mask {}
#[derive(Default)]
pub struct Link {
- link: Option<String>,
+ pub link: Option<String>,
+ // These attributes are only applicable in <text><a></a></text>.
+ pub tspan: TSpan,
}
impl SetAttributes for Link {
@@ -523,6 +526,8 @@ impl SetAttributes for Link {
}
}
+ self.tspan.set_attributes(attrs)?;
+
Ok(())
}
}
@@ -536,6 +541,15 @@ impl Draw for Link {
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
+
+ // If this element is inside of <text>, do not draw it.
+ // The <text> takes care of it.
+ for an in node.ancestors() {
+ if matches!(&*an.borrow_element(), Element::Text(_)) {
+ return Ok(draw_ctx.empty_bbox());
+ }
+ }
+
let cascaded = CascadedValues::new(cascaded, node);
let values = cascaded.get();
diff --git a/src/text.rs b/src/text.rs
index 46baef3b..20a673c6 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -38,6 +38,7 @@ struct Chunk {
x: Option<f64>,
y: Option<f64>,
spans: Vec<Span>,
+ link: Option<String>,
}
struct MeasuredChunk {
@@ -46,12 +47,14 @@ struct MeasuredChunk {
y: Option<f64>,
advance: (f64, 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 {
@@ -78,11 +81,12 @@ struct PositionedSpan {
}
impl Chunk {
- fn new(values: &ComputedValues, x: Option<f64>, y: Option<f64>) -> Chunk {
+ fn new(values: &ComputedValues, x: Option<f64>, y: Option<f64>, link: Option<String>) -> Chunk {
Chunk {
values: Rc::new(values.clone()),
x,
y,
+ link,
spans: Vec::new(),
}
}
@@ -110,6 +114,7 @@ impl MeasuredChunk {
y: chunk.y,
advance,
spans: measured_spans,
+ link: chunk.link.clone(),
}
}
}
@@ -183,6 +188,7 @@ impl PositionedChunk {
next_chunk_x: x,
next_chunk_y: y,
spans: positioned,
+ link: measured.link.clone(),
}
}
}
@@ -330,6 +336,7 @@ fn children_to_chunks(
dx: f64,
dy: f64,
depth: usize,
+ link: Option<String>,
) {
for child in node.children() {
if child.is_chars() {
@@ -352,6 +359,23 @@ fn children_to_chunks(
dx,
dy,
depth + 1,
+ link.clone(),
+ );
+ }
+
+ Element::Link(ref link) => {
+ let tspan = &link.tspan;
+ let cascaded = CascadedValues::new(cascaded, &child);
+ tspan.to_chunks(
+ &child,
+ acquired_nodes,
+ &cascaded,
+ draw_ctx,
+ chunks,
+ dx,
+ dy,
+ depth + 1,
+ link.link.clone(),
);
}
@@ -498,7 +522,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)));
+ chunks.push(Chunk::new(values, Some(x), Some(y), None));
let dx = self.dx.to_user(¶ms);
let dy = self.dy.to_user(¶ms);
@@ -512,6 +536,7 @@ impl Text {
dx,
dy,
0,
+ None,
);
chunks
}
@@ -592,7 +617,12 @@ impl Draw for Text {
for chunk in &positioned_chunks {
for span in &chunk.spans {
- let span_bbox = span.draw(an, dc, clipping)?;
+ let span_bbox = match chunk.link.as_ref() {
+ Some(l) if !l.is_empty() => {
+ dc.with_link_tag(l.as_str(), &mut |dc| span.draw(an, dc, clipping))?
+ }
+ _ => span.draw(an, dc, clipping)?,
+ };
bbox.insert(&span_bbox);
}
}
@@ -695,6 +725,7 @@ impl TSpan {
dx: f64,
dy: f64,
depth: usize,
+ link: Option<String>,
) {
let values = cascaded.get();
if !values.is_displayed() {
@@ -711,7 +742,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));
+ chunks.push(Chunk::new(values, x, y, link.clone()));
}
children_to_chunks(
@@ -723,6 +754,7 @@ impl TSpan {
span_dx,
span_dy,
depth,
+ link,
);
}
}
diff --git a/tests/fixtures/reftests/bugs/a-inside-text-content-738-ref.png
b/tests/fixtures/reftests/bugs/a-inside-text-content-738-ref.png
new file mode 100644
index 00000000..ea52230c
Binary files /dev/null and b/tests/fixtures/reftests/bugs/a-inside-text-content-738-ref.png differ
diff --git a/tests/fixtures/reftests/bugs/a-inside-text-content-738.svg
b/tests/fixtures/reftests/bugs/a-inside-text-content-738.svg
new file mode 100644
index 00000000..7c3a0482
--- /dev/null
+++ b/tests/fixtures/reftests/bugs/a-inside-text-content-738.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ viewBox="0 0 500 600"
+ font-family="sans-serif"
+ font-size="18">
+ <defs>
+ <style>
+ a {fill: black; font-family: Helvetica; font-size:10; }
+ text { font-family: Helvetica; font-size:10; }
+ </style>
+ </defs>
+
+ <text x="250" y="25" class="head" text-anchor="middle">SVG CSS Tests</text>
+ <g transform="translate(0,50)">
+ <text x="50">a:link</text>
+ <text x="250" class="test"><a xlink:href="#foo">xlink:href</a></text>
+ </g>
+
+</svg>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]