hexapdf 0.32.0 → 0.32.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/lib/hexapdf/content/canvas.rb +1 -0
- data/lib/hexapdf/encryption/security_handler.rb +1 -1
- data/lib/hexapdf/layout/style.rb +7 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +3 -1
- data/lib/hexapdf/type/font_simple.rb +7 -0
- data/lib/hexapdf/type/font_type0.rb +5 -0
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/content/test_canvas.rb +26 -0
- data/test/hexapdf/encryption/test_security_handler.rb +5 -0
- data/test/hexapdf/layout/test_style.rb +12 -3
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -0
- data/test/hexapdf/type/test_font_simple.rb +8 -4
- data/test/hexapdf/type/test_font_type0.rb +6 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bee477049a8d45aa858093fa683fef19c4760626c3368bf782b74ca10c26d4e1
|
4
|
+
data.tar.gz: e543e4d73eaf80d6f6e434e499715de454f43fb7dae789773282236c2154bc57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2204bac09267cc3459511a4580480b6157dc5eceafd34c61881dbbcc5c52cc457e7862b3d888d0aa5b8260470b38febf2779ee442f697ce971f82044d81f7ee
|
7
|
+
data.tar.gz: b77bbcb040ab16e98d3023447a96d7d942a8c80613969bece44ee96427d9235d6db25446dc1ddf6db6ba1f9d0010f4d4f076fdc7ee189947e7ab4cf94a871807
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 0.32.1 - 2023-04-20
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* [HexaPDF::Type::FontType0#font_descriptor] and
|
6
|
+
[HexaPDF::Type::FontSimple#font_descriptor] for easy access to the font
|
7
|
+
descriptor
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
|
11
|
+
* [HexaPDF::Content::Canvas#color_from_specification] to allow strings and color
|
12
|
+
objects without a wrapping array
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
* AES 128bit encryption to include unnecessary field in encryption dictionary to
|
17
|
+
work around buggy PDF libraries
|
18
|
+
* [HexaPDF::Layout::Style::LinkLayer] to correctly process the border color
|
19
|
+
* [HexaPDF::Type::AcroForm::AppearanceGenerator] to use fallback for font cap
|
20
|
+
height value when necessary
|
21
|
+
|
22
|
+
|
1
23
|
## 0.32.0 - 2023-03-08
|
2
24
|
|
3
25
|
### Added
|
@@ -2363,6 +2363,7 @@ module HexaPDF
|
|
2363
2363
|
# This utility method is meant for use by higher-level methods that need to convert a color
|
2364
2364
|
# specification into a color object for this Canvas object.
|
2365
2365
|
def color_from_specification(spec)
|
2366
|
+
spec = Array(spec)
|
2366
2367
|
if spec.length == 1 && spec[0].kind_of?(String)
|
2367
2368
|
ColorSpace.device_color_from_specification(spec)
|
2368
2369
|
elsif spec.length == 1 && spec[0].respond_to?(:color_space)
|
@@ -358,7 +358,7 @@ module HexaPDF
|
|
358
358
|
raise(HexaPDF::UnsupportedEncryptionError,
|
359
359
|
"Invalid key length #{key_length} specified")
|
360
360
|
end
|
361
|
-
dict[:Length] = key_length if dict[:V] == 2
|
361
|
+
dict[:Length] = key_length if dict[:V] == 4 || dict[:V] == 2
|
362
362
|
|
363
363
|
if ![:aes, :arc4].include?(algorithm)
|
364
364
|
raise(HexaPDF::UnsupportedEncryptionError,
|
data/lib/hexapdf/layout/style.rb
CHANGED
@@ -508,6 +508,12 @@ module HexaPDF
|
|
508
508
|
*matrix.evaluate(box.width, box.height), *matrix.evaluate(0, box.height)]
|
509
509
|
x_minmax = quad_points.values_at(0, 2, 4, 6).minmax
|
510
510
|
y_minmax = quad_points.values_at(1, 3, 5, 7).minmax
|
511
|
+
border_color = case @border_color
|
512
|
+
when [], nil
|
513
|
+
@border_color
|
514
|
+
else
|
515
|
+
canvas.color_from_specification(@border_color).components
|
516
|
+
end
|
511
517
|
annot = {
|
512
518
|
Subtype: :Link,
|
513
519
|
Rect: [x_minmax[0], y_minmax[0], x_minmax[1], y_minmax[1]],
|
@@ -515,7 +521,7 @@ module HexaPDF
|
|
515
521
|
Dest: @dest,
|
516
522
|
A: @action,
|
517
523
|
Border: @border,
|
518
|
-
C:
|
524
|
+
C: border_color,
|
519
525
|
}
|
520
526
|
(page[:Annots] ||= []) << page.document.add(annot)
|
521
527
|
end
|
@@ -395,7 +395,9 @@ module HexaPDF
|
|
395
395
|
|
396
396
|
# Adobe seems to be vertically centering based on the cap height, if enough space is
|
397
397
|
# available
|
398
|
-
|
398
|
+
tmp_cap_height = style.font.wrapped_font.cap_height ||
|
399
|
+
style.font.pdf_object.font_descriptor&.[](:CapHeight)
|
400
|
+
cap_height = tmp_cap_height * style.font.scaling_factor / 1000.0 *
|
399
401
|
style.font_size
|
400
402
|
y = padding + (height - 2 * padding - cap_height) / 2.0
|
401
403
|
y = padding - style.scaled_font_descender if y < 0
|
@@ -53,6 +53,13 @@ module HexaPDF
|
|
53
53
|
define_field :FontDescriptor, type: :FontDescriptor, indirect: true
|
54
54
|
define_field :Encoding, type: [Dictionary, Symbol]
|
55
55
|
|
56
|
+
# Returns the font descriptor. May be +nil+ for a standard 14 font.
|
57
|
+
#
|
58
|
+
# The font descriptor is required except for the standard 14 fonts in PDF version up to 1.7.
|
59
|
+
def font_descriptor
|
60
|
+
self[:FontDescriptor]
|
61
|
+
end
|
62
|
+
|
56
63
|
# Returns the encoding object used for this font.
|
57
64
|
#
|
58
65
|
# Note that the encoding is cached internally when accessed the first time.
|
@@ -63,6 +63,11 @@ module HexaPDF
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
# Returns the font descriptor of the descendant font.
|
67
|
+
def font_descriptor
|
68
|
+
descendant_font[:FontDescriptor]
|
69
|
+
end
|
70
|
+
|
66
71
|
# Returns the writing mode which is either :horizontal or :vertical.
|
67
72
|
def writing_mode
|
68
73
|
cmap.wmode == 0 ? :horizontal : :vertical
|
data/lib/hexapdf/version.rb
CHANGED
@@ -1280,4 +1280,30 @@ describe HexaPDF::Content::Canvas do
|
|
1280
1280
|
end
|
1281
1281
|
end
|
1282
1282
|
end
|
1283
|
+
|
1284
|
+
describe "color_from_specification "do
|
1285
|
+
it "accepts a color string" do
|
1286
|
+
assert_equal([1, 0, 0], @canvas.color_from_specification("red").components)
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
it "accepts a color string wrapped in an array" do
|
1290
|
+
assert_equal([1, 0, 0], @canvas.color_from_specification(["red"]).components)
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
it "accepts a color object" do
|
1294
|
+
color = @canvas.color_from_specification("red")
|
1295
|
+
assert_equal(color, @canvas.color_from_specification(color))
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
it "accepts a color object wrapped in an array" do
|
1299
|
+
color = @canvas.color_from_specification("red")
|
1300
|
+
assert_equal(color, @canvas.color_from_specification([color]))
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
it "accepts an array with 1, 3, or 4 color values" do
|
1304
|
+
assert_equal([1], @canvas.color_from_specification([255]).components)
|
1305
|
+
assert_equal([1, 0, 0], @canvas.color_from_specification([255, 0, 0]).components)
|
1306
|
+
assert_equal([1, 0, 0, 0], @canvas.color_from_specification([100, 0, 0, 0]).components)
|
1307
|
+
end
|
1308
|
+
end
|
1283
1309
|
end
|
@@ -141,6 +141,11 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
141
141
|
@handler.set_up_encryption(key_length: key_length, algorithm: algorithm)
|
142
142
|
assert(result == @handler.dict[:Length])
|
143
143
|
end
|
144
|
+
|
145
|
+
# Work-around buggy software
|
146
|
+
@handler.set_up_encryption(key_length: 128, algorithm: :aes)
|
147
|
+
assert_equal(4, @handler.dict[:V])
|
148
|
+
assert_equal(128, @handler.dict[:Length])
|
144
149
|
end
|
145
150
|
|
146
151
|
it "calls the prepare_encryption method" do
|
@@ -573,10 +573,19 @@ describe HexaPDF::Layout::Style::LinkLayer do
|
|
573
573
|
assert_equal([0, 0, 1], annot[:Border].value)
|
574
574
|
end
|
575
575
|
|
576
|
-
it "uses the specified border
|
577
|
-
annot = call_link(dest: true, border: [10, 10, 2]
|
576
|
+
it "uses the specified border" do
|
577
|
+
annot = call_link(dest: true, border: [10, 10, 2])
|
578
578
|
assert_equal([10, 10, 2], annot[:Border].value)
|
579
|
-
|
579
|
+
end
|
580
|
+
|
581
|
+
it "uses the specified border color" do
|
582
|
+
annot = call_link(dest: true, border_color: "red")
|
583
|
+
assert_equal([1.0, 0, 0], annot[:C].value)
|
584
|
+
end
|
585
|
+
|
586
|
+
it "works when the border color is transparent" do
|
587
|
+
annot = call_link(dest: true, border_color: [])
|
588
|
+
assert_equal([], annot[:C].value)
|
580
589
|
end
|
581
590
|
|
582
591
|
it "works for simple destinations" do
|
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.32.
|
43
|
+
<</Producer(HexaPDF version 0.32.1)>>
|
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.32.
|
75
|
+
<</Producer(HexaPDF version 0.32.1)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
@@ -214,7 +214,7 @@ describe HexaPDF::Writer do
|
|
214
214
|
<</Type/Page/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<<>>>>
|
215
215
|
endobj
|
216
216
|
5 0 obj
|
217
|
-
<</Producer(HexaPDF version 0.32.
|
217
|
+
<</Producer(HexaPDF version 0.32.1)>>
|
218
218
|
endobj
|
219
219
|
4 0 obj
|
220
220
|
<</Root 1 0 R/Info 5 0 R/Size 6/Type/XRef/W[1 1 2]/Index[0 6]/Filter/FlateDecode/DecodeParms<</Columns 4/Predictor 12>>/Length 33>>stream
|
@@ -519,6 +519,19 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
|
|
519
519
|
range: 7)
|
520
520
|
end
|
521
521
|
|
522
|
+
it "falls back to the cap height in the font descriptor for vertical alignment" do
|
523
|
+
font_metrics = @form.default_resources.font(:F1).font_wrapper.wrapped_font.metrics
|
524
|
+
cap_height = font_metrics.cap_height
|
525
|
+
font_metrics.cap_height = nil
|
526
|
+
|
527
|
+
@generator.create_appearances
|
528
|
+
assert_operators(@widget[:AP][:N].stream,
|
529
|
+
[:set_text_matrix, [1, 0, 0, 1, 2, 6.41]],
|
530
|
+
range: 7)
|
531
|
+
ensure
|
532
|
+
font_metrics.cap_height = cap_height
|
533
|
+
end
|
534
|
+
|
522
535
|
it "vertically aligns to the font descender if the text is too high" do
|
523
536
|
@widget[:Rect].height = 5
|
524
537
|
@generator.create_appearances
|
@@ -13,15 +13,19 @@ 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
|
+
MissingWidth: 500, Descent: -100, CapHeight: 800, StemV: 20})
|
19
19
|
@font = @doc.add({Type: :Font, Encoding: :WinAnsiEncoding,
|
20
|
-
BaseFont: :Embedded, FontDescriptor: font_descriptor, ToUnicode: cmap,
|
20
|
+
BaseFont: :Embedded, FontDescriptor: @font_descriptor, ToUnicode: cmap,
|
21
21
|
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]},
|
22
22
|
type: HexaPDF::Type::FontSimple)
|
23
23
|
end
|
24
24
|
|
25
|
+
it "returns the font descriptor of the font" do
|
26
|
+
assert_same(@font_descriptor, @font.font_descriptor)
|
27
|
+
end
|
28
|
+
|
25
29
|
describe "encoding" do
|
26
30
|
it "fails if /Encoding is absent because encoding_from_font is not implemented" do
|
27
31
|
@font.delete(:Encoding)
|
@@ -7,8 +7,8 @@ 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,
|
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
12
|
CIDSystemInfo: {Registry: 'Adobe', Ordering: 'Japan1', Supplement: 1}})
|
13
13
|
@font = @doc.wrap({Type: :Font, Subtype: :Type0, Encoding: :H, DescendantFonts: [@cid_font]})
|
14
14
|
end
|
@@ -26,6 +26,10 @@ describe HexaPDF::Type::FontType0 do
|
|
26
26
|
assert_equal(@cid_font.value, @font.descendant_font.value)
|
27
27
|
end
|
28
28
|
|
29
|
+
it "returns the font descriptor of the descendant font" do
|
30
|
+
assert_same(@fd, @font.font_descriptor)
|
31
|
+
end
|
32
|
+
|
29
33
|
it "uses the descendant font for getting the width of a code point" do
|
30
34
|
assert_equal(100, @font.width(0x2121))
|
31
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexapdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.32.
|
4
|
+
version: 0.32.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Leitner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|