prawn 0.1.2 → 0.2.0

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 (53) hide show
  1. data/README +16 -2
  2. data/Rakefile +3 -3
  3. data/data/images/arrow.png +0 -0
  4. data/data/images/arrow2.png +0 -0
  5. data/data/images/barcode_issue.png +0 -0
  6. data/data/images/ruport_type0.png +0 -0
  7. data/examples/cell.rb +14 -3
  8. data/examples/chinese_text_wrapping.rb +17 -0
  9. data/examples/family_based_styling.rb +21 -0
  10. data/examples/fancy_table.rb +4 -4
  11. data/examples/flowing_text_with_header_and_footer.rb +72 -0
  12. data/examples/font_size.rb +2 -2
  13. data/examples/lazy_bounding_boxes.rb +19 -0
  14. data/examples/table.rb +13 -11
  15. data/examples/text_flow.rb +1 -1
  16. data/lib/prawn.rb +44 -15
  17. data/lib/prawn/compatibility.rb +20 -7
  18. data/lib/prawn/document.rb +72 -122
  19. data/lib/prawn/document/bounding_box.rb +124 -24
  20. data/lib/prawn/document/internals.rb +107 -0
  21. data/lib/prawn/document/table.rb +99 -70
  22. data/lib/prawn/document/text.rb +92 -314
  23. data/lib/prawn/errors.rb +13 -2
  24. data/lib/prawn/font.rb +312 -1
  25. data/lib/prawn/font/cmap.rb +1 -1
  26. data/lib/prawn/font/metrics.rb +52 -49
  27. data/lib/prawn/font/wrapping.rb +14 -12
  28. data/lib/prawn/graphics.rb +23 -74
  29. data/lib/prawn/graphics/cell.rb +30 -25
  30. data/lib/prawn/graphics/color.rb +132 -0
  31. data/lib/prawn/images.rb +37 -16
  32. data/lib/prawn/images/png.rb +29 -24
  33. data/lib/prawn/pdf_object.rb +3 -1
  34. data/spec/bounding_box_spec.rb +12 -3
  35. data/spec/document_spec.rb +40 -72
  36. data/spec/font_spec.rb +97 -0
  37. data/spec/graphics_spec.rb +46 -99
  38. data/spec/images_spec.rb +4 -21
  39. data/spec/pdf_object_spec.rb +8 -8
  40. data/spec/png_spec.rb +47 -12
  41. data/spec/spec_helper.rb +5 -24
  42. data/spec/table_spec.rb +53 -59
  43. data/spec/text_spec.rb +28 -93
  44. data/vendor/pdf-inspector/README +18 -0
  45. data/vendor/pdf-inspector/lib/pdf/inspector.rb +25 -0
  46. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +80 -0
  47. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +16 -0
  48. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +31 -0
  49. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  50. metadata +63 -38
  51. data/examples/on_page_start.rb +0 -17
  52. data/examples/table_bench.rb +0 -92
  53. data/spec/box_calculation_spec.rb +0 -17
@@ -6,40 +6,42 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  module Prawn
9
- module Font #:nodoc:
10
- module Wrapping #:nodoc:
9
+ class Font #:nodoc:
10
+ module Wrapping #:nodoc:
11
+ ruby_18 { $KCODE="U" }
11
12
 
12
13
  # TODO: Replace with TeX optimal algorithm
13
14
  def naive_wrap(string, line_width, font_size, options = {})
14
- output = ""
15
- string.lines.each do |line|
16
- accumulated_width = 0
17
- segments = line.scan(/\S+|\s+/)
15
+ accumulated_width = 0
16
+ scan_pattern = options[:mode] == :character ? /./ : /\S+|\s+/
17
+
18
+ output = ""
19
+ string.lines.each do |line|
20
+ segments = line.scan(scan_pattern)
18
21
 
19
22
  segments.each do |segment|
20
23
  segment_width = string_width(segment, font_size,
21
24
  :kerning => options[:kerning])
22
25
 
23
26
  if (accumulated_width + segment_width).round > line_width.round
24
- output << "\n"
27
+ output = "#{output.rstrip}\n"
25
28
 
26
- if segment =~ /\s/
29
+ if segment =~ /\s/
27
30
  accumulated_width = 0
28
31
  else
29
32
  output << segment
30
33
  accumulated_width = segment_width
31
34
  end
32
- else
35
+ else
33
36
  output << segment
34
37
  accumulated_width += segment_width
35
38
  end
36
- end
39
+ end
37
40
  end
38
41
 
39
42
  output
40
43
  end
41
44
 
42
- end
43
-
45
+ end
44
46
  end
45
47
  end
@@ -7,7 +7,8 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
9
  require "enumerator"
