prawn 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,7 +40,7 @@ module Prawn
40
40
  end
41
41
 
42
42
  def write_stroke_cap_style
43
- add_content "#{CAP_STYLES[current_cap_style]} J"
43
+ renderer.add_content "#{CAP_STYLES[current_cap_style]} J"
44
44
  end
45
45
  end
46
46
  end
@@ -151,7 +151,7 @@ module Prawn
151
151
  raise ArgumentError, "unknown type '#{type}'"
152
152
  end
153
153
 
154
- add_content "/#{color_space} #{operator}"
154
+ renderer.add_content "/#{color_space} #{operator}"
155
155
  end
156
156
 
157
157
  def set_color(type, color, options = {})
@@ -166,7 +166,7 @@ module Prawn
166
166
 
167
167
  if options[:pattern]
168
168
  set_color_space type, :Pattern
169
- add_content "/#{color} #{operator}"
169
+ renderer.add_content "/#{color} #{operator}"
170
170
  else
171
171
  set_color_space type, color_space(color)
172
172
  color = color_to_s(color)
@@ -223,7 +223,7 @@ module Prawn
223
223
  end
224
224
 
225
225
  def write_color(color, operator)
226
- add_content "#{color} #{operator}"
226
+ renderer.add_content "#{color} #{operator}"
227
227
  end
228
228
 
229
229
  end
@@ -80,7 +80,7 @@ module Prawn
80
80
  private
81
81
 
82
82
  def write_stroke_dash
83
- add_content dash_setting
83
+ renderer.add_content dash_setting
84
84
  end
85
85
 
86
86
  def undashed_setting
@@ -42,7 +42,7 @@ module Prawn
42
42
 
43
43
 
44
44
  def write_stroke_join_style
45
- add_content "#{JOIN_STYLES[current_join_style]} j"
45
+ renderer.add_content "#{JOIN_STYLES[current_join_style]} j"
46
46
  end
47
47
  end
48
48
  end
@@ -56,7 +56,7 @@ module Prawn
56
56
  end
57
57
 
58
58
  set_color_space type, :Pattern
59
- add_content "/SP#{registry_key} #{operator}"
59
+ renderer.add_content "/SP#{registry_key} #{operator}"
60
60
  end
61
61
 
62
62
  def gradient_registry_key(gradient)
@@ -145,7 +145,7 @@ module Prawn
145
145
  def transformation_matrix(a, b, c, d, e, f)
146
146
  values = [a, b, c, d, e, f].map { |x| "%.5f" % x }.join(" ")
147
147
  save_graphics_state if block_given?
148
- add_content "#{values} cm"
148
+ renderer.add_content "#{values} cm"
149
149
  if block_given?
150
150
  yield
151
151
  restore_graphics_state
@@ -54,13 +54,13 @@ module Prawn
54
54
  # end
55
55
  #
56
56
  def transparent(opacity, stroke_opacity=opacity, &block)
57
- min_version(1.4)
57
+ renderer.min_version(1.4)
58
58
 
59
59
  opacity = [[opacity, 0.0].max, 1.0].min
60
60
  stroke_opacity = [[stroke_opacity, 0.0].max, 1.0].min
61
61
 
62
62
  save_graphics_state
63
- add_content "/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
63
+ renderer.add_content "/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
64
64
  yield
65
65
  restore_graphics_state
66
66
  end
@@ -28,7 +28,7 @@ module Prawn
28
28
  # or work with the grid system directly.
29
29
  #
30
30
  # @pdf.grid # Get the Grid directly
31
- # @pdf.grid([0,1]) # Get the box at [0,1]
31
+ # @pdf.grid([0,1]) # Get the GridBox at [0,1]
32
32
  # @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
33
33
  #
34
34
  def grid(*args)
@@ -49,7 +49,7 @@ module Prawn
49
49
  # A Grid represents the entire grid system of a Page and calculates
50
50
  # the column width and row height of the base box.
51
51
  #
52
- # @private
52
+ # @group Experimental API
53
53
  class Grid
54
54
  attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
55
55
  def initialize(pdf, options = {}) # :nodoc:
@@ -103,7 +103,7 @@ module Prawn
103
103
  # A Grid object has methods that allow easy access to the coordinates of
104
104
  # its corners, which can be plugged into most existing prawnmethods.
105
105
  #
106
- # @private
106
+ # @group Experimental API
107
107
  class GridBox
108
108
  attr_reader :pdf
109
109
 
