pdfrb 0.7.21 → 0.7.23

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: 8fede6fc181df1691732c051b8339ee2bded64c7f393691fd9dd5b0f151082e9
4
- data.tar.gz: a602406104c68a47a6d5ddca09fedaa12831528c9cb603a9dab0a123f171004f
3
+ metadata.gz: 8d9ae8c6a5750a4998d51924dc9d011b6b41565e2435e7dc87f25e913a5bf532
4
+ data.tar.gz: 7041b81cedd1d7387cc5ba54829da445add3278151d6579f30da6192d0244043
5
5
  SHA512:
6
- metadata.gz: 7822801383bb40e5d381f4b10801de93b3271304ff2b748ca6a2e1182de9620c5694920c1ddfa4d4bfceb15033fa6b6e069addb76fcdc1721c3ccde104da226d
7
- data.tar.gz: 94a2bbcb98addcb843be49ffdce5a75e693f34f7384106c8036f6247b66751c760176a55b55b6e407d24935ff26f1700512da96a827ef2d0e02ca70e8a9e48e2
6
+ metadata.gz: 35a3f9fe4ea0933fd2e33b2089799e32477e04824884ccc29f0c78377699d051a584e3facaef01c5a62666568db22f859557c394daff2c96c441574c2a054d75
7
+ data.tar.gz: 6baf785a854c19b549f6d66807bc9531fdd665164c6a02ab1570650a5faf9a8a5d5c412b7a7d01a9b467b4fb24301f53ac456bc6579d24615be837e786476a00
data/docs/SEMVER.md ADDED
@@ -0,0 +1,60 @@
1
+ # Pdfrb Semver Policy
2
+
3
+ ## Version Scheme
4
+
5
+ Pdfrb follows [Semantic Versioning 2.0.0](https://semver.org/).
6
+
7
+ - **MAJOR** (X.0.0): Breaking API changes. Existing code that depends
8
+ on pdfrb may need updates.
9
+ - **MINOR** (0.X.0): New features, backward-compatible. Existing code
10
+ continues to work.
11
+ - **PATCH** (0.0.X): Bug fixes, performance improvements, doc updates.
12
+ No new features, no breaking changes.
13
+
14
+ ## Current Phase: 0.x (pre-1.0)
15
+
16
+ During 0.x development, the API is not yet frozen. Minor version bumps
17
+ MAY include breaking changes, but they will be documented in
18
+ CHANGELOG.md with migration notes.
19
+
20
+ The goal is to reach 1.0 once:
21
+ - The public API is stable (Document, Writer, Canvas, Conformance).
22
+ - Round-trip is proven against a broad fixture corpus.
23
+ - All P0 TODOs are complete.
24
+ - veraPDF cross-check passes on PDF/A output.
25
+
26
+ ## Deprecation Policy
27
+
28
+ 1. A deprecated API is marked with YARD `@deprecated` tags and emits a
29
+ `Warning.warn` on first use.
30
+ 2. The deprecation period lasts at least one minor version.
31
+ 3. Removal happens in the next major version bump.
32
+
33
+ ## Release Checklist
34
+
35
+ - [ ] All specs pass: `bundle exec rake`
36
+ - [ ] Rubocop clean: `bundle exec rubocop`
37
+ - [ ] Coverage maintained or improved: `COVERAGE=1 bundle exec rspec`
38
+ - [ ] CHANGELOG.md updated with all changes
39
+ - [ ] Version bumped in `lib/pdfrb/version.rb`
40
+ - [ ] Git tag created: `vX.Y.Z`
41
+ - [ ] Gem pushed: `gem build && gem push`
42
+
43
+ ## Public API Stability Contract
44
+
45
+ The following are considered **stable** (subject to semver guarantees):
46
+
47
+ - `Pdfrb::Document` — top-level facade (new, open, write, pages, fonts, etc.)
48
+ - `Pdfrb::Writer` — serialization
49
+ - `Pdfrb::Serializer` — COS-to-bytes
50
+ - `Pdfrb::Canvas` — content-stream drawing
51
+ - `Pdfrb::Compare` — semantic diff
52
+ - `Pdfrb::Conformance` — PDF/A and PDF/UA validators
53
+ - `Pdfrb::DigitalSignature` — signing and verification
54
+ - `Pdfrb::Error` hierarchy
55
+
56
+ The following are **internal** (may change without notice):
57
+
58
+ - `Pdfrb::Source::*` — tokenizer/parser internals
59
+ - `Pdfrb::Model::Cos::*` — COS implementation details
60
+ - `Pdfrb::Arlington::*` — predicate evaluation internals
data/docs/USAGE.md ADDED
@@ -0,0 +1,173 @@
1
+ # Pdfrb Usage Guide
2
+
3
+ A cookbook of common PDF tasks using pdfrb.
4
+
5
+ ## Creating a PDF
6
+
7
+ ```ruby
8
+ require "pdfrb"
9
+
10
+ doc = Pdfrb::Document.new
11
+ font = doc.fonts.add("Helvetica")
12
+ page = doc.pages.add
13
+ page.canvas.text("Hello, World!", at: [72, 720], font: font, size: 24)
14
+
15
+ doc.write("hello.pdf")
16
+ ```
17
+
18
+ ## Reading a PDF
19
+
20
+ ```ruby
21
+ doc = Pdfrb.open("input.pdf")
22
+ puts "Pages: #{doc.pages.count}"
23
+ doc.pages.each do |page|
24
+ text = Pdfrb::Task::ExtractText.call_single_page(page)
25
+ puts text
26
+ end
27
+ ```
28
+
29
+ ## Drawing on a Canvas
30
+
31
+ ```ruby
32
+ doc = Pdfrb::Document.new
33
+ page = doc.pages.add
34
+ font = doc.fonts.add("Helvetica")
35
+
36
+ page.canvas.tap do |c|
37
+ c.text("Title", at: [72, 720], font: font, size: 18)
38
+ c.rectangle(point: [72, 700], width: 200, height: 50)
39
+ c.stroke
40
+ c.line(from: [72, 600], to: [300, 600])
41
+ c.stroke
42
+ end
43
+
44
+ doc.write("drawing.pdf")
45
+ ```
46
+
47
+ ## Embedding an ICC Profile
48
+
49
+ ```ruby
50
+ icc_bytes = File.binread("sRGB.icc")
51
+ cs = doc.colors.embed_icc_profile(icc_bytes)
52
+ page = doc.pages.first
53
+ cs_name = doc.colors.register(page, cs)
54
+ # Use cs_name in content stream: "/CS1 cs 0.5 0.3 0.2 scn"
55
+ ```
56
+
57
+ ## Tagged PDF (Accessibility)
58
+
59
+ ```ruby
60
+ doc.structure.enable!
61
+ doc.catalog.value[:Lang] = "en-US"
62
+
63
+ doc_elem = doc.structure.add_element(:Document)
64
+ doc.structure.add_child(doc_elem, :H1, title: "Introduction")
65
+ doc.structure.add_child(doc_elem, :P)
66
+ ```
67
+
68
+ ## Optional Content Groups (Layers)
69
+
70
+ ```ruby
71
+ doc.layers.add("Background Art", default_on: false)
72
+ doc.layers.add("Annotations")
73
+ doc.layers.sync!
74
+ ```
75
+
76
+ ## Interactive Forms (AcroForm)
77
+
78
+ ```ruby
79
+ page = doc.pages.add
80
+ doc.form.add_text_field("username", page: page, rect: [50, 700, 250, 720])
81
+ doc.form.add_checkbox("agree", page: page, rect: [50, 650, 65, 665], checked: true)
82
+ doc.form.add_combo("country", page: page, rect: [50, 600, 200, 620],
83
+ options: ["US", "UK", "JP"], value: "US")
84
+ ```
85
+
86
+ ## Digital Signatures
87
+
88
+ ```ruby
89
+ cert = OpenSSL::X509::Certificate.new(File.read("cert.pem"))
90
+ key = OpenSSL::PKey::RSA.new(File.read("key.pem"))
91
+
92
+ signed = Pdfrb::DigitalSignature::Signing.sign(doc, cert: cert, key: key,
93
+ reason: "Approval")
94
+ File.binwrite("signed.pdf", signed)
95
+
96
+ # Verify
97
+ results = Pdfrb::DigitalSignature::Verification.verify(signed, trusted_certs: [cert])
98
+ puts "Valid: #{results.first.valid?}"
99
+ ```
100
+
101
+ ## Semantic Comparison (Diff)
102
+
103
+ ```ruby
104
+ left = File.binread("v1.pdf")
105
+ right = File.binread("v2.pdf")
106
+ report = Pdfrb::Compare.compare(left, right)
107
+
108
+ puts "Pages: #{report.page_count_delta}"
109
+ puts "Fonts added: #{report.font_diff[:added]}"
110
+ puts "Equivalent: #{report.equivalent?}"
111
+ ```
112
+
113
+ ## Conformance Validation
114
+
115
+ ```ruby
116
+ doc = Pdfrb.open("archival.pdf")
117
+
118
+ # PDF/A
119
+ result = Pdfrb::Conformance::PdfA.validate(doc, level: :a2b)
120
+ puts "PDF/A-2b: #{result.passed? ? 'PASS' : 'FAIL'}"
121
+ result.errors.each { |e| puts " ERROR: #{e.message}" }
122
+
123
+ # PDF/UA
124
+ result = Pdfrb::Conformance::PdfUA.validate(doc)
125
+ puts "PDF/UA: #{result.passed? ? 'PASS' : 'FAIL'}"
126
+ ```
127
+
128
+ ## Linearization (Fast Web View)
129
+
130
+ ```ruby
131
+ doc = Pdfrb.open("large.pdf")
132
+ io = StringIO.new
133
+ Pdfrb::Linearization::Writer.new(doc).write(io)
134
+ File.binwrite("linearized.pdf", io.string)
135
+ ```
136
+
137
+ ## Encryption
138
+
139
+ ```ruby
140
+ doc = Pdfrb.open("input.pdf")
141
+ doc.write("encrypted.pdf")
142
+ # Encryption configuration via document.config
143
+ ```
144
+
145
+ ## Merging PDFs
146
+
147
+ ```ruby
148
+ target = Pdfrb.open("base.pdf")
149
+ source = Pdfrb.open("appendix.pdf")
150
+ Pdfrb::Task::Merge.call(target, source)
151
+ target.write("merged.pdf")
152
+ ```
153
+
154
+ ## Extracting Images
155
+
156
+ ```ruby
157
+ doc = Pdfrb.open("input.pdf")
158
+ images = Pdfrb::Task::ExtractImages.call(doc)
159
+ images.each_with_index do |img, i|
160
+ File.binwrite("image_#{i}.#{img[:format]}", img[:data])
161
+ end
162
+ ```
163
+
164
+ ## CLI
165
+
166
+ ```sh
167
+ pdfrb info input.pdf
168
+ pdfrb extract-text input.pdf
169
+ pdfrb merge a.pdf b.pdf -o merged.pdf
170
+ pdfrb diff v1.pdf v2.pdf
171
+ pdfrb encrypt input.pdf -o encrypted.pdf
172
+ pdfrb optimize input.pdf -o optimized.pdf
173
+ ```
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # GoToE action (s12.6.4.4, PDF 1.6). Navigate to a destination in
7
+ # an embedded PDF file.
8
+ class ActionGoToE < Action
9
+ arlington_object "ActionGoToE"
10
+ register_subtype :GoToE
11
+
12
+ def target_file; self[:F]; end
13
+ def destination; self[:D]; end
14
+ def new_window; self[:NewWindow]; end
15
+ def target; self[:T]; end
16
+
17
+ def new_window?
18
+ new_window == true
19
+ end
20
+
21
+ def targets_embedded_file?
22
+ !target_file.nil?
23
+ end
24
+
25
+ def named_destination?
26
+ destination.is_a?(Symbol) || destination.is_a?(String)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -6,11 +6,12 @@ module Pdfrb
6
6
  # RichMediaExecute action (s12.6.4.12, PDF 2.0). Execute a
7
7
  # command on a RichMedia annotation.
8
8
  class ActionRichMediaExecute < Action
9
+ arlington_object "ActionRichMediaExecute"
9
10
  register_subtype :RichMediaExecute
10
11
 
11
12
  def target; self[:TA]; end
12
- def instance; self[:Instance]; end
13
- def arguments; self[:Args]; end
13
+ def instance; self[:TI]; end
14
+ def command; self[:CMD]; end
14
15
  end
15
16
  end
16
17
  end
@@ -5,6 +5,7 @@ module Pdfrb
5
5
  module Type
6
6
  # Thread action (s12.6.4.6). Navigate within an article thread.
7
7
  class ActionThread < Action
8
+ arlington_object "ActionThread"
8
9
  register_subtype :Thread
9
10
 
10
11
  def thread; self[:F]; end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Additional Actions for interactive form fields (s12.6.3.17,
7
+ # Table 199). All four triggers carry JavaScript actions.
8
+ class AddActionFormField < Pdfrb::Model::Cos::Dictionary
9
+ arlington_object "AddActionFormField"
10
+
11
+ # /K — keystroke: format before committing a changed value.
12
+ def on_keystroke(document = nil)
13
+ resolve_action(:K, document)
14
+ end
15
+
16
+ # /F — format: reformat after a new value is committed.
17
+ def on_format(document = nil)
18
+ resolve_action(:F, document)
19
+ end
20
+
21
+ # /V — validate (recalculate) after the field value changes.
22
+ def on_validate(document = nil)
23
+ resolve_action(:V, document)
24
+ end
25
+
26
+ # /C — recalculate when another field changes.
27
+ def on_calculate(document = nil)
28
+ resolve_action(:C, document)
29
+ end
30
+
31
+ private
32
+
33
+ def resolve_action(key, document)
34
+ ref = value[key]
35
+ return nil unless ref && document
36
+
37
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Additional Actions for screen annotations (s12.6.3.17, PDF 1.5).
7
+ # Media events on the screen's region.
8
+ class AddActionScreenAnnotation < Pdfrb::Model::Cos::Dictionary
9
+ arlington_object "AddActionScreenAnnotation"
10
+
11
+ # /E — cursor enters the screen region.
12
+ def on_cursor_enter(document = nil)
13
+ resolve_action(:E, document)
14
+ end
15
+
16
+ # /X — cursor exits the screen region.
17
+ def on_cursor_exit(document = nil)
18
+ resolve_action(:X, document)
19
+ end
20
+
21
+ # /D — mouse button pressed inside.
22
+ def on_mouse_down(document = nil)
23
+ resolve_action(:D, document)
24
+ end
25
+
26
+ # /U — mouse button released inside.
27
+ def on_mouse_up(document = nil)
28
+ resolve_action(:U, document)
29
+ end
30
+
31
+ # /PO — page containing the screen is opened.
32
+ def on_page_open(document = nil)
33
+ resolve_action(:PO, document)
34
+ end
35
+
36
+ # /PC — page containing the screen is closed.
37
+ def on_page_close(document = nil)
38
+ resolve_action(:PC, document)
39
+ end
40
+
41
+ # /PV — screen becomes visible.
42
+ def on_visible(document = nil)
43
+ resolve_action(:PV, document)
44
+ end
45
+
46
+ # /PI — screen becomes invisible.
47
+ def on_invisible(document = nil)
48
+ resolve_action(:PI, document)
49
+ end
50
+
51
+ private
52
+
53
+ def resolve_action(key, document)
54
+ ref = value[key]
55
+ return nil unless ref && document
56
+
57
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Additional Actions for widget annotations (s12.6.3.17, PDF 1.2).
7
+ # Mouse, focus, and page events on the widget's region.
8
+ class AddActionWidgetAnnotation < Pdfrb::Model::Cos::Dictionary
9
+ arlington_object "AddActionWidgetAnnotation"
10
+
11
+ # /E — cursor enters the widget's region.
12
+ def on_cursor_enter(document = nil)
13
+ resolve_action(:E, document)
14
+ end
15
+
16
+ # /X — cursor exits the widget's region.
17
+ def on_cursor_exit(document = nil)
18
+ resolve_action(:X, document)
19
+ end
20
+
21
+ # /D — mouse button pressed inside.
22
+ def on_mouse_down(document = nil)
23
+ resolve_action(:D, document)
24
+ end
25
+
26
+ # /U — mouse button released inside.
27
+ def on_mouse_up(document = nil)
28
+ resolve_action(:U, document)
29
+ end
30
+
31
+ # /Fo — widget receives input focus.
32
+ def on_focus(document = nil)
33
+ resolve_action(:Fo, document)
34
+ end
35
+
36
+ # /Bl — widget loses input focus.
37
+ def on_blur(document = nil)
38
+ resolve_action(:Bl, document)
39
+ end
40
+
41
+ # /PO — page containing the widget is opened.
42
+ def on_page_open(document = nil)
43
+ resolve_action(:PO, document)
44
+ end
45
+
46
+ # /PC — page containing the widget is closed.
47
+ def on_page_close(document = nil)
48
+ resolve_action(:PC, document)
49
+ end
50
+
51
+ # /PV — widget becomes visible.
52
+ def on_visible(document = nil)
53
+ resolve_action(:PV, document)
54
+ end
55
+
56
+ # /PI — widget becomes invisible.
57
+ def on_invisible(document = nil)
58
+ resolve_action(:PI, document)
59
+ end
60
+
61
+ private
62
+
63
+ def resolve_action(key, document)
64
+ ref = value[key]
65
+ return nil unless ref && document
66
+
67
+ ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -6,7 +6,7 @@ module Pdfrb
6
6
  # AppearanceTrapNet sub-dictionary (s7.7.3.3, Table 327). Per-
7
7
  # appearance-stream trap-net (ink-flattening) parameters.
8
8
  class AppearanceTrapNetSubDict < Pdfrb::Model::Cos::Dictionary
9
- arlington_object "AppearanceTrapNet"
9
+ arlington_object "AppearanceTrapNetSubDict"
10
10
  def pos_h; self[:PosH]; end
11
11
  def pos_l; self[:PosL]; end
12
12
  def span_h_min; self[:SpanH]; end
@@ -19,8 +19,13 @@ module Pdfrb
19
19
  end
20
20
 
21
21
  # AppearanceTrapNet (s7.7.3.3). The trap-net dictionary that wraps
22
- # appearance sub-dicts.
22
+ # appearance sub-dicts (/N, /R, /D).
23
23
  class AppearanceTrapNet < Pdfrb::Model::Cos::Dictionary
24
+ arlington_object "AppearanceTrapNet"
25
+ def normal; self[:N]; end
26
+ def rollover; self[:R]; end
27
+ def down; self[:D]; end
28
+
24
29
  def type; self[:Type]; end
25
30
  def version; self[:Version]; end
26
31
  def font_state_appearance; self[:FontStateAppearance]; end
@@ -41,6 +46,7 @@ module Pdfrb
41
46
  # AppearanceSubDict (s12.5.4). Sub-dictionary inside Appearance
42
47
  # entries /N, /R, /D that maps each appearance state to a stream.
43
48
  class AppearanceSubDict < Pdfrb::Model::Cos::Dictionary
49
+ arlington_object "AppearanceSubDict"
44
50
  def each_state(&block)
45
51
  return enum_for(:each_state) unless block
46
52
 
@@ -64,22 +70,6 @@ module Pdfrb
64
70
  !!app_build
65
71
  end
66
72
  end
67
-
68
- # Annotation Projection dict (s12.5.6.21). Projection annotation
69
- # for spatial content.
70
- class AnnotationProjectionDict < Pdfrb::Model::Cos::Dictionary
71
- def ex_data; self[:ExData]; end
72
- end
73
-
74
- # ExData Projection dict (s12.5.6.21, Table 198). Holds the
75
- # geospatial projection details used by Projection annotations.
76
- class ExDataProjection < Pdfrb::Model::Cos::Dictionary
77
- def type; self[:Type]; end
78
-
79
- def project?
80
- type == :ProjectedPDL
81
- end
82
- end
83
73
  end
84
74
  end
85
75
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Movie annotation (s12.5.6.14). /Subtype /Movie. Plays a Movie
7
+ # when activated.
8
+ class MovieAnnotation < Annotation
9
+ arlington_object "AnnotMovie"
10
+
11
+ def movie; self[:Movie]; end
12
+ def action; self[:A]; end
13
+ def title; self[:T]; end
14
+
15
+ def has_movie?
16
+ !movie.nil?
17
+ end
18
+
19
+ def uses_action?
20
+ !action.nil?
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Projection annotation (s12.5.6.19, PDF 1.7+AdobeExt). Projects
7
+ # a duplicate of a region of a page with a modified appearance.
8
+ class ProjectionAnnotation < MarkupAnnotation
9
+ arlington_object "AnnotProjection"
10
+
11
+ def title; self[:T]; end
12
+ def popup; self[:Popup]; end
13
+ def rich_contents; self[:RC]; end
14
+ def creation_date; self[:CreationDate]; end
15
+ def in_reply_to; self[:IRT]; end
16
+ def subject; self[:Subj]; end
17
+ def reply_type; self[:RT]; end
18
+ def intent; self[:IT]; end
19
+ def ex_data; self[:ExData]; end
20
+
21
+ def has_projection_data?
22
+ !ex_data.nil?
23
+ end
24
+ end
25
+
26
+ # Annotation Projection dict (s12.5.6.21). Projection annotation
27
+ # for spatial content.
28
+ class AnnotationProjectionDict < Pdfrb::Model::Cos::Dictionary
29
+ def ex_data; self[:ExData]; end
30
+ end
31
+
32
+ # ExData Projection dict (s12.5.6.21, Table 198). Holds the
33
+ # geospatial projection details used by Projection annotations.
34
+ class ExDataProjection < Pdfrb::Model::Cos::Dictionary
35
+ def type; self[:Type]; end
36
+
37
+ def project?
38
+ type == :ProjectedPDL
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # 3D annotation (s13.6.2, PDF 1.6+). /Subtype /3D. Hosts a 3D
7
+ # artwork stream, activation behaviour, and viewing state.
8
+ class ThreeDAnnotation < Annotation
9
+ arlington_object "Annot3D"
10
+
11
+ def artwork; self[:"3DD"]; end
12
+ def default_view; self[:"3DV"]; end
13
+ def activation; self[:"3DA"]; end
14
+ def interactive; self[:"3DI"]; end
15
+ def view_box; self[:"3DB"]; end
16
+ def units; self[:"3DU"]; end
17
+ def geometry; self[:GEO]; end
18
+
19
+ def interactive?
20
+ interactive == true
21
+ end
22
+
23
+ def has_measure?
24
+ !geometry.nil?
25
+ end
26
+
27
+ def default_view_name?
28
+ default_view.is_a?(Symbol) || default_view.is_a?(String)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Trap network annotation (s14.11.5). Marks the extent of the
7
+ # trap network applied by a prepress system. Its appearance
8
+ # stream carries per-colorant trap parameters.
9
+ class TrapNetworkAnnotation < MarkupAnnotation
10
+ arlington_object "AnnotTrapNetwork"
11
+
12
+ def last_modified; self[:LastModified]; end
13
+ def version; self[:Version]; end
14
+ def annot_states; self[:AnnotStates]; end
15
+ def font_fauxing; self[:FontFauxing]; end
16
+
17
+ def annot_states?
18
+ !annot_states.nil?
19
+ end
20
+
21
+ def fauxed_font_names
22
+ fonts = font_fauxing
23
+ fonts.is_a?(Pdfrb::Model::PdfArray) ? fonts.to_a : fonts
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -201,6 +201,10 @@ module Pdfrb
201
201
  autoload :PrinterMarkSubDict, "pdfrb/model/type/transition"
202
202
  autoload :ScreenAnnotation, "pdfrb/model/type/screen_annotation"
203
203
  autoload :SoundAnnotation, "pdfrb/model/type/sound_annotation"
204
+ autoload :ThreeDAnnotation, "pdfrb/model/type/three_d_annotation"
205
+ autoload :MovieAnnotation, "pdfrb/model/type/movie_annotation"
206
+ autoload :ProjectionAnnotation, "pdfrb/model/type/projection_annotation"
207
+ autoload :TrapNetworkAnnotation, "pdfrb/model/type/trap_network_annotation"
204
208
 
205
209
  # Rich Media annotation family (s13.6).
206
210
  autoload :RichMediaAnnotation, "pdfrb/model/type/rich_media_annotation"
@@ -270,6 +274,7 @@ module Pdfrb
270
274
  autoload :ActionGoTo3DView, "pdfrb/model/type/action_go_to_3d_view"
271
275
  autoload :ActionGoToDp, "pdfrb/model/type/action_go_to_dp"
272
276
  autoload :ActionRichMediaExecute, "pdfrb/model/type/action_rich_media_execute"
277
+ autoload :ActionGoToE, "pdfrb/model/type/action_go_to_e"
273
278
  autoload :ActionNOP, "pdfrb/model/type/action_nop"
274
279
 
275
280
  # Signature family (s12.8).
@@ -286,8 +291,8 @@ module Pdfrb
286
291
  autoload :AppearanceSubDict, "pdfrb/model/type/appearance_trap_net"
287
292
  autoload :MediaClip, "pdfrb/model/type/media_clip"
288
293
  autoload :Rendition, "pdfrb/model/type/rendition"
289
- autoload :ExDataProjection, "pdfrb/model/type/appearance_trap_net"
290
- autoload :AnnotationProjectionDict, "pdfrb/model/type/appearance_trap_net"
294
+ autoload :ExDataProjection, "pdfrb/model/type/projection_annotation"
295
+ autoload :AnnotationProjectionDict, "pdfrb/model/type/projection_annotation"
291
296
 
292
297
  # Media offset / player / screen types.
293
298
  autoload :MediaOffsetTime, "pdfrb/model/type/media_offset"
@@ -405,6 +410,12 @@ module Pdfrb
405
410
  # Additional actions on page objects (s12.6.3.16).
406
411
  autoload :AddActionPageObject, "pdfrb/model/type/add_action_page_object"
407
412
 
413
+ # Additional actions on form fields / screen + widget annotations
414
+ # (s12.6.3.17).
415
+ autoload :AddActionFormField, "pdfrb/model/type/add_action_form_field"
416
+ autoload :AddActionScreenAnnotation, "pdfrb/model/type/add_action_screen_annotation"
417
+ autoload :AddActionWidgetAnnotation, "pdfrb/model/type/add_action_widget_annotation"
418
+
408
419
  # Border style (s12.5.4). BorderEffect lives in its own file.
409
420
  autoload :BorderStyle, "pdfrb/model/type/border_style"
410
421
  autoload :BorderEffect, "pdfrb/model/type/border_effect"
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.21"
4
+ VERSION = "0.7.23"
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.21
4
+ version: 0.7.23
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-17 00:00:00.000000000 Z
11
+ date: 2026-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -701,6 +701,8 @@ files:
701
701
  - data/pdfrb/glyphlist.txt
702
702
  - data/pdfrb/layout/hyphenation_en.txt
703
703
  - data/pdfrb/zapfdingbats.txt
704
+ - docs/SEMVER.md
705
+ - docs/USAGE.md
704
706
  - exe/pdfrb
705
707
  - lib/pdfrb.rb
706
708
  - lib/pdfrb/action.rb
@@ -954,6 +956,7 @@ files:
954
956
  - lib/pdfrb/model/type/action.rb
955
957
  - lib/pdfrb/model/type/action_go_to_3d_view.rb
956
958
  - lib/pdfrb/model/type/action_go_to_dp.rb
959
+ - lib/pdfrb/model/type/action_go_to_e.rb
957
960
  - lib/pdfrb/model/type/action_go_to_r.rb
958
961
  - lib/pdfrb/model/type/action_goto.rb
959
962
  - lib/pdfrb/model/type/action_hide.rb
@@ -975,7 +978,10 @@ files:
975
978
  - lib/pdfrb/model/type/action_trans.rb
976
979
  - lib/pdfrb/model/type/action_uri.rb
977
980
  - lib/pdfrb/model/type/add_action_catalog.rb
981
+ - lib/pdfrb/model/type/add_action_form_field.rb
978
982
  - lib/pdfrb/model/type/add_action_page_object.rb
983
+ - lib/pdfrb/model/type/add_action_screen_annotation.rb
984
+ - lib/pdfrb/model/type/add_action_widget_annotation.rb
979
985
  - lib/pdfrb/model/type/af_embedded_file.rb
980
986
  - lib/pdfrb/model/type/af_file_specification.rb
981
987
  - lib/pdfrb/model/type/alternate_image.rb
@@ -1077,6 +1083,7 @@ files:
1077
1083
  - lib/pdfrb/model/type/metadata.rb
1078
1084
  - lib/pdfrb/model/type/misc_helpers.rb
1079
1085
  - lib/pdfrb/model/type/movie.rb
1086
+ - lib/pdfrb/model/type/movie_annotation.rb
1080
1087
  - lib/pdfrb/model/type/names.rb
1081
1088
  - lib/pdfrb/model/type/namespace.rb
1082
1089
  - lib/pdfrb/model/type/object_reference.rb
@@ -1103,6 +1110,7 @@ files:
1103
1110
  - lib/pdfrb/model/type/polyline_annotation.rb
1104
1111
  - lib/pdfrb/model/type/popup_annotation.rb
1105
1112
  - lib/pdfrb/model/type/printer_mark_annotation.rb
1113
+ - lib/pdfrb/model/type/projection_annotation.rb
1106
1114
  - lib/pdfrb/model/type/redact_annotation.rb
1107
1115
  - lib/pdfrb/model/type/rendition.rb
1108
1116
  - lib/pdfrb/model/type/resources.rb
@@ -1144,6 +1152,7 @@ files:
1144
1152
  - lib/pdfrb/model/type/thread.rb
1145
1153
  - lib/pdfrb/model/type/three_d_activation.rb
1146
1154
  - lib/pdfrb/model/type/three_d_animation_style.rb
1155
+ - lib/pdfrb/model/type/three_d_annotation.rb
1147
1156
  - lib/pdfrb/model/type/three_d_background.rb
1148
1157
  - lib/pdfrb/model/type/three_d_cross_section.rb
1149
1158
  - lib/pdfrb/model/type/three_d_lighting_scheme.rb
@@ -1163,6 +1172,7 @@ files:
1163
1172
  - lib/pdfrb/model/type/timespan.rb
1164
1173
  - lib/pdfrb/model/type/to_unicode_cmap_stream.rb
1165
1174
  - lib/pdfrb/model/type/transition.rb
1175
+ - lib/pdfrb/model/type/trap_network_annotation.rb
1166
1176
  - lib/pdfrb/model/type/trap_region.rb
1167
1177
  - lib/pdfrb/model/type/underline_annotation.rb
1168
1178
  - lib/pdfrb/model/type/ur_transform_parameters.rb
@@ -1218,7 +1228,6 @@ files:
1218
1228
  - lib/pdfrb/xmp/packet.rb
1219
1229
  - lib/pdfrb/xmp/schemas.rb
1220
1230
  - lib/pdfrb/xref_section.rb
1221
- - pdfrb.gemspec
1222
1231
  - script/apply_fixes.sh
1223
1232
  - script/make_jpeg_fixture.rb
1224
1233
  - script/make_png_fixture.rb
data/pdfrb.gemspec DELETED
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/pdfrb/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "pdfrb"
7
- spec.version = Pdfrb::VERSION
8
- spec.authors = ["Ribose Inc."]
9
- spec.email = ["open.source@ribose.com"]
10
-
11
- spec.summary = "Pure-Ruby PDF parser, Arlington-model-driven domain model, and serializer"
12
- spec.description = <<~HEREDOC
13
- Pdfrb is a pure-Ruby PDF library: a byte-level reader, an
14
- Arlington-model-driven typed domain model, and a serializer. The
15
- PDF object model is sourced directly from the vendored Arlington
16
- PDF Model TSVs (machine-readable ISO 32000-2:2020), so field
17
- metadata, version predicates, and validators stay aligned with
18
- the spec by data, not by hand-coded mimicry.
19
-
20
- Two-direction contract: "PDF file <=> Model" and "API Builder
21
- Input => Model". Mirrors the layered design of the sibling
22
- postscript gem.
23
- HEREDOC
24
-
25
- spec.homepage = "https://github.com/claricle/pdfrb"
26
- spec.license = "BSD-2-Clause"
27
- spec.required_ruby_version = ">= 3.2.0"
28
-
29
- spec.metadata["homepage_uri"] = spec.homepage
30
- spec.metadata["source_code_uri"] = "https://github.com/claricle/pdfrb"
31
- spec.metadata["changelog_uri"] = "https://github.com/claricle/pdfrb/blob/main/CHANGELOG.md"
32
- spec.metadata["bug_tracker_uri"] = "https://github.com/claricle/pdfrb/issues"
33
- spec.metadata["rubygems_mfa_required"] = "true"
34
-
35
- spec.files = Dir.chdir(__dir__) do
36
- `git ls-files -z`.split("\x0").reject do |f|
37
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
38
- end
39
- end
40
- spec.bindir = "exe"
41
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
42
- spec.require_paths = ["lib"]
43
-
44
- spec.add_dependency "thor"
45
- end