prawn-svg 0.21.0 → 0.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -0
- data/README.md +11 -4
- data/lib/prawn-svg.rb +9 -6
- data/lib/prawn/svg/attributes.rb +6 -0
- data/lib/prawn/svg/attributes/clip_path.rb +17 -0
- data/lib/prawn/svg/attributes/display.rb +5 -0
- data/lib/prawn/svg/attributes/font.rb +38 -0
- data/lib/prawn/svg/attributes/opacity.rb +15 -0
- data/lib/prawn/svg/attributes/stroke.rb +35 -0
- data/lib/prawn/svg/attributes/transform.rb +50 -0
- data/lib/prawn/svg/calculators/aspect_ratio.rb +1 -1
- data/lib/prawn/svg/calculators/document_sizing.rb +2 -2
- data/lib/prawn/svg/calculators/pixels.rb +1 -1
- data/lib/prawn/svg/color.rb +44 -14
- data/lib/prawn/svg/document.rb +6 -5
- data/lib/prawn/svg/elements.rb +33 -0
- data/lib/prawn/svg/elements/base.rb +228 -0
- data/lib/prawn/svg/elements/circle.rb +25 -0
- data/lib/prawn/svg/elements/container.rb +15 -0
- data/lib/prawn/svg/elements/ellipse.rb +23 -0
- data/lib/prawn/svg/elements/gradient.rb +117 -0
- data/lib/prawn/svg/elements/ignored.rb +5 -0
- data/lib/prawn/svg/elements/image.rb +85 -0
- data/lib/prawn/svg/elements/line.rb +16 -0
- data/lib/prawn/svg/elements/path.rb +405 -0
- data/lib/prawn/svg/elements/polygon.rb +17 -0
- data/lib/prawn/svg/elements/polyline.rb +22 -0
- data/lib/prawn/svg/elements/rect.rb +33 -0
- data/lib/prawn/svg/elements/root.rb +9 -0
- data/lib/prawn/svg/elements/style.rb +10 -0
- data/lib/prawn/svg/elements/text.rb +87 -0
- data/lib/prawn/svg/elements/use.rb +29 -0
- data/lib/prawn/svg/extension.rb +2 -2
- data/lib/prawn/svg/font.rb +3 -3
- data/lib/prawn/svg/interface.rb +12 -5
- data/lib/prawn/svg/url_loader.rb +1 -1
- data/lib/prawn/svg/version.rb +2 -2
- data/prawn-svg.gemspec +3 -3
- data/spec/integration_spec.rb +59 -2
- data/spec/prawn/svg/attributes/font_spec.rb +49 -0
- data/spec/prawn/svg/attributes/transform_spec.rb +56 -0
- data/spec/prawn/svg/calculators/aspect_ratio_spec.rb +2 -2
- data/spec/prawn/svg/calculators/document_sizing_spec.rb +3 -3
- data/spec/prawn/svg/color_spec.rb +36 -15
- data/spec/prawn/svg/document_spec.rb +4 -4
- data/spec/prawn/svg/elements/base_spec.rb +125 -0
- data/spec/prawn/svg/elements/gradient_spec.rb +61 -0
- data/spec/prawn/svg/elements/path_spec.rb +123 -0
- data/spec/prawn/svg/elements/style_spec.rb +23 -0
- data/spec/prawn/svg/{parser → elements}/text_spec.rb +7 -8
- data/spec/prawn/svg/font_spec.rb +12 -12
- data/spec/prawn/svg/interface_spec.rb +7 -7
- data/spec/prawn/svg/url_loader_spec.rb +2 -2
- data/spec/sample_svg/gradients.svg +40 -0
- data/spec/sample_svg/rect02.svg +8 -11
- data/spec/spec_helper.rb +1 -1
- metadata +46 -18
- data/lib/prawn/svg/element.rb +0 -304
- data/lib/prawn/svg/parser.rb +0 -268
- data/lib/prawn/svg/parser/image.rb +0 -81
- data/lib/prawn/svg/parser/path.rb +0 -392
- data/lib/prawn/svg/parser/text.rb +0 -80
- data/spec/prawn/svg/element_spec.rb +0 -127
- data/spec/prawn/svg/parser/path_spec.rb +0 -89
- data/spec/prawn/svg/parser_spec.rb +0 -55
@@ -0,0 +1,33 @@
|
|
1
|
+
class Prawn::SVG::Elements::Rect < Prawn::SVG::Elements::Base
|
2
|
+
def parse
|
3
|
+
require_attributes 'width', 'height'
|
4
|
+
|
5
|
+
@x = x(attributes['x'] || '0')
|
6
|
+
@y = y(attributes['y'] || '0')
|
7
|
+
@width = distance(attributes['width'], :x)
|
8
|
+
@height = distance(attributes['height'], :y)
|
9
|
+
|
10
|
+
require_positive_value @width, @height
|
11
|
+
|
12
|
+
@radius = distance(attributes['rx'] || attributes['ry'])
|
13
|
+
if @radius
|
14
|
+
# If you implement separate rx and ry in the future, you'll want to change this
|
15
|
+
# so that rx is constrained to @width/2 and ry is constrained to @height/2.
|
16
|
+
max_value = [@width, @height].min / 2.0
|
17
|
+
@radius = clamp(@radius, 0, max_value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def apply
|
22
|
+
if @radius
|
23
|
+
# n.b. does not support both rx and ry being specified with different values
|
24
|
+
add_call "rounded_rectangle", [@x, @y], @width, @height, @radius
|
25
|
+
else
|
26
|
+
add_call "rectangle", [@x, @y], @width, @height
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def bounding_box
|
31
|
+
[@x, @y, @x + @width, @y - @height]
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Prawn::SVG::Elements::Root < Prawn::SVG::Elements::Base
|
2
|
+
def apply
|
3
|
+
add_call 'fill_color', '000000'
|
4
|
+
add_call 'transformation_matrix', @document.sizing.x_scale, 0, 0, @document.sizing.y_scale, 0, 0
|
5
|
+
add_call 'transformation_matrix', 1, 0, 0, 1, @document.sizing.x_offset, @document.sizing.y_offset
|
6
|
+
|
7
|
+
process_child_elements
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class Prawn::SVG::Elements::Text < Prawn::SVG::Elements::Base
|
2
|
+
def parse
|
3
|
+
case attributes['xml:space']
|
4
|
+
when 'preserve'
|
5
|
+
state[:preserve_space] = true
|
6
|
+
when 'default'
|
7
|
+
state[:preserve_space] = false
|
8
|
+
end
|
9
|
+
|
10
|
+
@relative = state[:text_relative] || false
|
11
|
+
|
12
|
+
if attributes['x'] || attributes['y']
|
13
|
+
@relative = false
|
14
|
+
@x_positions = attributes['x'].split(COMMA_WSP_REGEXP).collect {|n| document.x(n)} if attributes['x']
|
15
|
+
@y_positions = attributes['y'].split(COMMA_WSP_REGEXP).collect {|n| document.y(n)} if attributes['y']
|
16
|
+
end
|
17
|
+
|
18
|
+
@x_positions ||= state[:text_x_positions] || [document.x(0)]
|
19
|
+
@y_positions ||= state[:text_y_positions] || [document.y(0)]
|
20
|
+
end
|
21
|
+
|
22
|
+
def apply
|
23
|
+
raise SkipElementQuietly if state[:display] == "none"
|
24
|
+
|
25
|
+
add_call_and_enter "text_group" if name == 'text'
|
26
|
+
|
27
|
+
if attributes['dx'] || attributes['dy']
|
28
|
+
add_call_and_enter "translate", document.distance(attributes['dx'] || 0), -document.distance(attributes['dy'] || 0)
|
29
|
+
end
|
30
|
+
|
31
|
+
opts = {}
|
32
|
+
if size = state[:font_size]
|
33
|
+
opts[:size] = size
|
34
|
+
end
|
35
|
+
opts[:style] = state[:font_subfamily]
|
36
|
+
|
37
|
+
# This is not a prawn option but we can't work out how to render it here -
|
38
|
+
# it's handled by SVG#rewrite_call_arguments
|
39
|
+
if (anchor = attributes['text-anchor'] || state[:text_anchor]) &&
|
40
|
+
['start', 'middle', 'end'].include?(anchor)
|
41
|
+
opts[:text_anchor] = anchor
|
42
|
+
end
|
43
|
+
|
44
|
+
if spacing = attributes['letter-spacing']
|
45
|
+
add_call_and_enter 'character_spacing', document.points(spacing)
|
46
|
+
end
|
47
|
+
|
48
|
+
source.children.each do |child|
|
49
|
+
if child.node_type == :text
|
50
|
+
text = child.value.strip.gsub(state[:preserve_space] ? /[\n\t]/ : /\s+/, " ")
|
51
|
+
|
52
|
+
while text != ""
|
53
|
+
opts[:at] = [@x_positions.first, @y_positions.first]
|
54
|
+
|
55
|
+
if @x_positions.length > 1 || @y_positions.length > 1
|
56
|
+
# TODO : isn't this just text.shift ?
|
57
|
+
add_call 'draw_text', text[0..0], opts.dup
|
58
|
+
text = text[1..-1]
|
59
|
+
|
60
|
+
@x_positions.shift if @x_positions.length > 1
|
61
|
+
@y_positions.shift if @y_positions.length > 1
|
62
|
+
else
|
63
|
+
add_call @relative ? 'relative_draw_text' : 'draw_text', text, opts.dup
|
64
|
+
@relative = true
|
65
|
+
break
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
elsif child.name == "tspan"
|
70
|
+
add_call 'save'
|
71
|
+
|
72
|
+
new_state = state.dup
|
73
|
+
new_state[:text_x_positions] = @x_positions
|
74
|
+
new_state[:text_y_positions] = @y_positions
|
75
|
+
new_state[:text_relative] = @relative
|
76
|
+
new_state[:text_anchor] = opts[:text_anchor]
|
77
|
+
|
78
|
+
Prawn::SVG::Elements::Text.new(document, child, calls, new_state).process
|
79
|
+
|
80
|
+
add_call 'restore'
|
81
|
+
|
82
|
+
else
|
83
|
+
warnings << "Unknown tag '#{child.name}' inside text tag; ignoring"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Prawn::SVG::Elements::Use < Prawn::SVG::Elements::Base
|
2
|
+
def parse
|
3
|
+
require_attributes 'xlink:href'
|
4
|
+
|
5
|
+
href = attributes['xlink:href']
|
6
|
+
|
7
|
+
if href[0..0] != '#'
|
8
|
+
raise SkipElementError, "use tag has an href that is not a reference to an id; this is not supported"
|
9
|
+
end
|
10
|
+
|
11
|
+
id = href[1..-1]
|
12
|
+
@definition_element = @document.elements_by_id[id]
|
13
|
+
|
14
|
+
if @definition_element.nil?
|
15
|
+
raise SkipElementError, "no tag with ID '#{id}' was found, referenced by use tag"
|
16
|
+
end
|
17
|
+
|
18
|
+
@x = attributes['x']
|
19
|
+
@y = attributes['y']
|
20
|
+
end
|
21
|
+
|
22
|
+
def apply
|
23
|
+
if @x || @y
|
24
|
+
add_call_and_enter "translate", distance(@x || 0, :x), -distance(@y || 0, :y)
|
25
|
+
end
|
26
|
+
|
27
|
+
add_calls_from_element @definition_element
|
28
|
+
end
|
29
|
+
end
|
data/lib/prawn/svg/extension.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Prawn
|
2
|
-
module
|
2
|
+
module SVG
|
3
3
|
module Extension
|
4
4
|
#
|
5
5
|
# Draws an SVG document into the PDF.
|
@@ -15,7 +15,7 @@ module Prawn
|
|
15
15
|
# svg IO.read("example.svg"), :at => [100, 300], :width => 600
|
16
16
|
#
|
17
17
|
def svg(data, options = {}, &block)
|
18
|
-
svg = Prawn::
|
18
|
+
svg = Prawn::SVG::Interface.new(data, self, options, &block)
|
19
19
|
svg.draw
|
20
20
|
{:warnings => svg.document.warnings, :width => svg.document.sizing.output_width, :height => svg.document.sizing.output_height}
|
21
21
|
end
|
data/lib/prawn/svg/font.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class Prawn::
|
1
|
+
class Prawn::SVG::Font
|
2
2
|
GENERIC_CSS_FONT_MAPPING = {
|
3
3
|
"serif" => "Times-Roman",
|
4
4
|
"sans-serif" => "Helvetica",
|
@@ -34,12 +34,12 @@ class Prawn::Svg::Font
|
|
34
34
|
# This method is passed prawn's font_families hash. It'll be pre-populated with the fonts that prawn natively
|
35
35
|
# supports. We'll add fonts we find in the font path to this hash.
|
36
36
|
def self.load_external_fonts(fonts)
|
37
|
-
Prawn::
|
37
|
+
Prawn::SVG::Interface.font_path.uniq.collect {|path| Dir["#{path}/**/*"]}.flatten.each do |filename|
|
38
38
|
information = font_information(filename) rescue nil
|
39
39
|
if information && font_name = (information[16] || information[1])
|
40
40
|
subfamily = (information[17] || information[2] || "normal").gsub(/\s+/, "_").downcase.to_sym
|
41
41
|
subfamily = :normal if subfamily == :regular
|
42
|
-
(fonts[font_name] ||= {})[subfamily]
|
42
|
+
(fonts[font_name] ||= {})[subfamily] ||= filename
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
data/lib/prawn/svg/interface.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#
|
2
|
-
# Prawn::
|
2
|
+
# Prawn::SVG::Interface makes a Prawn::SVG::Document instance, uses that object to parse the supplied
|
3
3
|
# SVG into Prawn-compatible method calls, and then calls the Prawn methods.
|
4
4
|
#
|
5
5
|
module Prawn
|
6
|
-
module
|
6
|
+
module SVG
|
7
7
|
class Interface
|
8
8
|
VALID_OPTIONS = [:at, :position, :vposition, :width, :height, :cache_images, :fallback_font_name]
|
9
9
|
|
@@ -17,7 +17,7 @@ module Prawn
|
|
17
17
|
attr_reader :data, :prawn, :document, :options
|
18
18
|
|
19
19
|
#
|
20
|
-
# Creates a Prawn::
|
20
|
+
# Creates a Prawn::SVG object.
|
21
21
|
#
|
22
22
|
# +data+ is the SVG data to convert. +prawn+ is your Prawn::Document object.
|
23
23
|
#
|
@@ -40,7 +40,7 @@ module Prawn
|
|
40
40
|
@prawn = prawn
|
41
41
|
@options = options
|
42
42
|
|
43
|
-
Prawn::
|
43
|
+
Prawn::SVG::Font.load_external_fonts(prawn.font_families)
|
44
44
|
|
45
45
|
@document = Document.new(data, [prawn.bounds.width, prawn.bounds.height], options, &block)
|
46
46
|
end
|
@@ -54,10 +54,17 @@ module Prawn
|
|
54
54
|
return
|
55
55
|
end
|
56
56
|
|
57
|
+
@document.warnings.clear
|
58
|
+
|
57
59
|
prawn.bounding_box(position, :width => @document.sizing.output_width, :height => @document.sizing.output_height) do
|
58
60
|
prawn.save_graphics_state do
|
59
61
|
clip_rectangle 0, 0, @document.sizing.output_width, @document.sizing.output_height
|
60
|
-
|
62
|
+
|
63
|
+
calls = []
|
64
|
+
root_element = Prawn::SVG::Elements::Root.new(@document, @document.root, calls, fill: true)
|
65
|
+
root_element.process
|
66
|
+
|
67
|
+
proc_creator(prawn, calls).call
|
61
68
|
end
|
62
69
|
end
|
63
70
|
end
|
data/lib/prawn/svg/url_loader.rb
CHANGED
data/lib/prawn/svg/version.rb
CHANGED
data/prawn-svg.gemspec
CHANGED
@@ -3,7 +3,7 @@ require File.expand_path('../lib/prawn/svg/version', __FILE__)
|
|
3
3
|
|
4
4
|
spec = Gem::Specification.new do |gem|
|
5
5
|
gem.name = 'prawn-svg'
|
6
|
-
gem.version = Prawn::
|
6
|
+
gem.version = Prawn::SVG::VERSION
|
7
7
|
gem.summary = "SVG renderer for Prawn PDF library"
|
8
8
|
gem.description = "This gem allows you to render SVG directly into a PDF using the 'prawn' gem. Since PDF is vector-based, you'll get nice scaled graphics if you use SVG instead of an image."
|
9
9
|
gem.has_rdoc = false
|
@@ -18,9 +18,9 @@ spec = Gem::Specification.new do |gem|
|
|
18
18
|
gem.name = "prawn-svg"
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.required_ruby_version = '>=
|
21
|
+
gem.required_ruby_version = '>= 2.0.0'
|
22
22
|
|
23
|
-
gem.add_runtime_dependency "prawn", ">= 0.
|
23
|
+
gem.add_runtime_dependency "prawn", ">= 0.11.1", "< 3"
|
24
24
|
gem.add_runtime_dependency "css_parser", "~> 1.3"
|
25
25
|
gem.add_development_dependency "rspec", "~> 3.0"
|
26
26
|
gem.add_development_dependency "rake", "~> 10.1"
|
data/spec/integration_spec.rb
CHANGED
@@ -1,8 +1,65 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe "Integration test" do
|
4
4
|
root = "#{File.dirname(__FILE__)}/.."
|
5
5
|
|
6
|
+
describe "a basic SVG file" do
|
7
|
+
let(:document) { Prawn::SVG::Document.new(svg, [800, 600], {}) }
|
8
|
+
let(:element) { Prawn::SVG::Elements::Root.new(document, document.root, [], {}) }
|
9
|
+
|
10
|
+
let(:svg) do
|
11
|
+
<<-SVG
|
12
|
+
<svg width="100" height="200">
|
13
|
+
<style><![CDATA[
|
14
|
+
#puppy { fill: red; }
|
15
|
+
.animal { fill: green; }
|
16
|
+
rect { fill: blue; }
|
17
|
+
]]></style>
|
18
|
+
|
19
|
+
<rect x="0" y="0" width="10" height="10"/>
|
20
|
+
<rect x="10" y="0" width="10" height="10" class="animal"/>
|
21
|
+
<rect x="20" y="0" width="10" height="10" class="animal" id="puppy"/>
|
22
|
+
<rect x="30" y="0" width="10" height="10" class="animal" id="puppy" style="fill: yellow;"/>
|
23
|
+
</svg>
|
24
|
+
SVG
|
25
|
+
end
|
26
|
+
|
27
|
+
it "is correctly converted to a call stack" do
|
28
|
+
element.process
|
29
|
+
|
30
|
+
expect(element.calls).to eq [
|
31
|
+
["fill_color", ["000000"], []],
|
32
|
+
["transformation_matrix", [1, 0, 0, 1, 0, 0], []],
|
33
|
+
["transformation_matrix", [1, 0, 0, 1, 0, 0], []],
|
34
|
+
["save", [], []], ["restore", [], []],
|
35
|
+
["save", [], []],
|
36
|
+
["fill_color", ["0000ff"], []],
|
37
|
+
["fill", [], [
|
38
|
+
["rectangle", [[0.0, 200.0], 10.0, 10.0], []]
|
39
|
+
]],
|
40
|
+
["restore", [], []],
|
41
|
+
["save", [], []],
|
42
|
+
["fill_color", ["008000"], []],
|
43
|
+
["fill", [], [
|
44
|
+
["rectangle", [[10.0, 200.0], 10.0, 10.0], []]
|
45
|
+
]],
|
46
|
+
["restore", [], []],
|
47
|
+
["save", [], []],
|
48
|
+
["fill_color", ["ff0000"], []],
|
49
|
+
["fill", [], [
|
50
|
+
["rectangle", [[20.0, 200.0], 10.0, 10.0], []]
|
51
|
+
]],
|
52
|
+
["restore", [], []],
|
53
|
+
["save", [], []],
|
54
|
+
["fill_color", ["ffff00"], []],
|
55
|
+
["fill", [], [
|
56
|
+
["rectangle", [[30.0, 200.0], 10.0, 10.0], []]
|
57
|
+
]],
|
58
|
+
["restore", [], []]
|
59
|
+
]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
6
63
|
context "with option :position" do
|
7
64
|
let(:svg) { IO.read("#{root}/spec/sample_svg/cubic01a.svg") }
|
8
65
|
|
@@ -51,7 +108,7 @@ describe Prawn::Svg::Interface do
|
|
51
108
|
doc.url_loader.url_cache["https://raw.githubusercontent.com/mogest/prawn-svg/master/spec/sample_images/mushroom-long.jpg"] = IO.read("#{root}/spec/sample_images/mushroom-long.jpg")
|
52
109
|
end
|
53
110
|
|
54
|
-
warnings = r[:warnings].reject {|w| w =~ /Verdana/ && w =~ /is not a known font/ }
|
111
|
+
warnings = r[:warnings].reject {|w| w =~ /Verdana/ && w =~ /is not a known font/ || w =~ /render gradients$/}
|
55
112
|
end
|
56
113
|
warnings.should == []
|
57
114
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Attributes::Font do
|
4
|
+
class FontTestElement
|
5
|
+
include Prawn::SVG::Attributes::Font
|
6
|
+
|
7
|
+
attr_accessor :attributes, :warnings
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@state = {}
|
11
|
+
@warnings = []
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:element) { FontTestElement.new }
|
16
|
+
let(:document) { double(fallback_font_name: "Times-Roman") }
|
17
|
+
|
18
|
+
before do
|
19
|
+
allow(element).to receive(:document).and_return(document)
|
20
|
+
element.attributes = {"font-family" => family}
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#parse_font_attributes_and_call" do
|
24
|
+
context "with a specified existing font" do
|
25
|
+
let(:family) { "Helvetica" }
|
26
|
+
|
27
|
+
it "uses a font if it can find it" do
|
28
|
+
expect(element).to receive(:add_call_and_enter).with("font", "Helvetica", style: :normal)
|
29
|
+
element.parse_font_attributes_and_call
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "with a specified non-existing font" do
|
34
|
+
let(:family) { "Font That Doesn't Exist" }
|
35
|
+
|
36
|
+
it "uses the fallback font if specified" do
|
37
|
+
expect(element).to receive(:add_call_and_enter).with("font", "Times-Roman", style: :normal)
|
38
|
+
element.parse_font_attributes_and_call
|
39
|
+
end
|
40
|
+
|
41
|
+
it "doesn't call the font method if there's no fallback font" do
|
42
|
+
allow(document).to receive(:fallback_font_name).and_return(nil)
|
43
|
+
expect(element).to_not receive(:add_call_and_enter)
|
44
|
+
element.parse_font_attributes_and_call
|
45
|
+
expect(element.warnings.length).to eq 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Attributes::Transform do
|
4
|
+
class TransformTestElement
|
5
|
+
include Prawn::SVG::Attributes::Transform
|
6
|
+
|
7
|
+
attr_accessor :attributes, :warnings
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@warnings = []
|
11
|
+
@attributes = {}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:element) { TransformTestElement.new }
|
16
|
+
|
17
|
+
describe "#parse_transform_attribute_and_call" do
|
18
|
+
subject { element.send :parse_transform_attribute_and_call }
|
19
|
+
|
20
|
+
describe "translate" do
|
21
|
+
it "handles a missing y argument" do
|
22
|
+
expect(element).to receive(:add_call_and_enter).with('translate', -5.5, 0)
|
23
|
+
expect(element).to receive(:distance).with(-5.5, :x).and_return(-5.5)
|
24
|
+
expect(element).to receive(:distance).with(0.0, :y).and_return(0.0)
|
25
|
+
|
26
|
+
element.attributes['transform'] = 'translate(-5.5)'
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "rotate" do
|
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
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|