eideticpdf 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
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