hexapdf 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/CONTRIBUTERS +1 -1
- data/README.md +35 -4
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/data/hexapdf/cmap/83pv-RKSJ-H +314 -0
- data/data/hexapdf/cmap/90ms-RKSJ-H +259 -0
- data/data/hexapdf/cmap/90ms-RKSJ-V +156 -0
- data/data/hexapdf/cmap/90msp-RKSJ-H +257 -0
- data/data/hexapdf/cmap/90msp-RKSJ-V +155 -0
- data/data/hexapdf/cmap/90pv-RKSJ-H +355 -0
- data/data/hexapdf/cmap/Add-RKSJ-H +738 -0
- data/data/hexapdf/cmap/Add-RKSJ-V +135 -0
- data/data/hexapdf/cmap/Adobe-CNS1-UCS2 +18209 -0
- data/data/hexapdf/cmap/Adobe-GB1-UCS2 +14267 -0
- data/data/hexapdf/cmap/Adobe-Japan1-UCS2 +19159 -0
- data/data/hexapdf/cmap/Adobe-Korea1-UCS2 +9267 -0
- data/data/hexapdf/cmap/B5pc-H +337 -0
- data/data/hexapdf/cmap/B5pc-V +90 -0
- data/data/hexapdf/cmap/CNS-EUC-H +490 -0
- data/data/hexapdf/cmap/CNS-EUC-V +538 -0
- data/data/hexapdf/cmap/ETen-B5-H +343 -0
- data/data/hexapdf/cmap/ETen-B5-V +91 -0
- data/data/hexapdf/cmap/ETenms-B5-H +79 -0
- data/data/hexapdf/cmap/ETenms-B5-V +99 -0
- data/data/hexapdf/cmap/EUC-H +207 -0
- data/data/hexapdf/cmap/EUC-V +105 -0
- data/data/hexapdf/cmap/Ext-RKSJ-H +768 -0
- data/data/hexapdf/cmap/Ext-RKSJ-V +117 -0
- data/data/hexapdf/cmap/GB-EUC-H +173 -0
- data/data/hexapdf/cmap/GB-EUC-V +98 -0
- data/data/hexapdf/cmap/GBK-EUC-H +4273 -0
- data/data/hexapdf/cmap/GBK-EUC-V +97 -0
- data/data/hexapdf/cmap/GBK2K-H +5325 -0
- data/data/hexapdf/cmap/GBK2K-V +118 -0
- data/data/hexapdf/cmap/GBKp-EUC-H +4272 -0
- data/data/hexapdf/cmap/GBKp-EUC-V +97 -0
- data/data/hexapdf/cmap/GBpc-EUC-H +175 -0
- data/data/hexapdf/cmap/GBpc-EUC-V +98 -0
- data/data/hexapdf/cmap/H +200 -0
- data/data/hexapdf/cmap/HKscs-B5-H +1331 -0
- data/data/hexapdf/cmap/HKscs-B5-V +90 -0
- data/data/hexapdf/cmap/Identity-H +339 -0
- data/data/hexapdf/cmap/Identity-V +73 -0
- data/data/hexapdf/cmap/KSC-EUC-H +562 -0
- data/data/hexapdf/cmap/KSC-EUC-V +94 -0
- data/data/hexapdf/cmap/KSCms-UHC-H +776 -0
- data/data/hexapdf/cmap/KSCms-UHC-HW-H +775 -0
- data/data/hexapdf/cmap/KSCms-UHC-HW-V +93 -0
- data/data/hexapdf/cmap/KSCms-UHC-V +94 -0
- data/data/hexapdf/cmap/KSCpc-EUC-H +608 -0
- data/data/hexapdf/cmap/LICENSE.txt +26 -0
- data/data/hexapdf/cmap/README.txt +9 -0
- data/data/hexapdf/cmap/UniCNS-UCS2-H +16992 -0
- data/data/hexapdf/cmap/UniCNS-UCS2-V +90 -0
- data/data/hexapdf/cmap/UniCNS-UTF16-H +19117 -0
- data/data/hexapdf/cmap/UniCNS-UTF16-V +94 -0
- data/data/hexapdf/cmap/UniGB-UCS2-H +14321 -0
- data/data/hexapdf/cmap/UniGB-UCS2-V +101 -0
- data/data/hexapdf/cmap/UniGB-UTF16-H +14381 -0
- data/data/hexapdf/cmap/UniGB-UTF16-V +104 -0
- data/data/hexapdf/cmap/UniJIS-UCS2-H +8870 -0
- data/data/hexapdf/cmap/UniJIS-UCS2-HW-H +81 -0
- data/data/hexapdf/cmap/UniJIS-UCS2-HW-V +279 -0
- data/data/hexapdf/cmap/UniJIS-UCS2-V +275 -0
- data/data/hexapdf/cmap/UniJIS-UTF16-H +14450 -0
- data/data/hexapdf/cmap/UniJIS-UTF16-V +299 -0
- data/data/hexapdf/cmap/UniKS-UCS2-H +8725 -0
- data/data/hexapdf/cmap/UniKS-UCS2-V +95 -0
- data/data/hexapdf/cmap/UniKS-UTF16-H +8895 -0
- data/data/hexapdf/cmap/UniKS-UTF16-V +99 -0
- data/data/hexapdf/cmap/V +105 -0
- data/examples/arc.rb +3 -3
- data/examples/merging.rb +4 -1
- data/examples/optimizing.rb +3 -0
- data/examples/show_char_bboxes.rb +2 -2
- data/examples/truetype.rb +2 -2
- data/lib/hexapdf/cli.rb +40 -1
- data/lib/hexapdf/cli/batch.rb +72 -0
- data/lib/hexapdf/cli/command.rb +112 -15
- data/lib/hexapdf/cli/files.rb +2 -2
- data/lib/hexapdf/cli/images.rb +14 -6
- data/lib/hexapdf/cli/info.rb +6 -8
- data/lib/hexapdf/cli/inspect.rb +5 -8
- data/lib/hexapdf/cli/merge.rb +13 -20
- data/lib/hexapdf/cli/modify.rb +4 -7
- data/lib/hexapdf/cli/optimize.rb +2 -5
- data/lib/hexapdf/configuration.rb +32 -3
- data/lib/hexapdf/content/canvas.rb +130 -37
- data/lib/hexapdf/content/parser.rb +40 -6
- data/lib/hexapdf/content/processor.rb +4 -4
- data/lib/hexapdf/document.rb +40 -10
- data/lib/hexapdf/document/fonts.rb +1 -0
- data/lib/hexapdf/encryption/security_handler.rb +8 -12
- data/lib/hexapdf/filter/flate_decode.rb +25 -2
- data/lib/hexapdf/font/cmap.rb +124 -8
- data/lib/hexapdf/font/cmap/parser.rb +65 -15
- data/lib/hexapdf/font/encoding/base.rb +2 -2
- data/lib/hexapdf/font/encoding/glyph_list.rb +2 -4
- data/lib/hexapdf/font/true_type.rb +1 -0
- data/lib/hexapdf/font/true_type/builder.rb +75 -0
- data/lib/hexapdf/font/true_type/optimizer.rb +65 -0
- data/lib/hexapdf/font/true_type/subsetter.rb +9 -22
- data/lib/hexapdf/font/true_type_wrapper.rb +9 -21
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +1 -1
- data/lib/hexapdf/serializer.rb +5 -3
- data/lib/hexapdf/type.rb +2 -0
- data/lib/hexapdf/type/cid_font.rb +120 -0
- data/lib/hexapdf/type/font.rb +32 -12
- data/lib/hexapdf/type/font_simple.rb +34 -42
- data/lib/hexapdf/type/font_type0.rb +148 -0
- data/lib/hexapdf/type/form.rb +4 -4
- data/lib/hexapdf/type/page.rb +12 -11
- data/lib/hexapdf/type/resources.rb +14 -0
- data/lib/hexapdf/utils/graphics_helpers.rb +77 -0
- data/lib/hexapdf/version.rb +1 -1
- data/man/man1/hexapdf.1 +43 -1
- data/test/hexapdf/content/test_canvas.rb +76 -0
- data/test/hexapdf/content/test_parser.rb +20 -1
- data/test/hexapdf/content/test_processor.rb +11 -7
- data/test/hexapdf/document/test_fonts.rb +3 -1
- data/test/hexapdf/font/cmap/test_parser.rb +42 -7
- data/test/hexapdf/font/encoding/test_base.rb +1 -1
- data/test/hexapdf/font/encoding/test_glyph_list.rb +3 -3
- data/test/hexapdf/font/test_cmap.rb +104 -0
- data/test/hexapdf/font/test_true_type_wrapper.rb +63 -46
- data/test/hexapdf/font/true_type/test_builder.rb +37 -0
- data/test/hexapdf/font/true_type/test_optimizer.rb +27 -0
- data/test/hexapdf/font/true_type/test_subsetter.rb +6 -13
- data/test/hexapdf/test_configuration.rb +12 -7
- data/test/hexapdf/test_document.rb +24 -0
- data/test/hexapdf/test_importer.rb +9 -1
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/test_cid_font.rb +61 -0
- data/test/hexapdf/type/test_font.rb +31 -4
- data/test/hexapdf/type/test_font_simple.rb +6 -21
- data/test/hexapdf/type/test_font_type0.rb +114 -0
- data/test/hexapdf/type/test_resources.rb +17 -1
- data/test/hexapdf/utils/test_graphics_helpers.rb +29 -0
- metadata +82 -3
|
@@ -61,8 +61,8 @@ module HexaPDF
|
|
|
61
61
|
@code_to_name.fetch(code, :'.notdef')
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
# Returns the Unicode value in UTF-8 for the given code, or
|
|
65
|
-
#
|
|
64
|
+
# Returns the Unicode value in UTF-8 for the given code, or +nil+ if the code cannot be
|
|
65
|
+
# mapped.
|
|
66
66
|
#
|
|
67
67
|
# Note that this method caches the result of the Unicode mapping and therefore should only
|
|
68
68
|
# be called after all codes have been defined.
|
|
@@ -71,8 +71,8 @@ module HexaPDF
|
|
|
71
71
|
load
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
# Maps the given name to a string by following the Adobe Glyph Specification.
|
|
75
|
-
#
|
|
74
|
+
# Maps the given name to a string by following the Adobe Glyph Specification. Returns +nil+
|
|
75
|
+
# if the name has no correct mapping.
|
|
76
76
|
#
|
|
77
77
|
# If this method is invoked when dealing with the ZapfDingbats font, the +zapf_dingbats+
|
|
78
78
|
# option needs to be set to +true+.
|
|
@@ -88,8 +88,6 @@ module HexaPDF
|
|
|
88
88
|
name = name.to_s
|
|
89
89
|
if name =~ /\Auni([0-9A-F]{4})\Z/ || name =~ /\Au([0-9A-f]{4,6})\Z/
|
|
90
90
|
'' << $1.hex
|
|
91
|
-
else
|
|
92
|
-
''
|
|
93
91
|
end
|
|
94
92
|
end
|
|
95
93
|
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2017 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#++
|
|
33
|
+
|
|
34
|
+
module HexaPDF
|
|
35
|
+
module Font
|
|
36
|
+
module TrueType
|
|
37
|
+
|
|
38
|
+
# Builds a TrueType font file given a hash of TrueType tables.
|
|
39
|
+
module Builder
|
|
40
|
+
|
|
41
|
+
# Returns a TrueType font file representing the given TrueType tables (a hash mapping table
|
|
42
|
+
# names (strings) to table data).
|
|
43
|
+
def self.build(tables)
|
|
44
|
+
search_range = 2**(tables.length.bit_length - 1) * 16
|
|
45
|
+
entry_selector = tables.length.bit_length - 1
|
|
46
|
+
range_shift = tables.length * 16 - search_range
|
|
47
|
+
|
|
48
|
+
font_data = "\x0\x1\x0\x0".b + \
|
|
49
|
+
[tables.length, search_range, entry_selector, range_shift].pack('n4')
|
|
50
|
+
|
|
51
|
+
offset = font_data.length + tables.length * 16
|
|
52
|
+
checksum = Table.calculate_checksum(font_data)
|
|
53
|
+
|
|
54
|
+
# prepare head table for checksumming
|
|
55
|
+
tables['head'][8, 4] = "\0\0\0\0"
|
|
56
|
+
|
|
57
|
+
tables.each do |tag, data|
|
|
58
|
+
table_checksum = Table.calculate_checksum(data)
|
|
59
|
+
# tag, offset, data.length are all 32bit uint, table_checksum for header and body
|
|
60
|
+
checksum += tag.unpack('N').first + 2 * table_checksum + offset + data.length
|
|
61
|
+
font_data << [tag, table_checksum, offset, data.length].pack('a4N3')
|
|
62
|
+
offset += data.length
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
tables['head'][8, 4] = [0xB1B0AFBA - checksum].pack('N')
|
|
66
|
+
tables.each_value {|data| font_data << data}
|
|
67
|
+
|
|
68
|
+
font_data
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2017 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#++
|
|
33
|
+
|
|
34
|
+
require 'hexapdf/font/true_type/builder'
|
|
35
|
+
|
|
36
|
+
module HexaPDF
|
|
37
|
+
module Font
|
|
38
|
+
module TrueType
|
|
39
|
+
|
|
40
|
+
# Provides methods for optimizing a TrueType font file in various ways.
|
|
41
|
+
module Optimizer
|
|
42
|
+
|
|
43
|
+
# Returns for the given font a TrueType font file as binary string that is optimized for use
|
|
44
|
+
# in a PDF (i.e. only the essential tables are retained).
|
|
45
|
+
def self.build_for_pdf(font)
|
|
46
|
+
tables = {
|
|
47
|
+
'head' => font[:head].raw_data,
|
|
48
|
+
'hhea' => font[:hhea].raw_data,
|
|
49
|
+
'maxp' => font[:maxp].raw_data,
|
|
50
|
+
'glyf' => font[:glyf].raw_data,
|
|
51
|
+
'loca' => font[:loca].raw_data,
|
|
52
|
+
'hmtx' => font[:hmtx].raw_data,
|
|
53
|
+
}
|
|
54
|
+
tables['cmap'] = font[:cmap].raw_data if font[:cmap]
|
|
55
|
+
tables['cvt '] = font[:"cvt "].raw_data if font[:"cvt "]
|
|
56
|
+
tables['fpgm'] = font[:fpgm].raw_data if font[:fpgm]
|
|
57
|
+
tables['prep'] = font[:prep].raw_data if font[:prep]
|
|
58
|
+
Builder.build(tables)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
# is created or manipulated using HexaPDF.
|
|
32
32
|
#++
|
|
33
33
|
|
|
34
|
+
require 'hexapdf/font/true_type/builder'
|
|
35
|
+
|
|
34
36
|
module HexaPDF
|
|
35
37
|
module Font
|
|
36
38
|
module TrueType
|
|
@@ -61,6 +63,12 @@ module HexaPDF
|
|
|
61
63
|
@glyph_map[glyph_id] = @last_id
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
# Returns the new subset glyph ID for the given glyph ID, or +nil+ if the glyph isn't
|
|
67
|
+
# subset.
|
|
68
|
+
def subset_glyph_id(glyph_id)
|
|
69
|
+
@glyph_map[glyph_id]
|
|
70
|
+
end
|
|
71
|
+
|
|
64
72
|
# Builds the subset font file and returns it as a binary string.
|
|
65
73
|
def build_font
|
|
66
74
|
glyf, locations = build_glyf_table
|
|
@@ -82,28 +90,7 @@ module HexaPDF
|
|
|
82
90
|
tables['fpgm'] = @font[:fpgm].raw_data if @font[:fpgm]
|
|
83
91
|
tables['prep'] = @font[:prep].raw_data if @font[:prep]
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
entry_selector = tables.length.bit_length - 1
|
|
87
|
-
range_shift = tables.length * 16 - search_range
|
|
88
|
-
|
|
89
|
-
font_data = "\x0\x1\x0\x0".b + \
|
|
90
|
-
[tables.length, search_range, entry_selector, range_shift].pack('n4')
|
|
91
|
-
|
|
92
|
-
offset = font_data.length + tables.length * 16
|
|
93
|
-
checksum = Table.calculate_checksum(font_data)
|
|
94
|
-
|
|
95
|
-
tables.each do |tag, data|
|
|
96
|
-
table_checksum = Table.calculate_checksum(data)
|
|
97
|
-
# tag, offset, data.length are all 32bit uint, table_checksum for header and body
|
|
98
|
-
checksum += tag.unpack('N').first + 2 * table_checksum + offset + data.length
|
|
99
|
-
font_data << [tag, table_checksum, offset, data.length].pack('a4N3')
|
|
100
|
-
offset += data.length
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
head[8, 4] = [0xB1B0AFBA - checksum].pack('N')
|
|
104
|
-
tables.each_value {|data| font_data << data}
|
|
105
|
-
|
|
106
|
-
font_data
|
|
93
|
+
Builder.build(tables)
|
|
107
94
|
end
|
|
108
95
|
|
|
109
96
|
private
|
|
@@ -247,34 +247,22 @@ module HexaPDF
|
|
|
247
247
|
|
|
248
248
|
# Adds the /DW and /W fields to the CIDFont dictionary.
|
|
249
249
|
def complete_width_information
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
cid_font[:W] = widths = []
|
|
256
|
-
last_id = -10
|
|
257
|
-
cur_widths = nil
|
|
258
|
-
glyphs.each do |glyph|
|
|
259
|
-
gid = glyph.id
|
|
260
|
-
if last_id + 1 != gid
|
|
261
|
-
cur_widths = []
|
|
262
|
-
widths << gid << cur_widths
|
|
263
|
-
end
|
|
264
|
-
cur_widths << glyph.width
|
|
265
|
-
last_id = gid
|
|
266
|
-
end
|
|
267
|
-
end
|
|
250
|
+
default_width = glyph(3).width.to_i
|
|
251
|
+
widths = @encoded_glyphs.keys.reject {|g| g.width == default_width}.map! do |glyph|
|
|
252
|
+
[(@subsetter ? @subsetter.subset_glyph_id(glyph.id) : glyph.id), glyph.width]
|
|
253
|
+
end.sort!
|
|
254
|
+
@dict[:DescendantFonts].first.set_widths(widths, default_width: default_width)
|
|
268
255
|
end
|
|
269
256
|
|
|
270
257
|
# Creates the /ToUnicode CMap and updates the font dictionary so that text extraction works
|
|
271
258
|
# correctly.
|
|
272
259
|
def create_to_unicode_cmap
|
|
273
260
|
stream = HexaPDF::StreamData.new do
|
|
274
|
-
mapping = @encoded_glyphs.keys.
|
|
261
|
+
mapping = @encoded_glyphs.keys.map do |glyph|
|
|
275
262
|
# Using 0xFFFD as mentioned in Adobe #5411, last line before section 1.5
|
|
276
|
-
[
|
|
277
|
-
|
|
263
|
+
[(@subsetter ? @subsetter.subset_glyph_id(glyph.id) : glyph.id),
|
|
264
|
+
@cmap.gid_to_code(glyph.id) || 0xFFFD]
|
|
265
|
+
end.sort_by(&:first)
|
|
278
266
|
HexaPDF::Font::CMap.create_to_unicode_cmap(mapping)
|
|
279
267
|
end
|
|
280
268
|
stream_obj = @document.add({}, stream: stream)
|
data/lib/hexapdf/font_loader.rb
CHANGED
|
@@ -68,7 +68,7 @@ module HexaPDF
|
|
|
68
68
|
#
|
|
69
69
|
# decode_utf8(str)::
|
|
70
70
|
# This method needs to convert the given string into an array of glyph objects. The glyph
|
|
71
|
-
# objects themselves
|
|
71
|
+
# objects themselves have to respond to \#width which should return their horizontal width.
|
|
72
72
|
#
|
|
73
73
|
# encode(glyph)::
|
|
74
74
|
# This method takes a single glyph object, that needs to be compatible with the font wrapper,
|
data/lib/hexapdf/importer.rb
CHANGED
|
@@ -116,7 +116,7 @@ module HexaPDF
|
|
|
116
116
|
@mapper[object.data] = nil
|
|
117
117
|
else
|
|
118
118
|
obj = @mapper[object.data] = object.dup
|
|
119
|
-
obj.document = @destination
|
|
119
|
+
obj.document = @destination.__getobj__
|
|
120
120
|
obj.instance_variable_set(:@data, obj.data.dup)
|
|
121
121
|
obj.data.oid = 0
|
|
122
122
|
obj.data.gen = 0
|
data/lib/hexapdf/serializer.rb
CHANGED
|
@@ -231,10 +231,12 @@ module HexaPDF
|
|
|
231
231
|
def serialize_string(obj)
|
|
232
232
|
if @encrypter && @object.kind_of?(HexaPDF::Object) && @object.indirect?
|
|
233
233
|
obj = encrypter.encrypt_string(obj, @object)
|
|
234
|
-
elsif obj.encoding != Encoding::BINARY && obj =~ /[^ -~\t\r\n]/
|
|
235
|
-
obj = "\xFE\xFF".b << obj.encode(Encoding::UTF_16BE).force_encoding(Encoding::BINARY)
|
|
236
234
|
elsif obj.encoding != Encoding::BINARY
|
|
237
|
-
obj = obj
|
|
235
|
+
obj = if obj =~ /[^ -~\t\r\n]/
|
|
236
|
+
"\xFE\xFF".b << obj.encode(Encoding::UTF_16BE).force_encoding(Encoding::BINARY)
|
|
237
|
+
else
|
|
238
|
+
obj.b
|
|
239
|
+
end
|
|
238
240
|
end
|
|
239
241
|
"(" << obj.gsub(/[\(\)\\\r]/n) {|m| STRING_ESCAPE_MAP[m]} << ")".freeze
|
|
240
242
|
end
|
data/lib/hexapdf/type.rb
CHANGED
|
@@ -61,6 +61,8 @@ module HexaPDF
|
|
|
61
61
|
autoload(:FontSimple, 'hexapdf/type/font_simple')
|
|
62
62
|
autoload(:FontType1, 'hexapdf/type/font_type1')
|
|
63
63
|
autoload(:FontTrueType, 'hexapdf/type/font_true_type')
|
|
64
|
+
autoload(:FontType0, 'hexapdf/type/font_type0')
|
|
65
|
+
autoload(:CIDFont, 'hexapdf/type/cid_font')
|
|
64
66
|
|
|
65
67
|
end
|
|
66
68
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2017 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#++
|
|
33
|
+
|
|
34
|
+
require 'hexapdf/type/font'
|
|
35
|
+
|
|
36
|
+
module HexaPDF
|
|
37
|
+
module Type
|
|
38
|
+
|
|
39
|
+
# Represents a generic CIDFont which can only be used as a descendant font of a composite PDF
|
|
40
|
+
# font.
|
|
41
|
+
#
|
|
42
|
+
# See: PDF1.7 s9.7.4
|
|
43
|
+
class CIDFont < Font
|
|
44
|
+
|
|
45
|
+
DEFAULT_WIDTH = 1000 # :nodoc:
|
|
46
|
+
|
|
47
|
+
define_field :CIDSystemInfo, type: [Hash, Dictionary], required: true
|
|
48
|
+
define_field :FontDescriptor, type: :FontDescriptor, indirect: true, required: true
|
|
49
|
+
define_field :DW, type: Integer, default: DEFAULT_WIDTH
|
|
50
|
+
define_field :W, type: Array
|
|
51
|
+
define_field :DW2, type: Array, default: [880, -1100]
|
|
52
|
+
define_field :W2, type: Array
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Returns the unscaled width of the given CID in glyph units, or 0 if the width for the CID is
|
|
56
|
+
# missing.
|
|
57
|
+
#
|
|
58
|
+
# Note that in contrast to other fonts, the argument must *not* be a code point but a CID!
|
|
59
|
+
def width(cid)
|
|
60
|
+
widths[cid] || value[:DW] || DEFAULT_WIDTH
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Sets the /W and /DW keys using the given array of [CID, width] pairs and an optional default
|
|
64
|
+
# width.
|
|
65
|
+
#
|
|
66
|
+
# See: PDF1.7 s9.7.4.3
|
|
67
|
+
def set_widths(widths, default_width: DEFAULT_WIDTH)
|
|
68
|
+
if widths.empty?
|
|
69
|
+
(default_width == DEFAULT_WIDTH ? delete(:DW) : self[:DW] = default_width)
|
|
70
|
+
delete(:W)
|
|
71
|
+
else
|
|
72
|
+
self[:DW] = default_width.to_i unless default_width == DEFAULT_WIDTH
|
|
73
|
+
self[:W] = w = []
|
|
74
|
+
last_cid = -10
|
|
75
|
+
cur_widths = nil
|
|
76
|
+
widths.each do |cid, width|
|
|
77
|
+
if last_cid + 1 != cid
|
|
78
|
+
cur_widths = []
|
|
79
|
+
w << cid << cur_widths
|
|
80
|
+
end
|
|
81
|
+
cur_widths << width.to_i
|
|
82
|
+
last_cid = cid
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# Returns a hash mapping CIDs to their respective width.
|
|
90
|
+
#
|
|
91
|
+
# Note that the hash is cached internally when accessed the first time.
|
|
92
|
+
#
|
|
93
|
+
# See: PDF1.7 s9.7.4.3
|
|
94
|
+
def widths
|
|
95
|
+
document.cache(@data, :widths) do
|
|
96
|
+
result = {}
|
|
97
|
+
index = 0
|
|
98
|
+
array = self[:W] || []
|
|
99
|
+
|
|
100
|
+
while index < array.size
|
|
101
|
+
entry = array[index]
|
|
102
|
+
value = array[index + 1]
|
|
103
|
+
if value.kind_of?(Array)
|
|
104
|
+
value.each_with_index {|width, i| result[entry + i] = width}
|
|
105
|
+
index += 2
|
|
106
|
+
else
|
|
107
|
+
width = array[index + 2]
|
|
108
|
+
entry.upto(value) {|cid| result[cid] = width}
|
|
109
|
+
index += 3
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
result
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|