prawn-svg 0.34.2 → 0.35.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +19 -0
  3. data/.github/workflows/test.yml +14 -27
  4. data/.gitignore +0 -1
  5. data/.rubocop.yml +86 -0
  6. data/.rubocop_todo.yml +51 -0
  7. data/Gemfile +4 -3
  8. data/Gemfile.lock +81 -0
  9. data/README.md +1 -1
  10. data/Rakefile +1 -1
  11. data/lib/prawn/svg/attributes/clip_path.rb +3 -3
  12. data/lib/prawn/svg/attributes/opacity.rb +3 -3
  13. data/lib/prawn/svg/attributes/stroke.rb +9 -9
  14. data/lib/prawn/svg/attributes/transform.rb +2 -2
  15. data/lib/prawn/svg/attributes.rb +1 -1
  16. data/lib/prawn/svg/calculators/arc_to_bezier_curve.rb +17 -15
  17. data/lib/prawn/svg/calculators/aspect_ratio.rb +16 -14
  18. data/lib/prawn/svg/calculators/document_sizing.rb +9 -10
  19. data/lib/prawn/svg/calculators/pixels.rb +8 -5
  20. data/lib/prawn/svg/color.rb +209 -212
  21. data/lib/prawn/svg/css/font_family_parser.rb +2 -2
  22. data/lib/prawn/svg/css/selector_parser.rb +39 -35
  23. data/lib/prawn/svg/css/stylesheets.rb +24 -24
  24. data/lib/prawn/svg/css/values_parser.rb +68 -0
  25. data/lib/prawn/svg/document.rb +6 -5
  26. data/lib/prawn/svg/elements/base.rb +29 -34
  27. data/lib/prawn/svg/elements/circle.rb +4 -4
  28. data/lib/prawn/svg/elements/clip_path.rb +0 -1
  29. data/lib/prawn/svg/elements/depth_first_base.rb +6 -6
  30. data/lib/prawn/svg/elements/ellipse.rb +3 -4
  31. data/lib/prawn/svg/elements/gradient.rb +49 -51
  32. data/lib/prawn/svg/elements/image.rb +5 -5
  33. data/lib/prawn/svg/elements/marker.rb +5 -5
  34. data/lib/prawn/svg/elements/path.rb +46 -47
  35. data/lib/prawn/svg/elements/polygon.rb +1 -1
  36. data/lib/prawn/svg/elements/polyline.rb +2 -2
  37. data/lib/prawn/svg/elements/rect.rb +3 -3
  38. data/lib/prawn/svg/elements/text.rb +1 -1
  39. data/lib/prawn/svg/elements/text_component.rb +22 -22
  40. data/lib/prawn/svg/elements/use.rb +3 -7
  41. data/lib/prawn/svg/elements/viewport.rb +1 -3
  42. data/lib/prawn/svg/elements.rb +30 -29
  43. data/lib/prawn/svg/extension.rb +2 -1
  44. data/lib/prawn/svg/font.rb +7 -7
  45. data/lib/prawn/svg/font_registry.rb +13 -13
  46. data/lib/prawn/svg/gradients.rb +3 -2
  47. data/lib/prawn/svg/interface.rb +4 -3
  48. data/lib/prawn/svg/loaders/data.rb +2 -2
  49. data/lib/prawn/svg/loaders/file.rb +12 -14
  50. data/lib/prawn/svg/loaders/web.rb +4 -8
  51. data/lib/prawn/svg/pathable.rb +41 -37
  52. data/lib/prawn/svg/properties.rb +34 -33
  53. data/lib/prawn/svg/renderer.rb +7 -7
  54. data/lib/prawn/svg/state.rb +1 -1
  55. data/lib/prawn/svg/transform_parser.rb +5 -5
  56. data/lib/prawn/svg/ttf.rb +21 -17
  57. data/lib/prawn/svg/url_loader.rb +1 -1
  58. data/lib/prawn/svg/version.rb +1 -1
  59. data/lib/prawn-svg.rb +1 -0
  60. data/prawn-svg.gemspec +4 -6
  61. data/spec/integration_spec.rb +77 -70
  62. data/spec/prawn/svg/attributes/opacity_spec.rb +11 -15
  63. data/spec/prawn/svg/attributes/transform_spec.rb +6 -6
  64. data/spec/prawn/svg/calculators/aspect_ratio_spec.rb +50 -50
  65. data/spec/prawn/svg/calculators/document_sizing_spec.rb +35 -35
  66. data/spec/prawn/svg/calculators/pixels_spec.rb +31 -30
  67. data/spec/prawn/svg/color_spec.rb +31 -31
  68. data/spec/prawn/svg/css/font_family_parser_spec.rb +12 -12
  69. data/spec/prawn/svg/css/selector_parser_spec.rb +21 -21
  70. data/spec/prawn/svg/css/stylesheets_spec.rb +51 -45
  71. data/spec/prawn/svg/css/values_parser_spec.rb +16 -0
  72. data/spec/prawn/svg/document_spec.rb +15 -14
  73. data/spec/prawn/svg/elements/base_spec.rb +39 -34
  74. data/spec/prawn/svg/elements/gradient_spec.rb +39 -39
  75. data/spec/prawn/svg/elements/line_spec.rb +22 -22
  76. data/spec/prawn/svg/elements/marker_spec.rb +36 -40
  77. data/spec/prawn/svg/elements/path_spec.rb +134 -110
  78. data/spec/prawn/svg/elements/polygon_spec.rb +18 -18
  79. data/spec/prawn/svg/elements/polyline_spec.rb +16 -16
  80. data/spec/prawn/svg/elements/text_spec.rb +149 -127
  81. data/spec/prawn/svg/font_registry_spec.rb +34 -34
  82. data/spec/prawn/svg/font_spec.rb +4 -4
  83. data/spec/prawn/svg/interface_spec.rb +47 -39
  84. data/spec/prawn/svg/loaders/data_spec.rb +21 -21
  85. data/spec/prawn/svg/loaders/file_spec.rb +43 -40
  86. data/spec/prawn/svg/loaders/web_spec.rb +15 -15
  87. data/spec/prawn/svg/pathable_spec.rb +21 -21
  88. data/spec/prawn/svg/properties_spec.rb +51 -51
  89. data/spec/prawn/svg/transform_parser_spec.rb +12 -12
  90. data/spec/prawn/svg/ttf_spec.rb +5 -5
  91. data/spec/prawn/svg/url_loader_spec.rb +25 -23
  92. data/spec/spec_helper.rb +4 -4
  93. metadata +12 -143
