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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c74f0e152b612b628321f312413a0eb88e52a41a809f7b37e993acb9e0436b2
4
- data.tar.gz: 9dfe8cfaaa10527695b70d9019636ed9cc6059367125a45a3dacde7bc1d8c3bb
3
+ metadata.gz: bee477049a8d45aa858093fa683fef19c4760626c3368bf782b74ca10c26d4e1
4
+ data.tar.gz: e543e4d73eaf80d6f6e434e499715de454f43fb7dae789773282236c2154bc57
5
5
  SHA512:
6
- metadata.gz: f9ee0dbe507a6d31cbf024d2f34e69c15e491bc05a64a0f4039f38bcf6d52192245d6c7d2ac4cb65ae1eb110f8af735afcf13366e15975d96bcc17dda8e2a618
7
- data.tar.gz: 846ce0611e5f125011aa0535d2de69c15c356f6164f9b09f0a314f9968e34e4addda5396c03d82cd70dffc96eaa0408e1a6dd7a6fc55ce59646be5c3f8b4f9a6
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,
@@ -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: @border_color && canvas.color_from_specification(@border_color).components,
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
- cap_height = style.font.wrapped_font.cap_height * style.font.scaling_factor / 1000.0 *
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
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.32.0'
40
+ VERSION = '0.32.1'
41
41
 
42
42
  end
@@ -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 and border color" do
577
- annot = call_link(dest: true, border: [10, 10, 2], border_color: [255])
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
- assert_equal([1.0], annot[:C].value)
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
@@ -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.0)>>
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.0)>>
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.0)>>
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
- FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
18
- MissingWidth: 500, Descent: -100, CapHeight: 800, StemV: 20})
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.0
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-03-08 00:00:00.000000000 Z
11
+ date: 2023-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse