prawn 0.1.2 → 0.2.0

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