@@ -9,7 +9,7 @@ class Prawn::SVG::Elements::Use < Prawn::SVG::Elements::Base
9
9
  raise SkipElementError, 'use tag has an href that is not a reference to an id; this is not supported'
10
10
  end
11
11
 
12
- id = href[1..-1]
12
+ id = href[1..]
13
13
  referenced_element = @document.elements_by_id[id]
14
14
 
15
15
  if referenced_element
@@ -28,9 +28,7 @@ class Prawn::SVG::Elements::Use < Prawn::SVG::Elements::Base
28
28
 
29
29
  raise SkipElementError, "no tag with ID '#{id}' was found, referenced by use tag" if referenced_element_class.nil?
30
30
 
31
- if referenced_element_source.name == 'symbol'
32
- @referenced_element_class = Prawn::SVG::Elements::Viewport
33
- end
31
+ @referenced_element_class = Prawn::SVG::Elements::Viewport if referenced_element_source.name == 'symbol'
34
32
 
35
33
  state.inside_use = true
36
34
 
@@ -45,9 +43,7 @@ class Prawn::SVG::Elements::Use < Prawn::SVG::Elements::Base
45
43
  end
46
44
 
47
45
  def apply
48
- if @x || @y
49
- add_call_and_enter 'translate', x_pixels(@x || 0), -y_pixels(@y || 0)
50
- end
46
+ add_call_and_enter 'translate', x_pixels(@x || 0), -y_pixels(@y || 0) if @x || @y
51
47
  end
52
48
 
53
49
  def process_child_elements
@@ -12,9 +12,7 @@ class Prawn::SVG::Elements::Viewport < Prawn::SVG::Elements::Base
12
12
  end
13
13
 
14
14
  def apply
15
- if @x != 0 || @y != 0
16
- add_call 'transformation_matrix', 1, 0, 0, 1, @x, -@y
17
- end
15
+ add_call 'transformation_matrix', 1, 0, 0, 1, @x, -@y if @x != 0 || @y != 0
18
16
 
19
17
  if overflow_hidden?
20
18
  add_call 'rectangle', [0, y(0)], @sizing.output_width, @sizing.output_height
@@ -1,42 +1,43 @@
1
1
  module Prawn::SVG::Elements
2
- COMMA_WSP_REGEXP = /(?:\s+,?\s*|,\s*)/
2
+ COMMA_WSP_REGEXP = /(?:\s+,?\s*|,\s*)/.freeze
3
3
  end
4
4
 
5
5
  require 'prawn/svg/elements/call_duplicator'
6
6
 
7
- %w(base depth_first_base root container clip_path viewport text text_component line polyline polygon circle ellipse rect path use image gradient marker ignored).each do |filename|
7
+ %w[base depth_first_base root container clip_path viewport text text_component line polyline polygon circle ellipse
8
+ rect path use image gradient marker ignored].each do |filename|
8
9
  require "prawn/svg/elements/#{filename}"
9
10
  end
10
11
 
11
12
  module Prawn::SVG::Elements
