prawn-core 0.7.1 → 0.7.2

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.
data/HACKING CHANGED
@@ -22,7 +22,7 @@ If you are running on Ruby 1.9.1, you will need Test::Unit 1.2.3
22
22
 
23
23
  http://github.com/sandal/prawn/issues
24
24
  http://github.com/sandal/prawn-layout/issues
25
- http://github.com/sandal/prawn-format/issues
25
+ http://github.com/sandal/prawn-security/issues
26
26
 
27
27
  2. Fork any necessary repositories on Github, make your changes
28
28
  3. Submit pull request so Gregory is notified
data/README CHANGED
@@ -8,7 +8,7 @@ the many people who donated to the Ruby Mendicant project:
8
8
  http://rubymendicant.wikidot.com
9
9
 
10
10
  The project is currently maintained by Gregory Brown, with lots of help from
11
- the community.
11
+ Prawn's core developers and the community.
12
12
 
13
13
  == Quick Start
14
14
 
@@ -103,28 +103,22 @@ For tables and grid based layout:
103
103
 
104
104
  http://github.com/sandal/prawn-layout/tree/stable/examples
105
105
 
106
- For inline styling and advanced formatting:
107
-
108
- http://github.com/sandal/prawn-format/tree/stable/examples
109
-
110
106
  For encryption, password protection, and permissions:
111
107
 
112
108
  http://github.com/madriska/prawn-security/tree/stable/examples
113
109
 
114
- (or gem unpack prawn-core, prawn-format, prawn-security and prawn-layout if you want to run them locally)
110
+ (or gem unpack prawn-core, prawn-security and prawn-layout if you want to run them locally)
115
111
 
116
112
  === Bug Tracker / Wiki:
117
113
 
118
114
  http://github.com/sandal/prawn/issues
119
115
  http://github.com/sandal/prawn-layout/issues
120
- http://github.com/sandal/prawn-format/issues
121
116
  http://github.com/madriska/prawn-security/issues
122
117
 
123
118
  === Source Code:
124
119
 
125
120
  http://github.com/sandal/prawn
126
121
  http://github.com/sandal/prawn-layout
127
- http://github.com/sandal/prawn-format
128
122
  http://github.com/madriska/prawn-security
129
123
 
130
124
  === Mailing List:
@@ -136,6 +130,8 @@ http://groups.google.com/group/prawn-ruby
136
130
  Find us in #prawn on irc.freenode.net
137
131
  Gregory Brown: <sandal>
138
132
  James Healy: <yob>
133
+ Brad Ediger: <bradediger>
134
+ Daniel Nelson: <bluejade>
139
135
 
140
136
  == Notes to Developers:
141
137
 
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rake/testtask'
4
4
  require "rake/rdoctask"
5
5
  require "rake/gempackagetask"
6
6
 
7
- PRAWN_VERSION = "0.7.1"
7
+ PRAWN_VERSION = "0.7.2"
8
8
 
9
9
  task :default => [:test]
10
10
 
@@ -4,9 +4,22 @@
4
4
  # as simple as this?
5
5
  #
6
6
  class String #:nodoc:
7
+ def first_line
8
+ self.each_line { |line| return line }
9
+ end
7
10
  unless "".respond_to?(:lines)
8
11
  alias_method :lines, :to_a
9
12
  end
13
+ unless "".respond_to?(:each_char)
14
+ def each_char
15
+ # copied from jcode
16
+ if block_given?
17
+ scan(/./m) { |x| yield x }
18
+ else
19
+ scan(/./m)
20
+ end
21
+ end
22
+ end
10
23
  end
11
24
 
12
25
  unless File.respond_to?(:binread)
@@ -25,7 +25,7 @@ module Prawn
25
25
  # The base source directory for Prawn as installed on the system
26
26
  BASEDIR = File.expand_path(File.join(dir, '..', '..'))
27
27
 
28
- VERSION = "0.7.1"
28
+ VERSION = "0.7.2"
29
29
 
30
30
  extend self
31
31
 
