prawn 0.15.0 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (269) hide show
  1. data/COPYING +2 -2
  2. data/LICENSE +1 -1
  3. data/README.md +96 -0
  4. data/Rakefile +27 -30
  5. data/data/fonts/Action Man.dfont +0 -0
  6. data/data/fonts/Activa.ttf +0 -0
  7. data/data/fonts/Chalkboard.ttf +0 -0
  8. data/data/fonts/DejaVuSans.ttf +0 -0
  9. data/data/fonts/Dustismo_Roman.ttf +0 -0
  10. data/data/fonts/comicsans.ttf +0 -0
  11. data/data/fonts/gkai00mp.ttf +0 -0
  12. data/data/images/16bit.alpha +0 -0
  13. data/data/images/16bit.dat +0 -0
  14. data/data/images/dice.alpha +0 -0
  15. data/data/images/dice.dat +0 -0
  16. data/data/images/page_white_text.alpha +0 -0
  17. data/data/images/page_white_text.dat +0 -0
  18. data/data/images/rails.dat +0 -0
  19. data/data/images/rails.png +0 -0
  20. data/data/pdfs/nested_pages.pdf +13 -13
  21. data/lib/prawn.rb +21 -85
  22. data/lib/prawn/compatibility.rb +51 -0
  23. data/lib/prawn/core.rb +85 -0
  24. data/lib/prawn/core/annotations.rb +61 -0
  25. data/lib/prawn/core/byte_string.rb +9 -0
  26. data/lib/prawn/core/destinations.rb +90 -0
  27. data/lib/prawn/core/document_state.rb +78 -0
  28. data/lib/prawn/core/literal_string.rb +16 -0
  29. data/lib/prawn/core/name_tree.rb +177 -0
  30. data/lib/prawn/core/object_store.rb +264 -0
  31. data/lib/prawn/core/page.rb +215 -0
  32. data/lib/prawn/core/pdf_object.rb +108 -0
  33. data/lib/prawn/core/reference.rb +115 -0
  34. data/lib/prawn/core/text.rb +268 -0
  35. data/lib/prawn/core/text/formatted/arranger.rb +294 -0
  36. data/lib/prawn/core/text/formatted/line_wrap.rb +273 -0
  37. data/lib/prawn/core/text/formatted/wrap.rb +153 -0
  38. data/lib/prawn/document.rb +122 -155
  39. data/lib/prawn/document/bounding_box.rb +7 -36
  40. data/lib/prawn/document/column_box.rb +10 -38
  41. data/lib/prawn/document/graphics_state.rb +74 -11
  42. data/lib/prawn/document/internals.rb +23 -24
  43. data/lib/prawn/document/page_geometry.rb +136 -0
  44. data/lib/prawn/document/snapshot.rb +6 -7
  45. data/lib/prawn/document/span.rb +10 -12
  46. data/lib/prawn/encoding.rb +10 -9
  47. data/lib/prawn/errors.rb +30 -15
  48. data/lib/prawn/font.rb +104 -136
  49. data/lib/prawn/font/afm.rb +44 -46
  50. data/lib/prawn/font/dfont.rb +3 -4
  51. data/lib/prawn/font/ttf.rb +50 -31
  52. data/lib/prawn/graphics.rb +57 -302
  53. data/lib/prawn/graphics/cap_style.rb +3 -4
  54. data/lib/prawn/graphics/color.rb +5 -13
  55. data/lib/prawn/graphics/dash.rb +31 -53
  56. data/lib/prawn/graphics/gradient.rb +84 -0
  57. data/lib/prawn/graphics/join_style.rb +7 -9
  58. data/lib/prawn/graphics/transformation.rb +9 -10
  59. data/lib/prawn/graphics/transparency.rb +1 -3
  60. data/lib/prawn/images.rb +59 -69
  61. data/lib/prawn/images/image.rb +22 -6
  62. data/lib/prawn/images/jpg.rb +14 -20
  63. data/lib/prawn/images/png.rb +118 -61
  64. data/lib/prawn/layout.rb +15 -10
  65. data/lib/prawn/layout/grid.rb +54 -66
  66. data/lib/prawn/measurement_extensions.rb +6 -10
  67. data/lib/prawn/measurements.rb +21 -27
  68. data/lib/prawn/outline.rb +308 -6
  69. data/lib/prawn/repeater.rb +8 -10
  70. data/lib/prawn/security.rb +33 -55
  71. data/lib/prawn/security/arcfour.rb +0 -1
  72. data/lib/prawn/stamp.rb +3 -5
  73. data/lib/prawn/table.rb +60 -188
  74. data/lib/prawn/table/cell.rb +44 -272
  75. data/lib/prawn/table/cell/image.rb +3 -2
  76. data/lib/prawn/table/cell/in_table.rb +2 -4
  77. data/lib/prawn/table/cell/subtable.rb +2 -2
  78. data/lib/prawn/table/cell/text.rb +18 -41
  79. data/lib/prawn/table/cells.rb +48 -142
  80. data/lib/prawn/text.rb +25 -32
  81. data/lib/prawn/text/box.rb +6 -12
  82. data/lib/prawn/text/formatted.rb +4 -5
  83. data/lib/prawn/text/formatted/box.rb +59 -96
  84. data/lib/prawn/text/formatted/fragment.rb +23 -34
  85. data/lib/prawn/text/formatted/parser.rb +5 -15
  86. data/prawn.gemspec +13 -24
  87. data/spec/annotations_spec.rb +32 -16
  88. data/spec/bounding_box_spec.rb +17 -119
  89. data/spec/cell_spec.rb +42 -112
  90. data/spec/destinations_spec.rb +5 -5
  91. data/spec/document_spec.rb +111 -155
  92. data/spec/extensions/mocha.rb +0 -1
  93. data/spec/font_spec.rb +99 -149
  94. data/spec/formatted_text_arranger_spec.rb +43 -43
  95. data/spec/formatted_text_box_spec.rb +44 -43
  96. data/spec/formatted_text_fragment_spec.rb +8 -8
  97. data/spec/graphics_spec.rb +68 -151
  98. data/spec/grid_spec.rb +15 -26
  99. data/spec/images_spec.rb +30 -51
  100. data/spec/inline_formatted_text_parser_spec.rb +20 -69
  101. data/spec/jpg_spec.rb +4 -4
  102. data/spec/line_wrap_spec.rb +28 -28
  103. data/spec/measurement_units_spec.rb +6 -6
  104. data/spec/name_tree_spec.rb +112 -0
  105. data/spec/object_store_spec.rb +106 -17
  106. data/spec/outline_spec.rb +63 -103
  107. data/spec/pdf_object_spec.rb +170 -0
  108. data/spec/png_spec.rb +25 -25
  109. data/spec/reference_spec.rb +65 -8
  110. data/spec/repeater_spec.rb +10 -10
  111. data/spec/security_spec.rb +12 -44
  112. data/spec/snapshot_spec.rb +7 -7
  113. data/spec/span_spec.rb +15 -10
  114. data/spec/spec_helper.rb +8 -32
  115. data/spec/stamp_spec.rb +30 -29
  116. data/spec/stroke_styles_spec.rb +18 -36
  117. data/spec/table_spec.rb +111 -706
  118. data/spec/template_spec.rb +297 -0
  119. data/spec/text_at_spec.rb +33 -19
  120. data/spec/text_box_spec.rb +64 -100
  121. data/spec/text_rendering_mode_spec.rb +5 -5
  122. data/spec/text_spacing_spec.rb +4 -4
  123. data/spec/text_spec.rb +64 -84
  124. data/spec/transparency_spec.rb +5 -5
  125. metadata +290 -463
  126. checksums.yaml +0 -7
  127. data/.yardopts +0 -10
  128. data/Gemfile +0 -11
  129. data/data/images/16bit.color +0 -0
  130. data/data/images/dice.color +0 -0
  131. data/data/images/indexed_color.dat +0 -0
  132. data/data/images/indexed_color.png +0 -0
  133. data/data/images/page_white_text.color +0 -0
  134. data/lib/prawn/font_metric_cache.rb +0 -47
  135. data/lib/prawn/graphics/patterns.rb +0 -138
  136. data/lib/prawn/image_handler.rb +0 -36
  137. data/lib/prawn/soft_mask.rb +0 -96
  138. data/lib/prawn/table/cell/span_dummy.rb +0 -93
  139. data/lib/prawn/table/column_width_calculator.rb +0 -61
  140. data/lib/prawn/text/formatted/arranger.rb +0 -290
  141. data/lib/prawn/text/formatted/line_wrap.rb +0 -266
  142. data/lib/prawn/text/formatted/wrap.rb +0 -150
  143. data/lib/prawn/utilities.rb +0 -46
  144. data/manual/basic_concepts/adding_pages.rb +0 -27
  145. data/manual/basic_concepts/basic_concepts.rb +0 -34
  146. data/manual/basic_concepts/creation.rb +0 -39
  147. data/manual/basic_concepts/cursor.rb +0 -33
  148. data/manual/basic_concepts/measurement.rb +0 -25
  149. data/manual/basic_concepts/origin.rb +0 -38
  150. data/manual/basic_concepts/other_cursor_helpers.rb +0 -40
  151. data/manual/bounding_box/bounding_box.rb +0 -39
  152. data/manual/bounding_box/bounds.rb +0 -49
  153. data/manual/bounding_box/canvas.rb +0 -24
  154. data/manual/bounding_box/creation.rb +0 -23
  155. data/manual/bounding_box/indentation.rb +0 -46
  156. data/manual/bounding_box/nesting.rb +0 -45
  157. data/manual/bounding_box/russian_boxes.rb +0 -40
  158. data/manual/bounding_box/stretchy.rb +0 -31
  159. data/manual/document_and_page_options/background.rb +0 -27
  160. data/manual/document_and_page_options/document_and_page_options.rb +0 -32
  161. data/manual/document_and_page_options/metadata.rb +0 -23
  162. data/manual/document_and_page_options/page_margins.rb +0 -38
  163. data/manual/document_and_page_options/page_size.rb +0 -34
  164. data/manual/document_and_page_options/print_scaling.rb +0 -20
  165. data/manual/example_file.rb +0 -111
  166. data/manual/example_helper.rb +0 -411
  167. data/manual/example_package.rb +0 -53
  168. data/manual/example_section.rb +0 -46
  169. data/manual/graphics/circle_and_ellipse.rb +0 -22
  170. data/manual/graphics/color.rb +0 -24
  171. data/manual/graphics/common_lines.rb +0 -30
  172. data/manual/graphics/fill_and_stroke.rb +0 -42
  173. data/manual/graphics/fill_rules.rb +0 -37
  174. data/manual/graphics/gradients.rb +0 -37
  175. data/manual/graphics/graphics.rb +0 -58
  176. data/manual/graphics/helper.rb +0 -24
  177. data/manual/graphics/line_width.rb +0 -35
  178. data/manual/graphics/lines_and_curves.rb +0 -41
  179. data/manual/graphics/polygon.rb +0 -29
  180. data/manual/graphics/rectangle.rb +0 -21
  181. data/manual/graphics/rotate.rb +0 -28
  182. data/manual/graphics/scale.rb +0 -41
  183. data/manual/graphics/soft_masks.rb +0 -46
  184. data/manual/graphics/stroke_cap.rb +0 -31
  185. data/manual/graphics/stroke_dash.rb +0 -48
  186. data/manual/graphics/stroke_join.rb +0 -30
  187. data/manual/graphics/translate.rb +0 -29
  188. data/manual/graphics/transparency.rb +0 -35
  189. data/manual/images/absolute_position.rb +0 -23
  190. data/manual/images/fit.rb +0 -21
  191. data/manual/images/horizontal.rb +0 -25
  192. data/manual/images/images.rb +0 -40
  193. data/manual/images/plain_image.rb +0 -18
  194. data/manual/images/scale.rb +0 -22
  195. data/manual/images/vertical.rb +0 -28
  196. data/manual/images/width_and_height.rb +0 -25
  197. data/manual/layout/boxes.rb +0 -27
  198. data/manual/layout/content.rb +0 -25
  199. data/manual/layout/layout.rb +0 -28
  200. data/manual/layout/simple_grid.rb +0 -23
  201. data/manual/manual/cover.rb +0 -36
  202. data/manual/manual/foreword.rb +0 -85
  203. data/manual/manual/how_to_read_this_manual.rb +0 -41
  204. data/manual/manual/manual.rb +0 -34
  205. data/manual/outline/add_subsection_to.rb +0 -61
  206. data/manual/outline/insert_section_after.rb +0 -47
  207. data/manual/outline/outline.rb +0 -32
  208. data/manual/outline/sections_and_pages.rb +0 -67
  209. data/manual/repeatable_content/page_numbering.rb +0 -54
  210. data/manual/repeatable_content/repeatable_content.rb +0 -31
  211. data/manual/repeatable_content/repeater.rb +0 -55
  212. data/manual/repeatable_content/stamp.rb +0 -41
  213. data/manual/security/encryption.rb +0 -31
  214. data/manual/security/permissions.rb +0 -38
  215. data/manual/security/security.rb +0 -28
  216. data/manual/syntax_highlight.rb +0 -52
  217. data/manual/table/basic_block.rb +0 -53
  218. data/manual/table/before_rendering_page.rb +0 -26
  219. data/manual/table/cell_border_lines.rb +0 -24
  220. data/manual/table/cell_borders_and_bg.rb +0 -31
  221. data/manual/table/cell_dimensions.rb +0 -30
  222. data/manual/table/cell_text.rb +0 -38
  223. data/manual/table/column_widths.rb +0 -30
  224. data/manual/table/content_and_subtables.rb +0 -39
  225. data/manual/table/creation.rb +0 -27
  226. data/manual/table/filtering.rb +0 -36
  227. data/manual/table/flow_and_header.rb +0 -17
  228. data/manual/table/image_cells.rb +0 -33
  229. data/manual/table/position.rb +0 -29
  230. data/manual/table/row_colors.rb +0 -20
  231. data/manual/table/span.rb +0 -30
  232. data/manual/table/style.rb +0 -22
  233. data/manual/table/table.rb +0 -52
  234. data/manual/table/width.rb +0 -27
  235. data/manual/text/alignment.rb +0 -44
  236. data/manual/text/color.rb +0 -24
  237. data/manual/text/column_box.rb +0 -32
  238. data/manual/text/fallback_fonts.rb +0 -37
  239. data/manual/text/font.rb +0 -41
  240. data/manual/text/font_size.rb +0 -45
  241. data/manual/text/font_style.rb +0 -23
  242. data/manual/text/formatted_callbacks.rb +0 -60
  243. data/manual/text/formatted_text.rb +0 -54
  244. data/manual/text/free_flowing_text.rb +0 -51
  245. data/manual/text/group.rb +0 -31
  246. data/manual/text/inline.rb +0 -43
  247. data/manual/text/kerning_and_character_spacing.rb +0 -39
  248. data/manual/text/leading.rb +0 -25
  249. data/manual/text/line_wrapping.rb +0 -41
  250. data/manual/text/paragraph_indentation.rb +0 -26
  251. data/manual/text/positioned_text.rb +0 -38
  252. data/manual/text/registering_families.rb +0 -48
  253. data/manual/text/rendering_and_color.rb +0 -37
  254. data/manual/text/right_to_left_text.rb +0 -43
  255. data/manual/text/rotation.rb +0 -43
  256. data/manual/text/single_usage.rb +0 -37
  257. data/manual/text/text.rb +0 -75
  258. data/manual/text/text_box_excess.rb +0 -32
  259. data/manual/text/text_box_extensions.rb +0 -45
  260. data/manual/text/text_box_overflow.rb +0 -44
  261. data/manual/text/utf8.rb +0 -28
  262. data/manual/text/win_ansi_charset.rb +0 -59
  263. data/spec/acceptance/png.rb +0 -23
  264. data/spec/column_box_spec.rb +0 -65
  265. data/spec/extensions/encoding_helpers.rb +0 -9
  266. data/spec/font_metric_cache_spec.rb +0 -52
  267. data/spec/image_handler_spec.rb +0 -54
  268. data/spec/soft_mask_spec.rb +0 -117
  269. data/spec/table/span_dummy_spec.rb +0 -17