12
13
  TAG_CLASS_MAPPING = {
13
- g: Prawn::SVG::Elements::Container,
14
- symbol: Prawn::SVG::Elements::Container,
15
- defs: Prawn::SVG::Elements::Container,
16
- a: Prawn::SVG::Elements::Container,
17
- clipPath: Prawn::SVG::Elements::ClipPath,
18
- switch: Prawn::SVG::Elements::Container,
19
- svg: Prawn::SVG::Elements::Viewport,
20
- text: Prawn::SVG::Elements::Text,
21
- line: Prawn::SVG::Elements::Line,
22
- polyline: Prawn::SVG::Elements::Polyline,
23
- polygon: Prawn::SVG::Elements::Polygon,
24
- circle: Prawn::SVG::Elements::Circle,
25
- ellipse: Prawn::SVG::Elements::Ellipse,
26
- rect: Prawn::SVG::Elements::Rect,
27
- path: Prawn::SVG::Elements::Path,
28
- use: Prawn::SVG::Elements::Use,
29
- image: Prawn::SVG::Elements::Image,
14
+ g: Prawn::SVG::Elements::Container,
15
+ symbol: Prawn::SVG::Elements::Container,
16
+ defs: Prawn::SVG::Elements::Container,
17
+ a: Prawn::SVG::Elements::Container,
18
+ clipPath: Prawn::SVG::Elements::ClipPath,
19
+ switch: Prawn::SVG::Elements::Container,
20
+ svg: Prawn::SVG::Elements::Viewport,
21
+ text: Prawn::SVG::Elements::Text,
22
+ line: Prawn::SVG::Elements::Line,
23
+ polyline: Prawn::SVG::Elements::Polyline,
24
+ polygon: Prawn::SVG::Elements::Polygon,
25
+ circle: Prawn::SVG::Elements::Circle,
26
+ ellipse: Prawn::SVG::Elements::Ellipse,
27
+ rect: Prawn::SVG::Elements::Rect,
28
+ path: Prawn::SVG::Elements::Path,
29
+ use: Prawn::SVG::Elements::Use,
30
+ image: Prawn::SVG::Elements::Image,
30
31
  linearGradient: Prawn::SVG::Elements::Gradient,
31
32
  radialGradient: Prawn::SVG::Elements::Gradient,
32
- marker: Prawn::SVG::Elements::Marker,
33
- style: Prawn::SVG::Elements::Ignored, # because it is pre-parsed by Document
34
- title: Prawn::SVG::Elements::Ignored,
35
- desc: Prawn::SVG::Elements::Ignored,
36
- metadata: Prawn::SVG::Elements::Ignored,
37
- foreignObject: Prawn::SVG::Elements::Ignored,
38
- :"font-face" => Prawn::SVG::Elements::Ignored,
39
- filter: Prawn::SVG::Elements::Ignored, # unsupported
40
- mask: Prawn::SVG::Elements::Ignored, # unsupported
41
- }
33
+ marker: Prawn::SVG::Elements::Marker,
34
+ style: Prawn::SVG::Elements::Ignored, # because it is pre-parsed by Document
35
+ title: Prawn::SVG::Elements::Ignored,
36
+ desc: Prawn::SVG::Elements::Ignored,
37
+ metadata: Prawn::SVG::Elements::Ignored,
38
+ foreignObject: Prawn::SVG::Elements::Ignored,
39
+ 'font-face': Prawn::SVG::Elements::Ignored,
40
+ filter: Prawn::SVG::Elements::Ignored, # unsupported
41
+ mask: Prawn::SVG::Elements::Ignored # unsupported
42
+ }.freeze
42
43
  end
@@ -17,7 +17,8 @@ module Prawn
17
17
  def svg(data, options = {}, &block)
18
18
  svg = Prawn::SVG::Interface.new(data, self, options, &block)
19
19
  svg.draw
20
- {:warnings => svg.document.warnings, :width => svg.document.sizing.output_width, :height => svg.document.sizing.output_height}
20
+ { warnings: svg.document.warnings, width: svg.document.sizing.output_width,
21
+ height: svg.document.sizing.output_height }
21
22
  end
22
23
  end
23
24
  end
@@ -1,11 +1,11 @@
1
1
  class Prawn::SVG::Font
2
2
  GENERIC_CSS_FONT_MAPPING = {
3
- "serif" => "Times-Roman",
4
- "sans-serif" => "Helvetica",
5
- "cursive" => "Times-Roman",
6
- "fantasy" => "Times-Roman",
7
- "monospace" => "Courier"
8
- }
3
+ 'serif' => 'Times-Roman',
4
+ 'sans-serif' => 'Helvetica',
5
+ 'cursive' => 'Times-Roman',
6
+ 'fantasy' => 'Times-Roman',
7
+ 'monospace' => 'Courier'
8
+ }.freeze
9
9
 
10
10
  attr_reader :name, :weight, :style
11
11
 
@@ -38,7 +38,7 @@ class Prawn::SVG::Font
38
38
 
39
39
  # Construct a subfamily name, ensuring that the subfamily is a valid one for the font.
40
40
  def subfamily
