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
|
@@ -73,58 +73,75 @@ describe HexaPDF::Font::TrueTypeWrapper do
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
76
|
+
describe "creates the necessary PDF dictionaries" do
|
|
77
|
+
it "with fonts that are subset" do
|
|
78
|
+
@font_wrapper.encode(@font_wrapper.glyph(3))
|
|
79
|
+
glyph = @font_wrapper.decode_utf8('H').first
|
|
80
|
+
@font_wrapper.encode(glyph)
|
|
81
|
+
@doc.dispatch_message(:complete_objects)
|
|
82
|
+
|
|
83
|
+
dict = @font_wrapper.dict
|
|
84
|
+
|
|
85
|
+
# Checking Type 0 font dictionary
|
|
86
|
+
assert_equal(:Font, dict[:Type])
|
|
87
|
+
assert_equal(:Type0, dict[:Subtype])
|
|
88
|
+
assert_equal(:'Identity-H', dict[:Encoding])
|
|
89
|
+
assert_equal(1, dict[:DescendantFonts].length)
|
|
90
|
+
assert_equal(dict[:BaseFont], dict[:DescendantFonts][0][:BaseFont])
|
|
91
|
+
assert_equal(HexaPDF::Font::CMap.create_to_unicode_cmap([[1, ' '.ord], [2, 'H'.ord]]),
|
|
92
|
+
dict[:ToUnicode].stream)
|
|
93
|
+
assert_match(/\A[A-Z]{6}\+Ubuntu-Title\z/, dict[:BaseFont])
|
|
94
|
+
|
|
95
|
+
# Checking CIDFont dictionary
|
|
96
|
+
cidfont = dict[:DescendantFonts][0]
|
|
97
|
+
assert_equal(:Font, cidfont[:Type])
|
|
98
|
+
assert_equal(:CIDFontType2, cidfont[:Subtype])
|
|
99
|
+
assert_equal({Registry: "Adobe", Ordering: "Identity", Supplement: 0}, cidfont[:CIDSystemInfo])
|
|
100
|
+
assert_equal(:Identity, cidfont[:CIDToGIDMap])
|
|
101
|
+
assert_equal(@font_wrapper.glyph(3).width, cidfont[:DW])
|
|
102
|
+
assert_equal([2, [glyph.width]], cidfont[:W])
|
|
103
|
+
assert(cidfont.validate)
|
|
104
|
+
|
|
105
|
+
# Checking font descriptor
|
|
106
|
+
fd = cidfont[:FontDescriptor]
|
|
107
|
+
assert_equal(dict[:BaseFont], fd[:FontName])
|
|
108
|
+
assert(fd.flagged?(:symbolic))
|
|
109
|
+
assert(fd.key?(:FontFile2))
|
|
110
|
+
assert(fd.validate)
|
|
111
|
+
|
|
112
|
+
# Two special cases for determining cap height and x-height
|
|
113
|
+
@cmap.stub(:[], nil) do
|
|
114
|
+
@font[:'OS/2'].typo_ascender = 1000
|
|
115
|
+
font_wrapper = HexaPDF::Font::TrueTypeWrapper.new(@doc, @font)
|
|
116
|
+
font_wrapper.encode(glyph)
|
|
117
|
+
fd = font_wrapper.dict[:DescendantFonts][0][:FontDescriptor]
|
|
118
|
+
assert_equal(800, fd[:CapHeight])
|
|
119
|
+
assert_equal(500, fd[:XHeight])
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
@font[:'OS/2'].version = 2
|
|
123
|
+
@font[:'OS/2'].x_height = 500 * @font[:head].units_per_em / 1000
|
|
124
|
+
@font[:'OS/2'].cap_height = 1000 * @font[:head].units_per_em / 1000
|
|
113
125
|
font_wrapper = HexaPDF::Font::TrueTypeWrapper.new(@doc, @font)
|
|
114
126
|
font_wrapper.encode(glyph)
|
|
115
127
|
fd = font_wrapper.dict[:DescendantFonts][0][:FontDescriptor]
|
|
116
|
-
assert_equal(
|
|
128
|
+
assert_equal(1000, fd[:CapHeight])
|
|
117
129
|
assert_equal(500, fd[:XHeight])
|
|
118
130
|
end
|
|
119
131
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
it "with fonts that are not subset (only differences to other case)" do
|
|
133
|
+
@font_wrapper = HexaPDF::Font::TrueTypeWrapper.new(@doc, @font, subset: false)
|
|
134
|
+
@font_wrapper.encode(@font_wrapper.glyph(3))
|
|
135
|
+
glyph = @font_wrapper.decode_utf8('H').first
|
|
136
|
+
@font_wrapper.encode(glyph)
|
|
137
|
+
@doc.dispatch_message(:complete_objects)
|
|
138
|
+
|
|
139
|
+
dict = @font_wrapper.dict
|
|
140
|
+
|
|
141
|
+
assert_equal(HexaPDF::Font::CMap.create_to_unicode_cmap([[3, ' '.ord], [glyph.id, 'H'.ord]]),
|
|
142
|
+
dict[:ToUnicode].stream)
|
|
143
|
+
assert_equal([glyph.id, [glyph.width]], dict[:DescendantFonts][0][:W])
|
|
144
|
+
end
|
|
128
145
|
end
|
|
129
146
|
|
|
130
147
|
describe "font file embedding" do
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'test_helper'
|
|
5
|
+
require 'hexapdf/font/true_type'
|
|
6
|
+
require 'hexapdf/font/true_type/builder'
|
|
7
|
+
|
|
8
|
+
describe HexaPDF::Font::TrueType::Builder do
|
|
9
|
+
before do
|
|
10
|
+
font_file = File.join(TEST_DATA_DIR, "fonts", "Ubuntu-Title.ttf")
|
|
11
|
+
@font = HexaPDF::Font::TrueType::Font.new(File.open(font_file))
|
|
12
|
+
@subsetter = HexaPDF::Font::TrueType::Subsetter.new(@font)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after do
|
|
16
|
+
@font.io.close
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "builds the font file" do
|
|
20
|
+
tables = {
|
|
21
|
+
"head" => @font[:head].raw_data,
|
|
22
|
+
"glyf" => @font[:glyf].raw_data,
|
|
23
|
+
"loca" => @font[:loca].raw_data,
|
|
24
|
+
"maxp" => @font[:maxp].raw_data,
|
|
25
|
+
}
|
|
26
|
+
font_data = HexaPDF::Font::TrueType::Builder.build(tables)
|
|
27
|
+
built_font = HexaPDF::Font::TrueType::Font.new(StringIO.new(font_data))
|
|
28
|
+
|
|
29
|
+
assert(built_font[:head].checksum_valid?)
|
|
30
|
+
assert_equal(@font[:glyf].raw_data, built_font[:glyf].raw_data)
|
|
31
|
+
assert(built_font[:glyf].checksum_valid?)
|
|
32
|
+
assert_equal(@font[:loca].raw_data, built_font[:loca].raw_data)
|
|
33
|
+
assert(built_font[:loca].checksum_valid?)
|
|
34
|
+
assert_equal(@font[:maxp].raw_data, built_font[:maxp].raw_data)
|
|
35
|
+
assert(built_font[:maxp].checksum_valid?)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'test_helper'
|
|
5
|
+
require 'hexapdf/font/true_type'
|
|
6
|
+
|
|
7
|
+
describe HexaPDF::Font::TrueType::Optimizer do
|
|
8
|
+
before do
|
|
9
|
+
font_file = File.join(TEST_DATA_DIR, "fonts", "Ubuntu-Title.ttf")
|
|
10
|
+
@font = HexaPDF::Font::TrueType::Font.new(File.open(font_file))
|
|
11
|
+
@subsetter = HexaPDF::Font::TrueType::Subsetter.new(@font)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
after do
|
|
15
|
+
@font.io.close
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "build_for_pdf" do
|
|
19
|
+
it "builds a font file that is optimized for use with PDFs" do
|
|
20
|
+
font_data = HexaPDF::Font::TrueType::Optimizer.build_for_pdf(@font)
|
|
21
|
+
built_font = HexaPDF::Font::TrueType::Font.new(StringIO.new(font_data))
|
|
22
|
+
%I(FFTM GDEF GPOS GSUB name post).each do |table|
|
|
23
|
+
refute(built_font[table])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -21,24 +21,17 @@ describe HexaPDF::Font::TrueType::Subsetter do
|
|
|
21
21
|
assert_equal(1, @subsetter.use_glyph(5))
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
it "returns the subset glyph ID for already subset glyphs" do
|
|
25
|
+
assert_nil(@subsetter.subset_glyph_id(5))
|
|
26
|
+
value = @subsetter.use_glyph(5)
|
|
27
|
+
assert_equal(value, @subsetter.subset_glyph_id(5))
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
it "creates the subset font file" do
|
|
25
31
|
gid = @font[:cmap].preferred_table[0x41]
|
|
26
32
|
@subsetter.use_glyph(gid)
|
|
27
33
|
subset = HexaPDF::Font::TrueType::Font.new(StringIO.new(@subsetter.build_font))
|
|
28
34
|
|
|
29
|
-
assert(subset[:head])
|
|
30
|
-
assert(subset[:head].checksum_valid?)
|
|
31
|
-
assert(subset[:hhea])
|
|
32
|
-
assert(subset[:hhea].checksum_valid?)
|
|
33
|
-
assert(subset[:glyf])
|
|
34
|
-
assert(subset[:glyf].checksum_valid?)
|
|
35
|
-
assert(subset[:loca])
|
|
36
|
-
assert(subset[:loca].checksum_valid?)
|
|
37
|
-
assert(subset[:maxp])
|
|
38
|
-
assert(subset[:maxp].checksum_valid?)
|
|
39
|
-
assert(subset[:hmtx])
|
|
40
|
-
assert(subset[:hmtx].checksum_valid?)
|
|
41
|
-
|
|
42
35
|
assert(Time.now - subset[:head].modified < 10)
|
|
43
36
|
assert_equal(2, subset[:maxp].num_glyphs)
|
|
44
37
|
assert_equal(2, subset[:hhea].num_of_long_hor_metrics)
|
|
@@ -60,19 +60,24 @@ describe HexaPDF::Configuration do
|
|
|
60
60
|
assert_equal(HexaPDF, @config.constantize('test', 1))
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
def assert_constantize_error # :nodoc:
|
|
64
|
+
exp = assert_raises(HexaPDF::Error) { yield }
|
|
65
|
+
assert_match(/Error getting constant for configuration option/, exp.message)
|
|
65
66
|
end
|
|
66
67
|
|
|
67
|
-
it "
|
|
68
|
+
it "raises an error for an unknown option" do
|
|
69
|
+
assert_constantize_error { @config.constantize('unknown') }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "raises an error for an unknown constant" do
|
|
68
73
|
@config['test'] = 'SomeUnknownConstant'
|
|
69
|
-
|
|
74
|
+
assert_constantize_error { @config.constantize('test') }
|
|
70
75
|
end
|
|
71
76
|
|
|
72
|
-
it "
|
|
77
|
+
it "raises an error for an unknown constant using a nested option" do
|
|
73
78
|
@config['test'] = {}
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
assert_constantize_error { @config.constantize('test', 'test') }
|
|
80
|
+
assert_constantize_error { @config.constantize('test', nil) }
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
it "returns the result of the given block when no constant is found" do
|
|
@@ -564,4 +564,28 @@ EOF
|
|
|
564
564
|
assert_equal([[:callable, [:arg]], [:block, [:arg]]], args)
|
|
565
565
|
end
|
|
566
566
|
end
|
|
567
|
+
|
|
568
|
+
describe "caching interface" do
|
|
569
|
+
it "allows setting and retrieving values" do
|
|
570
|
+
assert_equal(:test, @doc.cache(:a, :b, :test))
|
|
571
|
+
assert_equal(:test, @doc.cache(:a, :b, :other))
|
|
572
|
+
assert_equal(:other, @doc.cache(:a, :c) { :other })
|
|
573
|
+
assert(@doc.cached?(:a, :b))
|
|
574
|
+
assert(@doc.cached?(:a, :c))
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
it "allows clearing cached values" do
|
|
578
|
+
@doc.cache(:a, :b, :c)
|
|
579
|
+
@doc.cache(:b, :c, :d)
|
|
580
|
+
@doc.clear_cache(:a)
|
|
581
|
+
refute(@doc.cached?(:a, :b))
|
|
582
|
+
assert(@doc.cached?(:b, :c))
|
|
583
|
+
@doc.clear_cache
|
|
584
|
+
refute(@doc.cached?(:a, :c))
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
it "fails if no cached value exists and neither a value nor a block is given" do
|
|
588
|
+
assert_raises(LocalJumpError) { @doc.cache(:a, :b) }
|
|
589
|
+
end
|
|
590
|
+
end
|
|
567
591
|
end
|
|
@@ -8,7 +8,8 @@ describe HexaPDF::Importer do
|
|
|
8
8
|
before do
|
|
9
9
|
@source = HexaPDF::Document.new
|
|
10
10
|
obj = @source.add("test")
|
|
11
|
-
@
|
|
11
|
+
@hash = @source.wrap(key: "value")
|
|
12
|
+
@obj = @source.add(hash: @hash, array: ["one", "two"],
|
|
12
13
|
ref: HexaPDF::Reference.new(obj.oid, obj.gen),
|
|
13
14
|
others: [:symbol, 5, 5.5, nil, true, false])
|
|
14
15
|
@source.pages.add
|
|
@@ -24,6 +25,13 @@ describe HexaPDF::Importer do
|
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
describe "import" do
|
|
28
|
+
it "updates the associated document" do
|
|
29
|
+
obj = @importer.import(@obj)
|
|
30
|
+
assert_same(obj.document, @dest)
|
|
31
|
+
obj = @importer.import(@hash)
|
|
32
|
+
assert_same(obj.document, @dest)
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
it "imports an object only once" do
|
|
28
36
|
obj = @importer.import(@obj)
|
|
29
37
|
assert_same(obj, @importer.import(@obj))
|
data/test/hexapdf/test_writer.rb
CHANGED
|
@@ -40,7 +40,7 @@ startxref
|
|
|
40
40
|
219
|
|
41
41
|
%%EOF
|
|
42
42
|
3 0 obj
|
|
43
|
-
<</Producer(HexaPDF version 0.
|
|
43
|
+
<</Producer(HexaPDF version 0.4.0)>>
|
|
44
44
|
endobj
|
|
45
45
|
xref
|
|
46
46
|
3 1
|
|
@@ -72,7 +72,7 @@ startxref
|
|
|
72
72
|
141
|
|
73
73
|
%%EOF
|
|
74
74
|
6 0 obj
|
|
75
|
-
<</Producer(HexaPDF version 0.
|
|
75
|
+
<</Producer(HexaPDF version 0.4.0)>>
|
|
76
76
|
endobj
|
|
77
77
|
2 0 obj
|
|
78
78
|
<</Length 10>>stream
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'hexapdf/document'
|
|
5
|
+
require 'hexapdf/type/cid_font'
|
|
6
|
+
|
|
7
|
+
describe HexaPDF::Type::CIDFont do
|
|
8
|
+
before do
|
|
9
|
+
@doc = HexaPDF::Document.new
|
|
10
|
+
@font = @doc.wrap(Type: :Font, Subtype: :CIDFontType2, W: [1, 2, 3], DW: 100,
|
|
11
|
+
CIDSystemInfo: {Registry: 'Adobe', Ordering: 'Japan1', Supplement: 1})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "width" do
|
|
15
|
+
before do
|
|
16
|
+
@font[:W] = [1, [1], 2, [2, 3, 4], 5, 6, 10, 20, [20, 21], 30, 32, 40]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "returns the glyph width for a CID defined via the /W array" do
|
|
20
|
+
assert_equal(1, @font.width(1))
|
|
21
|
+
assert_equal(2, @font.width(2))
|
|
22
|
+
assert_equal(3, @font.width(3))
|
|
23
|
+
assert_equal(4, @font.width(4))
|
|
24
|
+
assert_equal(10, @font.width(5))
|
|
25
|
+
assert_equal(10, @font.width(6))
|
|
26
|
+
assert_equal(20, @font.width(20))
|
|
27
|
+
assert_equal(21, @font.width(21))
|
|
28
|
+
assert_equal(40, @font.width(32))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "returns the /DW value for CIDs not in the /W array" do
|
|
32
|
+
assert_equal(100, @font.width(100))
|
|
33
|
+
@font.delete(:DW)
|
|
34
|
+
assert_equal(1000, @font.width(100))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "set_widths" do
|
|
39
|
+
it "allows setting the widths" do
|
|
40
|
+
@font.set_widths([[1, 1], [2, 2], [4, 4], [5, 5], [7, 7.1]], default_width: 5.1)
|
|
41
|
+
assert_equal(5, @font[:DW])
|
|
42
|
+
assert_equal([1, [1, 2], 4, [4, 5], 7, [7]], @font[:W])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "handles an empty widths array correctly" do
|
|
46
|
+
@font.set_widths([], default_width: 100)
|
|
47
|
+
refute(@font.key?(:W))
|
|
48
|
+
assert_equal(100, @font[:DW])
|
|
49
|
+
|
|
50
|
+
@font.set_widths([])
|
|
51
|
+
refute(@font.key?(:W))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "handles setting /DW to the default value correctly" do
|
|
55
|
+
@font.set_widths([])
|
|
56
|
+
refute(@font.key?(:DW))
|
|
57
|
+
@font.set_widths([[1, 1]])
|
|
58
|
+
refute(@font.key?(:DW))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -13,7 +13,8 @@ describe HexaPDF::Type::Font do
|
|
|
13
13
|
<22> <0042>
|
|
14
14
|
endbfchar
|
|
15
15
|
EOF
|
|
16
|
-
|
|
16
|
+
fd = @doc.add(Type: :FontDescriptor, FontBBox: [0, 1, 2, 3])
|
|
17
|
+
@font = @doc.add(Type: :Font, BaseFont: :TestFont, FontDescriptor: fd, ToUnicode: cmap)
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
it "must always be an indirect" do
|
|
@@ -24,12 +25,38 @@ describe HexaPDF::Type::Font do
|
|
|
24
25
|
it "uses the /ToUnicode CMap if it is available" do
|
|
25
26
|
assert_equal("A", @font.to_utf8(32))
|
|
26
27
|
assert_equal("B", @font.to_utf8(34))
|
|
27
|
-
|
|
28
|
+
assert_raises(HexaPDF::Error) { @font.to_utf8(0) }
|
|
28
29
|
end
|
|
29
30
|
|
|
30
|
-
it "
|
|
31
|
+
it "calls the configured proc if no /ToUnicode CMap is available" do
|
|
31
32
|
@font.delete(:ToUnicode)
|
|
32
|
-
|
|
33
|
+
assert_raises(HexaPDF::Error) { @font.to_utf8(32) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "bounding_box" do
|
|
38
|
+
it "returns the bounding box" do
|
|
39
|
+
assert_equal([0, 1, 2, 3], @font.bounding_box)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "returns nil if no bounding box information can be found" do
|
|
43
|
+
@font[:FontDescriptor].delete(:FontBBox)
|
|
44
|
+
assert_nil(@font.bounding_box)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "embedded" do
|
|
49
|
+
it "returns true if the font is embedded" do
|
|
50
|
+
refute(@font.embedded?)
|
|
51
|
+
@font[:FontDescriptor][:FontFile] = 5
|
|
52
|
+
assert(@font.embedded?)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "font_file" do
|
|
57
|
+
it "returns the stream object representing the embedded font file" do
|
|
58
|
+
@font[:FontDescriptor][:FontFile] = 5
|
|
59
|
+
assert_equal(5, @font.font_file)
|
|
33
60
|
end
|
|
34
61
|
end
|
|
35
62
|
end
|
|
@@ -112,9 +112,9 @@ describe HexaPDF::Type::FontSimple do
|
|
|
112
112
|
assert_equal(" ", @font.to_utf8(32))
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
-
it "
|
|
115
|
+
it "calls the configured proc if no correct mapping could be found" do
|
|
116
116
|
@font.delete(:ToUnicode)
|
|
117
|
-
|
|
117
|
+
assert_raises(HexaPDF::Error) { @font.to_utf8(0) }
|
|
118
118
|
end
|
|
119
119
|
end
|
|
120
120
|
|
|
@@ -141,25 +141,6 @@ describe HexaPDF::Type::FontSimple do
|
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
-
describe "bounding_box" do
|
|
145
|
-
it "returns the bounding box" do
|
|
146
|
-
assert_equal([0, 1, 2, 3], @font.bounding_box)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "returns nil if no bounding box information can be found" do
|
|
150
|
-
@font[:FontDescriptor].delete(:FontBBox)
|
|
151
|
-
assert_nil(@font.bounding_box)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
describe "embedded" do
|
|
156
|
-
it "returns true if the font is embedded" do
|
|
157
|
-
refute(@font.embedded?)
|
|
158
|
-
@font[:FontDescriptor][:FontFile] = 5
|
|
159
|
-
assert(@font.embedded?)
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
144
|
describe "symbolic?" do
|
|
164
145
|
it "return true if the font is symbolic" do
|
|
165
146
|
@font[:FontDescriptor].flag(clear_existing: true)
|
|
@@ -175,6 +156,10 @@ describe HexaPDF::Type::FontSimple do
|
|
|
175
156
|
end
|
|
176
157
|
end
|
|
177
158
|
|
|
159
|
+
it "defines word spacing as always applicable" do
|
|
160
|
+
assert(@font.word_spacing_applicable?)
|
|
161
|
+
end
|
|
162
|
+
|
|
178
163
|
describe "validation" do
|
|
179
164
|
it "validates the existence of required keys" do
|
|
180
165
|
assert(@font.validate)
|