lib/prawn/svg/calculators/document_sizing.rb in prawn-svg-0.19.0 vs lib/prawn/svg/calculators/document_sizing.rb in prawn-svg-0.20.0
- old
+ new
@@ -1,10 +1,13 @@
module Prawn::Svg::Calculators
class DocumentSizing
+ DEFAULT_WIDTH = 300
+ DEFAULT_HEIGHT = 150
+ DEFAULT_ASPECT_RATIO = "xMidYMid meet"
+
attr_writer :document_width, :document_height
attr_writer :view_box, :preserve_aspect_ratio
- attr_writer :requested_width, :requested_height
attr_reader :bounds
attr_reader :x_offset, :y_offset, :x_scale, :y_scale
attr_reader :viewport_width, :viewport_height, :viewport_diagonal, :output_width, :output_height
@@ -15,61 +18,82 @@
def set_from_attributes(attributes)
@document_width = attributes['width']
@document_height = attributes['height']
@view_box = attributes['viewBox']
- @preserve_aspect_ratio = attributes['preserveAspectRatio']
+ @preserve_aspect_ratio = attributes['preserveAspectRatio'] || DEFAULT_ASPECT_RATIO
end
def calculate
@x_offset = @y_offset = 0
@x_scale = @y_scale = 1
- width = Prawn::Svg::Calculators::Pixels.to_pixels(@document_width, @bounds[0])
- height = Prawn::Svg::Calculators::Pixels.to_pixels(@document_height, @bounds[1])
+ container_width = @requested_width || @bounds[0]
+ container_height = @requested_height || @bounds[1]
- default_aspect_ratio = "x#{width ? "Mid" : "Min"}Y#{height ? "Mid" : "Min"} meet"
+ @output_width = Pixels.to_pixels(@document_width || @requested_width, container_width)
+ @output_height = Pixels.to_pixels(@document_height || @requested_height, container_height)
- width ||= @bounds[0]
- height ||= @bounds[1]
-
if @view_box
- values = @view_box.strip.split(/\s+/)
+ values = @view_box.strip.split(Prawn::Svg::Parser::COMMA_WSP_REGEXP)
@x_offset, @y_offset, @viewport_width, @viewport_height = values.map {|value| value.to_f}
@x_offset = -@x_offset
- @preserve_aspect_ratio ||= default_aspect_ratio
- aspect = Prawn::Svg::Calculators::AspectRatio.new(@preserve_aspect_ratio, [width, height], [@viewport_width, @viewport_height])
- @x_scale = aspect.width / @viewport_width
- @y_scale = aspect.height / @viewport_height
- @x_offset -= aspect.x
- @y_offset -= aspect.y
+ if @viewport_width > 0 && @viewport_height > 0
+ @output_width ||= container_width
+ @output_height ||= @output_width * @viewport_height / @viewport_width
+
+ aspect = AspectRatio.new(@preserve_aspect_ratio, [@output_width, @output_height], [@viewport_width, @viewport_height])
+ @x_scale = aspect.width / @viewport_width
+ @y_scale = aspect.height / @viewport_height
+ @x_offset -= aspect.x / @x_scale
+ @y_offset -= aspect.y / @y_scale
+ end
+ else
+ @output_width ||= Pixels.to_pixels(DEFAULT_WIDTH, container_width)
+ @output_height ||= Pixels.to_pixels(DEFAULT_HEIGHT, container_height)
+
+ @viewport_width = @output_width
+ @viewport_height = @output_height
end
- @viewport_width ||= width
- @viewport_height ||= height
+ return if invalid?
# SVG 1.1 section 7.10
@viewport_diagonal = Math.sqrt(@viewport_width**2 + @viewport_height**2) / Math.sqrt(2)
if @requested_width
- scale = @requested_width / width
- width = @requested_width
- height *= scale
+ scale = @requested_width / @output_width
+ @output_width = @requested_width
+ @output_height *= scale
@x_scale *= scale
@y_scale *= scale
elsif @requested_height
- scale = @requested_height / height
- height = @requested_height
- width *= scale
+ scale = @requested_height / @output_height
+ @output_height = @requested_height
+ @output_width *= scale
@x_scale *= scale
@y_scale *= scale
end
- @output_width = width
- @output_height = height
-
self
+ end
+
+ def invalid?
+ @viewport_width <= 0 ||
+ @viewport_height <= 0 ||
+ @output_width <= 0 ||
+ @output_height <= 0 ||
+ (@requested_width && @requested_width <= 0) ||
+ (@requested_height && @requested_height <= 0)
+ end
+
+ def requested_width=(value)
+ @requested_width = (value.to_f if value)
+ end
+
+ def requested_height=(value)
+ @requested_height = (value.to_f if value)
end
end
end