eideticpdf 0.9.9

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.
Files changed (177) hide show
  1. data/fonts/AntiqueOlive-Bold.afm +406 -0
  2. data/fonts/AntiqueOlive-Bold.inf +27 -0
  3. data/fonts/AntiqueOlive-Compact.afm +401 -0
  4. data/fonts/AntiqueOlive-Compact.inf +27 -0
  5. data/fonts/AntiqueOlive-Italic.afm +401 -0
  6. data/fonts/AntiqueOlive-Italic.inf +27 -0
  7. data/fonts/AntiqueOlive-Roman.afm +409 -0
  8. data/fonts/AntiqueOlive-Roman.inf +27 -0
  9. data/fonts/AvantGarde-Book.afm +667 -0
  10. data/fonts/AvantGarde-Book.inf +26 -0
  11. data/fonts/AvantGarde-BookOblique.afm +667 -0
  12. data/fonts/AvantGarde-BookOblique.inf +26 -0
  13. data/fonts/AvantGarde-Demi.afm +673 -0
  14. data/fonts/AvantGarde-Demi.inf +26 -0
  15. data/fonts/AvantGarde-DemiOblique.afm +673 -0
  16. data/fonts/AvantGarde-DemiOblique.inf +26 -0
  17. data/fonts/Bookman-Demi.afm +669 -0
  18. data/fonts/Bookman-Demi.inf +25 -0
  19. data/fonts/Bookman-DemiItalic.afm +669 -0
  20. data/fonts/Bookman-DemiItalic.inf +25 -0
  21. data/fonts/Bookman-Light.afm +643 -0
  22. data/fonts/Bookman-Light.inf +25 -0
  23. data/fonts/Bookman-LightItalic.afm +620 -0
  24. data/fonts/Bookman-LightItalic.inf +25 -0
  25. data/fonts/Clarendon-Bold.afm +412 -0
  26. data/fonts/Clarendon-Bold.inf +27 -0
  27. data/fonts/Clarendon-Light.afm +410 -0
  28. data/fonts/Clarendon-Light.inf +27 -0
  29. data/fonts/Clarendon.afm +410 -0
  30. data/fonts/Clarendon.inf +27 -0
  31. data/fonts/CooperBlack-Italic.afm +421 -0
  32. data/fonts/CooperBlack-Italic.inf +26 -0
  33. data/fonts/CooperBlack.afm +427 -0
  34. data/fonts/CooperBlack.inf +26 -0
  35. data/fonts/Coronet-Regular.afm +327 -0
  36. data/fonts/Coronet-Regular.inf +25 -0
  37. data/fonts/Courier-Bold.afm +342 -0
  38. data/fonts/Courier-Bold.inf +26 -0
  39. data/fonts/Courier-BoldOblique.afm +342 -0
  40. data/fonts/Courier-BoldOblique.inf +26 -0
  41. data/fonts/Courier-Oblique.afm +342 -0
  42. data/fonts/Courier-Oblique.inf +26 -0
  43. data/fonts/Courier.afm +342 -0
  44. data/fonts/Courier.inf +26 -0
  45. data/fonts/Eurostile.afm +419 -0
  46. data/fonts/Eurostile.inf +27 -0
  47. data/fonts/Goudy-ExtraBold.afm +412 -0
  48. data/fonts/Goudy-ExtraBold.inf +27 -0
  49. data/fonts/Helvetica-Bold.afm +2827 -0
  50. data/fonts/Helvetica-Bold.inf +26 -0
  51. data/fonts/Helvetica-BoldOblique.afm +2827 -0
  52. data/fonts/Helvetica-BoldOblique.inf +26 -0
  53. data/fonts/Helvetica-Condensed-Bold.afm +623 -0
  54. data/fonts/Helvetica-Condensed-Bold.inf +25 -0
  55. data/fonts/Helvetica-Condensed-BoldObl.afm +623 -0
  56. data/fonts/Helvetica-Condensed-BoldObl.inf +25 -0
  57. data/fonts/Helvetica-Condensed-Oblique.afm +528 -0
  58. data/fonts/Helvetica-Condensed-Oblique.inf +25 -0
  59. data/fonts/Helvetica-Condensed.afm +528 -0
  60. data/fonts/Helvetica-Condensed.inf +25 -0
  61. data/fonts/Helvetica-Narrow-Bold.afm +1439 -0
  62. data/fonts/Helvetica-Narrow-Bold.inf +26 -0
  63. data/fonts/Helvetica-Narrow-BoldOblique.afm +1439 -0
  64. data/fonts/Helvetica-Narrow-BoldOblique.inf +26 -0
  65. data/fonts/Helvetica-Narrow-Oblique.afm +1556 -0
  66. data/fonts/Helvetica-Narrow-Oblique.inf +26 -0
  67. data/fonts/Helvetica-Narrow.afm +1556 -0
  68. data/fonts/Helvetica-Narrow.inf +26 -0
  69. data/fonts/Helvetica-Oblique.afm +3051 -0
  70. data/fonts/Helvetica-Oblique.inf +26 -0
  71. data/fonts/Helvetica.afm +3051 -0
  72. data/fonts/Helvetica.inf +26 -0
  73. data/fonts/LetterGothic-Bold.afm +443 -0
  74. data/fonts/LetterGothic-Bold.inf +26 -0
  75. data/fonts/LetterGothic-BoldSlanted.afm +443 -0
  76. data/fonts/LetterGothic-BoldSlanted.inf +26 -0
  77. data/fonts/LetterGothic-Slanted.afm +443 -0
  78. data/fonts/LetterGothic-Slanted.inf +26 -0
  79. data/fonts/LetterGothic.afm +443 -0
  80. data/fonts/LetterGothic.inf +26 -0
  81. data/fonts/LubalinGraph-Book.afm +351 -0
  82. data/fonts/LubalinGraph-Book.inf +25 -0
  83. data/fonts/LubalinGraph-BookOblique.afm +351 -0
  84. data/fonts/LubalinGraph-BookOblique.inf +25 -0
  85. data/fonts/LubalinGraph-Demi.afm +351 -0
  86. data/fonts/LubalinGraph-Demi.inf +25 -0
  87. data/fonts/LubalinGraph-DemiOblique.afm +351 -0
  88. data/fonts/LubalinGraph-DemiOblique.inf +25 -0
  89. data/fonts/Marigold.afm +491 -0
  90. data/fonts/Marigold.inf +27 -0
  91. data/fonts/MonaLisa-Recut.afm +663 -0
  92. data/fonts/MonaLisa-Recut.inf +27 -0
  93. data/fonts/NewCenturySchlbk-Bold.afm +886 -0
  94. data/fonts/NewCenturySchlbk-Bold.inf +25 -0
  95. data/fonts/NewCenturySchlbk-BoldItalic.afm +1521 -0
  96. data/fonts/NewCenturySchlbk-BoldItalic.inf +26 -0
  97. data/fonts/NewCenturySchlbk-Italic.afm +1113 -0
  98. data/fonts/NewCenturySchlbk-Italic.inf +26 -0
  99. data/fonts/NewCenturySchlbk-Roman.afm +1067 -0
  100. data/fonts/NewCenturySchlbk-Roman.inf +26 -0
  101. data/fonts/Optima-Bold.afm +515 -0
  102. data/fonts/Optima-Bold.inf +27 -0
  103. data/fonts/Optima-BoldItalic.afm +712 -0
  104. data/fonts/Optima-BoldItalic.inf +26 -0
  105. data/fonts/Optima-Italic.afm +737 -0
  106. data/fonts/Optima-Italic.inf +26 -0
  107. data/fonts/Optima.afm +501 -0
  108. data/fonts/Optima.inf +27 -0
  109. data/fonts/Palatino-Bold.afm +675 -0
  110. data/fonts/Palatino-Bold.inf +26 -0
  111. data/fonts/Palatino-BoldItalic.afm +702 -0
  112. data/fonts/Palatino-BoldItalic.inf +26 -0
  113. data/fonts/Palatino-Italic.afm +700 -0
  114. data/fonts/Palatino-Italic.inf +26 -0
  115. data/fonts/Palatino-Roman.afm +718 -0
  116. data/fonts/Palatino-Roman.inf +26 -0
  117. data/fonts/StempelGaramond-Bold.afm +412 -0
  118. data/fonts/StempelGaramond-Bold.inf +27 -0
  119. data/fonts/StempelGaramond-BoldItalic.afm +413 -0
  120. data/fonts/StempelGaramond-BoldItalic.inf +27 -0
  121. data/fonts/StempelGaramond-Italic.afm +413 -0
  122. data/fonts/StempelGaramond-Italic.inf +27 -0
  123. data/fonts/StempelGaramond-Roman.afm +412 -0
  124. data/fonts/StempelGaramond-Roman.inf +27 -0
  125. data/fonts/Symbol.afm +213 -0
  126. data/fonts/Symbol.inf +27 -0
  127. data/fonts/Times-Bold.afm +2588 -0
  128. data/fonts/Times-Bold.inf +26 -0
  129. data/fonts/Times-BoldItalic.afm +2384 -0
  130. data/fonts/Times-BoldItalic.inf +26 -0
  131. data/fonts/Times-Italic.afm +2667 -0
  132. data/fonts/Times-Italic.inf +26 -0
  133. data/fonts/Times-Roman.afm +2419 -0
  134. data/fonts/Times-Roman.inf +26 -0
  135. data/fonts/Univers-Bold.afm +712 -0
  136. data/fonts/Univers-Bold.inf +27 -0
  137. data/fonts/Univers-BoldOblique.afm +712 -0
  138. data/fonts/Univers-BoldOblique.inf +27 -0
  139. data/fonts/Univers-Condensed.afm +403 -0
  140. data/fonts/Univers-Condensed.inf +27 -0
  141. data/fonts/Univers-CondensedOblique.afm +403 -0
  142. data/fonts/Univers-CondensedOblique.inf +27 -0
  143. data/fonts/Univers-Light.afm +737 -0
  144. data/fonts/Univers-Light.inf +27 -0
  145. data/fonts/Univers-LightOblique.afm +737 -0
  146. data/fonts/Univers-LightOblique.inf +27 -0
  147. data/fonts/Univers-Oblique.afm +656 -0
  148. data/fonts/Univers-Oblique.inf +27 -0
  149. data/fonts/Univers.afm +656 -0
  150. data/fonts/Univers.inf +27 -0
  151. data/fonts/ZapfChancery-MediumItalic.afm +842 -0
  152. data/fonts/ZapfChancery-MediumItalic.inf +26 -0
  153. data/fonts/ZapfDingbats.afm +225 -0
  154. data/fonts/ZapfDingbats.inf +26 -0
  155. data/lib/epdfafm.rb +334 -0
  156. data/lib/epdfdw.rb +710 -0
  157. data/lib/epdfk.rb +3142 -0
  158. data/lib/epdfo.rb +882 -0
  159. data/lib/epdfpw.rb +1749 -0
  160. data/lib/epdfs.rb +101 -0
  161. data/lib/epdfsw.rb +267 -0
  162. data/lib/epdft.rb +145 -0
  163. data/lib/epdftt.rb +458 -0
  164. data/test/pdf_tests.rb +16 -0
  165. data/test/test.rb +816 -0
  166. data/test/test_epdfafm.rb +202 -0
  167. data/test/test_epdfdw.rb +369 -0
  168. data/test/test_epdfk.rb +47 -0
  169. data/test/test_epdfo.rb +762 -0
  170. data/test/test_epdfpw.rb +129 -0
  171. data/test/test_epdfs.rb +54 -0
  172. data/test/test_epdfsw.rb +314 -0
  173. data/test/test_epdft.rb +198 -0
  174. data/test/test_epdftt.rb +34 -0
  175. data/test/test_helpers.rb +18 -0
  176. data/test/testimg.jpg +0 -0
  177. metadata +247 -0
