prawn 0.3.0 → 0.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.
- data/Rakefile +3 -1
- data/data/fonts/Action Man.dfont +0 -0
- data/examples/general/measurement_units.rb +2 -2
- data/examples/graphics/image_flow.rb +2 -2
- data/examples/graphics/stroke_bounds.rb +1 -1
- data/examples/m17n/win_ansi_charset.rb +3 -3
- data/examples/text/dfont.rb +49 -0
- data/examples/text/flowing_text_with_header_and_footer.rb +2 -48
- data/examples/text/font_calculations.rb +7 -6
- data/examples/text/font_size.rb +4 -4
- data/examples/text/text_flow.rb +1 -1
- data/lib/prawn.rb +6 -3
- data/lib/prawn/compatibility.rb +12 -17
- data/lib/prawn/document.rb +10 -10
- data/lib/prawn/document/internals.rb +8 -3
- data/lib/prawn/document/text.rb +39 -57
- data/lib/prawn/document/text/box.rb +1 -2
- data/lib/prawn/document/text/wrapping.rb +59 -0
- data/lib/prawn/errors.rb +0 -8
- data/lib/prawn/font.rb +192 -277
- data/lib/prawn/font/afm.rb +199 -0
- data/lib/prawn/font/dfont.rb +31 -0
- data/lib/prawn/font/ttf.rb +318 -0
- data/lib/prawn/graphics.rb +7 -2
- data/lib/prawn/images/png.rb +1 -1
- data/lib/prawn/reference.rb +7 -4
- data/spec/font_spec.rb +154 -61
- data/spec/text_spec.rb +47 -6
- data/vendor/pdf-inspector/lib/pdf/inspector.rb +1 -1
- data/vendor/ttfunk/example.rb +42 -2
- data/vendor/ttfunk/lib/ttfunk.rb +96 -42
- data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
- data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
- data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
- data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
- data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
- data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
- data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +46 -0
- data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
- data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
- data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +51 -0
- data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
- data/vendor/ttfunk/lib/ttfunk/table.rb +37 -18
- data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +24 -84
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
- data/vendor/ttfunk/lib/ttfunk/table/head.rb +38 -19
- data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +35 -21
- data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +40 -13
- data/vendor/ttfunk/lib/ttfunk/table/kern.rb +69 -38
- data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
- data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
- data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +34 -11
- data/vendor/ttfunk/lib/ttfunk/table/name.rb +109 -42
- data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
- data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
- metadata +54 -25
- data/examples/table/addressbook.csv +0 -6
- data/examples/table/cell.rb +0 -40
- data/examples/table/currency.csv +0 -1834
- data/examples/table/fancy_table.rb +0 -62
- data/examples/table/ruport_formatter.rb +0 -53
- data/examples/table/table.rb +0 -51
- data/examples/table/table_alignment.rb +0 -18
- data/examples/table/table_border_color.rb +0 -17
- data/examples/table/table_colspan.rb +0 -19
- data/examples/table/table_header_color.rb +0 -19
- data/examples/table/table_header_underline.rb +0 -15
- data/lib/prawn/document/table.rb +0 -338
- data/lib/prawn/font/cmap.rb +0 -59
- data/lib/prawn/font/metrics.rb +0 -378
- data/lib/prawn/font/wrapping.rb +0 -47
- data/lib/prawn/graphics/cell.rb +0 -264
- data/spec/metrics_spec.rb +0 -62
- data/spec/table_spec.rb +0 -179
- data/vendor/ttfunk/lib/ttfunk/table/directory.rb +0 -25
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Glyf
|
6
|
+
class Compound
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
ARG_1_AND_2_ARE_WORDS = 0x0001
|
10
|
+
WE_HAVE_A_SCALE = 0x0008
|
11
|
+
MORE_COMPONENTS = 0x0020
|
12
|
+
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040
|
13
|
+
WE_HAVE_A_TWO_BY_TWO = 0x0080
|
14
|
+
WE_HAVE_INSTRUCTIONS = 0x0100
|
15
|
+
|
16
|
+
attr_reader :raw
|
17
|
+
attr_reader :x_min, :y_min, :x_max, :y_max
|
18
|
+
attr_reader :glyph_ids
|
19
|
+
|
20
|
+
Component = Struct.new(:flags, :glyph_index, :arg1, :arg2, :transform)
|
21
|
+
|
22
|
+
def initialize(raw, x_min, y_min, x_max, y_max)
|
23
|
+
@raw = raw
|
24
|
+
@x_min, @y_min, @x_max, @y_max = x_min, y_min, x_max, y_max
|
25
|
+
|
26
|
+
# Because TTFunk only cares about glyphs insofar as they (1) provide
|
27
|
+
# a bounding box for each glyph, and (2) can be rewritten into a
|
28
|
+
# font subset, we don't really care about the rest of the glyph data
|
29
|
+
# except as a whole. Thus, we don't actually decompose the glyph
|
30
|
+
# into it's parts--all we really care about are the locations within
|
31
|
+
# the raw string where the component glyph ids are stored, so that
|
32
|
+
# when we rewrite this glyph into a subset we can rewrite the
|
33
|
+
# component glyph-ids so they are correct for the subset.
|
34
|
+
|
35
|
+
@glyph_ids = []
|
36
|
+
@glyph_id_offsets = []
|
37
|
+
offset = 10 # 2 bytes for each of num-contours, min x/y, max x/y
|
38
|
+
|
39
|
+
loop do
|
40
|
+
flags, glyph_id = @raw[offset, 4].unpack("n*")
|
41
|
+
@glyph_ids << glyph_id
|
42
|
+
@glyph_id_offsets << offset + 2
|
43
|
+
|
44
|
+
break unless flags & MORE_COMPONENTS != 0
|
45
|
+
offset += 4
|
46
|
+
|
47
|
+
if flags & ARG_1_AND_2_ARE_WORDS != 0
|
48
|
+
offset += 4
|
49
|
+
else
|
50
|
+
offset += 2
|
51
|
+
end
|
52
|
+
|
53
|
+
if flags & WE_HAVE_A_TWO_BY_TWO != 0
|
54
|
+
offset += 8
|
55
|
+
elsif flags & WE_HAVE_AN_X_AND_Y_SCALE != 0
|
56
|
+
offset += 4
|
57
|
+
elsif flags & WE_HAVE_A_SCALE != 0
|
58
|
+
offset += 2
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def compound?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def recode(mapping)
|
68
|
+
result = @raw.dup
|
69
|
+
new_ids = glyph_ids.map { |id| mapping[id] }
|
70
|
+
|
71
|
+
new_ids.zip(@glyph_id_offsets).each do |new_id, offset|
|
72
|
+
result[offset, 2] = [new_id].pack("n")
|
73
|
+
end
|
74
|
+
|
75
|
+
return result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Glyf
|
6
|
+
class Simple
|
7
|
+
attr_reader :raw
|
8
|
+
attr_reader :number_of_contours
|
9
|
+
attr_reader :x_min, :y_min, :x_max, :y_max
|
10
|
+
|
11
|
+
def initialize(raw, number_of_contours, x_min, y_min, x_max, y_max)
|
12
|
+
@raw = raw
|
13
|
+
@number_of_contours = number_of_contours
|
14
|
+
@x_min, @y_min = x_min, y_min
|
15
|
+
@x_max, @y_max = x_max, y_max
|
16
|
+
|
17
|
+
# Because TTFunk is, at this time, a library for simply pulling
|
18
|
+
# metrics out of font files, or for writing font subsets, we don't
|
19
|
+
# really care what the contours are for simple glyphs. We just
|
20
|
+
# care that we've got an entire glyph's definition. Also, a
|
21
|
+
# bounding box could be nice to know. Since we've got all that
|
22
|
+
# at this point, we don't need to worry about parsing the full
|
23
|
+
# contents of the glyph.
|
24
|
+
end
|
25
|
+
|
26
|
+
def compound?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def recode(mapping)
|
31
|
+
raw
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -1,25 +1,44 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
1
3
|
module TTFunk
|
2
4
|
class Table
|
3
5
|
class Head < TTFunk::Table
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :font_revision
|
8
|
+
attr_reader :checksum_adjustment
|
9
|
+
attr_reader :magic_number
|
10
|
+
attr_reader :flags
|
11
|
+
attr_reader :units_per_em
|
12
|
+
attr_reader :created
|
13
|
+
attr_reader :modified
|
14
|
+
attr_reader :x_min
|
15
|
+
attr_reader :y_min
|
16
|
+
attr_reader :x_max
|
17
|
+
attr_reader :y_max
|
18
|
+
attr_reader :mac_style
|
19
|
+
attr_reader :lowest_rec_ppem
|
20
|
+
attr_reader :font_direction_hint
|
21
|
+
attr_reader :index_to_loc_format
|
22
|
+
attr_reader :glyph_data_format
|
23
|
+
|
24
|
+
def self.encode(head, loca)
|
25
|
+
table = head.raw
|
26
|
+
table[8,4] = "\0\0\0\0" # set checksum adjustment to 0 initially
|
27
|
+
table[-4,2] = [loca[:type]].pack("n") # set index_to_loc_format
|
28
|
+
return table
|
22
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse!
|
34
|
+
@version, @font_revision, @check_sum_adjustment, @magic_number,
|
35
|
+
@flags, @units_per_em, @created, @modified = read(36, "N4n2q2")
|
36
|
+
|
37
|
+
@x_min, @y_min, @x_max, @y_max = read_signed(4)
|
38
|
+
|
39
|
+
@mac_style, @lowest_rec_ppem, @font_direction_hint,
|
40
|
+
@index_to_loc_format, @glyph_data_format = read(10, "n*")
|
41
|
+
end
|
23
42
|
end
|
24
43
|
end
|
25
|
-
end
|
44
|
+
end
|
@@ -1,27 +1,41 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
1
3
|
module TTFunk
|
2
4
|
class Table
|
3
5
|
class Hhea < Table
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
data = fh.read(2)
|
23
|
-
@number_of_hmetrics = data.unpack("n").first
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :ascent
|
8
|
+
attr_reader :descent
|
9
|
+
attr_reader :line_gap
|
10
|
+
attr_reader :advance_width_max
|
11
|
+
attr_reader :min_left_side_bearing
|
12
|
+
attr_reader :min_right_side_bearing
|
13
|
+
attr_reader :x_max_extent
|
14
|
+
attr_reader :carot_slope_rise
|
15
|
+
attr_reader :carot_slope_run
|
16
|
+
attr_reader :metric_data_format
|
17
|
+
attr_reader :number_of_metrics
|
18
|
+
|
19
|
+
def self.encode(hhea, hmtx)
|
20
|
+
raw = hhea.raw
|
21
|
+
raw[-2,2] = [hmtx[:number_of_metrics]].pack("n")
|
22
|
+
return raw
|
24
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse!
|
28
|
+
@version = read(4, "N").first
|
29
|
+
@ascent, @descent, @line_gap = read_signed(3)
|
30
|
+
@advance_width_max = read(2, "n").first
|
31
|
+
|
32
|
+
@min_left_side_bearing, @min_right_side_bearing, @x_max_extent,
|
33
|
+
@carot_slope_rise, @carot_slope_run, @caret_offset,
|
34
|
+
reserved, reserved, reserved, reserved,
|
35
|
+
@metric_data_format = read_signed(11)
|
36
|
+
|
37
|
+
@number_of_metrics = read(2, "n").first
|
38
|
+
end
|
25
39
|
end
|
26
40
|
end
|
27
|
-
end
|
41
|
+
end
|
@@ -1,20 +1,47 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
1
3
|
module TTFunk
|
2
4
|
class Table
|
3
5
|
class Hmtx < Table
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
attr_reader :metrics
|
7
|
+
attr_reader :left_side_bearings
|
8
|
+
attr_reader :widths
|
9
|
+
|
10
|
+
def self.encode(hmtx, mapping)
|
11
|
+
metrics = mapping.keys.sort.map do |new_id|
|
12
|
+
metric = hmtx.for(mapping[new_id])
|
13
|
+
[metric.advance_width, metric.left_side_bearing]
|
12
14
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
|
16
|
+
{ :number_of_metrics => metrics.length,
|
17
|
+
:table => metrics.flatten.pack("n*") }
|
18
|
+
end
|
19
|
+
|
20
|
+
HorizontalMetric = Struct.new(:advance_width, :left_side_bearing)
|
21
|
+
|
22
|
+
def for(glyph_id)
|
23
|
+
@metrics[glyph_id] ||
|
24
|
+
HorizontalMetric.new(@metrics.last.advance_width,
|
25
|
+
@left_side_bearings[glyph_id - @metrics.length])
|
17
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse!
|
31
|
+
@metrics = []
|
32
|
+
|
33
|
+
file.horizontal_header.number_of_metrics.times do
|
34
|
+
advance = read(2, "n").first
|
35
|
+
lsb = read_signed(1).first
|
36
|
+
@metrics.push HorizontalMetric.new(advance, lsb)
|
37
|
+
end
|
38
|
+
|
39
|
+
lsb_count = file.maximum_profile.num_glyphs - file.horizontal_header.number_of_metrics
|
40
|
+
@left_side_bearings = read_signed(lsb_count)
|
41
|
+
|
42
|
+
@widths = @metrics.map { |metric| metric.advance_width }
|
43
|
+
@widths += [@widths.last] * @left_side_bearings.length
|
44
|
+
end
|
18
45
|
end
|
19
46
|
end
|
20
|
-
end
|
47
|
+
end
|
@@ -1,48 +1,79 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
1
3
|
module TTFunk
|
2
4
|
class Table
|
3
5
|
class Kern < Table
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
version, length, coverage = fh.read(6).unpack("n3")
|
14
|
-
@table_headers[version] = { :length => length,
|
15
|
-
:coverage => coverage,
|
16
|
-
:format => coverage >> 8 }
|
17
|
-
end
|
18
|
-
|
19
|
-
generate_subtables
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :tables
|
8
|
+
|
9
|
+
def self.encode(kerning, mapping)
|
10
|
+
return nil unless kerning.exists? && kerning.tables.any?
|
11
|
+
tables = kerning.tables.map { |table| table.recode(mapping) }.compact
|
12
|
+
return nil if tables.empty?
|
13
|
+
|
14
|
+
[0, tables.length, tables.join].pack("nnA*")
|
20
15
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parse!
|
20
|
+
@version, num_tables = read(4, "n*")
|
21
|
+
@tables = []
|
22
|
+
|
23
|
+
if @version == 1 # Mac OS X fonts
|
24
|
+
@version = (@version << 16) + num_tables
|
25
|
+
num_tables = read(4, "N").first
|
26
|
+
parse_version_1_tables(num_tables)
|
27
27
|
else
|
28
|
-
|
28
|
+
parse_version_0_tables(num_tables)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
|
32
|
+
def parse_version_0_tables(num_tables)
|
33
|
+
# It looks like some MS fonts report their kerning subtable lengths
|
34
|
+
# wrong. In one case, the length was reported to be some 19366, and yet
|
35
|
+
# the table also claimed to hold 14148 pairs (each pair consisting of 6 bytes).
|
36
|
+
# You do the math!
|
37
|
+
#
|
38
|
+
# We're going to assume that the microsoft fonts hold only a single kerning
|
39
|
+
# subtable, which occupies the entire length of the kerning table. Worst
|
40
|
+
# case, we lose any other subtables that the font contains, but it's better
|
41
|
+
# than reading a truncated kerning table.
|
42
|
+
#
|
43
|
+
# And what's more, it appears to work. So.
|
44
|
+
version, length, coverage = read(6, "n*")
|
45
|
+
format = coverage >> 8
|
46
|
+
|
47
|
+
add_table format, :version => version, :length => length,
|
48
|
+
:coverage => coverage, :data => raw[10..-1],
|
49
|
+
:vertical => (coverage & 0x1 == 0),
|
50
|
+
:minimum => (coverage & 0x2 != 0),
|
51
|
+
:cross => (coverage & 0x4 != 0),
|
52
|
+
:override => (coverage & 0x8 != 0)
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_version_1_tables(num_tables)
|
56
|
+
num_tables.times do
|
57
|
+
length, coverage, tuple_index = read(8, "Nnn")
|
58
|
+
format = coverage & 0x0FF
|
59
|
+
|
60
|
+
add_table format, :length => length, :coverage => coverage,
|
61
|
+
:tuple_index => tuple_index, :data => io.read(length-8),
|
62
|
+
:vertical => (coverage & 0x8000 != 0),
|
63
|
+
:cross => (coverage & 0x4000 != 0),
|
64
|
+
:variation => (coverage & 0x2000 != 0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_table(format, attributes={})
|
69
|
+
if format == 0
|
70
|
+
@tables << Kern::Format0.new(attributes)
|
71
|
+
else
|
72
|
+
# silently ignore unsupported kerning tables
|
73
|
+
end
|
41
74
|
end
|
42
|
-
|
43
|
-
return sub_table
|
44
|
-
end
|
45
|
-
|
46
75
|
end
|
47
76
|
end
|
48
|
-
end
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'ttfunk/table/kern/format0'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Kern
|
6
|
+
class Format0
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
attr_reader :attributes
|
10
|
+
attr_reader :pairs
|
11
|
+
|
12
|
+
def initialize(attributes={})
|
13
|
+
@attributes = attributes
|
14
|
+
|
15
|
+
num_pairs, search_range, entry_selector, range_shift, *pairs =
|
16
|
+
attributes.delete(:data).unpack("n*")
|
17
|
+
|
18
|
+
@pairs = {}
|
19
|
+
num_pairs.times do |i|
|
20
|
+
break if i*3+2 > pairs.length # sanity check, in case there's a bad length somewhere
|
21
|
+
left = pairs[i*3]
|
22
|
+
right = pairs[i*3+1]
|
23
|
+
value = to_signed(pairs[i*3+2])
|
24
|
+
@pairs[[left, right]] = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def vertical?
|
29
|
+
@attributes[:vertical]
|
30
|
+
end
|
31
|
+
|
32
|
+
def horizontal?
|
33
|
+
!vertical?
|
34
|
+
end
|
35
|
+
|
36
|
+
def cross_stream?
|
37
|
+
@attributes[:cross]
|
38
|
+
end
|
39
|
+
|
40
|
+
def recode(mapping)
|
41
|
+
subset = []
|
42
|
+
pairs.each do |(left, right), value|
|
43
|
+
if mapping[left] && mapping[right]
|
44
|
+
subset << [mapping[left], mapping[right], value]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
return nil if subset.empty?
|
49
|
+
|
50
|
+
num_pairs = subset.length
|
51
|
+
search_range = 2 * 2 ** (Math.log(num_pairs) / Math.log(2)).to_i
|
52
|
+
entry_selector = (Math.log(search_range / 2) / Math.log(2)).to_i
|
53
|
+
range_shift = (2 * num_pairs) - search_range
|
54
|
+
|
55
|
+
[attributes[:version], num_pairs * 6 + 14, attributes[:coverage],
|
56
|
+
num_pairs, search_range, entry_selector, range_shift, subset].
|
57
|
+
flatten.pack("n*")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|