prawn 0.13.0 → 0.14.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.
- checksums.yaml +4 -4
- data/.yardopts +9 -0
- data/Gemfile +7 -14
- data/Rakefile +5 -10
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/lib/pdf/core/document_state.rb +3 -2
- data/lib/pdf/core/graphics_state.rb +29 -8
- data/lib/pdf/core/object_store.rb +6 -15
- data/lib/pdf/core/pdf_object.rb +8 -33
- data/lib/prawn/document/bounding_box.rb +11 -0
- data/lib/prawn/document/column_box.rb +12 -4
- data/lib/prawn/document.rb +30 -42
- data/lib/prawn/encoding.rb +1 -2
- data/lib/prawn/font/afm.rb +71 -30
- data/lib/prawn/font/dfont.rb +1 -1
- data/lib/prawn/font/ttf.rb +10 -2
- data/lib/prawn/font.rb +7 -8
- data/lib/prawn/graphics.rb +8 -7
- data/lib/prawn/image_handler.rb +4 -0
- data/lib/prawn/images/jpg.rb +9 -10
- data/lib/prawn/images/png.rb +46 -118
- data/lib/prawn/images.rb +2 -7
- data/lib/prawn/layout.rb +2 -2
- data/lib/prawn/measurement_extensions.rb +1 -1
- data/lib/prawn/table/cells.rb +6 -2
- data/lib/prawn/table/column_width_calculator.rb +55 -0
- data/lib/prawn/table.rb +9 -22
- data/lib/prawn/templates.rb +75 -0
- data/lib/prawn/text/formatted/arranger.rb +1 -5
- data/lib/prawn/text/formatted/box.rb +1 -1
- data/lib/prawn/text/formatted/fragment.rb +5 -11
- data/lib/prawn/text/formatted/line_wrap.rb +4 -25
- data/lib/prawn/text/formatted/wrap.rb +1 -4
- data/lib/prawn.rb +1 -2
- data/manual/document_and_page_options/document_and_page_options.rb +2 -1
- data/manual/document_and_page_options/metadata.rb +3 -3
- data/manual/document_and_page_options/print_scaling.rb +20 -0
- data/manual/example_file.rb +2 -7
- data/manual/manual/cover.rb +3 -2
- data/manual/manual/manual.rb +1 -2
- data/prawn.gemspec +10 -6
- data/spec/bounding_box_spec.rb +12 -0
- data/spec/column_box_spec.rb +32 -0
- data/spec/document_spec.rb +5 -7
- data/spec/extensions/encoding_helpers.rb +2 -3
- data/spec/filters_spec.rb +1 -1
- data/spec/font_spec.rb +3 -2
- data/spec/formatted_text_box_spec.rb +14 -25
- data/spec/graphics_spec.rb +18 -0
- data/spec/image_handler_spec.rb +12 -0
- data/spec/images_spec.rb +2 -6
- data/spec/line_wrap_spec.rb +2 -2
- data/spec/object_store_spec.rb +6 -0
- data/spec/outline_spec.rb +10 -10
- data/spec/png_spec.rb +9 -12
- data/spec/table_spec.rb +55 -2
- data/spec/{template_spec.rb → template_spec_obsolete.rb} +2 -1
- data/spec/text_at_spec.rb +11 -26
- data/spec/text_box_spec.rb +6 -2
- data/spec/text_spec.rb +39 -27
- metadata +58 -38
- data/README.md +0 -109
- data/data/images/16bit.dat +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/lib/prawn/compatibility.rb +0 -91
- data/manual/templates/full_template.rb +0 -25
- data/manual/templates/page_template.rb +0 -48
- data/manual/templates/templates.rb +0 -27
data/lib/prawn/font.rb
CHANGED
@@ -6,10 +6,10 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
require_relative "font/afm"
|
10
|
+
require_relative "font/ttf"
|
11
|
+
require_relative "font/dfont"
|
12
|
+
require_relative "font_metric_cache"
|
13
13
|
|
14
14
|
module Prawn
|
15
15
|
|
@@ -174,10 +174,9 @@ module Prawn
|
|
174
174
|
# wish to support.
|
175
175
|
#
|
176
176
|
# By default the styles :bold, :italic, :bold_italic, and :normal are
|
177
|
-
# defined for fonts "Courier", "Times-Roman" and "Helvetica".
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# custom ones, like :thin, and use them in font calls.
|
177
|
+
# defined for fonts "Courier", "Times-Roman" and "Helvetica". When
|
178
|
+
# defining your own font families, you can map any or all of these
|
179
|
+
# styles to whatever font files you'd like.
|
181
180
|
#
|
182
181
|
def font_families
|
183
182
|
@font_families ||= {}.merge!(
|
data/lib/prawn/graphics.rb
CHANGED
@@ -6,13 +6,14 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
|
10
|
+
require_relative "graphics/color"
|
11
|
+
require_relative "graphics/dash"
|
12
|
+
require_relative "graphics/cap_style"
|
13
|
+
require_relative "graphics/join_style"
|
14
|
+
require_relative "graphics/transparency"
|
15
|
+
require_relative "graphics/transformation"
|
16
|
+
require_relative "graphics/patterns"
|
16
17
|
|
17
18
|
module Prawn
|
18
19
|
|
data/lib/prawn/image_handler.rb
CHANGED
data/lib/prawn/images/jpg.rb
CHANGED
@@ -17,8 +17,7 @@ module Prawn
|
|
17
17
|
attr_reader :width, :height, :bits, :channels
|
18
18
|
attr_accessor :scaled_width, :scaled_height
|
19
19
|
|
20
|
-
JPEG_SOF_BLOCKS =
|
21
|
-
JPEG_APP_BLOCKS = %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef)
|
20
|
+
JPEG_SOF_BLOCKS = [0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF]
|
22
21
|
|
23
22
|
def self.can_render?(image_blob)
|
24
23
|
image_blob[0, 3].unpack("C*") == [255, 216, 255]
|
@@ -29,22 +28,22 @@ module Prawn
|
|
29
28
|
# <tt>:data</tt>:: A binary string of JPEG data
|
30
29
|
#
|
31
30
|
def initialize(data)
|
32
|
-
@data = data
|
33
|
-
|
34
|
-
|
31
|
+
@data = data
|
32
|
+
d = StringIO.new(@data)
|
33
|
+
d.binmode
|
35
34
|
|
36
|
-
c_marker =
|
37
|
-
|
35
|
+
c_marker = 0xff # Section marker.
|
36
|
+
d.seek(2) # Skip the first two bytes of JPEG identifier.
|
38
37
|
loop do
|
39
|
-
marker, code, length =
|
38
|
+
marker, code, length = d.read(4).unpack('CCn')
|
40
39
|
raise "JPEG marker not found!" if marker != c_marker
|
41
40
|
|
42
41
|
if JPEG_SOF_BLOCKS.include?(code)
|
43
|
-
@bits, @height, @width, @channels =
|
42
|
+
@bits, @height, @width, @channels = d.read(6).unpack("CnnC")
|
44
43
|
break
|
45
44
|
end
|
46
45
|
|
47
|
-
|
46
|
+
d.seek(length - 2, IO::SEEK_CUR)
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
data/lib/prawn/images/png.rb
CHANGED
@@ -107,34 +107,17 @@ module Prawn
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
# number of bits used per pixel
|
111
|
-
#
|
112
|
-
def pixel_bitlength
|
113
|
-
if alpha_channel?
|
114
|
-
self.bits * (self.colors + 1)
|
115
|
-
else
|
116
|
-
self.bits * self.colors
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
110
|
# split the alpha channel data from the raw image data in images
|
121
111
|
# where it's required.
|
122
112
|
#
|
123
113
|
def split_alpha_channel!
|
124
|
-
|
114
|
+
split_image_data if alpha_channel?
|
125
115
|
end
|
126
116
|
|
127
117
|
def alpha_channel?
|
128
118
|
@color_type == 4 || @color_type == 6
|
129
119
|
end
|
130
120
|
|
131
|
-
# Adobe Reader can't handle 16-bit png channels -- chop off the second
|
132
|
-
# byte (least significant)
|
133
|
-
#
|
134
|
-
def alpha_channel_bits
|
135
|
-
8
|
136
|
-
end
|
137
|
-
|
138
121
|
# Build a PDF object representing this image in +document+, and return
|
139
122
|
# a Reference to it.
|
140
123
|
#
|
@@ -180,18 +163,14 @@ module Prawn
|
|
180
163
|
# append the actual image data to the object as a stream
|
181
164
|
obj << img_data
|
182
165
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
:
|
188
|
-
|
189
|
-
:Colors => colors,
|
190
|
-
:BitsPerComponent => bits,
|
191
|
-
:Columns => width
|
192
|
-
}
|
166
|
+
obj.stream.filters << {
|
167
|
+
:FlateDecode => {
|
168
|
+
:Predictor => 15,
|
169
|
+
:Colors => colors,
|
170
|
+
:BitsPerComponent => bits,
|
171
|
+
:Columns => width
|
193
172
|
}
|
194
|
-
|
173
|
+
}
|
195
174
|
|
196
175
|
# sort out the colours of the image
|
197
176
|
if palette.empty?
|
@@ -243,12 +222,20 @@ module Prawn
|
|
243
222
|
:Subtype => :Image,
|
244
223
|
:Height => height,
|
245
224
|
:Width => width,
|
246
|
-
:BitsPerComponent =>
|
225
|
+
:BitsPerComponent => bits,
|
247
226
|
:ColorSpace => :DeviceGray,
|
248
227
|
:Decode => [0, 1]
|
249
228
|
)
|
250
229
|
smask_obj.stream << alpha_channel
|
251
|
-
|
230
|
+
|
231
|
+
smask_obj.stream.filters << {
|
232
|
+
:FlateDecode => {
|
233
|
+
:Predictor => 15,
|
234
|
+
:Colors => 1,
|
235
|
+
:BitsPerComponent => bits,
|
236
|
+
:Columns => width
|
237
|
+
}
|
238
|
+
}
|
252
239
|
obj.data[:SMask] = smask_obj
|
253
240
|
end
|
254
241
|
|
@@ -270,99 +257,40 @@ module Prawn
|
|
270
257
|
|
271
258
|
private
|
272
259
|
|
273
|
-
def
|
274
|
-
|
260
|
+
def split_image_data
|
261
|
+
alpha_bytes = bits / 8
|
262
|
+
color_bytes = colors * bits / 8
|
275
263
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
pixel_bytes = pixel_bitlength / 8
|
280
|
-
scanline_length = pixel_bytes * self.width + 1
|
281
|
-
row = 0
|
282
|
-
pixels = []
|
283
|
-
row_data = [] # reused for each row of the image
|
284
|
-
paeth, pa, pb, pc = nil
|
285
|
-
|
286
|
-
data.bytes.each do |byte|
|
287
|
-
# accumulate a whole scanline of bytes, and then process it all at once
|
288
|
-
# we could do this with Enumerable#each_slice, but it allocates memory,
|
289
|
-
# and we are trying to avoid that
|
290
|
-
row_data << byte
|
291
|
-
next if row_data.length < scanline_length
|
292
|
-
|
293
|
-
filter = row_data.shift
|
294
|
-
case filter
|
295
|
-
when 0 # None
|
296
|
-
when 1 # Sub
|
297
|
-
row_data.each_with_index do |row_byte, index|
|
298
|
-
left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
|
299
|
-
row_data[index] = (row_byte + left) % 256
|
300
|
-
end
|
301
|
-
when 2 # Up
|
302
|
-
row_data.each_with_index do |row_byte, index|
|
303
|
-
col = (index / pixel_bytes).floor
|
304
|
-
upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
|
305
|
-
row_data[index] = (upper + row_byte) % 256
|
306
|
-
end
|
307
|
-
when 3 # Average
|
308
|
-
row_data.each_with_index do |row_byte, index|
|
309
|
-
col = (index / pixel_bytes).floor
|
310
|
-
upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
|
311
|
-
left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
|
264
|
+
scanline_length = (color_bytes + alpha_bytes) * self.width + 1
|
265
|
+
scanlines = @img_data.bytesize / scanline_length
|
266
|
+
pixels = self.width * self.height
|
312
267
|
|
313
|
-
|
314
|
-
|
315
|
-
when 4 # Paeth
|
316
|
-
left = upper = upper_left = nil
|
317
|
-
row_data.each_with_index do |row_byte, index|
|
318
|
-
col = (index / pixel_bytes).floor
|
319
|
-
|
320
|
-
left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
|
321
|
-
if row.zero?
|
322
|
-
upper = upper_left = 0
|
323
|
-
else
|
324
|
-
upper = pixels[row-1][col][index % pixel_bytes]
|
325
|
-
upper_left = col.zero? ? 0 :
|
326
|
-
pixels[row-1][col-1][index % pixel_bytes]
|
327
|
-
end
|
328
|
-
|
329
|
-
p = left + upper - upper_left
|
330
|
-
pa = (p - left).abs
|
331
|
-
pb = (p - upper).abs
|
332
|
-
pc = (p - upper_left).abs
|
333
|
-
|
334
|
-
paeth = if pa <= pb && pa <= pc
|
335
|
-
left
|
336
|
-
elsif pb <= pc
|
337
|
-
upper
|
338
|
-
else
|
339
|
-
upper_left
|
340
|
-
end
|
341
|
-
|
342
|
-
row_data[index] = (row_byte + paeth) % 256
|
343
|
-
end
|
344
|
-
else
|
345
|
-
raise ArgumentError, "Invalid filter algorithm #{filter}"
|
346
|
-
end
|
268
|
+
data = StringIO.new(@img_data)
|
269
|
+
data.binmode
|
347
270
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
end
|
271
|
+
color_data = [0x00].pack('C') * (pixels * color_bytes + scanlines)
|
272
|
+
color = StringIO.new(color_data)
|
273
|
+
color.binmode
|
274
|
+
|
275
|
+
@alpha_channel = [0x00].pack('C') * (pixels * alpha_bytes + scanlines)
|
276
|
+
alpha = StringIO.new(@alpha_channel)
|
277
|
+
alpha.binmode
|
356
278
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
279
|
+
scanlines.times do |line|
|
280
|
+
data.seek(line * scanline_length)
|
281
|
+
|
282
|
+
filter = data.getbyte
|
283
|
+
|
284
|
+
color.putc filter
|
285
|
+
alpha.putc filter
|
286
|
+
|
287
|
+
self.width.times do
|
288
|
+
color.write data.read(color_bytes)
|
289
|
+
alpha.write data.read(alpha_bytes)
|
364
290
|
end
|
365
291
|
end
|
292
|
+
|
293
|
+
@img_data = color_data
|
366
294
|
end
|
367
295
|
end
|
368
296
|
end
|
data/lib/prawn/images.rb
CHANGED
@@ -12,13 +12,8 @@ module Prawn
|
|
12
12
|
|
13
13
|
module Images
|
14
14
|
# Add the image at filename to the current page. Currently only
|
15
|
-
# JPG and PNG files are supported.
|
16
|
-
#
|
17
|
-
# NOTE: Prawn is very slow at rendering PNGs with alpha channels, and this
|
18
|
-
# uses a lot of RAM. The workaround for those who don't mind installing
|
19
|
-
# RMagick is to use:
|
20
|
-
#
|
21
|
-
# http://github.com/amberbit/prawn-fast-png
|
15
|
+
# JPG and PNG files are supported. (Note that processing PNG
|
16
|
+
# images with alpha channels can be processor and memory intensive.)
|
22
17
|
#
|
23
18
|
# Arguments:
|
24
19
|
# <tt>file</tt>:: path to file or an object that responds to #read
|
data/lib/prawn/layout.rb
CHANGED
data/lib/prawn/table/cells.rb
CHANGED
@@ -240,6 +240,9 @@ module Prawn
|
|
240
240
|
end
|
241
241
|
end
|
242
242
|
|
243
|
+
#if there are only colspanned or rowspanned cells in a table
|
244
|
+
spanned_width_needs_fixing = true
|
245
|
+
|
243
246
|
each do |cell|
|
244
247
|
index = cell.send(row_or_column)
|
245
248
|
if cell.colspan > 1
|
@@ -251,8 +254,9 @@ module Prawn
|
|
251
254
|
|
252
255
|
#calculate future return value
|
253
256
|
new_sum = cell.send(meth) * cell.colspan
|
257
|
+
spanned_width_needs_fixing = (new_sum > old_sum)
|
254
258
|
|
255
|
-
if
|
259
|
+
if spanned_width_needs_fixing
|
256
260
|
#not entirely sure why we need this line, but with it the tests pass
|
257
261
|
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
|
258
262
|
#overwrite the old values with the new ones, but only if all entries existed
|
@@ -263,7 +267,7 @@ module Prawn
|
|
263
267
|
}
|
264
268
|
end
|
265
269
|
else
|
266
|
-
if cell.class == Prawn::Table::Cell::SpanDummy
|
270
|
+
if spanned_width_needs_fixing && cell.class == Prawn::Table::Cell::SpanDummy
|
267
271
|
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
|
268
272
|
end
|
269
273
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Prawn
|
2
|
+
class Table
|
3
|
+
class ColumnWidthCalculator
|
4
|
+
def initialize(cells)
|
5
|
+
@cells = cells
|
6
|
+
|
7
|
+
@widths_by_column = Hash.new(0)
|
8
|
+
@rows_with_a_span_dummy = Hash.new(false)
|
9
|
+
end
|
10
|
+
|
11
|
+
def natural_widths
|
12
|
+
@cells.each do |cell|
|
13
|
+
@rows_with_a_span_dummy[cell.row] = true if cell.is_a?(Cell::SpanDummy)
|
14
|
+
end
|
15
|
+
|
16
|
+
#calculate natural column width for all rows that do not include a span dummy
|
17
|
+
@cells.each do |cell|
|
18
|
+
unless @rows_with_a_span_dummy[cell.row]
|
19
|
+
@widths_by_column[cell.column] =
|
20
|
+
[@widths_by_column[cell.column], cell.width.to_f].max
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#integrate natural column widths for all rows that do include a span dummy
|
25
|
+
@cells.each do |cell|
|
26
|
+
next unless @rows_with_a_span_dummy[cell.row]
|
27
|
+
#the width of a SpanDummy cell will be calculated by the "mother" cell
|
28
|
+
next if cell.is_a?(Cell::SpanDummy)
|
29
|
+
|
30
|
+
if cell.colspan == 1
|
31
|
+
@widths_by_column[cell.column] =
|
32
|
+
[@widths_by_column[cell.column], cell.width.to_f].max
|
33
|
+
else
|
34
|
+
#calculate the current with of all cells that will be spanned by the current cell
|
35
|
+
current_width_of_spanned_cells =
|
36
|
+
@widths_by_column.to_a[cell.column..(cell.column + cell.colspan - 1)]
|
37
|
+
.collect{|key, value| value}.inject(0, :+)
|
38
|
+
|
39
|
+
#update the Hash only if the new with is at least equal to the old one
|
40
|
+
if cell.width.to_f > current_width_of_spanned_cells
|
41
|
+
# Split the width of colspanned cells evenly by columns
|
42
|
+
width_per_column = cell.width.to_f / cell.colspan
|
43
|
+
# Update the Hash
|
44
|
+
cell.colspan.times do |i|
|
45
|
+
@widths_by_column[cell.column + i] = width_per_column
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
@widths_by_column.sort_by { |col, _| col }.map { |_, w| w }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/prawn/table.rb
CHANGED
@@ -6,13 +6,14 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
require_relative 'table/column_width_calculator'
|
10
|
+
require_relative 'table/cells'
|
11
|
+
require_relative 'table/cell'
|
12
|
+
require_relative 'table/cell/in_table'
|
13
|
+
require_relative 'table/cell/text'
|
14
|
+
require_relative 'table/cell/subtable'
|
15
|
+
require_relative 'table/cell/image'
|
16
|
+
require_relative 'table/cell/span_dummy'
|
16
17
|
|
17
18
|
module Prawn
|
18
19
|
|
@@ -549,21 +550,7 @@ module Prawn
|
|
549
550
|
# Returns an array of each column's natural (unconstrained) width.
|
550
551
|
#
|
551
552
|
def natural_column_widths
|
552
|
-
@natural_column_widths ||=
|
553
|
-
begin
|
554
|
-
widths_by_column = Hash.new(0)
|
555
|
-
cells.each do |cell|
|
556
|
-
next if cell.is_a?(Cell::SpanDummy)
|
557
|
-
|
558
|
-
# Split the width of colspanned cells evenly by columns
|
559
|
-
width_per_column = cell.width.to_f / cell.colspan
|
560
|
-
cell.colspan.times do |i|
|
561
|
-
widths_by_column[cell.column + i] =
|
562
|
-
[widths_by_column[cell.column + i], width_per_column].max
|
563
|
-
end
|
564
|
-
end
|
565
|
-
widths_by_column.sort_by { |col, _| col }.map { |_, w| w }
|
566
|
-
end
|
553
|
+
@natural_column_widths ||= ColumnWidthCalculator.new(cells).natural_widths
|
567
554
|
end
|
568
555
|
|
569
556
|
# Returns the "natural" (unconstrained) width of the table. This may be
|
@@ -0,0 +1,75 @@
|
|
1
|
+
warn "Templates are no longer supported in Prawn!\n" +
|
2
|
+
"This code is for experimental testing only, and\n" +
|
3
|
+
"will extracted into its own gem in a future Prawn release"
|
4
|
+
|
5
|
+
module Prawn
|
6
|
+
module Templates
|
7
|
+
def initialize_first_page(options)
|
8
|
+
return super unless options[:template]
|
9
|
+
|
10
|
+
fresh_content_streams(options)
|
11
|
+
go_to_page(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
## FIXME: This is going to be terribly brittle because
|
15
|
+
# it copy-pastes the start_new_page method. But at least
|
16
|
+
# it should only run when templates are used.
|
17
|
+
|
18
|
+
def start_new_page(options = {})
|
19
|
+
return super unless options[:template]
|
20
|
+
|
21
|
+
if last_page = state.page
|
22
|
+
last_page_size = last_page.size
|
23
|
+
last_page_layout = last_page.layout
|
24
|
+
last_page_margins = last_page.margins
|
25
|
+
end
|
26
|
+
|
27
|
+
page_options = {:size => options[:size] || last_page_size,
|
28
|
+
:layout => options[:layout] || last_page_layout,
|
29
|
+
:margins => last_page_margins}
|
30
|
+
if last_page
|
31
|
+
new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
|
32
|
+
#erase the color space so that it gets reset on new page for fussy pdf-readers
|
33
|
+
new_graphic_state.color_space = {} if new_graphic_state
|
34
|
+
page_options.merge!(:graphic_state => new_graphic_state)
|
35
|
+
end
|
36
|
+
|
37
|
+
merge_template_options(page_options, options)
|
38
|
+
|
39
|
+
state.page = PDF::Core::Page.new(self, page_options)
|
40
|
+
|
41
|
+
apply_margin_options(options)
|
42
|
+
generate_margin_box
|
43
|
+
|
44
|
+
# Reset the bounding box if the new page has different size or layout
|
45
|
+
if last_page && (last_page.size != state.page.size ||
|
46
|
+
last_page.layout != state.page.layout)
|
47
|
+
@bounding_box = @margin_box
|
48
|
+
end
|
49
|
+
|
50
|
+
state.page.new_content_stream
|
51
|
+
use_graphic_settings(true)
|
52
|
+
forget_text_rendering_mode!
|
53
|
+
|
54
|
+
unless options[:orphan]
|
55
|
+
state.insert_page(state.page, @page_number)
|
56
|
+
@page_number += 1
|
57
|
+
|
58
|
+
canvas { image(@background, :scale => @background_scale, :at => bounds.top_left) } if @background
|
59
|
+
@y = @bounding_box.absolute_top
|
60
|
+
|
61
|
+
float do
|
62
|
+
state.on_page_create_action(self)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def merge_template_options(page_options, options)
|
68
|
+
object_id = state.store.import_page(options[:template], options[:template_page] || 1)
|
69
|
+
page_options.merge!(:object_id => object_id, :page_template => true)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Prawn::Document::VALID_OPTIONS << :template
|
75
|
+
Prawn::Document.extensions << Prawn::Templates
|
@@ -52,11 +52,7 @@ module Prawn
|
|
52
52
|
raise "Lines must be finalized before calling #line"
|
53
53
|
end
|
54
54
|
@fragments.collect do |fragment|
|
55
|
-
|
56
|
-
fragment.text
|
57
|
-
else
|
58
|
-
fragment.text.dup.force_encoding("utf-8")
|
59
|
-
end
|
55
|
+
fragment.text.dup.force_encoding(::Encoding::UTF_8)
|
60
56
|
end.join
|
61
57
|
end
|
62
58
|
|
@@ -392,7 +392,7 @@ module Prawn
|
|
392
392
|
# all fonts
|
393
393
|
fallback_fonts << fragment_font
|
394
394
|
|
395
|
-
hash[:text].
|
395
|
+
hash[:text].each_char do |char|
|
396
396
|
@document.font(fragment_font)
|
397
397
|
font_glyph_pairs << [find_font_for_this_glyph(char,
|
398
398
|
@document.font.family,
|
@@ -212,11 +212,7 @@ module Prawn
|
|
212
212
|
end
|
213
213
|
case direction
|
214
214
|
when :rtl
|
215
|
-
|
216
|
-
string.scan(/./mu).reverse.join
|
217
|
-
else
|
218
|
-
string.reverse
|
219
|
-
end
|
215
|
+
string.reverse
|
220
216
|
else
|
221
217
|
string
|
222
218
|
end
|
@@ -232,11 +228,9 @@ module Prawn
|
|
232
228
|
|
233
229
|
def process_soft_hyphens(string)
|
234
230
|
if string.length > 0 && normalized_soft_hyphen
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
end
|
239
|
-
}
|
231
|
+
if string.encoding != normalized_soft_hyphen.encoding
|
232
|
+
string.force_encoding(normalized_soft_hyphen.encoding)
|
233
|
+
end
|
240
234
|
string[0..-2].gsub(normalized_soft_hyphen, "") + string[-1..-1]
|
241
235
|
else
|
242
236
|
string
|
@@ -244,7 +238,7 @@ module Prawn
|
|
244
238
|
end
|
245
239
|
|
246
240
|
def strip_zero_width_spaces(string)
|
247
|
-
if
|
241
|
+
if string.encoding == ::Encoding::UTF_8
|
248
242
|
string.gsub(Prawn::Text::ZWSP, "")
|
249
243
|
else
|
250
244
|
string
|