pdfrb 0.6.0 → 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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +144 -0
  3. data/RELEASE.md +52 -33
  4. data/data/pdfrb/afm/Courier-Bold.afm +342 -342
  5. data/data/pdfrb/afm/Courier-BoldOblique.afm +342 -342
  6. data/data/pdfrb/afm/Courier-Oblique.afm +342 -342
  7. data/data/pdfrb/afm/Courier.afm +342 -342
  8. data/data/pdfrb/afm/Helvetica-Bold.afm +2827 -2827
  9. data/data/pdfrb/afm/Helvetica-BoldOblique.afm +2827 -2827
  10. data/data/pdfrb/afm/Helvetica-Oblique.afm +3051 -3051
  11. data/data/pdfrb/afm/Helvetica.afm +3051 -3051
  12. data/data/pdfrb/afm/Symbol.afm +213 -213
  13. data/data/pdfrb/afm/Times-Bold.afm +2588 -2588
  14. data/data/pdfrb/afm/Times-BoldItalic.afm +2384 -2384
  15. data/data/pdfrb/afm/Times-Italic.afm +2667 -2667
  16. data/data/pdfrb/afm/Times-Roman.afm +2419 -2419
  17. data/data/pdfrb/afm/ZapfDingbats.afm +225 -225
  18. data/data/pdfrb/layout/hyphenation_en.txt +408 -0
  19. data/lib/pdfrb/color/default_profile.rb +213 -0
  20. data/lib/pdfrb/color/icc_validator.rb +69 -0
  21. data/lib/pdfrb/color.rb +2 -0
  22. data/lib/pdfrb/conformance/ltv.rb +112 -0
  23. data/lib/pdfrb/conformance/pades.rb +198 -0
  24. data/lib/pdfrb/conformance/pdf_2_af.rb +185 -0
  25. data/lib/pdfrb/conformance/pdf_a.rb +123 -0
  26. data/lib/pdfrb/conformance/pdf_a4_deep.rb +94 -0
  27. data/lib/pdfrb/conformance/pdf_ua2_deep.rb +93 -0
  28. data/lib/pdfrb/conformance/pdf_ua_tagging_deep.rb +125 -0
  29. data/lib/pdfrb/conformance/pdf_vt.rb +128 -0
  30. data/lib/pdfrb/conformance/pdf_x.rb +66 -1
  31. data/lib/pdfrb/conformance/tagged_pdf.rb +182 -0
  32. data/lib/pdfrb/conformance.rb +8 -0
  33. data/lib/pdfrb/content/canvas.rb +137 -0
  34. data/lib/pdfrb/content/operators/inline_image.rb +53 -0
  35. data/lib/pdfrb/content/operators.rb +1 -0
  36. data/lib/pdfrb/content/parser.rb +82 -0
  37. data/lib/pdfrb/digital_signature/timestamp_client.rb +86 -0
  38. data/lib/pdfrb/digital_signature.rb +1 -0
  39. data/lib/pdfrb/document.rb +29 -0
  40. data/lib/pdfrb/encryption/public_key_security_handler.rb +146 -0
  41. data/lib/pdfrb/encryption/standard_security_handler.rb +98 -3
  42. data/lib/pdfrb/encryption/v5_writer.rb +108 -0
  43. data/lib/pdfrb/encryption.rb +3 -0
  44. data/lib/pdfrb/font_loader/type3.rb +65 -0
  45. data/lib/pdfrb/font_loader.rb +1 -0
  46. data/lib/pdfrb/image_loader/gif.rb +246 -0
  47. data/lib/pdfrb/image_loader/png.rb +76 -19
  48. data/lib/pdfrb/image_loader/tiff.rb +257 -0
  49. data/lib/pdfrb/image_loader.rb +2 -0
  50. data/lib/pdfrb/layout/font_fallback.rb +203 -0
  51. data/lib/pdfrb/layout/hyphenation.rb +120 -0
  52. data/lib/pdfrb/layout/justification_kashidas.rb +72 -0
  53. data/lib/pdfrb/layout/multi_cell_text_layout.rb +65 -0
  54. data/lib/pdfrb/layout/multi_page_table_box.rb +155 -0
  55. data/lib/pdfrb/layout/polygon_frame.rb +106 -0
  56. data/lib/pdfrb/layout/table_box.rb +154 -23
  57. data/lib/pdfrb/layout/text_shaper.rb +129 -0
  58. data/lib/pdfrb/layout.rb +7 -0
  59. data/lib/pdfrb/model/type/page_piece_info.rb +58 -0
  60. data/lib/pdfrb/model/type.rb +3 -0
  61. data/lib/pdfrb/source/linearization_reader.rb +76 -0
  62. data/lib/pdfrb/source/recovery.rb +65 -1
  63. data/lib/pdfrb/source/tokenizer.rb +21 -0
  64. data/lib/pdfrb/source.rb +1 -0
  65. data/lib/pdfrb/task/regenerate_appearances.rb +98 -0
  66. data/lib/pdfrb/task/thumbnail.rb +133 -0
  67. data/lib/pdfrb/task.rb +2 -0
  68. data/lib/pdfrb/version.rb +1 -1
  69. metadata +35 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f24b6c90eb4e01436139908a7aaa0472ed8a22704e40e934f651c0265763d62
