hexapdf 0.32.0 → 0.32.1
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 +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
|