10
- require "prawn/graphics/cell"
10
+ require "prawn/graphics/cell"
11
+ require "prawn/graphics/color"
11
12
 
12
13
  module Prawn
13
14
 
@@ -17,9 +18,10 @@ module Prawn
17
18
  # This file lifts and modifies several of PDF::Writer's graphics functions
18
19
  # ruby-pdf.rubyforge.org
19
20
  #
20
- module Graphics
21
-
22
-
21
+ module Graphics
22
+
23
+ include Color
24
+
23
25
  #######################################################################
24
26
  # Low level drawing operations must translate to absolute coords! #
25
27
  #######################################################################
@@ -84,8 +86,12 @@ module Prawn
84
86
 
85
87
  # The current line thickness
86
88
  #
87
- def line_width
88
- @line_width || 1
89
+ def line_width(width=nil)
90
+ if width
91
+ self.line_width = width
92
+ else
93
+ @line_width || 1
94
+ end
89
95
  end
90
96
 
91
97
  # Draws a line from one point to another. Points may be specified as
@@ -104,7 +110,7 @@ module Prawn
104
110
  # current <tt>y</tt> position.
105
111
  #
106
112
  def horizontal_line(x1,x2)
107
- line(x1,y,x2,y)
113
+ line(x1,y-bounds.absolute_bottom,x2,y-bounds.absolute_bottom)
108
114
  end
109
115
 
110
116
  # Draws a horizontal line from the left border to the right border of the
@@ -191,95 +197,38 @@ module Prawn
191
197
  line_to(*p2)
192
198
  end
193
199
  end
194
-
195
- # Sets the fill color. 6 digit HTML color codes are used.
196
- #
197
- # pdf.fill_color "f0ffc1"
198
- #
199
- def fill_color(color=nil)
200
- return @fill_color unless color
201
- @fill_color = color
202
- set_fill_color
203
- end
204
-
205
- alias_method :fill_color=, :fill_color
206
200
 
207
- # Sets the line stroking color. 6 digit HTML color codes are used.
208
- #
209
- # pdf.stroke_color "cc2fde"
210
- #
211
- def stroke_color(color=nil)
212
- return @stroke_color unless color
213
- @stroke_color = color
214
- set_stroke_color
215
- end
216
-
217
- alias_method :stroke_color=, :stroke_color
218
-
219
- # Strokes and closes the current path.
201
+ # Strokes and closes the current path. See Graphic::Color for color details
220
202
  #
221
203
  def stroke
222
204
  yield if block_given?
223
205
  add_content "S"
224
206
  end
225
207
 
226
- # Fills and closes the current path
208
+ # Fills and closes the current path. See Graphic::Color for color details
227
209
  #
228
210
  def fill
229
211
  yield if block_given?
230
212
  add_content "f"
231
213
  end
232
-
233
- # Fills, strokes, and closes the current path.
214
+
215
+ # Fills, strokes, and closes the current path. See Graphic::Color for color details
234
216
  #
235
217
  def fill_and_stroke
236
218
  yield if block_given?
237
219
  add_content "b"
238
- end
239
-
240
- # Provides the following shortcuts:
241
- #
242
- # stroke_some_method(*args) #=> some_method(*args); stroke
243
- # fill_some_method(*args) #=> some_method(*args); fill
244
- #
245
- def method_missing(id,*args,&block)
246
- case(id.to_s)
247
- when /^fill_and_stroke_(.*)/
248
- send($1,*args,&block); fill_and_stroke
249
- when /^stroke_(.*)/
250
- send($1,*args,&block); stroke
251
- when /^fill_(.*)/
252
- send($1,*args,&block); fill
253
- else
254
- super
255
- end
256
- end
220
+ end
257
221
 
258
- private
222
+ private
259
223
 
260
224
  def translate(*point)
261
225
  x,y = point.flatten