4
- data.tar.gz: da4e7fc8a4f9c4cecbbf22ca2ab2288ca8f07c4bc974dc6eac8b2166fb784d94
3
+ metadata.gz: e852ec0176452037ffd0e715fc4edd866261d20e9de19938e0342741701e7f4a
4
+ data.tar.gz: 1e36dcfec95c64efa1265c4264a34f290ecd82de3b7acc65dd6d6c315b845e4b
5
5
  SHA512:
6
- metadata.gz: 550b8e52600d4ebe1cffbce341d0725d750a41ba8585c1b85c827f9c7a4b6fda7e24d6dd6f3c2ed6f5f83e442729e792f3fef05a9d34459118a9720d039bf3bb
7
- data.tar.gz: c950a24d0cf3af6734edbe2819d0390c07442fa941e026be4744fb6db0e02beadc4e3d2ac220fbb5d4f52eee67bc3e9d19e03602dabaaefdf65929ecbe1a61d3
6
+ metadata.gz: '085c4d548c341bb9db63df48b0b5c9efc2eb897c135e36b57f36cd1385c7062a5b08f043113695f2a0b5f30caa4e02d11fa5031cbf870b83827bc4303cddc0f3'
7
+ data.tar.gz: a5a131520e73cee21be784f947e6bf21c348d708b54d86757a90b6dc3a2de925ca8188b544f7864b53c4930d60c3a101f4281e9517adf4188f2b6d85dc1eeb1b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,150 @@
2
2
 
3
3
  All notable changes to the pdfrb gem will be documented in this file.
4
4
 
