Commit 091e08cc authored by RazrFalcon's avatar RazrFalcon

(resvg) Fixed bbox calculation of the text with rotate.

Closes #66
parent 03c666e0
......@@ -16,6 +16,7 @@ This changelog also contains an important changes in dependencies.
### Fixed
- (cairo-backend) Text layout.
- (resvg) Recursive SVG images via `image` tag.
- (resvg) Bbox calculation of the text with rotate.
- (qt-api) SVG from QByteArray loading when data is invalid.
### Removed
......
......@@ -22,6 +22,7 @@ use {
};
use self::ext::*;
macro_rules! try_create_surface {
($size:expr, $ret:expr) => {
try_opt_warn!(
......@@ -394,7 +395,10 @@ fn _calc_node_bbox(
let segments = from_cairo_path(&path);
let mut t = ts2;
t.append(&usvg::Transform::new(1.0, 0.0, 0.0, 1.0, block.bbox.x, block.bbox.y));
if !block.rotate.is_fuzzy_zero() {
t.rotate_at(block.rotate, block.bbox.x, block.bbox.y + block.font_ascent);
}
t.translate(block.bbox.x, block.bbox.y);
if !segments.is_empty() {
let c_bbox = utils::path_bbox(&segments, block.stroke.as_ref(), &t);
......
......@@ -327,13 +327,13 @@ pub fn calc_node_bbox(
let p = qt::Painter::new(&img);
let abs_ts = utils::abs_transform(node);
_calc_node_bbox(node, abs_ts, opt, &p)
_calc_node_bbox(node, opt, abs_ts, &p)
}
fn _calc_node_bbox(
node: &usvg::Node,
ts: usvg::Transform,
opt: &Options,
ts: usvg::Transform,
p: &qt::Painter,
) -> Option<Rect> {
let mut ts2 = ts;
......@@ -349,14 +349,19 @@ fn _calc_node_bbox(
text::draw_blocks(text, &mut fm, |block| {
let mut p_path = qt::PainterPath::new();
p_path.add_text(0.0, 0.0, &block.font, &block.text);
p.set_font(&block.font);
let y = block.bbox.y + p.font_metrics().ascent();
p_path.add_text(block.bbox.x, y, &block.font, &block.text);
let y = block.bbox.y + block.font_ascent;
let mut t = ts2;
if !block.rotate.is_fuzzy_zero() {
t.rotate_at(block.rotate, block.bbox.x, y);
}
t.translate(block.bbox.x, y);
let segments = from_qt_path(&p_path);
if !segments.is_empty() {
let c_bbox = utils::path_bbox(&segments, block.stroke.as_ref(), &ts2);
let c_bbox = utils::path_bbox(&segments, block.stroke.as_ref(), &t);
bbox.expand(c_bbox);
}
});
......@@ -371,7 +376,7 @@ fn _calc_node_bbox(
let mut bbox = Rect::new_bbox();
for child in node.children() {
if let Some(c_bbox) = _calc_node_bbox(&child, ts2, opt, p) {
if let Some(c_bbox) = _calc_node_bbox(&child, opt, ts2, p) {
bbox.expand(c_bbox);
}
}
......
......@@ -17,6 +17,7 @@ pub struct TextBlock<Font> {
pub fill: Option<usvg::Fill>,
pub stroke: Option<usvg::Stroke>,
pub font: Font,
pub font_ascent: f64,
pub decoration: usvg::TextDecoration,
}
......@@ -130,6 +131,7 @@ fn prepare_blocks<Font>(
fill: tspan.fill.clone(),
stroke: tspan.stroke.clone(),
font: font_metrics.font(),
font_ascent: font_metrics.ascent(),
decoration: tspan.decoration.clone(),
});
}
......
......@@ -81,32 +81,11 @@ pub fn path_bbox(
use lyon_geom;
let mut path_buf = Vec::new();
let mut path_buf;
let new_path = if !ts.is_default() {
// Allocate only when transform is required.
path_buf.reserve(segments.len());
for seg in segments {
match *seg {
usvg::PathSegment::MoveTo { x, y } => {
let (x, y) = ts.apply(x, y);
path_buf.push(usvg::PathSegment::MoveTo { x, y });
}
usvg::PathSegment::LineTo { x, y } => {
let (x, y) = ts.apply(x, y);
path_buf.push(usvg::PathSegment::LineTo { x, y });
}
usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y } => {
let (x1, y1) = ts.apply(x1, y1);
let (x2, y2) = ts.apply(x2, y2);
let (x, y) = ts.apply(x, y);
path_buf.push(usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y });
}
usvg::PathSegment::ClosePath => {
path_buf.push(usvg::PathSegment::ClosePath);
}
}
}
// Clone only when transform is required.
path_buf = segments.to_vec();
transform_path(&mut path_buf, ts);
&path_buf
} else {
segments
......@@ -181,6 +160,27 @@ pub fn path_bbox(
(minx as f64, miny as f64, width as f64, height as f64).into()
}
/// Applies the transform to the path segments.
pub fn transform_path(segments: &mut [usvg::PathSegment], ts: &usvg::Transform) {
for seg in segments {
match *seg {
usvg::PathSegment::MoveTo { ref mut x, ref mut y } => {
ts.apply_to(x, y);
}
usvg::PathSegment::LineTo { ref mut x, ref mut y } => {
ts.apply_to(x, y);
}
usvg::PathSegment::CurveTo { ref mut x1, ref mut y1, ref mut x2,
ref mut y2, ref mut x, ref mut y } => {
ts.apply_to(x1, y1);
ts.apply_to(x2, y2);
ts.apply_to(x, y);
}
usvg::PathSegment::ClosePath => {}
}
}
}
/// Converts `rect` to path segments.
pub fn rect_to_path(rect: Rect) -> Vec<usvg::PathSegment> {
vec![
......
......@@ -26,6 +26,7 @@ fn query_all() {
text2,200.875,102,32.172,28
text3,202.311,178,57.692,22
text4,195.703,243,65.406,32
text5,206.739,306.299,58.393,26.092
g1,350,20,100,50
g2,350,95,120,70
");
......@@ -42,6 +43,7 @@ fn query_all() {
text2,200.875,101.375,31.172,28.766
text3,202.311,178.531,56.068,21.828
text4,195.703,243.531,64.063,31.828
text5,206.739,306.759,58.136,25.632
g1,350,20,100,50
g2,350,95,120,70
");
......
......@@ -31,6 +31,9 @@
<text x="200" y="240">Text with stroke</text>
<text id="text4" x="200" y="270" font-size="30" stroke="black" stroke-width="10">Text</text>
<text x="200" y="300">Text with rotate</text>
<text id="text5" x="200" y="325" font-size="30" rotate="30">Text</text>
<text x="350" y="15">Simple group</text>
<g id="g1">
<rect x="350" y="20" width="100" height="50" fill="black"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment