prawn-svg 0.35.1 → 0.36.0
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 +5 -1
 - 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/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,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
         
     | 
| 
         @@ -6,7 +6,7 @@ RSpec.describe Prawn::SVG::TransformParser do 
     | 
|
| 
       6 
6 
     | 
    
         
             
                include Prawn::SVG::TransformParser
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                State = Struct.new(:viewport_sizing)
         
     | 
| 
       9 
     | 
    
         
            -
                Properties = Struct.new(: 
     | 
| 
      
 9 
     | 
    
         
            +
                Properties = Struct.new(:numeric_font_size)
         
     | 
| 
       10 
10 
     | 
    
         
             
                Document = Struct.new(:sizing)
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                def document
         
     | 
| 
         @@ -30,27 +30,27 @@ RSpec.describe Prawn::SVG::TransformParser do 
     | 
|
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
              context 'with no transform' do
         
     | 
| 
       32 
32 
     | 
    
         
             
                let(:transform) { '' }
         
     | 
| 
       33 
     | 
    
         
            -
                it { is_expected.to eq [1, 0, 0, 1, 0, 0] }
         
     | 
| 
      
 33 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]] }
         
     | 
| 
       34 
34 
     | 
    
         
             
              end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
              context 'with translate' do
         
     | 
| 
       37 
37 
     | 
    
         
             
                let(:transform) { 'translate(10 20)' }
         
     | 
| 
       38 
     | 
    
         
            -
                it { is_expected.to eq [1, 0, 0,  
     | 
| 
      
 38 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, 0, 10.0], [0, 1, -20.0], [0, 0, 1.0]] }
         
     | 
| 
       39 
39 
     | 
    
         
             
              end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
              context 'with single argument translate' do
         
     | 
| 
       42 
42 
     | 
    
         
             
                let(:transform) { 'translate(10)' }
         
     | 
| 
       43 
     | 
    
         
            -
                it { is_expected.to eq [1, 0, 0, 1,  
     | 
| 
      
 43 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, 0, 10.0], [0, 1, 0.0], [0, 0, 1.0]] }
         
     | 
| 
       44 
44 
     | 
    
         
             
              end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
              context 'with translateX' do
         
     | 
| 
       47 
47 
     | 
    
         
             
                let(:transform) { 'translateX(10)' }
         
     | 
| 
       48 
     | 
    
         
            -
                it { is_expected.to eq [1, 0, 0, 1,  
     | 
| 
      
 48 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, 0, 10.0], [0, 1, 0.0], [0, 0, 1.0]] }
         
     | 
| 
       49 
49 
     | 
    
         
             
              end
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
51 
     | 
    
         
             
              context 'with translateY' do
         
     | 
| 
       52 
52 
     | 
    
         
             
                let(:transform) { 'translateY(10)' }
         
     | 
| 
       53 
     | 
    
         
            -
                it { is_expected.to eq [1, 0, 0,  
     | 
| 
      
 53 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, 0, 0.0], [0, 1, -10.0], [0, 0, 1.0]] }
         
     | 
| 
       54 
54 
     | 
    
         
             
              end
         
     | 
| 
       55 
55 
     | 
    
         | 
| 
       56 
56 
     | 
    
         
             
              let(:sin30) { Math.sin(30 * Math::PI / 180.0) }
         
     | 
| 
         @@ -59,36 +59,36 @@ RSpec.describe Prawn::SVG::TransformParser do 
     | 
|
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
              context 'with single argument rotate' do
         
     | 
| 
       61 
61 
     | 
    
         
             
                let(:transform) { 'rotate(30)' }
         
     | 
| 
       62 
     | 
    
         
            -
                it { is_expected.to eq [cos30,  
     | 
| 
      
 62 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[cos30, sin30, 0], [-sin30, cos30, 0], [0.0, 0.0, 1]] }
         
     | 
| 
       63 
63 
     | 
    
         
             
              end
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
65 
     | 
    
         
             
              context 'with triple argument rotate' do
         
     | 
| 
       66 
66 
     | 
    
         
             
                let(:transform) { 'rotate(30 100 200)' }
         
     | 
| 
       67 
     | 
    
         
            -
                it { is_expected.to eq [cos30,  
     | 
| 
      
 67 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[cos30, sin30, 113.39745962155611], [-sin30, cos30, 23.205080756887753], [0.0, 0.0, 1.0]] }
         
     | 
| 
       68 
68 
     | 
    
         
             
              end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
       70 
70 
     | 
    
         
             
              context 'with scale' do
         
     | 
| 
       71 
71 
     | 
    
         
             
                let(:transform) { 'scale(1.5)' }
         
     | 
| 
       72 
     | 
    
         
            -
                it { is_expected.to eq [1.5, 0, 0, 1.5, 0, 0] }
         
     | 
| 
      
 72 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1.5, 0.0, 0], [0.0, 1.5, 0], [0.0, 0.0, 1]] }
         
     | 
| 
       73 
73 
     | 
    
         
             
              end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
              context 'with skewX' do
         
     | 
| 
       76 
76 
     | 
    
         
             
                let(:transform) { 'skewX(30)' }
         
     | 
| 
       77 
     | 
    
         
            -
                it { is_expected.to eq [1, 0,  
     | 
| 
      
 77 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1, -tan30, 0], [0, 1.0, 0], [0, 0.0, 1]] }
         
     | 
| 
       78 
78 
     | 
    
         
             
              end
         
     | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
80 
     | 
    
         
             
              context 'with skewY' do
         
     | 
| 
       81 
81 
     | 
    
         
             
                let(:transform) { 'skewY(30)' }
         
     | 
| 
       82 
     | 
    
         
            -
                it { is_expected.to eq [1, -tan30, 0,  
     | 
| 
      
 82 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1.0, 0, 0], [-tan30, 1, 0], [0.0, 0, 1]] }
         
     | 
| 
       83 
83 
     | 
    
         
             
              end
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
85 
     | 
    
         
             
              context 'with matrix' do
         
     | 
| 
       86 
86 
     | 
    
         
             
                let(:transform) { 'matrix(1 2 3 4 5 6)' }
         
     | 
| 
       87 
     | 
    
         
            -
                it { is_expected.to eq [1, - 
     | 
| 
      
 87 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[1.0, -3.0, 5.0], [-2.0, 4.0, -6.0], [0.0, 0.0, 1.0]] }
         
     | 
| 
       88 
88 
     | 
    
         
             
              end
         
     | 
| 
       89 
89 
     | 
    
         | 
| 
       90 
90 
     | 
    
         
             
              context 'with multiple' do
         
     | 
| 
       91 
91 
     | 
    
         
             
                let(:transform) { 'scale(2) translate(7) scale(3)' }
         
     | 
| 
       92 
     | 
    
         
            -
                it { is_expected.to eq [6, 0, 0, 6,  
     | 
| 
      
 92 
     | 
    
         
            +
                it { is_expected.to eq Matrix[[6.0, 0.0, 14.0], [0.0, 6.0, 0.0], [0.0, 0.0, 1.0]] }
         
     | 
| 
       93 
93 
     | 
    
         
             
              end
         
     | 
| 
       94 
94 
     | 
    
         
             
            end
         
     |