5
+ ## [Unreleased]
6
+
7
+ ### Added — Parity batches 4-9
8
+
9
+ * **TODO 103 Hyphenation** — Knuth-Liang `Pdfrb::Layout::Hyphenation`
10
+ with curated English patterns in `data/pdfrb/layout/hyphenation_en.txt`.
11
+ * **TODO 116 PDF/X-6** — `Pdfrb::Conformance::PdfX#X6` ISO 15930-11
12
+ profile.
13
+ * **TODO 117 PDF/VT** — `Pdfrb::Conformance::PdfVT` (VT-1, VT-2)
14
+ ISO 16612-2 profiles.
15
+ * **TODO 118 Multi-revision traversal** — `Document#each_revision`
16
+ walks the `/Prev` chain yielding `(revision_index, xref, trailer)`.
17
+ * **TODO 119 Table cell spans** — `TableBox.cell(box, colspan:,
18
+ rowspan:)`, hash-form cells, span-aware layout.
19
+ * **TODO 120 Multi-page table** — `MultiPageTableBox` splits a table
20
+ across pages with header-row repeat.
21
+ * **TODO 122 Bidi** — `Pdfrb::Layout::Bidi` paragraph-level UAX #9
22
+ reordering; `TextLayouter` reorders Hebrew/Arabic for visual order.
23
+ * **TODO 128 Linearization-aware reader** —
24
+ `Source::LinearizationReader.detect(io)` parses the first indirect
25
+ object's dict for `/Linearized`.
26
+ * **TODO 129 Type3 font loader** — `Pdfrb::FontLoader::Type3` with
27
+ glyph procedures + encoding.
28
+ * **TODO 131 Inline images (write)** — `Canvas#inline_image(dict:,
29
+ data:)` plus `Operator::{BeginInlineImage, EndInlineImage}`.
30
+ * **TODO 133 Custom canvas primitives** — `polyline`, `polygon`,
31
+ `arc`, `circle`, `ellipse`, `rounded_rectangle`, `dash=`.
32
+ * **TODO 135 PDF thumbnail generation** — `Pdfrb::Task::Thumbnail`
33
+ builds `/Thumb` image XObjects on every page.
34
+ * **TODO 136 PDF/A preflight deep** — `PREFLIGHT_DEEP` rule set on
35
+ PdfA (JavaScript, PostScript XObjects, encryption, embedded-file
36
+ bans for A-1/A-2/A-4).
37
+ * **TODO 137 PDF/UA tagging deep** — list/LI/LBody, Table/TR,
38
+ TH/Scope structural checks.
39
+ * **TODO 138 Tagged PDF validation** —
40
+ `Pdfrb::Conformance::TaggedPdf` baseline structural rule set.
41
+ * **TODO 140 PDF 2.0 AF validation** —
42
+ `Pdfrb::Conformance::Pdf2AF` App Note 002 validator.
43
+ * **TODO 104 Default ICC profile** — `Color::DefaultProfile` emits a
44
+ usable sRGB v4 ICC profile with desc/wtpt/rXYZ/gXYZ/bXYZ/rTRC/
45
+ gTRC/bTRC tags and a real MD5 Profile ID.
46
+ * **TODO 139 ICC profile validation** —
47
+ `Pdfrb::Color::ICCValidator` checks signature, version, device
48
+ class, color space per ICC.1:2022 §7.
49
+ * **TODO 108 Image downsampling** —
50
+ `Pdfrb::Image::Downsampler` + `Task::Optimize#downsample_images!`
51
+ for FlateDecode 8-bpc non-palette images.
52
+ * **TODO 130 Color-key masking** — `ImageLoader::PNG` parses tRNS and
53
+ emits `/Mask` color-key array.
54
+ * **TODO 131 Inline images (read)** — `Content::Parser` recognises
55
+ the BI/ID/EI sequence and yields an `InlineImage` invocation.
56
+ * **TODO 132 Page-piece dict** —
57
+ `Pdfrb::Model::Type::PagePieceInfo` per s14.5.
58
+ * **TODO 134 Tagged PDF alt-text API** — `Document::Structure`
59
+ facade for `/Alt`, `/ActualText`, `/Lang`.
60
+ * **Layout** — cluster-aware default `TextShaper`, real AFM-based
61
+ `FontFallback`, `PolygonFrame` with proper inscribed-rectangle
62
+ scan, `MultiCellTextLayout`, `JustificationKashidas`.
63
+ * **Encryption** — `StandardSecurityHandler.for_v5` write-side
64
+ AES-256 R6 handler (file key + `/U`/`/O`/`/UE`/`/OE`/`/Perms`),
65
+ `V5Writer` PKCS#5 algorithms, `PublicKeySecurityHandler` with
66
+ real CMS EnvelopedData construction via `OpenSSL::PKCS7`.
67
+ * **Signatures** — `Pdfrb::Conformance::Pades` (B-B, B-T, B-LT,
68
+ B-LTA profiles), `Pdfrb::Conformance::Ltv` long-term validation,
69
+ `Pdfrb::Conformance::PdfA4Deep`, `PdfUA2Deep`,
70
+ `DigitalSignature::TimestampClient` (RFC 3161 TSA over HTTPS).
71
+ * **Images** — `ImageLoader::TIFF` decodes uncompressed RGB/gray;
72
+ `ImageLoader::GIF` does full GIF-spec LZW decode with palette.
73
+ * **Source** — extended `Pdfrb::Source::Recovery` with
74
+ trailer-reference recovery, hybrid-xref detection,
75
+ object-stream rebuild.
76
+ * **Tasks** — `Pdfrb::Task::RegenerateAppearances` walks widget
77
+ annotations and rebuilds `/AP /N` via `Appearance::Generator`.
78
+
79
+ ### Fixed
80
+
81
+ * Stream deduplication in `Task::Optimize` (was a stub).
82
+ * `Writer#write_xref_stream` now emits a free entry for every gap
83
+ in the oid space (was misaligning the reader).
84
+ * `Document::Form#flatten!` now stamps field appearances into page
85
+ content via `/Do` (was a stub).
86
+ * Issue #63: PostScript name extraction for `/BaseFont`.
87
+ * Issue #64: `Resources#empty?` handles Hash, Array, Cos::Dictionary,
88
+ PdfArray.
89
+
90
+ ### Changed
91
+
92
+ * Release workflow switched to emf2svg-ruby pattern: direct OIDC
93
+ trusted publishing via `rubygems/configure-rubygems-credentials@main`
94
+ + plain `gem push`. Bump job commits version.rb and tags `vX.Y.Z`.
95
+ * Removed all `instance_variable_set/get`, `send` to private
96
+ methods, `respond_to?` for type checks.
97
+
98
+ ## [0.7.0] — 2026-08-08
99
+
100
+ ### Added — Release infrastructure
101
+
102
+ * `.github/workflows/rake.yml` — Metanorma CI generic-rake workflow
103
+ for tests on every push, PR, tag, and dispatch.
104
+ * `.github/workflows/release.yml` — Metanorma CI rubygems-release
105
+ workflow driven by `workflow_dispatch` with `next_version` input
106
+ or `repository_dispatch` of type `do-release`.
107
+ * `RELEASE.md` — documents the publish flow and required secrets.
108
+
109
+ ### Added — Image subsystem
110
+
111
+ * `Pdfrb::Image::Audit` — read-only metadata extractor (ImageInfo
112
+ struct per image XObject) with `each_image`, `all`, `oversized`
113
+ helpers.
114
+ * `Pdfrb::Image::Downsampler` — pure-Ruby nearest-neighbour for
115
+ FlateDecode-encoded 8-bpc non-palette images. PNG predictor
116
+ round-trip on both decode and encode. JPEG/JP2K skipped (no
117
+ native deps).
118
+ * `Pdfrb::Task::Optimize#downsample_images!(factor:)` — applies the
119
+ downsampler across every image XObject in the document.
120
+
121
+ ### Added — Layout bidi
122
+
123
+ * `Pdfrb::Layout::Bidi` — paragraph-level UAX #9 bidi reordering
124
+ (P2-P3 paragraph level, BD1 type classification, I1/I2 implicit
125
+ levels, L2 reverse by level, L4 paired-bracket mirroring).
126
+ * `Pdfrb::Layout::TextLayouter#layout` calls `Bidi.reorder` before
127
+ line breaking, so Hebrew and Arabic render in visual order.
128
+
129
+ ### Fixed
130
+
131
+ * Issue #63: `Document::Fonts#add` now extracts the PostScript name
132
+ (name table nameID 6) and uses it in `/BaseFont` (e.g.
133
+ `ABCDEF+MinionPro-Regular` instead of `ABCDEF+EmbeddedFont3132`).
134
+ * Issue #64: `Model::Type::Resources#empty?` handles Hash, Array,
135
+ Cos::Dictionary, and PdfArray values via a single
136
+ `empty_collection?` helper.
137
+
138
+ ### Changed
139
+
140
+ * `Pdfrb::Task::Optimize.dedup_streams!` now actually rewrites
141
+ references to duplicate streams (was a stub).
142
+ * `Pdfrb::Writer#write_xref_stream` emits a free entry for every
143
+ gap in the oid space, so dedup'd oids don't misalign the reader's
144
+ per-oid index.
145
+ * `Pdfrb::Document::Form#flatten!` stamps each field's `/AP /N`
146
+ appearance stream into the page content via the `/Do` operator
147
+ (was a stubbed no-op).
148
+
5
149
  ## [0.3.0] — 2026-08-02
