pdfrb 0.7.1 → 0.7.10

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +93 -0
  3. data/RELEASE.md +17 -11
  4. data/data/pdfrb/layout/hyphenation_en.txt +408 -0
  5. data/lib/pdfrb/color/default_profile.rb +213 -0
  6. data/lib/pdfrb/color/icc_validator.rb +69 -0
  7. data/lib/pdfrb/color.rb +2 -0
  8. data/lib/pdfrb/conformance/ltv.rb +112 -0
  9. data/lib/pdfrb/conformance/pades.rb +198 -0
  10. data/lib/pdfrb/conformance/pdf_2_af.rb +185 -0
  11. data/lib/pdfrb/conformance/pdf_a.rb +123 -0
  12. data/lib/pdfrb/conformance/pdf_a4_deep.rb +94 -0
  13. data/lib/pdfrb/conformance/pdf_ua2_deep.rb +93 -0
  14. data/lib/pdfrb/conformance/pdf_ua_tagging_deep.rb +125 -0
  15. data/lib/pdfrb/conformance/pdf_vt.rb +128 -0
  16. data/lib/pdfrb/conformance/pdf_x.rb +66 -1
  17. data/lib/pdfrb/conformance/tagged_pdf.rb +182 -0
  18. data/lib/pdfrb/conformance.rb +8 -0
  19. data/lib/pdfrb/content/parser.rb +82 -0
  20. data/lib/pdfrb/digital_signature/timestamp_client.rb +86 -0
  21. data/lib/pdfrb/digital_signature.rb +1 -0
  22. data/lib/pdfrb/document.rb +29 -0
  23. data/lib/pdfrb/encryption/public_key_security_handler.rb +146 -0
  24. data/lib/pdfrb/encryption/standard_security_handler.rb +98 -3
  25. data/lib/pdfrb/encryption/v5_writer.rb +108 -0
  26. data/lib/pdfrb/encryption.rb +3 -0
  27. data/lib/pdfrb/font_loader/type3.rb +65 -0
  28. data/lib/pdfrb/font_loader.rb +1 -0
  29. data/lib/pdfrb/image_loader/gif.rb +246 -0
  30. data/lib/pdfrb/image_loader/tiff.rb +257 -0
  31. data/lib/pdfrb/image_loader.rb +2 -0
  32. data/lib/pdfrb/layout/font_fallback.rb +203 -0
  33. data/lib/pdfrb/layout/hyphenation.rb +120 -0
  34. data/lib/pdfrb/layout/justification_kashidas.rb +72 -0
  35. data/lib/pdfrb/layout/multi_cell_text_layout.rb +65 -0
  36. data/lib/pdfrb/layout/multi_page_table_box.rb +155 -0
  37. data/lib/pdfrb/layout/polygon_frame.rb +106 -0
  38. data/lib/pdfrb/layout/table_box.rb +154 -23
  39. data/lib/pdfrb/layout/text_shaper.rb +129 -0
  40. data/lib/pdfrb/layout.rb +7 -0
  41. data/lib/pdfrb/source/linearization_reader.rb +76 -0
  42. data/lib/pdfrb/source/recovery.rb +65 -1
  43. data/lib/pdfrb/source/tokenizer.rb +21 -0
  44. data/lib/pdfrb/source.rb +1 -0
  45. data/lib/pdfrb/task/thumbnail.rb +133 -0
  46. data/lib/pdfrb/task.rb +1 -0
  47. data/lib/pdfrb/version.rb +1 -1
  48. metadata +28 -2
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Task
5
+ # Generates a low-resolution thumbnail for each page (or a single
6
+ # page) and attaches it via the page-level /Thumb key. PDF
7
+ # viewers use /Thumb to render page previews quickly without
8
+ # parsing the full content stream.
9
+ #
10
+ # The thumbnail is a Form XObject rendered to a small image
11
+ # XObject. Pure-Ruby implementation: renders only the page's text
12
+ # (no image / form XObject content) at the target resolution
13
+ # using the standard 14 AFM metrics when available, otherwise a
14
+ # placeholder rectangle.
15
+ module Thumbnail
16
+ DEFAULT_DPI = 72
17
+ DEFAULT_MAX_WIDTH = 200
18
+
19
+ module_function
20
+
21
+ # Generate thumbnails for every page in +document+. Returns the
22
+ # count of thumbnails added. Idempotent: existing /Thumb
23
+ # entries are left alone unless +force:+ is true.
24
+ def call(document, dpi: DEFAULT_DPI, max_width: DEFAULT_MAX_WIDTH, force: false)
25
+ count = 0
26
+ document.pages.each do |page|
27
+ next if page.value[:Thumb] && !force
28
+
29
+ thumb = build_thumbnail(document, page, dpi: dpi, max_width: max_width)
30
+ next unless thumb
31
+
32
+ page.value[:Thumb] = Pdfrb::Model::Reference.new(thumb.oid, thumb.gen)
33
+ count += 1
34
+ end
35
+ count
36
+ end
37
+
38
+ # Build a single thumbnail image XObject for +page+ at the
39
+ # given DPI, capped at +max_width+ pixels. Returns the image
40
+ # XObject or nil if the page has no media box.
41
+ def build_thumbnail(document, page, dpi: DEFAULT_DPI, max_width: DEFAULT_MAX_WIDTH)
42
+ media_box = page.value[:MediaBox]
43
+ return nil unless media_box.is_a?(::Array) && media_box.length == 4
44
+
45
+ width, height = page_pixel_dimensions(media_box, dpi, max_width)
46
+ return nil unless width.positive? && height.positive?
47
+
48
+ # Single-component grayscale image — 1 byte per pixel.
49
+ # White background, black "text" rectangle placeholder. Real
50
+ # text rendering would require running the content processor
51
+ # against a rasteriser; that's a much larger feature.
52
+ pixel_data = render_placeholder(width, height, page)
53
+ compressed = require_zlib.deflate(pixel_data)
54
+
55
+ image = document.add(
56
+ {
57
+ Type: :XObject, Subtype: :Image,
58
+ Width: width, Height: height,
59
+ ColorSpace: :DeviceGray,
60
+ BitsPerComponent: 8,
61
+ Filter: :FlateDecode,
62
+ Length: compressed.bytesize
63
+ },
64
+ type: Pdfrb::Model::Cos::Stream
65
+ )
66
+ image.stream = compressed
67
+ image
68
+ end
69
+
70
+ # Compute thumbnail pixel dimensions, capped at +max_width+.
71
+ def page_pixel_dimensions(media_box, dpi, max_width)
72
+ _x0, _y0, x1, y1 = media_box
73
+ pt_w = x1.to_f
74
+ pt_h = y1.to_f
75
+ return [0, 0] if pt_w.zero? || pt_h.zero?
76
+
77
+ scale = (dpi / 72.0) * (max_width.to_f / pt_w)
78
+ scale = 1.0 if scale > 1.0
79
+ [(pt_w * scale).round, (pt_h * scale).round]
80
+ end
81
+
82
+ # Render a 1-bpp-style grayscale placeholder: white background,
83
+ # a black border, and a few black "text line" rectangles
84
+ # representing where text content might appear. Pure visual
85
+ # cue, not a real render.
86
+ def render_placeholder(width, height, _page)
87
+ bytes = Array.new(width * height, 255) # white
88
+
89
+ draw_rect(bytes, width, height, 0, 0, width, height, 0) # border (black)
90
+ # Determine text area: roughly 80% of page width, centred
91
+ margin = (width * 0.1).round
92
+ text_top = (height * 0.85).round
93
+ line_height = (height * 0.02).round
94
+ line_height = 1 if line_height.zero?
95
+ line_count = [(height * 0.6 / line_height).floor, 3].max
96
+ line_count.times do |i|
97
+ y = text_top - (i * line_height * 2)
98
+ draw_horizontal_line(bytes, width, height, margin, y,
99
+ width - margin, 0)
100
+ end
101
+ bytes.pack("C*").b
102
+ end
103
+
104
+ def draw_rect(bytes, width, height, x0, y0, x1, y1, value)
105
+ x0.upto([x1 - 1, width - 1].min) do |x|
106
+ set_pixel(bytes, width, height, x, y0, value)
107
+ set_pixel(bytes, width, height, x, y1 - 1, value)
108
+ end
109
+ y0.upto([y1 - 1, height - 1].min) do |y|
110
+ set_pixel(bytes, width, height, x0, y, value)
111
+ set_pixel(bytes, width, height, x1 - 1, y, value)
112
+ end
113
+ end
114
+
115
+ def draw_horizontal_line(bytes, width, height, x0, y, x1, value)
116
+ x0.upto([x1 - 1, width - 1].min) do |x|
117
+ set_pixel(bytes, width, height, x, y, value)
118
+ end
119
+ end
120
+
121
+ def set_pixel(bytes, width, height, x, y, value)
122
+ return if x.negative? || y.negative? || x >= width || y >= height
123
+
124
+ bytes[(y * width) + x] = value
125
+ end
126
+
127
+ def require_zlib
128
+ require "zlib"
129
+ ::Zlib
130
+ end
131
+ end
132
+ end
133
+ end
data/lib/pdfrb/task.rb CHANGED
@@ -10,5 +10,6 @@ module Pdfrb
10
10
  autoload :Benchmark, "pdfrb/task/benchmark"
