module Prawn::Graphics

Implements the drawing facilities for Prawn::Document. Use this to draw the most beautiful imaginable things.

This file lifts and modifies several of PDF::Writer's graphics functions ruby-pdf.rubyforge.org

Constants

KAPPA

This constant is used to approximate a symmetrical arc using a cubic Bezier curve.

Public Instance Methods

circle(center, radius) click to toggle source

Draws a circle of radius radius with the centre-point at point 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
# File lib/prawn/graphics.rb, line 197
def circle(center, radius)
  ellipse(center, radius, radius)
end
close_and_stroke() { || ... } click to toggle source

Closes and strokes the current path. If a block is provided, yields to the block before closing the path. See Graphics::Color for color details.

# File lib/prawn/graphics.rb, line 300
def close_and_stroke
  yield if block_given?
  renderer.add_content 's'
end
close_path() click to toggle source

Closes the current path.

# File lib/prawn/graphics.rb, line 419
def close_path
  renderer.add_content 'h'
end
curve(origin, dest, options = {}) click to toggle source

Draws a Bezier curve between two points, bounded by two additional points

pdf.curve [50,100], [100,100], :bounds => [[90,90],[75,75]]
# File lib/prawn/graphics.rb, line 181
def curve(origin, dest, options = {})
  move_to(*origin)
  curve_to(dest, options)
end
curve_to(dest, options = {}) click to toggle source

Draws a Bezier curve from the current drawing position to the specified point, bounded by two additional points.

pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
# File lib/prawn/graphics.rb, line 66
def curve_to(dest, options = {})
  options[:bounds] || raise(
    Prawn::Errors::InvalidGraphicsPath,
    'Bounding points for bezier curve must be specified ' \
    'as :bounds => [[x1,y1],[x2,y2]]'
  )

  curve_points = PDF::Core.real_params(
    (options[:bounds] << dest).flat_map { |e| map_to_absolute(e) }
  )

  renderer.add_content("#{curve_points} c")
end
ellipse(point, r1, r2 = r1) click to toggle source

Draws an ellipse of x radius r1 and y radius r2 with the centre-point at point as a complete subpath. The drawing point will be moved to the centre-point upon completion of the drawing the ellipse.

# draws an ellipse with x-radius 25 and y-radius 50
pdf.ellipse [100,100], 25, 50
# File lib/prawn/graphics.rb, line 209
def ellipse(point, r1, r2 = r1)
  x, y = point
  l1 = r1 * KAPPA
  l2 = r2 * KAPPA

  move_to(x + r1, y)

  # Upper right hand corner
  curve_to [x,  y + r2],
    bounds: [[x + r1, y + l2], [x + l1, y + r2]]

  # Upper left hand corner
  curve_to [x - r1, y],
    bounds: [[x - l1, y + r2], [x - r1, y + l2]]

  # Lower left hand corner
  curve_to [x, y - r2],
    bounds: [[x - r1, y - l2], [x - l1, y - r2]]

  # Lower right hand corner
  curve_to [x + r1, y],
    bounds: [[x + l1, y - r2], [x + r1, y - l2]]

  move_to(x, y)
end
fill(options = {}) { || ... } click to toggle source

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 Painting -> Clipping Path Operators” for details on the difference.

# File lib/prawn/graphics.rb, line 398
def fill(options = {})
  yield if block_given?
  renderer.add_content(options[:fill_rule] == :even_odd ? 'f*' : 'f')
end
fill_and_stroke(options = {}) { || ... } click to toggle source

Closes, fills, and strokes the current path. If a block is provided, yields to the block before closing the 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 Painting -> Clipping Path Operators” for details on the difference.

# File lib/prawn/graphics.rb, line 412
def fill_and_stroke(options = {})
  yield if block_given?
  renderer.add_content(options[:fill_rule] == :even_odd ? 'b*' : 'b')
end
fill_and_stroke_circle(center,radius) click to toggle source

Draws, strokes, and fills a circle of radius radius with the centre-point at point.

# File lib/prawn/graphics.rb, line 551
    
fill_and_stroke_ellipse(point, r1, r2 = r1) click to toggle source

Draws, strokes, and fills an ellipse of x radius r1 and y radius r2 with the centre-point at point.

# File lib/prawn/graphics.rb, line 578
    
fill_and_stroke_polygon(*points) click to toggle source

Draws, strokes, and fills a polygon from the specified points.

# File lib/prawn/graphics.rb, line 602
    
fill_and_stroke_rectangle(point,width,height) click to toggle source

Draws, fills, and strokes a rectangle given point, width and height. The rectangle is bounded by its upper-left corner.

# File lib/prawn/graphics.rb, line 450
    
fill_and_stroke_rounded_polygon(radius, *points) click to toggle source

Draws, strokes, and fills a rounded polygon from specified points, using radius to define Bezier curves.

# File lib/prawn/graphics.rb, line 629
ops = %w[fill stroke fill_and_stroke]
fill_circle(center,radius) click to toggle source