@@ -6,13 +6,10 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require_relative '../../prawn/encoding'
9
+ require 'prawn/encoding'
10
10
 
11
11
  module Prawn
12
12
  class Font
13
-
14
- # @private
15
-
16
13
  class AFM < Font
17
14
  BUILT_INS = %w[ Courier Helvetica Times-Roman Symbol ZapfDingbats
18
15
  Courier-Bold Courier-Oblique Courier-BoldOblique
@@ -30,8 +27,8 @@ module Prawn
30
27
  @metrics_path ||= [
31
28
  ".", "/usr/lib/afm",
32
29
  "/usr/local/lib/afm",
33
- "/usr/openwin/lib/fonts/afm",
34
- Prawn::DATADIR+'/fonts']
30
+ "/usr/openwin/lib/fonts/afm/",
31
+ Prawn::BASEDIR+'/data/fonts/']
35
32
  end
36
33
  end
37
34
 
@@ -44,20 +41,16 @@ module Prawn
44
41
 
45
42
  super
46
43
 
47
- @@winansi ||= Prawn::Encoding::WinAnsi.new # parse data/encodings/win_ansi.txt once only
48
- @@font_data ||= SynchronizedCache.new # parse each ATM font file once only
44
+ @attributes = {}
45
+ @glyph_widths = {}
46
+ @bounding_boxes = {}
47
+ @kern_pairs = {}
49
48
 
