prawn-git 2.0.1
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 +7 -0
- data/.yardopts +10 -0
- data/COPYING +2 -0
- data/GPLv2 +340 -0
- data/GPLv3 +674 -0
- data/Gemfile +11 -0
- data/LICENSE +56 -0
- data/Rakefile +55 -0
- data/data/fonts/Courier-Bold.afm +342 -0
- data/data/fonts/Courier-BoldOblique.afm +342 -0
- data/data/fonts/Courier-Oblique.afm +342 -0
- data/data/fonts/Courier.afm +342 -0
- data/data/fonts/Helvetica-Bold.afm +2827 -0
- data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/data/fonts/Helvetica.afm +3051 -0
- data/data/fonts/MustRead.html +19 -0
- data/data/fonts/Symbol.afm +213 -0
- data/data/fonts/Times-Bold.afm +2588 -0
- data/data/fonts/Times-BoldItalic.afm +2384 -0
- data/data/fonts/Times-Italic.afm +2667 -0
- data/data/fonts/Times-Roman.afm +2419 -0
- data/data/fonts/ZapfDingbats.afm +225 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/license.md +8 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pal_bk.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +1 -0
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +820 -0
- data/data/pdfs/hexagon.pdf +61 -0
- data/data/pdfs/indirect_reference.pdf +86 -0
- data/data/pdfs/multipage_template.pdf +127 -0
- data/data/pdfs/nested_pages.pdf +118 -0
- data/data/pdfs/page_without_mediabox.pdf +193 -0
- data/data/pdfs/resources_as_indirect_object.pdf +83 -0
- data/data/pdfs/two_hexagons.pdf +90 -0
- data/data/pdfs/version_1_6.pdf +61 -0
- data/data/shift_jis_text.txt +1 -0
- data/lib/prawn.rb +89 -0
- data/lib/prawn/document.rb +706 -0
- data/lib/prawn/document/bounding_box.rb +539 -0
- data/lib/prawn/document/column_box.rb +144 -0
- data/lib/prawn/document/internals.rb +58 -0
- data/lib/prawn/document/span.rb +57 -0
- data/lib/prawn/encoding.rb +87 -0
- data/lib/prawn/errors.rb +80 -0
- data/lib/prawn/font.rb +413 -0
- data/lib/prawn/font/afm.rb +256 -0
- data/lib/prawn/font/dfont.rb +43 -0
- data/lib/prawn/font/ttf.rb +355 -0
- data/lib/prawn/font_metric_cache.rb +46 -0
- data/lib/prawn/graphics.rb +646 -0
- data/lib/prawn/graphics/cap_style.rb +47 -0
- data/lib/prawn/graphics/color.rb +232 -0
- data/lib/prawn/graphics/dash.rb +109 -0
- data/lib/prawn/graphics/join_style.rb +49 -0
- data/lib/prawn/graphics/patterns.rb +126 -0
- data/lib/prawn/graphics/transformation.rb +157 -0
- data/lib/prawn/graphics/transparency.rb +101 -0
- data/lib/prawn/grid.rb +279 -0
- data/lib/prawn/image_handler.rb +44 -0
- data/lib/prawn/images.rb +199 -0
- data/lib/prawn/images/image.rb +49 -0
- data/lib/prawn/images/jpg.rb +91 -0
- data/lib/prawn/images/png.rb +290 -0
- data/lib/prawn/measurement_extensions.rb +50 -0
- data/lib/prawn/measurements.rb +77 -0
- data/lib/prawn/outline.rb +289 -0
- data/lib/prawn/repeater.rb +124 -0
- data/lib/prawn/security.rb +288 -0
- data/lib/prawn/security/arcfour.rb +54 -0
- data/lib/prawn/soft_mask.rb +94 -0
- data/lib/prawn/stamp.rb +136 -0
- data/lib/prawn/text.rb +437 -0
- data/lib/prawn/text/box.rb +141 -0
- data/lib/prawn/text/formatted.rb +7 -0
- data/lib/prawn/text/formatted/arranger.rb +290 -0
- data/lib/prawn/text/formatted/box.rb +614 -0
- data/lib/prawn/text/formatted/fragment.rb +264 -0
- data/lib/prawn/text/formatted/line_wrap.rb +277 -0
- data/lib/prawn/text/formatted/parser.rb +224 -0
- data/lib/prawn/text/formatted/wrap.rb +160 -0
- data/lib/prawn/utilities.rb +46 -0
- data/lib/prawn/version.rb +5 -0
- data/lib/prawn/view.rb +91 -0
- data/manual/absolute_position.pdf +0 -0
- data/manual/basic_concepts/adding_pages.rb +27 -0
- data/manual/basic_concepts/basic_concepts.rb +36 -0
- data/manual/basic_concepts/creation.rb +39 -0
- data/manual/basic_concepts/cursor.rb +33 -0
- data/manual/basic_concepts/measurement.rb +25 -0
- data/manual/basic_concepts/origin.rb +38 -0
- data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
- data/manual/basic_concepts/view.rb +42 -0
- data/manual/bounding_box/bounding_box.rb +39 -0
- data/manual/bounding_box/bounds.rb +49 -0
- data/manual/bounding_box/canvas.rb +24 -0
- data/manual/bounding_box/creation.rb +23 -0
- data/manual/bounding_box/indentation.rb +46 -0
- data/manual/bounding_box/nesting.rb +45 -0
- data/manual/bounding_box/russian_boxes.rb +40 -0
- data/manual/bounding_box/stretchy.rb +31 -0
- data/manual/contents.rb +29 -0
- data/manual/cover.rb +39 -0
- data/manual/document_and_page_options/background.rb +27 -0
- data/manual/document_and_page_options/document_and_page_options.rb +32 -0
- data/manual/document_and_page_options/metadata.rb +23 -0
- data/manual/document_and_page_options/page_margins.rb +38 -0
- data/manual/document_and_page_options/page_size.rb +34 -0
- data/manual/document_and_page_options/print_scaling.rb +20 -0
- data/manual/example_helper.rb +7 -0
- data/manual/graphics/circle_and_ellipse.rb +22 -0
- data/manual/graphics/color.rb +24 -0
- data/manual/graphics/common_lines.rb +30 -0
- data/manual/graphics/fill_and_stroke.rb +42 -0
- data/manual/graphics/fill_rules.rb +37 -0
- data/manual/graphics/gradients.rb +37 -0
- data/manual/graphics/graphics.rb +58 -0
- data/manual/graphics/helper.rb +24 -0
- data/manual/graphics/line_width.rb +35 -0
- data/manual/graphics/lines_and_curves.rb +41 -0
- data/manual/graphics/polygon.rb +29 -0
- data/manual/graphics/rectangle.rb +21 -0
- data/manual/graphics/rotate.rb +28 -0
- data/manual/graphics/scale.rb +41 -0
- data/manual/graphics/soft_masks.rb +46 -0
- data/manual/graphics/stroke_cap.rb +31 -0
- data/manual/graphics/stroke_dash.rb +48 -0
- data/manual/graphics/stroke_join.rb +30 -0
- data/manual/graphics/translate.rb +29 -0
- data/manual/graphics/transparency.rb +35 -0
- data/manual/how_to_read_this_manual.rb +40 -0
- data/manual/images/absolute_position.rb +23 -0
- data/manual/images/fit.rb +21 -0
- data/manual/images/horizontal.rb +25 -0
- data/manual/images/images.rb +40 -0
- data/manual/images/plain_image.rb +18 -0
- data/manual/images/scale.rb +22 -0
- data/manual/images/vertical.rb +28 -0
- data/manual/images/width_and_height.rb +25 -0
- data/manual/layout/boxes.rb +27 -0
- data/manual/layout/content.rb +25 -0
- data/manual/layout/layout.rb +28 -0
- data/manual/layout/simple_grid.rb +23 -0
- data/manual/outline/add_subsection_to.rb +61 -0
- data/manual/outline/insert_section_after.rb +47 -0
- data/manual/outline/outline.rb +32 -0
- data/manual/outline/sections_and_pages.rb +67 -0
- data/manual/repeatable_content/alternate_page_numbering.rb +32 -0
- data/manual/repeatable_content/page_numbering.rb +54 -0
- data/manual/repeatable_content/repeatable_content.rb +32 -0
- data/manual/repeatable_content/repeater.rb +55 -0
- data/manual/repeatable_content/stamp.rb +41 -0
- data/manual/security/encryption.rb +31 -0
- data/manual/security/permissions.rb +38 -0
- data/manual/security/security.rb +28 -0
- data/manual/table.rb +16 -0
- data/manual/text/alignment.rb +44 -0
- data/manual/text/color.rb +24 -0
- data/manual/text/column_box.rb +32 -0
- data/manual/text/fallback_fonts.rb +37 -0
- data/manual/text/font.rb +41 -0
- data/manual/text/font_size.rb +45 -0
- data/manual/text/font_style.rb +23 -0
- data/manual/text/formatted_callbacks.rb +60 -0
- data/manual/text/formatted_text.rb +50 -0
- data/manual/text/free_flowing_text.rb +51 -0
- data/manual/text/inline.rb +41 -0
- data/manual/text/kerning_and_character_spacing.rb +39 -0
- data/manual/text/leading.rb +25 -0
- data/manual/text/line_wrapping.rb +41 -0
- data/manual/text/paragraph_indentation.rb +34 -0
- data/manual/text/positioned_text.rb +38 -0
- data/manual/text/registering_families.rb +48 -0
- data/manual/text/rendering_and_color.rb +37 -0
- data/manual/text/right_to_left_text.rb +47 -0
- data/manual/text/rotation.rb +43 -0
- data/manual/text/single_usage.rb +37 -0
- data/manual/text/text.rb +73 -0
- data/manual/text/text_box_excess.rb +32 -0
- data/manual/text/text_box_extensions.rb +45 -0
- data/manual/text/text_box_overflow.rb +48 -0
- data/manual/text/utf8.rb +28 -0
- data/manual/text/win_ansi_charset.rb +60 -0
- data/prawn.gemspec +45 -0
- data/spec/acceptance/png.rb +25 -0
- data/spec/annotations_spec.rb +74 -0
- data/spec/bounding_box_spec.rb +510 -0
- data/spec/column_box_spec.rb +65 -0
- data/spec/data/curves.pdf +66 -0
- data/spec/destinations_spec.rb +15 -0
- data/spec/document_spec.rb +748 -0
- data/spec/extensions/encoding_helpers.rb +11 -0
- data/spec/extensions/mocha.rb +46 -0
- data/spec/font_metric_cache_spec.rb +52 -0
- data/spec/font_spec.rb +474 -0
- data/spec/formatted_text_arranger_spec.rb +421 -0
- data/spec/formatted_text_box_spec.rb +705 -0
- data/spec/formatted_text_fragment_spec.rb +298 -0
- data/spec/graphics_spec.rb +683 -0
- data/spec/grid_spec.rb +96 -0
- data/spec/image_handler_spec.rb +54 -0
- data/spec/images_spec.rb +153 -0
- data/spec/inline_formatted_text_parser_spec.rb +564 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/line_wrap_spec.rb +367 -0
- data/spec/measurement_units_spec.rb +25 -0
- data/spec/outline_spec.rb +430 -0
- data/spec/png_spec.rb +245 -0
- data/spec/reference_spec.rb +25 -0
- data/spec/repeater_spec.rb +160 -0
- data/spec/security_spec.rb +158 -0
- data/spec/soft_mask_spec.rb +79 -0
- data/spec/span_spec.rb +44 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/stamp_spec.rb +160 -0
- data/spec/stroke_styles_spec.rb +211 -0
- data/spec/text_at_spec.rb +143 -0
- data/spec/text_box_spec.rb +1043 -0
- data/spec/text_rendering_mode_spec.rb +45 -0
- data/spec/text_spacing_spec.rb +93 -0
- data/spec/text_spec.rb +557 -0
- data/spec/text_with_inline_formatting_spec.rb +35 -0
- data/spec/transparency_spec.rb +91 -0
- data/spec/view_spec.rb +43 -0
- metadata +509 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# font_metric_cache.rb : The Prawn font class
|
4
|
+
#
|
5
|
+
# Copyright Dec 2012, Kenneth Kalmer. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
|
12
|
+
# Cache used internally by Prawn::Document instances to calculate the width
|
13
|
+
# of various strings for layout purposes.
|
14
|
+
#
|
15
|
+
# @private
|
16
|
+
class FontMetricCache
|
17
|
+
|
18
|
+
CacheEntry = Struct.new( :font, :options, :string )
|
19
|
+
|
20
|
+
def initialize( document )
|
21
|
+
@document = document
|
22
|
+
|
23
|
+
@cache = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def width_of( string, options )
|
27
|
+
f = if options[:style]
|
28
|
+
# override style with :style => :bold
|
29
|
+
@document.find_font(@document.font.family, :style => options[:style])
|
30
|
+
else
|
31
|
+
@document.font
|
32
|
+
end
|
33
|
+
|
34
|
+
key = CacheEntry.new( f, options, string )
|
35
|
+
|
36
|
+
unless length = @cache[ key ]
|
37
|
+
length = @cache[ key ] = f.compute_width_of(string, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
length +
|
41
|
+
(@document.character_spacing * @document.font.character_count(string))
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,646 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# graphics.rb : Implements PDF drawing primitives
|
4
|
+
#
|
5
|
+
# Copyright April 2008, Gregory Brown. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
|
9
|
+
|
10
|
+
require_relative "graphics/color"
|
11
|
+
require_relative "graphics/dash"
|
12
|
+
require_relative "graphics/cap_style"
|
13
|
+
require_relative "graphics/join_style"
|
14
|
+
require_relative "graphics/transparency"
|
15
|
+
require_relative "graphics/transformation"
|
16
|
+
require_relative "graphics/patterns"
|
17
|
+
|
18
|
+
module Prawn
|
19
|
+
|
20
|
+
# Implements the drawing facilities for Prawn::Document.
|
21
|
+
# Use this to draw the most beautiful imaginable things.
|
22
|
+
#
|
23
|
+
# This file lifts and modifies several of PDF::Writer's graphics functions
|
24
|
+
# ruby-pdf.rubyforge.org
|
25
|
+
#
|
26
|
+
module Graphics
|
27
|
+
|
28
|
+
include Color
|
29
|
+
include Dash
|
30
|
+
include CapStyle
|
31
|
+
include JoinStyle
|
32
|
+
include Transparency
|
33
|
+
include Transformation
|
34
|
+
include Patterns
|
35
|
+
|
36
|
+
# @group Stable API
|
37
|
+
|
38
|
+
#######################################################################
|
39
|
+
# Low level drawing operations must map the point to absolute coords! #
|
40
|
+
#######################################################################
|
41
|
+
|
42
|
+
# Moves the drawing position to a given point. The point can be
|
43
|
+
# specified as a tuple or a flattened argument list
|
44
|
+
#
|
45
|
+
# pdf.move_to [100,50]
|
46
|
+
# pdf.move_to(100,50)
|
47
|
+
#
|
48
|
+
def move_to(*point)
|
49
|
+
xy = PDF::Core.real_params(map_to_absolute(point))
|
50
|
+
renderer.add_content("#{xy} m")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Draws a line from the current drawing position to the specified point.
|
54
|
+
# The destination may be described as a tuple or a flattened list:
|
55
|
+
#
|
56
|
+
# pdf.line_to [50,50]
|
57
|
+
# pdf.line_to(50,50)
|
58
|
+
#
|
59
|
+
def line_to(*point)
|
60
|
+
xy = PDF::Core.real_params(map_to_absolute(point))
|
61
|
+
renderer.add_content("#{xy} l")
|
62
|
+
end
|
63
|
+
|
64
|
+
# Draws a Bezier curve from the current drawing position to the
|
65
|
+
# specified point, bounded by two additional points.
|
66
|
+
#
|
67
|
+
# pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
|
68
|
+
#
|
69
|
+
def curve_to(dest,options={})
|
70
|
+
options[:bounds] or raise Prawn::Errors::InvalidGraphicsPath,
|
71
|
+
"Bounding points for bezier curve must be specified "+
|
72
|
+
"as :bounds => [[x1,y1],[x2,y2]]"
|
73
|
+
|
74
|
+
curve_points = PDF::Core.real_params(
|
75
|
+
(options[:bounds] << dest).flat_map { |e| map_to_absolute(e) })
|
76
|
+
|
77
|
+
renderer.add_content("#{curve_points} c")
|
78
|
+
end
|
79
|
+
|
80
|
+
# Draws a rectangle given <tt>point</tt>, <tt>width</tt> and
|
81
|
+
# <tt>height</tt>. The rectangle is bounded by its upper-left corner.
|
82
|
+
#
|
83
|
+
# pdf.rectangle [300,300], 100, 200
|
84
|
+
#
|
85
|
+
def rectangle(point,width,height)
|
86
|
+
x,y = map_to_absolute(point)
|
87
|
+
box = PDF::Core.real_params([x, y - height, width, height])
|
88
|
+
|
89
|
+
renderer.add_content("#{box} re")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Draws a rounded rectangle given <tt>point</tt>, <tt>width</tt> and
|
93
|
+
# <tt>height</tt> and <tt>radius</tt> for the rounded corner. The rectangle
|
94
|
+
# is bounded by its upper-left corner.
|
95
|
+
#
|
96
|
+
# pdf.rounded_rectangle [300,300], 100, 200, 10
|
97
|
+
#
|
98
|
+
def rounded_rectangle(point,width,height,radius)
|
99
|
+
x, y = point
|
100
|
+
rounded_polygon(radius, point, [x + width, y], [x + width, y - height], [x, y - height])
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
###########################################################
|
105
|
+
# Higher level functions: May use relative coords #
|
106
|
+
###########################################################
|
107
|
+
|
108
|
+
# Sets line thickness to the <tt>width</tt> specified.
|
109
|
+
#
|
110
|
+
def line_width=(width)
|
111
|
+
self.current_line_width = width
|
112
|
+
write_line_width
|
113
|
+
end
|
114
|
+
|
115
|
+
# When called without an argument, returns the current line thickness.
|
116
|
+
# When called with an argument, sets the line thickness to the specified
|
117
|
+
# value (in PDF points)
|
118
|
+
#
|
119
|
+
# pdf.line_width #=> 1
|
120
|
+
# pdf.line_width(5)
|
121
|
+
# pdf.line_width #=> 5
|
122
|
+
#
|
123
|
+
def line_width(width=nil)
|
124
|
+
if width
|
125
|
+
self.line_width = width
|
126
|
+
else
|
127
|
+
current_line_width
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Draws a line from one point to another. Points may be specified as
|
132
|
+
# tuples or flattened argument list:
|
133
|
+
#
|
134
|
+
# pdf.line [100,100], [200,250]
|
135
|
+
# pdf.line(100,100,200,250)
|
136
|
+
#
|
137
|
+
def line(*points)
|
138
|
+
x0,y0,x1,y1 = points.flatten
|
139
|
+
move_to(x0, y0)
|
140
|
+
line_to(x1, y1)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Draws a horizontal line from <tt>x1</tt> to <tt>x2</tt> at the
|
144
|
+
# current <tt>y</tt> position, or the position specified by the :at option.
|
145
|
+
#
|
146
|
+
# # draw a line from [25, 75] to [100, 75]
|
147
|
+
# horizontal_line 25, 100, :at => 75
|
148
|
+
#
|
149
|
+
def horizontal_line(x1,x2,options={})
|
150
|
+
if options[:at]
|
151
|
+
y1 = options[:at]
|
152
|
+
else
|
153
|
+
y1 = y - bounds.absolute_bottom
|
154
|
+
end
|
155
|
+
|
156
|
+
line(x1,y1,x2,y1)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Draws a horizontal line from the left border to the right border of the
|
160
|
+
# bounding box at the current <tt>y</tt> position.
|
161
|
+
#
|
162
|
+
def horizontal_rule
|
163
|
+
horizontal_line(bounds.left, bounds.right)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Draws a vertical line at the x cooordinate given by :at from y1 to y2.
|
167
|
+
#
|
168
|
+
# # draw a line from [25, 100] to [25, 300]
|
169
|
+
# vertical_line 100, 300, :at => 25
|
170
|
+
#
|
171
|
+
def vertical_line(y1,y2,params)
|
172
|
+
line(params[:at],y1,params[:at],y2)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Draws a Bezier curve between two points, bounded by two additional
|
176
|
+
# points
|
177
|
+
#
|
178
|
+
# pdf.curve [50,100], [100,100], :bounds => [[90,90],[75,75]]
|
179
|
+
#
|
180
|
+
def curve(origin,dest, options={})
|
181
|
+
move_to(*origin)
|
182
|
+
curve_to(dest,options)
|
183
|
+
end
|
184
|
+
|
185
|
+
# This constant is used to approximate a symmetrical arc using a cubic
|
186
|
+
# Bezier curve.
|
187
|
+
#
|
188
|
+
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
|
189
|
+
|
190
|
+
# Draws a circle of radius <tt>radius</tt> with the centre-point at <tt>point</tt>
|
191
|
+
# as a complete subpath. The drawing point will be moved to the
|
192
|
+
# centre-point upon completion of the drawing the circle.
|
193
|
+
#
|
194
|
+
# pdf.circle [100,100], 25
|
195
|
+
#
|
196
|
+
def circle(center, radius)
|
197
|
+
ellipse(center, radius, radius)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
|
201
|
+
# with the centre-point at <tt>point</tt> as a complete subpath. The
|
202
|
+
# drawing point will be moved to the centre-point upon completion of the
|
203
|
+
# drawing the ellipse.
|
204
|
+
#
|
205
|
+
# # draws an ellipse with x-radius 25 and y-radius 50
|
206
|
+
# pdf.ellipse [100,100], 25, 50
|
207
|
+
#
|
208
|
+
def ellipse(point, r1, r2 = r1)
|
209
|
+
x, y = point
|
210
|
+
l1 = r1 * KAPPA
|
211
|
+
l2 = r2 * KAPPA
|
212
|
+
|
213
|
+
move_to(x + r1, y)
|
214
|
+
|
215
|
+
# Upper right hand corner
|
216
|
+
curve_to [x, y + r2],
|
217
|
+
:bounds => [[x + r1, y + l2], [x + l1, y + r2]]
|
218
|
+
|
219
|
+
# Upper left hand corner
|
220
|
+
curve_to [x - r1, y],
|
221
|
+
:bounds => [[x - l1, y + r2], [x - r1, y + l2]]
|
222
|
+
|
223
|
+
# Lower left hand corner
|
224
|
+
curve_to [x, y - r2],
|
225
|
+
:bounds => [[x - r1, y - l2], [x - l1, y - r2]]
|
226
|
+
|
227
|
+
# Lower right hand corner
|
228
|
+
curve_to [x + r1, y],
|
229
|
+
:bounds => [[x + l1, y - r2], [x + r1, y - l2]]
|
230
|
+
|
231
|
+
move_to(x, y)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Draws a polygon from the specified points.
|
235
|
+
#
|
236
|
+
# # draws a snazzy triangle
|
237
|
+
# pdf.polygon [100,100], [100,200], [200,200]
|
238
|
+
#
|
239
|
+
def polygon(*points)
|
240
|
+
move_to points[0]
|
241
|
+
(points[1..-1] << points[0]).each do |point|
|
242
|
+
line_to(*point)
|
243
|
+
end
|
244
|
+
# close the path
|
245
|
+
renderer.add_content "h"
|
246
|
+
end
|
247
|
+
|
248
|
+
# Draws a rounded polygon from specified points using the radius to define bezier curves
|
249
|
+
#
|
250
|
+
# # draws a rounded filled in polygon
|
251
|
+
# pdf.fill_and_stroke_rounded_polygon(10, [100, 250], [200, 300], [300, 250],
|
252
|
+
# [300, 150], [200, 100], [100, 150])
|
253
|
+
def rounded_polygon(radius, *points)
|
254
|
+
move_to point_on_line(radius, points[1], points[0])
|
255
|
+
sides = points.size
|
256
|
+
points << points[0] << points[1]
|
257
|
+
(sides).times do |i|
|
258
|
+
rounded_vertex(radius, points[i], points[i + 1], points[i + 2])
|
259
|
+
end
|
260
|
+
# close the path
|
261
|
+
renderer.add_content "h"
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# Creates a rounded vertex for a line segment used for building a rounded polygon
|
266
|
+
# requires a radius to define bezier curve and three points. The first two points define
|
267
|
+
# the line segment and the third point helps define the curve for the vertex.
|
268
|
+
def rounded_vertex(radius, *points)
|
269
|
+
radial_point_1 = point_on_line(radius, points[0], points[1])
|
270
|
+
bezier_point_1 = point_on_line((radius - radius*KAPPA), points[0], points[1] )
|
271
|
+
radial_point_2 = point_on_line(radius, points[2], points[1])
|
272
|
+
bezier_point_2 = point_on_line((radius - radius*KAPPA), points[2], points[1])
|
273
|
+
line_to(radial_point_1)
|
274
|
+
curve_to(radial_point_2, :bounds => [bezier_point_1, bezier_point_2])
|
275
|
+
end
|
276
|
+
|
277
|
+
# Strokes the current path. If a block is provided, yields to the block
|
278
|
+
# before closing the path. See Graphics::Color for color details.
|
279
|
+
#
|
280
|
+
def stroke
|
281
|
+
yield if block_given?
|
282
|
+
renderer.add_content "S"
|
283
|
+
end
|
284
|
+
|
285
|
+
# Closes and strokes the current path. If a block is provided, yields to
|
286
|
+
# the block before closing the path. See Graphics::Color for color details.
|
287
|
+
#
|
288
|
+
def close_and_stroke
|
289
|
+
yield if block_given?
|
290
|
+
renderer.add_content "s"
|
291
|
+
end
|
292
|
+
|
293
|
+
# Draws and strokes a rectangle represented by the current bounding box
|
294
|
+
#
|
295
|
+
def stroke_bounds
|
296
|
+
stroke_rectangle bounds.top_left, bounds.width, bounds.height
|
297
|
+
end
|
298
|
+
|
299
|
+
# Draws and strokes X and Y axes rulers beginning at the current bounding
|
300
|
+
# box origin (or at a custom location).
|
301
|
+
#
|
302
|
+
# == Options
|
303
|
+
#
|
304
|
+
# +:at+::
|
305
|
+
# Origin of the X and Y axes (default: [0, 0] = origin of the bounding
|
306
|
+
# box)
|
307
|
+
#
|
308
|
+
# +:width+::
|
309
|
+
# Length of the X axis (default: width of the bounding box)
|
310
|
+
#
|
311
|
+
# +:height+::
|
312
|
+
# Length of the Y axis (default: height of the bounding box)
|
313
|
+
#
|
314
|
+
# +:step_length+::
|
315
|
+
# Length of the step between markers (default: 100)
|
316
|
+
#
|
317
|
+
# +:negative_axes_length+::
|
318
|
+
# Length of the negative parts of the axes (default: 20)
|
319
|
+
#
|
320
|
+
# +:color+:
|
321
|
+
# The color of the axes and the text.
|
322
|
+
#
|
323
|
+
def stroke_axis(options = {})
|
324
|
+
options = {
|
325
|
+
:at => [0,0],
|
326
|
+
:height => bounds.height.to_i - (options[:at] || [0,0])[1],
|
327
|
+
:width => bounds.width.to_i - (options[:at] || [0,0])[0],
|
328
|
+
:step_length => 100,
|
329
|
+
:negative_axes_length => 20,
|
330
|
+
:color => "000000",
|
331
|
+
}.merge(options)
|
332
|
+
|
333
|
+
Prawn.verify_options([:at, :width, :height, :step_length,
|
334
|
+
:negative_axes_length, :color], options)
|
335
|
+
|
336
|
+
save_graphics_state do
|
337
|
+
fill_color(options[:color])
|
338
|
+
stroke_color(options[:color])
|
339
|
+
|
340
|
+
dash(1, :space => 4)
|
341
|
+
stroke_horizontal_line(options[:at][0] - options[:negative_axes_length],
|
342
|
+
options[:at][0] + options[:width], :at => options[:at][1])
|
343
|
+
stroke_vertical_line(options[:at][1] - options[:negative_axes_length],
|
344
|
+
options[:at][1] + options[:height], :at => options[:at][0])
|
345
|
+
undash
|
346
|
+
|
347
|
+
fill_circle(options[:at], 1)
|
348
|
+
|
349
|
+
(options[:step_length]..options[:width]).step(options[:step_length]) do |point|
|
350
|
+
fill_circle([options[:at][0] + point, options[:at][1]], 1)
|
351
|
+
draw_text(point, :at => [options[:at][0] + point - 5, options[:at][1] - 10], :size => 7)
|
352
|
+
end
|
353
|
+
|
354
|
+
(options[:step_length]..options[:height]).step(options[:step_length]) do |point|
|
355
|
+
fill_circle([options[:at][0], options[:at][1] + point], 1)
|
356
|
+
draw_text(point, :at => [options[:at][0] - 17, options[:at][1] + point - 2], :size => 7)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Closes and fills the current path. See Graphics::Color for color details.
|
362
|
+
#
|
363
|
+
# If the option :fill_rule => :even_odd is specified, Prawn will use the
|
364
|
+
# even-odd rule to fill the path. Otherwise, the nonzero winding number rule
|
365
|
+
# will be used. See the PDF reference, "Graphics -> Path Construction and
|
366
|
+
# Painting -> Clipping Path Operators" for details on the difference.
|
367
|
+
#
|
368
|
+
def fill(options={})
|
369
|
+
yield if block_given?
|
370
|
+
renderer.add_content(options[:fill_rule] == :even_odd ? "f*" : "f")
|
371
|
+
end
|
372
|
+
|
373
|
+
# Closes, fills, and strokes the current path. If a block is provided,
|
374
|
+
# yields to the block before closing the path. See Graphics::Color for
|
375
|
+
# color details.
|
376
|
+
#
|
377
|
+
# If the option :fill_rule => :even_odd is specified, Prawn will use the
|
378
|
+
# even-odd rule to fill the path. Otherwise, the nonzero winding number rule
|
379
|
+
# will be used. See the PDF reference, "Graphics -> Path Construction and
|
380
|
+
# Painting -> Clipping Path Operators" for details on the difference.
|
381
|
+
#
|
382
|
+
def fill_and_stroke(options={})
|
383
|
+
yield if block_given?
|
384
|
+
renderer.add_content(options[:fill_rule] == :even_odd ? "b*" : "b")
|
385
|
+
end
|
386
|
+
|
387
|
+
# Closes the current path.
|
388
|
+
#
|
389
|
+
def close_path
|
390
|
+
renderer.add_content "h"
|
391
|
+
end
|
392
|
+
|
393
|
+
##
|
394
|
+
# :method: stroke_rectangle
|
395
|
+
#
|
396
|
+
# Draws and strokes a rectangle given +point+, +width+ and +height+. The
|
397
|
+
# rectangle is bounded by its upper-left corner.
|
398
|
+
#
|
399
|
+
# :call-seq:
|
400
|
+
# stroke_rectangle(point,width,height)
|
401
|
+
|
402
|
+
##
|
403
|
+
# :method: fill_rectangle
|
404
|
+
#
|
405
|
+
# Draws and fills ills a rectangle given +point+, +width+ and +height+. The
|
406
|
+
# rectangle is bounded by its upper-left corner.
|
407
|
+
#
|
408
|
+
# :call-seq:
|
409
|
+
# fill_rectangle(point,width,height)
|
410
|
+
|
411
|
+
##
|
412
|
+
# :method: fill_and_stroke_rectangle
|
413
|
+
#
|
414
|
+
# Draws, fills, and strokes a rectangle given +point+, +width+ and +height+.
|
415
|
+
# The rectangle is bounded by its upper-left corner.
|
416
|
+
#
|
417
|
+
# :call-seq:
|
418
|
+
# fill_and_stroke_rectangle(point,width,height)
|
419
|
+
|
420
|
+
##
|
421
|
+
# :method: stroke_rounded_rectangle
|
422
|
+
#
|
423
|
+
# Draws and strokes a rounded rectangle given +point+, +width+ and +height+
|
424
|
+
# and +radius+ for the rounded corner. The rectangle is bounded by its
|
425
|
+
# upper-left corner.
|
426
|
+
#
|
427
|
+
# :call-seq:
|
428
|
+
# stroke_rounded_rectangle(point,width,height,radius)
|
429
|
+
|
430
|
+
##
|
431
|
+
# :method: fill_rounded_rectangle
|
432
|
+
#
|
433
|
+
# Draws and fills a rounded rectangle given +point+, +width+ and +height+
|
434
|
+
# and +radius+ for the rounded corner. The rectangle is bounded by its
|
435
|
+
# upper-left corner.
|
436
|
+
#
|
437
|
+
# :call-seq:
|
438
|
+
# fill_rounded_rectangle(point,width,height,radius)
|
439
|
+
|
440
|
+
##
|
441
|
+
# :method: stroke_and_fill_rounded_rectangle
|
442
|
+
#
|
443
|
+
# Draws, fills, and strokes a rounded rectangle given +point+, +width+ and
|
444
|
+
# +height+ and +radius+ for the rounded corner. The rectangle is bounded by
|
445
|
+
# its upper-left corner.
|
446
|
+
#
|
447
|
+
# :call-seq:
|
448
|
+
# stroke_and_fill_rounded_rectangle(point,width,height,radius)
|
449
|
+
|
450
|
+
##
|
451
|
+
# :method: stroke_line
|
452
|
+
#
|
453
|
+
# Strokes a line from one point to another. Points may be specified as
|
454
|
+
# tuples or flattened argument list.
|
455
|
+
#
|
456
|
+
# :call-seq:
|
457
|
+
# stroke_line(*points)
|
458
|
+
|
459
|
+
##
|
460
|
+
# :method: stroke_horizontal_line
|
461
|
+
#
|
462
|
+
# Strokes a horizontal line from +x1+ to +x2+ at the current y position, or
|
463
|
+
# the position specified by the :at option.
|
464
|
+
#
|
465
|
+
# :call-seq:
|
466
|
+
# stroke_horizontal_line(x1,x2,options={})
|
467
|
+
|
468
|
+
##
|
469
|
+
# :method: stroke_horizontal_rule
|
470
|
+
#
|
471
|
+
# Strokes a horizontal line from the left border to the right border of the
|
472
|
+
# bounding box at the current y position.
|
473
|
+
#
|
474
|
+
# :call-seq:
|
475
|
+
# stroke_horizontal_rule
|
476
|
+
|
477
|
+
##
|
478
|
+
# :method: stroke_vertical_line
|
479
|
+
#
|
480
|
+
# Strokes a vertical line at the x coordinate given by :at from y1 to y2.
|
481
|
+
#
|
482
|
+
# :call-seq:
|
483
|
+
# stroke_vertical_line(y1,y2,params)
|
484
|
+
|
485
|
+
##
|
486
|
+
# :method: stroke_curve
|
487
|
+
#
|
488
|
+
# Strokes a Bezier curve between two points, bounded by two additional
|
489
|
+
# points.
|
490
|
+
#
|
491
|
+
# :call-seq:
|
492
|
+
# stroke_curve(origin,dest,options={})
|
493
|
+
|
494
|
+
##
|
495
|
+
# :method: stroke_circle
|
496
|
+
#
|
497
|
+
# Draws and strokes a circle of radius +radius+ with the centre-point at
|
498
|
+
# +point+.
|
499
|
+
#
|
500
|
+
# :call-seq:
|
501
|
+
# stroke_circle(center,radius)
|
502
|
+
|
503
|
+
##
|
504
|
+
# :method: fill_circle
|
505
|
+
#
|
506
|
+
# Draws and fills a circle of radius +radius+ with the centre-point at
|
507
|
+
# +point+.
|
508
|
+
#
|
509
|
+
# :call-seq:
|
510
|
+
# fill_circle(center,radius)
|
511
|
+
|
512
|
+
##
|
513
|
+
# :method: fill_and_stroke_circle
|
514
|
+
#
|
515
|
+
# Draws, strokes, and fills a circle of radius +radius+ with the
|
516
|
+
# centre-point at +point+.
|
517
|
+
#
|
518
|
+
# :call-seq:
|
519
|
+
# fill_and_stroke_circle(center,radius)
|
520
|
+
|
521
|
+
##
|
522
|
+
# :method: stroke_ellipse
|
523
|
+
#
|
524
|
+
# Draws and strokes an ellipse of x radius +r1+ and y radius +r2+ with the
|
525
|
+
# centre-point at +point+.
|
526
|
+
#
|
527
|
+
# :call-seq:
|
528
|
+
# stroke_ellipse(point, r1, r2 = r1)
|
529
|
+
|
530
|
+
##
|
531
|
+
# :method: fill_ellipse
|
532
|
+
#
|
533
|
+
# Draws and fills an ellipse of x radius +r1+ and y radius +r2+ with the
|
534
|
+
# centre-point at +point+.
|
535
|
+
#
|
536
|
+
# :call-seq:
|
537
|
+
# fill_ellipse(point, r1, r2 = r1)
|
538
|
+
|
539
|
+
##
|
540
|
+
# :method: fill_and_stroke_ellipse
|
541
|
+
#
|
542
|
+
# Draws, strokes, and fills an ellipse of x radius +r1+ and y radius +r2+
|
543
|
+
# with the centre-point at +point+.
|
544
|
+
#
|
545
|
+
# :call-seq:
|
546
|
+
# fill_and_stroke_ellipse(point, r1, r2 = r1)
|
547
|
+
|
548
|
+
##
|
549
|
+
# :method: stroke_polygon
|
550
|
+
#
|
551
|
+
# Draws and strokes a polygon from the specified points.
|
552
|
+
#
|
553
|
+
# :call-seq:
|
554
|
+
# stroke_polygon(*points)
|
555
|
+
|
556
|
+
##
|
557
|
+
# :method: fill_polygon
|
558
|
+
#
|
559
|
+
# Draws and fills a polygon from the specified points.
|
560
|
+
#
|
561
|
+
# :call-seq:
|
562
|
+
# fill_polygon(*points)
|
563
|
+
|
564
|
+
##
|
565
|
+
# :method: fill_and_stroke_polygon
|
566
|
+
#
|
567
|
+
# Draws, strokes, and fills a polygon from the specified points.
|
568
|
+
#
|
569
|
+
# :call-seq:
|
570
|
+
# fill_and_stroke_polygon(*points)
|
571
|
+
|
572
|
+
##
|
573
|
+
# :method: stroke_rounded_polygon
|
574
|
+
#
|
575
|
+
# Draws and strokes a rounded polygon from specified points, using +radius+
|
576
|
+
# to define Bezier curves.
|
577
|
+
#
|
578
|
+
# :call-seq:
|
579
|
+
# stroke_rounded_polygon(radius, *points)
|
580
|
+
|
581
|
+
##
|
582
|
+
# :method: fill_rounded_polygon
|
583
|
+
#
|
584
|
+
# Draws and fills a rounded polygon from specified points, using +radius+ to
|
585
|
+
# define Bezier curves.
|
586
|
+
#
|
587
|
+
# :call-seq:
|
588
|
+
# fill_rounded_polygon(radius, *points)
|
589
|
+
|
590
|
+
##
|
591
|
+
# :method: fill_and_stroke_rounded_polygon
|
592
|
+
#
|
593
|
+
# Draws, strokes, and fills a rounded polygon from specified points, using
|
594
|
+
# +radius+ to define Bezier curves.
|
595
|
+
#
|
596
|
+
# :call-seq:
|
597
|
+
# fill_and_stroke_rounded_polygon(radius, *points)
|
598
|
+
|
599
|
+
ops = %w{fill stroke fill_and_stroke}
|
600
|
+
shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
|
601
|
+
curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
|
602
|
+
|
603
|
+
ops.product(shapes).each do |operation,shape|
|
604
|
+
class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
|
605
|
+
end
|
606
|
+
|
607
|
+
private
|
608
|
+
|
609
|
+
def current_line_width
|
610
|
+
graphic_state.line_width
|
611
|
+
end
|
612
|
+
|
613
|
+
def current_line_width=(width)
|
614
|
+
graphic_state.line_width = width
|
615
|
+
end
|
616
|
+
|
617
|
+
def write_line_width
|
618
|
+
renderer.add_content("#{current_line_width} w")
|
619
|
+
end
|
620
|
+
|
621
|
+
def map_to_absolute(*point)
|
622
|
+
x,y = point.flatten
|
623
|
+
[@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
|
624
|
+
end
|
625
|
+
|
626
|
+
def map_to_absolute!(point)
|
627
|
+
point.replace(map_to_absolute(point))
|
628
|
+
end
|
629
|
+
|
630
|
+
def degree_to_rad(angle)
|
631
|
+
angle * Math::PI / 180
|
632
|
+
end
|
633
|
+
|
634
|
+
# Returns the coordinates for a point on a line that is a given distance away from the second
|
635
|
+
# point defining the line segement
|
636
|
+
def point_on_line(distance_from_end, *points)
|
637
|
+
x0,y0,x1,y1 = points.flatten
|
638
|
+
length = Math.sqrt((x1 - x0)**2 + (y1 - y0)**2)
|
639
|
+
p = (length - distance_from_end) / length
|
640
|
+
xr = x0 + p*(x1 - x0)
|
641
|
+
yr = y0 + p*(y1 - y0)
|
642
|
+
[xr, yr]
|
643
|
+
end
|
644
|
+
|
645
|
+
end
|
646
|
+
end
|