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,157 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# transformation.rb: Implements rotate, translate, skew, scale and a generic
|
4
|
+
# transformation_matrix
|
5
|
+
#
|
6
|
+
# Copyright January 2010, Michael Witrant. All Rights Reserved.
|
7
|
+
#
|
8
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
module Graphics
|
12
|
+
module Transformation
|
13
|
+
# @group Stable API
|
14
|
+
|
15
|
+
# Rotate the user space. If a block is not provided, then you must save
|
16
|
+
# and restore the graphics state yourself.
|
17
|
+
#
|
18
|
+
# == Options
|
19
|
+
# <tt>:origin</tt>:: <tt>[number, number]</tt>. The point around which to
|
20
|
+
# rotate. A block must be provided if using the :origin
|
21
|
+
#
|
22
|
+
# raises <tt>Prawn::Errors::BlockRequired</tt> if an :origin option is
|
23
|
+
# provided, but no block is given
|
24
|
+
#
|
25
|
+
# Example without a block:
|
26
|
+
#
|
27
|
+
# save_graphics_state
|
28
|
+
# rotate 30
|
29
|
+
# text "rotated text"
|
30
|
+
# restore_graphics_state
|
31
|
+
#
|
32
|
+
# Example with a block: rotating a rectangle around its upper-left corner
|
33
|
+
#
|
34
|
+
# x = 300
|
35
|
+
# y = 300
|
36
|
+
# width = 150
|
37
|
+
# height = 200
|
38
|
+
# angle = 30
|
39
|
+
# pdf.rotate(angle, :origin => [x, y]) do
|
40
|
+
# pdf.stroke_rectangle([x, y], width, height)
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
def rotate(angle, options={}, &block)
|
44
|
+
Prawn.verify_options(:origin, options)
|
45
|
+
rad = degree_to_rad(angle)
|
46
|
+
cos = Math.cos(rad)
|
47
|
+
sin = Math.sin(rad)
|
48
|
+
if options[:origin].nil?
|
49
|
+
transformation_matrix(cos, sin, -sin, cos, 0, 0, &block)
|
50
|
+
else
|
51
|
+
raise Prawn::Errors::BlockRequired unless block_given?
|
52
|
+
x = options[:origin][0] + bounds.absolute_left
|
53
|
+
y = options[:origin][1] + bounds.absolute_bottom
|
54
|
+
x_prime = x * cos - y * sin
|
55
|
+
y_prime = x * sin + y * cos
|
56
|
+
translate(x - x_prime, y - y_prime) do
|
57
|
+
transformation_matrix(cos, sin, -sin, cos, 0, 0, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Translate the user space. If a block is not provided, then you must save
|
63
|
+
# and restore the graphics state yourself.
|
64
|
+
#
|
65
|
+
# Example without a block: move the text up and over 10
|
66
|
+
#
|
67
|
+
# save_graphics_state
|
68
|
+
# translate(10, 10)
|
69
|
+
# text "scaled text"
|
70
|
+
# restore_graphics_state
|
71
|
+
#
|
72
|
+
# Example with a block: draw a rectangle with its upper-left corner at
|
73
|
+
# x + 10, y + 10
|
74
|
+
#
|
75
|
+
# x = 300
|
76
|
+
# y = 300
|
77
|
+
# width = 150
|
78
|
+
# height = 200
|
79
|
+
# pdf.translate(10, 10) do
|
80
|
+
# pdf.stroke_rectangle([x, y], width, height)
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
def translate(x, y, &block)
|
84
|
+
transformation_matrix(1, 0, 0, 1, x, y, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Scale the user space. If a block is not provided, then you must save
|
88
|
+
# and restore the graphics state yourself.
|
89
|
+
#
|
90
|
+
# == Options
|
91
|
+
# <tt>:origin</tt>:: <tt>[number, number]</tt>. The point from which to
|
92
|
+
# scale. A block must be provided if using the :origin
|
93
|
+
#
|
94
|
+
# raises <tt>Prawn::Errors::BlockRequired</tt> if an :origin option is
|
95
|
+
# provided, but no block is given
|
96
|
+
#
|
97
|
+
# Example without a block:
|
98
|
+
#
|
99
|
+
# save_graphics_state
|
100
|
+
# scale 1.5
|
101
|
+
# text "scaled text"
|
102
|
+
# restore_graphics_state
|
103
|
+
#
|
104
|
+
# Example with a block: scale a rectangle from its upper-left corner
|
105
|
+
#
|
106
|
+
# x = 300
|
107
|
+
# y = 300
|
108
|
+
# width = 150
|
109
|
+
# height = 200
|
110
|
+
# factor = 1.5
|
111
|
+
# pdf.scale(angle, :origin => [x, y]) do
|
112
|
+
# pdf.stroke_rectangle([x, y], width, height)
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
def scale(factor, options={}, &block)
|
116
|
+
Prawn.verify_options(:origin, options)
|
117
|
+
if options[:origin].nil?
|
118
|
+
transformation_matrix(factor, 0, 0, factor, 0, 0, &block)
|
119
|
+
else
|
120
|
+
raise Prawn::Errors::BlockRequired unless block_given?
|
121
|
+
x = options[:origin][0] + bounds.absolute_left
|
122
|
+
y = options[:origin][1] + bounds.absolute_bottom
|
123
|
+
x_prime = factor * x
|
124
|
+
y_prime = factor * y
|
125
|
+
translate(x - x_prime, y - y_prime) do
|
126
|
+
transformation_matrix(factor, 0, 0, factor, 0, 0, &block)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# The following definition of skew would only work in a clearly
|
132
|
+
# predicatable manner when if the document had no margin. don't provide
|
133
|
+
# this shortcut until it behaves in a clearly understood manner
|
134
|
+
#
|
135
|
+
# def skew(a, b, &block)
|
136
|
+
# transformation_matrix(1,
|
137
|
+
# Math.tan(degree_to_rad(a)),
|
138
|
+
# Math.tan(degree_to_rad(b)),
|
139
|
+
# 1, 0, 0, &block)
|
140
|
+
# end
|
141
|
+
|
142
|
+
# Transform the user space (see notes for rotate regarding graphics state)
|
143
|
+
# Generally, one would use the rotate, scale, translate, and skew
|
144
|
+
# convenience methods instead of calling transformation_matrix directly
|
145
|
+
def transformation_matrix(a, b, c, d, e, f)
|
146
|
+
values = [a, b, c, d, e, f].map { |x| "%.5f" % x }.join(" ")
|
147
|
+
save_graphics_state if block_given?
|
148
|
+
renderer.add_content "#{values} cm"
|
149
|
+
if block_given?
|
150
|
+
yield
|
151
|
+
restore_graphics_state
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# transparency.rb : Implements transparency
|
4
|
+
#
|
5
|
+
# Copyright October 2009, Daniel Nelson. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
module Graphics
|
12
|
+
|
13
|
+
# The Prawn::Transparency module is used to place transparent
|
14
|
+
# content on the page. It has the capacity for separate
|
15
|
+
# transparency values for stroked content and all other content.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# # both the fill and stroke will be at 50% opacity
|
19
|
+
# pdf.transparent(0.5) do
|
20
|
+
# pdf.text("hello world")
|
21
|
+
# pdf.fill_and_stroke_circle([x, y], 25)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # the fill will be at 50% opacity, but the stroke will
|
25
|
+
# # be at 75% opacity
|
26
|
+
# pdf.transparent(0.5, 0.75) do
|
27
|
+
# pdf.text("hello world")
|
28
|
+
# pdf.fill_and_stroke_circle([x, y], 25)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
module Transparency
|
32
|
+
|
33
|
+
# @group Stable API
|
34
|
+
|
35
|
+
# Sets the <tt>opacity</tt> and <tt>stroke_opacity</tt> for all
|
36
|
+
# the content within the <tt>block</tt>
|
37
|
+
# If <tt>stroke_opacity</tt> is not provided, then it takes on
|
38
|
+
# the same value as <tt>opacity</tt>
|
39
|
+
#
|
40
|
+
# Valid ranges for both paramters are 0.0 to 1.0
|
41
|
+
#
|
42
|
+
# Example:
|
43
|
+
# # both the fill and stroke will be at 50% opacity
|
44
|
+
# pdf.transparent(0.5) do
|
45
|
+
# pdf.text("hello world")
|
46
|
+
# pdf.fill_and_stroke_circle([x, y], 25)
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# # the fill will be at 50% opacity, but the stroke will
|
50
|
+
# # be at 75% opacity
|
51
|
+
# pdf.transparent(0.5, 0.75) do
|
52
|
+
# pdf.text("hello world")
|
53
|
+
# pdf.fill_and_stroke_circle([x, y], 25)
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def transparent(opacity, stroke_opacity=opacity, &block)
|
57
|
+
renderer.min_version(1.4)
|
58
|
+
|
59
|
+
opacity = [[opacity, 0.0].max, 1.0].min
|
60
|
+
stroke_opacity = [[stroke_opacity, 0.0].max, 1.0].min
|
61
|
+
|
62
|
+
save_graphics_state
|
63
|
+
renderer.add_content "/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
|
64
|
+
yield
|
65
|
+
restore_graphics_state
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def opacity_dictionary_registry
|
71
|
+
@opacity_dictionary_registry ||= {}
|
72
|
+
end
|
73
|
+
|
74
|
+
def next_opacity_dictionary_id
|
75
|
+
opacity_dictionary_registry.length + 1
|
76
|
+
end
|
77
|
+
|
78
|
+
def opacity_dictionary_name(opacity, stroke_opacity)
|
79
|
+
key = "#{opacity}_#{stroke_opacity}"
|
80
|
+
|
81
|
+
if opacity_dictionary_registry[key]
|
82
|
+
dictionary = opacity_dictionary_registry[key][:obj]
|
83
|
+
dictionary_name = opacity_dictionary_registry[key][:name]
|
84
|
+
else
|
85
|
+
dictionary = ref!(:Type => :ExtGState,
|
86
|
+
:CA => stroke_opacity,
|
87
|
+
:ca => opacity
|
88
|
+
)
|
89
|
+
|
90
|
+
dictionary_name = "Tr#{next_opacity_dictionary_id}"
|
91
|
+
opacity_dictionary_registry[key] = { :name => dictionary_name,
|
92
|
+
:obj => dictionary }
|
93
|
+
end
|
94
|
+
|
95
|
+
page.ext_gstates.merge!(dictionary_name => dictionary)
|
96
|
+
dictionary_name
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/prawn/grid.rb
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# grid.rb: Provides a basic grid layout system for Prawn
|
4
|
+
#
|
5
|
+
# Contributed by Andrew O'Brien in March 2009
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
|
9
|
+
module Prawn
|
10
|
+
class Document
|
11
|
+
# @group Experimental API
|
12
|
+
|
13
|
+
# Defines the grid system for a particular document. Takes the number of
|
14
|
+
# rows and columns and the width to use for the gutter as the
|
15
|
+
# keys :rows, :columns, :gutter, :row_gutter, :column_gutter
|
16
|
+
#
|
17
|
+
# Note that a completely new grid object is built each time define_grid()
|
18
|
+
# is called. This means that all subsequent calls to grid() will use
|
19
|
+
# the newly defined Grid object -- grids are not nestable like
|
20
|
+
# bounding boxes are.
|
21
|
+
|
22
|
+
def define_grid(options = {})
|
23
|
+
@boxes = nil
|
24
|
+
@grid = Grid.new(self, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# A method that can either be used to access a particular grid on the page
|
28
|
+
# or work with the grid system directly.
|
29
|
+
#
|
30
|
+
# @pdf.grid # Get the Grid directly
|
31
|
+
# @pdf.grid([0,1]) # Get the GridBox at [0,1]
|
32
|
+
# @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
|
33
|
+
#
|
34
|
+
def grid(*args)
|
35
|
+
@boxes ||= {}
|
36
|
+
@boxes[args] ||= if args.empty?
|
37
|
+
@grid
|
38
|
+
else
|
39
|
+
g1, g2 = args
|
40
|
+
if(g1.class == Array && g2.class == Array &&
|
41
|
+
g1.length == 2 && g2.length == 2)
|
42
|
+
multi_box(single_box(*g1), single_box(*g2))
|
43
|
+
else
|
44
|
+
single_box(g1, g2)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# A Grid represents the entire grid system of a Page and calculates
|
50
|
+
# the column width and row height of the base box.
|
51
|
+
#
|
52
|
+
# @group Experimental API
|
53
|
+
class Grid
|
54
|
+
attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
|
55
|
+
def initialize(pdf, options = {}) # :nodoc:
|
56
|
+
valid_options = [:columns, :rows, :gutter, :row_gutter, :column_gutter]
|
57
|
+
Prawn.verify_options valid_options, options
|
58
|
+
|
59
|
+
@pdf = pdf
|
60
|
+
@columns = options[:columns]
|
61
|
+
@rows = options[:rows]
|
62
|
+
set_gutter(options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Calculates the base width of boxes.
|
66
|
+
def column_width
|
67
|
+
@column_width ||= subdivide(pdf.bounds.width, columns, column_gutter)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Calculates the base height of boxes.
|
71
|
+
def row_height
|
72
|
+
@row_height ||= subdivide(pdf.bounds.height, rows, row_gutter)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Diagnostic tool to show all of the grids. Defaults to gray.
|
76
|
+
def show_all(color = "CCCCCC")
|
77
|
+
self.rows.times do |i|
|
78
|
+
self.columns.times do |j|
|
79
|
+
pdf.grid(i,j).show(color)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def subdivide(total, num, gutter)
|
87
|
+
(total.to_f - (gutter * (num - 1).to_f)) / num.to_f
|
88
|
+
end
|
89
|
+
|
90
|
+
def set_gutter(options)
|
91
|
+
if options.has_key?(:gutter)
|
92
|
+
@gutter = options[:gutter].to_f
|
93
|
+
@row_gutter, @column_gutter = @gutter, @gutter
|
94
|
+
else
|
95
|
+
@row_gutter = options[:row_gutter].to_f
|
96
|
+
@column_gutter = options[:column_gutter].to_f
|
97
|
+
@gutter = 0
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# A Box is a class that represents a bounded area of a page.
|
103
|
+
# A Grid object has methods that allow easy access to the coordinates of
|
104
|
+
# its corners, which can be plugged into most existing prawnmethods.
|
105
|
+
#
|
106
|
+
# @group Experimental API
|
107
|
+
class GridBox
|
108
|
+
attr_reader :pdf
|
109
|
+
|
110
|
+
def initialize(pdf, i, j)
|
111
|
+
@pdf = pdf
|
112
|
+
@i = i
|
113
|
+
@j = j
|
114
|
+
end
|
115
|
+
|
116
|
+
# Mostly diagnostic method that outputs the name of a box as
|
117
|
+
# col_num, row_num
|
118
|
+
#
|
119
|
+
def name
|
120
|
+
"#{@i.to_s},#{@j.to_s}"
|
121
|
+
end
|
122
|
+
|
123
|
+
# :nodoc
|
124
|
+
def total_height
|
125
|
+
pdf.bounds.height.to_f
|
126
|
+
end
|
127
|
+
|
128
|
+
# Width of a box
|
129
|
+
def width
|
130
|
+
grid.column_width.to_f
|
131
|
+
end
|
132
|
+
|
133
|
+
# Height of a box
|
134
|
+
def height
|
135
|
+
grid.row_height.to_f
|
136
|
+
end
|
137
|
+
|
138
|
+
# Width of the gutter
|
139
|
+
def gutter
|
140
|
+
grid.gutter.to_f
|
141
|
+
end
|
142
|
+
|
143
|
+
# x-coordinate of left side
|
144
|
+
def left
|
145
|
+
@left ||= (width + grid.column_gutter) * @j.to_f
|
146
|
+
end
|
147
|
+
|
148
|
+
# x-coordinate of right side
|
149
|
+
def right
|
150
|
+
@right ||= left + width
|
151
|
+
end
|
152
|
+
|
153
|
+
# y-coordinate of the top
|
154
|
+
def top
|
155
|
+
@top ||= total_height - ((height + grid.row_gutter) * @i.to_f)
|
156
|
+
end
|
157
|
+
|
158
|
+
# y-coordinate of the bottom
|
159
|
+
def bottom
|
160
|
+
@bottom ||= top - height
|
161
|
+
end
|
162
|
+
|
163
|
+
# x,y coordinates of top left corner
|
164
|
+
def top_left
|
165
|
+
[left, top]
|
166
|
+
end
|
167
|
+
|
168
|
+
# x,y coordinates of top right corner
|
169
|
+
def top_right
|
170
|
+
[right, top]
|
171
|
+
end
|
172
|
+
|
173
|
+
# x,y coordinates of bottom left corner
|
174
|
+
def bottom_left
|
175
|
+
[left, bottom]
|
176
|
+
end
|
177
|
+
|
178
|
+
# x,y coordinates of bottom right corner
|
179
|
+
def bottom_right
|
180
|
+
[right, bottom]
|
181
|
+
end
|
182
|
+
|
183
|
+
# Creates a standard bounding box based on the grid box.
|
184
|
+
def bounding_box(&blk)
|
185
|
+
pdf.bounding_box(top_left, :width => width, :height => height, &blk)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Diagnostic method
|
189
|
+
def show(grid_color = "CCCCCC")
|
190
|
+
self.bounding_box do
|
191
|
+
original_stroke_color = pdf.stroke_color
|
192
|
+
|
193
|
+
pdf.stroke_color = grid_color
|
194
|
+
pdf.text self.name
|
195
|
+
pdf.stroke_bounds
|
196
|
+
|
197
|
+
pdf.stroke_color = original_stroke_color
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
def grid
|
203
|
+
pdf.grid
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# A MultiBox is specified by 2 Boxes and spans the areas between.
|
208
|
+
#
|
209
|
+
# @group Experimental API
|
210
|
+
class MultiBox < GridBox
|
211
|
+
def initialize(pdf, b1, b2)
|
212
|
+
@pdf = pdf
|
213
|
+
@bs = [b1, b2]
|
214
|
+
end
|
215
|
+
|
216
|
+
def name
|
217
|
+
@bs.map {|b| b.name}.join(":")
|
218
|
+
end
|
219
|
+
|
220
|
+
def total_height
|
221
|
+
@bs[0].total_height
|
222
|
+
end
|
223
|
+
|
224
|
+
def width
|
225
|
+
right_box.right - left_box.left
|
226
|
+
end
|
227
|
+
|
228
|
+
def height
|
229
|
+
top_box.top - bottom_box.bottom
|
230
|
+
end
|
231
|
+
|
232
|
+
def gutter
|
233
|
+
@bs[0].gutter
|
234
|
+
end
|
235
|
+
|
236
|
+
def left
|
237
|
+
left_box.left
|
238
|
+
end
|
239
|
+
|
240
|
+
def right
|
241
|
+
right_box.right
|
242
|
+
end
|
243
|
+
|
244
|
+
def top
|
245
|
+
top_box.top
|
246
|
+
end
|
247
|
+
|
248
|
+
def bottom
|
249
|
+
bottom_box.bottom
|
250
|
+
end
|
251
|
+
|
252
|
+
private
|
253
|
+
def left_box
|
254
|
+
@left_box ||= @bs.min {|a,b| a.left <=> b.left}
|
255
|
+
end
|
256
|
+
|
257
|
+
def right_box
|
258
|
+
@right_box ||= @bs.max {|a,b| a.right <=> b.right}
|
259
|
+
end
|
260
|
+
|
261
|
+
def top_box
|
262
|
+
@top_box ||= @bs.max {|a,b| a.top <=> b.top}
|
263
|
+
end
|
264
|
+
|
265
|
+
def bottom_box
|
266
|
+
@bottom_box ||= @bs.min {|a,b| a.bottom <=> b.bottom}
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
private
|
271
|
+
def single_box(i, j)
|
272
|
+
GridBox.new(self, i, j)
|
273
|
+
end
|
274
|
+
|
275
|
+
def multi_box(b1, b2)
|
276
|
+
MultiBox.new(self, b1, b2)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|