41
- if subfamilies = @font_registry.installed_fonts[name]
41
+ if (subfamilies = @font_registry.installed_fonts[name])
42
42
  if subfamilies.key?(subfamily_name)
43
43
  subfamily_name
44
44
  elsif subfamilies.key?(:normal)
@@ -1,11 +1,11 @@
1
1
  class Prawn::SVG::FontRegistry
2
2
  DEFAULT_FONT_PATHS = [
3
- "/Library/Fonts",
4
- "/System/Library/Fonts",
5
- "#{ENV["HOME"]}/Library/Fonts",
6
- "/usr/share/fonts/truetype",
7
- "/mnt/c/Windows/Fonts", # Bash on Ubuntu on Windows
8
- ]
3
+ '/Library/Fonts',
4
+ '/System/Library/Fonts',
5
+ "#{Dir.home}/Library/Fonts",
6
+ '/usr/share/fonts/truetype',
7
+ '/mnt/c/Windows/Fonts' # Bash on Ubuntu on Windows
8
+ ].freeze
9
9
 
10
10
  @font_path = DEFAULT_FONT_PATHS.select { |path| Dir.exist?(path) }
11
11
 
@@ -37,8 +37,8 @@ class Prawn::SVG::FontRegistry
37
37
  def merge_external_fonts
38
38
  if @font_case_mapping.nil?
39
39
  self.class.load_external_fonts unless self.class.external_font_families
40
- @font_families.merge!(self.class.external_font_families) do |key, v1, v2|
41
- v1
40
+ @font_families.merge!(self.class.external_font_families) do |_key, v1, _v2|
41
+ v1
42
42
  end
43
43
  @font_case_mapping = @font_families.keys.each.with_object({}) do |key, result|
44
44
  result[key.downcase] = key
@@ -54,11 +54,11 @@ class Prawn::SVG::FontRegistry
54
54
 
55
55
  external_font_paths.each do |filename|
56
56
  ttf = Prawn::SVG::TTF.new(filename)
57
- if ttf.family
58
- subfamily = (ttf.subfamily || "normal").gsub(/\s+/, "_").downcase.to_sym
59
- subfamily = :normal if subfamily == :regular
60
- (external_font_families[ttf.family] ||= {})[subfamily] ||= filename
61
- end
57
+ next unless ttf.family
58
+
59
+ subfamily = (ttf.subfamily || 'normal').gsub(/\s+/, '_').downcase.to_sym
60
+ subfamily = :normal if subfamily == :regular
61
+ (external_font_families[ttf.family] ||= {})[subfamily] ||= filename
62
62
  end
63
63
  end
64
64
 
@@ -9,9 +9,9 @@ module Prawn::SVG
9
9
  id &&= id.strip
10
10
  return unless id && id != ''
11
11
 
12
- if element = @gradients_by_id[id]
12
+ if (element = @gradients_by_id[id])
13
13
  element
14
- elsif raw_element = find_raw_gradient_element_by_id(id)
14
+ elsif (raw_element = find_raw_gradient_element_by_id(id))
15
15
  create_gradient_element(raw_element)
16
16
  end
17
17
  end
@@ -37,6 +37,7 @@ module Prawn::SVG
37
37
 
38
38
  def gradient_element?(raw_element)
39
39
  return false if raw_element.nil? || raw_element.name.nil?
40
+
40
41
  Elements::TAG_CLASS_MAPPING[raw_element.name.to_sym] == Elements::Gradient
41
42
  end
42
43
 
@@ -8,12 +8,12 @@ module Prawn
8
8
  VALID_OPTIONS = %i[
9
9
  at position vposition width height cache_images enable_web_requests
10
10
  enable_file_requests_with_root fallback_font_name color_mode
11
- ]
11
+ ].freeze
12
12
 
13
13
  INHERITABLE_OPTIONS = %i[
14
14
  enable_web_requests enable_file_requests_with_root
15
15
  cache_images fallback_font_name color_mode
16
- ]
16
+ ].freeze
17
17
 
18
18
  attr_reader :data, :prawn, :document, :options
19
19
 
@@ -60,7 +60,8 @@ module Prawn
60
60
  @renderer.position
61
61
  end
62
62
 
63
- def self.font_path # backwards support for when the font_path used to be stored on this class
63
+ # backwards support for when the font_path used to be stored on this class
64
+ def self.font_path
64
65
  Prawn::SVG::FontRegistry.font_path
65
66
  end
66
67
  end
@@ -1,6 +1,6 @@
1
1
  module Prawn::SVG::Loaders
2
2
  class Data
3
- REGEXP = %r{\Adata:image/(png|jpeg|svg\+xml);base64(;[a-z0-9]+)*,}i
3
+ REGEXP = %r{\Adata:image/(png|jpeg|svg\+xml);base64(;[a-z0-9]+)*,}i.freeze
4
4
 
5
5
  def from_url(url)
6
6
  return if url[0..4].downcase != 'data:'