@@ -395,7 +395,7 @@ module Prawn
395
395
  # Sets Document#bounds to the BoundingBox provided. See above for a brief
396
396
  # description of what a bounding box is. This function is useful if you
397
397
  # really need to change the bounding box manually, but usually, just entering
398
- # and existing bounding box code blocks is good enough.
398
+ # and exiting bounding box code blocks is good enough.
399
399
  #
400
400
  def bounds=(bounding_box)
401
401
  @bounding_box = bounding_box
@@ -46,6 +46,7 @@ module Prawn
46
46
  def take_snapshot
47
47
  {:page_content => Marshal.load(Marshal.dump(page_content)),
48
48
  :current_page => Marshal.load(Marshal.dump(current_page)),
49
+ :page_number => @page_number,
49
50
  :page_kids => @store.pages.data[:Kids].map{|kid| kid.identifier},
50
51
  :dests => names? &&
51
52
  Marshal.load(Marshal.dump(names.data[:Dests]))}
@@ -64,6 +65,8 @@ module Prawn
64
65
  current_page.replace shot[:current_page]
65
66
  current_page.data[:Contents] = page_content
66
67
 
68
+ @page_number = shot[:page_number]
69
+
67
70
  @store.pages.data[:Kids] = shot[:page_kids].map{|id| @store[id]}
68
71
  @store.pages.data[:Count] = shot[:page_kids].size
69
72
 
@@ -28,6 +28,10 @@ module Prawn
28
28
  #
29
29
  UnknownFont = Class.new(StandardError)
30
30
 
31
+ # Raised when Prawn is asked to draw something into a too-small box
32
+ #
33
+ CannotFit = Class.new(StandardError)
34
+
31
35
  # This error is raised when Prawn is being used on a M17N aware VM,
32
36
  # and the user attempts to add text that isn't compatible with UTF-8
33
37
  # to their document
@@ -13,20 +13,37 @@ module Prawn
13
13
 
14
14
  class Document
15
15
  # Without arguments, this returns the currently selected font. Otherwise,
16
- # it sets the current font.
16
+ # it sets the current font. When a block is used, the font is applied
17
+ # transactionally and is rolled back when the block exits.
17
18
  #
18
- # The single parameter must be a string. It can be one of the 14 built-in
19
+ # Prawn::Document.generate("font.pdf") do
20
+ # text "Default font is Helvetica"
21
+ #
22
+ # font "Times-Roman"
23
+ # text "Now using Times-Roman"
24
+ #
25
+ # font("Chalkboard.ttf") do
26
+ # text "Using TTF font from file Chalkboard.ttf"
27
+ # font "Courier", :style => :bold
28
+ # text "You see this in bold Courier"
29
+ # end
30
+ #
31
+ # text "Times-Roman, again"
32
+ # end
33
+ #
34
+ # The :name parameter must be a string. It can be one of the 14 built-in
19
35
  # fonts supported by PDF, or the location of a TTF file. The Font::AFM::BUILT_INS
20
36
  # array specifies the valid built in font values.
21
37
  #
22
- # pdf.font "Times-Roman"
23
- # pdf.font "Chalkboard.ttf"
24
- #
25
38
  # If a ttf font is specified, the glyphs necessary to render your document
26
39
  # will be embedded in the rendered PDF. This should be your preferred option
27
40
  # in most cases. It will increase the size of the resulting file, but also
28
41
  # make it more portable.
29
42
  #
43
+ # The options parameter is an optional hash providing size and style. To use
44
+ # the :style option you need to map those font styles to their respective font files.
45
+ # See font_families for more information.
46
+ #
30
47
  def font(name=nil, options={})
31
48
  return((defined?(@font) && @font) || font("Helvetica")) if name.nil?
32
49
 
@@ -131,7 +148,7 @@ module Prawn
131
148
  @font_registry ||= {}
132
149
  end
133
150
 
134
- # Hash that maps font family names to their styled individual font names
151
+ # Hash that maps font family names to their styled individual font names.
135
152
  #
136
153
  # To add support for another font family, append to this hash, e.g:
137
154
  #
@@ -151,6 +168,12 @@ module Prawn
151
168
  # This assumes that you have appropriate TTF fonts for each style you
152
169
  # wish to support.
153
170
  #
171
+ # By default the styles :bold, :italic, :bold_italic, and :normal are
172
+ # defined for fonts "Courier", "Times-Roman" and "Helvetica".
173
+ #
174
+ # You probably want to provide those four styles, but are free to define
175
+ # custom ones, like :thin, and use them in font calls.
176
+ #
154
177
  def font_families
155
178
  @font_families ||= Hash.new { |h,k| h[k] = {} }.merge!(
156
179
  { "Courier" => { :bold => "Courier-Bold",
@@ -8,6 +8,10 @@ module Prawn
8
8
  Times-Bold Times-Italic Times-BoldItalic
9
9
  Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique ]
10
10
 
11
+ def unicode?
12
+ false
13
+ end
14
+
11
15
  def self.metrics_path
12
16
  if m = ENV['METRICS']
13
17
  @metrics_path ||= m.split(':')
@@ -98,10 +102,18 @@ module Prawn
98
102
  private
99
103
 
100
104
  def register(subset)
101
- @document.ref!(:Type => :Font,
102
- :Subtype => :Type1,
103
- :BaseFont => name.to_sym,
104
- :Encoding => :WinAnsiEncoding)
105
+ font_dict = {:Type => :Font,
106
+ :Subtype => :Type1,
107
+ :BaseFont => name.to_sym}
108
+
109
+ # Symbolic AFM fonts (Symbol, ZapfDingbats) have their own encodings
110
+ font_dict.merge!(:Encoding => :WinAnsiEncoding) unless symbolic?
111
+
112
+ @document.ref!(font_dict)
113
+ end
114
+
115
+ def symbolic?
116
+ attributes["characterset"] == "Special"
105
117
  end
106
118
 
107
119
  def find_font(file)
@@ -5,6 +5,10 @@ module Prawn
5
5
  class Font
6
6
  class TTF < Font
7
7
  attr_reader :ttf, :subsets
8
+
9
+ def unicode?
10
+ true
11
+ end
8
12
 
9
13
  def initialize(document, name, options={})
10
14
  super
@@ -10,7 +10,9 @@ module Prawn
10
10
  module Graphics
11
11
  module Color
12
12
 
13
- # Sets the fill color.
13
+ # Sets or returns the fill color.
14
+ #
15
+ # When called with no argument, it returns the current fill color.
14
16
  #
15
17
  # If a single argument is provided, it should be a 6 digit HTML color
16
18
  # code.
@@ -30,7 +32,9 @@ module Prawn
30
32
 
31
33
  alias_method :fill_color=, :fill_color
32
34
 
33
- # Sets the line stroking color. 6 digit HTML color codes are used.
35
+ # Sets or returns the line stroking color.
36
+ #
37
+ # When called with no argument, it returns the current stroking color.
34
38
  #
35
39
  # If a single argument is provided, it should be a 6 digit HTML color
36
40
  # code.
@@ -234,6 +234,11 @@ module Prawn
234
234
  :kerning => @kerning,
235
235
  :size => @font_size,
236
236
  :width => @width)
237
+
238
+ if line_to_print.empty? && remaining_text.length > 0
239
+ raise Errors::CannotFit
240
+ end
241
+
237
242
  remaining_text = remaining_text.slice(line_to_print.length..
238
243
  remaining_text.length)
239
244
  print_ellipses = (@overflow == :ellipses && last_line? &&
@@ -290,7 +295,8 @@ module Prawn
290
295
 
291
296
  def default_wrap_block
292
297
  lambda do |line, options|
293
- scan_pattern = /\S+|\s+/
298
+ scan_pattern = options[:document].font.unicode? ? /\S+|\s+/ : /\S+|\s+/n
299
+ space_scan_pattern = options[:document].font.unicode? ? /\s/ : /\s/n
294
300
  output = ""
295
301
  accumulated_width = 0
296
302
  line.scan(scan_pattern).each do |segment|
@@ -304,9 +310,9 @@ module Prawn
304
310
  else
305
311
  # if the line contains white space, don't split the
306
312
  # final word that doesn't fit, just return what fits nicely
307
- break if output =~ /\s/
313
+ break if output =~ space_scan_pattern
308
314
 
309
- # if there is no white space on the curren tline, then just
315
+ # if there is no white space on the current line, then just
310
316
  # print whatever part of the last segment that will fit on the
311
317
  # line
312
318
  begin
@@ -319,6 +325,7 @@ module Prawn
319
325
  output << char
320
326
  end
321
327
  rescue
328
+ # not valid unicode
322
329
  segment.each_char do |char|
323
330
  accumulated_width += options[:document].width_of(char,
324
331
  :size => options[:size],
@@ -335,10 +342,3 @@ module Prawn
335
342
  end
336
343
  end
337
344
  end
338
-
339
-
340
- class String
341
- def first_line
342
- self.each_line { |line| return line }
343
- end
344
- end
@@ -179,6 +179,12 @@ describe "AFM fonts" do
179
179
  end
180
180
 
181
181
  end
182
+
183
+ it "should omit /Encoding for symbolic fonts" do
184
+ zapf = @pdf.find_font "ZapfDingbats"
185
+ font_dict = zapf.send(:register, nil)
186
+ font_dict.data[:Encoding].should == nil
187
+ end
182
188
 
183
189
  end
184
190
 
@@ -123,5 +123,16 @@ describe "Prawn::Document#transaction" do
123
123
 
124
124
  end
125
125
 
126
+ it "should restore page_number on rollback" do
127
+ Prawn::Document.new do
128
+ transaction do
129
+ 5.times { start_new_page }
130
+ rollback
131
+ end
132
+
133
+ page_number.should == 1
134
+ end
135
+ end
136
+
126
137
  end
127
138
 
@@ -233,90 +233,118 @@ end
233
233
 
234
234
 
235
235
  describe 'Text::Box wrapping' do
236
-
236
+ before(:each) do
237
+ create_pdf
238
+ end
237
239
 
238
240
  it "should wrap text" do
239
241
  text = "Please wrap this text about HERE. More text that should be wrapped"
240
242
  expect = "Please wrap this text about\nHERE. More text that should be\nwrapped"
241
243
 
242
- @pdf = Prawn::Document.new
243
244
  @pdf.font "Courier"
244
- @text_box = Prawn::Text::Box.new(text,
245
+ text_box = Prawn::Text::Box.new(text,
245
246
  :width => 220,
246
247
  :overflow => :expand,
247
248
  :document => @pdf)
248
- @text_box.render
249
- @text_box.text.should == expect
249
+ text_box.render
250
+ text_box.text.should == expect
250
251
  end
251
252
 
252
253
  it "should respect end of line when wrapping text" do
253
254
  text = "Please wrap only before\nTHIS word. Don't wrap this"
254
255
  expect = text
255
256
 
256
- @pdf = Prawn::Document.new
257
257
  @pdf.font "Courier"
258
- @text_box = Prawn::Text::Box.new(text,
258
+ text_box = Prawn::Text::Box.new(text,
259
259
  :width => 220,
260
260
  :overflow => :expand,
261
261
  :document => @pdf)
262
- @text_box.render
263
- @text_box.text.should == expect
262
+ text_box.render
263
+ text_box.text.should == expect
264
264
  end
265
265
 
266
266
  it "should respect multiple newlines when wrapping text" do
267
267
  text = "Please wrap only before THIS\n\nword. Don't wrap this"
268
268
  expect= "Please wrap only before\nTHIS\n\nword. Don't wrap this"
269
269
 
270
- @pdf = Prawn::Document.new
271
270
  @pdf.font "Courier"
272
- @text_box = Prawn::Text::Box.new(text,
271
+ text_box = Prawn::Text::Box.new(text,
273
272
  :width => 200,
274
273
  :overflow => :expand,
275
274
  :document => @pdf)
276
- @text_box.render
277
- @text_box.text.should == expect
275
+ text_box.render
276
+ text_box.text.should == expect
278
277
  end
279
278
 
280
279
  it "should respect multiple newlines when wrapping text when those newlines coincide with a line break" do
281
280
  text = "Please wrap only before\n\nTHIS word. Don't wrap this"
282
281
  expect = text
283
282
 
284
- @pdf = Prawn::Document.new
285
283
  @pdf.font "Courier"
286
- @text_box = Prawn::Text::Box.new(text,
284
+ text_box = Prawn::Text::Box.new(text,
287
285
  :width => 220,
288
286
  :overflow => :expand,
289
287
  :document => @pdf)
290
- @text_box.render
291
- @text_box.text.should == expect
288
+ text_box.render
289
+ text_box.text.should == expect
292
290
  end
293
291
 
294
292
  it "should respect initial newlines" do
295
293
  text = "\nThis should be on line 2"
296
294
  expect = text
297
295
 
298
- @pdf = Prawn::Document.new
299
296
  @pdf.font "Courier"
300
- @text_box = Prawn::Text::Box.new(text,
297
+ text_box = Prawn::Text::Box.new(text,
301
298
  :width => 220,
302
299
  :overflow => :expand,
303
300
  :document => @pdf)
304
- @text_box.render
305
- @text_box.text.should == expect
301
+ text_box.render
302
+ text_box.text.should == expect
306
303
  end
307
304
 
308
305
  it "should wrap lines comprised of a single word of the bounds when wrapping text" do
309
306
  text = "You_can_wrap_this_text_HERE"
310
307
  expect = "You_can_wrap_this_text_HE\nRE"
311
308
 
312
- @pdf = Prawn::Document.new
313
309
  @pdf.font "Courier"
314
- @text_box = Prawn::Text::Box.new(text,
310
+ text_box = Prawn::Text::Box.new(text,
315
311
  :width => 180,
316
312
  :overflow => :expand,
317
313
  :document => @pdf)
318
- @text_box.render
319
- @text_box.text.should == expect
320
- end
314
+ text_box.render
315
+ text_box.text.should == expect
316
+ end
317
+
318
+ it "should wrap lines comprised of a single word of the bounds when wrapping text" do
319
+ text = '©' * 30
320
+
321
+ @pdf.font "Courier"
322
+ text_box = Prawn::Text::Box.new(text, :width => 180,
323
+ :overflow => :expand,
324
+ :document => @pdf)
325
+
326
+ text_box.render
327
+
328
+ expected = '©'*25 + "\n" + '©' * 5
329
+ @pdf.font.normalize_encoding!(expected)
330
+
331
+ text_box.text.should == expected
332
+ end
333
+
334
+ it "should wrap non-unicode strings using single-byte word-wrapping" do
335
+ text = "continúa esforzandote " * 5
336
+ text_box = Prawn::Text::Box.new(text, :width => 180,
337
+ :document => @pdf)
338
+ text_box.render
339
+ results_with_accent = text_box.text
340
+
341
+ text = "continua esforzandote " * 5
342
+ text_box = Prawn::Text::Box.new(text, :width => 180,
343
+ :document => @pdf)
344
+ text_box.render
345
+ results_without_accent = text_box.text
346
+
347
+ results_with_accent.first_line.length.should == results_without_accent.first_line.length
348
+ end
321
349
 
322
350
  end
@@ -12,6 +12,12 @@ describe "#height_of" do
12
12
  new_y = @pdf.y
13
13
  @pdf.height_of("Foo", :width => 300).should.be.close(original_y - new_y, 0.0001)
14
14
  end
15
+
16
+ it "should raise CannotFit if a too-small width is given" do
17
+ lambda do
18
+ @pdf.height_of("text", :width => 1)
19
+ end.should.raise(Prawn::Errors::CannotFit)
20
+ end
15
21
  end
16
22
 
17
23
  describe "when drawing text" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prawn-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregory Brown
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-03 00:00:00 -05:00
12
+ date: 2010-01-31 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15