data/lib/epdfdw.rb ADDED
@@ -0,0 +1,710 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: ASCII-8BIT
3
+ #
4
+ # Created by Brent Rowland on 2007-07-13.
5
+ # Copyright (c) 2007, 2008 Eidetic Software. All rights reserved.
6
+
7
+ require 'epdfpw'
8
+ require 'epdfo'
9
+ require 'epdfk'
10
+ require 'epdfafm'
11
+ require 'epdftt'
12
+
13
+ module EideticPDF
14
+
15
+ class DocumentWriter
16
+ def next_seq # :nodoc:
17
+ @next_seq += 1
18
+ end
19
+
20
+ attr_reader :pages # :nodoc:
21
+ attr_reader :catalog, :file, :resources # :nodoc:
22
+ attr_reader :fonts, :images, :encodings, :bullets # :nodoc:
23
+ attr_reader :in_page
24
+
25
+ # Instantiate a new DocumentWriter object. Document is NOT open for writing at this point.
26
+ def initialize
27
+ @fonts = {}
28
+ @images = {}
29
+ @encodings = {}
30
+ @bullets = {}
31
+ end
32
+
33
+ # Render document to PDF and return as a binary string.
34
+ def to_s
35
+ @file.to_s
36
+ end
37
+
38
+ # Open the document for writing.
39
+ #
40
+ # The following document options apply:
41
+ # [:+pages_up+] A tuple (array) of the form [+pages_across+, +pages_down+] specifying the layout of virtual pages. Defaults to [1, 1] (no virtual pages).
42
+ # [:+pages_up_layout+] When :+across+, virtual pages proceed from left to right before top to bottom. When :+down+, virtual pages proceed from top to bottom before left to right.
43
+ #
44
+ # In addition, any of the options for +open_page+ may be supplied and will apply to each page, unless explicitly overridden.
45
+ def open(options={})
46
+ raise Exception.new("Already in document") if @in_doc
47
+ @in_doc = true
48
+ @options = options
49
+ @pages = []
50
+ @next_seq = 0
51
+ @file = PdfObjects::PdfFile.new
52
+ pages = PdfObjects::PdfPages.new(next_seq, 0)
53
+ outlines = PdfObjects::PdfOutlines.new(next_seq, 0)
54
+ @catalog = PdfObjects::PdfCatalog.new(next_seq, 0, :use_none, pages, outlines)
55
+ @file.body << pages << outlines << @catalog
56
+ @file.trailer.root = @catalog
57
+ define_resources
58
+ @pages_across, @pages_down = options[:pages_up] || [1, 1]
59
+ @pages_up = @pages_across * @pages_down
60
+ end
61
+
62
+ # Close any open pages, preparing the document for rendering to PDF.
63
+ def close
64
+ open_page if @pages.empty? # empty document needs at least one page
65
+ close_page if @in_page
66
+ @pages.each { |page| page.close unless page.closed? }
67
+ end
68
+
69
+ # Open the document for writing and yield to the block given before calling +close+.
70
+ def doc(options={}, &block)
71
+ open(options)
72
+ yield(self)
73
+ close
74
+ end
75
+
76
+ # Open a page for writing. Raises Exception if a page is already open.
77
+ #
78
+ # The following page options apply:
79
+ # [:+compress+] Compress page streams using zlib deflate.
80
+ # [:+units+] A symbol from EideticPDF::UNIT_CONVERSION hash, specifying ratio of units to points. Defaults to :+pt+. Other choices are :+in+ for inches and :+cm+ for centimeters. Custom units may be added.
81
+ # [:+v_text_align+] Initial vertical text alignment for page. See +v_text_align+ method.
82
+ # [:+font+] Initial font for page. Defaults to <tt>{ :name => 'Helvetica', :size => 12 }</tt>.
83
+ # [:+fill_color+] Initial fill color. Defaults to 0 (black). See +fill_color+ method.
84
+ # [:+line_color+] Initial line color. Defaults to 0 (black). See +line_color+ method.
85
+ # [:+line_height+] Initial line height. Defaults to 1.7. See +line_height+ method.
86
+ # [:+line_width+] Initial line width. Defaults to 1.0. See +line_width+ method.
87
+ # [:+margins+] Page margins. Defaults to 0. See +margins+ method.
88
+ # [:+unscaled+] If true, virtual pages are not scaled down. Defaults to +false+.
89
+ def open_page(options={})
90
+ raise Exception.new("Already in page") if @in_page
91
+ options.update(:_page => pdf_page(@pages.size), :sub_page => sub_page(@pages.size))
92
+ @cur_page = PageWriter.new(self, @options.merge(options))
93
+ @pages << @cur_page
94
+ @in_page = true
95
+ return @cur_page
96
+ end
97
+
98
+ # Close the current open page. Raises Exception if no page is currently open.
99
+ def close_page
100
+ raise Exception.new("Not in page") unless @in_page
101
+ @cur_page.close
102
+ @cur_page = nil
103
+ @in_page = false
104
+ end
105
+
106
+ # Open a page for writing and yield to the block given before calling +close_page+.
107
+ #
108
+ # +options+ is passed through to +open_page+.
109
+ def page(options={}, &block)
110
+ cur_page = open_page(options)
111
+ yield(cur_page)
112
+ close_page
113
+ end
114
+
115
+ # Close the current page and begin a new page with the specified options.
116
+ # [+options+] See +open_page+ method.
117
+ def new_page(options={})
118
+ close_page
119
+ open_page(options)
120
+ end
121
+
122
+ def cur_page # :nodoc:
123
+ @cur_page || open_page
124
+ end
125
+
126
+ # Set units measurements are to be specified in. If no units are specified, returns current units setting.
127
+ # Valid units include :+pt+ (points), :+in+ (inches) and :+cm+ (centimeters) by default.
128
+ #
129
+ # Custom units can be specified by updating the EideticPDF::UNIT_CONVERSION hash with a new symbol and conversion ratio.
130
+ def units(units=nil)
131
+ cur_page.units(units)
132
+ end
133
+
134
+ # Set top, right, bottom and left margins. If 1, 2 or 4 values are not specified, returns current margins as a tuple (array)
135
+ # of values in the form [top, right, bottom, left].
136
+ # [+margins+] When 4 values are given, [top, right, bottom, left]. When 2 values are given, [top and bottom, right and left]. When 1 value is specified, it is used for all 4 settings.
137
+ def margins(*margins)
138
+ cur_page.margins(*margins)
139
+ end
140
+
141
+ # Returns top margin as set by +margins+ method.
142
+ def margin_top
143
+ cur_page.margin_top
144
+ end
145
+
146
+ # Returns right margin as set by +margins+ method.
147
+ def margin_right
148
+ cur_page.margin_right
149
+ end
150
+
151
+ # Returns bottom margin as set by +margins+ method.
152
+ def margin_bottom
153
+ cur_page.margin_bottom
154
+ end
155
+
156
+ # Returns left margin as set by +margins+ method.
157
+ def margin_left
158
+ cur_page.margin_left
159
+ end
160
+
161
+ # +page_height+ excluding top and bottom margins.
162
+ def canvas_width
163
+ cur_page.canvas_width
164
+ end
165
+
166
+ # +page_width+ excluding left and right margins.
167
+ def canvas_height
168
+ cur_page.canvas_height
169
+ end
170
+
171
+ # Set horizontal tabs using an array of numbers or a comma-delimited string. If no tabs are specified, returns current tabs.
172
+ # Use false to clear current tab stops.
173
+ def tabs(tabs=nil)
174
+ cur_page.tabs(tabs)
175
+ end
176
+
177
+ # Move right to next horizontal tab. If no more tab stops exist, then moves to first tab stop on the following line.
178
+ # If a block is given, the value returned is used instead as the vertical distance to move down.
179
+ def tab(&block)
180
+ cur_page.tab(&block)
181
+ end
182
+
183
+ # Set vertical tabs using an array of numbers or a comma-delimited string. If no tabs are specified, returns current tabs.
184
+ # Use false to clear current tab stops.
185
+ def vtabs(tabs=nil)
186
+ cur_page.vtabs(tabs)
187
+ end
188
+
189
+ # Move down to next vertical tab. If no more tab stops exist and a block is given, moves up to the first vertical tab stop
190
+ # and right the value returned by the block.
191
+ def vtab(&block)
192
+ cur_page.vtab(&block)
193
+ end
194
+
195
+ # Set horizontal indentation. If no value is specified, returns current indentation setting.
196
+ # [+value+] The new indentation.
197
+ # [+absolute+] If +true+, the new value is relative only to the left margin. If +false+, value is relative to previous indentation.
198
+ # The indent setting is used by the +puts+ and +new_line+ methods.
199
+ def indent(value=nil, absolute=false)
200
+ cur_page.indent(value, absolute)
201
+ end
202
+
203
+ # Returns page width in current units.
204
+ def page_width
205
+ cur_page.page_width
206
+ end
207
+
208
+ # Returns page height in current units.
209
+ def page_height
210
+ cur_page.page_height
211
+ end
212
+
213
+ # Set line height as used by methods like +paragraph+ that display multiple lines of text.
214
+ # If no value is specified, returns current +line_height+.
215
+ # [+height+] Ratio of +font_size+ to effective line height.
216
+ def line_height(height=nil)
217
+ cur_page.line_height(height)
218
+ end
219
+
220
+ # Move pen to point <tt>(x, y)</tt>.
221
+ def move_to(x, y)
222
+ cur_page.move_to(x, y)
223
+ end
224
+
225
+ # Move pen to point <tt>(x, y)</tt> like +move_to+, returning previous location. If x is not specified, returns current location.
226
+ def pen_pos(x=nil, y=nil)
227
+ cur_page.pen_pos(x, y)
228
+ end
229
+
230
+ # Move the pen to a new location relative to the current location.
231
+ # [+dx+] Horizontal distance to move pen. Positive values move right. Negative values move left.
232
+ # [+dy+] Vertical distance to move pen. Positive values move down. Negative values move up.
233
+ def move_by(dx, dy)
234
+ cur_page.move_by(dx, dy)
235
+ end
236
+
237
+ # Draw a line from the current location to point <tt>(x, y)</tt>.
238
+ # If +auto_path+ is off, a new segment is appended to the current path.
239
+ def line_to(x, y)
240
+ cur_page.line_to(x, y)
241
+ end
242
+
243
+ # Draw a line from point <tt>(x, y)</tt> to a point +length+ units distant at +angle+ degrees.
244
+ def line(x, y, angle, length)
245
+ cur_page.line(x, y, angle, length)
246
+ end
247
+
248
+ # Draw a rectangle with the specified +width+ and +height+ and its top, left corner at <tt>(x, y)</tt>.
249
+ #
250
+ # The following +options+ apply:
251
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
252
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
253
+ # [:+clip+] If true and a block is given, the shape acts as a clipping boundary for anything drawn within the supplied block.
254
+ # [:+reverse+] Draw polygon clockwise. This is useful for drawing hollow shapes.
255
+ #
256
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
257
+ def rectangle(x, y, width, height, options={})
258
+ cur_page.rectangle(x, y, width, height, options)
259
+ end
260
+
261
+ # Draw a cubic Bezier curve from <tt>(x0, y0)</tt> to <tt>(x3, y3)</tt> with control points <tt><x1, y1></tt> and <tt>(x2, y2)</tt>.
262
+ # If the first point does not coincide with the current position, any current path is stroked and a new path is begun.
263
+ # Otherwise, the curve is appended to the current path.
264
+ def curve(x0, y0, x1, y1, x2, y2, x3, y3)
265
+ cur_page.curve(x0, y0, x1, y1, x2, y2, x3, y3)
266
+ end
267
+
268
+ # Draw a series of cubic Bezier curves. After moving to the first point, a curve to the 4th point is appended to the current path
269
+ # with the 2nd and 3rd points acting as control points. A curve is appended to the current path for each additional group
270
+ # of 3 points, with the 1st and 2nd point in each group acting as control points.
271
+ #
272
+ # [+points+] array of +Location+ structs
273
+ def curve_points(points)
274
+ cur_page.curve_points(points)
275
+ end
276
+
277
+ # Returns array of +Location+ structs for circle, suitable for feeding to +curve_points+ method. See +circle+ method.
278
+ def points_for_circle(x, y, r)
279
+ cur_page.points_for_circle(x, y, r)
280
+ end
281
+
282
+ # Draw a circle with center <tt>x, y</tt> and radius +r+.
283
+ # Direction is counterclockwise (anticlockwise), unless :+reverse+ option is specified.
284
+ #
285
+ # The following +options+ apply:
286
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
287
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
288
+ # [:+clip+] The shape acts as a clipping boundary for anything drawn within the supplied block.
289
+ # [:+reverse+] Draw circle clockwise. Useful for drawing hollow shapes.
290
+ #
291
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
292
+ def circle(x, y, r, options={}, &block)
293
+ cur_page.circle(x, y, r, options, &block)
294
+ end
295
+
296
+ # Returns array of +Location+ structs for ellipse, suitable for feeding to +curve_points+ method. See +ellipse+ method.
297
+ def points_for_ellipse(x, y, rx, ry)
298
+ cur_page.points_for_ellipse(x, y, rx, ry)
299
+ end
300
+
301
+ # Draw an ellipse with foci (<tt>x, y</tt>) and (<tt>x, y</tt>) and radius +r+.
302
+ # Direction is counterclockwise (anticlockwise), unless :+reverse+ option is specified.
303
+ #
304
+ # The following +options+ apply:
305
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
306
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
307
+ # [:+clip+] The shape acts as a clipping boundary for anything drawn within the supplied block.
308
+ # [:+reverse+] Draw ellipse clockwise. Useful for drawing hollow shapes.
309
+ #
310
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
311
+ def ellipse(x, y, rx, ry, options={})
312
+ cur_page.ellipse(x, y, rx, ry, options)
313
+ end
314
+
315
+ # Returns array of +Location+ structs for arc, suitable for feeding to +curve_points+ method. See +arc+ method.
316
+ def points_for_arc(x, y, r, start_angle, end_angle)
317
+ cur_page.points_for_arc(x, y, r, start_angle, end_angle)
318
+ end
319
+
320
+ # Draw an arc with origin <tt>x, y</tt> and radius +r+ from +start_angle+ to +end_angle+ degrees.
321
+ # Direction is counterclockwise (anticlockwise), unless +end_angle+ < +start_angle+.
322
+ # Angles are allowed to exceed 360 degrees.
323
+ #
324
+ # By default, arc extends the current path to the point where the arc begins.
325
+ # If <tt>move_to0</tt> is true (or there is no current path) a move is performed to where the arc begins.
326
+ #
327
+ # This method returns immediately if <tt>start_angle == end_angle</tt>.
328
+ def arc(x, y, r, start_angle, end_angle, move_to0=false)
329
+ cur_page.arc(x, y, r, start_angle, end_angle, move_to0)
330
+ end
331
+
332
+ # Draw a pie-shaped wedge with origin <tt>x, y</tt> and radius +r+ from +start_angle+ to +end_angle+ degrees.
333
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
334
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
335
+ # [:+clip+] If true and a block is given, the shape acts as a clipping boundary for anything drawn within the supplied block.
336
+ # [:+reverse+] By default, the bounding path is drawn from <tt>(x, y)</tt> to <tt>(r, start_angle)</tt> through <tt>(r, end_angle)</tt> and back to <tt>(x, y)</tt>. This order is reversed if <tt>:reverse => true</tt>. This is useful for drawing hollow shapes.
337
+ #
338
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
339
+ def pie(x, y, r, start_angle, end_angle, options={})
340
+ cur_page.pie(x, y, r, start_angle, end_angle, options)
341
+ end
342
+
343
+ # Draw an arch with origin <tt>x, y</tt> from +start_angle+ to _end_angle_ degrees.
344
+ # The result is a bounded area between radii <tt>r1</tt> and <tt>r2</tt>.
345
+ #
346
+ # The following +options+ apply:
347
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
348
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
349
+ # [:+clip+] If true and a block is given, the shape acts as a clipping boundary for anything drawn within the supplied block.
350
+ # [:+reverse+] By default, the bounding path is drawn from <tt>(r1, start_angle)</tt> to <tt>(r1, end_angle)</tt>, <tt>(r2, end_angle)</tt>, <tt>(r2, start_angle)</tt> and back to <tt>(r1, start_angle)</tt>. This order is reversed if <tt>reverse => true</tt>. This is useful for drawing hollow shapes.
351
+ #
352
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
353
+ def arch(x, y, r1, r2, start_angle, end_angle, options={}, &block)
354
+ cur_page.arch(x, y, r1, r2, start_angle, end_angle, options, &block)
355
+ end
356
+
357
+ # Returns array of +Location+ structs representing the vertices of a polygon. See +polygon+ method.
358
+ def points_for_polygon(x, y, r, sides, options={})
359
+ cur_page.points_for_polygon(x, y, r, sides, options)
360
+ end
361
+
362
+ # Draw a polygon with origin <tt>(x, y)</tt>, radius +r+ and the specified number of +sides+.
363
+ #
364
+ # The following +options+ apply:
365
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
366
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
367
+ # [:+clip+] If true and a block is given, the shape acts as a clipping boundary for anything drawn within the supplied block.
368
+ # [:+reverse+] Draw polygon clockwise. This is useful for drawing hollow shapes.
369
+ #
370
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
371
+ def polygon(x, y, r, sides, options={})
372
+ cur_page.polygon(x, y, r, sides, options)
373
+ end
374
+
375
+ # Draw a star with origin <tt>(x, y)</tt>, outer radius +r1+, inner radius +r2+ and the specified number of +sides+.
376
+ #
377
+ # The following +options+ apply:
378
+ # [:+border+] If true or a color, a border is drawn with the current or specified +line_color+, respectively. Defaults to +true+.
379
+ # [:+fill+] If true or a color, the area is filled with the current or specified +fill_color+, respectively. Defaults to +false+.
380
+ # [:+clip+] If true and a block is given, the shape acts as a clipping boundary for anything drawn within the supplied block.
381
+ # [:+reverse+] Draw polygon clockwise. This is useful for drawing hollow shapes.
382
+ #
383
+ # These current settings also apply: +line_color+, +line_width+, +line_dash_pattern+ and +fill_color+.
384
+ def star(x, y, r1, r2, points, options={})
385
+ cur_page.star(x, y, r1, r2, points, options)
386
+ end
387
+
388
+ # Returns current status of auto_path. Defaults to +true+. False while in a block given to +path+ method.
389
+ # When +true+, paths are automatically stroked before a new, non-contiguous segment is appended or a closed shape is drawn.
390
+ def auto_path
391
+ cur_page.auto_path
392
+ end
393
+
394
+ # Turn off auto_path. If a block is given, yields to it before filling and/or stroking anything drawn within it according to
395
+ # the +options+ supplied. The path may be non-contiguous. Shapes may be hollow when inner paths are drawn in the opposite
396
+ # direction as outer paths.
397
+ #
398
+ # The following options apply:
399
+ # [:+stroke+] If true or a color, the path will be stroked with the current or specified +line_color+, respectively. Defaults to +false+.
400
+ # [:+fill+] If true or a color, the area bounded by the path will be filled with the current or specified +fill_color+, respectively. Defaults to +false+.
401
+ def path(options={}, &block)
402
+ cur_page.path(options, &block)
403
+ end
404
+
405
+ # Fill current path (begun by +path+ method) and resume +auto_path+. The +line_color+ and +fill_color+ in effect before +path+
406
+ # was begun are restored. Raises Exception if no current path exists.
407
+ def fill
408
+ cur_page.fill
409
+ end
410
+
411
+ # Stroke current path (begun by +path+ method) and resume +auto_path+. The +line_color+ and +fill_color+ in effect before +path+
412
+ # was begun are restored. Raises Exception if no current path exists.
413
+ def stroke
414
+ cur_page.stroke
415
+ end
416
+
417
+ # Fill and stroke current path (begun by +pat+ method) and resume +auto_path+. The +line_color+ and +fill_color+ in effect
418
+ # before +path+ was begun are restored. Raises Exception if no current path exists.
419
+ def fill_and_stroke
420
+ cur_page.fill_and_stroke
421
+ end
422
+
423
+ # Use current path as a clipping boundary for anything drawn within the supplied block.
424
+ #
425
+ # The following +options+ apply:
426
+ # [:+stroke+] If true, the current path is stroked with the current +line_color+. Defaults to +false+.
427
+ # [:+fill+] If true, the area bounded by the current path is filled with the current +fill_color+. Defaults to +false+.
428
+ def clip(options={}, &block)
429
+ cur_page.clip(options, &block)
430
+ end
431
+
432
+ # Set the shape to be used at the ends of lines. If no style is specified, returns current style.
433
+ # [+style+] One of the symbols :butt_cap, :round_cap or :projecting_square_cap, or a string 'butt_cap', 'round_cap' or 'projecting_square_cap'.
434
+ def line_cap_style(style=nil)
435
+ cur_page.line_cap_style(style)
436
+ end
437
+
438
+ # Set the pattern of dashes and gaps used to draw lines. If no pattern is specified, returns current pattern.
439
+ # [+pattern+] A string of the form '[dash gap] phase' or one of the symbols :+solid+, :+dotted+ or :+dashed+.
440
+ # When a symbol is specified, dash and gap lengths are multiplied by +line_width+ for proportion.
441
+ def line_dash_pattern(pattern=nil)
442
+ cur_page.line_dash_pattern(pattern)
443
+ end
444
+
445
+ # Set line width used when stroking paths. If no width is specified, returns current +line_width+.
446
+ # [+value+] If +value+ is a number, the new +line_width+ setting. If +value+ is a symbol (such as :pt, :cm or :in), the units to return the current +line_width+ in. If +value+ is a string, it may include the units as a suffix, e.g. "5.5in" for 5.5 inches.
447
+ # [+units+] Units value is expressed in. Defaults to current units setting.
448
+ def line_width(value=nil, units=nil)
449
+ cur_page.line_width(value, units)
450
+ end
451
+
452
+ # Returns hash of named colors consisting of (name, color) pairs.
453
+ # Initial value comes from EideticPDF::PdfK::NAMED_COLORS, but may be augmented or replaced.
454
+ def named_colors
455
+ @named_colors ||= PdfK::NAMED_COLORS.dup
456
+ end
457
+
458
+ # Set line color, returning previous line color. If no color is specified, returns current font color.
459
+ # [+color+] Tuple (array) containing [red, green, blue] components of new color (where components range from 0..255), string key into +named_colors+ or integer encoded from rgb bytes where blue is in the least-significant byte.
460
+ # Return values are always in string or integer form.
461
+ def line_color(color=nil)
462
+ cur_page.line_color(color)
463
+ end
464
+
465
+ # Set fill color, returning previous fill color. If no color is specified, returns current fill color.
466
+ # [+color+] Tuple (array) containing [red, green, blue] components of new color (where components range from 0..255) or integer encoded from rgb bytes where blue is in the least-significant byte.
467
+ # Return values are always in integer form.
468
+ def fill_color(color=nil)
469
+ cur_page.fill_color(color)
470
+ end
471
+
472
+ # Set font color, returning previous font color. If no color is specified, returns current font color.
473
+ # [+color+] Tuple (array) containing [red, green, blue] components of new color (where components range from 0..255) or integer encoded from rgb bytes where blue is in the least-significant byte.
474
+ # Return values are always in integer form.
475
+ def font_color(color=nil)
476
+ cur_page.font_color(color)
477
+ end
478
+
479
+ # Set font encoding, returning previous font encoding. If no encoding is specified, returns current font encoding.
480
+ def font_encoding(encoding=nil)
481
+ cur_page.font_encoding(encoding)
482
+ end
483
+
484
+ # Print text, starting from the current position.
485
+ #
486
+ # The following options apply:
487
+ # [:+align+] When :+left+, left edge of text is aligned to current position. When :+center+, text is centered at current position. When :+right+, right edge of text is aligned to current position. When any alignment is specified, the pen is restored to its original location.
488
+ # [:+angle+] Print text at the specified +angle+ in degrees. Defaults to 0.
489
+ # [:+scale+] Horizontal scaling of text, specified as ratio to normal width. Defaults to 1.0. Cannot be combined with :+clip+.
490
+ # [:+underline+] Override +underline+ setting for this piece of text.
491
+ # [:+clip+] If true and a block is given, the edges of the text act as a clipping boundary for anything drawn within the supplied block. Cannot be combined with :+scale+.
492
+ # [:+fill+] (Only applicable with :+clip+) Fill text and add to path for clipping.
493
+ # [:+stroke+] (Only applicable with :+clip+) Stroke text with current +line_color+ and add to path for clipping.
494
+ #
495
+ # These current settings also apply: +font+, +font_color+, +line_color+ (when outlines are stroked) and vertical text alignment (+v_text_align+).
496
+ def print(text, options={}, &block)
497
+ cur_page.print(text, options, &block)
498
+ end
499
+
500
+ # Move to <tt>(x, y)</tt> and print text. See +print+ method.
501
+ def print_xy(x, y, text, options={}, &block)
502
+ cur_page.print_xy(x, y, text, options, &block)
503
+ end
504
+
505
+ # Print one or more lines of text before moving to the next line, as specified by +indent+.
506
+ def puts(text='', options={}, &block)
507
+ cur_page.puts(text, options, &block)
508
+ end
509
+
510
+ # Move to <tt>(x, y)</tt> and print one or more lines of text indented to +x+. See +puts+ method.
511
+ def puts_xy(x, y, text, options={}, &block)
512
+ cur_page.puts_xy(x, y, text, options={}, &block)
513
+ end
514
+
515
+ # Move pen down one or more lines and back to current indent.
516
+ # [+count+] Number of lines to move down.
517
+ def new_line(count=1)
518
+ cur_page.new_line(count)
519
+ end
520
+
521
+ # Returns width of a string as rendered using the current font.
522
+ def width(text)
523
+ cur_page.width(text)
524
+ end
525
+
526
+ # Breaks text into tokens and reassembles into array of strings, each one not exceeding +length+.
527
+ # Newlines are respected and all other white space is preserved.
528
+ def wrap(text, length)
529
+ cur_page.wrap(text, length)
530
+ end
531
+
532
+ # Returns text ascent, based on the current font.
533
+ # [+units+] Units the value is returned in.
534
+ def text_ascent(units=nil)
535
+ cur_page.text_ascent(units)
536
+ end
537
+
538
+ # Returns text height, based on the current font, excluding external leading.
539
+ # [+units+] Units the value is returned in.
540
+ def text_height(units=nil)
541
+ cur_page.text_height(units)
542
+ end
543
+
544
+ # Returns height of a line or array of lines, including external leading as determined by +line_height+.
545
+ # [+text+] Line or array of lines to be measured. Height is determined only by current font and number of lines.
546
+ # [+units+] Units result should be expressed in. Defaults to current +units+.
547
+ def height(text='', units=nil) # may not include external leading?
548
+ cur_page.height(text, units)
549
+ end
550
+
551
+ # Wrap +text+ and render with the following +options+.
552
+ # [:+width+] Maximum width to wrap text within. Defaults to the canvas width minus the current horizontal position.
553
+ # [:+height+] Maximum height allowed. Any text not rendered will be returned by the method call. Defaults to the canvas height minus the current vertical position.
554
+ # [:+bullet+] Render paragraph as a bullet, using the named bullet as defined using the +bullet+ method. The bullet width is subtracted from the :+width+ specified.
555
+ def paragraph(text, options={})
556
+ cur_page.paragraph(text, options)
557
+ end
558
+
559
+ # Move to <tt>(x, y)</tt> and render paragraph.
560
+ def paragraph_xy(x, y, text, options={})
561
+ cur_page.paragraph_xy(x, y, text, options)
562
+ end
563
+
564
+ # Set vertical text alignment. This is the part of the text that would coincide with a line if one were drawn at the same
565
+ # coordinates as the text.
566
+ # [:+above+] At the top of the text, plus an amount equal to the height of descenders.
567
+ # [:+top+] At the top of the text--text is rendered below the line.
568
+ # [:+middle+] Through the middle of the text, like a strikeout.
569
+ # [:+base+] At the base of the text--text is rendered above the line, except for descenders.
570
+ # [:+below+] Below the text--text is rendered above the line, including descenders.
571
+ # Default is :+top+.
572
+ def v_text_align(vta=nil)
573
+ cur_page.v_text_align(vta)
574
+ end
575
+
576
+ # Set new underline status, returning previous status. If new status is not specified, returns current underline status.
577
+ def underline(underline=nil)
578
+ cur_page.underline(underline)
579
+ end
580
+
581
+ # Returns an array of font names, including weight and style, from the (local) fonts directory.
582
+ def type1_font_names
583
+ if @options[:built_in_fonts]
584
+ PdfK::FONT_NAMES
585
+ else
586
+ AFM::font_names
587
+ end
588
+ end
589
+
590
+ def truetype_font_names # :nodoc:
591
+ if @options[:built_in_fonts]
592
+ PdfTT::FONT_NAMES
593
+ else
594
+ raise Exception.new("Non-built-in TrueType fonts not supported yet.")
595
+ end
596
+ end
597
+
598
+ # Set font, returning previous font. If no font is specified, returns current font.
599
+ # [+name+] Base name of a Type1 font with metrics file in fonts directory.
600
+ # [+size+] Size of font in points. See also +font_size+ method.
601
+ # The following +options+ apply:
602
+ # [:+style+] Bold, Italic, Oblique or a combination of weight and style such as BoldItalic or BoldOblique. See +font_style+ method.
603
+ # [:+color+] Font color as given to +font_color+ method. Color is unchanged if not specified.
604
+ # [:+encoding+] Currently-supported encodings include StandardEncoding, WinAnsiEncoding/CP1250, CP1250, CP1254, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-7, ISO-8859-9, ISO-8859-10, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, MacTurkish or Macintosh. Defaults to WinAnsiEncoding.
605
+ # [:+sub_type+] Currently only Type1 fonts are supported. Defaults to Type1.
606
+ # [:+fill+] Fill text with current +font_color+. Defaults to +true+.
607
+ # [:+stroke+] Stroke text with current +line_color+. Defaults to +false+.
608
+ def font(name=nil, size=nil, options={})
609
+ cur_page.font(name, size, options)
610
+ end
611
+
612
+ # Set font style, returning previous font style. If no style is specified, returns current font style.
613
+ # [+style+] Bold (or other weight), Italic, Oblique or combination such as BoldItalic or BoldOblique.
614
+ # Exact weights and combinations available depend on the font specification files in the (local) fonts directory.
615
+ def font_style(style=nil)
616
+ cur_page.font_style(style)
617
+ end
618
+
619
+ # Set font size, returning previous font size. If no size is specified, returns current font size.
620
+ # [+size+] Size of font in points.
621
+ def font_size(size=nil)
622
+ cur_page.font_size(size)
623
+ end
624
+
625
+ # Returns +true+ if image is a buffer beginning with a JPEG signature.
626
+ def jpeg?(image)
627
+ cur_page.jpeg?(image)
628
+ end
629
+
630
+ # Returns a tuple (array) of image dimensions of the form [width, height, components, bits_per_component].
631
+ # Raises ArgumentError if +image+ is not a JPEG.
632
+ def jpeg_dimensions(image)
633
+ cur_page.jpeg_dimensions(image)
634
+ end
635
+
636
+ def load_image(image_file_name, stream=nil) # :nodoc:
637
+ cur_page.load_image(image_file_name, stream)
638
+ end
639
+
640
+ # Load graphic file (currently only JPEG is supported) from disk (or network, if open-uri library is loaded) and display at the specified location.
641
+ # [+image_file_name+] Path or URL to image.
642
+ # [+x+] Left edge of image is placed at this offset. Defaults to <tt>pen_pos.x</tt>.
643
+ # [+y+] Top edge of image is placed at this offset. Defaults to <tt>pen_pos.y</tt>.
644
+ # [+width+] Width to make image. Defaults to natural image width or a width proportionate to +height+ if +height+ is specified.
645
+ # [+height+] Height to make image. Defaults to natural image height or a height proportionate to +width+ if +width+ is specified.
646
+ def print_image_file(image_file_name, x=nil, y=nil, width=nil, height=nil)
647
+ cur_page.print_image_file(image_file_name, x, y, width, height)
648
+ end
649
+
650
+ # Display graphic (currently only JPEG is supported) from disk (or network, if open-uri library is loaded) and display at the specified location.
651
+ # [+data+] Buffer containing image.
652
+ # [+x+] Left edge of image is placed at this offset. Defaults to <tt>pen_pos.x</tt>.
653
+ # [+y+] Top edge of image is placed at this offset. Defaults to <tt>pen_pos.y</tt>.
654
+ # [+width+] Width to make image. Defaults to natural image width or a width proportionate to +height+ if +height+ is specified.
655
+ # [+height+] Height to make image. Defaults to natural image height or a height proportionate to +width+ if +width+ is specified.
656
+ def print_image(data, x=nil, y=nil, width=nil, height=nil)
657
+ cur_page.print_image(data, x, y, width, height)
658
+ end
659
+
660
+ def print_link(s, uri) # :nodoc:
661
+ cur_page.print_link(s, uri)
662
+ end
663
+
664
+ # Given a block, defines a named bullet. Otherwise the named Bullet struct is returned.
665
+ #
666
+ # The following +options+ apply:
667
+ # [:+units+] The units that :+width+ is expressed in. Defaults to the current units setting.
668
+ # [:+width+] The width of the area reserved for the bullet.
669
+ #
670
+ # If a block is given, the block should expect a +writer+ parameter to be used for printing or drawing the bullet.
671
+ # Within the block, all altered settings, other than the location, should be restored.
672
+ def bullet(name, options={}, &block)
673
+ cur_page.bullet(name, options, &block)
674
+ end
675
+
676
+ # Rotate anything drawn within the supplied block +angle+ degrees around origin <tt>(x, y)</tt>.
677
+ def rotate(angle, x, y, &block)
678
+ cur_page.rotate(angle, x, y, &block)
679
+ end
680
+
681
+ def scale(x, y, scale_x, scale_y, &block)
682
+ cur_page.scale(x, y, scale_x, scale_y, &block)
683
+ end
684
+
685
+ protected
686
+ def define_resources # :nodoc:
687
+ @resources = PdfObjects::PdfResources.new(next_seq, 0)
688
+ @resources.proc_set = PdfObjects::PdfName.ary ['PDF','Text','ImageB','ImageC']
689
+ @file.body << @resources
690
+ end
691
+
692
+ def sub_page(page_no) # :nodoc:
693
+ if @pages_up == 1
694
+ nil
695
+ elsif @options[:pages_up_layout] == :down
696
+ [(page_no / @pages_down) % @pages_across, @pages_across, page_no % @pages_down, @pages_down]
697
+ else
698
+ [page_no % @pages_across, @pages_across, (page_no / @pages_across) % @pages_down, @pages_down]
699
+ end
700
+ end
701
+
702
+ def pdf_page(page_no) # :nodoc:
703
+ if page = @pages[page_no / @pages_up * @pages_up]
704
+ page.page
705
+ else
706
+ nil
707
+ end
708
+ end
709
+ end
710
+ end