...
 
Commits (12)
......@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
This changelog also contains important changes in dependencies.
## [Unreleased]
### Added
- Nested `baseline-shift` support.
- (qt-api) `renderToImage`.
### Changed
- `baseline-shift` with `sub`, `super` and percent values calculation.
- (qt-api) `render` methods are `const` now.
### Fixed
- (cairo-backend) `font-family` parsing.
- (usvg) `filter:none` processing.
- (usvg) `text` inside `text` processing.
- (svgtypes) Style with comments parsing.
## [0.5.0] - 2018-01-04
### Added
......
......@@ -416,15 +416,15 @@ dependencies = [
[[package]]
name = "phf"
version = "0.7.23"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_shared"
version = "0.7.23"
version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -552,16 +552,16 @@ dependencies = [
"roxmltree 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"svgtypes 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"svgtypes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "svgtypes"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -684,8 +684,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6eb49268e69dd0c1da5d3001a61aac08e2e9d2bfbe4ae4b19b9963c998f6453"
"checksum pangocairo 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4325b65f44487564a18d6402bed48c1bc4642167bfe972a753d039d1ac938c21"
"checksum pangocairo-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e79ffb01eae5bc130b44fde529fa493ad6308c340da1358eaa2435ed3580e4f"
"checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6"
"checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93"
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
......@@ -698,7 +698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
"checksum svgdom 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16b0f1267a0a705747fde1cfbc5acfa5ef5c445f9756cab1a242cb465c083fe3"
"checksum svgtypes 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5aedf4c8cddf659deb5149ba5038e10bb05e589a5cd0515356958f391c2ca00"
"checksum svgtypes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a012193f7a8b1ad646da3003a25a9d7d01c073d4d9d91d2178ce3de2df1a47c"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
......
......@@ -34,7 +34,7 @@ removes groups and invisible elements, fixes a lot of issues in malformed SVG fi
Then it creates a simple render tree with all elements and attributes resolved.
And only then it starts to render. So it's very easy to implement a new rendering backend.
More details [here](https://github.com/RazrFalcon/usvg/blob/master/docs/usvg_spec.adoc).
More details [here](https://github.com/RazrFalcon/resvg/blob/master/docs/usvg_spec.adoc).
### resvg vs librsvg
......@@ -88,7 +88,7 @@ Also, we do not test against Chrome, Firefox, Inkscape and Batik because they ha
![Chart3](./.github/perf-elementary.svg)
- Elementary Icon Theme contains 3417 files.
- resvg-qt is slow for unknown reasons.
- Qt backend is slow because `QRasterPaintEngine` is slow.
![Chart4](./.github/perf-oxygen.svg)
......
......@@ -231,7 +231,7 @@ public:
/**
* @brief Renders the SVG data to canvas.
*/
void render(QPainter *p);
void render(QPainter *p) const;
/**
* @brief Renders the SVG data to canvas with the specified \b bounds.
......@@ -239,7 +239,7 @@ public:
* If the bounding rectangle is not specified
* the SVG file is mapped to the whole paint device.
*/
void render(QPainter *p, const QRectF &bounds);
void render(QPainter *p, const QRectF &bounds) const;
/**
* @brief Renders the given element with \b elementId on the specified \b bounds.
......@@ -247,8 +247,14 @@ public:
* If the bounding rectangle is not specified
* the SVG element is mapped to the whole paint device.
*/
void render(QPainter *p, const QString &elementId,
const QRectF &bounds = QRectF());
void render(QPainter *p, const QString &elementId, const QRectF &bounds = QRectF()) const;
/**
* @brief Renders the SVG data to \b QImage with a specified \b size.
*
* If \b size is not set, the \b defaultSize() will be used.
*/
QImage renderToImage(const QSize &size = QSize()) const;
/**
* @brief Initializes the library log.
......@@ -419,12 +425,12 @@ inline void ResvgRenderer::setDevicePixelRatio(qreal scaleFactor)
d->scaleFactor = scaleFactor;
}
inline void ResvgRenderer::render(QPainter *p)
inline void ResvgRenderer::render(QPainter *p) const
{
render(p, QRectF());
}
inline void ResvgRenderer::render(QPainter *p, const QRectF &bounds)
inline void ResvgRenderer::render(QPainter *p, const QRectF &bounds) const
{
if (!d->tree)
return;
......@@ -444,12 +450,25 @@ inline void ResvgRenderer::render(QPainter *p, const QRectF &bounds)
p->restore();
}
inline void ResvgRenderer::render(QPainter *p, const QString &elementId, const QRectF &bounds)
inline void ResvgRenderer::render(QPainter *p, const QString &elementId, const QRectF &bounds) const
{
Q_UNUSED(p) Q_UNUSED(elementId) Q_UNUSED(bounds)
Q_UNIMPLEMENTED();
}
inline QImage ResvgRenderer::renderToImage(const QSize &size) const
{
const auto s = size.isValid() ? size : defaultSize();
QImage img(s, QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::transparent);
QPainter p(&img);
render(&p);
p.end();
return img;
}
inline void ResvgRenderer::initLog()
{
resvg_init_log();
......
......@@ -32,7 +32,6 @@
### Attributes
- `alignment-baseline`
- Nested `baseline-shift`
- `clip` (deprecated in the SVG 2)
- `color-interpolation`
- `color-profile`
......@@ -41,6 +40,7 @@
- `dominant-baseline`
- [`enable-background`](https://www.w3.org/TR/SVG11/filters.html#EnableBackgroundProperty) (deprecated in the SVG 2)
- `font`
- `font-variant` (unsupported only by cairo backend)
- `font-size-adjust`
- `glyph-orientation-horizontal` (removed in the SVG 2)
- `glyph-orientation-vertical` (deprecated in the SVG 2)
......@@ -51,7 +51,7 @@
- `shape-rendering`
- `text-rendering`
- `unicode-bidi`
- `word-spacing` (unsupported only on the cairo backend)
- `word-spacing` (unsupported only by cairo backend)
- `writing-mode`
**Note:** this list does not include elements and attributes outside the
......
......@@ -102,7 +102,7 @@ fn draw_subpath(
//
// Buy the SVG spec, a zero length subpath with a square cap should be
// rendered as a square/rect, but it's not (at least on 1.14.12/1.15.12).
// And this is probably a bug, since round cap is rendered correctly.
// And this is probably a bug, since round caps are rendered correctly.
let mut is_zero_path = false;
if is_square_cap {
if utils::path_length(segments).is_fuzzy_zero() {
......
......@@ -198,7 +198,9 @@ fn draw_block(
fn init_font(dom_font: &usvg::Font, dpi: f64) -> pango::FontDescription {
let mut font = pango::FontDescription::new();
font.set_family(&dom_font.family);
// We have to remove quotes, because `pango` doesn't support them.
let font_family = dom_font.family.replace('\'', "");
font.set_family(&font_family);
let font_style = match dom_font.style {
usvg::FontStyle::Normal => pango::Style::Normal,
......
......@@ -53,7 +53,7 @@ fn convert_path(
p_path: &mut qt::PainterPath,
) {
// Qt's QPainterPath automatically closes open subpaths if start and end positions are equal.
// This is incorrect behaviour according to the SVG.
// This is an incorrect behaviour according to the SVG.
// So we have to shift the last segment a bit, to prevent such behaviour.
//
// 'A closed path has coinciding start and end points.'
......@@ -136,7 +136,7 @@ fn convert_path(
}
}
// If CurveTo is approximately a LineTo than we should draw it as LineTo,
// If a CurveTo is approximately a LineTo than we should draw it as a LineTo,
// otherwise Qt will draw it incorrectly.
//
// See QTBUG-72796
......
......@@ -115,17 +115,9 @@ pub fn prepare_blocks<Font>(
x = new_w;
} else {
let baseline_shift = match tspan.baseline_shift {
usvg::BaselineShift::Baseline => 0.0,
usvg::BaselineShift::Subscript => font_metrics.height() / 2.0,
usvg::BaselineShift::Superscript => -font_metrics.height() / 2.0,
usvg::BaselineShift::Percent(n) => -font_metrics.height() * (n / 100.0),
usvg::BaselineShift::Number(n) => -n,
};
let font_ascent = font_metrics.ascent(c);
let width = font_metrics.width(c);
let yy = y - font_ascent + baseline_shift;
let yy = y - font_ascent - tspan.baseline_shift;
let height = font_metrics.height();
let bbox = Rect { x, y: yy, width, height };
x += width;
......
......@@ -10,7 +10,8 @@ use std::fmt;
// external
use usvg::{
FuzzyEq
self,
FuzzyEq,
};
pub use usvg::{
Line,
......
......@@ -58,9 +58,7 @@ void SvgViewWorker::render(const QSize &viewSize)
QImage img(s * m_dpiRatio, QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::transparent);
QPainter p;
p.begin(&img);
p.setRenderHint(QPainter::Antialiasing);
QPainter p(&img);
m_renderer.render(&p);
p.end();
......
......@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
- Nested `baseline-shift` support.
### Changed
- `baseline-shift` with `sub`, `super` and percent values calculation.
- `TextSpan::baseline_shift` is `f64` now.
### Fixed
- `filter:none` processing.
- `text` inside `text` processing.
### Removed
- `BaselineShift` enum.
## [0.5.0] - 2018-01-04
### Added
- Added marker support.
- Implement `FuzzyEq` for `Rect`, `Size` and `Point`.
- `StrokeMiterlimit` and `FontSize` wrappers for `f64`.
......@@ -125,7 +140,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Gradient stops resolving.
- `switch` element resolving.
[Unreleased]: https://github.com/RazrFalcon/usvg/compare/v0.4.0...HEAD
[Unreleased]: https://github.com/RazrFalcon/usvg/compare/v0.5.0...HEAD
[0.5.0]: https://github.com/RazrFalcon/usvg/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/RazrFalcon/usvg/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/RazrFalcon/usvg/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/RazrFalcon/usvg/compare/v0.1.1...v0.2.0
# usvg
[![Build Status](https://travis-ci.org/RazrFalcon/usvg.svg?branch=master)](https://travis-ci.org/RazrFalcon/usvg)
[![Build Status](https://travis-ci.org/RazrFalcon/resvg.svg?branch=master)](https://travis-ci.org/RazrFalcon/usvg)
[![Crates.io](https://img.shields.io/crates/v/usvg.svg)](https://crates.io/crates/usvg)
[![Documentation](https://docs.rs/usvg/badge.svg)](https://docs.rs/usvg)
......@@ -46,7 +46,7 @@ and an XML library with some small amount of code.
- Paint fallback will be resolved
- No `script` (simply ignoring it)
Full spec can be found [here](docs/usvg_spec.adoc).
Full spec can be found [here](../docs/usvg_spec.adoc).
## Limitations
......
......@@ -77,20 +77,13 @@ fn convert_chunks(
chunks.push(chunk_node);
}
let fill = fill::convert(tree, attrs, true);
let stroke = stroke::convert(tree, attrs, true);
let font = conv_font(attrs, opt);
let decoration = conv_tspan_decoration2(tree, text_elem, &tspan);
let visibility = super::convert_visibility(attrs);
let baseline_shift = conv_baseline_shift(attrs);
let span = tree::TextSpan {
visibility,
fill,
stroke,
font,
baseline_shift,
decoration,
visibility: super::convert_visibility(attrs),
fill: fill::convert(tree, attrs, true),
stroke: stroke::convert(tree, attrs, true),
font: conv_font(attrs, opt),
baseline_shift: attrs.get_number_or(AId::BaselineShift, 0.0),
decoration: conv_tspan_decoration2(tree, text_elem, &tspan),
text,
};
......@@ -196,49 +189,6 @@ fn conv_text_anchor(attrs: &svgdom::Attributes) -> tree::TextAnchor {
}
}
fn conv_baseline_shift(attrs: &svgdom::Attributes) -> tree::BaselineShift {
let av = attrs.get_value(AId::BaselineShift);
match av {
Some(AValue::String(ref s)) => {
match s.as_str() {
"baseline" => tree::BaselineShift::Baseline,
"sub" => tree::BaselineShift::Subscript,
"super" => tree::BaselineShift::Superscript,
_ => {
warn!("An invalid 'baseline-shift' value: '{}'. Fallback to 'baseline'.", s);
tree::BaselineShift::Baseline
}
}
}
Some(AValue::Length(len)) => {
if len.num.is_fuzzy_zero() {
tree::BaselineShift::Baseline
} else {
match len.unit {
Unit::Percent => {
tree::BaselineShift::Percent(len.num)
}
_ => {
warn!("'baseline-shift' value must be a number or a percent.");
tree::BaselineShift::Baseline
}
}
}
}
Some(AValue::Number(n)) => {
tree::BaselineShift::Number(*n)
}
None => {
// Fallback to a default value.
tree::BaselineShift::Baseline
}
_ => {
warn!("An invalid 'baseline-shift' value: '{:?}'. Fallback to 'baseline'.", av);
tree::BaselineShift::Baseline
}
}
}
fn conv_font(attrs: &svgdom::Attributes, opt: &Options) -> tree::Font {
let style = attrs.get_str_or(AId::FontStyle, "normal");
let style = match style {
......
......@@ -79,7 +79,7 @@ pub fn fix_links(doc: &mut Document) {
fn is_valid_func_link(node: &Node, aid: AId) -> bool {
match node.attributes().get_value(aid) {
Some(AValue::FuncLink(_)) | None => true,
Some(AValue::FuncLink(_)) | Some(AValue::None) | None => true,
_ => false,
}
}
......@@ -20,8 +20,7 @@ mod group_defs;
mod prepare_clip_path;
mod prepare_mask;
mod prepare_nested_svg;
mod prepare_text_decoration;
mod prepare_text_nodes;
mod prepare_text;
mod regroup;
mod resolve_attrs_via_xlink;
mod resolve_children_via_xlink;
......@@ -53,8 +52,7 @@ use self::group_defs::*;
use self::prepare_clip_path::*;
use self::prepare_mask::*;
use self::prepare_nested_svg::*;
use self::prepare_text_decoration::*;
use self::prepare_text_nodes::*;
use self::prepare_text::*;
use self::regroup::*;
use self::resolve_attrs_via_xlink::*;
use self::resolve_children_via_xlink::*;
......@@ -204,7 +202,7 @@ pub fn prepare_doc(doc: &mut svgdom::Document, opt: &Options) {
ungroup_groups(doc, opt);
regroup_elements(doc, svg);
prepare_text_nodes(doc);
prepare_text_nodes(doc, opt);
remove_invalid_font_size(doc, opt);
remove_unused_defs(doc);
......
......@@ -11,7 +11,102 @@ use svgdom::{
use super::prelude::*;
pub fn prepare_text_nodes(doc: &mut Document) {
// <g fill="red" text-decoration="underline">
// <g fill="blue" text-decoration="overline">
// <text fill="green" text-decoration="line-through">Text</text>
// </g>
// </g>
//
// In this example 'text' element will have all decorators enabled, but color
// will be green for all of them.
//
// There is no simpler way to express 'text-decoration' property
// without groups than collect all the options to the string.
// It's not by the SVG spec, but easier than keeping all the groups.
pub fn prepare_text_decoration(doc: &Document) {
for mut node in doc.root().descendants().filter(|n| n.is_tag_name(EId::Text)) {
let mut td = String::new();
if has_decoration_attr(&node, "underline") {
td.push_str("underline;");
}
if has_decoration_attr(&node, "overline") {
td.push_str("overline;");
}
if has_decoration_attr(&node, "line-through") {
td.push_str("line-through;");
}
if !td.is_empty() {
td.pop();
node.set_attribute((AId::TextDecoration, td));
}
}
}
fn has_decoration_attr(root: &Node, decoration_id: &str) -> bool {
for (_, node) in root.ancestors().svg() {
let attrs = node.attributes();
if let Some(text) = attrs.get_str(AId::TextDecoration) {
if text == decoration_id {
return true;
}
}
}
false
}
fn prepare_baseline_shift(doc: &Document, opt: &Options) {
let mut resolved = Vec::new();
for node in doc.root().descendants().filter(|n| n.is_tag_name(EId::Text)) {
for text_node in node.descendants().filter(|n| n.is_text()) {
let mut shift = 0.0;
for tspan in text_node.ancestors().take_while(|n| !n.is_tag_name(EId::Text)) {
let attrs = tspan.attributes();
let av = attrs.get_value(AId::BaselineShift);
let font_size = attrs.get_number(AId::FontSize).unwrap_or(opt.font_size);
match av {
Some(AValue::String(ref s)) => {
match s.as_str() {
"baseline" => {}
"sub" => shift += font_size * -0.2,
"super" => shift += font_size * 0.4,
_ => {}
}
}
Some(AValue::Length(len)) => {
if len.unit == Unit::Percent {
shift += font_size * (len.num / 100.0);
}
}
Some(AValue::Number(n)) => shift += n,
_ => {}
}
}
let mut tspan = text_node.parent().unwrap();
resolved.push((tspan, shift));
}
}
for (mut node, shift) in resolved {
node.set_attribute((AId::BaselineShift, shift));
}
}
pub fn prepare_text_nodes(doc: &mut Document, opt: &Options) {
sanitize_text(doc.root(), doc);
prepare_baseline_shift(doc, opt);
// Resolve rotation for each character before any preprocessing,
// because rotate angles depend on text children tree structure.
{
......@@ -53,6 +148,20 @@ pub fn prepare_text_nodes(doc: &mut Document) {
}
}
// Removes `text` inside `text`, since it should be ignored.
fn sanitize_text(parent: Node, doc: &mut Document) {
for node in parent.children() {
if node.is_tag_name(EId::Text) {
doc.drain(node, |n| n.is_tag_name(EId::Text));
continue;
}
if node.has_children() {
sanitize_text(node, doc);
}
}
}
fn resolve_rotate(parent: &Node, mut offset: usize, list: &mut Vec<f64>) {
for child in parent.children() {
if child.is_text() {
......
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use super::prelude::*;
// <g fill="red" text-decoration="underline">
// <g fill="blue" text-decoration="overline">
// <text fill="green" text-decoration="line-through">Text</text>
// </g>
// </g>
//
// In this example 'text' element will have all decorators enabled, but color
// will be green for all of them.
//
// There is no simpler way to express 'text-decoration' property
// without groups than collect all the options to the string.
// It's not by the SVG spec, but easier than keeping all the groups.
pub fn prepare_text_decoration(doc: &mut Document) {
for mut node in doc.root().descendants().filter(|n| n.is_tag_name(EId::Text)) {
let mut td = String::new();
if has_attr(&node, "underline") {
td.push_str("underline;");
}
if has_attr(&node, "overline") {
td.push_str("overline;");
}
if has_attr(&node, "line-through") {
td.push_str("line-through;");
}
if !td.is_empty() {
td.pop();
node.set_attribute((AId::TextDecoration, td));
}
}
}
fn has_attr(root: &Node, decoration_id: &str) -> bool {
for (_, node) in root.ancestors().svg() {
let attrs = node.attributes();
if let Some(text) = attrs.get_str(AId::TextDecoration) {
if text == decoration_id {
return true;
}
}
}
false
}
......@@ -178,14 +178,7 @@ pub trait GetValue {
impl GetValue for Attributes {
fn get_type<T: FromValue + ?Sized>(&self, id: AId) -> Option<&T> {
match self.get_value(id) {
Some(av) => {
FromValue::get(av)
}
None => {
None
}
}
self.get_value(id).and_then(|av| FromValue::get(av))
}
}
......@@ -199,11 +192,7 @@ impl FindAttribute for Node {
fn find_attribute<T: FromValue + Display + Clone>(&self, id: AId) -> Option<T> {
for n in self.ancestors() {
if n.has_attribute(id) {
let v = FromValue::get(n.attributes().get_value(id).unwrap()).cloned();
return match v {
Some(v) => Some(v),
None => None,
};
return FromValue::get(n.attributes().get_value(id).unwrap()).cloned();
}
}
......
......@@ -672,18 +672,6 @@ pub enum FeImageKind {
}
/// A baseline shift value.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum BaselineShift {
Baseline,
Subscript,
Superscript,
Percent(f64),
Number(f64),
}
/// A path marker properties.
#[derive(Clone, Debug)]
pub struct PathMarker {
......
......@@ -395,7 +395,8 @@ fn conv_elements(
conv_fill(tree, &tspan.fill, defs, parent, &mut tspan_elem);
conv_stroke(tree, &tspan.stroke, defs, &mut tspan_elem);
conv_font(&tspan.font, &mut tspan_elem);
conv_baseline_shift(tspan.baseline_shift, &mut tspan_elem);
tspan_elem.set_attribute((AId::BaselineShift, tspan.baseline_shift));
if tspan.text.contains(" ") {
is_preserve_required = true;
......@@ -589,21 +590,6 @@ fn conv_font(
conv_text_spacing(font.word_spacing, AId::WordSpacing, node);
}
fn conv_baseline_shift(
baseline_shift: BaselineShift,
node: &mut svgdom::Node,
) {
let av: AValue = match baseline_shift {
BaselineShift::Baseline => "baseline".into(),
BaselineShift::Subscript => "sub".into(),
BaselineShift::Superscript => "super".into(),
BaselineShift::Percent(n) => svgdom::Length::new(n, svgdom::LengthUnit::Percent).into(),
BaselineShift::Number(n) => n.into(),
};
node.set_attribute((AId::BaselineShift, av));
}
fn conv_text_spacing(
spacing: Option<f64>,
aid: AId,
......
......@@ -196,7 +196,7 @@ pub struct TextSpan {
pub font: Font,
/// Baseline shift.
pub baseline_shift: BaselineShift,
pub baseline_shift: f64,
/// Text decoration.
///
......
a-baseline-shift-002,637
a-baseline-shift-003,547
a-baseline-shift-010,634
a-baseline-shift-011,1113
a-baseline-shift-012,547
a-baseline-shift-013,1397
a-baseline-shift-014,3787
a-baseline-shift-016,3794
a-baseline-shift-019,1755
a-baseline-shift-020,737
a-baseline-shift-021,1105
a-display-002,25284,chrome bug
a-display-003,25284,chrome bug
a-display-004,31852,chrome bug
......@@ -165,11 +176,15 @@ e-symbol-006,58
e-text-016,1551,chrome uses different coefficients
e-text-032,552,unsupported #4
e-text-033,361,unsupported #4
e-text-038,1959,chrome bug
e-tref-001,2005,chrome bug
e-tref-002,1189,chrome bug
e-tref-002,1180,chrome bug
e-tref-005,2005,chrome bug
e-tref-006,25,bug
e-tref-007,2005,chrome bug
e-tref-008,720,bug
e-tspan-015,3283,bug
e-tspan-018,280,chrome bug
e-tspan-020,1989,chrome bug
e-tspan-021,2005,chrome bug
e-tspan-022,6588,chrome bug
This diff is collapsed.
......@@ -429,7 +429,7 @@ test!(preserve_id, false,
fill-opacity='1'
fill-rule='nonzero'
stroke='none'
baseline-shift='baseline'
baseline-shift='0'
font-family='Times New Roman'
font-size='12'
font-stretch='normal'
......@@ -446,7 +446,7 @@ test!(preserve_id, false,
fill-opacity='1'
fill-rule='nonzero'
stroke='none'
baseline-shift='baseline'
baseline-shift='0'
font-family='Times New Roman'
font-size='12'
font-stretch='normal'
......