262
226
  [@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
263
- end
264
-
265
- def set_fill_color
266
- r,g,b = [@fill_color[0..1], @fill_color[2..3], @fill_color[4..5]].
267
- map { |e| e.to_i(16) }
268
- add_content "%.3f %.3f %.3f rg" % [r / 255.0, g / 255.0, b / 255.0]
269
- end
270
-
271
- def set_stroke_color
272
- r,g,b = [@stroke_color[0..1], @stroke_color[2..3], @stroke_color[4..5]].
273
- map { |e| e.to_i(16) }
274
- add_content "%.3f %.3f %.3f RG" % [r / 255.0, g / 255.0, b / 255.0]
275
- end
227
+ end
276
228
 
277
- def update_colors
278
- @fill_color ||= "000000"
279
- @stroke_color ||= "000000"
280
- set_fill_color
281
- set_stroke_color
282
- end
229
+ def translate!(point)
230
+ point.replace(translate(point))
231
+ end
283
232
 
284
233
  end
285
234
  end
@@ -54,7 +54,8 @@ module Prawn
54
54
  @document = options[:document]
55
55
  @text = options[:text].to_s
56
56
  @width = options[:width]
57
- @border = options[:border] || 1
57
+ @borders = options[:borders]
58
+ @border_width = options[:border_width] || 1
58
59
  @border_style = options[:border_style] || :all
59
60
  @background_color = options[:background_color]
60
61
  @align = options[:align] || :left
@@ -67,9 +68,10 @@ module Prawn
67
68
  end
68
69
  end
69
70
 
70
- attr_accessor :point, :border_style, :border, :background_color,
71
- :document, :horizontal_padding, :vertical_padding,
72
- :align
71
+ attr_accessor :point, :border_style, :border_width, :background_color,
72
+ :document, :horizontal_padding, :vertical_padding, :align,
73
+ :borders
74
+
73
75
  attr_writer :height, :width #:nodoc:
74
76
 
75
77
  # Returns the cell's text as a string.
@@ -87,22 +89,20 @@ module Prawn
87
89
  # The width of the cell in PDF points
88
90
  #
89
91
  def width
90
- @width || (@document.font_metrics.string_width(@text,
91
- @document.font_size)) + 2*@horizontal_padding
92
+ @width || (@document.font.metrics.string_width(@text,
93
+ @document.font.size)) + 2*@horizontal_padding
92
94
  end
93
95
 
94
96
  # The height of the cell in PDF points
95
97
  #
96
- def height
98
+ def height
97
99
  @height || text_area_height + 2*@vertical_padding
98
100
  end
99
101
 
100
102
  # The height of the text area excluding the vertical padding
101
103
  #
102
104
  def text_area_height
103
- @document.font_metrics.string_height(@text,
104
- :font_size => @document.font_size,
105
- :line_width => text_area_width)
105
+ @document.font.height_of(@text, :line_width => text_area_width)
106
106
  end
107
107
 
108
108
  # Draws the cell onto the PDF document
@@ -113,32 +113,33 @@ module Prawn
113
113
  if @background_color
114
114
  @document.mask(:fill_color) do
115
115
  @document.fill_color @background_color
116
- h = borders.include?(:bottom) ? height - border : height + border / 2.0
117
- @document.fill_rectangle [rel_point[0] + border / 2.0,
118
- rel_point[1] - border / 2.0 ],
119
- width - border, h
116
+ h = borders.include?(:bottom) ?
117
+ height - border_width : height + border_width / 2.0
118
+ @document.fill_rectangle [rel_point[0] + border_width / 2.0,
119
+ rel_point[1] - border_width / 2.0 ],
120
+ width - border_width, h
120
121
  end
121
122
  end
122
123
 
123
- if @border > 0
124
+ if @border_width > 0
124
125
  @document.mask(:line_width) do
125
- @document.line_width = @border
126
+ @document.line_width = @border_width
126
127
 
127
128
  if borders.include?(:left)
128
- @document.stroke_line [rel_point[0], rel_point[1] + (@border / 2.0)],
129
- [rel_point[0], rel_point[1] - height - @border / 2.0 ]
129
+ @document.stroke_line [rel_point[0], rel_point[1] + (@border_width / 2.0)],
130
+ [rel_point[0], rel_point[1] - height - @border_width / 2.0 ]
130
131
  end
131
132
 
132
133
  if borders.include?(:right)
133
134
  @document.stroke_line(
134
- [rel_point[0] + width, rel_point[1] + (@border / 2.0)],
135
- [rel_point[0] + width, rel_point[1] - height - @border / 2.0] )
135
+ [rel_point[0] + width, rel_point[1] + (@border_width / 2.0)],
136
+ [rel_point[0] + width, rel_point[1] - height - @border_width / 2.0] )
136
137
  end
137
138
 
138
139
  if borders.include?(:top)
139
140
  @document.stroke_line(
140
- [ rel_point[0] + @border / 2.0, rel_point[1] ],
141
- [ rel_point[0] - @border / 2.0 + width, rel_point[1] ])
141
+ [ rel_point[0] + @border_width / 2.0, rel_point[1] ],
142
+ [ rel_point[0] - @border_width / 2.0 + width, rel_point[1] ])
142
143
  end
143
144
 
144
145
  if borders.include?(:bottom)
@@ -214,13 +215,17 @@ module Prawn
214
215
  @document.y = y - @height
215
216
  end
216
217
 
217
- def border
218
- @cells[0].border
218
+ def border_width
219
+ @cells[0].border_width
219
220
  end
220
221
 
221
222
  def border_style=(s)
222
223
  @cells.each { |e| e.border_style = s }