@@ -8,7 +8,7 @@ module Prawn::SVG::Loaders
8
8
  matches = url.match(REGEXP)
9
9
  if matches.nil?
10
10
  raise Prawn::SVG::UrlLoader::Error,
11
- 'prawn-svg only supports base64-encoded image/png, image/jpeg, and image/svg+xml data URLs'
11
+ 'prawn-svg only supports base64-encoded image/png, image/jpeg, and image/svg+xml data URLs'
12
12
  end
13
13
 
14
14
  matches.post_match.unpack1('m')
@@ -24,7 +24,7 @@ require 'addressable/uri'
24
24
  # FILES READ AS BINARY
25
25
  # ====================
26
26
  # At the moment, prawn-svg uses this class only to load graphical files, which are binary.
27
- # This class therefore uses IO.binread to read file data. If it is ever used in the future
27
+ # This class therefore uses File.binread to read file data. If it is ever used in the future
28
28
  # to load text files, it will have to be taught about what kind of file it's expecting to
29
29
  # read, and adjust the file read function accordingly.
30
30
  #
@@ -34,7 +34,8 @@ module Prawn::SVG::Loaders
34
34
 
35
35
  def initialize(root_path)
36
36
  if root_path.empty?
37
- raise ArgumentError, "An empty string is not a valid root path. Use '.' if you want the current working directory."
37
+ raise ArgumentError,
38
+ "An empty string is not a valid root path. Use '.' if you want the current working directory."
38
39
  end
39
40
 
40
41
  @root_path = ::File.expand_path(root_path)
@@ -62,14 +63,12 @@ module Prawn::SVG::Loaders
62
63
  path = build_absolute_and_expand_path(path)
63
64
  assert_valid_path!(path)
64
65
  assert_file_exists!(path)
65
- IO.binread(path)
66
+ ::File.binread(path)
66
67
  end
67
68
 
68
69
  def build_uri(url)
69
- begin
70
- URI(url)
71
- rescue URI::InvalidURIError
72
- end
70
+ URI(url)
71
+ rescue URI::InvalidURIError
73
72
  end
74
73
 
75
74
  def assert_valid_path!(path)
@@ -77,7 +76,7 @@ module Prawn::SVG::Loaders
77
76
  # making it dependent on whether the file system is case sensitive or not.
78
77
  # Leaving it like this until it's a problem for someone.
79
78
 
80
- if !path.start_with?("#{root_path}#{::File::SEPARATOR}")
79
+ unless path.start_with?("#{root_path}#{::File::SEPARATOR}")
81
80
  raise Prawn::SVG::UrlLoader::Error, "file path is not inside the root path of #{root_path}"
82
81
  end
83
82
  end
@@ -88,19 +87,18 @@ module Prawn::SVG::Loaders
88
87
 
89
88
  def assert_valid_file_uri!(uri)
90
89
  unless uri.host.nil? || uri.host.empty?
91
- raise Prawn::SVG::UrlLoader::Error, "prawn-svg does not suport file: URLs with a host. Your URL probably doesn't start with three slashes, and it should."
90
+ raise Prawn::SVG::UrlLoader::Error,
91
+ "prawn-svg does not suport file: URLs with a host. Your URL probably doesn't start with three slashes, and it should."
92
92
  end
93
93
  end
94
94
 
95
95
  def assert_file_exists!(path)
96
- if !::File.exist?(path)
97
- raise Prawn::SVG::UrlLoader::Error, "File #{path} does not exist"
98
- end
96
+ raise Prawn::SVG::UrlLoader::Error, "File #{path} does not exist" unless ::File.exist?(path)
99
97
  end
100
98
 
101
99
  def fix_windows_path(path)
102
- if matches = path.match(%r(\A/[a-z]:/)i)
103
- path[1..-1]
100
+ if path.match(%r{\A/[a-z]:/}i)
101
+ path[1..]
104
102
  else
105
103
  path
106
104
  end
@@ -5,23 +5,19 @@ module Prawn::SVG::Loaders
5
5
  def from_url(url)
6
6
  uri = build_uri(url)
7
7
 
8
- if uri && %w(http https).include?(uri.scheme)
9
- perform_request(uri)
10
- end
8
+ perform_request(uri) if uri && %w[http https].include?(uri.scheme)
11
9
  end
12
10
 
13
11
  private
14
12
 
15
13
  def build_uri(url)
16
- begin
17
- URI(url)
18
- rescue URI::InvalidURIError
19
- end
14
+ URI(url)
15
+ rescue URI::InvalidURIError
20
16
  end
21
17
 
22
18
  def perform_request(uri)
23
19
  Net::HTTP.get(uri)
24
- rescue => e
20
+ rescue StandardError => e
25
21
  raise Prawn::SVG::UrlLoader::Error, e.message
26
22
  end
27
23
  end
@@ -24,25 +24,26 @@ module Prawn::SVG::Pathable
24
24
  when Line
25
25
  add_call 'line_to', translate(command.destination)
