hexapdf 0.10.0 → 0.11.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 +33 -0
- data/CONTRIBUTERS +1 -1
- data/Rakefile +35 -50
- data/VERSION +1 -1
- data/lib/hexapdf/cli.rb +4 -0
- data/lib/hexapdf/cli/command.rb +6 -2
- data/lib/hexapdf/cli/image2pdf.rb +141 -0
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +32 -2
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +130 -0
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +7 -1
- data/lib/hexapdf/content/canvas.rb +2 -2
- data/lib/hexapdf/content/graphic_object/arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/dictionary.rb +11 -3
- data/lib/hexapdf/dictionary_fields.rb +32 -3
- data/lib/hexapdf/document.rb +7 -3
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +21 -1
- data/lib/hexapdf/document/pages.rb +2 -2
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -2
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +2 -2
- data/lib/hexapdf/font/true_type/table/os2.rb +4 -4
- data/lib/hexapdf/font/true_type_wrapper.rb +16 -16
- data/lib/hexapdf/font/type1_wrapper.rb +16 -16
- data/lib/hexapdf/font_loader.rb +2 -0
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -0
- data/lib/hexapdf/font_loader/standard14.rb +5 -0
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/layout/box.rb +2 -2
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/style.rb +50 -24
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +2 -2
- data/lib/hexapdf/layout/text_layouter.rb +14 -10
- data/lib/hexapdf/name_tree_node.rb +3 -3
- data/lib/hexapdf/number_tree_node.rb +3 -3
- data/lib/hexapdf/pdf_array.rb +207 -0
- data/lib/hexapdf/rectangle.rb +12 -12
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +6 -4
- data/lib/hexapdf/task/optimize.rb +3 -3
- data/lib/hexapdf/type.rb +2 -0
- data/lib/hexapdf/type/acro_form.rb +51 -0
- data/lib/hexapdf/type/acro_form/field.rb +129 -0
- data/lib/hexapdf/type/acro_form/form.rb +124 -0
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -0
- data/lib/hexapdf/type/annotations/link.rb +4 -15
- data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -1
- data/lib/hexapdf/type/annotations/text.rb +3 -6
- data/lib/hexapdf/type/annotations/widget.rb +90 -0
- data/lib/hexapdf/type/catalog.rb +12 -9
- data/lib/hexapdf/type/cid_font.rb +3 -3
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +5 -2
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +2 -2
- data/lib/hexapdf/type/graphics_state_parameter.rb +11 -6
- data/lib/hexapdf/type/icon_fit.rb +58 -0
- data/lib/hexapdf/type/image.rb +14 -8
- data/lib/hexapdf/type/info.rb +2 -1
- data/lib/hexapdf/type/page.rb +4 -4
- data/lib/hexapdf/type/page_tree_node.rb +3 -7
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +4 -4
- data/lib/hexapdf/type/viewer_preferences.rb +7 -4
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/man/man1/hexapdf.1 +77 -8
- data/test/hexapdf/content/test_canvas.rb +2 -2
- data/test/hexapdf/content/test_processor.rb +3 -3
- data/test/hexapdf/document/test_files.rb +4 -4
- data/test/hexapdf/document/test_fonts.rb +13 -1
- data/test/hexapdf/document/test_images.rb +6 -6
- data/test/hexapdf/document/test_pages.rb +8 -8
- data/test/hexapdf/encryption/test_security_handler.rb +7 -7
- data/test/hexapdf/encryption/test_standard_security_handler.rb +5 -5
- data/test/hexapdf/font/test_true_type_wrapper.rb +2 -2
- data/test/hexapdf/font_loader/test_from_configuration.rb +4 -0
- data/test/hexapdf/font_loader/test_standard14.rb +10 -0
- data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
- data/test/hexapdf/image_loader/test_png.rb +3 -3
- data/test/hexapdf/layout/test_box.rb +2 -2
- data/test/hexapdf/layout/test_frame.rb +1 -1
- data/test/hexapdf/layout/test_image_box.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +18 -13
- data/test/hexapdf/layout/test_text_box.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +11 -6
- data/test/hexapdf/task/test_dereference.rb +2 -2
- data/test/hexapdf/task/test_optimize.rb +11 -11
- data/test/hexapdf/test_composer.rb +1 -1
- data/test/hexapdf/test_dictionary.rb +10 -2
- data/test/hexapdf/test_dictionary_fields.rb +27 -3
- data/test/hexapdf/test_document.rb +16 -15
- data/test/hexapdf/test_importer.rb +4 -4
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_pdf_array.rb +162 -0
- data/test/hexapdf/test_rectangle.rb +3 -5
- data/test/hexapdf/test_serializer.rb +1 -1
- data/test/hexapdf/test_stream.rb +1 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_field.rb +85 -0
- data/test/hexapdf/type/acro_form/test_form.rb +69 -0
- data/test/hexapdf/type/annotations/test_text.rb +2 -6
- data/test/hexapdf/type/annotations/test_widget.rb +24 -0
- data/test/hexapdf/type/test_annotation.rb +1 -1
- data/test/hexapdf/type/test_catalog.rb +1 -1
- data/test/hexapdf/type/test_cid_font.rb +3 -3
- data/test/hexapdf/type/test_font.rb +2 -2
- data/test/hexapdf/type/test_font_descriptor.rb +2 -1
- data/test/hexapdf/type/test_font_simple.rb +3 -3
- data/test/hexapdf/type/test_font_true_type.rb +6 -6
- data/test/hexapdf/type/test_font_type0.rb +5 -5
- data/test/hexapdf/type/test_font_type1.rb +8 -8
- data/test/hexapdf/type/test_font_type3.rb +4 -4
- data/test/hexapdf/type/test_image.rb +16 -12
- data/test/hexapdf/type/test_page.rb +11 -11
- data/test/hexapdf/type/test_page_tree_node.rb +20 -20
- data/test/hexapdf/type/test_resources.rb +6 -6
- data/test/hexapdf/type/test_trailer.rb +5 -2
- data/test/hexapdf/type/test_xref_stream.rb +1 -0
- data/test/hexapdf/utils/test_sorted_tree_node.rb +35 -35
- metadata +23 -7
- data/test/hexapdf/type/annotations/test_link.rb +0 -19
|
@@ -6,8 +6,9 @@ require 'hexapdf/document'
|
|
|
6
6
|
|
|
7
7
|
describe HexaPDF::Rectangle do
|
|
8
8
|
describe "after_data_change" do
|
|
9
|
-
it "fails if the
|
|
10
|
-
assert_raises(ArgumentError) { HexaPDF::Rectangle.new(
|
|
9
|
+
it "fails if the rectangle doesn't contain four numbers" do
|
|
10
|
+
assert_raises(ArgumentError) { HexaPDF::Rectangle.new([1, 2, 3]) }
|
|
11
|
+
assert_raises(ArgumentError) { HexaPDF::Rectangle.new([1, 2, 3, :a]) }
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
it "normalizes the array values" do
|
|
@@ -53,9 +54,6 @@ describe HexaPDF::Rectangle do
|
|
|
53
54
|
|
|
54
55
|
rect.value.unshift(:A)
|
|
55
56
|
refute(rect.validate)
|
|
56
|
-
|
|
57
|
-
rect.data.value = :A
|
|
58
|
-
refute(rect.validate)
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
end
|
|
@@ -137,7 +137,7 @@ describe HexaPDF::Serializer do
|
|
|
137
137
|
it "serializes streams" do
|
|
138
138
|
@stream.stream = "somedata"
|
|
139
139
|
assert_serialized("<</Key(value)/Length 8>>stream\nsomedata\nendstream", @stream)
|
|
140
|
-
assert_serialized("<</Name 2 0 R>>", HexaPDF::Object.new(Name: @stream))
|
|
140
|
+
assert_serialized("<</Name 2 0 R>>", HexaPDF::Object.new({Name: @stream}))
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
it "handles self-referencing streams" do
|
data/test/hexapdf/test_stream.rb
CHANGED
|
@@ -81,6 +81,7 @@ describe HexaPDF::Stream do
|
|
|
81
81
|
@document.config = HexaPDF::Configuration.with_defaults
|
|
82
82
|
@document.instance_variable_set(:@version, '1.2')
|
|
83
83
|
def (@document).unwrap(obj); obj; end
|
|
84
|
+
def (@document).wrap(obj, *); obj; end
|
|
84
85
|
def (@document).deref(obj); obj; end
|
|
85
86
|
|
|
86
87
|
@stm = HexaPDF::Stream.new({}, oid: 1, document: @document)
|
data/test/hexapdf/test_writer.rb
CHANGED
|
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
|
|
|
40
40
|
219
|
|
41
41
|
%%EOF
|
|
42
42
|
3 0 obj
|
|
43
|
-
<</Producer(HexaPDF version 0.
|
|
43
|
+
<</Producer(HexaPDF version 0.11.0)>>
|
|
44
44
|
endobj
|
|
45
45
|
xref
|
|
46
46
|
3 1
|
|
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
|
|
|
72
72
|
141
|
|
73
73
|
%%EOF
|
|
74
74
|
6 0 obj
|
|
75
|
-
<</Producer(HexaPDF version 0.
|
|
75
|
+
<</Producer(HexaPDF version 0.11.0)>>
|
|
76
76
|
endobj
|
|
77
77
|
2 0 obj
|
|
78
78
|
<</Length 10>>stream
|
|
@@ -116,7 +116,7 @@ describe HexaPDF::Writer do
|
|
|
116
116
|
|
|
117
117
|
it "raises an error if no xref stream is in a revision but object streams are" do
|
|
118
118
|
document = HexaPDF::Document.new
|
|
119
|
-
document.add(Type: :ObjStm)
|
|
119
|
+
document.add({Type: :ObjStm})
|
|
120
120
|
assert_raises(HexaPDF::Error) { HexaPDF::Writer.new(document, StringIO.new).write }
|
|
121
121
|
end
|
|
122
122
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'hexapdf/document'
|
|
5
|
+
require 'hexapdf/type/acro_form/field'
|
|
6
|
+
|
|
7
|
+
describe HexaPDF::Type::AcroForm::Field do
|
|
8
|
+
before do
|
|
9
|
+
@doc = HexaPDF::Document.new
|
|
10
|
+
@field = @doc.add({}, type: :XXAcroFormField)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "must always be an indirect object" do
|
|
14
|
+
assert(@field.must_be_indirect?)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "resolves inherited field values" do
|
|
18
|
+
assert_nil(@field[:FT])
|
|
19
|
+
|
|
20
|
+
@field[:Parent] = {FT: :Tx}
|
|
21
|
+
assert_equal(:Tx, @field[:FT])
|
|
22
|
+
|
|
23
|
+
@field[:FT] = :Ch
|
|
24
|
+
assert_equal(:Ch, @field[:FT])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "returns the field type" do
|
|
28
|
+
assert_nil(@field.field_type)
|
|
29
|
+
|
|
30
|
+
@field[:FT] = :Tx
|
|
31
|
+
assert_equal(:Tx, @field.field_type)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "returns the full name of the field" do
|
|
35
|
+
assert_nil(@field.full_name)
|
|
36
|
+
|
|
37
|
+
@field[:T] = "Test"
|
|
38
|
+
assert_equal("Test", @field.full_name)
|
|
39
|
+
|
|
40
|
+
@field[:Parent] = {}
|
|
41
|
+
assert_equal("Test", @field.full_name)
|
|
42
|
+
|
|
43
|
+
@field[:Parent] = {T: 'Parent'}
|
|
44
|
+
assert_equal("Parent.Test", @field.full_name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "returns whether the field is a terminal field" do
|
|
48
|
+
assert(@field.terminal_field?)
|
|
49
|
+
|
|
50
|
+
@field[:Kids] = []
|
|
51
|
+
assert(@field.terminal_field?)
|
|
52
|
+
|
|
53
|
+
@field[:Kids] = [{Subtype: :Widget}]
|
|
54
|
+
assert(@field.terminal_field?)
|
|
55
|
+
|
|
56
|
+
@field[:Kids] = [{FT: :Tx}]
|
|
57
|
+
refute(@field.terminal_field?)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "perform_validation" do
|
|
61
|
+
before do
|
|
62
|
+
@field[:FT] = :Tx
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "requires the /FT key to be present for terminal fields" do
|
|
66
|
+
assert(@field.validate)
|
|
67
|
+
|
|
68
|
+
@field.delete(:FT)
|
|
69
|
+
refute(@field.validate)
|
|
70
|
+
|
|
71
|
+
@field[:Kids] = [{}]
|
|
72
|
+
assert(@field.validate)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "doesn't allow periods in partial field names" do
|
|
76
|
+
assert(@field.validate)
|
|
77
|
+
|
|
78
|
+
@field[:T] = "Test"
|
|
79
|
+
assert(@field.validate)
|
|
80
|
+
|
|
81
|
+
@field[:T] = "Te.st"
|
|
82
|
+
refute(@field.validate)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'hexapdf/document'
|
|
5
|
+
require 'hexapdf/type/acro_form/form'
|
|
6
|
+
|
|
7
|
+
describe HexaPDF::Type::AcroForm::Form do
|
|
8
|
+
before do
|
|
9
|
+
@doc = HexaPDF::Document.new
|
|
10
|
+
@acroform = @doc.add({}, type: :XXAcroForm)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "signature flags" do
|
|
14
|
+
before do
|
|
15
|
+
@acroform[:SigFlags] = 3
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns all signature flags" do
|
|
19
|
+
assert_equal([:signatures_exist, :append_only], @acroform.signature_flags)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns true if the given flag is set" do
|
|
23
|
+
assert(@acroform.signature_flag?(:signatures_exist))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "raises an error if an unknown flag name is provided" do
|
|
27
|
+
assert_raises(ArgumentError) { @acroform.signature_flag?(:non_exist) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "sets the given flag bits" do
|
|
31
|
+
@acroform[:SigFlags] = 0
|
|
32
|
+
@acroform.signature_flag(:append_only)
|
|
33
|
+
assert_equal([:append_only], @acroform.signature_flags)
|
|
34
|
+
@acroform.signature_flag(:signatures_exist, clear_existing: true)
|
|
35
|
+
assert_equal([:signatures_exist], @acroform.signature_flags)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "finds the root fields" do
|
|
40
|
+
@doc.pages.add[:Annots] = [{FT: :Tx1}, {FT: :Tx2, Parent: {FT: :Tx3}}]
|
|
41
|
+
@doc.pages.add[:Annots] = [{Subtype: :Widget}]
|
|
42
|
+
|
|
43
|
+
result = [{FT: :Tx1}, {FT: :Tx3}]
|
|
44
|
+
assert_equal(result, @acroform.find_root_fields.map(&:value))
|
|
45
|
+
refute(@acroform.key?(:Fields))
|
|
46
|
+
|
|
47
|
+
@acroform.find_root_fields!
|
|
48
|
+
assert_equal(result, @acroform[:Fields].value.map(&:value))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "each_field" do
|
|
52
|
+
before do
|
|
53
|
+
@acroform[:Fields] = [
|
|
54
|
+
{FT: :Tx1},
|
|
55
|
+
{FT: :Tx2, Kids: [{Subtype: :Widget}]},
|
|
56
|
+
{FT: :Tx3, Kids: [{FT: :Tx4}, {FT: :Tx5, Kids: [{FT: :Tx6}]}]},
|
|
57
|
+
]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "iterates over all terminal fields" do
|
|
61
|
+
assert_equal([:Tx1, :Tx2, :Tx4, :Tx6], @acroform.each_field.map {|h| h[:FT] })
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "iterates over all fields" do
|
|
65
|
+
assert_equal([:Tx1, :Tx2, :Tx3, :Tx4, :Tx5, :Tx6],
|
|
66
|
+
@acroform.each_field(terminal_only: false).map {|h| h[:FT] })
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -14,17 +14,13 @@ describe HexaPDF::Type::Annotations::Text do
|
|
|
14
14
|
describe "validation" do
|
|
15
15
|
it "checks for correct /StateModel values" do
|
|
16
16
|
@annot[:StateModel] = 'Invalid'
|
|
17
|
-
refute(@annot.validate {|msg| assert_match(/
|
|
17
|
+
refute(@annot.validate {|msg| assert_match(/does not contain an allowed value/, msg) })
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
it "automatically sets /StateModel based on the /State entry
|
|
20
|
+
it "automatically sets /StateModel based on the /State entry" do
|
|
21
21
|
@annot[:State] = 'Marked'
|
|
22
22
|
assert(@annot.validate)
|
|
23
23
|
assert_equal('Marked', @annot[:StateModel])
|
|
24
|
-
|
|
25
|
-
@annot.delete(:StateModel)
|
|
26
|
-
@annot[:State] = 'Unknown'
|
|
27
|
-
refute(@annot.validate {|msg| assert_match(/StateModel required/, msg) })
|
|
28
24
|
end
|
|
29
25
|
|
|
30
26
|
it "checks whether /State and /StateModel match" do
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'hexapdf/document'
|
|
5
|
+
require 'hexapdf/type/annotations/widget'
|
|
6
|
+
|
|
7
|
+
describe HexaPDF::Type::Annotations::Widget::AppearanceCharacteristics do
|
|
8
|
+
before do
|
|
9
|
+
@doc = HexaPDF::Document.new
|
|
10
|
+
@annot = @doc.wrap({}, type: :XXAppearanceCharacteristics)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "validation" do
|
|
14
|
+
it "needs /R to be a multiple of 90" do
|
|
15
|
+
assert(@annot.validate)
|
|
16
|
+
|
|
17
|
+
@annot[:R] = 45
|
|
18
|
+
refute(@annot.validate)
|
|
19
|
+
|
|
20
|
+
@annot[:R] = 90
|
|
21
|
+
assert(@annot.validate)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -7,8 +7,8 @@ require 'hexapdf/type/cid_font'
|
|
|
7
7
|
describe HexaPDF::Type::CIDFont do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
@font = @doc.wrap(Type: :Font, Subtype: :CIDFontType2, W: [1, 2, 3], DW: 100,
|
|
11
|
-
|
|
10
|
+
@font = @doc.wrap({Type: :Font, Subtype: :CIDFontType2, W: [1, 2, 3], DW: 100,
|
|
11
|
+
CIDSystemInfo: {Registry: 'Adobe', Ordering: 'Japan1', Supplement: 1}})
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
describe "width" do
|
|
@@ -39,7 +39,7 @@ describe HexaPDF::Type::CIDFont do
|
|
|
39
39
|
it "allows setting the widths" do
|
|
40
40
|
@font.set_widths([[1, 1], [2, 2], [4, 4], [5, 5], [7, 7.1]], default_width: 5.1)
|
|
41
41
|
assert_equal(5, @font[:DW])
|
|
42
|
-
assert_equal([1, [1, 2], 4, [4, 5], 7, [7]], @font[:W])
|
|
42
|
+
assert_equal([1, [1, 2], 4, [4, 5], 7, [7]], @font[:W].value)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
it "handles an empty widths array correctly" do
|
|
@@ -13,8 +13,8 @@ describe HexaPDF::Type::Font do
|
|
|
13
13
|
<22> <0042>
|
|
14
14
|
endbfchar
|
|
15
15
|
EOF
|
|
16
|
-
fd = @doc.add(Type: :FontDescriptor, FontBBox: [0, 1, 2, 3])
|
|
17
|
-
@font = @doc.add(Type: :Font, BaseFont: :TestFont, FontDescriptor: fd, ToUnicode: cmap)
|
|
16
|
+
fd = @doc.add({Type: :FontDescriptor, FontBBox: [0, 1, 2, 3]})
|
|
17
|
+
@font = @doc.add({Type: :Font, BaseFont: :TestFont, FontDescriptor: fd, ToUnicode: cmap})
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "must always be an indirect" do
|
|
@@ -7,7 +7,8 @@ require 'hexapdf/type/font_descriptor'
|
|
|
7
7
|
describe HexaPDF::Type::FontDescriptor do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
@font_desc = @doc.add(Type: :FontDescriptor, FontName: :Test, Flags: 0b1001001,
|
|
10
|
+
@font_desc = @doc.add({Type: :FontDescriptor, FontName: :Test, Flags: 0b1001001,
|
|
11
|
+
ItalicAngle: 10})
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
describe "flags" do
|
|
@@ -13,9 +13,9 @@ describe HexaPDF::Type::FontSimple do
|
|
|
13
13
|
<22> <0042>
|
|
14
14
|
endbfchar
|
|
15
15
|
EOF
|
|
16
|
-
font_descriptor = @doc.add(Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
font_descriptor = @doc.add({Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
|
|
17
|
+
FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
|
|
18
|
+
Descent: -100, CapHeight: 800, StemV: 20})
|
|
19
19
|
@font = @doc.add({Type: :Font, Encoding: :WinAnsiEncoding,
|
|
20
20
|
BaseFont: :Embedded, FontDescriptor: font_descriptor, ToUnicode: cmap,
|
|
21
21
|
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]},
|
|
@@ -7,12 +7,12 @@ require 'hexapdf/type/font_true_type'
|
|
|
7
7
|
describe HexaPDF::Type::FontTrueType do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
font_descriptor = @doc.add(Type: :FontDescriptor, FontName: :Something, Flags: 0b100,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@font = @doc.add(Type: :Font, Subtype: :TrueType, Encoding: :WinAnsiEncoding,
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
font_descriptor = @doc.add({Type: :FontDescriptor, FontName: :Something, Flags: 0b100,
|
|
11
|
+
FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
|
|
12
|
+
Descent: -100, CapHeight: 800, StemV: 20})
|
|
13
|
+
@font = @doc.add({Type: :Font, Subtype: :TrueType, Encoding: :WinAnsiEncoding,
|
|
14
|
+
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700],
|
|
15
|
+
BaseFont: :Something, FontDescriptor: font_descriptor})
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe "validation" do
|
|
@@ -7,15 +7,15 @@ require 'hexapdf/type/font_type0'
|
|
|
7
7
|
describe HexaPDF::Type::FontType0 do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
fd = @doc.add(Type: :FontDescriptor, FontBBox: [0, 1, 2, 3])
|
|
11
|
-
@cid_font = @doc.wrap(Type: :Font, Subtype: :CIDFontType2, W: [633, [100]], FontDescriptor: fd,
|
|
12
|
-
|
|
13
|
-
@font = @doc.wrap(Type: :Font, Subtype: :Type0, Encoding: :H, DescendantFonts: [@cid_font])
|
|
10
|
+
fd = @doc.add({Type: :FontDescriptor, FontBBox: [0, 1, 2, 3]})
|
|
11
|
+
@cid_font = @doc.wrap({Type: :Font, Subtype: :CIDFontType2, W: [633, [100]], FontDescriptor: fd,
|
|
12
|
+
CIDSystemInfo: {Registry: 'Adobe', Ordering: 'Japan1', Supplement: 1}})
|
|
13
|
+
@font = @doc.wrap({Type: :Font, Subtype: :Type0, Encoding: :H, DescendantFonts: [@cid_font]})
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "returns the correct writing mode" do
|
|
17
17
|
assert_equal(:horizontal, @font.writing_mode)
|
|
18
|
-
font = @doc.wrap(Type: :Font, Subtype: :Type0, Encoding: :V)
|
|
18
|
+
font = @doc.wrap({Type: :Font, Subtype: :Type0, Encoding: :V})
|
|
19
19
|
assert_equal(:vertical, font.writing_mode)
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -39,8 +39,8 @@ end
|
|
|
39
39
|
describe HexaPDF::Type::FontType1 do
|
|
40
40
|
before do
|
|
41
41
|
@doc = HexaPDF::Document.new
|
|
42
|
-
@font = @doc.add(Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
|
|
43
|
-
|
|
42
|
+
@font = @doc.add({Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
|
|
43
|
+
BaseFont: :"Times-Roman"})
|
|
44
44
|
|
|
45
45
|
font_file = @doc.add({}, stream: <<-EOF)
|
|
46
46
|
/Encoding 256 array
|
|
@@ -49,12 +49,12 @@ describe HexaPDF::Type::FontType1 do
|
|
|
49
49
|
dup 34 /B put
|
|
50
50
|
readonly def
|
|
51
51
|
EOF
|
|
52
|
-
font_descriptor = @doc.add(Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@embedded_font = @doc.add(Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
font_descriptor = @doc.add({Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
|
|
53
|
+
FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
|
|
54
|
+
Descent: -100, CapHeight: 800, StemV: 20, FontFile: font_file})
|
|
55
|
+
@embedded_font = @doc.add({Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
|
|
56
|
+
BaseFont: :Embedded, FontDescriptor: font_descriptor,
|
|
57
|
+
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]})
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
describe "encoding" do
|
|
@@ -7,10 +7,10 @@ require 'hexapdf/type/font_type3'
|
|
|
7
7
|
describe HexaPDF::Type::FontType3 do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
@font = @doc.add(Type: :Font, Subtype: :Type3, Encoding: :WinAnsiEncoding,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
@font = @doc.add({Type: :Font, Subtype: :Type3, Encoding: :WinAnsiEncoding,
|
|
11
|
+
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700],
|
|
12
|
+
FontBBox: [0, 0, 100, 100], FontMatrix: [1, 0, 0, 1, 0, 0],
|
|
13
|
+
CharProcs: {}})
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
describe "validation" do
|
|
@@ -12,19 +12,19 @@ describe HexaPDF::Type::Image do
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it "returns the width of the image" do
|
|
15
|
-
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Width: 10)
|
|
15
|
+
@image = @doc.wrap({Type: :XObject, Subtype: :Image, Width: 10})
|
|
16
16
|
assert_equal(10, @image.width)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it "returns the height of the image" do
|
|
20
|
-
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Height: 10)
|
|
20
|
+
@image = @doc.wrap({Type: :XObject, Subtype: :Image, Height: 10})
|
|
21
21
|
assert_equal(10, @image.height)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
describe "info" do
|
|
25
25
|
before do
|
|
26
|
-
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Width: 10, Height: 5,
|
|
27
|
-
|
|
26
|
+
@image = @doc.wrap({Type: :XObject, Subtype: :Image, Width: 10, Height: 5,
|
|
27
|
+
ColorSpace: :DeviceRGB, BitsPerComponent: 4})
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
it "uses the Width, Height and BitsPerComponent values" do
|
|
@@ -184,6 +184,10 @@ describe HexaPDF::Type::Image do
|
|
|
184
184
|
Dir.glob(File.join(TEST_DATA_DIR, 'images', '*.png')).each do |png_file|
|
|
185
185
|
it "writes #{File.basename(png_file)} correctly as PNG file" do
|
|
186
186
|
image = @doc.images.add(png_file)
|
|
187
|
+
if png_file =~ /greyscale-1bit.png/ # force use of arrays for one image
|
|
188
|
+
image[:DecodeParms] = [image[:DecodeParms]]
|
|
189
|
+
image[:Filter] = [image[:Filter]]
|
|
190
|
+
end
|
|
187
191
|
image.write(@file.path)
|
|
188
192
|
assert_valid_png(@file.path, png_file)
|
|
189
193
|
|
|
@@ -197,7 +201,7 @@ describe HexaPDF::Type::Image do
|
|
|
197
201
|
assert_equal(image[:Height], new_image[:Height], "file: #{png_file}")
|
|
198
202
|
assert_equal(image[:BitsPerComponent], new_image[:BitsPerComponent], "file: #{png_file}")
|
|
199
203
|
if image[:Mask]
|
|
200
|
-
assert_equal(image[:Mask], new_image[:Mask], "file: #{png_file}")
|
|
204
|
+
assert_equal(image[:Mask].value, new_image[:Mask].value, "file: #{png_file}")
|
|
201
205
|
else
|
|
202
206
|
assert_nil(new_image[:Mask], "file: #{png_file}")
|
|
203
207
|
end
|
|
@@ -217,15 +221,15 @@ describe HexaPDF::Type::Image do
|
|
|
217
221
|
end
|
|
218
222
|
|
|
219
223
|
it "works for greyscale indexed images" do
|
|
220
|
-
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 2, Height: 2, BitsPerComponent: 2,
|
|
221
|
-
|
|
224
|
+
image = @doc.add({Type: :XObject, Subtype: :Image, Width: 2, Height: 2, BitsPerComponent: 2,
|
|
225
|
+
ColorSpace: [:Indexed, :DeviceGray, 3, "\x00\x40\x80\xFF".b]})
|
|
222
226
|
image.stream = HexaPDF::StreamData.new(filter: :ASCIIHexDecode) { "10 B0".b }
|
|
223
227
|
image.write(@file.path)
|
|
224
228
|
assert_valid_png(@file.path)
|
|
225
229
|
|
|
226
230
|
new_image = @doc.images.add(@file.path)
|
|
227
231
|
assert_equal([:Indexed, :DeviceRGB, 3, "\x00\x00\x00\x40\x40\x40\x80\x80\x80\xFF\xFF\xFF".b],
|
|
228
|
-
new_image[:ColorSpace])
|
|
232
|
+
new_image[:ColorSpace].value)
|
|
229
233
|
assert_equal(image.stream, new_image.stream)
|
|
230
234
|
end
|
|
231
235
|
|
|
@@ -236,14 +240,14 @@ describe HexaPDF::Type::Image do
|
|
|
236
240
|
end
|
|
237
241
|
|
|
238
242
|
it "fails if an unsupported colorspace is used" do
|
|
239
|
-
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
|
240
|
-
|
|
243
|
+
image = @doc.add({Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
|
244
|
+
ColorSpace: :ICCBased})
|
|
241
245
|
assert_raises(HexaPDF::Error) { image.write(@file) }
|
|
242
246
|
end
|
|
243
247
|
|
|
244
248
|
it "fails if an indexed image with an unsupported colorspace is used" do
|
|
245
|
-
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
|
246
|
-
|
|
249
|
+
image = @doc.add({Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
|
250
|
+
ColorSpace: [:Indexed, :ICCBased, 0, "0"]})
|
|
247
251
|
assert_raises(HexaPDF::Error) { image.write(@file) }
|
|
248
252
|
end
|
|
249
253
|
end
|