@@ -206,8 +206,8 @@ module Prawn
206
206
 
207
207
  # A MultiBox is specified by 2 Boxes and spans the areas between.
208
208
  #
209
- # @private
210
- class MultiBox < GridBox #:nodoc:
209
+ # @group Experimental API
210
+ class MultiBox < GridBox
211
211
  def initialize(pdf, b1, b2)
212
212
  @pdf = pdf
213
213
  @bs = [b1, b2]
@@ -89,7 +89,7 @@ module Prawn
89
89
  info = Prawn.image_handler.find(image_content).new(image_content)
90
90
 
91
91
  # Bump PDF version if the image requires it
92
- min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version)
92
+ renderer.min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version)
93
93
 
94
94
  # Add the image to the PDF and register it in case we see it again.
95
95
  image_obj = info.build_pdf_object(self)
@@ -123,7 +123,7 @@ module Prawn
123
123
 
124
124
  # add the image to the current page
125
125
  instruct = "\nq\n%.3f 0 0 %.3f %.3f %.3f cm\n/%s Do\nQ"
126
- add_content instruct % [ w, h, x, y - h, label ]
126
+ renderer.add_content instruct % [ w, h, x, y - h, label ]
127
127
  end
128
128
 
129
129
  private
@@ -10,7 +10,7 @@ require 'digest/md5'
10
10
 
11
11
  require 'pdf/core/byte_string'
12
12
 
13
- require 'prawn/security/arcfour'
13
+ require_relative 'security/arcfour'
14
14
 
15
15
  module Prawn
16
16
  class Document
@@ -29,7 +29,7 @@ module Prawn
29
29
  # @group Stable API
30
30
 
31
31
  def soft_mask(&block)
32
- min_version(1.4)
32
+ renderer.min_version(1.4)
33
33
 
