prawn-core 0.7.1 → 0.7.2

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