11
11
  autoload :MemoryProfile, "pdfrb/task/memory_profile"
12
12
  autoload :RegenerateAppearances, "pdfrb/task/regenerate_appearances"
13
+ autoload :Thumbnail, "pdfrb/task/thumbnail"
13
14
  end
14
15
  end
data/lib/pdfrb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pdfrb
4
- VERSION = "0.7.1"
4
+ VERSION = "0.7.10"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-08 00:00:00.000000000 Z
11
+ date: 2026-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -699,6 +699,7 @@ files:
699
699
  - data/pdfrb/arlington/latest/_UniversalArray.tsv
700
700
  - data/pdfrb/arlington/latest/_UniversalDictionary.tsv
701
701
  - data/pdfrb/glyphlist.txt
702
+ - data/pdfrb/layout/hyphenation_en.txt
702
703
  - data/pdfrb/zapfdingbats.txt
703
704
  - exe/pdfrb
704
705
  - lib/pdfrb.rb
@@ -746,18 +747,28 @@ files:
746
747
  - lib/pdfrb/cli/watermark.rb
747
748
  - lib/pdfrb/color.rb
748
749
  - lib/pdfrb/color/color_space.rb
750
+ - lib/pdfrb/color/default_profile.rb
749
751
  - lib/pdfrb/color/icc_profile.rb