223
- end
224
+ end
225
+
226
+ def align=(align)
227
+ @cells.each { |e| e.align = align }
228
+ end
224
229
 
225
230
  def border_style
226
231
  @cells[0].border_style
@@ -0,0 +1,132 @@
1
+ module Prawn
2
+ module Graphics
3
+ module Color
4
+
5
+ # Sets the fill color.
6
+ #
7
+ # If a single argument is provided, it should be a 6 digit HTML color
8
+ # code.
9
+ #
10
+ # pdf.fill_color "f0ffc1"
11
+ #
12
+ # If 4 arguments are provided, the color is assumed to be a CMYK value
13
+ # Values range from 0 - 100.
14
+ #
15
+ # pdf.fill_color 0, 99, 95, 0
16
+ #
17
+ def fill_color(*color)
18
+ return @fill_color if color.empty?
19
+ @fill_color = process_color(*color)
20
+ set_fill_color
21
+ end
22
+
23
+ alias_method :fill_color=, :fill_color
24
+
25
+ # Sets the line stroking color. 6 digit HTML color codes are used.
26
+ #
27
+ # If a single argument is provided, it should be a 6 digit HTML color
28
+ # code.
29
+ #
30
+ # pdf.fill_color "f0ffc1"
31
+ #
32
+ # If 4 arguments are provided, the color is assumed to be a CMYK value
33
+ # Values range from 0 - 100.
34
+ #
35
+ # pdf.fill_color 0, 99, 95, 0
36
+ #
37
+ def stroke_color(*color)
38
+ return @stroke_color if color.empty?
39
+ @stroke_color = process_color(*color)
40
+ set_stroke_color
41
+ end
42
+
43
+ alias_method :stroke_color=, :stroke_color
44
+
45
+ # Provides the following shortcuts:
46
+ #
47
+ # stroke_some_method(*args) #=> some_method(*args); stroke
48
+ # fill_some_method(*args) #=> some_method(*args); fill
49
+ #
50
+ def method_missing(id,*args,&block)
51
+ case(id.to_s)
52
+ when /^fill_and_stroke_(.*)/
53
+ send($1,*args,&block); fill_and_stroke
54
+ when /^stroke_(.*)/
55
+ send($1,*args,&block); stroke
56
+ when /^fill_(.*)/
57
+ send($1,*args,&block); fill
58
+ else
59
+ super
60
+ end
61
+ end
62
+
63
+ module_function
64
+
65
+ # Converts RGB value array to hex string suitable for use with fill_color
66
+ # and stroke_color
67
+ #
68
+ # >> Prawn::Graphics::Color.rgb2hex([255,120,8])
69
+ # => "ff7808"
70
+ #
71
+ def rgb2hex(rgb)
72
+ rgb.map { |e| "%02x" % e }.join
73
+ end
74
+
75
+ # Converts hex string into RGB value array:
76
+ #
77
+ # >> Prawn::Graphics::Color.hex2rgb("ff7808")
78
+ # => [255, 120, 8]
79
+ #
80
+ def hex2rgb(hex)
81
+ r,g,b = hex[0..1], hex[2..3], hex[4..5]
82
+ [r,g,b].map { |e| e.to_i(16) }
83
+ end
84
+
85
+ private
86
+
87
+ def process_color(*color)
88
+ case(color.size)
89
+ when 1
90
+ color[0]
91
+ when 4
92
+ color
93
+ else
94
+ raise ArgumentError, 'wrong number of arguments supplied'
95
+ end
96
+ end
97
+
98
+ def set_fill_color
99
+ case @fill_color
100
+ when String
101
+ r,g,b = hex2rgb(@fill_color)
102
+ add_content "%.3f %.3f %.3f rg" %
103
+ [r / 255.0, g / 255.0, b / 255.0]
104
+ when Array
105
+ c,m,y,k = *@fill_color
106
+ add_content "%.3f %.3f %.3f %.3f k" %
107
+ [c / 100.0, m / 100.0, y / 100.0, k / 100.0]
108
+ end
109
+ end
110
+
111
+ def set_stroke_color
112
+ case @stroke_color
113
+ when String
114
+ r,g,b = hex2rgb(@stroke_color)
115
+ add_content "%.3f %.3f %.3f RG" %
116
+ [r / 255.0, g / 255.0, b / 255.0]
117
+ when Array
118
+ c,m,y,k = *@stroke_color
119
+ add_content "%.3f %.3f %.3f %.3f K" %
120
+ [c / 100.0, m / 100.0, y / 100.0, k / 100.0]
121
+ end
122
+ end
123
+
124
+ def update_colors
125
+ @fill_color ||= "000000"
126
+ @stroke_color ||= "000000"
127
+ set_fill_color
128
+ set_stroke_color
129
+ end
130
+ end
131
+ end
132
+ end