26
26
  when Curve
27
- add_call 'curve_to', translate(command.destination), bounds: [translate(command.point1), translate(command.point2)]
27
+ add_call 'curve_to', translate(command.destination),
28
+ bounds: [translate(command.point1), translate(command.point2)]
28
29
  else
29
- raise NotImplementedError, "Unknown path command type"
30
+ raise NotImplementedError, 'Unknown path command type'
30
31
  end
31
32
  end
32
33
  end
33
34
 
34
35
  def apply_markers
35
- if marker = extract_element_from_url_id_reference(properties.marker_start, "marker")
36
+ if (marker = extract_element_from_url_id_reference(properties.marker_start, 'marker'))
36
37
  marker.apply_marker(self, point: commands.first.destination, angle: angles.first)
37
38
  end
38
39
 
39
- if marker = extract_element_from_url_id_reference(properties.marker_mid, "marker")
40
- (1..commands.length-2).each do |index|
40
+ if (marker = extract_element_from_url_id_reference(properties.marker_mid, 'marker'))
41
+ (1..commands.length - 2).each do |index|
41
42
  marker.apply_marker(self, point: commands[index].destination, angle: angles[index])
42
43
  end
43
44
  end
44
45
 
45
- if marker = extract_element_from_url_id_reference(properties.marker_end, "marker")
46
+ if (marker = extract_element_from_url_id_reference(properties.marker_end, 'marker'))
46
47
  marker.apply_marker(self, point: commands.last.destination, angle: angles.last)
47
48
  end
48
49
  end
@@ -53,23 +54,26 @@ module Prawn::SVG::Pathable
53
54
  last_point = nil
54
55
 
55
56
  destination_angles = commands.map do |command|
56
- angles = case command
57
- when Move
58
- [nil, nil]
59
- when Close, Line
60
- angle = Math.atan2(command.destination[1] - last_point[1], command.destination[0] - last_point[0]) * 180.0 / Math::PI
61
- [angle, angle]
62
- when Curve
63
- point = select_non_equal_point(last_point, command.point1, command.point2, command.destination)
64
- start = Math.atan2(point[1] - last_point[1], point[0] - last_point[0]) * 180.0 / Math::PI
65
-
66
- point = select_non_equal_point(command.destination, command.point2, command.point1, last_point)
67
- stop = Math.atan2(command.destination[1] - point[1], command.destination[0] - point[0]) * 180.0 / Math::PI
68
-
69
- [start, stop]
70
- else
71
- raise NotImplementedError, "Unknown path command type"
72
- end
57
+ angles =
58
+ case command
59
+ when Move
60
+ [nil, nil]
61
+ when Close, Line
62
+ angle = Math.atan2(command.destination[1] - last_point[1],
63
+ command.destination[0] - last_point[0]) * 180.0 / Math::PI
64
+ [angle, angle]
65
+ when Curve
66
+ point = select_non_equal_point(last_point, command.point1, command.point2, command.destination)
67
+ start = Math.atan2(point[1] - last_point[1], point[0] - last_point[0]) * 180.0 / Math::PI
68
+
69
+ point = select_non_equal_point(command.destination, command.point2, command.point1, last_point)
70
+ stop = Math.atan2(command.destination[1] - point[1],
71
+ command.destination[0] - point[0]) * 180.0 / Math::PI
72
+
73
+ [start, stop]
74
+ else
75
+ raise NotImplementedError, 'Unknown path command type'
76
+ end
73
77
 
74
78
  last_point = command.destination
75
79
  angles
@@ -99,10 +103,10 @@ module Prawn::SVG::Pathable
99
103
  bisect = (first + second) / 2.0
100
104
 
101
105
  angles << if (first - second).abs > 180
102
- bisect >= 0 ? bisect - 180 : bisect + 180
103
- else
104
- bisect
105
- end
106
+ bisect >= 0 ? bisect - 180 : bisect + 180
107
+ else
108
+ bisect
109
+ end
106
110
  else
107
111
  angles << destination_angles.last.last
108
112
  end
@@ -111,19 +115,19 @@ module Prawn::SVG::Pathable
111
115
  end
112
116
 
113
117
  def parse_points(points_string)
114
- values = points_string.
115
- to_s.
116
- strip.
117
- gsub(/(\d)-(\d)/, '\1 -\2').
118
- split(Prawn::SVG::Elements::COMMA_WSP_REGEXP).
119
- map(&:to_f)
120
-
121
- if values.length % 2 == 1
122
- document.warnings << "points attribute has an odd number of points; ignoring the last one"
118
+ values = points_string
119
+ .to_s
120
+ .strip
121
+ .gsub(/(\d)-(\d)/, '\1 -\2')
122
+ .split(Prawn::SVG::Elements::COMMA_WSP_REGEXP)
123
+ .map(&:to_f)
124
+
125
+ if values.length.odd?
126
+ document.warnings << 'points attribute has an odd number of points; ignoring the last one'
123
127
  values.pop