34
34
  group_attrs = ref!({
35
35
  :Type => :Group,
@@ -73,7 +73,7 @@ module Prawn
73
73
  }.hash
74
74
 
75
75
  if soft_mask_registry[registry_key]
76
- add_content "/#{soft_mask_registry[registry_key]} gs"
76
+ renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
77
77
  else
78
78
  masks = page.resources[:ExtGState] ||= {}
79
79
  id = masks.empty? ? 'GS1' : masks.keys.sort.last.succ
@@ -81,7 +81,7 @@ module Prawn
81
81
 
82
82
  soft_mask_registry[registry_key] = id
83
83
 
84
- add_content "/#{id} gs"
84
+ renderer.add_content "/#{id} gs"
85
85
  end
86
86
  end
87
87
 
@@ -44,7 +44,7 @@ module Prawn
44
44
  #
45
45
  def stamp(name)
46
46
  dictionary_name, dictionary = stamp_dictionary(name)
47
- add_content "/#{dictionary_name} Do"
47
+ renderer.add_content "/#{dictionary_name} Do"
48
48
  state.page.xobjects.merge!(dictionary_name => dictionary)
49
49
  end
50
50
 
@@ -288,6 +288,14 @@ module Prawn
288
288
  end
289
289
  end
290
290
 
291
+ # Low level text placement method. All font and size alterations
292
+ # should already be set
293
+ #
294
+ def draw_text!(text, options)
295
+ x,y = map_to_absolute(options[:at])
296
+ add_text_content(text,x,y,options)
297
+ end
298
+
291
299
  # Gets height of text in PDF points.
292
300
  # Same options as #text, except as noted.
293
301
  # Not compatible with :indent_paragraphs option
@@ -209,9 +209,19 @@ module Prawn
209
209
 
210
210
  def process_text(text)
211
211
  string = strip_zero_width_spaces(text)
212
+
212
213
  if exclude_trailing_white_space?
213
- string = process_soft_hyphens(string.rstrip)
214
+ string = string.rstrip
215
+
216
+ if soft_hyphens_need_processing?(string)
217
+ string = process_soft_hyphens(string[0..-2]) + string[-1..-1]
218
+ end
219
+ else
220
+ if soft_hyphens_need_processing?(string)
221
+ string = process_soft_hyphens(string)
222
+ end
214
223
  end
224
+
215
225
  case direction
216
226
  when :rtl
217
227
  string.reverse
@@ -224,19 +234,20 @@ module Prawn
224
234
  @format_state[:exclude_trailing_white_space]
225
235
  end
226
236
 
237
+ def soft_hyphens_need_processing?(string)
238
+ string.length > 0 && normalized_soft_hyphen
239
+ end
240
+
227
241
  def normalized_soft_hyphen
228
242
  @format_state[:normalized_soft_hyphen]
229
243
  end
230
244
 
231
245
  def process_soft_hyphens(string)
232
- if string.length > 0 && normalized_soft_hyphen
233
- if string.encoding != normalized_soft_hyphen.encoding
234
- string.force_encoding(normalized_soft_hyphen.encoding)
235
- end
236
- string[0..-2].gsub(normalized_soft_hyphen, "") + string[-1..-1]
237
- else
238
- string
246
+ if string.encoding != normalized_soft_hyphen.encoding
247
+ string.force_encoding(normalized_soft_hyphen.encoding)
239
248
  end
249
+
250
+ string.gsub(normalized_soft_hyphen, "")
240
251
  end
241
252
 
242
253
  def strip_zero_width_spaces(string)
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Prawn
4
+ VERSION = "1.3.0"
5
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # prawn/view.rb : Implements a mixin for Prawn's DSL
4
+ #
5
+ # This is free software. Please see the LICENSE and COPYING files for details.
6
+
7
+ module Prawn
8
+ # This mixin allows you to create modular Prawn code without the
9
+ # need to create subclasses of Prawn::Document.
10
+ #
11
+ # class Greeter
12
+ # include Prawn::View
13
+ #
14
+ # def initialize(name)
15
+ # @name = name
16
+ # end
17
+ #
18
+ # def say_hello
19
+ # text "Hello, #{@name}!"
20
+ # end
21
+ #
22
+ # def say_goodbye
23
+ # font("Courier") do
24
+ # text "Goodbye, #{@name}!"
25
+ # end
26
+ # end
27
+ # end
28
+ #
29
+ # greeter = Greeter.new("Gregory")
30
+ #
31
+ # greeter.say_hello
32
+ # greeter.say_goodbye
33
+ #
34
+ # greeter.save_as("greetings.pdf")
35
+ #
36
+ # The short story about why you should use this mixin rather than
37
+ # creating subclasses of +Prawn::Document+ is that it helps
38
+ # prevent accidental conflicts between your code and Prawn's
39
+ # code.
40
+ #
41
+ # Here's the slightly longer story...
42
+ #
43
+ # By using composition rather than inheritance under the hood, this
44
+ # mixin allows you to keep your state separate from +Prawn::Document+'s
45
+ # state, and also will prevent unexpected method name collisions due
46
+ # to late binding effects.
47
+ #
48
+ # This mixin is mostly meant for extending Prawn's functionality
49
+ # with your own additions, but you can also use it to replace or
50
+ # wrap existing Prawn methods. Calling +super+ will still work
51
+ # as expected, and alternatively you can explictly call
52
+ # +document.some_method+ to delegate to Prawn where needed.
53
+ module View
54
+ # @group Experimental API
55
+
56
+ # Lazily instantiates a +Prawn::Document+ object.
57
+ #
58
+ # You can also redefine this method in your own classes to use
59
+ # a custom document class.
60
+ def document
61
+ @document ||= Prawn::Document.new
62
+ end
63
+
64
+ # Delegates all unhandled calls to object returned by +document+ method.
65
+ # (which is an instance of Prawn::Document by default)
66
+ def method_missing(m, *a, &b)
67
+ return super unless document.respond_to?(m)
68
+
69
+ document.send(m, *a, &b)
70
+ end
71
+
72
+ # Syntactic sugar that uses +instance_eval+ under the hood to provide
73
+ # a block-based DSL.
74
+ #
75
+ # greeter.update do
76
+ # say_hello
77
+ # say_goodbye
78
+ # end
79
+ #
80
+ def update(&b)
81
+ instance_eval(&b)
82
+ end
83
+
84
+ # Syntatic sugar that calls +document.render_file+ under the hood.
85
+ #
86
+ # greeter.save_as("greetings.pdf")
87
+ def save_as(filename)
88
+ document.render_file(filename)
89
+ end
90
+ end
91
+ end
@@ -15,6 +15,7 @@ Prawn::ManualBuilder::Example.generate("basic_concepts.pdf", :page_size => "FOLI
15
15
  p.example "other_cursor_helpers"
16
16
  p.example "adding_pages"
17
17
  p.example "measurement"
18
+ p.example "view", :eval_source => false, :full_source => true
18
19
 
19
20
  p.intro do
20
21
  prose("This chapter covers the minimum amount of functionality you'll need to start using Prawn.
@@ -27,7 +28,8 @@ Prawn::ManualBuilder::Example.generate("basic_concepts.pdf", :page_size => "FOLI
27
28
  "Where the origin for the document coordinates is. What are Bounding Boxes and how they interact with the origin",
28
29
  "How the cursor behaves",
29
30
  "How to start new pages",
30
- "What the base unit for measurement and coordinates is and how to use other convenient measures"
31
+ "What the base unit for measurement and coordinates is and how to use other convenient measures",
32
+ "How to build custom view objects that use Prawn's DSL"
31
33
  )
32
34
  end
33
35
  end
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # To create a custom class that extends Prawn's functionality,
4
+ # use the <code>Prawn::View</code> mixin. This approach is safer than creating
5
+ # subclasses of <code>Prawn::Document</code> while being just as convenient.
6
+ #
7
+ # By using this mixin, your state will be kept completely separate
8
+ # from <code>Prawn::Document</code>'s state, and you will avoid accidental method
9
+ # collisions within <code>Prawn::Document</code>.
10
+ #
11
+ # To build custom classes that make use of other custom classes,
12
+ # you can define a method named <code>document()</code> that returns
13
+ # any object that acts similar to a <code>Prawn::Document</code>
14
+ # object. <code>Prawn::View</code> will then direct all delegated
15
+ # calls to that object instead.
16
+
17
+ require_relative "../example_helper"
18
+
19
+ class Greeter
20
+ include Prawn::View
21
+
22
+ def initialize(name)
23
+ @name = name
24
+ end
25
+
26
+ def say_hello
27
+ text "Hello, #{@name}!"
28
+ end
29
+
30
+ def say_goodbye
31
+ font("Courier") do
32
+ text "Goodbye, #{@name}!"
33
+ end
34
+ end
35
+ end
36
+
37
+ greeter = Greeter.new("Gregory")
38
+
39
+ greeter.say_hello
40
+ greeter.say_goodbye
41
+
42
+ greeter.save_as("greetings.pdf")
@@ -1,6 +1,10 @@
1
+ basedir = File.expand_path(File.dirname(__FILE__))
2
+
3
+ require "#{basedir}/lib/prawn/version"
4
+
1
5
  Gem::Specification.new do |spec|
2
6
  spec.name = "prawn"
3
- spec.version = File.read(File.expand_path('VERSION', File.dirname(__FILE__))).strip
7
+ spec.version = Prawn::VERSION
4
8
  spec.platform = Gem::Platform::RUBY
5
9
  spec.summary = "A fast and nimble PDF generator for Ruby"
6
10
  spec.files = Dir.glob("{examples,lib,spec,manual}/**/**/*") +
@@ -9,7 +13,7 @@ Gem::Specification.new do |spec|
9
13
  ["data/shift_jis_text.txt"] +
10
14
  ["Rakefile", "prawn.gemspec", "Gemfile",
11
15
  "COPYING", "LICENSE", "GPLv2", "GPLv3",
12
- "VERSION", ".yardopts"]
16
+ ".yardopts"]
13
17
  spec.require_path = "lib"
14
18
  spec.required_ruby_version = '>= 1.9.3'
15
19
  spec.required_rubygems_version = ">= 1.3.6"
@@ -20,8 +24,8 @@ Gem::Specification.new do |spec|
20
24
  spec.rubyforge_project = "prawn"
21
25
  spec.licenses = ['RUBY', 'GPL-2', 'GPL-3']
22
26
 
23
- spec.add_dependency('ttfunk', '~> 1.2.0')
24
- spec.add_dependency('pdf-core', "~> 0.2.5")
27
+ spec.add_dependency('ttfunk', '~> 1.4.0')
28
+ spec.add_dependency('pdf-core', "~> 0.4.0")
25
29
 
26
30
  spec.add_development_dependency('pdf-inspector', '~> 1.1.0')
27
31
  spec.add_development_dependency('yard')
@@ -32,6 +36,7 @@ Gem::Specification.new do |spec|
32
36
  spec.add_development_dependency('prawn-manual_builder', ">= 0.2.0")
33
37
  spec.add_development_dependency('pdf-reader', '~>1.2')
34
38
  spec.add_development_dependency('rubocop', '0.20.1')
39
+ spec.add_development_dependency('code_statistics', '0.2.13')
35
40
 
36
41
  spec.homepage = "http://prawn.majesticseacreature.com"
37
42
  spec.description = <<END_DESC