prawn-svg 0.29.1 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +6 -5
- data/lib/prawn-svg.rb +4 -0
- data/lib/prawn/svg/attributes/opacity.rb +4 -4
- data/lib/prawn/svg/attributes/transform.rb +2 -44
- data/lib/prawn/svg/elements.rb +1 -0
- data/lib/prawn/svg/elements/base.rb +2 -0
- data/lib/prawn/svg/elements/gradient.rb +6 -5
- data/lib/prawn/svg/elements/path.rb +1 -0
- data/lib/prawn/svg/elements/text_component.rb +15 -1
- data/lib/prawn/svg/extensions/additional_gradient_transforms.rb +23 -0
- data/lib/prawn/svg/interface.rb +13 -0
- data/lib/prawn/svg/loaders/data.rb +1 -1
- data/lib/prawn/svg/loaders/file.rb +3 -1
- data/lib/prawn/svg/transform_parser.rb +72 -0
- data/lib/prawn/svg/version.rb +1 -1
- data/spec/prawn/svg/attributes/opacity_spec.rb +85 -0
- data/spec/prawn/svg/attributes/transform_spec.rb +30 -35
- data/spec/prawn/svg/elements/base_spec.rb +2 -2
- data/spec/prawn/svg/elements/gradient_spec.rb +26 -2
- data/spec/prawn/svg/loaders/data_spec.rb +8 -0
- data/spec/prawn/svg/transform_parser_spec.rb +94 -0
- data/spec/sample_svg/double_opacity.svg +6 -0
- data/spec/sample_svg/gradient_transform.svg +19 -0
- data/spec/sample_svg/links.svg +18 -0
- data/spec/sample_svg/transform.svg +20 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34f48795bbd6ee32d7c18228b833137dc52cb5b02f0446de0e3908d0827e7234
|
4
|
+
data.tar.gz: 4f654b0c484f81ba80660940d2823c836c0aaba0156cb9e803c722170fdec993
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bf2b53a65607c75da3907433b40e1f4aaee67a70268f562a3f6c554087ab7a66924874befc1da5a6954b86b71f0e32ab6bff5108f64f3582b677500dc0a2f8b
|
7
|
+
data.tar.gz: 25d862c9b5b6e25a3dc22ac581c2e04c025ff76b3f842033578f2565d8641f2a951d03e0a88c272e52f584c87fb27a2af90593ae6aea8d69c80ec4ec06d0b36a
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -60,7 +60,7 @@ prawn-svg supports most but not all of the full SVG 1.1 specification. It curre
|
|
60
60
|
- <tt><path></tt> supports all commands defined in SVG 1.1, although the
|
61
61
|
implementation of elliptical arc is a bit rough at the moment.
|
62
62
|
|
63
|
-
- `<text>`, `<tspan>` and `<tref>` with attributes `x`, `y`, `dx`, `dy`, `rotate`, and with extra properties
|
63
|
+
- `<text>`, `<tspan>` and `<tref>` with attributes `x`, `y`, `dx`, `dy`, `rotate`, 'textLength', 'lengthAdjust', and with extra properties
|
64
64
|
`text-anchor`, `font-size`, `font-family`, `font-weight`, `font-style`, `letter-spacing`
|
65
65
|
|
66
66
|
- <tt><svg></tt>, <tt><g></tt> and <tt><symbol></tt>
|
@@ -76,7 +76,7 @@ prawn-svg supports most but not all of the full SVG 1.1 specification. It curre
|
|
76
76
|
|
77
77
|
- `<marker>`
|
78
78
|
|
79
|
-
- `<linearGradient>` is implemented
|
79
|
+
- `<linearGradient>` is implemented on Prawn 2.2.0+ with attributes `gradientUnits` and `gradientTransform` (spreadMethod and stop-opacity are unimplemented.)
|
80
80
|
|
81
81
|
- `<switch>` and `<foreignObject>`, although prawn-svg cannot handle any data that is not SVG so `<foreignObject>`
|
82
82
|
tags are always ignored.
|
@@ -91,7 +91,7 @@ prawn-svg supports most but not all of the full SVG 1.1 specification. It curre
|
|
91
91
|
|
92
92
|
- the <tt>preserveAspectRatio</tt> attribute on <tt><svg></tt>, <tt><image></tt> and `<marker>` elements
|
93
93
|
|
94
|
-
- transform methods:
|
94
|
+
- transform methods: `translate`, `translateX`, `translateY`, `rotate`, `scale`, `skewX`, `skewY`, `matrix`
|
95
95
|
|
96
96
|
- colors: HTML standard names, <tt>#xxx</tt>, <tt>#xxxxxx</tt>, <tt>rgb(1, 2, 3)</tt>, <tt>rgb(1%, 2%, 3%)</tt>
|
97
97
|
|
@@ -135,5 +135,6 @@ Mac OS X and Debian Linux users. You can add to the font path:
|
|
135
135
|
|
136
136
|
In your Gemfile, put `gem 'prawn-svg'` before `gem 'prawn-rails'` so that prawn-rails can see the prawn-svg extension.
|
137
137
|
|
138
|
-
|
139
|
-
|
138
|
+
## Licence
|
139
|
+
|
140
|
+
MIT licence. Copyright Roger Nesbitt.
|
data/lib/prawn-svg.rb
CHANGED
@@ -10,6 +10,7 @@ require 'prawn/svg/calculators/arc_to_bezier_curve'
|
|
10
10
|
require 'prawn/svg/calculators/aspect_ratio'
|
11
11
|
require 'prawn/svg/calculators/document_sizing'
|
12
12
|
require 'prawn/svg/calculators/pixels'
|
13
|
+
require 'prawn/svg/transform_parser'
|
13
14
|
require 'prawn/svg/url_loader'
|
14
15
|
require 'prawn/svg/loaders/data'
|
15
16
|
require 'prawn/svg/loaders/file'
|
@@ -29,6 +30,9 @@ require 'prawn/svg/font'
|
|
29
30
|
require 'prawn/svg/document'
|
30
31
|
require 'prawn/svg/state'
|
31
32
|
|
33
|
+
require 'prawn/svg/extensions/additional_gradient_transforms'
|
34
|
+
Prawn::Document.prepend Prawn::SVG::Extensions::AdditionalGradientTransforms
|
35
|
+
|
32
36
|
module Prawn
|
33
37
|
Svg = SVG # backwards compatibility
|
34
38
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Prawn::SVG::Attributes::Opacity
|
2
2
|
def parse_opacity_attributes_and_call
|
3
3
|
# We can't do nested opacities quite like the SVG requires, but this is close enough.
|
4
|
-
|
4
|
+
opacity = clamp(properties.opacity.to_f, 0, 1) if properties.opacity
|
5
5
|
fill_opacity = clamp(properties.fill_opacity.to_f, 0, 1) if properties.fill_opacity
|
6
6
|
stroke_opacity = clamp(properties.stroke_opacity.to_f, 0, 1) if properties.stroke_opacity
|
7
7
|
|
8
|
-
if fill_opacity || stroke_opacity
|
9
|
-
state.fill_opacity *= fill_opacity || 1
|
10
|
-
state.stroke_opacity *= stroke_opacity || 1
|
8
|
+
if opacity || fill_opacity || stroke_opacity
|
9
|
+
state.fill_opacity *= [opacity || 1, fill_opacity || 1].min
|
10
|
+
state.stroke_opacity *= [opacity || 1, stroke_opacity || 1].min
|
11
11
|
|
12
12
|
add_call_and_enter 'transparent', state.fill_opacity, state.stroke_opacity
|
13
13
|
end
|
@@ -2,49 +2,7 @@ module Prawn::SVG::Attributes::Transform
|
|
2
2
|
def parse_transform_attribute_and_call
|
3
3
|
return unless transform = attributes['transform']
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
when 'translate'
|
8
|
-
x, y = arguments
|
9
|
-
add_call_and_enter name, x_pixels(x.to_f), -y_pixels(y.to_f)
|
10
|
-
|
11
|
-
when 'rotate'
|
12
|
-
r, x, y = arguments.collect {|a| a.to_f}
|
13
|
-
case arguments.length
|
14
|
-
when 1
|
15
|
-
add_call_and_enter name, -r, :origin => [0, y('0')]
|
16
|
-
when 3
|
17
|
-
add_call_and_enter name, -r, :origin => [x(x), y(y)]
|
18
|
-
else
|
19
|
-
warnings << "transform 'rotate' must have either one or three arguments"
|
20
|
-
end
|
21
|
-
|
22
|
-
when 'scale'
|
23
|
-
x_scale = arguments[0].to_f
|
24
|
-
y_scale = (arguments[1] || x_scale).to_f
|
25
|
-
add_call_and_enter "transformation_matrix", x_scale, 0, 0, y_scale, 0, 0
|
26
|
-
|
27
|
-
when 'matrix'
|
28
|
-
if arguments.length != 6
|
29
|
-
warnings << "transform 'matrix' must have six arguments"
|
30
|
-
else
|
31
|
-
a, b, c, d, e, f = arguments.collect {|argument| argument.to_f}
|
32
|
-
add_call_and_enter "transformation_matrix", a, -b, -c, d, x_pixels(e), -y_pixels(f)
|
33
|
-
end
|
34
|
-
|
35
|
-
else
|
36
|
-
warnings << "Unknown transformation '#{name}'; ignoring"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def parse_css_method_calls(string)
|
44
|
-
string.scan(/\s*(\w+)\(([^)]+)\)\s*/).collect do |call|
|
45
|
-
name, argument_string = call
|
46
|
-
arguments = argument_string.strip.split(/\s*[,\s]\s*/)
|
47
|
-
[name, arguments]
|
48
|
-
end
|
5
|
+
matrix = parse_transform_attribute(transform)
|
6
|
+
add_call_and_enter "transformation_matrix", *matrix unless matrix == [1, 0, 0, 1, 0, 0]
|
49
7
|
end
|
50
8
|
end
|
data/lib/prawn/svg/elements.rb
CHANGED
@@ -13,6 +13,7 @@ module Prawn::SVG::Elements
|
|
13
13
|
g: Prawn::SVG::Elements::Container,
|
14
14
|
symbol: Prawn::SVG::Elements::Container,
|
15
15
|
defs: Prawn::SVG::Elements::Container,
|
16
|
+
a: Prawn::SVG::Elements::Container,
|
16
17
|
clipPath: Prawn::SVG::Elements::ClipPath,
|
17
18
|
switch: Prawn::SVG::Elements::Container,
|
18
19
|
svg: Prawn::SVG::Elements::Viewport,
|
@@ -11,6 +11,8 @@ class Prawn::SVG::Elements::Base
|
|
11
11
|
include Prawn::SVG::Attributes::Stroke
|
12
12
|
include Prawn::SVG::Attributes::Space
|
13
13
|
|
14
|
+
include Prawn::SVG::TransformParser
|
15
|
+
|
14
16
|
PAINT_TYPES = %w(fill stroke)
|
15
17
|
COMMA_WSP_REGEXP = Prawn::SVG::Elements::COMMA_WSP_REGEXP
|
16
18
|
SVG_NAMESPACE = "http://www.w3.org/2000/svg"
|
@@ -32,7 +32,11 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
|
|
32
32
|
to = [@x2, @y2]
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
# Passing in a transformation matrix to the apply_transformations option is supported
|
36
|
+
# by a monkey patch installed by prawn-svg. Prawn only sees this as a truthy variable.
|
37
|
+
#
|
38
|
+
# See Prawn::SVG::Extensions::AdditionalGradientTransforms for details.
|
39
|
+
{from: from, to: to, stops: @stops, apply_transformations: @transform_matrix || true}
|
36
40
|
end
|
37
41
|
|
38
42
|
private
|
@@ -51,10 +55,7 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
|
|
51
55
|
@units = attributes["gradientUnits"] == 'userSpaceOnUse' ? :user_space : :bounding_box
|
52
56
|
|
53
57
|
if transform = attributes["gradientTransform"]
|
54
|
-
|
55
|
-
if matrix != [1, 0, 0, 1, 0, 0]
|
56
|
-
raise SkipElementError, "prawn-svg does not yet support gradients with a non-identity gradientTransform attribute"
|
57
|
-
end
|
58
|
+
@transform_matrix = parse_transform_attribute(transform)
|
58
59
|
end
|
59
60
|
|
60
61
|
if (spread_method = attributes['spreadMethod']) && spread_method != "pad"
|
@@ -2,7 +2,7 @@ class Prawn::SVG::Elements::TextComponent < Prawn::SVG::Elements::DepthFirstBase
|
|
2
2
|
attr_reader :commands
|
3
3
|
|
4
4
|
Printable = Struct.new(:element, :text, :leading_space?, :trailing_space?)
|
5
|
-
TextState = Struct.new(:parent, :x, :y, :dx, :dy, :rotation, :spacing, :mode)
|
5
|
+
TextState = Struct.new(:parent, :x, :y, :dx, :dy, :rotation, :spacing, :mode, :text_length, :length_adjust)
|
6
6
|
|
7
7
|
def parse
|
8
8
|
if state.inside_clip_path
|
@@ -14,6 +14,8 @@ class Prawn::SVG::Elements::TextComponent < Prawn::SVG::Elements::DepthFirstBase
|
|
14
14
|
state.text.dx = (attributes['dx'] || "").split(COMMA_WSP_REGEXP).collect { |n| x_pixels(n) }
|
15
15
|
state.text.dy = (attributes['dy'] || "").split(COMMA_WSP_REGEXP).collect { |n| y_pixels(n) }
|
16
16
|
state.text.rotation = (attributes['rotate'] || "").split(COMMA_WSP_REGEXP).collect(&:to_f)
|
17
|
+
state.text.text_length = normalize_length(attributes['textLength'])
|
18
|
+
state.text.length_adjust = attributes['lengthAdjust']
|
17
19
|
state.text.spacing = calculate_character_spacing
|
18
20
|
state.text.mode = calculate_text_rendering_mode
|
19
21
|
|
@@ -133,6 +135,14 @@ class Prawn::SVG::Elements::TextComponent < Prawn::SVG::Elements::DepthFirstBase
|
|
133
135
|
opts.delete(:rotate)
|
134
136
|
end
|
135
137
|
|
138
|
+
if state.text.text_length
|
139
|
+
if state.text.length_adjust == 'spacingAndGlyphs'
|
140
|
+
opts[:stretch_to_width] = state.text.text_length
|
141
|
+
else
|
142
|
+
opts[:pad_to_width] = state.text.text_length
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
136
146
|
if remaining
|
137
147
|
add_call 'draw_text', text[0..0], opts.dup
|
138
148
|
text = text[1..-1]
|
@@ -222,4 +232,8 @@ class Prawn::SVG::Elements::TextComponent < Prawn::SVG::Elements::DepthFirstBase
|
|
222
232
|
# overridden, we don't want to call fill/stroke as draw_text does this for us
|
223
233
|
def apply_drawing_call
|
224
234
|
end
|
235
|
+
|
236
|
+
def normalize_length(length)
|
237
|
+
x_pixels(length) if length && length.match(/\d/)
|
238
|
+
end
|
225
239
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Prawn::SVG::Extensions
|
2
|
+
module AdditionalGradientTransforms
|
3
|
+
def gradient_coordinates(gradient)
|
4
|
+
# As of Prawn 2.2.0, apply_transformations is used as purely a boolean.
|
5
|
+
#
|
6
|
+
# Here we're using it to optionally pass in a 6-tuple transformation matrix that gets applied to the
|
7
|
+
# gradient. This should be added to Prawn properly, and then this monkey patch will not be necessary.
|
8
|
+
|
9
|
+
if gradient.apply_transformations.is_a?(Array)
|
10
|
+
x1, y1, x2, y2, transformation = super
|
11
|
+
a, b, c, d, e, f = transformation
|
12
|
+
na, nb, nc, nd, ne, nf = gradient.apply_transformations
|
13
|
+
|
14
|
+
matrix = Matrix[[a, c, e], [b, d, f], [0, 0, 1]] * Matrix[[na, nc, ne], [nb, nd, nf], [0, 0, 1]]
|
15
|
+
new_transformation = matrix.to_a[0..1].transpose.flatten
|
16
|
+
|
17
|
+
[x1, y1, x2, y2, new_transformation]
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/prawn/svg/interface.rb
CHANGED
@@ -148,6 +148,19 @@ module Prawn
|
|
148
148
|
|
149
149
|
width = prawn.width_of(text, options.merge(kerning: true))
|
150
150
|
|
151
|
+
if stretch_to_width = options.delete(:stretch_to_width)
|
152
|
+
factor = stretch_to_width.to_f * 100 / width.to_f
|
153
|
+
prawn.add_content "#{factor} Tz"
|
154
|
+
width = stretch_to_width.to_f
|
155
|
+
end
|
156
|
+
|
157
|
+
if pad_to_width = options.delete(:pad_to_width)
|
158
|
+
padding_required = pad_to_width.to_f - width.to_f
|
159
|
+
padding_per_character = padding_required / text.length.to_f
|
160
|
+
prawn.add_content "#{padding_per_character} Tc"
|
161
|
+
width = pad_to_width.to_f
|
162
|
+
end
|
163
|
+
|
151
164
|
case options.delete(:text_anchor)
|
152
165
|
when 'middle'
|
153
166
|
at[0] -= width / 2
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
1
3
|
#
|
2
4
|
# Load a file from disk.
|
3
5
|
#
|
@@ -56,7 +58,7 @@ module Prawn::SVG::Loaders
|
|
56
58
|
private
|
57
59
|
|
58
60
|
def load_file(path)
|
59
|
-
path = URI.
|
61
|
+
path = Addressable::URI.unencode(path)
|
60
62
|
path = build_absolute_and_expand_path(path)
|
61
63
|
assert_valid_path!(path)
|
62
64
|
assert_file_exists!(path)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Prawn::SVG::TransformParser
|
2
|
+
def parse_transform_attribute(transform)
|
3
|
+
matrix = Matrix.identity(3)
|
4
|
+
|
5
|
+
parse_css_method_calls(transform).each do |name, arguments|
|
6
|
+
case name
|
7
|
+
when 'translate'
|
8
|
+
x, y = arguments
|
9
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
10
|
+
|
11
|
+
when 'translateX'
|
12
|
+
x = arguments.first
|
13
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, 0], [0, 0, 1]]
|
14
|
+
|
15
|
+
when 'translateY'
|
16
|
+
y = arguments.first
|
17
|
+
matrix *= Matrix[[1, 0, 0], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
18
|
+
|
19
|
+
when 'rotate'
|
20
|
+
angle, x, y = arguments.collect { |a| a.to_f }
|
21
|
+
angle = angle * Math::PI / 180.0
|
22
|
+
|
23
|
+
case arguments.length
|
24
|
+
when 1
|
25
|
+
matrix *= Matrix[[Math.cos(angle), Math.sin(angle), 0], [-Math.sin(angle), Math.cos(angle), 0], [0, 0, 1]]
|
26
|
+
when 3
|
27
|
+
matrix *= Matrix[[1, 0, x_pixels(x.to_f)], [0, 1, -y_pixels(y.to_f)], [0, 0, 1]]
|
28
|
+
matrix *= Matrix[[Math.cos(angle), Math.sin(angle), 0], [-Math.sin(angle), Math.cos(angle), 0], [0, 0, 1]]
|
29
|
+
matrix *= Matrix[[1, 0, -x_pixels(x.to_f)], [0, 1, y_pixels(y.to_f)], [0, 0, 1]]
|
30
|
+
else
|
31
|
+
warnings << "transform 'rotate' must have either one or three arguments"
|
32
|
+
end
|
33
|
+
|
34
|
+
when 'scale'
|
35
|
+
x_scale = arguments[0].to_f
|
36
|
+
y_scale = (arguments[1] || x_scale).to_f
|
37
|
+
matrix *= Matrix[[x_scale, 0, 0], [0, y_scale, 0], [0, 0, 1]]
|
38
|
+
|
39
|
+
when 'skewX'
|
40
|
+
angle = arguments[0].to_f * Math::PI / 180.0
|
41
|
+
matrix *= Matrix[[1, -Math.tan(angle), 0], [0, 1, 0], [0, 0, 1]]
|
42
|
+
|
43
|
+
when 'skewY'
|
44
|
+
angle = arguments[0].to_f * Math::PI / 180.0
|
45
|
+
matrix *= Matrix[[1, 0, 0], [-Math.tan(angle), 1, 0], [0, 0, 1]]
|
46
|
+
|
47
|
+
when 'matrix'
|
48
|
+
if arguments.length != 6
|
49
|
+
warnings << "transform 'matrix' must have six arguments"
|
50
|
+
else
|
51
|
+
a, b, c, d, e, f = arguments.collect { |argument| argument.to_f }
|
52
|
+
matrix *= Matrix[[a, -c, e], [-b, d, -f], [0, 0, 1]]
|
53
|
+
end
|
54
|
+
|
55
|
+
else
|
56
|
+
warnings << "Unknown/unsupported transformation '#{name}'; ignoring"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
matrix.to_a[0..1].transpose.flatten
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def parse_css_method_calls(string)
|
66
|
+
string.scan(/\s*(\w+)\(([^)]+)\)\s*/).collect do |call|
|
67
|
+
name, argument_string = call
|
68
|
+
arguments = argument_string.strip.split(/\s*[,\s]\s*/)
|
69
|
+
[name, arguments]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/prawn/svg/version.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Attributes::Opacity do
|
4
|
+
class OpacityTestElement
|
5
|
+
include Prawn::SVG::Attributes::Opacity
|
6
|
+
|
7
|
+
attr_accessor :properties, :state
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@properties = ::Prawn::SVG::Properties.new
|
11
|
+
@state = ::Prawn::SVG::State.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def clamp(value, min_value, max_value)
|
15
|
+
[[value, min_value].max, max_value].min
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:element) { OpacityTestElement.new }
|
20
|
+
|
21
|
+
describe "#parse_opacity_attributes_and_call" do
|
22
|
+
subject { element.parse_opacity_attributes_and_call }
|
23
|
+
|
24
|
+
context "with no opacity specified" do
|
25
|
+
it "does nothing" do
|
26
|
+
expect(element).not_to receive(:add_call_and_enter)
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with opacity" do
|
32
|
+
it "sets fill and stroke opacity" do
|
33
|
+
element.properties.opacity = '0.4'
|
34
|
+
|
35
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 0.4)
|
36
|
+
subject
|
37
|
+
|
38
|
+
expect(element.state.fill_opacity).to eq 0.4
|
39
|
+
expect(element.state.stroke_opacity).to eq 0.4
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with just fill opacity" do
|
44
|
+
it "sets fill opacity and sets stroke opacity to 1" do
|
45
|
+
element.properties.fill_opacity = '0.4'
|
46
|
+
|
47
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 1)
|
48
|
+
subject
|
49
|
+
|
50
|
+
expect(element.state.fill_opacity).to eq 0.4
|
51
|
+
expect(element.state.stroke_opacity).to eq 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with an existing fill/stroke opacity" do
|
56
|
+
it "multiplies the new opacity by the old" do
|
57
|
+
element.state.fill_opacity = 0.5
|
58
|
+
element.state.stroke_opacity = 0.8
|
59
|
+
|
60
|
+
element.properties.fill_opacity = '0.4'
|
61
|
+
element.properties.stroke_opacity = '0.5'
|
62
|
+
|
63
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.2, 0.4)
|
64
|
+
subject
|
65
|
+
|
66
|
+
expect(element.state.fill_opacity).to eq 0.2
|
67
|
+
expect(element.state.stroke_opacity).to eq 0.4
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with stroke, fill, and opacity all specified" do
|
72
|
+
it "choses the lower of them" do
|
73
|
+
element.properties.fill_opacity = '0.4'
|
74
|
+
element.properties.stroke_opacity = '0.6'
|
75
|
+
element.properties.opacity = '0.5'
|
76
|
+
|
77
|
+
expect(element).to receive(:add_call_and_enter).with('transparent', 0.4, 0.5)
|
78
|
+
subject
|
79
|
+
|
80
|
+
expect(element.state.fill_opacity).to eq 0.4
|
81
|
+
expect(element.state.stroke_opacity).to eq 0.5
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -14,43 +14,38 @@ describe Prawn::SVG::Attributes::Transform do
|
|
14
14
|
|
15
15
|
let(:element) { TransformTestElement.new }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
subject { element.send :parse_transform_attribute_and_call }
|
18
|
+
|
19
|
+
context "when a non-identity matrix is requested" do
|
20
|
+
let(:transform) { 'translate(-5.5)' }
|
21
|
+
|
22
|
+
it "passes the transform and executes the returned matrix" do
|
23
|
+
expect(element).to receive(:parse_transform_attribute).with(transform).and_return([1, 2, 3, 4, 5, 6])
|
24
|
+
expect(element).to receive(:add_call_and_enter).with('transformation_matrix', 1, 2, 3, 4, 5, 6)
|
25
|
+
|
26
|
+
element.attributes['transform'] = transform
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when an identity matrix is requested" do
|
32
|
+
let(:transform) { 'translate(0)' }
|
33
|
+
|
34
|
+
it "does not execute any commands" do
|
35
|
+
expect(element).to receive(:parse_transform_attribute).with(transform).and_return([1, 0, 0, 1, 0, 0])
|
36
|
+
expect(element).not_to receive(:add_call_and_enter)
|
37
|
+
|
38
|
+
element.attributes['transform'] = transform
|
39
|
+
subject
|
29
40
|
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when transform is blank" do
|
44
|
+
it "does nothing" do
|
45
|
+
expect(element).not_to receive(:parse_transform_attribute)
|
46
|
+
expect(element).not_to receive(:add_call_and_enter)
|
30
47
|
|
31
|
-
|
32
|
-
it "handles a single angle argument" do
|
33
|
-
expect(element).to receive(:add_call_and_enter).with('rotate', -5.5, :origin => [0, 0])
|
34
|
-
expect(element).to receive(:y).with('0').and_return(0)
|
35
|
-
|
36
|
-
element.attributes['transform'] = 'rotate(5.5)'
|
37
|
-
subject
|
38
|
-
end
|
39
|
-
|
40
|
-
it "handles three arguments" do
|
41
|
-
expect(element).to receive(:add_call_and_enter).with('rotate', -5.5, :origin => [1.0, 2.0])
|
42
|
-
expect(element).to receive(:x).with(1.0).and_return(1.0)
|
43
|
-
expect(element).to receive(:y).with(2.0).and_return(2.0)
|
44
|
-
|
45
|
-
element.attributes['transform'] = 'rotate(5.5 1 2)'
|
46
|
-
subject
|
47
|
-
end
|
48
|
-
|
49
|
-
it "does nothing and warns if two arguments" do
|
50
|
-
expect(element).to receive(:warnings).and_return([])
|
51
|
-
element.attributes['transform'] = 'rotate(5.5 1)'
|
52
|
-
subject
|
53
|
-
end
|
48
|
+
subject
|
54
49
|
end
|
55
50
|
end
|
56
51
|
end
|
@@ -25,14 +25,14 @@ describe Prawn::SVG::Elements::Base do
|
|
25
25
|
describe "applying calls from the standard attributes" do
|
26
26
|
let(:svg) do
|
27
27
|
<<-SVG
|
28
|
-
<something transform="
|
28
|
+
<something transform="scale(2)" fill-opacity="0.5" fill="red" stroke="blue" stroke-width="5"/>
|
29
29
|
SVG
|
30
30
|
end
|
31
31
|
|
32
32
|
it "appends the relevant calls" do
|
33
33
|
element.process
|
34
34
|
expect(element.base_calls).to eq [
|
35
|
-
["
|
35
|
+
["transformation_matrix", [2, 0, 0, 2, 0, 0], [
|
36
36
|
["transparent", [0.5, 1], [
|
37
37
|
["fill_color", ["ff0000"], []],
|
38
38
|
["stroke_color", ["0000ff"], []],
|
@@ -29,7 +29,8 @@ describe Prawn::SVG::Elements::Gradient do
|
|
29
29
|
expect(arguments).to eq(
|
30
30
|
from: [100.0, 100.0],
|
31
31
|
to: [120.0, 0.0],
|
32
|
-
stops: [[0, "ff0000"], [0.25, "ff0000"], [0.5, "ffffff"], [0.75, "0000ff"], [1, "0000ff"]]
|
32
|
+
stops: [[0, "ff0000"], [0.25, "ff0000"], [0.5, "ffffff"], [0.75, "0000ff"], [1, "0000ff"]],
|
33
|
+
apply_transformations: true,
|
33
34
|
)
|
34
35
|
end
|
35
36
|
|
@@ -54,7 +55,30 @@ describe Prawn::SVG::Elements::Gradient do
|
|
54
55
|
expect(arguments).to eq(
|
55
56
|
from: [100.0, 100.0],
|
56
57
|
to: [200.0, 0.0],
|
57
|
-
stops: [[0, "ff0000"], [1, "0000ff"]]
|
58
|
+
stops: [[0, "ff0000"], [1, "0000ff"]],
|
59
|
+
apply_transformations: true,
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when gradientTransform is specified" do
|
65
|
+
let(:svg) do
|
66
|
+
<<-SVG
|
67
|
+
<linearGradient id="flag" gradientTransform="translateX(10) scale(2)" x1="0" y1="0" x2="10" y2="10">
|
68
|
+
<stop offset="0" stop-color="red"/>
|
69
|
+
<stop offset="1" stop-color="blue"/>
|
70
|
+
</linearGradient>
|
71
|
+
SVG
|
72
|
+
end
|
73
|
+
|
74
|
+
it "passes in the transform via the apply_transformations option" do
|
75
|
+
arguments = element.gradient_arguments(double(bounding_box: [0, 0, 10, 10]))
|
76
|
+
|
77
|
+
expect(arguments).to eq(
|
78
|
+
from: [0, 0],
|
79
|
+
to: [10, 10],
|
80
|
+
stops: [[0, "ff0000"], [1, "0000ff"]],
|
81
|
+
apply_transformations: [2, 0, 0, 2, 10, 0],
|
58
82
|
)
|
59
83
|
end
|
60
84
|
end
|
@@ -29,6 +29,14 @@ RSpec.describe Prawn::SVG::Loaders::Data do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
context "with a data URL that's uppercase" do
|
33
|
+
let(:url) { "DATA:IMAGE/PNG;BASE64;METADATA;HERE,aGVsbG8=" }
|
34
|
+
|
35
|
+
it "loads the data" do
|
36
|
+
expect(subject).to eq "hello"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
32
40
|
context "with a URL that's not a data scheme" do
|
33
41
|
let(:url) { "http://some.host" }
|
34
42
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Prawn::SVG::TransformParser do
|
4
|
+
class Test
|
5
|
+
include Prawn::SVG::Calculators::Pixels
|
6
|
+
include Prawn::SVG::TransformParser
|
7
|
+
|
8
|
+
State = Struct.new(:viewport_sizing)
|
9
|
+
Properties = Struct.new(:numerical_font_size)
|
10
|
+
Document = Struct.new(:sizing)
|
11
|
+
|
12
|
+
def document
|
13
|
+
Document.new(_sizing)
|
14
|
+
end
|
15
|
+
|
16
|
+
def state
|
17
|
+
State.new(_sizing)
|
18
|
+
end
|
19
|
+
|
20
|
+
def computed_properties
|
21
|
+
Properties.new(14)
|
22
|
+
end
|
23
|
+
|
24
|
+
def _sizing
|
25
|
+
Prawn::SVG::Calculators::DocumentSizing.new([1000, 800])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subject { Test.new.parse_transform_attribute(transform) }
|
30
|
+
|
31
|
+
context "with no transform" do
|
32
|
+
let(:transform) { '' }
|
33
|
+
it { is_expected.to eq [1, 0, 0, 1, 0, 0] }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with translate" do
|
37
|
+
let(:transform) { 'translate(10 20)' }
|
38
|
+
it { is_expected.to eq [1, 0, 0, 1, 10, -20] }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with single argument translate" do
|
42
|
+
let(:transform) { 'translate(10)' }
|
43
|
+
it { is_expected.to eq [1, 0, 0, 1, 10, 0] }
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with translateX" do
|
47
|
+
let(:transform) { 'translateX(10)' }
|
48
|
+
it { is_expected.to eq [1, 0, 0, 1, 10, 0] }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with translateY" do
|
52
|
+
let(:transform) { 'translateY(10)' }
|
53
|
+
it { is_expected.to eq [1, 0, 0, 1, 0, -10] }
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:sin30) { Math.sin(30 * Math::PI / 180.0) }
|
57
|
+
let(:cos30) { Math.cos(30 * Math::PI / 180.0) }
|
58
|
+
let(:tan30) { Math.tan(30 * Math::PI / 180.0) }
|
59
|
+
|
60
|
+
context "with single argument rotate" do
|
61
|
+
let(:transform) { 'rotate(30)' }
|
62
|
+
it { is_expected.to eq [cos30, -sin30, sin30, cos30, 0, 0] }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with triple argument rotate" do
|
66
|
+
let(:transform) { 'rotate(30 100 200)' }
|
67
|
+
it { is_expected.to eq [cos30, -sin30, sin30, cos30, 113.39745962155611, 23.205080756887753] }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with scale" do
|
71
|
+
let(:transform) { 'scale(1.5)' }
|
72
|
+
it { is_expected.to eq [1.5, 0, 0, 1.5, 0, 0] }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "with skewX" do
|
76
|
+
let(:transform) { 'skewX(30)' }
|
77
|
+
it { is_expected.to eq [1, 0, -tan30, 1, 0, 0] }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "with skewY" do
|
81
|
+
let(:transform) { 'skewY(30)' }
|
82
|
+
it { is_expected.to eq [1, -tan30, 0, 1, 0, 0] }
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with matrix" do
|
86
|
+
let(:transform) { 'matrix(1 2 3 4 5 6)' }
|
87
|
+
it { is_expected.to eq [1, -2, -3, 4, 5, -6] }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with multiple" do
|
91
|
+
let(:transform) { 'scale(2) translate(7) scale(3)' }
|
92
|
+
it { is_expected.to eq [6, 0, 0, 6, 14, 0] }
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="206.404" height="167.984" viewBox="0 0 54.611 44.446">
|
2
|
+
<g transform="translate(-27.725 -80.097)" stroke="#000" stroke-width=".5">
|
3
|
+
<ellipse cx="48.451" cy="103.356" rx="20.476" ry="19.462" fill="#52e0ff"/>
|
4
|
+
<ellipse cx="66.77" cy="102.32" rx="15.316" ry="21.973" fill="#ff6c52" style="opacity:.75; fill-opacity:1"/>
|
5
|
+
</g>
|
6
|
+
</svg>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<svg viewBox="0 0 420 200" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<linearGradient id="gradient1" gradientUnits="userSpaceOnUse"
|
3
|
+
x1="0" y1="0" x2="200" y2="200">
|
4
|
+
<stop offset="0%" stop-color="darkblue" />
|
5
|
+
<stop offset="50%" stop-color="skyblue" />
|
6
|
+
<stop offset="100%" stop-color="darkblue" />
|
7
|
+
</linearGradient>
|
8
|
+
<linearGradient id="gradient2" gradientUnits="userSpaceOnUse"
|
9
|
+
x1="0" y1="0" x2="200" y2="200"
|
10
|
+
xgradientTransform="skewX(45) translate(-100, 0)"
|
11
|
+
gradientTransform="matrix(0.5, 0, 0, 1, 0, 100)">
|
12
|
+
<stop offset="0%" stop-color="darkblue" />
|
13
|
+
<stop offset="50%" stop-color="skyblue" />
|
14
|
+
<stop offset="100%" stop-color="darkblue" />
|
15
|
+
</linearGradient>
|
16
|
+
|
17
|
+
<rect x="0" y="0" width="200" height="200" fill="url(#gradient1)" />
|
18
|
+
<rect x="0" y="0" width="200" height="200" fill="url(#gradient2)" transform="translate(220, 0)" />
|
19
|
+
</svg>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg width="1200" height="400" viewBox="0 0 600 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
4
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" textLength="78" x="14" y="20">You can use</text>
|
5
|
+
<a target="_top" xlink:actuate="onRequest" xlink:href="http://plantuml.com/start" xlink:show="new" xlink:title="http://plantuml.com/start" xlink:type="simple">
|
6
|
+
<text fill="#0000FF" font-family="sans-serif" font-size="13" text-decoration="underline" textLength="87" x="96" y="20">links in notes</text>
|
7
|
+
<line style="stroke: #0000FF; stroke-width: 1.0;" x1="96" x2="183" y1="20" y2="20"/>
|
8
|
+
</a>
|
9
|
+
|
10
|
+
<g transform="translate(0 20)">
|
11
|
+
<text fill="#000000" font-family="sans-serif" font-size="13" textLength="78" lengthAdjust="spacingAndGlyphs" x="14" y="20">You can use</text>
|
12
|
+
<a target="_top" xlink:actuate="onRequest" xlink:href="http://plantuml.com/start" xlink:show="new" xlink:title="http://plantuml.com/start" xlink:type="simple">
|
13
|
+
<text fill="#0000FF" font-family="sans-serif" font-size="13" text-decoration="underline" textLength="87" lengthAdjust="spacingAndGlyphs" x="96" y="20">links in notes</text>
|
14
|
+
<line style="stroke: #0000FF; stroke-width: 1.0;" x1="96" x2="183" y1="20" y2="20"/>
|
15
|
+
</a>
|
16
|
+
</g>
|
17
|
+
</svg>
|
18
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<svg height="975" version="1.1" width="1275" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<rect x="0" y="0" width="200" height="100" fill="blue"/>
|
3
|
+
<rect x="0" y="0" width="200" height="100" fill="lightblue" transform="rotate(30 200 100) translate(200)"/>
|
4
|
+
<rect x="0" y="0" width="200" height="100" fill="lightblue" transform="rotate(-5) translate(400)"/>
|
5
|
+
|
6
|
+
<g transform="translate(0 200)">
|
7
|
+
<rect x="0" y="0" width="200" height="100" fill="green"/>
|
8
|
+
<rect x="0" y="0" width="200" height="100" fill="lightgreen" transform="skewX(35) translate(200)"/>
|
9
|
+
</g>
|
10
|
+
|
11
|
+
<g transform="translate(0 320)">
|
12
|
+
<rect x="0" y="0" width="200" height="100" fill="red"/>
|
13
|
+
<rect x="0" y="0" width="200" height="100" fill="pink" transform="skewY(5) translate(200)"/>
|
14
|
+
</g>
|
15
|
+
|
16
|
+
<g transform="translate(0 470)">
|
17
|
+
<rect x="0" y="0" width="200" height="100" fill="black"/>
|
18
|
+
<rect x="0" y="0" width="200" height="100" fill="grey" transform="translate(200) scale(1.5)"/>
|
19
|
+
</g>
|
20
|
+
</svg>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prawn-svg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.30.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Nesbitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prawn
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- lib/prawn/svg/elements/use.rb
|
127
127
|
- lib/prawn/svg/elements/viewport.rb
|
128
128
|
- lib/prawn/svg/extension.rb
|
129
|
+
- lib/prawn/svg/extensions/additional_gradient_transforms.rb
|
129
130
|
- lib/prawn/svg/font.rb
|
130
131
|
- lib/prawn/svg/font_registry.rb
|
131
132
|
- lib/prawn/svg/interface.rb
|
@@ -135,11 +136,13 @@ files:
|
|
135
136
|
- lib/prawn/svg/pathable.rb
|
136
137
|
- lib/prawn/svg/properties.rb
|
137
138
|
- lib/prawn/svg/state.rb
|
139
|
+
- lib/prawn/svg/transform_parser.rb
|
138
140
|
- lib/prawn/svg/ttf.rb
|
139
141
|
- lib/prawn/svg/url_loader.rb
|
140
142
|
- lib/prawn/svg/version.rb
|
141
143
|
- prawn-svg.gemspec
|
142
144
|
- spec/integration_spec.rb
|
145
|
+
- spec/prawn/svg/attributes/opacity_spec.rb
|
143
146
|
- spec/prawn/svg/attributes/transform_spec.rb
|
144
147
|
- spec/prawn/svg/calculators/aspect_ratio_spec.rb
|
145
148
|
- spec/prawn/svg/calculators/document_sizing_spec.rb
|
@@ -165,6 +168,7 @@ files:
|
|
165
168
|
- spec/prawn/svg/loaders/web_spec.rb
|
166
169
|
- spec/prawn/svg/pathable_spec.rb
|
167
170
|
- spec/prawn/svg/properties_spec.rb
|
171
|
+
- spec/prawn/svg/transform_parser_spec.rb
|
168
172
|
- spec/prawn/svg/ttf_spec.rb
|
169
173
|
- spec/prawn/svg/url_loader_spec.rb
|
170
174
|
- spec/sample_images/mushroom-long.jpg
|
@@ -180,9 +184,11 @@ files:
|
|
180
184
|
- spec/sample_svg/cubic01a.svg
|
181
185
|
- spec/sample_svg/cubic02.svg
|
182
186
|
- spec/sample_svg/display_none.svg
|
187
|
+
- spec/sample_svg/double_opacity.svg
|
183
188
|
- spec/sample_svg/ellipse01.svg
|
184
189
|
- spec/sample_svg/gistfile1.svg
|
185
190
|
- spec/sample_svg/google_charts.svg
|
191
|
+
- spec/sample_svg/gradient_transform.svg
|
186
192
|
- spec/sample_svg/gradients.svg
|
187
193
|
- spec/sample_svg/hidden_paths.svg
|
188
194
|
- spec/sample_svg/highcharts.svg
|
@@ -190,6 +196,7 @@ files:
|
|
190
196
|
- spec/sample_svg/image02_base64.svg
|
191
197
|
- spec/sample_svg/image03.svg
|
192
198
|
- spec/sample_svg/line01.svg
|
199
|
+
- spec/sample_svg/links.svg
|
193
200
|
- spec/sample_svg/marker.svg
|
194
201
|
- spec/sample_svg/markers_degenerate_cp.svg
|
195
202
|
- spec/sample_svg/maths.svg
|
@@ -216,6 +223,7 @@ files:
|
|
216
223
|
- spec/sample_svg/subviewports2.svg
|
217
224
|
- spec/sample_svg/text_entities.svg
|
218
225
|
- spec/sample_svg/text_stroke.svg
|
226
|
+
- spec/sample_svg/transform.svg
|
219
227
|
- spec/sample_svg/tref01.svg
|
220
228
|
- spec/sample_svg/triangle01.svg
|
221
229
|
- spec/sample_svg/tspan01.svg
|
@@ -256,6 +264,7 @@ specification_version: 4
|
|
256
264
|
summary: SVG renderer for Prawn PDF library
|
257
265
|
test_files:
|
258
266
|
- spec/integration_spec.rb
|
267
|
+
- spec/prawn/svg/attributes/opacity_spec.rb
|
259
268
|
- spec/prawn/svg/attributes/transform_spec.rb
|
260
269
|
- spec/prawn/svg/calculators/aspect_ratio_spec.rb
|
261
270
|
- spec/prawn/svg/calculators/document_sizing_spec.rb
|
@@ -281,6 +290,7 @@ test_files:
|
|
281
290
|
- spec/prawn/svg/loaders/web_spec.rb
|
282
291
|
- spec/prawn/svg/pathable_spec.rb
|
283
292
|
- spec/prawn/svg/properties_spec.rb
|
293
|
+
- spec/prawn/svg/transform_parser_spec.rb
|
284
294
|
- spec/prawn/svg/ttf_spec.rb
|
285
295
|
- spec/prawn/svg/url_loader_spec.rb
|
286
296
|
- spec/sample_images/mushroom-long.jpg
|
@@ -296,9 +306,11 @@ test_files:
|
|
296
306
|
- spec/sample_svg/cubic01a.svg
|
297
307
|
- spec/sample_svg/cubic02.svg
|
298
308
|
- spec/sample_svg/display_none.svg
|
309
|
+
- spec/sample_svg/double_opacity.svg
|
299
310
|
- spec/sample_svg/ellipse01.svg
|
300
311
|
- spec/sample_svg/gistfile1.svg
|
301
312
|
- spec/sample_svg/google_charts.svg
|
313
|
+
- spec/sample_svg/gradient_transform.svg
|
302
314
|
- spec/sample_svg/gradients.svg
|
303
315
|
- spec/sample_svg/hidden_paths.svg
|
304
316
|
- spec/sample_svg/highcharts.svg
|
@@ -306,6 +318,7 @@ test_files:
|
|
306
318
|
- spec/sample_svg/image02_base64.svg
|
307
319
|
- spec/sample_svg/image03.svg
|
308
320
|
- spec/sample_svg/line01.svg
|
321
|
+
- spec/sample_svg/links.svg
|
309
322
|
- spec/sample_svg/marker.svg
|
310
323
|
- spec/sample_svg/markers_degenerate_cp.svg
|
311
324
|
- spec/sample_svg/maths.svg
|
@@ -332,6 +345,7 @@ test_files:
|
|
332
345
|
- spec/sample_svg/subviewports2.svg
|
333
346
|
- spec/sample_svg/text_entities.svg
|
334
347
|
- spec/sample_svg/text_stroke.svg
|
348
|
+
- spec/sample_svg/transform.svg
|
335
349
|
- spec/sample_svg/tref01.svg
|
336
350
|
- spec/sample_svg/triangle01.svg
|
337
351
|
- spec/sample_svg/tspan01.svg
|