124
128
  end
125
129
 
126
- raise Prawn::SVG::Elements::Base::SkipElementQuietly if values.length == 0
130
+ raise Prawn::SVG::Elements::Base::SkipElementQuietly if values.empty?
127
131
 
128
132
  values.each_slice(2).to_a
129
133
  end
@@ -10,40 +10,41 @@ class Prawn::SVG::Properties
10
10
  'large' => EM / 4 * 5,
11
11
  'x-large' => EM / 4 * 6,
12
12
  'xx-large' => EM / 4 * 7
13
- }
13
+ }.freeze
14
14
 
15
15
  PROPERTIES = {
16
- "clip-path" => Config.new("none", false, %w(inherit none)),
17
- "color" => Config.new('', true),
18
- "display" => Config.new("inline", false, %w(inherit inline none), true),
19
- "fill" => Config.new("black", true, %w(inherit none currentColor)),
20
- "fill-opacity" => Config.new("1", true),
21
- "fill-rule" => Config.new("nonzero", true, %w(inherit nonzero evenodd)),
22
- "font-family" => Config.new("sans-serif", true),
23
- "font-size" => Config.new("medium", true, %w(inherit xx-small x-small small medium large x-large xx-large larger smaller)),
24
- "font-style" => Config.new("normal", true, %w(inherit normal italic oblique), true),
25
- "font-variant" => Config.new("normal", true, %w(inherit normal small-caps), true),
26
- "font-weight" => Config.new("normal", true, %w(inherit normal bold 100 200 300 400 500 600 700 800 900), true), # bolder/lighter not supported
27
- "letter-spacing" => Config.new("normal", true, %w(inherit normal)),
28
- "marker-end" => Config.new("none", true, %w(inherit none)),
29
- "marker-mid" => Config.new("none", true, %w(inherit none)),
30
- "marker-start" => Config.new("none", true, %w(inherit none)),
31
- "opacity" => Config.new("1", false),
32
- "overflow" => Config.new('visible', false, %w(inherit visible hidden scroll auto), true),
33
- "stop-color" => Config.new("black", false, %w(inherit none currentColor)),
34
- "stroke" => Config.new("none", true, %w(inherit none currentColor)),
35
- "stroke-dasharray" => Config.new("none", true, %w(inherit none)),
36
- "stroke-linecap" => Config.new("butt", true, %w(inherit butt round square), true),
37
- "stroke-linejoin" => Config.new("miter", true, %w(inherit miter round bevel), true),
38
- "stroke-opacity" => Config.new("1", true),
39
- "stroke-width" => Config.new("1", true),
40
- "text-anchor" => Config.new("start", true, %w(inherit start middle end), true),
41
- 'text-decoration' => Config.new('none', true, %w(inherit none underline), true),
42
- "dominant-baseline" => Config.new("auto", true, %w(inherit auto middle), true),
16
+ 'clip-path' => Config.new('none', false, %w[inherit none]),
17
+ 'color' => Config.new('', true),
18
+ 'display' => Config.new('inline', false, %w[inherit inline none], true),
19
+ 'fill' => Config.new('black', true, %w[inherit none currentColor]),
20
+ 'fill-opacity' => Config.new('1', true),
21
+ 'fill-rule' => Config.new('nonzero', true, %w[inherit nonzero evenodd]),
22
+ 'font-family' => Config.new('sans-serif', true),
23
+ 'font-size' => Config.new('medium', true,
24
+ %w[inherit xx-small x-small small medium large x-large xx-large larger smaller]),
25
+ 'font-style' => Config.new('normal', true, %w[inherit normal italic oblique], true),
26
+ 'font-variant' => Config.new('normal', true, %w[inherit normal small-caps], true),
27
+ 'font-weight' => Config.new('normal', true, %w[inherit normal bold 100 200 300 400 500 600 700 800 900], true), # bolder/lighter not supported
28
+ 'letter-spacing' => Config.new('normal', true, %w[inherit normal]),
29
+ 'marker-end' => Config.new('none', true, %w[inherit none]),
30
+ 'marker-mid' => Config.new('none', true, %w[inherit none]),
31
+ 'marker-start' => Config.new('none', true, %w[inherit none]),
32
+ 'opacity' => Config.new('1', false),
33
+ 'overflow' => Config.new('visible', false, %w[inherit visible hidden scroll auto], true),
34
+ 'stop-color' => Config.new('black', false, %w[inherit none currentColor]),
35
+ 'stroke' => Config.new('none', true, %w[inherit none currentColor]),
36
+ 'stroke-dasharray' => Config.new('none', true, %w[inherit none]),
37
+ 'stroke-linecap' => Config.new('butt', true, %w[inherit butt round square], true),
38
+ 'stroke-linejoin' => Config.new('miter', true, %w[inherit miter round bevel], true),
39
+ 'stroke-opacity' => Config.new('1', true),
40
+ 'stroke-width' => Config.new('1', true),
41
+ 'text-anchor' => Config.new('start', true, %w[inherit start middle end], true),
42
+ 'text-decoration' => Config.new('none', true, %w[inherit none underline], true),
43
+ 'dominant-baseline' => Config.new('auto', true, %w[inherit auto middle], true)
43
44
  }.freeze