6
150
 
7
151
  ### Added — Semantic PDF diff
data/RELEASE.md CHANGED
@@ -1,48 +1,67 @@
1
1
  # Releasing pdfrb
2
2
 
3
- Releases are driven by git tags. The release workflow is at
4
- `.github/workflows/release.yml` and runs on tag push (or manual dispatch
5
- for an existing tag).
3
+ Releases are driven by the Metanorma CI reusable workflow at
4
+ `.github/workflows/release.yml`. It supports two triggers:
6
5
 
7
- ## Publish flow
6
+ 1. **`workflow_dispatch`** with a `next_version` input — manual run
7
+ from the Actions UI. Accepted values: `x.y.z`, `major`, `minor`,
8
+ `patch`, `pre|rc|etc`, or `skip` (release the current gemspec
9
+ version as-is).
10
+ 2. **`repository_dispatch`** with event type `do-release` — for
11
+ automation triggers from other repos.
8
12
 
9
- 1. Ensure `lib/pdfrb/version.rb` has the target version.
10
- 2. Merge the version-bump change via a PR (never commit directly to main).
11
- 3. When the PR lands, tag the merged commit:
13
+ Both call
14
+ [`metanorma/ci/.github/workflows/rubygems-release.yml@main`](https://github.com/metanorma/ci/blob/main/.github/workflows/rubygems-release.yml),
15
+ which handles version bumping, tag creation, gem build, RubyGems
16
+ publish, and GitHub release creation.
12
17
 
13
- ```sh
14
- git tag v$(ruby -Ilib -e 'require "pdfrb/version"; print Pdfrb::VERSION')
15
- git push origin v<VERSION>
16
- ```
18
+ ## Authentication
17
19
 
18
- 4. The `Release` workflow fires automatically:
19
- - Verifies tag `lib/pdfrb/version.rb` match.
20
- - Builds the gem (`bundle exec rake build`).
21
- - Publishes to RubyGems via OIDC trusted publishing (no stored API key).
22
- - Creates a GitHub release with auto-generated notes.
20
+ The reusable workflow uses the `CLARICLE_CI_RUBYGEMS_API_KEY` secret
21
+ for RubyGems authentication. Ensure this secret is set in repo
22
+ Settings Secrets and Variables Actions.
23
23
 
24
- ## Trusted publishing (OIDC)
24
+ The `GITHUB_TOKEN` is passed as `pat_token` for the version-bump
25
+ commit/tag/push steps.
25
26
 
26
- The workflow uses `rubygems/configure-rubygems-credentials` with OIDC.
27
- To enable, on RubyGems:
27
+ ## Triggering a release
28
28
 
29
- 1. Open the `pdfrb` gem settings.
30
- 2. Add the GitHub workflow as a trusted publisher:
31
- - Repository: `claricle/pdfrb`
32
- - Workflow filename: `release.yml`
33
- - Environment: (leave blank)
29
+ ### From the Actions UI
34
30
 
35
- Until that is configured, the `Publish to RubyGems` step will fail.
31
+ 1. Go to Actions `release` workflow.
32
+ 2. Click "Run workflow".
33
+ 3. Enter the next version (e.g., `0.8.0`, `patch`, `minor`, `major`).
34
+ 4. Click "Run workflow".
36
35
 
37
- ## Manual dispatch
36
+ ### From the API / CI
38
37
 
39
- The workflow accepts a `tag` input. Run it from the Actions UI on a
40
- previously-pushed tag if the auto-trigger missed (e.g., the workflow
41
- file was added after the tag was pushed).
38
+ ```sh
39
+ gh workflow run release.yml \
40
+ -f next_version=0.8.0
41
+ ```
42
+
43
+ Or via `repository_dispatch` from another repo:
44
+
45
+ ```sh
46
+ gh api /repos/claricle/pdfrb/dispatches \
47
+ -f event_type=do-release \
48
+ -f 'client_payload[next_version]=0.8.0'
49
+ ```
50
+
51
+ ## CI (test) workflow
52
+
53
+ `.github/workflows/rake.yml` runs the standard Metanorma CI
54
+ generic-rake workflow on every push to `main`/`master`, every tag
55
+ push, every pull request, and via manual `workflow_dispatch`.
56
+
57
+ `.github/workflows/ci.yml` (the original hand-rolled CI) is also
58
+ present as a fallback.
42
59
 
43
60
  ## Pre-release checklist
44
61
 
45
- - `bundle exec rake` is green.
46
- - `lib/pdfrb/version.rb` matches the intended tag.
47
- - `CHANGELOG.md` has an entry for the new version.
48
- - No uncommitted changes on `main`.
62
+ * `bundle exec rake` is green locally.
63
+ * `lib/pdfrb/version.rb` matches the intended release (the release
64
+ workflow handles this automatically when given `next_version`).
65
+ * `CHANGELOG.md` has an entry for the new version.
66
+ * No uncommitted changes on `main`.
67
+ * `CLARICLE_CI_RUBYGEMS_API_KEY` secret is set in repo settings.