752
+ - lib/pdfrb/color/icc_validator.rb
750
753
  - lib/pdfrb/compare.rb
751
754
  - lib/pdfrb/compare/comparator.rb
752
755
  - lib/pdfrb/compare/report.rb
753
756
  - lib/pdfrb/composer.rb
754
757
  - lib/pdfrb/configuration.rb
755
758
  - lib/pdfrb/conformance.rb
759
+ - lib/pdfrb/conformance/ltv.rb
760
+ - lib/pdfrb/conformance/pades.rb
761
+ - lib/pdfrb/conformance/pdf_2_af.rb
756
762
  - lib/pdfrb/conformance/pdf_a.rb
763
+ - lib/pdfrb/conformance/pdf_a4_deep.rb
757
764
  - lib/pdfrb/conformance/pdf_ua.rb
765
+ - lib/pdfrb/conformance/pdf_ua2_deep.rb
766
+ - lib/pdfrb/conformance/pdf_ua_tagging_deep.rb
767
+ - lib/pdfrb/conformance/pdf_vt.rb
758
768
  - lib/pdfrb/conformance/pdf_x.rb
759
769
  - lib/pdfrb/conformance/rule.rb
760
770
  - lib/pdfrb/conformance/structure_elements.rb
771
+ - lib/pdfrb/conformance/tagged_pdf.rb
761
772
  - lib/pdfrb/conformance/verapdf_bridge.rb
762
773
  - lib/pdfrb/content.rb
763
774
  - lib/pdfrb/content/canvas.rb
@@ -796,6 +807,7 @@ files:
796
807
  - lib/pdfrb/digital_signature/cms_handler.rb
797
808
  - lib/pdfrb/digital_signature/handler.rb
798
809
  - lib/pdfrb/digital_signature/signing.rb
810
+ - lib/pdfrb/digital_signature/timestamp_client.rb
799
811
  - lib/pdfrb/digital_signature/timestamp_handler.rb
800
812
  - lib/pdfrb/digital_signature/verification.rb
801
813
  - lib/pdfrb/digital_signature/verification_result.rb
@@ -826,9 +838,11 @@ files:
826
838
  - lib/pdfrb/encryption/aes.rb
827
839
  - lib/pdfrb/encryption/identity.rb
828
840
  - lib/pdfrb/encryption/password_verification.rb
