Skip to content
This repository was archived by the owner on Oct 30, 2021. It is now read-only.

Commit 8719352

Browse files
committedMay 16, 2017
Added --coordinates-precision and --transform-precision.
1 parent 07cdc3f commit 8719352

15 files changed

+163
-34
lines changed
 

‎CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212
- `--no-defaults`.
1313
- `--apply-transform-to-paths`.
1414
- `--allow-bigger-file`.
15+
- `--coordinates-precision`.
16+
- `--transform-precision`.
1517
- Better groups with transforms ungrouping.
1618
- `--remove-text-attributes` removes `line-height` and `xml:space` now.
1719
- Some algorithms are moved to the `svgdom` crate.

‎FAQ.md

-26
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,6 @@ can impact rendering.
2020

2121
Yes. But those elements don't impact rendering.
2222

23-
## Can you add an option to specify numeric precision?
24-
25-
No. It was a difficult decision, but it's hard to implement numeric rounding in a lossless way.
26-
27-
However, previous versions of the *svgcleaner* did have this option, as well as other SVG cleaning applications.
28-
And it's actually pretty good for size reduction. But usually, it's just a straightforward
29-
number rounding without a context, which is very dangerous in some cases.
30-
31-
**Here's one example:**
32-
33-
Let's take a very small rect:
34-
```svg
35-
<rect height="0.0001" width="0.0001"/>
36-
```
37-
It's obvious that it will not be rendered. With a small precision, it will have a size of zero and
38-
can even be removed completely. That's how non-contextual rounding works.
39-
40-
But what if it actually looks like this?:
41-
```svg
42-
<rect height="0.0001" width="0.0001" transform="scale(100000)"/>
43-
```
44-
45-
Well, in this case, we just broke an image. And there are lots of examples like this.
46-
47-
This option will be added only in the case that I find a way to prove every image will be unchanged.
48-
4923
## Why is it so fast?
5024

5125
It's not. *svgcleaner* could be many times faster, but it's not a current priority.

‎data/help.txt

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ Paths:
8181
Output:
8282
--trim-colors <FLAG> Use #RGB notation [default: yes]
8383
--simplify-transforms <FLAG> Simplify transform matrices [default: yes]
84+
--coordinates-precision <NUM> Set coordinates numeric precision (1..12) [default: 6]
85+
--transform-precision <NUM> Set transform values numeric precision (1..12) [default: 8]
8486
--paths-coordinates-precision <NUM> Set path's coordinates numeric precision (1..12) [default: 8]
8587
--indent <INDENT> Set XML nodes indent [values: none, 0, 1, 2, 3, 4, tabs] [default: none]
8688

‎docs/src/coordinates-precision.rst

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Set coordinates numeric precision
2+
---------------------------------
3+
4+
Reduce the numeric precision of the specific coordinate attributes.
5+
6+
This includes: x, y, dx, dy, x1, y1, x2, y2, r, rx, ry, cx, cy, fx, fy, width, height,
7+
and translate part of transforms.
8+
9+
Range: 1..12
10+
11+
Default: 6

‎docs/src/order.txt

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ use-implicit-cmds.rst
4545
-- Output
4646
trim-colors.rst
4747
simplify-transforms.rst
48+
coordinates-precision.rst
49+
transform-precision.rst
4850
paths-coordinates-precision.rst
4951
indent.rst
5052
-- Other

‎docs/src/transform-precision.rst

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Set transforms values numeric precision
2+
---------------------------------------
3+
4+
Set numeric precision of the a, b, c, d values of transforms.
5+
6+
Range: 1..12
7+
8+
Default: 8

‎src/cleaner.rs

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub fn clean_doc(doc: &Document, options: &Options, opt: &WriteOptions)
7373
// Do not remove any attributes before this methods
7474
// since they uses them.
7575

