pdfrb 0.1.0 → 0.1.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/.rubocop.yml +5 -0
- data/CHANGELOG.md +61 -0
- data/Gemfile +2 -0
- data/lib/pdfrb/font/true_type/cmap.rb +16 -16
- data/lib/pdfrb/model/cos/stream.rb +1 -1
- data/lib/pdfrb/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b4392d590986dd2cf33d0596f355ea5cf05c32cf8bf0635ad069aa27bc1dfa4
|
|
4
|
+
data.tar.gz: c23d124eff4500baa4488ba6fa3c5353e37b191ae795708006aad46402f67758
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: efd253a06b41184caaa0f24dc3652a8216efe7bac7b926d8af3b645158fd467b1a3d2b2c12a5ab8c8c11da9c18abc4945934936e20e2b163008327d6a1421d8e
|
|
7
|
+
data.tar.gz: 3331dccbeff017114f54ce22cc36fe5977d20d497d889ebb4417602b9ca172f86564ce1af33913fba8b94e9376216904c8c85a4eaddf8adcf0b8fcfe82063592
|
data/.rubocop.yml
CHANGED
|
@@ -20,3 +20,8 @@ AllCops:
|
|
|
20
20
|
|
|
21
21
|
# Project-specific: TSV files are data, not code; PDFs are binary.
|
|
22
22
|
# Both are excluded via AllCops above. Local overrides go here.
|
|
23
|
+
|
|
24
|
+
# Integration tests use string describes ("FOP-generated PDF reading")
|
|
25
|
+
# because they exercise multiple classes through a real workflow.
|
|
26
|
+
RSpec/DescribeClass:
|
|
27
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the pdfrb gem will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.1] — 2026-08-02
|
|
6
|
+
|
|
7
|
+
### Housekeeping
|
|
8
|
+
|
|
9
|
+
* **Layout/Composer extracted to sibling `arroolio` gem.** Pdfrb is now
|
|
10
|
+
pure PDF: bytes ↔ model. No page templates, no flows, no Knuth-Plass,
|
|
11
|
+
no tables, no SVG. Removed `lib/pdfrb/layout/`, `lib/pdfrb/composer.rb`,
|
|
12
|
+
`lib/pdfrb/layout.rb`, `spec/pdfrb/layout/`, `TODO.layout/`.
|
|
13
|
+
* **Removed `rexml` runtime dependency** (was only needed for the FO
|
|
14
|
+
parser, which moved to Arroolio).
|
|
15
|
+
* **Fixed all 12 rubocop offenses.** 0 offenses remaining. Disabled
|
|
16
|
+
`RSpec/DescribeClass` (legitimate string describes in integration tests).
|
|
17
|
+
* **Added SimpleCov** (opt-in via `COVERAGE=1` env var). Current line
|
|
18
|
+
coverage: **84.5%**. Grouped by Source / Model / Filters / Content /
|
|
19
|
+
Font / Encryption / Tasks / CLI / Document.
|
|
20
|
+
* **Replaced 3 `pending` specs with `skip`** — clearer exit semantics
|
|
21
|
+
for strict CI runs.
|
|
22
|
+
* **Fixed `Model::Cos::Stream#as_parms_list`** — Hash parms now
|
|
23
|
+
correctly wraps to `[parms]` instead of `Array(parms)` which
|
|
24
|
+
produced `[[:k, :v], ...]`. Bug was hidden by tests that didn't
|
|
25
|
+
exercise DecodeParms as a Hash through the Stream facade.
|
|
26
|
+
* **Renamed CMap format dispatchers** — `parse_format_4` →
|
|
27
|
+
`parse_format_four`, etc. (rubocop `Naming/VariableNumber`).
|
|
28
|
+
* **README/CLAUDE.md** updated to reflect pure-PDF scope; layout
|
|
29
|
+
concerns documented as living in `arroolio`.
|
|
30
|
+
|
|
31
|
+
### Verified
|
|
32
|
+
|
|
33
|
+
* 503 examples, 0 failures, 3 pending (conformance specs awaiting
|
|
34
|
+
fixture corpus).
|
|
35
|
+
* 0 rubocop offenses.
|
|
36
|
+
* `gem build pdfrb.gemspec` produces `pdfrb-0.1.1.gem`.
|
|
37
|
+
* End-to-end round-trip: build PDF → write → read → extract text →
|
|
38
|
+
matches.
|
|
39
|
+
|
|
40
|
+
## [0.1.0] — 2026-08-02
|
|
41
|
+
|
|
42
|
+
### Initial release
|
|
43
|
+
|
|
44
|
+
Pure-Ruby PDF library: byte-level reader, Arlington-model-driven typed
|
|
45
|
+
domain model, and serializer.
|
|
46
|
+
|
|
47
|
+
* Source: bytes → tokens → COS graph.
|
|
48
|
+
* Model: typed COS values + Type::* semantics, sourced from vendored
|
|
49
|
+
Arlington PDF Model TSVs (ISO 32000-2:2020).
|
|
50
|
+
* Filter pipeline: FlateDecode, ASCII-Hex, ASCII-85, LZW, RunLength,
|
|
51
|
+
CCITTFax, DCT, JPX, JBIG2, Crypt.
|
|
52
|
+
* Content: 52 content-stream operators + Canvas drawing API.
|
|
53
|
+
* Encryption: RC4 (pure Ruby), AES (OpenSSL), StandardSecurityHandler
|
|
54
|
+
(V1-V6 / R2-R6).
|
|
55
|
+
* Font machinery: AFM parser, 5 encoding tables, CMap parser, TrueType
|
|
56
|
+
file parser (head/hhea/hmtx/cmap/OS-2), Type1 metrics.
|
|
57
|
+
* Image loaders: JPEG, PNG, PDF page import.
|
|
58
|
+
* Tasks: ExtractText (with /ToUnicode CMap), ExtractImages, Merge,
|
|
59
|
+
Optimize.
|
|
60
|
+
* CLI: version, info, tree, merge, extract-text/images, encrypt,
|
|
61
|
+
decrypt, optimize, form.
|
|
62
|
+
* Conformance: PDF/A + PDF/UA rule subsets.
|
|
63
|
+
* Round-trip property tested against ISO 32000-2 Annex H examples
|
|
64
|
+
(12 PDFs).
|
|
65
|
+
|
|
5
66
|
## [Unreleased]
|
|
6
67
|
|
|
7
68
|
### Added — 2026-08-01 (layout engine session)
|
data/Gemfile
CHANGED
|
@@ -74,10 +74,10 @@ module Pdfrb
|
|
|
74
74
|
def read_format_header
|
|
75
75
|
@format = u16(@subtable_offset)
|
|
76
76
|
case @format
|
|
77
|
-
when 0 then
|
|
78
|
-
when 4 then
|
|
79
|
-
when 6 then
|
|
80
|
-
when 12 then
|
|
77
|
+
when 0 then parse_format_zero
|
|
78
|
+
when 4 then parse_format_four
|
|
79
|
+
when 6 then parse_format_six
|
|
80
|
+
when 12 then parse_format_twelve
|
|
81
81
|
else
|
|
82
82
|
@format = nil
|
|
83
83
|
end
|
|
@@ -85,27 +85,27 @@ module Pdfrb
|
|
|
85
85
|
|
|
86
86
|
def lookup(unicode)
|
|
87
87
|
case @format
|
|
88
|
-
when 0 then
|
|
89
|
-
when 4 then
|
|
90
|
-
when 6 then
|
|
91
|
-
when 12 then
|
|
88
|
+
when 0 then lookup_format_zero(unicode)
|
|
89
|
+
when 4 then lookup_format_four(unicode)
|
|
90
|
+
when 6 then lookup_format_six(unicode)
|
|
91
|
+
when 12 then lookup_format_twelve(unicode)
|
|
92
92
|
else 0
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# Format 0: 256-entry byte table.
|
|
97
|
-
def
|
|
97
|
+
def parse_format_zero
|
|
98
98
|
@f0_glyph_ids = (0..255).map { |i| u8(@subtable_offset + 6 + i) }
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
def
|
|
101
|
+
def lookup_format_zero(unicode)
|
|
102
102
|
return 0 unless unicode < 256
|
|
103
103
|
|
|
104
104
|
@f0_glyph_ids[unicode]
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
# Format 4: segment mapping. BMP only.
|
|
108
|
-
def
|
|
108
|
+
def parse_format_four
|
|
109
109
|
seg_count_x2 = u16(@subtable_offset + 6)
|
|
110
110
|
seg_count = seg_count_x2 / 2
|
|
111
111
|
end_codes_off = @subtable_offset + 14
|
|
@@ -123,7 +123,7 @@ module Pdfrb
|
|
|
123
123
|
}
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
-
def
|
|
126
|
+
def lookup_format_four(unicode)
|
|
127
127
|
return 0 unless @f4
|
|
128
128
|
|
|
129
129
|
seg = @f4
|
|
@@ -154,7 +154,7 @@ module Pdfrb
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
# Format 6: trimmed table.
|
|
157
|
-
def
|
|
157
|
+
def parse_format_six
|
|
158
158
|
first = u16(@subtable_offset + 6)
|
|
159
159
|
count = u16(@subtable_offset + 8)
|
|
160
160
|
@f6 = {
|
|
@@ -164,7 +164,7 @@ module Pdfrb
|
|
|
164
164
|
}
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
-
def
|
|
167
|
+
def lookup_format_six(unicode)
|
|
168
168
|
return 0 unless @f6
|
|
169
169
|
|
|
170
170
|
idx = unicode - @f6[:first_code]
|
|
@@ -174,7 +174,7 @@ module Pdfrb
|
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
# Format 12: sparse coverage, full Unicode.
|
|
177
|
-
def
|
|
177
|
+
def parse_format_twelve
|
|
178
178
|
num_groups = u32(@subtable_offset + 12)
|
|
179
179
|
@f12 = []
|
|
180
180
|
num_groups.times do |i|
|
|
@@ -187,7 +187,7 @@ module Pdfrb
|
|
|
187
187
|
end
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
-
def
|
|
190
|
+
def lookup_format_twelve(unicode)
|
|
191
191
|
return 0 unless @f12
|
|
192
192
|
|
|
193
193
|
# Binary search for the group covering this codepoint.
|
data/lib/pdfrb/version.rb
CHANGED