Draws and fills a circle of radius radius with the centre-point at point.

# File lib/prawn/graphics.rb, line 542
    
fill_ellipse(point, r1, r2 = r1) click to toggle source

Draws and fills an ellipse of x radius r1 and y radius r2 with the centre-point at point.

# File lib/prawn/graphics.rb, line 569
    
fill_polygon(*points) click to toggle source

Draws and fills a polygon from the specified points.

# File lib/prawn/graphics.rb, line 594
    
fill_rectangle(point,width,height) click to toggle source

Draws and fills ills a rectangle given point, width and height. The rectangle is bounded by its upper-left corner.

# File lib/prawn/graphics.rb, line 441
    
fill_rounded_polygon(radius, *points) click to toggle source

Draws and fills a rounded polygon from specified points, using radius to define Bezier curves.

# File lib/prawn/graphics.rb, line 620
    
fill_rounded_rectangle(point,width,height,radius) click to toggle source

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.

# File lib/prawn/graphics.rb, line 470
    
horizontal_line(x1, x2, options = {}) click to toggle source

Draws a horizontal line from x1 to x2 at the current y position, or the position specified by the :at option.

# draw a line from [25, 75] to [100, 75]
horizontal_line 25, 100, :at => 75
# File lib/prawn/graphics.rb, line 150
def horizontal_line(x1, x2, options = {})
  y1 = if options[:at]
         options[:at]
       else
         y - bounds.absolute_bottom
       end

  line(x1, y1, x2, y1)
end
horizontal_rule() click to toggle source

Draws a horizontal line from the left border to the right border of the bounding box at the current y position.

# File lib/prawn/graphics.rb, line 163
def horizontal_rule
  horizontal_line(bounds.left, bounds.right)
end
line(*points) click to toggle source

Draws a line from one point to another. Points may be specified as tuples or flattened argument list:

pdf.line [100,100], [200,250]
pdf.line(100,100,200,250)
# File lib/prawn/graphics.rb, line 138
def line(*points)
  x0, y0, x1, y1 = points.flatten
  move_to(x0, y0)
  line_to(x1, y1)
end
line_to(*point) click to toggle source

Draws a line from the current drawing position to the specified point. The destination may be described as a tuple or a flattened list:

pdf.line_to [50,50]
pdf.line_to(50,50)
# File lib/prawn/graphics.rb, line 56
def line_to(*point)
  xy = PDF::Core.real_params(map_to_absolute(point))
  renderer.add_content("#{xy} l")
end
line_width(width = nil) click to toggle source

When called without an argument, returns the current line thickness. When called with an argument, sets the line thickness to the specified value (in PDF points)

pdf.line_width #=> 1
pdf.line_width(5)
pdf.line_width #=> 5
# File lib/prawn/graphics.rb, line 124
def line_width(width = nil)
  if width
    self.line_width = width
  else
    current_line_width
  end
end
line_width=(width) click to toggle source

Sets line thickness to the width specified.

# File lib/prawn/graphics.rb, line 111
def line_width=(width)
  self.current_line_width = width
  write_line_width
end
move_to(*point) click to toggle source

Moves the drawing position to a given point. The point can be specified as a tuple or a flattened argument list

pdf.move_to [100,50]
pdf.move_to(100,50)
# File lib/prawn/graphics.rb, line 45
def move_to(*point)
  xy = PDF::Core.real_params(map_to_absolute(point))
  renderer.add_content("#{xy} m")
end
polygon(*points) click to toggle source

Draws a polygon from the specified points.

# draws a snazzy triangle
pdf.polygon [100,100], [100,200], [200,200]
# File lib/prawn/graphics.rb, line 240
def polygon(*points)
  move_to points[0]
  (points[1..-1] << points[0]).each do |point|
    line_to(*point)
  end
  # close the path
  renderer.add_content 'h'
end
rectangle(point, width, height) click to toggle source

Draws a rectangle given point, width and height. The rectangle is bounded by its upper-left corner.

pdf.rectangle [300,300], 100, 200
# File lib/prawn/graphics.rb, line 85
def rectangle(point, width, height)
  x, y = map_to_absolute(point)
  box = PDF::Core.real_params([x, y - height, width, height])

  renderer.add_content("#{box} re")
end
rounded_polygon(radius, *points) click to toggle source

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]
)
# File lib/prawn/graphics.rb, line 257
def rounded_polygon(radius, *points)
  move_to point_on_line(radius, points[1], points[0])
  sides = points.size
  points << points[0] << points[1]
  sides.times do |i|
    rounded_vertex(radius, points[i], points[i + 1], points[i + 2])
  end
  # close the path
  renderer.add_content 'h'
end
rounded_rectangle(point, width, height, radius) click to toggle source

Draws a rounded rectangle given point, width and height and radius for the rounded corner. The rectangle is bounded by its upper-left corner.

pdf.rounded_rectangle [300,300], 100, 200, 10
# File lib/prawn/graphics.rb, line 98
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
rounded_vertex(radius, *points) click to toggle source

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.