44
45
 
45
46
  PROPERTIES.each do |name, value|
46
- value.attr = name.gsub("-", "_")
47
+ value.attr = name.gsub('-', '_')
47
48
  value.ivar = "@#{value.attr}"
48
49
  end
49
50
 
@@ -51,7 +52,7 @@ class Prawn::SVG::Properties
51
52
  NAMES = PROPERTIES.keys
52
53
  ATTR_NAMES = PROPERTIES.keys.map { |name| name.gsub('-', '_') }
53
54
 
54
- attr_accessor *ATTR_NAMES
55
+ attr_accessor(*ATTR_NAMES)
55
56
 
56
57
  def load_default_stylesheet
57
58
  PROPERTY_CONFIGS.each do |config|
@@ -62,7 +63,7 @@ class Prawn::SVG::Properties
62
63
  end
63
64
 
64
65
  def set(name, value)
65
- if config = PROPERTIES[name.to_s.downcase]
66
+ if (config = PROPERTIES[name.to_s.downcase])
66
67
  value = value.strip
67
68
  keyword = value.downcase
68
69
  keywords = config.keywords || ['inherit']
@@ -92,7 +93,7 @@ class Prawn::SVG::Properties
92
93
  value = other.send(config.attr)
93
94
 
94
95
  if value && value != 'inherit'
95
- value = compute_font_size_property(value).to_s if config.attr == "font_size"
96
+ value = compute_font_size_property(value).to_s if config.attr == 'font_size'
96
97
  instance_variable_set(config.ivar, value)
97
98
 
98
99
  elsif value.nil? && !config.inheritable?
@@ -109,7 +110,7 @@ class Prawn::SVG::Properties
109
110
  private
110
111
 
111
112
  def compute_font_size_property(value)
112
- if value[-1] == "%"
113
+ if value[-1] == '%'
113
114
  numerical_font_size * (value.to_f / 100.0)
114
115
  elsif value == 'larger'
115
116
  numerical_font_size + 4
@@ -74,7 +74,7 @@ module Prawn
74
74
  when :top
75
75
  sizing.bounds[1]
76
76
  when :center, :centre
77
- sizing.bounds[1] - (sizing.bounds[1] - sizing.output_height) / 2.0
77
+ sizing.bounds[1] - ((sizing.bounds[1] - sizing.output_height) / 2.0)
78
78
  when :bottom
79
79
  sizing.output_height
80
80
  when Numeric
@@ -135,20 +135,20 @@ module Prawn
135
135
  @cursor = [at[0], at[1]]
136
136
  end
137
137
 
138
- if offset = options.delete(:offset)
138
+ if (offset = options.delete(:offset))
139
139
  at[0] += offset[0]
140
140
  at[1] -= offset[1]
141
141
  end
142
142
 
143
143
  width = prawn.width_of(text, options.merge(kerning: true))
144
144
 
145
- if stretch_to_width = options.delete(:stretch_to_width)
145
+ if (stretch_to_width = options.delete(:stretch_to_width))
146
146
  factor = stretch_to_width.to_f * 100 / width.to_f
147
147
  prawn.add_content "#{factor} Tz"
148
148
  width = stretch_to_width.to_f
149
149
  end
150
150
 
151
- if pad_to_width = options.delete(:pad_to_width)
151
+ if (pad_to_width = options.delete(:pad_to_width))
152
152
  padding_required = pad_to_width.to_f - width.to_f
153
153
  padding_per_character = padding_required / text.length.to_f
154
154
  prawn.add_content "#{padding_per_character} Tc"
@@ -158,7 +158,7 @@ module Prawn
158
158
  case options.delete(:text_anchor)
159
159
  when 'middle'
160
160
  at[0] -= width / 2
161
- @cursor = [at[0] + width / 2, at[1]]
161
+ @cursor = [at[0] + (width / 2), at[1]]
162
162
  when 'end'
163
163
  at[0] -= width
164
164
  @cursor = at.dup
@@ -178,8 +178,8 @@ module Prawn
178
178
  when 'transformation_matrix'
179
179
  left = prawn.bounds.absolute_left
180
180
  top = prawn.bounds.absolute_top
181
- arguments[4] += left - (left * arguments[0] + top * arguments[2])
182
- arguments[5] += top - (left * arguments[1] + top * arguments[3])
181
+ arguments[4] += left - ((left * arguments[0]) + (top * arguments[2]))
182
+ arguments[5] += top - ((left * arguments[1]) + (top * arguments[3]))
183
183
 
184
184
  when 'clip'
185
185
  prawn.add_content 'W n' # clip to path