prawn 2.3.0 → 2.4.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +2 -31
- data/lib/prawn.rb +1 -0
- data/lib/prawn/document.rb +20 -15
- data/lib/prawn/document/bounding_box.rb +10 -2
- data/lib/prawn/document/span.rb +2 -1
- data/lib/prawn/font.rb +6 -4
- data/lib/prawn/font_metric_cache.rb +7 -6
- data/lib/prawn/fonts/afm.rb +18 -16
- data/lib/prawn/fonts/ttf.rb +55 -29
- data/lib/prawn/graphics.rb +11 -11
- data/lib/prawn/graphics/color.rb +18 -16
- data/lib/prawn/graphics/join_style.rb +1 -1
- data/lib/prawn/graphics/patterns.rb +57 -49
- data/lib/prawn/graphics/transformation.rb +3 -3
- data/lib/prawn/grid.rb +36 -1
- data/lib/prawn/images.rb +29 -27
- data/lib/prawn/images/jpg.rb +4 -1
- data/lib/prawn/images/png.rb +2 -1
- data/lib/prawn/outline.rb +6 -5
- data/lib/prawn/repeater.rb +1 -1
- data/lib/prawn/security.rb +39 -36
- data/lib/prawn/text.rb +18 -18
- data/lib/prawn/text/box.rb +10 -9
- data/lib/prawn/text/formatted/arranger.rb +38 -19
- data/lib/prawn/text/formatted/box.rb +20 -15
- data/lib/prawn/text/formatted/line_wrap.rb +18 -16
- data/lib/prawn/text/formatted/parser.rb +28 -26
- data/lib/prawn/text/formatted/wrap.rb +15 -11
- data/lib/prawn/version.rb +1 -1
- data/lib/prawn/view.rb +2 -2
- data/manual/basic_concepts/measurement.rb +1 -1
- data/manual/bounding_box/canvas.rb +3 -3
- data/manual/bounding_box/nesting.rb +1 -1
- data/manual/document_and_page_options/background.rb +6 -2
- data/manual/document_and_page_options/document_and_page_options.rb +3 -3
- data/manual/document_and_page_options/print_scaling.rb +2 -1
- data/manual/graphics/common_lines.rb +1 -1
- data/manual/graphics/fill_and_stroke.rb +1 -1
- data/manual/graphics/fill_rules.rb +4 -3
- data/manual/graphics/helper.rb +11 -4
- data/manual/graphics/lines_and_curves.rb +1 -1
- data/manual/graphics/stroke_dash.rb +5 -5
- data/manual/graphics/translate.rb +2 -1
- data/manual/images/horizontal.rb +2 -2
- data/manual/images/scale.rb +3 -3
- data/manual/images/vertical.rb +6 -3
- data/manual/images/width_and_height.rb +3 -3
- data/manual/layout/content.rb +2 -2
- data/manual/outline/outline.rb +1 -1
- data/manual/security/permissions.rb +4 -2
- data/manual/security/security.rb +1 -1
- data/manual/text/alignment.rb +2 -2
- data/manual/text/column_box.rb +2 -2
- data/manual/text/font_style.rb +5 -2
- data/manual/text/formatted_callbacks.rb +17 -12
- data/manual/text/formatted_text.rb +7 -4
- data/manual/text/free_flowing_text.rb +3 -3
- data/manual/text/kerning_and_character_spacing.rb +4 -4
- data/manual/text/paragraph_indentation.rb +4 -5
- data/manual/text/rendering_and_color.rb +1 -1
- data/manual/text/right_to_left_text.rb +6 -6
- data/manual/text/rotation.rb +8 -3
- data/manual/text/text_box_extensions.rb +1 -1
- data/manual/text/text_box_overflow.rb +11 -9
- data/manual/text/win_ansi_charset.rb +9 -9
- data/prawn.gemspec +4 -10
- data/spec/prawn/document/bounding_box_spec.rb +82 -78
- data/spec/prawn/document/security_spec.rb +1 -1
- data/spec/prawn/document_span_spec.rb +14 -6
- data/spec/prawn/document_spec.rb +29 -26
- data/spec/prawn/font_spec.rb +16 -14
- data/spec/prawn/graphics_spec.rb +79 -44
- data/spec/prawn/images_spec.rb +13 -8
- data/spec/prawn/outline_spec.rb +127 -27
- data/spec/prawn/repeater_spec.rb +9 -8
- data/spec/prawn/soft_mask_spec.rb +1 -1
- data/spec/prawn/stamp_spec.rb +3 -2
- data/spec/prawn/text/box_spec.rb +57 -59
- data/spec/prawn/text/formatted/arranger_spec.rb +10 -10
- data/spec/prawn/text/formatted/box_spec.rb +8 -5
- data/spec/prawn/text/formatted/line_wrap_spec.rb +2 -1
- data/spec/prawn/text_draw_text_spec.rb +9 -8
- data/spec/prawn/text_spacing_spec.rb +2 -2
- data/spec/prawn/text_spec.rb +9 -9
- data/spec/prawn/text_with_inline_formatting_spec.rb +1 -1
- data/spec/prawn_manual_spec.rb +4 -4
- metadata +14 -98
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d64c2da1e4be48e40f4fa6fa4de35e04c75debf0119e8c59b3fba9d944c112db
|
4
|
+
data.tar.gz: 393bbdd1a5df657d5c6190d4bd10ecd7353522e714b2f60c8d9c5f70e5bc1ce9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4980639ca24796d577be790ed0f6fa85c985f1a6eb147e4c5db1df261c5d50afe8a466f06b65588b71a897e22e8d2b7b01daceed1714f6164124057154d2d28
|
7
|
+
data.tar.gz: e0fd560d4a80f2827736d599266bcb2e2fe19abedcde639520fba8bd19a2f12fe2cf0e8a60a91b87dbac4336d25c680f94b2341e5f9ce3d6d24f2e65f24e24a3
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Rakefile
CHANGED
@@ -1,23 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require '
|
5
|
-
require 'yard'
|
6
|
-
require 'rubygems/package_task'
|
7
|
-
require 'rubocop/rake_task'
|
3
|
+
GEMSPEC = File.expand_path('prawn.gemspec', __dir__)
|
4
|
+
require 'prawn/dev/tasks'
|
8
5
|
|
9
6
|
task default: %i[spec rubocop]
|
10
7
|
|
11
|
-
desc 'Run all rspec files'
|
12
|
-
RSpec::Core::RakeTask.new('spec') do |c|
|
13
|
-
c.rspec_opts = '-t ~unresolved'
|
14
|
-
end
|
15
|
-
|
16
|
-
YARD::Rake::YardocTask.new do |t|
|
17
|
-
t.options = ['--output-dir', 'doc/html']
|
18
|
-
end
|
19
|
-
task docs: :yard
|
20
|
-
|
21
8
|
desc "Generate the 'Prawn by Example' manual"
|
22
9
|
task :manual do
|
23
10
|
puts 'Building manual...'
|
@@ -26,12 +13,6 @@ task :manual do
|
|
26
13
|
puts 'The Prawn manual is available at manual.pdf. Happy Prawning!'
|
27
14
|
end
|
28
15
|
|
29
|
-
spec = Gem::Specification.load 'prawn.gemspec'
|
30
|
-
Gem::PackageTask.new(spec) do |pkg|
|
31
|
-
pkg.need_zip = true
|
32
|
-
pkg.need_tar = true
|
33
|
-
end
|
34
|
-
|
35
16
|
desc 'Run a console with Prawn loaded'
|
36
17
|
task :console do
|
37
18
|
require 'irb'
|
@@ -42,13 +23,3 @@ task :console do
|
|
42
23
|
ARGV.clear
|
43
24
|
IRB.start
|
44
25
|
end
|
45
|
-
|
46
|
-
RuboCop::RakeTask.new
|
47
|
-
|
48
|
-
task :checksum do
|
49
|
-
require 'digest/sha2'
|
50
|
-
built_gem_path = "prawn-#{Prawn::VERSION}.gem"
|
51
|
-
checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))
|
52
|
-
checksum_path = "checksums/#{built_gem_path}.sha512"
|
53
|
-
File.write(checksum_path, checksum)
|
54
|
-
end
|
data/lib/prawn.rb
CHANGED
data/lib/prawn/document.rb
CHANGED
@@ -98,6 +98,7 @@ module Prawn
|
|
98
98
|
|
99
99
|
# @private
|
100
100
|
def self.inherited(base)
|
101
|
+
super
|
101
102
|
extensions.each { |e| base.extensions << e }
|
102
103
|
end
|
103
104
|
|
@@ -570,11 +571,12 @@ module Prawn
|
|
570
571
|
opts = options.dup
|
571
572
|
start_count_at = opts.delete(:start_count_at).to_i
|
572
573
|
|
573
|
-
page_filter =
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
574
|
+
page_filter =
|
575
|
+
if opts.key?(:page_filter)
|
576
|
+
opts.delete(:page_filter)
|
577
|
+
else
|
578
|
+
:all
|
579
|
+
end
|
578
580
|
|
579
581
|
total_pages = opts.delete(:total_pages)
|
580
582
|
txtcolor = opts.delete(:color)
|
@@ -585,12 +587,13 @@ module Prawn
|
|
585
587
|
pseudopage = 0
|
586
588
|
(1..page_count).each do |p|
|
587
589
|
unless start_count
|
588
|
-
pseudopage =
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
590
|
+
pseudopage =
|
591
|
+
case start_count_at
|
592
|
+
when 0
|
593
|
+
1
|
594
|
+
else
|
595
|
+
start_count_at.to_i
|
596
|
+
end
|
594
597
|
end
|
595
598
|
if page_match?(page_filter, p)
|
596
599
|
go_to_page(p)
|
@@ -668,9 +671,9 @@ module Prawn
|
|
668
671
|
# and then restores the original values after the block has executed.
|
669
672
|
# -- I will remove the nodoc if/when this feature is a little less hacky
|
670
673
|
stored = {}
|
671
|
-
fields.each { |f| stored[f] =
|
674
|
+
fields.each { |f| stored[f] = public_send(f) }
|
672
675
|
yield
|
673
|
-
fields.each { |f|
|
676
|
+
fields.each { |f| public_send("#{f}=", stored[f]) }
|
674
677
|
end
|
675
678
|
|
676
679
|
# @group Extension API
|
@@ -737,8 +740,10 @@ module Prawn
|
|
737
740
|
|
738
741
|
# Treat :margin as CSS shorthand with 1-4 values.
|
739
742
|
positions = {
|
740
|
-
4 => [0, 1, 2, 3],
|
741
|
-
|
743
|
+
4 => [0, 1, 2, 3],
|
744
|
+
3 => [0, 1, 2, 1],
|
745
|
+
2 => [0, 1, 0, 1],
|
746
|
+
1 => [0, 0, 0, 0],
|
742
747
|
0 => []
|
743
748
|
}[margin.length]
|
744
749
|
|
@@ -173,7 +173,9 @@ module Prawn
|
|
173
173
|
init_bounding_box(block, hold_position: true) do |_|
|
174
174
|
# Canvas bbox acts like margin_box in that its parent bounds are unset.
|
175
175
|
@bounding_box = BoundingBox.new(
|
176
|
-
self,
|
176
|
+
self,
|
177
|
+
nil,
|
178
|
+
[0, page.dimensions[3]],
|
177
179
|
width: page.dimensions[2],
|
178
180
|
height: page.dimensions[3]
|
179
181
|
)
|
@@ -221,6 +223,12 @@ module Prawn
|
|
221
223
|
# is used for.
|
222
224
|
#
|
223
225
|
class BoundingBox
|
226
|
+
class NoReferenceBounds < StandardError
|
227
|
+
def initialize(message = "Can't find reference bounds: my parent is unset")
|
228
|
+
super
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
224
232
|
# @private
|
225
233
|
def initialize(document, parent, point, options = {})
|
226
234
|
unless options[:width]
|
@@ -504,7 +512,7 @@ module Prawn
|
|
504
512
|
#
|
505
513
|
def reference_bounds
|
506
514
|
if stretchy?
|
507
|
-
raise
|
515
|
+
raise NoReferenceBounds unless @parent
|
508
516
|
|
509
517
|
@parent.reference_bounds
|
510
518
|
else
|
data/lib/prawn/document/span.rb
CHANGED
data/lib/prawn/font.rb
CHANGED
@@ -318,10 +318,10 @@ module Prawn
|
|
318
318
|
return options.fetch(:format, 'ttf') if src.respond_to? :read
|
319
319
|
|
320
320
|
case src.to_s
|
321
|
-
when /\.ttf$/i
|
322
|
-
when /\.otf$/i
|
321
|
+
when /\.ttf$/i then 'ttf'
|
322
|
+
when /\.otf$/i then 'otf'
|
323
323
|
when /\.dfont$/i then 'dfont'
|
324
|
-
when /\.ttc$/i
|
324
|
+
when /\.ttc$/i then 'ttc'
|
325
325
|
else 'afm'
|
326
326
|
end
|
327
327
|
end
|
@@ -420,7 +420,7 @@ module Prawn
|
|
420
420
|
#
|
421
421
|
def eql?(other) #:nodoc:
|
422
422
|
self.class == other.class && name == other.name &&
|
423
|
-
family == other.family && size == other.
|
423
|
+
family == other.family && size == other.size
|
424
424
|
end
|
425
425
|
|
426
426
|
private
|
@@ -445,6 +445,8 @@ module Prawn
|
|
445
445
|
end
|
446
446
|
end
|
447
447
|
|
448
|
+
protected
|
449
|
+
|
448
450
|
def size
|
449
451
|
@document.font_size
|
450
452
|
end
|
@@ -22,12 +22,13 @@ module Prawn
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def width_of(string, options)
|
25
|
-
f =
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
f =
|
26
|
+
if options[:style]
|
27
|
+
# override style with :style => :bold
|
28
|
+
@document.find_font(@document.font.family, style: options[:style])
|
29
|
+
else
|
30
|
+
@document.font
|
31
|
+
end
|
31
32
|
|
32
33
|
encoded_string = f.normalize_encoding(string)
|
33
34
|
|
data/lib/prawn/fonts/afm.rb
CHANGED
@@ -31,16 +31,17 @@ module Prawn
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.metrics_path
|
34
|
-
@metrics_path ||=
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
@metrics_path ||=
|
35
|
+
if ENV['METRICS']
|
36
|
+
ENV['METRICS'].split(':')
|
37
|
+
else
|
38
|
+
[
|
39
|
+
'.', '/usr/lib/afm',
|
40
|
+
'/usr/local/lib/afm',
|
41
|
+
'/usr/openwin/lib/fonts/afm',
|
42
|
+
"#{Prawn::DATADIR}/fonts"
|
43
|
+
]
|
44
|
+
end
|
44
45
|
end
|
45
46
|
|
46
47
|
attr_reader :attributes #:nodoc:
|
@@ -88,7 +89,7 @@ module Prawn
|
|
88
89
|
|
89
90
|
if options[:kerning]
|
90
91
|
strings, numbers = kern(string).partition { |e| e.is_a?(String) }
|
91
|
-
total_kerning_offset = numbers.
|
92
|
+
total_kerning_offset = numbers.sum
|
92
93
|
(unscaled_width_of(strings.join) - total_kerning_offset) * scale
|
93
94
|
else
|
94
95
|
unscaled_width_of(string) * scale
|
@@ -176,7 +177,7 @@ module Prawn
|
|
176
177
|
rescue NoMethodError
|
177
178
|
raise Prawn::Errors::UnknownFont,
|
178
179
|
"Couldn't find the font: #{file} in any of:\n" +
|
179
|
-
|
180
|
+
self.class.metrics_path.join("\n")
|
180
181
|
end
|
181
182
|
|
182
183
|
def parse_afm(file_name)
|
@@ -220,9 +221,10 @@ module Prawn
|
|
220
221
|
|
221
222
|
# process data parsed from AFM file to build tables which
|
222
223
|
# will be used when measuring and kerning text
|
223
|
-
data[:glyph_table] =
|
224
|
-
|
225
|
-
|
224
|
+
data[:glyph_table] =
|
225
|
+
(0..255).map do |i|
|
226
|
+
data[:glyph_widths][Encoding::WinAnsi::CHARACTERS[i]].to_i
|
227
|
+
end
|
226
228
|
|
227
229
|
character_hash = Hash[
|
228
230
|
Encoding::WinAnsi::CHARACTERS.zip(
|
@@ -281,7 +283,7 @@ module Prawn
|
|
281
283
|
end
|
282
284
|
|
283
285
|
def unscaled_width_of(string)
|
284
|
-
string.bytes.
|
286
|
+
string.bytes.reduce(0) do |s, r|
|
285
287
|
s + @glyph_table[r]
|
286
288
|
end
|
287
289
|
end
|
data/lib/prawn/fonts/ttf.rb
CHANGED
@@ -14,6 +14,29 @@ module Prawn
|
|
14
14
|
module Fonts
|
15
15
|
# @private
|
16
16
|
class TTF < Font
|
17
|
+
class Error < StandardError
|
18
|
+
DEFAULT_MESSAGE = 'TTF font error'
|
19
|
+
MESSAGE_WITH_FONT = 'TTF font error in font %<font>s'
|
20
|
+
|
21
|
+
def initialize(message = DEFAULT_MESSAGE, font: nil)
|
22
|
+
if font && message == DEFAULT_MESSAGE
|
23
|
+
super format(MESSAGE_WITH_FONT, font: font)
|
24
|
+
else
|
25
|
+
super message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class NoUnicodeCMap < Error
|
31
|
+
DEFAULT_MESSAGE = 'No unicode cmap found in font'
|
32
|
+
MESSAGE_WITH_FONT = 'No unicode cmap found in font %<font>s'
|
33
|
+
end
|
34
|
+
|
35
|
+
class NoPostscriptName < Error
|
36
|
+
DEFAULT_MESSAGE = 'Can not detect a postscript name'
|
37
|
+
MESSAGE_WITH_FONT = 'Can not detect a postscript name in font %<font>s'
|
38
|
+
end
|
39
|
+
|
17
40
|
attr_reader :ttf, :subsets
|
18
41
|
|
19
42
|
def unicode?
|
@@ -41,15 +64,15 @@ module Prawn
|
|
41
64
|
def compute_width_of(string, options = {}) #:nodoc:
|
42
65
|
scale = (options[:size] || size) / 1000.0
|
43
66
|
if options[:kerning]
|
44
|
-
kern(string).
|
67
|
+
kern(string).reduce(0) do |s, r|
|
45
68
|
if r.is_a?(Numeric)
|
46
69
|
s - r
|
47
70
|
else
|
48
|
-
r.
|
71
|
+
r.reduce(s) { |a, e| a + character_width_by_code(e) }
|
49
72
|
end
|
50
73
|
end * scale
|
51
74
|
else
|
52
|
-
string.codepoints.
|
75
|
+
string.codepoints.reduce(0) do |s, r|
|
53
76
|
s + character_width_by_code(r)
|
54
77
|
end * scale
|
55
78
|
end
|
@@ -82,7 +105,7 @@ module Prawn
|
|
82
105
|
|
83
106
|
if options[:kerning]
|
84
107
|
last_subset = nil
|
85
|
-
kern(text).
|
108
|
+
kern(text).reduce([]) do |result, element|
|
86
109
|
if element.is_a?(Numeric)
|
87
110
|
unless result.last[1].is_a?(Array)
|
88
111
|
result.last[1] = [result.last[1]]
|
@@ -136,10 +159,11 @@ module Prawn
|
|
136
159
|
end
|
137
160
|
|
138
161
|
def cap_height
|
139
|
-
@cap_height ||=
|
140
|
-
|
141
|
-
|
142
|
-
|
162
|
+
@cap_height ||=
|
163
|
+
begin
|
164
|
+
height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
|
165
|
+
height.zero? ? @ascender : height
|
166
|
+
end
|
143
167
|
end
|
144
168
|
|
145
169
|
def x_height
|
@@ -161,23 +185,24 @@ module Prawn
|
|
161
185
|
end
|
162
186
|
|
163
187
|
def pdf_flags
|
164
|
-
@pdf_flags ||=
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
188
|
+
@pdf_flags ||=
|
189
|
+
begin
|
190
|
+
flags = 0
|
191
|
+
flags |= 0x0001 if @ttf.postscript.fixed_pitch?
|
192
|
+
flags |= 0x0002 if serif?
|
193
|
+
flags |= 0x0008 if script?
|
194
|
+
flags |= 0x0040 if italic_angle != 0
|
195
|
+
# Assume the font contains at least some non-latin characters
|
196
|
+
flags | 0x0004
|
197
|
+
end
|
173
198
|
end
|
174
199
|
|
175
200
|
def normalize_encoding(text)
|
176
201
|
text.encode(::Encoding::UTF_8)
|
177
202
|
rescue StandardError => e
|
178
203
|
puts e
|
179
|
-
raise Prawn::Errors::IncompatibleStringEncoding,
|
180
|
-
"#{text.encoding} can not be transparently converted to UTF-8. " \
|
204
|
+
raise Prawn::Errors::IncompatibleStringEncoding,
|
205
|
+
"Encoding #{text.encoding} can not be transparently converted to UTF-8. " \
|
181
206
|
'Please ensure the encoding of the string you are attempting ' \
|
182
207
|
'to use is set correctly'
|
183
208
|
end
|
@@ -200,7 +225,7 @@ module Prawn
|
|
200
225
|
private
|
201
226
|
|
202
227
|
def cmap
|
203
|
-
(@cmap ||= @ttf.cmap.unicode.first) || raise(
|
228
|
+
(@cmap ||= @ttf.cmap.unicode.first) || raise(NoUnicodeCMap.new(font: name))
|
204
229
|
end
|
205
230
|
|
206
231
|
# +string+ must be UTF8-encoded.
|
@@ -275,7 +300,7 @@ module Prawn
|
|
275
300
|
# if their font name is more than 33 bytes long. Strange. But true.
|
276
301
|
basename = font.name.postscript_name[0, 33].delete("\0")
|
277
302
|
|
278
|
-
raise
|
303
|
+
raise NoPostscriptName.new(font: font) if basename.nil?
|
279
304
|
|
280
305
|
fontfile = @document.ref!(Length1: font_content.size)
|
281
306
|
fontfile.stream << font_content
|
@@ -313,7 +338,7 @@ module Prawn
|
|
313
338
|
map = @subsets[subset].to_unicode_map
|
314
339
|
|
315
340
|
ranges = [[]]
|
316
|
-
map.keys.sort.
|
341
|
+
map.keys.sort.reduce('') do |_s, code|
|
317
342
|
ranges << [] if ranges.last.length >= 100
|
318
343
|
unicode = map[code]
|
319
344
|
ranges.last << format(
|
@@ -323,13 +348,14 @@ module Prawn
|
|
323
348
|
)
|
324
349
|
end
|
325
350
|
|
326
|
-
range_blocks =
|
327
|
-
s
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
351
|
+
range_blocks =
|
352
|
+
ranges.reduce(+'') do |s, list|
|
353
|
+
s << format(
|
354
|
+
"%<lenght>d beginbfchar\n%<list>s\nendbfchar\n",
|
355
|
+
lenght: list.length,
|
356
|
+
list: list.join("\n")
|
357
|
+
)
|
358
|
+
end
|
333
359
|
|
334
360
|
to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
|
335
361
|
|