841
+ - lib/pdfrb/encryption/public_key_security_handler.rb
829
842
  - lib/pdfrb/encryption/rc4.rb
830
843
  - lib/pdfrb/encryption/security_handler.rb
831
844
  - lib/pdfrb/encryption/standard_security_handler.rb
845
+ - lib/pdfrb/encryption/v5_writer.rb
832
846
  - lib/pdfrb/error.rb
833
847
  - lib/pdfrb/filter.rb
834
848
  - lib/pdfrb/filter/ascii_85_decode.rb
@@ -881,15 +895,18 @@ files:
881
895
  - lib/pdfrb/font_loader/standard14.rb
882
896
  - lib/pdfrb/font_loader/true_type.rb
883
897
  - lib/pdfrb/font_loader/type1.rb
898
+ - lib/pdfrb/font_loader/type3.rb
884
899
  - lib/pdfrb/font_loader/variant_from_name.rb
885
900
  - lib/pdfrb/font_resolver.rb
886
901
  - lib/pdfrb/image.rb
887
902
  - lib/pdfrb/image/audit.rb
888
903
  - lib/pdfrb/image/downsampler.rb
889
904
  - lib/pdfrb/image_loader.rb
905
+ - lib/pdfrb/image_loader/gif.rb
890
906
  - lib/pdfrb/image_loader/jpeg.rb
891
907
  - lib/pdfrb/image_loader/pdf.rb
892
908
  - lib/pdfrb/image_loader/png.rb
909
+ - lib/pdfrb/image_loader/tiff.rb
893
910
  - lib/pdfrb/importer.rb
894
911
  - lib/pdfrb/layout.rb
895
912
  - lib/pdfrb/layout/bidi.rb
@@ -897,18 +914,25 @@ files:
897
914
  - lib/pdfrb/layout/box_fitter.rb
898
915
  - lib/pdfrb/layout/column_box.rb
899
916
  - lib/pdfrb/layout/container_box.rb
917
+ - lib/pdfrb/layout/font_fallback.rb
900
918
  - lib/pdfrb/layout/frame.rb
919
+ - lib/pdfrb/layout/hyphenation.rb
901
920
  - lib/pdfrb/layout/image_box.rb
902
921
  - lib/pdfrb/layout/inline_box.rb
922
+ - lib/pdfrb/layout/justification_kashidas.rb
903
923
  - lib/pdfrb/layout/line.rb
904
924
  - lib/pdfrb/layout/list_box.rb
925
+ - lib/pdfrb/layout/multi_cell_text_layout.rb
926
+ - lib/pdfrb/layout/multi_page_table_box.rb
905
927
  - lib/pdfrb/layout/numeric_refinements.rb
906
928
  - lib/pdfrb/layout/page_style.rb
929
+ - lib/pdfrb/layout/polygon_frame.rb
907
930
  - lib/pdfrb/layout/style.rb
908
931
  - lib/pdfrb/layout/table_box.rb
909
932
  - lib/pdfrb/layout/text_box.rb
910
933
  - lib/pdfrb/layout/text_fragment.rb
911
934
  - lib/pdfrb/layout/text_layouter.rb
935
+ - lib/pdfrb/layout/text_shaper.rb
912
936
  - lib/pdfrb/linearization.rb
913
937
  - lib/pdfrb/linearization/hint_stream.rb
914
938
  - lib/pdfrb/linearization/writer.rb
@@ -1145,6 +1169,7 @@ files:
1145
1169
  - lib/pdfrb/source/header_reader.rb
1146
1170
  - lib/pdfrb/source/helpers.rb
1147
1171
  - lib/pdfrb/source/linearization_detection.rb
1172
+ - lib/pdfrb/source/linearization_reader.rb
1148
1173
  - lib/pdfrb/source/object_reader.rb
1149
1174
  - lib/pdfrb/source/object_stream_reader.rb
1150
1175
  - lib/pdfrb/source/parser.rb
@@ -1164,6 +1189,7 @@ files:
1164
1189
  - lib/pdfrb/task/merge.rb
1165
1190
  - lib/pdfrb/task/optimize.rb
1166
1191
  - lib/pdfrb/task/regenerate_appearances.rb
1192
+ - lib/pdfrb/task/thumbnail.rb
1167
1193
  - lib/pdfrb/test_utils.rb
1168
1194
  - lib/pdfrb/validator.rb
1169
1195
  - lib/pdfrb/version.rb