prawn-svg 0.35.1 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -5
- data/README.md +4 -7
- data/lib/prawn/svg/attributes/opacity.rb +23 -8
- data/lib/prawn/svg/attributes/stroke.rb +7 -9
- data/lib/prawn/svg/attributes/transform.rb +1 -1
- data/lib/prawn/svg/calculators/pixels.rb +9 -22
- data/lib/prawn/svg/color.rb +58 -59
- data/lib/prawn/svg/css/font_parser.rb +46 -0
- data/lib/prawn/svg/document.rb +16 -9
- data/lib/prawn/svg/elements/base.rb +22 -30
- data/lib/prawn/svg/elements/gradient.rb +99 -74
- data/lib/prawn/svg/elements/line.rb +1 -1
- data/lib/prawn/svg/elements/marker.rb +2 -0
- data/lib/prawn/svg/elements/root.rb +1 -1
- data/lib/prawn/svg/elements/text_component.rb +3 -3
- data/lib/prawn/svg/funciri.rb +14 -0
- data/lib/prawn/svg/gradient_renderer.rb +313 -0
- data/lib/prawn/svg/length.rb +43 -0
- data/lib/prawn/svg/paint.rb +67 -0
- data/lib/prawn/svg/percentage.rb +24 -0
- data/lib/prawn/svg/properties.rb +208 -104
- data/lib/prawn/svg/renderer.rb +5 -0
- data/lib/prawn/svg/state.rb +5 -3
- data/lib/prawn/svg/transform_parser.rb +19 -13
- data/lib/prawn/svg/transform_utils.rb +37 -0
- data/lib/prawn/svg/version.rb +1 -1
- data/lib/prawn-svg.rb +7 -3
- data/prawn-svg.gemspec +4 -4
- data/spec/prawn/svg/attributes/opacity_spec.rb +27 -20
- data/spec/prawn/svg/attributes/transform_spec.rb +5 -2
- data/spec/prawn/svg/calculators/pixels_spec.rb +1 -2
- data/spec/prawn/svg/color_spec.rb +22 -52
- data/spec/prawn/svg/document_spec.rb +18 -4
- data/spec/prawn/svg/elements/base_spec.rb +9 -10
- data/spec/prawn/svg/elements/gradient_spec.rb +92 -36
- data/spec/prawn/svg/elements/marker_spec.rb +13 -15
- data/spec/prawn/svg/funciri_spec.rb +59 -0
- data/spec/prawn/svg/length_spec.rb +89 -0
- data/spec/prawn/svg/paint_spec.rb +96 -0
- data/spec/prawn/svg/pathable_spec.rb +3 -3
- data/spec/prawn/svg/pdfmatrix_spec.rb +60 -0
- data/spec/prawn/svg/percentage_spec.rb +60 -0
- data/spec/prawn/svg/properties_spec.rb +124 -107
- data/spec/prawn/svg/transform_parser_spec.rb +13 -13
- data/spec/sample_svg/gradient_stress_test.svg +115 -0
- metadata +17 -5
- data/lib/prawn/svg/extensions/additional_gradient_transforms.rb +0 -23
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Length do
|
4
|
+
describe '.parse' do
|
5
|
+
it 'parses a length' do
|
6
|
+
expect(described_class.parse('1.23em')).to eq(described_class.new(1.23, :em))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses a length with a positive sign' do
|
10
|
+
expect(described_class.parse('+1.23em')).to eq(described_class.new(1.23, :em))
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'parses a length with a negative sign' do
|
14
|
+
expect(described_class.parse('-1.23em')).to eq(described_class.new(-1.23, :em))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'parses a length with the unit in caps' do
|
18
|
+
expect(described_class.parse('1.23EM')).to eq(described_class.new(1.23, :em))
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'parses a length with no decimal points' do
|
22
|
+
expect(described_class.parse('1em')).to eq(described_class.new(1, :em))
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'parses a length with no unit' do
|
26
|
+
expect(described_class.parse('1.23')).to eq(described_class.new(1.23, nil))
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'allows numbers without a leading zero' do
|
30
|
+
expect(described_class.parse('.23em')).to eq(described_class.new(0.23, :em))
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'does not allow numbers with a trailing dot' do
|
34
|
+
expect(described_class.parse('1.em')).to be nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not allow units it does not recognise' do
|
38
|
+
expect(described_class.parse('1.23foo')).to be nil
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when positive_only is true' do
|
42
|
+
it 'does not allow negative numbers' do
|
43
|
+
expect(described_class.parse('-1.23em', positive_only: true)).to be nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'does allow zero' do
|
47
|
+
expect(described_class.parse('0em', positive_only: true)).to eq(described_class.new(0, :em))
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'does allow positive numbers' do
|
51
|
+
expect(described_class.parse('1.23em', positive_only: true)).to eq(described_class.new(1.23, :em))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#to_pixels' do
|
57
|
+
it 'converts a em-unit length to pixels' do
|
58
|
+
expect(described_class.new(2.5, :em).to_pixels(nil, 12)).to eq(12 * 2.5)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'converts a rem-unit length to pixels' do
|
62
|
+
expect(described_class.new(2.5, :rem).to_pixels(nil, 12)).to eq(16 * 2.5)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'converts a ex-unit length to pixels' do
|
66
|
+
expect(described_class.new(2.5, :ex).to_pixels(nil, 12)).to eq(6 * 2.5)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'converts a pc-unit length to pixels' do
|
70
|
+
expect(described_class.new(2.5, :pc).to_pixels(nil, 12)).to eq(37.5)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'converts a in-unit length to pixels' do
|
74
|
+
expect(described_class.new(2.5, :in).to_pixels(nil, 12)).to eq(180)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'converts a cm-unit length to pixels' do
|
78
|
+
expect(described_class.new(2.5, :cm).to_pixels(nil, 12)).to be_within(0.001).of(70.866)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'converts a mm-unit length to pixels' do
|
82
|
+
expect(described_class.new(2.5, :mm).to_pixels(nil, 12)).to be_within(0.001).of(7.087)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns the value for an unknown unit' do
|
86
|
+
expect(described_class.new(2.5, nil).to_pixels(nil, 12)).to eq(2.5)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Prawn::SVG::Paint do
|
4
|
+
let(:red) { Prawn::SVG::Color::RGB.new('ff0000') }
|
5
|
+
|
6
|
+
describe '.parse' do
|
7
|
+
it 'parses a color' do
|
8
|
+
expect(described_class.parse('red')).to eq(described_class.new(red, nil))
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'parses an rgb color with an icc color, ignoring the icc color' do
|
12
|
+
expect(described_class.parse('rgb(255, 0, 0) icc-color(1)')).to eq(described_class.new(red, nil))
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'parses a URL' do
|
16
|
+
expect(described_class.parse('url(#foo)')).to eq(described_class.new(:none, '#foo'))
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'parses a keyword' do
|
20
|
+
expect(described_class.parse('NONE')).to eq(described_class.new(:none, nil))
|
21
|
+
expect(described_class.parse('currentColor')).to eq(described_class.new(:currentcolor, nil))
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses a URL with a fallback keyword' do
|
25
|
+
expect(described_class.parse('url(#foo) none')).to eq(described_class.new(:none, '#foo'))
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'parses a URL with a fallback color' do
|
29
|
+
expect(described_class.parse('url(#foo) red')).to eq(described_class.new(red, '#foo'))
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'parses a URL with a fallback color and an icc color, ignoring the icc color' do
|
33
|
+
expect(described_class.parse('url(#foo) red icc-color(1)')).to eq(described_class.new(red, '#foo'))
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns nil if the value is unrecognised' do
|
37
|
+
expect(described_class.parse('foo')).to be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns nil if the url has multiple arguments' do
|
41
|
+
expect(described_class.parse('url(#foo, bar)')).to be_nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#none?' do
|
46
|
+
it 'returns true if the color is none' do
|
47
|
+
expect(described_class.new(:none, nil).none?).to be(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns true if the color is none and the URL is unresolved' do
|
51
|
+
paint = described_class.new(:none, '#foo')
|
52
|
+
paint.instance_variable_set(:@unresolved_url, true)
|
53
|
+
expect(paint.none?).to be(true)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'returns false if the color is not none' do
|
57
|
+
expect(described_class.new(Prawn::SVG::Color::RGB.new('ff0000'), nil).none?).to be(false)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#resolve' do
|
62
|
+
it 'returns the current color if the color is currentcolor' do
|
63
|
+
current_color = double
|
64
|
+
paint = described_class.new(:currentcolor, nil)
|
65
|
+
expect(paint.resolve(nil, current_color, :rgb)).to eq current_color
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns the nil if the color is none' do
|
69
|
+
current_color = double
|
70
|
+
paint = described_class.new(:none, nil)
|
71
|
+
expect(paint.resolve(nil, current_color, :rgb)).to be nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns the gradient if the URL is resolvable' do
|
75
|
+
gradient = double
|
76
|
+
paint = described_class.new(:none, '#foo')
|
77
|
+
expect(paint.resolve({ 'foo' => gradient }, nil, :rgb)).to eq(gradient)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'falls back to the color if the URL is unresolvable' do
|
81
|
+
paint = described_class.new(red, '#foo')
|
82
|
+
expect(paint.resolve(nil, nil, :rgb)).to eq red
|
83
|
+
expect(paint.resolve({}, nil, :rgb)).to eq red
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns the color if the color is not currentcolor or none' do
|
87
|
+
paint = described_class.new(red, nil)
|
88
|
+
expect(paint.resolve(nil, nil, :rgb)).to eq red
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'converts the color to CMYK if the color mode is CMYK' do
|
92
|
+
paint = described_class.new(red, nil)
|
93
|
+
expect(paint.resolve(nil, nil, :cmyk)).to eq Prawn::SVG::Color::CMYK.new([0, 100, 100, 0])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -57,7 +57,7 @@ RSpec.describe Prawn::SVG::Pathable do
|
|
57
57
|
|
58
58
|
context 'with marker-start attribute specified' do
|
59
59
|
before do
|
60
|
-
subject.properties.marker_start = '
|
60
|
+
subject.properties.marker_start = Prawn::SVG::FuncIRI.new('#triangle')
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'calls apply_marker on the marker' do
|
@@ -68,7 +68,7 @@ RSpec.describe Prawn::SVG::Pathable do
|
|
68
68
|
|
69
69
|
context 'with marker-mid attribute specified' do
|
70
70
|
before do
|
71
|
-
subject.properties.marker_mid = '
|
71
|
+
subject.properties.marker_mid = Prawn::SVG::FuncIRI.new('#triangle')
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'calls apply_marker on the marker' do
|
@@ -80,7 +80,7 @@ RSpec.describe Prawn::SVG::Pathable do
|
|
80
80
|
|
81
81
|
context 'with marker-end attribute specified' do
|
82
82
|
before do
|
83
|
-
subject.properties.marker_end = '
|
83
|
+
subject.properties.marker_end = Prawn::SVG::FuncIRI.new('#triangle')
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'calls apply_marker on the marker' do
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Prawn::SVG::PDFMatrix do
|
4
|
+
subject do
|
5
|
+
obj = Object.new
|
6
|
+
obj.extend(Prawn::SVG::PDFMatrix)
|
7
|
+
obj
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#load_matrix' do
|
11
|
+
it 'converts a PDF-style matrix into a Ruby Matrix' do
|
12
|
+
expect(subject.load_matrix([1.0, 0.0, 0.0, 1.0, 5.0, 7.0])).to eq(Matrix[
|
13
|
+
[1.0, 0.0, 5.0],
|
14
|
+
[0.0, 1.0, 7.0],
|
15
|
+
[0.0, 0.0, 1.0]
|
16
|
+
])
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns the same Ruby Matrix if it has the correct dimensions' do
|
20
|
+
matrix = Matrix[[1.0, 0.0, 5.0], [0.0, 1.0, 7.0], [0.0, 0.0, 1.0]]
|
21
|
+
expect(subject.load_matrix(matrix)).to eq(matrix)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'raises an error for unexpected Ruby matrices' do
|
25
|
+
matrix = Matrix.identity(4)
|
26
|
+
expect { subject.load_matrix(matrix) }.to raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'raises an error for unexpected PDF-style matrices' do
|
30
|
+
matrix = [1.0, 2.0, 3.0, 4.0]
|
31
|
+
expect { subject.load_matrix(matrix) }.to raise_error(ArgumentError)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#matrix_for_pdf' do
|
36
|
+
it 'converts a Ruby Matrix into the correct format for PDF' do
|
37
|
+
matrix = Matrix[[1.0, 0.0, 5.0], [0.0, 1.0, 7.0], [0.0, 0.0, 1.0]]
|
38
|
+
expect(subject.matrix_for_pdf(matrix)).to eq([1.0, 0.0, 0.0, 1.0, 5.0, 7.0])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#rotation_matrix' do
|
43
|
+
let(:angle) { 45 * Math::PI / 180.0 }
|
44
|
+
let(:inv_root_2) { 0.707 }
|
45
|
+
|
46
|
+
context 'in PDF space' do
|
47
|
+
it 'returns the expected matrix' do
|
48
|
+
matrix = Matrix[[inv_root_2, inv_root_2, 0], [-inv_root_2, inv_root_2, 0], [0, 0, 1]]
|
49
|
+
expect(subject.rotation_matrix(angle).round(3)).to eq(matrix)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'in SVG space' do
|
54
|
+
it 'returns the expected matrix' do
|
55
|
+
matrix = Matrix[[inv_root_2, -inv_root_2, 0], [inv_root_2, inv_root_2, 0], [0, 0, 1]]
|
56
|
+
expect(subject.rotation_matrix(angle, space: :svg).round(3)).to eq(matrix)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Prawn::SVG::Percentage do
|
4
|
+
describe '.parse' do
|
5
|
+
it 'parses a percentage' do
|
6
|
+
expect(described_class.parse('1.23%')).to eq(described_class.new(1.23))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses a percentage with a positive sign' do
|
10
|
+
expect(described_class.parse('+1.23%')).to eq(described_class.new(1.23))
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'parses a percentage with a negative sign' do
|
14
|
+
expect(described_class.parse('-1.23%')).to eq(described_class.new(-1.23))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'parses a percentage with no decimal points' do
|
18
|
+
expect(described_class.parse('1%')).to eq(described_class.new(1))
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does not parse a percentage with no number' do
|
22
|
+
expect(described_class.parse('%')).to be nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does not parse a percentage with a trailing dot' do
|
26
|
+
expect(described_class.parse('1.%')).to be nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'requires that the percentage sign is specified' do
|
30
|
+
expect(described_class.parse('1.23')).to be nil
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when positive_only is true' do
|
34
|
+
it 'does not allow negative numbers' do
|
35
|
+
expect(described_class.parse('-1.23%', positive_only: true)).to be nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does allow zero' do
|
39
|
+
expect(described_class.parse('0%', positive_only: true)).to eq(described_class.new(0))
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does allow positive numbers' do
|
43
|
+
expect(described_class.parse('1.23%', positive_only: true)).to eq(described_class.new(1.23))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#to_factor' do
|
49
|
+
it 'converts a percentage to a factor' do
|
50
|
+
expect(described_class.new(2.5).to_factor).to eq(0.025)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#to_pixels' do
|
55
|
+
it 'converts a percentage to pixels' do
|
56
|
+
expect(described_class.new(2.5).to_pixels(100, nil)).to eq(2.5)
|
57
|
+
expect(described_class.new(2.5).to_pixels(200, nil)).to eq(5)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -14,13 +14,13 @@ RSpec.describe Prawn::SVG::Properties do
|
|
14
14
|
it 'sets a property' do
|
15
15
|
result = subject.set('color', 'red')
|
16
16
|
expect(result).to be
|
17
|
-
expect(subject.color).to eq '
|
17
|
+
expect(subject.color).to eq Prawn::SVG::Color::RGB.new('ff0000')
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'handles property names that are not lower case' do
|
21
21
|
result = subject.set('COLor', 'red')
|
22
22
|
expect(result).to be
|
23
|
-
expect(subject.color).to eq '
|
23
|
+
expect(subject.color).to eq Prawn::SVG::Color::RGB.new('ff0000')
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'right-cases and strips keywords' do
|
@@ -28,22 +28,99 @@ RSpec.describe Prawn::SVG::Properties do
|
|
28
28
|
expect(subject.stroke_linecap).to eq 'round'
|
29
29
|
end
|
30
30
|
|
31
|
-
it
|
32
|
-
subject.set('
|
33
|
-
expect(subject.
|
31
|
+
it 'ignores invalid values, retaining any previously set value' do
|
32
|
+
subject.set('display', 'invalid')
|
33
|
+
expect(subject.display).to be nil
|
34
|
+
subject.set('display', 'none')
|
35
|
+
expect(subject.display).to eq 'none'
|
36
|
+
subject.set('display', 'invalid')
|
37
|
+
expect(subject.display).to eq 'none'
|
34
38
|
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
context 'when setting the font shorthand property' do
|
41
|
+
it 'sets font style, weight, size, and family' do
|
42
|
+
subject.set('font', 'italic bold 12px/30px "New Font", sans-serif')
|
43
|
+
expect(subject.font_style).to eq 'italic'
|
44
|
+
expect(subject.font_weight).to eq 'bold'
|
45
|
+
expect(subject.font_variant).to eq 'normal'
|
46
|
+
expect(subject.font_size).to eq Prawn::SVG::Length.parse('12px')
|
47
|
+
expect(subject.font_family).to eq '"New Font", sans-serif'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'sets font style, weight, variant, size, and family' do
|
51
|
+
subject.set('font', 'italic small-caps bold 12px/30px "New Font", sans-serif')
|
52
|
+
expect(subject.font_style).to eq 'italic'
|
53
|
+
expect(subject.font_weight).to eq 'bold'
|
54
|
+
expect(subject.font_variant).to eq 'small-caps'
|
55
|
+
expect(subject.font_size).to eq Prawn::SVG::Length.parse('12px')
|
56
|
+
expect(subject.font_family).to eq '"New Font", sans-serif'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'sets size and family, defaulting everything else to normal' do
|
60
|
+
subject.set('font-weight', 'bold')
|
61
|
+
subject.set('font-style', 'italic')
|
62
|
+
subject.set('font-variant', 'small-caps')
|
63
|
+
|
64
|
+
subject.set('font', '12px fontname')
|
65
|
+
expect(subject.font_style).to eq 'normal'
|
66
|
+
expect(subject.font_weight).to eq 'normal'
|
67
|
+
expect(subject.font_variant).to eq 'normal'
|
68
|
+
expect(subject.font_size).to eq Prawn::SVG::Length.parse('12px')
|
69
|
+
expect(subject.font_family).to eq 'fontname'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'suports the inherit keyword' do
|
73
|
+
subject.set('font', 'inherit')
|
74
|
+
expect(subject.font_style).to eq 'inherit'
|
75
|
+
expect(subject.font_weight).to eq 'inherit'
|
76
|
+
expect(subject.font_variant).to eq 'inherit'
|
77
|
+
expect(subject.font_size).to eq 'inherit'
|
78
|
+
expect(subject.font_family).to eq 'inherit'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'supports the standard font keyword, menu' do
|
82
|
+
subject.set('font', 'menu')
|
83
|
+
expect(subject.font_style).to eq 'normal'
|
84
|
+
expect(subject.font_weight).to eq 'normal'
|
85
|
+
expect(subject.font_variant).to eq 'normal'
|
86
|
+
expect(subject.font_size).to eq 'medium'
|
87
|
+
expect(subject.font_family).to eq 'sans-serif'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does nothing if an unrecognised keyword is used' do
|
91
|
+
subject.set('font', 'invalid')
|
92
|
+
expect(subject.font_style).to be nil
|
93
|
+
expect(subject.font_weight).to be nil
|
94
|
+
expect(subject.font_variant).to be nil
|
95
|
+
expect(subject.font_size).to be nil
|
96
|
+
expect(subject.font_family).to be nil
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'does nothing if the font size is not valid' do
|
100
|
+
subject.set('font', '23bad sans-serif')
|
101
|
+
expect(subject.font_style).to be nil
|
102
|
+
expect(subject.font_weight).to be nil
|
103
|
+
expect(subject.font_variant).to be nil
|
104
|
+
expect(subject.font_size).to be nil
|
105
|
+
expect(subject.font_family).to be nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'does nothing if one of the font keywords is not recognised' do
|
109
|
+
subject.set('font', 'italic invalid bold 12px/30px "New Font", sans-serif')
|
110
|
+
expect(subject.font_style).to be nil
|
111
|
+
expect(subject.font_weight).to be nil
|
112
|
+
expect(subject.font_variant).to be nil
|
113
|
+
expect(subject.font_size).to be nil
|
114
|
+
expect(subject.font_family).to be nil
|
115
|
+
end
|
39
116
|
end
|
40
117
|
end
|
41
118
|
|
42
119
|
describe '#load_hash' do
|
43
120
|
it 'uses #set to load in a hash of properties' do
|
44
121
|
subject.load_hash('stroke' => 'blue', 'fill' => 'green', 'stroke-linecap' => 'Round')
|
45
|
-
expect(subject.stroke).to eq '
|
46
|
-
expect(subject.fill).to eq '
|
122
|
+
expect(subject.stroke).to eq Prawn::SVG::Paint.new(Prawn::SVG::Color::RGB.new('0000ff'))
|
123
|
+
expect(subject.fill).to eq Prawn::SVG::Paint.new(Prawn::SVG::Color::RGB.new('008000'))
|
47
124
|
expect(subject.stroke_linecap).to eq 'round'
|
48
125
|
end
|
49
126
|
end
|
@@ -54,7 +131,7 @@ RSpec.describe Prawn::SVG::Properties do
|
|
54
131
|
it 'auto-inherits inheritable properties when the property is not supplied' do
|
55
132
|
subject.set('color', 'green')
|
56
133
|
subject.compute_properties(other)
|
57
|
-
expect(subject.color).to eq '
|
134
|
+
expect(subject.color).to eq Prawn::SVG::Color::RGB.new('008000')
|
58
135
|
end
|
59
136
|
|
60
137
|
it "doesn't auto-inherit non-inheritable properties" do
|
@@ -74,112 +151,52 @@ RSpec.describe Prawn::SVG::Properties do
|
|
74
151
|
subject.set('color', 'green')
|
75
152
|
other.set('color', 'red')
|
76
153
|
subject.compute_properties(other)
|
77
|
-
expect(subject.color).to eq '
|
154
|
+
expect(subject.color).to eq Prawn::SVG::Color::RGB.new('ff0000')
|
78
155
|
end
|
156
|
+
end
|
79
157
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
context 'when given a % as a font-size' do
|
87
|
-
let(:font_size) { '120%' }
|
88
|
-
|
89
|
-
it 'calculates the new font size' do
|
90
|
-
subject.compute_properties(other)
|
91
|
-
expect(subject.font_size).to eq '18.0'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context "when given 'larger' as a font-size" do
|
96
|
-
let(:font_size) { 'larger' }
|
97
|
-
|
98
|
-
it 'calculates the new font size' do
|
99
|
-
subject.compute_properties(other)
|
100
|
-
expect(subject.font_size).to eq '19.0'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context "when given 'smaller' as a font-size" do
|
105
|
-
let(:font_size) { 'smaller' }
|
106
|
-
|
107
|
-
it 'calculates the new font size' do
|
108
|
-
subject.compute_properties(other)
|
109
|
-
expect(subject.font_size).to eq '11.0'
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "when given a value in 'em' as a font-size" do
|
114
|
-
let(:font_size) { '2.5em' }
|
115
|
-
|
116
|
-
it 'calculates the new font size' do
|
117
|
-
subject.compute_properties(other)
|
118
|
-
expect(subject.font_size).to eq '37.5'
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
context "when given a value in 'rem' as a font-size" do
|
123
|
-
let(:font_size) { '2.5rem' }
|
124
|
-
|
125
|
-
it 'calculates the new font size' do
|
126
|
-
subject.compute_properties(other)
|
127
|
-
expect(subject.font_size).to eq '40.0'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
context "when given a value in 'px' as a font-size" do
|
132
|
-
let(:font_size) { '19.5px' }
|
133
|
-
|
134
|
-
it 'uses the font size specified' do
|
135
|
-
subject.compute_properties(other)
|
136
|
-
expect(subject.font_size).to eq '19.5'
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
context "when given a value in 'pt' as a font-size" do
|
141
|
-
let(:font_size) { '19.5pt' }
|
142
|
-
|
143
|
-
it 'uses the font size specified' do
|
144
|
-
subject.compute_properties(other)
|
145
|
-
expect(subject.font_size).to eq '19.5'
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
context 'when given a value without units as a font-size' do
|
150
|
-
let(:font_size) { '19.5' }
|
151
|
-
|
152
|
-
it 'uses the font size specified' do
|
153
|
-
subject.compute_properties(other)
|
154
|
-
expect(subject.font_size).to eq '19.5'
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context "when given the keyword 'inherit' as a font-size" do
|
159
|
-
let(:font_size) { 'inherit' }
|
158
|
+
describe '#numeric_font_size' do
|
159
|
+
def calculate
|
160
|
+
properties = Prawn::SVG::Properties.new
|
161
|
+
properties.compute_properties(subject)
|
162
|
+
properties.numeric_font_size
|
163
|
+
end
|
160
164
|
|
161
|
-
|
162
|
-
|
163
|
-
|
165
|
+
cases =
|
166
|
+
{
|
167
|
+
Prawn::SVG::Length.parse('18.5pt') => 18.5,
|
168
|
+
Prawn::SVG::Percentage.new(120) => 19.2,
|
169
|
+
19.5 => 19.5,
|
170
|
+
'larger' => 20,
|
171
|
+
'smaller' => 12,
|
172
|
+
nil => 16,
|
173
|
+
'inherit' => 16,
|
174
|
+
'x-large' => 24
|
175
|
+
}
|
176
|
+
|
177
|
+
cases.each do |font_size, expected|
|
178
|
+
context "when the font size is #{font_size.inspect}" do
|
179
|
+
before { subject.font_size = font_size }
|
180
|
+
|
181
|
+
it 'returns the correct number' do
|
182
|
+
expect(calculate).to eq expected
|
164
183
|
end
|
165
184
|
end
|
166
185
|
end
|
167
|
-
end
|
168
186
|
|
169
|
-
|
170
|
-
|
171
|
-
|
187
|
+
context 'with a font-size of 1.2em, under a parent with a font size of x-large' do
|
188
|
+
it 'returns 24 * 1.2' do
|
189
|
+
a = Prawn::SVG::Properties.new
|
190
|
+
a.set('font-size', 'x-large')
|
172
191
|
|
173
|
-
|
174
|
-
|
175
|
-
end
|
176
|
-
end
|
192
|
+
b = Prawn::SVG::Properties.new
|
193
|
+
b.set('font-size', '1.2em')
|
177
194
|
|
178
|
-
|
179
|
-
|
195
|
+
properties = Prawn::SVG::Properties.new
|
196
|
+
properties.compute_properties(a)
|
197
|
+
properties.compute_properties(b)
|
180
198
|
|
181
|
-
|
182
|
-
expect(subject.numerical_font_size).to eq 24
|
199
|
+
expect(properties.numeric_font_size.round(1)).to eq 28.8
|
183
200
|
end
|
184
201
|
end
|
185
202
|
end
|