76+
round_coordinates(doc, options);
77+
7678
// Independent task, doesn't impact any other tasks..
7779
if options.remove_title {
7880
remove_element(doc, ElementId::Title);

‎src/cli.rs

+17
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub enum Key {
9090

9191
TrimColors,
9292
SimplifyTransforms,
93+
CoordinatesPrecision,
94+
TransformPrecision,
9395
PathsCoordinatesPrecision,
9496
Indent,
9597

@@ -158,6 +160,8 @@ pub static KEYS: &'static KeysData<'static> = &KeysData(&[
158160

159161
"trim-colors",
160162
"simplify-transforms",
163+
"coordinates-precision",
164+
"transform-precision",
161165
"paths-coordinates-precision",
162166
"indent",
163167

@@ -264,6 +268,16 @@ pub fn prepare_app<'a, 'b>() -> App<'a, 'b> {
264268
// output
265269
.arg(gen_flag!(Key::TrimColors, "true"))
266270
.arg(gen_flag!(Key::SimplifyTransforms, "true"))
271+
.arg(Arg::with_name(KEYS[Key::CoordinatesPrecision])
272+
.long(KEYS[Key::CoordinatesPrecision])
273+
.value_name("NUM")
274+
.validator(is_precision)
275+
.default_value("6"))
276+
.arg(Arg::with_name(KEYS[Key::TransformPrecision])
277+
.long(KEYS[Key::TransformPrecision])
278+
.value_name("NUM")
279+
.validator(is_precision)
280+
.default_value("8"))
267281
.arg(Arg::with_name(KEYS[Key::PathsCoordinatesPrecision])
268282
.long(KEYS[Key::PathsCoordinatesPrecision])
269283
.value_name("NUM")
@@ -506,6 +520,9 @@ pub fn gen_cleaning_options(args: &ArgMatches) -> Options {
506520
flags.resolve(&mut opt.convert_segments, Key::ConvertSegments);
507521
flags.resolve(&mut opt.apply_transform_to_paths, Key::ApplyTransformToPaths);
508522

523+
opt.coordinates_precision = value_t!(args, KEYS[Key::CoordinatesPrecision], u8).unwrap();
524+
opt.transform_precision = value_t!(args, KEYS[Key::TransformPrecision], u8).unwrap();
525+
509526
opt
510527
}
511528

‎src/options.rs

+8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ pub struct Options {
6363
pub remove_unused_segments: bool,
6464
pub convert_segments: bool,
6565
pub apply_transform_to_paths: bool,
66+
67+
// 1..12
68+
pub coordinates_precision: u8,
69+
// 1..12
70+
pub transform_precision: u8,
6671
}
6772

6873
// Should all be 'false'.
@@ -103,6 +108,9 @@ impl Default for Options {
103108
remove_unused_segments: false,
104109
convert_segments: false,
105110
apply_transform_to_paths: false,
111+
112+
coordinates_precision: 6,
113+
transform_precision: 8,
106114
}
107115
}
108116
}

‎src/task/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub use self::rm_version::remove_version;
5252
pub use self::trim_ids::trim_ids;
5353
pub use self::ungroup_defs::ungroup_defs;
5454
pub use self::ungroup_groups::ungroup_groups;
55+
pub use self::round_coords::round_coordinates;
5556

5657
#[macro_use] mod macros;
5758
mod conv_shapes;
@@ -79,6 +80,7 @@ mod rm_version;
7980
mod trim_ids;
8081
mod ungroup_defs;
8182
mod ungroup_groups;
83+
mod round_coords;
8284
pub mod apply_transforms;
8385
pub mod paths;
8486

‎src/task/round_coords.rs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/****************************************************************************
2+
**
3+
** svgcleaner could help you to clean up your SVG files
4+
** from unnecessary data.
5+
** Copyright (C) 2012-2017 Evgeniy Reizner
6+
**
7+
** This program is free software; you can redistribute it and/or modify
8+
** it under the terms of the GNU General Public License as published by
9+
** the Free Software Foundation; either version 2 of the License, or
10+
** (at your option) any later version.
11+
**
12+
** This program is distributed in the hope that it will be useful,
13+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
** GNU General Public License for more details.
16+
**
17+
** You should have received a copy of the GNU General Public License along
18+
** with this program; if not, write to the Free Software Foundation, Inc.,
19+
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20+
**
21+
****************************************************************************/
22+
23+
use super::short::AId;
24+
25+
use svgdom::{Document, AttributeValue};
26+
27+
use options::Options;
28+
29+
static POW_VEC: &'static [f64] = &[
30+
0.0,
31+
10.0,
32+
100.0,
33+
1_000.0,
34+
10_000.0,
35+
100_000.0,
36+
1_000_000.0,
37+
10_000_000.0,
38+
100_000_000.0,
39+
1_000_000_000.0,
40+
10_000_000_000.0,
41+
100_000_000_000.0,
42+
1_000_000_000_000.0,
43+
];
44+
45+
pub fn round_coordinates(doc: &Document, options: &Options) {
46+
let coord_precision = options.coordinates_precision as usize;
47+
let ts_precision = options.transform_precision as usize;
48+
49+
for node in doc.descendants().svg() {
50+
let mut attrs = node.attributes_mut();
51+
52+
for (aid, ref mut attr) in attrs.iter_svg_mut() {
53+
match aid {
54+
AId::X | AId::Y |
55+
AId::Dx | AId::Dy |
56+
AId::X1 | AId::Y1 |
57+
AId::X2 | AId::Y2 |
58+
AId::R |
59+
AId::Rx | AId::Ry |
60+
AId::Cx | AId::Cy |
61+
AId::Fx | AId::Fy |
62+
AId::Width | AId::Height => {
63+
match attr.value {
64+
AttributeValue::Length(ref mut v) => {
65+
round_number(&mut v.num, coord_precision);
66+
}
67+
_ => {}
68+
}
69+
}
70+
AId::Transform |
71+
AId::GradientTransform |
72+
AId::PatternTransform => {
73+
match attr.value {
74+
AttributeValue::Transform(ref mut ts) => {
75+
round_number(&mut ts.a, ts_precision);
76+
round_number(&mut ts.b, ts_precision);
77+
round_number(&mut ts.c, ts_precision);
78+
round_number(&mut ts.d, ts_precision);
79+
round_number(&mut ts.e, coord_precision);
80+
round_number(&mut ts.f, coord_precision);
81+
}
82+
_ => {}
83+
}
84+
}
85+
_ => {}
86+
}
87+
}
88+
}
89+
}
90+
91+
fn round_number(n: &mut f64, precision: usize) {
92+
*n = (*n * POW_VEC[precision]).round() / POW_VEC[precision];
93+
}

‎tools/files-testing/data/oxygen.json

+13-5
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@
528528
},
529529
{
530530
"name": "actions/small/22x22/edit-image-face-recognize.svg",
531-
"valid_ae": 1235
531+
"valid_ae": 1398
532532
},
533533
{
534534
"name": "actions/small/48x48/view-bank-account.svg",
@@ -697,7 +697,7 @@
697697
},
698698
{
699699
"name": "actions/small/22x22/edit-image-face-add.svg",
700-
"valid_ae": 1151
700+
"valid_ae": 1152
701701
},
702702
{
703703
"info": "webkit bug",
@@ -716,11 +716,11 @@
716716
},
717717
{
718718
"name": "actions/small/48x48/mail-encrypted-full.svg",
719-
"valid_ae": 4957
719+
"valid_ae": 4958
720720
},
721721
{
722722
"name": "actions/small/48x48/mail-encrypted.svg",
723-
"valid_ae": 5022
723+
"valid_ae": 5023
724724
},
725725
{
726726
"name": "actions/small/48x48/mail-message-new-list.svg",
@@ -798,7 +798,7 @@
798798
},
799799
{
800800
"name": "apps/kuickshow.svg",
801-
"valid_ae": 555
801+
"valid_ae": 569
802802
},
803803
{
804804
"name": "mimetypes/hidef/application-x-kcsrc.svg",
@@ -867,6 +867,14 @@
867867
{
868868
"name": "mimetypes/application-x-kcsrc.svg",
869869
"valid_ae": 855
870+
},
871+
{
872+
"name": "actions/small/22x22/edit-image-face-detect.svg",
873+
"valid_ae": 887
874+
},
875+
{
876+
"name": "devices/small/22x22/multimedia-player-apple-ipod.svg",
877+
"valid_ae": 690
870878
}
871879
],
872880
"ignore": [

‎tools/files-testing/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn main() {
101101
return;
102102
}
103103

104-
let svgcleaner_path = Path::new("../../target/debug/svgcleaner");
104+
let svgcleaner_path = Path::new("../../target/release/svgcleaner");
105105
if !svgcleaner_path.exists() {
106106
println!("Error: {:?} not found.", svgcleaner_path);
107107
return;

‎tools/stats/data/ratio_chart_W3C_SVG_11_TestSuite.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"items": [
88
{
99
"name": "svgcleaner 0.8.1",
10-
"value": 32.84
10+
"value": 32.87
1111
},
1212
{
1313
"name": "svgcleaner 0.8.0",

‎tools/stats/data/ratio_chart_oxygen.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"items": [
88
{
99
"name": "svgcleaner 0.8.1",
10-
"value": 61.15
10+
"value": 61.19
1111
},
1212
{
1313
"name": "svgcleaner 0.8.0",

0 commit comments

Comments
 (0)
This repository has been archived.