50
49
  file_name = @name.dup
51
50
  file_name << ".afm" unless file_name =~ /\.afm$/
52
51
  file_name = file_name[0] == ?/ ? file_name : find_font(file_name)
53
52
 
54
- font_data = @@font_data[file_name] ||= parse_afm(file_name)
55
- @glyph_widths = font_data[:glyph_widths]
56
- @glyph_table = font_data[:glyph_table]
57
- @bounding_boxes = font_data[:bounding_boxes]
58
- @kern_pairs = font_data[:kern_pairs]
59
- @kern_pair_table = font_data[:kern_pair_table]
60
- @attributes = font_data[:attributes]
53
+ parse_afm(file_name)
61
54
 
62
55
  @ascender = @attributes["ascender"].to_i
63
56
  @descender = @attributes["descender"].to_i
@@ -94,7 +87,7 @@ module Prawn
94
87
  # is replaced with a string in WinAnsi encoding.
95
88
  #
96
89
  def normalize_encoding(text)
97
- enc = @@winansi
90
+ enc = Prawn::Encoding::WinAnsi.new
98
91
  text.unpack("U*").collect { |i| enc[i] }.pack("C*")
99
92
  rescue ArgumentError
100
93
  raise Prawn::Errors::IncompatibleStringEncoding,
@@ -157,7 +150,6 @@ module Prawn
157
150
  end
158
151
 
159
152
  def parse_afm(file_name)
160
- data = {:glyph_widths => {}, :bounding_boxes => {}, :kern_pairs => {}, :attributes => {}}
161
153
  section = []
