lib/prawn/graphics.rb in prawn-0.15.0 vs lib/prawn/graphics.rb in prawn-1.0.0.rc1
- old
+ new
@@ -4,19 +4,18 @@
#
# Copyright April 2008, Gregory Brown. All Rights Reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.
+require "prawn/graphics/color"
+require "prawn/graphics/dash"
+require "prawn/graphics/cap_style"
+require "prawn/graphics/join_style"
+require "prawn/graphics/transparency"
+require "prawn/graphics/transformation"
+require "prawn/graphics/gradient"
-require_relative "graphics/color"
-require_relative "graphics/dash"
-require_relative "graphics/cap_style"
-require_relative "graphics/join_style"
-require_relative "graphics/transparency"
-require_relative "graphics/transformation"
-require_relative "graphics/patterns"
-
module Prawn
# Implements the drawing facilities for Prawn::Document.
# Use this to draw the most beautiful imaginable things.
#
@@ -29,14 +28,12 @@
include Dash
include CapStyle
include JoinStyle
include Transparency
include Transformation
- include Patterns
+ include Gradient
- # @group Stable API
-
#######################################################################
# Low level drawing operations must map the point to absolute coords! #
#######################################################################
# Moves the drawing position to a given point. The point can be
@@ -83,23 +80,23 @@
#
def rectangle(point,width,height)
x,y = map_to_absolute(point)
add_content("%.3f %.3f %.3f %.3f re" % [ x, y - height, width, height ])
end
-
+
# Draws a rounded rectangle given <tt>point</tt>, <tt>width</tt> and
- # <tt>height</tt> and <tt>radius</tt> for the rounded corner. The rectangle
+ # <tt>height</tt> and <tt>radius</tt> for the rounded corner. The rectangle
# is bounded by its upper-left corner.
#
# pdf.rounded_rectangle [300,300], 100, 200, 10
#
def rounded_rectangle(point,width,height,radius)
x, y = point
rounded_polygon(radius, point, [x + width, y], [x + width, y - height], [x, y - height])
end
+
-
###########################################################
# Higher level functions: May use relative coords #
###########################################################
# Sets line thickness to the <tt>width</tt> specified.
@@ -139,19 +136,19 @@
# Draws a horizontal line from <tt>x1</tt> to <tt>x2</tt> at the
# current <tt>y</tt> position, or the position specified by the :at option.
#
# # draw a line from [25, 75] to [100, 75]
- # horizontal_line 25, 100, :at => 75
+ # horizontal_line 25, 100, :at => 75
#
def horizontal_line(x1,x2,options={})
if options[:at]
y1 = options[:at]
else
y1 = y - bounds.absolute_bottom
end
-
+
line(x1,y1,x2,y1)
end
# Draws a horizontal line from the left border to the right border of the
# bounding box at the current <tt>y</tt> position.
@@ -182,20 +179,34 @@
# This constant is used to approximate a symmetrical arc using a cubic
# Bezier curve.
#
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
+ # <b>DEPRECATED:</b> Please use <tt>circle</tt> instead.
+ def circle_at(point, options)
+ warn "[DEPRECATION] 'circle_at' is deprecated in favor of 'circle'. " +
+ "'circle_at' will be removed in release 1.1"
+ circle(point, options[:radius])
+ end
+
# Draws a circle of radius <tt>radius</tt> with the centre-point at <tt>point</tt>
# as a complete subpath. The drawing point will be moved to the
# centre-point upon completion of the drawing the circle.
#
# pdf.circle [100,100], 25
#
def circle(center, radius)
ellipse(center, radius, radius)
end
+ # <b>DEPRECATED:</b> Please use <tt>ellipse</tt> instead.
+ def ellipse_at(point, r1, r2=r1)
+ warn "[DEPRECATION] 'ellipse_at' is deprecated in favor of 'ellipse'. " +
+ "'ellipse_at' will be removed in release 1.1"
+ ellipse(point, r1, r2)
+ end
+
# Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
# with the centre-point at <tt>point</tt> as a complete subpath. The
# drawing point will be moved to the centre-point upon completion of the
# drawing the ellipse.
#
@@ -209,23 +220,23 @@
move_to(x + r1, y)
# Upper right hand corner
curve_to [x, y + r2],
- :bounds => [[x + r1, y + l2], [x + l1, y + r2]]
+ :bounds => [[x + r1, y + l1], [x + l2, y + r2]]
# Upper left hand corner
curve_to [x - r1, y],
- :bounds => [[x - l1, y + r2], [x - r1, y + l2]]
+ :bounds => [[x - l2, y + r2], [x - r1, y + l1]]
# Lower left hand corner
curve_to [x, y - r2],
- :bounds => [[x - r1, y - l2], [x - l1, y - r2]]
+ :bounds => [[x - r1, y - l1], [x - l2, y - r2]]
# Lower right hand corner
curve_to [x + r1, y],
- :bounds => [[x + l1, y - r2], [x + r1, y - l2]]
+ :bounds => [[x + l2, y - r2], [x + r1, y - l1]]
move_to(x, y)
end
# Draws a polygon from the specified points.
@@ -239,11 +250,11 @@
line_to(*point)
end
# close the path
add_content "h"
end
-
+
# Draws a rounded polygon from specified points using the radius to define bezier curves
#
# # draws a rounded filled in polygon
# pdf.fill_and_stroke_rounded_polygon(10, [100, 250], [200, 300], [300, 250],
# [300, 150], [200, 100], [100, 150])
@@ -255,23 +266,24 @@
rounded_vertex(radius, points[i], points[i + 1], points[i + 2])
end
# close the path
add_content "h"
end
-
-
+
+
# Creates a rounded vertex for a line segment used for building a rounded polygon
# requires a radius to define bezier curve and three points. The first two points define
# the line segment and the third point helps define the curve for the vertex.
def rounded_vertex(radius, *points)
+ x0,y0,x1,y1,x2,y2 = points.flatten
radial_point_1 = point_on_line(radius, points[0], points[1])
bezier_point_1 = point_on_line((radius - radius*KAPPA), points[0], points[1] )
radial_point_2 = point_on_line(radius, points[2], points[1])
bezier_point_2 = point_on_line((radius - radius*KAPPA), points[2], points[1])
line_to(radial_point_1)
curve_to(radial_point_2, :bounds => [bezier_point_1, bezier_point_2])
- end
+ end
# Strokes the current path. If a block is provided, yields to the block
# before closing the path. See Graphics::Color for color details.
#
def stroke
@@ -284,79 +296,17 @@
#
def close_and_stroke
yield if block_given?
add_content "s"
end
-
+
# Draws and strokes a rectangle represented by the current bounding box
#
def stroke_bounds
stroke_rectangle bounds.top_left, bounds.width, bounds.height
end
- # Draws and strokes X and Y axes rulers beginning at the current bounding
- # box origin (or at a custom location).
- #
- # == Options
- #
- # +:at+::
- # Origin of the X and Y axes (default: [0, 0] = origin of the bounding
- # box)
- #
- # +:width+::
- # Length of the X axis (default: width of the bounding box)
- #
- # +:height+::
- # Length of the Y axis (default: height of the bounding box)
- #
- # +:step_length+::
- # Length of the step between markers (default: 100)
- #
- # +:negative_axes_length+::
- # Length of the negative parts of the axes (default: 20)
- #
- # +:color+:
- # The color of the axes and the text.
- #
- def stroke_axis(options = {})
- options = {
- :at => [0,0],
- :height => bounds.height.to_i - (options[:at] || [0,0])[1],
- :width => bounds.width.to_i - (options[:at] || [0,0])[0],
- :step_length => 100,
- :negative_axes_length => 20,
- :color => "000000",
- }.merge(options)
-
- Prawn.verify_options([:at, :width, :height, :step_length,
- :negative_axes_length, :color], options)
-
- save_graphics_state do
- fill_color(options[:color])
- stroke_color(options[:color])
-
- dash(1, :space => 4)
- stroke_horizontal_line(options[:at][0] - options[:negative_axes_length],
- options[:at][0] + options[:width], :at => options[:at][1])
- stroke_vertical_line(options[:at][1] - options[:negative_axes_length],
- options[:at][1] + options[:height], :at => options[:at][0])
- undash
-
- fill_circle(options[:at], 1)
-
- (options[:step_length]..options[:width]).step(options[:step_length]) do |point|
- fill_circle([options[:at][0] + point, options[:at][1]], 1)
- draw_text(point, :at => [options[:at][0] + point - 5, options[:at][1] - 10], :size => 7)
- end
-
- (options[:step_length]..options[:height]).step(options[:step_length]) do |point|
- fill_circle([options[:at][0], options[:at][1] + point], 1)
- draw_text(point, :at => [options[:at][0] - 17, options[:at][1] + point - 2], :size => 7)
- end
- end
- end
-
# Closes and fills the current path. See Graphics::Color for color details.
#
# If the option :fill_rule => :even_odd is specified, Prawn will use the
# even-odd rule to fill the path. Otherwise, the nonzero winding number rule
# will be used. See the PDF reference, "Graphics -> Path Construction and
@@ -385,234 +335,39 @@
#
def close_path
add_content "h"
end
- ##
- # :method: stroke_rectangle
+ # Provides the following shortcuts:
#
- # Draws and strokes a rectangle given +point+, +width+ and +height+. The
- # rectangle is bounded by its upper-left corner.
+ # stroke_some_method(*args) #=> some_method(*args); stroke
+ # fill_some_method(*args) #=> some_method(*args); fill
+ # fill_and_stroke_some_method(*args) #=> some_method(*args); fill_and_stroke
#
- # :call-seq:
- # stroke_rectangle(point,width,height)
-
- ##
- # :method: fill_rectangle
- #
- # Draws and fills ills a rectangle given +point+, +width+ and +height+. The
- # rectangle is bounded by its upper-left corner.
- #
- # :call-seq:
- # fill_rectangle(point,width,height)
-
- ##
- # :method: fill_and_stroke_rectangle
- #
- # Draws, fills, and strokes a rectangle given +point+, +width+ and +height+.
- # The rectangle is bounded by its upper-left corner.
- #
- # :call-seq:
- # fill_and_stroke_rectangle(point,width,height)
-
- ##
- # :method: stroke_rounded_rectangle
- #
- # Draws and strokes a rounded rectangle given +point+, +width+ and +height+
- # and +radius+ for the rounded corner. The rectangle is bounded by its
- # upper-left corner.
- #
- # :call-seq:
- # stroke_rounded_rectangle(point,width,height,radius)
-
- ##
- # :method: fill_rounded_rectangle
- #
- # Draws and fills a rounded rectangle given +point+, +width+ and +height+
- # and +radius+ for the rounded corner. The rectangle is bounded by its
- # upper-left corner.
- #
- # :call-seq:
- # fill_rounded_rectangle(point,width,height,radius)
-
- ##
- # :method: stroke_and_fill_rounded_rectangle
- #
- # Draws, fills, and strokes a rounded rectangle given +point+, +width+ and
- # +height+ and +radius+ for the rounded corner. The rectangle is bounded by
- # its upper-left corner.
- #
- # :call-seq:
- # stroke_and_fill_rounded_rectangle(point,width,height,radius)
-
- ##
- # :method: stroke_line
- #
- # Strokes a line from one point to another. Points may be specified as
- # tuples or flattened argument list.
- #
- # :call-seq:
- # stroke_line(*points)
-
- ##
- # :method: stroke_horizontal_line
- #
- # Strokes a horizontal line from +x1+ to +x2+ at the current y position, or
- # the position specified by the :at option.
- #
- # :call-seq:
- # stroke_horizontal_line(x1,x2,options={})
-
- ##
- # :method: stroke_horizontal_rule
- #
- # Strokes a horizontal line from the left border to the right border of the
- # bounding box at the current y position.
- #
- # :call-seq:
- # stroke_horizontal_rule
-
- ##
- # :method: stroke_vertical_line
- #
- # Strokes a vertical line at the x coordinate given by :at from y1 to y2.
- #
- # :call-seq:
- # stroke_vertical_line(y1,y2,params)
-
- ##
- # :method: stroke_curve
- #
- # Strokes a Bezier curve between two points, bounded by two additional
- # points.
- #
- # :call-seq:
- # stroke_curve(origin,dest,options={})
-
- ##
- # :method: stroke_circle
- #
- # Draws and strokes a circle of radius +radius+ with the centre-point at
- # +point+.
- #
- # :call-seq:
- # stroke_circle(center,radius)
-
- ##
- # :method: fill_circle
- #
- # Draws and fills a circle of radius +radius+ with the centre-point at
- # +point+.
- #
- # :call-seq:
- # fill_circle(center,radius)
-
- ##
- # :method: fill_and_stroke_circle
- #
- # Draws, strokes, and fills a circle of radius +radius+ with the
- # centre-point at +point+.
- #
- # :call-seq:
- # fill_and_stroke_circle(center,radius)
-
- ##
- # :method: stroke_ellipse
- #
- # Draws and strokes an ellipse of x radius +r1+ and y radius +r2+ with the
- # centre-point at +point+.
- #
- # :call-seq:
- # stroke_ellipse(point, r1, r2 = r1)
-
- ##
- # :method: fill_ellipse
- #
- # Draws and fills an ellipse of x radius +r1+ and y radius +r2+ with the
- # centre-point at +point+.
- #
- # :call-seq:
- # fill_ellipse(point, r1, r2 = r1)
-
- ##
- # :method: fill_and_stroke_ellipse
- #
- # Draws, strokes, and fills an ellipse of x radius +r1+ and y radius +r2+
- # with the centre-point at +point+.
- #
- # :call-seq:
- # fill_and_stroke_ellipse(point, r1, r2 = r1)
-
- ##
- # :method: stroke_polygon
- #
- # Draws and strokes a polygon from the specified points.
- #
- # :call-seq:
- # stroke_polygon(*points)
-
- ##
- # :method: fill_polygon
- #
- # Draws and fills a polygon from the specified points.
- #
- # :call-seq:
- # fill_polygon(*points)
-
- ##
- # :method: fill_and_stroke_polygon
- #
- # Draws, strokes, and fills a polygon from the specified points.
- #
- # :call-seq:
- # fill_and_stroke_polygon(*points)
-
- ##
- # :method: stroke_rounded_polygon
- #
- # Draws and strokes a rounded polygon from specified points, using +radius+
- # to define Bezier curves.
- #
- # :call-seq:
- # stroke_rounded_polygon(radius, *points)
-
- ##
- # :method: fill_rounded_polygon
- #
- # Draws and fills a rounded polygon from specified points, using +radius+ to
- # define Bezier curves.
- #
- # :call-seq:
- # fill_rounded_polygon(radius, *points)
-
- ##
- # :method: fill_and_stroke_rounded_polygon
- #
- # Draws, strokes, and fills a rounded polygon from specified points, using
- # +radius+ to define Bezier curves.
- #
- # :call-seq:
- # fill_and_stroke_rounded_polygon(radius, *points)
-
- ops = %w{fill stroke fill_and_stroke}
- shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
- curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
-
- ops.product(shapes).each do |operation,shape|
- class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
+ def method_missing(id,*args,&block)
+ case(id.to_s)
+ when /^fill_and_stroke_(.*)/
+ send($1,*args,&block); fill_and_stroke
+ when /^stroke_(.*)/
+ send($1,*args,&block); stroke
+ when /^fill_(.*)/
+ send($1,*args,&block); fill
+ else
+ super
+ end
end
private
-
+
def current_line_width
graphic_state.line_width
end
-
+
def current_line_width=(width)
graphic_state.line_width = width
end
-
+
def write_line_width
add_content("#{current_line_width} w")
end
def map_to_absolute(*point)
@@ -625,19 +380,19 @@
end
def degree_to_rad(angle)
angle * Math::PI / 180
end
-
+
# Returns the coordinates for a point on a line that is a given distance away from the second
# point defining the line segement
def point_on_line(distance_from_end, *points)
x0,y0,x1,y1 = points.flatten
length = Math.sqrt((x1 - x0)**2 + (y1 - y0)**2)
p = (length - distance_from_end) / length
xr = x0 + p*(x1 - x0)
yr = y0 + p*(y1 - y0)
[xr, yr]
end
-
+
end
end