# File lib/prawn/graphics.rb, line 272
def rounded_vertex(radius, *points)
  radial_point1 = point_on_line(radius, points[0], points[1])
  bezier_point1 = point_on_line(
    (radius - radius * KAPPA),
    points[0],
    points[1]
  )
  radial_point2 = point_on_line(radius, points[2], points[1])
  bezier_point2 = point_on_line(
    (radius - radius * KAPPA),
    points[2],
    points[1]
  )
  line_to(radial_point1)
  curve_to(radial_point2, bounds: [bezier_point1, bezier_point2])
end
stroke() { || ... } click to toggle source

Strokes the current path. If a block is provided, yields to the block before closing the path. See Graphics::Color for color details.

# File lib/prawn/graphics.rb, line 292
def stroke
  yield if block_given?
  renderer.add_content 'S'
end
stroke_and_fill_rounded_rectangle(point,width,height,radius) click to toggle source

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.

# File lib/prawn/graphics.rb, line 480
    
stroke_axis(options = {}) click to toggle source

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.
# File lib/prawn/graphics.rb, line 335
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
stroke_bounds() click to toggle source

Draws and strokes a rectangle represented by the current bounding box

# File lib/prawn/graphics.rb, line 307
def stroke_bounds
  stroke_rectangle bounds.top_left, bounds.width, bounds.height
end
stroke_circle(center,radius) click to toggle source

Draws and strokes a circle of radius radius with the centre-point at point.

# File lib/prawn/graphics.rb, line 533
    
stroke_curve(origin,dest,options={}) click to toggle source

Strokes a Bezier curve between two points, bounded by two additional points.

# File lib/prawn/graphics.rb, line 524
    
stroke_ellipse(point, r1, r2 = r1) click to toggle source

Draws and strokes an ellipse of x radius r1 and y radius r2 with the centre-point at point.

# File lib/prawn/graphics.rb, line 560
    
stroke_horizontal_line(x1,x2,options={}) click to toggle source

Strokes a horizontal line from x1 to x2 at the current y position, or the position specified by the :at option.

# File lib/prawn/graphics.rb, line 498
    
stroke_horizontal_rule click to toggle source

Strokes a horizontal line from the left border to the right border of the bounding box at the current y position.

# File lib/prawn/graphics.rb, line 507
    
stroke_line(*points) click to toggle source

Strokes a line from one point to another. Points may be specified as tuples or flattened argument list.

# File lib/prawn/graphics.rb, line 489
    
stroke_polygon(*points) click to toggle source

Draws and strokes a polygon from the specified points.

# File lib/prawn/graphics.rb, line 586
    
stroke_rectangle(point,width,height) click to toggle source

Draws and strokes a rectangle given point, width and height. The rectangle is bounded by its upper-left corner.

# File lib/prawn/graphics.rb, line 432
    
stroke_rounded_polygon(radius, *points) click to toggle source

Draws and strokes a rounded polygon from specified points, using radius to define Bezier curves.

# File lib/prawn/graphics.rb, line 611
    
stroke_rounded_rectangle(point,width,height,radius) click to toggle source

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.

# File lib/prawn/graphics.rb, line 460
    
stroke_vertical_line(y1,y2,params) click to toggle source

Strokes a vertical line at the x coordinate given by :at from y1 to y2.

# File lib/prawn/graphics.rb, line 515
    
vertical_line(y1, y2, params) click to toggle source

Draws a vertical line at the x cooordinate given by :at from y1 to y2.

# draw a line from [25, 100] to [25, 300]
vertical_line 100, 300, :at => 25
# File lib/prawn/graphics.rb, line 172
def vertical_line(y1, y2, params)
  line(params[:at], y1, params[:at], y2)
end

Private Instance Methods

current_line_width() click to toggle source
# File lib/prawn/graphics.rb, line 647
def current_line_width
  graphic_state.line_width
end
current_line_width=(width) click to toggle source
# File lib/prawn/graphics.rb, line 651
def current_line_width=(width)
  graphic_state.line_width = width
end
degree_to_rad(angle) click to toggle source
# File lib/prawn/graphics.rb, line 668
def degree_to_rad(angle)
  angle * Math::PI / 180
end
map_to_absolute(*point) click to toggle source
# File lib/prawn/graphics.rb, line 659
def map_to_absolute(*point)
  x, y = point.flatten
  [@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
end
map_to_absolute!(point) click to toggle source
# File lib/prawn/graphics.rb, line 664
def map_to_absolute!(point)
  point.replace(map_to_absolute(point))
end
point_on_line(distance_from_end, *points) click to toggle source

Returns the coordinates for a point on a line that is a given distance away from the second point defining the line segement

# File lib/prawn/graphics.rb, line 674
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
write_line_width() click to toggle source
# File lib/prawn/graphics.rb, line 655
def write_line_width
  renderer.add_content("#{current_line_width} w")
end