162
154
 
163
155
  File.foreach(file_name) do |line|
@@ -174,41 +166,27 @@ module Prawn
174
166
  when ["FontMetrics", "CharMetrics"]
175
167
  next unless line =~ /^CH?\s/
176
168
 
177
- name = line[/\bN\s+(\.?\w+)\s*;/, 1]
178
- data[:glyph_widths][name] = line[/\bWX\s+(\d+)\s*;/, 1].to_i
179
- data[:bounding_boxes][name] = line[/\bB\s+([^;]+);/, 1].to_s.rstrip
169
+ name = line[/\bN\s+(\.?\w+)\s*;/, 1]
170
+ @glyph_widths[name] = line[/\bWX\s+(\d+)\s*;/, 1].to_i
171
+ @bounding_boxes[name] = line[/\bB\s+([^;]+);/, 1].to_s.rstrip
180
172
  when ["FontMetrics", "KernData", "KernPairs"]
181
173
  next unless line =~ /^KPX\s+(\.?\w+)\s+(\.?\w+)\s+(-?\d+)/
182
- data[:kern_pairs][[$1, $2]] = $3.to_i
174
+ @kern_pairs[[$1, $2]] = $3.to_i
183
175
  when ["FontMetrics", "KernData", "TrackKern"],
184
176
  ["FontMetrics", "Composites"]
185
177
  next
186
178
  else
187
- parse_generic_afm_attribute(line, data)
179
+ parse_generic_afm_attribute(line)
188
180
  end
189
181
  end
190
-
191
- # process data parsed from AFM file to build tables which
192
- # will be used when measuring and kerning text
193
- data[:glyph_table] = (0..255).map do |i|
194
- data[:glyph_widths][Encoding::WinAnsi::CHARACTERS[i]].to_i
195
- end
196
-
197
- character_hash = Hash[Encoding::WinAnsi::CHARACTERS.zip((0..Encoding::WinAnsi::CHARACTERS.size).to_a)]
198
- data[:kern_pair_table] = data[:kern_pairs].inject({}) do |h,p|
199
- h[p[0].map { |n| character_hash[n] }] = p[1]
200
- h
201
- end
202
-
203
- data.each_value { |hash| hash.freeze }
204
- data.freeze
205
182
  end
206
183
 
207
- def parse_generic_afm_attribute(line, hash)
184
+ def parse_generic_afm_attribute(line)
208
185
  line =~ /(^\w+)\s+(.*)/
209
186
  key, value = $1.to_s.downcase, $2
210
187
 
211
- hash[:attributes][key] = hash[:attributes][key] ? Array(hash[:attributes][key]) << value : value
188
+ @attributes[key] = @attributes[key] ?
189
+ Array(@attributes[key]) << value : value
212
190
  end
213
191
 
214
192
  # converts a string into an array with spacing offsets
@@ -220,26 +198,46 @@ module Prawn
220
198
  kerned = [[]]
221
199
  last_byte = nil
222
200
 
223
- string.each_byte do |byte|
224
- if k = last_byte && @kern_pair_table[[last_byte, byte]]
201
+ kern_pairs = latin_kern_pairs_table
202
+
203
+ string.unpack("C*").each do |byte|
204
+ if k = last_byte && kern_pairs[[last_byte, byte]]
225
205
  kerned << -k << [byte]
226
206
  else
227
207
  kerned.last << byte
228
- end
208
+ end
229
209
  last_byte = byte
230
210
  end
231
211
 
232
- kerned.map { |e|
212
+ kerned.map { |e|
233
213
  e = (Array === e ? e.pack("C*") : e)
234
- e.respond_to?(:force_encoding) ? e.force_encoding(::Encoding::Windows_1252) : e
214
+ e.respond_to?(:force_encoding) ? e.force_encoding("Windows-1252") : e
235
215
  }
236
216
  end
217
+
218
+ def latin_kern_pairs_table
219
+ return @kern_pairs_table if defined?(@kern_pairs_table)
220
+
221
+ character_hash = Hash[Encoding::WinAnsi::CHARACTERS.zip((0..Encoding::WinAnsi::CHARACTERS.size).to_a)]
222
+ @kern_pairs_table = @kern_pairs.inject({}) do |h,p|
223
+ h[p[0].map { |n| character_hash[n] }] = p[1]
224
+ h
225
+ end
226
+ end
227
+
228
+ def latin_glyphs_table
229
+ @glyphs_table ||= (0..255).map do |i|
230
+ @glyph_widths[Encoding::WinAnsi::CHARACTERS[i]].to_i
231
+ end
232
+ end
237
233
 
238
234
  private
239
235
 
240
236
  def unscaled_width_of(string)
241
- string.bytes.inject(0) do |s,r|
242
- s + @glyph_table[r]
237
+ glyph_table = latin_glyphs_table
238
+
239
+ string.unpack("C*").inject(0) do |s,r|
240
+ s + glyph_table[r]
243
241
  end
244
242
  end
245
243
  end
@@ -6,13 +6,12 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  #
9
- require_relative 'ttf'
9
+ require 'prawn/font/ttf'
10
10
 
11
11
  module Prawn
12
12
  class Font
13
- # @private
14
13
  class DFont < TTF
15
-
14
+
16
15
  # Returns a list of the names of all named fonts in the given dfont file.
17
16
  # Note that fonts are not required to be named in a dfont file, so the
18
17
  # list may be empty even if the file does contain fonts. Also, note that
@@ -33,7 +32,7 @@ module Prawn
33
32
  end
34
33
  end
35
34
 
36
- private
35
+ private
37
36
 
38
37
  def read_ttf_file
39
38
  TTFunk::File.from_dfont(@name, @options[:font] || 0)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # prawn/font/ttf.rb : Implements AFM font support for Prawn
4
4
  #
5
- # Copyright May 2008, Gregory Brown / James Healy / Jamis Buck
5
+ # Copyright May 2008, Gregory Brown / James Healy / Jamis Buck
6
6
  # All Rights Reserved.
7
7
  #
8
8
  # This is free software. Please see the LICENSE and COPYING files for details.
@@ -12,15 +12,13 @@ require 'ttfunk/subset_collection'
12
12
 
13
13
  module Prawn
14
14
  class Font
15
-
16
- # @private
17
15
  class TTF < Font
18
16
  attr_reader :ttf, :subsets
19
17
 
20
18
  def unicode?
21
19
  true
22
20
  end
23
-
21
+
24
22
  def initialize(document, name, options={})
25
23
  super
26
24
 
@@ -28,8 +26,8 @@ module Prawn
28
26
  @subsets = TTFunk::SubsetCollection.new(@ttf)
29
27
 
30
28
  @attributes = {}
31
- @bounding_boxes = {}
32
- @char_widths = {}
29
+ @bounding_boxes = {}
30
+ @char_widths = {}
33
31
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
34
32
 
35
33
  @ascender = Integer(@ttf.ascent * scale_factor)
@@ -44,26 +42,26 @@ module Prawn
44
42
  kern(string).inject(0) do |s,r|
45
43
  if r.is_a?(Numeric)
46
44
  s - r
47
- else
45
+ else
48
46
  r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
49
47
  end
50
48
  end * scale
51
49
  else
52
- string.codepoints.inject(0) do |s,r|
50
+ string.unpack("U*").inject(0) do |s,r|
53
51
  s + character_width_by_code(r)
54
52
  end * scale
55
53
  end
56
- end
57
-
54
+ end
55
+
58
56
  # The font bbox, as an array of integers
59
- #
57
+ #
60
58
  def bbox
61
59
  @bbox ||= @ttf.bbox.map { |i| Integer(i * scale_factor) }
62
60
  end
63
61
 
64
62
  # Returns true if the font has kerning data, false otherwise
65
63
  def has_kerning_data?
66
- @has_kerning_data
64
+ @has_kerning_data
67
65
  end
68
66
 
69
67
  # Perform any changes to the string that need to happen
@@ -79,7 +77,7 @@ module Prawn
79
77
 
80
78
  if options[:kerning]
81
79
  last_subset = nil
82
- kern(text).inject([]) do |result, element|
80
+ kern(text).inject([]) do |result, element|
83
81
  if element.is_a?(Numeric)
84
82
  result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
85
83
  result.last[1] << element
@@ -104,7 +102,7 @@ module Prawn
104
102
  @subsets.encode(text.unpack("U*"))
105
103
  end
106
104
  end
107
-
105
+
108
106
  def basename
109
107
  @basename ||= @ttf.name.postscript_name
110
108
  end
@@ -162,26 +160,44 @@ module Prawn
162
160
  end
163
161
 
164
162
  def normalize_encoding(text)
165
- begin
166
- text.encode(::Encoding::UTF_8)
167
- rescue => e
168
- puts e
169
- raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
163
+ if text.respond_to?(:encode)
164
+ # if we're running under a M17n aware VM, ensure the string provided is
165
+ # UTF-8 (by converting it if necessary)
166
+ begin
167
+ text.encode("UTF-8")
168
+ rescue
169
+ raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
170
170
  "#{text.encoding} can not be transparently converted to UTF-8. " +
171
171
  "Please ensure the encoding of the string you are attempting " +
172
172
  "to use is set correctly"
173
+ end
174
+ else
175
+ # on a non M17N aware VM, use unpack as a hackish way to verify the
176
+ # string is valid utf-8. I thought it was better than loading iconv
177
+ # though.
178
+ begin
179
+ text.unpack("U*")
180
+ return text.dup
181
+ rescue
182
+ raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
183
+ "are attempting to render is not encoded in valid UTF-8."
184
+ end
173
185
  end
174
186
  end
175
187
 
176
188
  def glyph_present?(char)
177
- code = char.codepoints.first
189
+ code = char.unpack("U*").first
178
190
  cmap[code] > 0
179
191
  end
180
192
 
181
193
  # Returns the number of characters in +str+ (a UTF-8-encoded string).
182
194
  #
183
195
  def character_count(str)
184
- str.length
196
+ if str.respond_to?(:encode)
197
+ str.length
198
+ else
199
+ str.unpack("U*").length
200
+ end
185
201
  end
186
202
 
187
203
  private
@@ -189,7 +205,7 @@ module Prawn
189
205
  def cmap
190
206
  @cmap ||= @ttf.cmap.unicode.first or raise("no unicode cmap for font")
191
207
  end
192
-
208
+
193
209
  # +string+ must be UTF8-encoded.
194
210
  #
195
211
  # Returns an array. If an element is a numeric, it represents the
@@ -198,7 +214,7 @@ module Prawn
198
214
  def kern(string)
199
215
  a = []
200
216
 
201
- string.each_codepoint do |r|
217
+ string.unpack("U*").each do |r|
202
218
  if a.empty?
203
219
  a << [r]
204
220
  elsif (kern = kern_pairs_table[[cmap[a.last.last], cmap[r]]])
@@ -225,7 +241,7 @@ module Prawn
225
241
  @hmtx ||= @ttf.horizontal_metrics
226
242
  end
227
243
 
228
- def character_width_by_code(code)
244
+ def character_width_by_code(code)
229
245
  return 0 unless cmap[code]
230
246
 
231
247
  # Some TTF fonts have nonzero widths for \n (UTF-8 / ASCII code: 10).
@@ -233,7 +249,7 @@ module Prawn
233
249
  return 0.0 if code == 10
234
250
 
235
251
  @char_widths[code] ||= Integer(hmtx.widths[cmap[code]] * scale_factor)
236
- end
252
+ end
237
253
 
238
254
  def scale_factor
239
255
  @scale ||= 1000.0 / @ttf.header.units_per_em
@@ -243,7 +259,7 @@ module Prawn
243
259
  temp_name = @ttf.name.postscript_name.gsub("\0","").to_sym
244
260
  ref = @document.ref!(:Type => :Font, :BaseFont => temp_name)
245
261
 
246
- # Embed the font metrics in the document after everything has been
262
+ # Embed the font metrics in the document after everything has been
247
263
  # drawn, just before the document is emitted.
248
264
  @document.before_render { |doc| embed(ref, subset) }
249
265
 
@@ -264,9 +280,12 @@ module Prawn
264
280
 
265
281
  raise "Can't detect a postscript name for #{file}" if basename.nil?
266
282
 
267
- fontfile = @document.ref!(:Length1 => font_content.size)
268
- fontfile.stream << font_content
269
- fontfile.stream.compress!
283
+ compressed_font = Zlib::Deflate.deflate(font_content)
284
+
285
+ fontfile = @document.ref!(:Length => compressed_font.size,
286
+ :Length1 => font_content.size,
287
+ :Filter => :FlateDecode )
288
+ fontfile << compressed_font
270
289
 
271
290
  descriptor = @document.ref!(:Type => :FontDescriptor,
272
291
  :FontName => basename.to_sym,
@@ -297,7 +316,7 @@ module Prawn
297
316
  map = @subsets[subset].to_unicode_map
298
317
 
299
318
  ranges = [[]]
300
- map.keys.sort.inject("") do |s, code|
319
+ lines = map.keys.sort.inject("") do |s, code|
301
320
  ranges << [] if ranges.last.length >= 100
302
321
  unicode = map[code]
303
322
  ranges.last << "<%02x><%04x>" % [code, unicode]
@@ -311,7 +330,7 @@ module Prawn
311
330
 
312
331
  cmap = @document.ref!({})
313
332
  cmap << to_unicode_cmap
314
- cmap.stream.compress!
333
+ cmap.compress_stream
315
334
 
316
335
  reference.data.update(:Subtype => :TrueType,
317
336
  :BaseFont => basename.to_sym,
@@ -6,14 +6,13 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
-
10
- require_relative "graphics/color"
11
- require_relative "graphics/dash"
12
- require_relative "graphics/cap_style"
13
- require_relative "graphics/join_style"
14
- require_relative "graphics/transparency"
15
- require_relative "graphics/transformation"
16
- require_relative "graphics/patterns"
9
+ require "prawn/graphics/color"
10
+ require "prawn/graphics/dash"
11
+ require "prawn/graphics/cap_style"
12
+ require "prawn/graphics/join_style"
13
+ require "prawn/graphics/transparency"
14
+ require "prawn/graphics/transformation"
15
+ require "prawn/graphics/gradient"
17
16
 
18
17
  module Prawn
19
18
 
@@ -31,9 +30,7 @@ module Prawn
31
30
  include JoinStyle
32
31
  include Transparency
33
32
  include Transformation
34
- include Patterns
35
-
36
- # @group Stable API
33
+ include Gradient
37
34
 
38
35
  #######################################################################
39
36
  # Low level drawing operations must map the point to absolute coords! #
@@ -85,9 +82,9 @@ module Prawn
85
82
  x,y = map_to_absolute(point)
86
83
  add_content("%.3f %.3f %.3f %.3f re" % [ x, y - height, width, height ])
87
84
  end
88
-
85
+
89
86
  # Draws a rounded rectangle given <tt>point</tt>, <tt>width</tt> and
90
- # <tt>height</tt> and <tt>radius</tt> for the rounded corner. The rectangle
87
+ # <tt>height</tt> and <tt>radius</tt> for the rounded corner. The rectangle
91
88
  # is bounded by its upper-left corner.
92
89
  #
93
90
  # pdf.rounded_rectangle [300,300], 100, 200, 10
@@ -96,7 +93,7 @@ module Prawn
96
93
  x, y = point
97
94
  rounded_polygon(radius, point, [x + width, y], [x + width, y - height], [x, y - height])
98
95
  end
99
-
96
+
100
97
 
101
98
  ###########################################################
102
99
  # Higher level functions: May use relative coords #
@@ -141,7 +138,7 @@ module Prawn
141
138
  # current <tt>y</tt> position, or the position specified by the :at option.
142
139
  #
143
140
  # # draw a line from [25, 75] to [100, 75]
144
- # horizontal_line 25, 100, :at => 75
141
+ # horizontal_line 25, 100, :at => 75
145
142
  #
146
143
  def horizontal_line(x1,x2,options={})
147
144
  if options[:at]
@@ -149,7 +146,7 @@ module Prawn
149
146
  else
150
147
  y1 = y - bounds.absolute_bottom
151
148
  end
152
-
149
+
153
150
  line(x1,y1,x2,y1)
154
151
  end
155
152
 
@@ -184,6 +181,13 @@ module Prawn
184
181
  #
185
182
  KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
186
183
 
184
+ # <b>DEPRECATED:</b> Please use <tt>circle</tt> instead.
185
+ def circle_at(point, options)
186
+ warn "[DEPRECATION] 'circle_at' is deprecated in favor of 'circle'. " +
187
+ "'circle_at' will be removed in release 1.1"
188
+ circle(point, options[:radius])
189
+ end
190
+
187
191
  # Draws a circle of radius <tt>radius</tt> with the centre-point at <tt>point</tt>
188
192
  # as a complete subpath. The drawing point will be moved to the
189
193
  # centre-point upon completion of the drawing the circle.
@@ -194,6 +198,13 @@ module Prawn
194
198
  ellipse(center, radius, radius)
195
199
  end
196
200
 
201
+ # <b>DEPRECATED:</b> Please use <tt>ellipse</tt> instead.
202
+ def ellipse_at(point, r1, r2=r1)
203
+ warn "[DEPRECATION] 'ellipse_at' is deprecated in favor of 'ellipse'. " +
204
+ "'ellipse_at' will be removed in release 1.1"
205
+ ellipse(point, r1, r2)
206
+ end
207
+
197
208
  # Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
198
209
  # with the centre-point at <tt>point</tt> as a complete subpath. The
199
210
  # drawing point will be moved to the centre-point upon completion of the
@@ -211,19 +222,19 @@ module Prawn
211
222
 
212
223
  # Upper right hand corner
213
224
  curve_to [x, y + r2],
214
- :bounds => [[x + r1, y + l2], [x + l1, y + r2]]
225
+ :bounds => [[x + r1, y + l1], [x + l2, y + r2]]
215
226
 
216
227
  # Upper left hand corner
217
228
  curve_to [x - r1, y],
218
- :bounds => [[x - l1, y + r2], [x - r1, y + l2]]
229
+ :bounds => [[x - l2, y + r2], [x - r1, y + l1]]
219
230
 
220
231
  # Lower left hand corner
221
232
  curve_to [x, y - r2],
222
- :bounds => [[x - r1, y - l2], [x - l1, y - r2]]
233
+ :bounds => [[x - r1, y - l1], [x - l2, y - r2]]
223
234
 
224
235
  # Lower right hand corner
225
236
  curve_to [x + r1, y],
226
- :bounds => [[x + l1, y - r2], [x + r1, y - l2]]
237
+ :bounds => [[x + l2, y - r2], [x + r1, y - l1]]
227
238
 
228
239
  move_to(x, y)
229
240
  end
@@ -241,7 +252,7 @@ module Prawn
241
252
  # close the path
242
253
  add_content "h"
243
254
  end
244
-
255
+
245
256
  # Draws a rounded polygon from specified points using the radius to define bezier curves
246
257
  #
247
258
  # # draws a rounded filled in polygon
@@ -257,19 +268,20 @@ module Prawn
257
268
  # close the path
258
269
  add_content "h"
259
270
  end
260
-
261
-
271
+
272
+
262
273
  # Creates a rounded vertex for a line segment used for building a rounded polygon
263
274
  # requires a radius to define bezier curve and three points. The first two points define
264
275
  # the line segment and the third point helps define the curve for the vertex.
265
276
  def rounded_vertex(radius, *points)
277
+ x0,y0,x1,y1,x2,y2 = points.flatten
266
278
  radial_point_1 = point_on_line(radius, points[0], points[1])
267
279
  bezier_point_1 = point_on_line((radius - radius*KAPPA), points[0], points[1] )
268
280
  radial_point_2 = point_on_line(radius, points[2], points[1])
269
281
  bezier_point_2 = point_on_line((radius - radius*KAPPA), points[2], points[1])
270
282
  line_to(radial_point_1)
271
283
  curve_to(radial_point_2, :bounds => [bezier_point_1, bezier_point_2])
272
- end
284
+ end
273
285
 
274
286
  # Strokes the current path. If a block is provided, yields to the block
275
287
  # before closing the path. See Graphics::Color for color details.
@@ -286,75 +298,13 @@ module Prawn
286
298
  yield if block_given?
287
299
  add_content "s"
288
300
  end
289
-
301
+
290
302
  # Draws and strokes a rectangle represented by the current bounding box
291
303
  #
292
304
  def stroke_bounds
293
305
  stroke_rectangle bounds.top_left, bounds.width, bounds.height
294
306
  end
295
307
 
296
- # Draws and strokes X and Y axes rulers beginning at the current bounding
297
- # box origin (or at a custom location).
298
- #
299
- # == Options
300
- #
301
- # +:at+::
302
- # Origin of the X and Y axes (default: [0, 0] = origin of the bounding
303
- # box)
304
- #
305
- # +:width+::
306
- # Length of the X axis (default: width of the bounding box)
307
- #
308
- # +:height+::
309
- # Length of the Y axis (default: height of the bounding box)
310
- #
311
- # +:step_length+::
312
- # Length of the step between markers (default: 100)
313
- #
314
- # +:negative_axes_length+::
315
- # Length of the negative parts of the axes (default: 20)
316
- #
317
- # +:color+:
318
- # The color of the axes and the text.
319
- #
320
- def stroke_axis(options = {})
321
- options = {
322
- :at => [0,0],
323
- :height => bounds.height.to_i - (options[:at] || [0,0])[1],
324
- :width => bounds.width.to_i - (options[:at] || [0,0])[0],
325
- :step_length => 100,
326
- :negative_axes_length => 20,
327
- :color => "000000",
328
- }.merge(options)
329
-
330
- Prawn.verify_options([:at, :width, :height, :step_length,
331
- :negative_axes_length, :color], options)
332
-
333
- save_graphics_state do
334
- fill_color(options[:color])
335
- stroke_color(options[:color])
336
-
337
- dash(1, :space => 4)
338
- stroke_horizontal_line(options[:at][0] - options[:negative_axes_length],
339
- options[:at][0] + options[:width], :at => options[:at][1])
340
- stroke_vertical_line(options[:at][1] - options[:negative_axes_length],
341
- options[:at][1] + options[:height], :at => options[:at][0])
342
- undash
343
-
344
- fill_circle(options[:at], 1)
345
-
346
- (options[:step_length]..options[:width]).step(options[:step_length]) do |point|
347
- fill_circle([options[:at][0] + point, options[:at][1]], 1)
348
- draw_text(point, :at => [options[:at][0] + point - 5, options[:at][1] - 10], :size => 7)
349
- end
350
-
351
- (options[:step_length]..options[:height]).step(options[:step_length]) do |point|
352
- fill_circle([options[:at][0], options[:at][1] + point], 1)
353
- draw_text(point, :at => [options[:at][0] - 17, options[:at][1] + point - 2], :size => 7)
354
- end
355
- end
356
- end
357
-
358
308
  # Closes and fills the current path. See Graphics::Color for color details.
359
309
  #
360
310
  # If the option :fill_rule => :even_odd is specified, Prawn will use the
@@ -387,230 +337,35 @@ module Prawn
387
337
  add_content "h"
388
338
  end
389
339
 
390
- ##
391
- # :method: stroke_rectangle
392
- #
393
- # Draws and strokes a rectangle given +point+, +width+ and +height+. The
394
- # rectangle is bounded by its upper-left corner.
395
- #
396
- # :call-seq:
397
- # stroke_rectangle(point,width,height)
398
-
399
- ##
400
- # :method: fill_rectangle
401
- #
402
- # Draws and fills ills a rectangle given +point+, +width+ and +height+. The
403
- # rectangle is bounded by its upper-left corner.
404
- #
405
- # :call-seq:
406
- # fill_rectangle(point,width,height)
407
-
408
- ##
409
- # :method: fill_and_stroke_rectangle
410
- #
411
- # Draws, fills, and strokes a rectangle given +point+, +width+ and +height+.
412
- # The rectangle is bounded by its upper-left corner.
413
- #
414
- # :call-seq:
415
- # fill_and_stroke_rectangle(point,width,height)
416
-
417
- ##
418
- # :method: stroke_rounded_rectangle
419
- #
420
- # Draws and strokes a rounded rectangle given +point+, +width+ and +height+
421
- # and +radius+ for the rounded corner. The rectangle is bounded by its
422
- # upper-left corner.
423
- #
424
- # :call-seq:
425
- # stroke_rounded_rectangle(point,width,height,radius)
426
-
427
- ##
428
- # :method: fill_rounded_rectangle
429
- #
430
- # Draws and fills a rounded rectangle given +point+, +width+ and +height+
431
- # and +radius+ for the rounded corner. The rectangle is bounded by its
432
- # upper-left corner.
433
- #
434
- # :call-seq:
435
- # fill_rounded_rectangle(point,width,height,radius)
436
-
437
- ##
438
- # :method: stroke_and_fill_rounded_rectangle
439
- #
440
- # Draws, fills, and strokes a rounded rectangle given +point+, +width+ and
441
- # +height+ and +radius+ for the rounded corner. The rectangle is bounded by
442
- # its upper-left corner.
443
- #
444
- # :call-seq:
445
- # stroke_and_fill_rounded_rectangle(point,width,height,radius)
446
-
447
- ##
448
- # :method: stroke_line
449
- #
450
- # Strokes a line from one point to another. Points may be specified as
451
- # tuples or flattened argument list.
452
- #
453
- # :call-seq:
454
- # stroke_line(*points)
455
-
456
- ##
457
- # :method: stroke_horizontal_line
458
- #
459
- # Strokes a horizontal line from +x1+ to +x2+ at the current y position, or
460
- # the position specified by the :at option.
461
- #
462
- # :call-seq:
463
- # stroke_horizontal_line(x1,x2,options={})
464
-
465
- ##
466
- # :method: stroke_horizontal_rule
467
- #
468
- # Strokes a horizontal line from the left border to the right border of the
469
- # bounding box at the current y position.
470
- #
471
- # :call-seq:
472
- # stroke_horizontal_rule
473
-
474
- ##
475
- # :method: stroke_vertical_line
476
- #
477
- # Strokes a vertical line at the x coordinate given by :at from y1 to y2.
478
- #
479
- # :call-seq:
480
- # stroke_vertical_line(y1,y2,params)
481
-
482
- ##
483
- # :method: stroke_curve
484
- #
485
- # Strokes a Bezier curve between two points, bounded by two additional
486
- # points.
487
- #
488
- # :call-seq:
489
- # stroke_curve(origin,dest,options={})
490
-
491
- ##
492
- # :method: stroke_circle
493
- #
494
- # Draws and strokes a circle of radius +radius+ with the centre-point at
495
- # +point+.
496
- #
497
- # :call-seq:
498
- # stroke_circle(center,radius)
499
-
500
- ##
501
- # :method: fill_circle
340
+ # Provides the following shortcuts:
502
341
  #
503
- # Draws and fills a circle of radius +radius+ with the centre-point at
504
- # +point+.
342
+ # stroke_some_method(*args) #=> some_method(*args); stroke
343
+ # fill_some_method(*args) #=> some_method(*args); fill
344
+ # fill_and_stroke_some_method(*args) #=> some_method(*args); fill_and_stroke
505
345
  #
506
- # :call-seq:
507
- # fill_circle(center,radius)
508
-
509
- ##
510
- # :method: fill_and_stroke_circle
511
- #
512
- # Draws, strokes, and fills a circle of radius +radius+ with the
513
- # centre-point at +point+.
514
- #
515
- # :call-seq:
516
- # fill_and_stroke_circle(center,radius)
517
-
518
- ##
519
- # :method: stroke_ellipse
520
- #
521
- # Draws and strokes an ellipse of x radius +r1+ and y radius +r2+ with the
522
- # centre-point at +point+.
523
- #
524
- # :call-seq:
525
- # stroke_ellipse(point, r1, r2 = r1)
526
-
527
- ##
528
- # :method: fill_ellipse
529
- #
530
- # Draws and fills an ellipse of x radius +r1+ and y radius +r2+ with the
531
- # centre-point at +point+.
532
- #
533
- # :call-seq:
534
- # fill_ellipse(point, r1, r2 = r1)
535
-
536
- ##
537
- # :method: fill_and_stroke_ellipse
538
- #
539
- # Draws, strokes, and fills an ellipse of x radius +r1+ and y radius +r2+
540
- # with the centre-point at +point+.
541
- #
542
- # :call-seq:
543
- # fill_and_stroke_ellipse(point, r1, r2 = r1)
544
-
545
- ##
546
- # :method: stroke_polygon
547
- #
548
- # Draws and strokes a polygon from the specified points.
549
- #
550
- # :call-seq:
551
- # stroke_polygon(*points)
552
-
553
- ##
554
- # :method: fill_polygon
555
- #
556
- # Draws and fills a polygon from the specified points.
557
- #
558
- # :call-seq:
559
- # fill_polygon(*points)
560
-
561
- ##
562
- # :method: fill_and_stroke_polygon
563
- #
564
- # Draws, strokes, and fills a polygon from the specified points.
565
- #
566
- # :call-seq:
567
- # fill_and_stroke_polygon(*points)
568
-
569
- ##
570
- # :method: stroke_rounded_polygon
571
- #
572
- # Draws and strokes a rounded polygon from specified points, using +radius+
573
- # to define Bezier curves.
574
- #
575
- # :call-seq:
576
- # stroke_rounded_polygon(radius, *points)
577
-
578
- ##
579
- # :method: fill_rounded_polygon
580
- #
581
- # Draws and fills a rounded polygon from specified points, using +radius+ to
582
- # define Bezier curves.
583
- #
584
- # :call-seq:
585
- # fill_rounded_polygon(radius, *points)
586
-
587
- ##
588
- # :method: fill_and_stroke_rounded_polygon
589
- #
590
- # Draws, strokes, and fills a rounded polygon from specified points, using
591
- # +radius+ to define Bezier curves.
592
- #
593
- # :call-seq:
594
- # fill_and_stroke_rounded_polygon(radius, *points)
595
-
596
- ops = %w{fill stroke fill_and_stroke}
597
- shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
598
- curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
599
-
600
- ops.product(shapes).each do |operation,shape|
601
- class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
346
+ def method_missing(id,*args,&block)
347
+ case(id.to_s)
348
+ when /^fill_and_stroke_(.*)/
349
+ send($1,*args,&block); fill_and_stroke
350
+ when /^stroke_(.*)/
351
+ send($1,*args,&block); stroke
352
+ when /^fill_(.*)/
353
+ send($1,*args,&block); fill
354
+ else
355
+ super
356
+ end
602
357
  end
603
358
 
604
359
  private
605
-
360
+
606
361
  def current_line_width
607
362
  graphic_state.line_width
608
363
  end
609
-
364
+
610
365
  def current_line_width=(width)
611
366
  graphic_state.line_width = width
612
367
  end
613
-
368
+
614
369
  def write_line_width
615
370
  add_content("#{current_line_width} w")
616
371
  end
@@ -627,7 +382,7 @@ module Prawn
627
382
  def degree_to_rad(angle)
628
383
  angle * Math::PI / 180
629
384
  end
630
-
385
+
631
386
  # Returns the coordinates for a point on a line that is a given distance away from the second
632
387
  # point defining the line segement
633
388
  def point_on_line(distance_from_end, *points)
@@ -638,6 +393,6 @@ module Prawn
638
393
  yr = y0 + p*(y1 - y0)
639
394
  [xr, yr]
640
395
  end
641
-
396
+
642
397
  end
643
398
  end