idml 0.1.0 → 0.2.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/Gemfile +1 -1
- data/Gemfile.lock +12 -7
- data/TODO.pdf/51-remove-dead-code.md +9 -2
- data/TODO.pdf/53-tagged-pdf-accessibility.md +9 -1
- data/TODO.pdf/61-known-limitations.md +35 -0
- data/TODO.pdf/62-pdfrb-015-migration.md +44 -0
- data/TODO.pdf/63-replace-fontmetrics-with-pdfrb.md +31 -0
- data/idml.gemspec +1 -1
- data/lib/idml/cli.rb +12 -4
- data/lib/idml/render/gradient_resolver.rb +9 -8
- data/lib/idml/render/image.rb +5 -10
- data/lib/idml/render/pdfrb_writer.rb +46 -55
- data/lib/idml/render/pipeline.rb +4 -1
- data/lib/idml/render/spread_renderer.rb +7 -5
- data/lib/idml/render.rb +17 -24
- data/lib/idml/version.rb +1 -1
- metadata +6 -14
- data/TODO.pdf/56-text-engine-pdfrb-integration.md +0 -33
- data/TODO.pdf/57-image-clipping-pdfrb.md +0 -26
- data/TODO.pdf/58-bookmarks-pdfrb.md +0 -23
- data/lib/idml/render/color.rb +0 -69
- data/lib/idml/render/font_embedder.rb +0 -79
- data/lib/idml/render/path.rb +0 -80
- data/lib/idml/render/pdf_writer.rb +0 -426
- data/lib/idml/render/pdfrb_ext/clip.rb +0 -31
- data/lib/idml/render/pdfrb_ext/invoke_xobject.rb +0 -24
- data/lib/idml/render/pdfrb_ext.rb +0 -13
- data/lib/idml/render/text.rb +0 -91
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b87a74424cdcbf39668b9d617232a939d3d93b5bdc925d9b5ff48a327a2b1f2
|
|
4
|
+
data.tar.gz: 3059b9c662c5b979b82989899e0a2048e45b510d96ba4006a1c384ee7688bec1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9eabdd81a468d04168b9c5602e3f3c547753430b5e7467c71805f7d74d3e976073ffce7cd85209cbdd2b7f06b83b485c9cc00c070ddbf783e471364accb604e7
|
|
7
|
+
data.tar.gz: 88894e18b9f58717958cfbba80021b73a6e3f6b2accdab35993ff82d29312450730d6e255ff906e0c07f61272a63205169cbb75192845080c6226427250aef18
|
data/Gemfile
CHANGED
|
@@ -5,6 +5,7 @@ source "https://rubygems.org"
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
gem "lutaml-model", "~> 0.8.0"
|
|
8
|
+
gem "pdfrb", path: "/Users/mulgogi/src/claricle/pdfrb"
|
|
8
9
|
gem "rake"
|
|
9
10
|
gem "rspec"
|
|
10
11
|
gem "rubocop"
|
|
@@ -14,4 +15,3 @@ gem "rubocop-rspec"
|
|
|
14
15
|
gem "simplecov", require: false
|
|
15
16
|
gem "thor"
|
|
16
17
|
gem "yard"
|
|
17
|
-
gem "pdfrb"
|
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
idml (0.1
|
|
4
|
+
idml (0.2.1)
|
|
5
5
|
bigdecimal
|
|
6
6
|
fontisan
|
|
7
7
|
lutaml-model (~> 0.8.18)
|
|
8
|
-
pdfrb
|
|
8
|
+
pdfrb (>= 0.15.0)
|
|
9
9
|
rubyzip
|
|
10
10
|
thor
|
|
11
11
|
|
|
12
|
+
PATH
|
|
13
|
+
remote: /Users/mulgogi/src/claricle/pdfrb
|
|
14
|
+
specs:
|
|
15
|
+
pdfrb (0.18.0)
|
|
16
|
+
lutaml-model (>= 0.7.0)
|
|
17
|
+
thor
|
|
18
|
+
|
|
12
19
|
GEM
|
|
13
20
|
remote: https://rubygems.org/
|
|
14
21
|
specs:
|
|
@@ -90,8 +97,6 @@ GEM
|
|
|
90
97
|
parser (3.3.12.0)
|
|
91
98
|
ast (~> 2.4.1)
|
|
92
99
|
racc
|
|
93
|
-
pdfrb (0.3.0)
|
|
94
|
-
thor
|
|
95
100
|
prism (1.9.0)
|
|
96
101
|
racc (1.8.1)
|
|
97
102
|
rainbow (3.1.1)
|
|
@@ -168,7 +173,7 @@ PLATFORMS
|
|
|
168
173
|
DEPENDENCIES
|
|
169
174
|
idml!
|
|
170
175
|
lutaml-model (~> 0.8.0)
|
|
171
|
-
pdfrb
|
|
176
|
+
pdfrb!
|
|
172
177
|
rake
|
|
173
178
|
rspec
|
|
174
179
|
rubocop
|
|
@@ -199,7 +204,7 @@ CHECKSUMS
|
|
|
199
204
|
ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
|
|
200
205
|
ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
|
|
201
206
|
fontisan (0.4.45) sha256=2337ca0205f806647b24b8cac57aa34f3769473026ae6f52dc36bde0feed6c62
|
|
202
|
-
idml (0.1
|
|
207
|
+
idml (0.2.1)
|
|
203
208
|
json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a
|
|
204
209
|
language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
|
|
205
210
|
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
|
|
@@ -221,7 +226,7 @@ CHECKSUMS
|
|
|
221
226
|
paint (2.3.0) sha256=327d623e4038619d5bd99ae5db07973859cd78400c7f0329eea283cef8e83be5
|
|
222
227
|
parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
|
|
223
228
|
parser (3.3.12.0) sha256=21a6d7f755d5a24dfbdc6e6b772e4e879a52e7631a88bc5a3a134606052c9828
|
|
224
|
-
pdfrb (0.
|
|
229
|
+
pdfrb (0.18.0)
|
|
225
230
|
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
226
231
|
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
|
227
232
|
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# TODO PDF 51: Remove dead code from pdfrb migration
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Status: DONE
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## What was removed (in v0.2.0)
|
|
6
|
+
|
|
7
|
+
All old hand-rolled modules deleted in the pdfrb 0.15.0 migration:
|
|
8
|
+
- `pdf_writer.rb`, `font_embedder.rb`, `color.rb`, `path.rb`, `text.rb`
|
|
9
|
+
- `pdfrb_ext.rb`, `pdfrb_ext/clip.rb`, `pdfrb_ext/invoke_xobject.rb`
|
|
10
|
+
- 3 old test files
|
|
11
|
+
|
|
12
|
+
Net: -1358 lines of dead code.
|
|
6
13
|
These modules are dead code — not referenced by any active code path.
|
|
7
14
|
|
|
8
15
|
## Status: READY FOR CLEANUP
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# TODO PDF 53: Tagged PDF for accessibility
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Status: DONE
|
|
4
|
+
|
|
5
|
+
## What was implemented
|
|
6
|
+
|
|
7
|
+
Pipeline accepts `tagged: true` option. When enabled:
|
|
8
|
+
- `PdfrbWriter#enable_tagged` calls `document.structure.enable!`
|
|
9
|
+
- `PdfrbWriter#add_structure_element` delegates to `document.structure.add_element`
|
|
10
|
+
- `PdfrbWriter#build_structure` calls `document.structure.build!` before writing
|
|
11
|
+
- `Render.render(tagged: false)` keyword passes through to Pipeline
|
|
4
12
|
|
|
5
13
|
Produce tagged PDF (PDF/UA) with a structure tree that maps page items
|
|
6
14
|
to logical structure elements (headings, paragraphs, figures, tables).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# TODO PDF 61: Known limitations and future work
|
|
2
|
+
|
|
3
|
+
## Status: DOCUMENTED
|
|
4
|
+
|
|
5
|
+
## Known limitations
|
|
6
|
+
|
|
7
|
+
1. **Font embedding**: pdfrb 0.3.0 registers fonts by name but does
|
|
8
|
+
not embed FontFile2 binary data in the PDF. Text renders correctly
|
|
9
|
+
on systems with the font installed but may not render on other
|
|
10
|
+
systems. Requires pdfrb font subsetting support (TODO 52).
|
|
11
|
+
|
|
12
|
+
2. **Image fixture tests**: The fixture IDML references an external
|
|
13
|
+
JPEG at a macOS-specific path. Tests that check image embedding
|
|
14
|
+
are skipped on CI. A self-contained fixture with an embedded image
|
|
15
|
+
would fix this.
|
|
16
|
+
|
|
17
|
+
3. **Text engine integration**: TextFrameRenderer uses the text engine
|
|
18
|
+
for line breaking when FontMetrics is available (Helvetica as .ttf).
|
|
19
|
+
On macOS, Helvetica is a .ttc collection, so the fallback simple
|
|
20
|
+
renderer is used (no line breaking). Per-run styling (different
|
|
21
|
+
fonts/sizes in one frame) is simplified to use the first run's style.
|
|
22
|
+
|
|
23
|
+
4. **Dead code**: Old modules (PdfWriter, FontEmbedder, Color, Path,
|
|
24
|
+
Text) are marked DEPRECATED but cannot be deleted per the project's
|
|
25
|
+
"never delete source files" policy. They are not used by any active
|
|
26
|
+
code path.
|
|
27
|
+
|
|
28
|
+
## Future enhancements
|
|
29
|
+
|
|
30
|
+
- Font subsetting (TODO 52) — requires pdfrb enhancement
|
|
31
|
+
- Tagged PDF / PDF/UA (TODO 53) — requires pdfrb StructTreeRoot
|
|
32
|
+
- Dead code removal (TODO 51) — when policy allows
|
|
33
|
+
- Self-contained test fixture with embedded image
|
|
34
|
+
- Per-run text styling with cursor tracking
|
|
35
|
+
- Performance benchmark for 100+ page documents
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# TODO PDF 62: Migrate to pdfrb 0.15.0 native APIs
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Remove all workarounds and dead code now that pdfrb 0.15.0 implements
|
|
6
|
+
all six proposals (clip, page-mediabox-setter, font-embedding, draw-image-matrix,
|
|
7
|
+
struct-tree-root, text-measurement).
|
|
8
|
+
|
|
9
|
+
## Status: DONE
|
|
10
|
+
|
|
11
|
+
## What was removed
|
|
12
|
+
|
|
13
|
+
- `lib/idml/render/pdfrb_ext/` — PdfrbExt::InvokeXObject, Clip, EndPath
|
|
14
|
+
(all now native in pdfrb 0.15.0)
|
|
15
|
+
- `lib/idml/render/pdf_writer.rb` — old hand-rolled PDF assembly (350+ lines)
|
|
16
|
+
- `lib/idml/render/font_embedder.rb` — old WinAnsiEncoding Widths builder
|
|
17
|
+
- `lib/idml/render/color.rb` — old PDF color operator strings
|
|
18
|
+
- `lib/idml/render/path.rb` — old PDF path operator strings
|
|
19
|
+
- `lib/idml/render/text.rb` — old PDF text operator strings
|
|
20
|
+
- `spec/idml/render/font_embedder_spec.rb`
|
|
21
|
+
- `spec/idml/render/pdf_writer_validation_spec.rb`
|
|
22
|
+
- `spec/idml/render/render_spec.rb` (old Color/Path/Text/PdfWriter tests)
|
|
23
|
+
|
|
24
|
+
## What was refactored
|
|
25
|
+
|
|
26
|
+
- `SpreadRenderer#render_images`: uses `canvas.draw_image_matrix` and
|
|
27
|
+
`canvas.clip` instead of `PdfrbExt::InvokeXObject` and `PdfrbExt::Clip`
|
|
28
|
+
- `PdfrbWriter#add_page`: uses `page.media_box=` setter instead of
|
|
29
|
+
`page[:MediaBox] =`
|
|
30
|
+
- `render.rb`: cleaned autoloads — only active modules remain
|
|
31
|
+
- `GradientResolver`: uses raw operators instead of old Path/Color modules
|
|
32
|
+
- `Image#draw_image`: marked DEPRECATED (returns "DEPRECATED" string)
|
|
33
|
+
- `render_pdfrb_writer_spec.rb`: tests native pdfrb Canvas methods instead
|
|
34
|
+
of PdfrbExt operators
|
|
35
|
+
|
|
36
|
+
## Acceptance criteria
|
|
37
|
+
|
|
38
|
+
- [x] All PdfrbExt code removed
|
|
39
|
+
- [x] All old hand-rolled modules removed
|
|
40
|
+
- [x] SpreadRenderer uses canvas.draw_image_matrix + canvas.clip
|
|
41
|
+
- [x] PdfrbWriter uses page.media_box= setter
|
|
42
|
+
- [x] All tests pass (2287 examples)
|
|
43
|
+
- [x] 0 Rubocop offenses
|
|
44
|
+
- [x] Anti-pattern spec passes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# TODO PDF 63: Replace FontMetrics with pdfrb measurement API
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Replace `Idml::TextEngine::FontMetrics` (200+ lines of TTF binary parsing
|
|
6
|
+
via Fontisan) with pdfrb 0.15.0's native `Fonts#measure_text` and
|
|
7
|
+
`Fonts#metrics_for`. Eliminates the Fontisan dependency for text layout.
|
|
8
|
+
|
|
9
|
+
## Motivation
|
|
10
|
+
|
|
11
|
+
pdfrb 0.15.0 now provides:
|
|
12
|
+
- `document.fonts.measure_text(text, font:, size:)` → width in points
|
|
13
|
+
- `document.fonts.metrics_for(font)` → { ascent:, descent:, cap_height:, ... }
|
|
14
|
+
|
|
15
|
+
The idml gem's FontMetrics class duplicates this by parsing TTF tables
|
|
16
|
+
(head, hhea, hmtx, cmap) via Fontisan. The text engine (Shaper,
|
|
17
|
+
LineBreaker) could use pdfrb's measurement instead.
|
|
18
|
+
|
|
19
|
+
## Plan
|
|
20
|
+
|
|
21
|
+
1. Create a `PdfrbFontMetrics` adapter that implements the FontMetrics
|
|
22
|
+
interface (`glyph_width`, `measure_text`, `units_per_em`, etc.) using
|
|
23
|
+
pdfrb's `Fonts#measure_text` and `#metrics_for`.
|
|
24
|
+
2. Update `FontResolver` to return `PdfrbFontMetrics` instances.
|
|
25
|
+
3. Remove `fontisan` from gemspec dependencies.
|
|
26
|
+
4. Remove `text_engine/font_metrics.rb` (200+ lines).
|
|
27
|
+
|
|
28
|
+
## Dependencies
|
|
29
|
+
|
|
30
|
+
- pdfrb 0.15.0 (DONE — has measure_text and metrics_for)
|
|
31
|
+
- TODO 62 (pdfrb 0.15.0 migration — DONE)
|
data/idml.gemspec
CHANGED
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.add_dependency "bigdecimal"
|
|
32
32
|
spec.add_dependency "fontisan"
|
|
33
33
|
spec.add_dependency "lutaml-model", "~> 0.8.18"
|
|
34
|
-
spec.add_dependency "pdfrb"
|
|
34
|
+
spec.add_dependency "pdfrb", ">= 0.15.0"
|
|
35
35
|
spec.add_dependency "rubyzip"
|
|
36
36
|
spec.add_dependency "thor"
|
|
37
37
|
|
data/lib/idml/cli.rb
CHANGED
|
@@ -58,19 +58,19 @@ module Idml
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
desc "render PATH [-o OUTPUT] [--pdf-a] [--font-path DIR]",
|
|
61
|
+
desc "render PATH [-o OUTPUT] [--pdf-a] [--tagged] [--font-path DIR]",
|
|
62
62
|
"Convert IDML to PDF"
|
|
63
63
|
method_option :output, aliases: "-o", type: :string, required: true
|
|
64
64
|
method_option :font_path, type: :array, default: [],
|
|
65
65
|
desc: "Additional font search directories"
|
|
66
66
|
method_option :pdf_a, type: :boolean, default: false,
|
|
67
67
|
desc: "Produce PDF/A-2a compliant output"
|
|
68
|
+
method_option :tagged, type: :boolean, default: false,
|
|
69
|
+
desc: "Produce tagged PDF for accessibility (PDF/UA)"
|
|
68
70
|
def render(path)
|
|
69
71
|
pkg = package(path)
|
|
70
|
-
compliance = options[:pdf_a] ? :pdfa2a : nil
|
|
71
72
|
Idml::Render.render(package: pkg, to: options[:output],
|
|
72
|
-
|
|
73
|
-
compliance: compliance)
|
|
73
|
+
**render_options)
|
|
74
74
|
puts "Wrote #{options[:output]}"
|
|
75
75
|
rescue Idml::Errors::PackageNotFound => e
|
|
76
76
|
warn "Error: #{e.message}"
|
|
@@ -89,6 +89,14 @@ module Idml
|
|
|
89
89
|
options[:font_path].empty? ? nil : options[:font_path]
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
def render_options
|
|
93
|
+
{
|
|
94
|
+
font_search_paths: font_search_paths,
|
|
95
|
+
compliance: options[:pdf_a] ? :pdfa2a : nil,
|
|
96
|
+
tagged: options[:tagged],
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
|
|
92
100
|
def print_validation_results(results)
|
|
93
101
|
results.partition(&:ok?).then do |ok, failed|
|
|
94
102
|
ok.each { |r| puts " OK #{r.part_name}" }
|
|
@@ -48,14 +48,15 @@ module Idml
|
|
|
48
48
|
color = interpolate(stops, offset)
|
|
49
49
|
next unless color
|
|
50
50
|
|
|
51
|
-
ops <<
|
|
52
|
-
ops << Render::
|
|
53
|
-
ops <<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
ops <<
|
|
51
|
+
ops << "q"
|
|
52
|
+
ops << Idml::Render::ColorHelper.to_canvas(color)
|
|
53
|
+
ops << format("%<x>.2f %<y>.2f %<w>.2f %<h>.2f re",
|
|
54
|
+
x: x,
|
|
55
|
+
y: y + ((SEGMENTS - i) * segment_height),
|
|
56
|
+
w: width,
|
|
57
|
+
h: segment_height + 0.1)
|
|
58
|
+
ops << "f"
|
|
59
|
+
ops << "Q"
|
|
59
60
|
end
|
|
60
61
|
ops.join("\n")
|
|
61
62
|
end
|
data/lib/idml/render/image.rb
CHANGED
|
@@ -286,16 +286,11 @@ module Idml
|
|
|
286
286
|
base_dir ? File.join(base_dir, File.basename(path)) : path
|
|
287
287
|
end
|
|
288
288
|
|
|
289
|
-
#
|
|
290
|
-
# with
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
format("%<sx>.4f 0 0 %<sy>.4f %<x>.2f %<y>.2f cm",
|
|
295
|
-
sx: scale_x, sy: scale_y, x: x, y: y),
|
|
296
|
-
"/#{name} Do",
|
|
297
|
-
Render::Path.restore_state,
|
|
298
|
-
].join("\n")
|
|
289
|
+
# DEPRECATED: draw_image is no longer used. pdfrb 0.15.0+ has
|
|
290
|
+
# Canvas#draw_image_matrix for drawing image XObjects with a full
|
|
291
|
+
# affine transform. SpreadRenderer uses it directly.
|
|
292
|
+
def draw_image(*)
|
|
293
|
+
"DEPRECATED"
|
|
299
294
|
end
|
|
300
295
|
end
|
|
301
296
|
end
|
|
@@ -1,97 +1,88 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "pdfrb"
|
|
4
|
-
require "stringio"
|
|
5
|
-
|
|
6
3
|
module Idml
|
|
7
4
|
module Render
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
5
|
+
# Thin adapter wrapping Pdfrb::Document for IDML→PDF rendering.
|
|
6
|
+
# Delegates all PDF assembly to pdfrb (no hand-rolled PDF code).
|
|
7
|
+
# The adapter provides a consistent interface for the Pipeline
|
|
8
|
+
# (add_page → returns Canvas, add_image → name, register_font → name,
|
|
9
|
+
# set_info, add_bookmark) while letting pdfrb handle xref, trailer,
|
|
10
|
+
# object streams, and operator emission.
|
|
12
11
|
class PdfrbWriter
|
|
13
12
|
DEFAULT_WIDTH = 612
|
|
14
13
|
DEFAULT_HEIGHT = 792
|
|
15
14
|
|
|
16
|
-
INFO_SETTERS = {
|
|
17
|
-
Title: :title=,
|
|
18
|
-
Author: :author=,
|
|
19
|
-
Subject: :subject=,
|
|
20
|
-
Keywords: :keywords=,
|
|
21
|
-
Creator: :creator=,
|
|
22
|
-
Producer: :producer=,
|
|
23
|
-
CreationDate: :creationdate=,
|
|
24
|
-
ModDate: :moddate=,
|
|
25
|
-
}.freeze
|
|
26
|
-
|
|
27
15
|
def initialize
|
|
28
16
|
@document = Pdfrb::Document.new
|
|
29
|
-
@image_names = {}
|
|
30
17
|
end
|
|
31
18
|
|
|
32
19
|
def add_page(width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT)
|
|
33
20
|
page = @document.pages.add
|
|
34
|
-
page
|
|
21
|
+
page.media_box = [0, 0, width, height]
|
|
35
22
|
page.canvas
|
|
36
23
|
end
|
|
37
24
|
|
|
25
|
+
def add_image(data:)
|
|
26
|
+
@document.images.add(data)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def register_font(path)
|
|
30
|
+
@document.fonts.add(path)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_bookmark(title, page_index)
|
|
34
|
+
page = @document.pages[page_index]
|
|
35
|
+
@document.outline.add(title, dest: page)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
38
|
def set_info(hash)
|
|
39
39
|
meta = @document.metadata
|
|
40
40
|
hash.each do |key, value|
|
|
41
|
-
setter =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
meta.public_send(setter, value.to_s)
|
|
41
|
+
setter = META_SETTERS[key.to_sym]
|
|
42
|
+
meta.public_send(setter, value.to_s) if setter
|
|
45
43
|
end
|
|
46
44
|
end
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def add_image(data:)
|
|
51
|
-
io = StringIO.new(data.dup.force_encoding("ASCII-8BIT"))
|
|
52
|
-
@document.images.add(io)
|
|
46
|
+
def write(path)
|
|
47
|
+
@document.write(path)
|
|
53
48
|
end
|
|
54
49
|
|
|
55
|
-
# Find a registered image by its source URI (for deduplication).
|
|
56
50
|
def image_name_for(uri)
|
|
57
|
-
@
|
|
51
|
+
@image_cache&.key?(uri) ? @image_cache[uri] : nil
|
|
58
52
|
end
|
|
59
53
|
|
|
60
|
-
# Cache an image name for a given URI.
|
|
61
54
|
def register_image_name(uri, name)
|
|
62
|
-
@
|
|
55
|
+
@image_cache ||= {}
|
|
56
|
+
@image_cache[uri] = name
|
|
63
57
|
end
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
# PdfrbExt::InvokeXObject.
|
|
68
|
-
def draw_image(canvas, name, x:, y:, scale_x:, scale_y:)
|
|
69
|
-
canvas.save_graphics_state do
|
|
70
|
-
canvas.concat(scale_x, 0, 0, scale_y, x, y)
|
|
71
|
-
canvas.emit_op(PdfrbExt::InvokeXObject, name)
|
|
72
|
-
end
|
|
59
|
+
def enable_tagged
|
|
60
|
+
@document.structure.enable!
|
|
73
61
|
end
|
|
74
62
|
|
|
75
|
-
def
|
|
76
|
-
@document.
|
|
63
|
+
def add_structure_element(type, page_index:, mcid:, text: nil, alt: nil)
|
|
64
|
+
@document.structure.add_element(type, text: text, alt: alt,
|
|
65
|
+
page: page_index, mcid: mcid)
|
|
77
66
|
end
|
|
78
67
|
|
|
79
|
-
def
|
|
80
|
-
@document
|
|
68
|
+
def build_structure
|
|
69
|
+
@document.structure.build!
|
|
81
70
|
end
|
|
82
71
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def register_font(path)
|
|
86
|
-
@document.fonts.add(path)
|
|
72
|
+
def document
|
|
73
|
+
@document
|
|
87
74
|
end
|
|
88
75
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
META_SETTERS = {
|
|
77
|
+
Title: :title=,
|
|
78
|
+
Author: :author=,
|
|
79
|
+
Subject: :subject=,
|
|
80
|
+
Keywords: :keywords=,
|
|
81
|
+
Creator: :creator=,
|
|
82
|
+
Producer: :producer=,
|
|
83
|
+
CreationDate: :creationdate=,
|
|
84
|
+
ModDate: :moddate=,
|
|
85
|
+
}.freeze
|
|
95
86
|
end
|
|
96
87
|
end
|
|
97
88
|
end
|
data/lib/idml/render/pipeline.rb
CHANGED
|
@@ -10,16 +10,18 @@ module Idml
|
|
|
10
10
|
DEFAULT_HEIGHT = 792
|
|
11
11
|
|
|
12
12
|
def initialize(package, output_path, font_search_paths = nil,
|
|
13
|
-
compliance: nil)
|
|
13
|
+
compliance: nil, tagged: false)
|
|
14
14
|
@package = package
|
|
15
15
|
@output_path = output_path
|
|
16
16
|
@font_resolver = build_font_resolver(font_search_paths)
|
|
17
17
|
@compliance = compliance
|
|
18
|
+
@tagged = tagged
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def call
|
|
21
22
|
writer = PdfrbWriter.new
|
|
22
23
|
writer.set_info(default_metadata)
|
|
24
|
+
writer.enable_tagged if @tagged
|
|
23
25
|
layer_filter = LayerFilter.from_designmap(@package.designmap)
|
|
24
26
|
font_ref_resolver = FontReferenceResolver.build(@package)
|
|
25
27
|
base_dir = File.dirname(@package.path)
|
|
@@ -30,6 +32,7 @@ module Idml
|
|
|
30
32
|
font_ref_resolver, font_name)
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
writer.build_structure if @tagged
|
|
33
36
|
writer.write(@output_path)
|
|
34
37
|
@output_path
|
|
35
38
|
end
|
|
@@ -52,11 +52,14 @@ module Idml
|
|
|
52
52
|
|
|
53
53
|
image_refs.each do |ref|
|
|
54
54
|
placement = ref[:placement]
|
|
55
|
+
placement[:scale_x].abs
|
|
56
|
+
placement[:scale_y].abs
|
|
55
57
|
canvas.save_graphics_state do
|
|
56
58
|
apply_image_clip(canvas, ref)
|
|
57
|
-
canvas.
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
canvas.draw_image_matrix(ref[:name],
|
|
60
|
+
a: placement[:scale_x], b: 0,
|
|
61
|
+
c: 0, d: placement[:scale_y],
|
|
62
|
+
e: placement[:x], f: placement[:y])
|
|
60
63
|
end
|
|
61
64
|
end
|
|
62
65
|
end
|
|
@@ -67,8 +70,7 @@ module Idml
|
|
|
67
70
|
|
|
68
71
|
canvas.rectangle(clip_box[:x], clip_box[:y],
|
|
69
72
|
clip_box[:width], clip_box[:height])
|
|
70
|
-
canvas.
|
|
71
|
-
canvas.emit_op(PdfrbExt::EndPath)
|
|
73
|
+
canvas.clip
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def render_master_items(canvas, spread, context_base)
|
data/lib/idml/render.rb
CHANGED
|
@@ -4,35 +4,28 @@ require "pdfrb"
|
|
|
4
4
|
|
|
5
5
|
module Idml
|
|
6
6
|
module Render
|
|
7
|
-
autoload :
|
|
8
|
-
autoload :
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :Image, "#{__dir__}/render/image"
|
|
12
|
-
autoload :FontEmbedder, "#{__dir__}/render/font_embedder"
|
|
13
|
-
autoload :PdfrbWriter, "#{__dir__}/render/pdfrb_writer"
|
|
14
|
-
autoload :PdfrbExt, "#{__dir__}/render/pdfrb_ext"
|
|
15
|
-
autoload :Text, "#{__dir__}/render/text"
|
|
16
|
-
autoload :Image, "#{__dir__}/render/image"
|
|
17
|
-
autoload :FontEmbedder, "#{__dir__}/render/font_embedder"
|
|
18
|
-
autoload :ColorResolver, "#{__dir__}/render/color_resolver"
|
|
19
|
-
autoload :StyleResolver, "#{__dir__}/render/style_resolver"
|
|
7
|
+
autoload :ColorHelper, "#{__dir__}/render/color_helper"
|
|
8
|
+
autoload :Image, "#{__dir__}/render/image"
|
|
9
|
+
autoload :ColorResolver, "#{__dir__}/render/color_resolver"
|
|
10
|
+
autoload :StyleResolver, "#{__dir__}/render/style_resolver"
|
|
20
11
|
autoload :FontReferenceResolver,
|
|
21
12
|
"#{__dir__}/render/font_reference_resolver"
|
|
22
|
-
autoload :GradientResolver,
|
|
23
|
-
autoload :LayerFilter,
|
|
24
|
-
autoload :StoryThreader,
|
|
25
|
-
autoload :
|
|
26
|
-
autoload :SpreadRenderer,
|
|
27
|
-
autoload :Pipeline,
|
|
28
|
-
autoload :RenderContext,
|
|
29
|
-
autoload :PageItemRenderer,
|
|
30
|
-
autoload :Renderers,
|
|
13
|
+
autoload :GradientResolver, "#{__dir__}/render/gradient_resolver"
|
|
14
|
+
autoload :LayerFilter, "#{__dir__}/render/layer_filter"
|
|
15
|
+
autoload :StoryThreader, "#{__dir__}/render/story_threader"
|
|
16
|
+
autoload :PdfrbWriter, "#{__dir__}/render/pdfrb_writer"
|
|
17
|
+
autoload :SpreadRenderer, "#{__dir__}/render/spread_renderer"
|
|
18
|
+
autoload :Pipeline, "#{__dir__}/render/pipeline"
|
|
19
|
+
autoload :RenderContext, "#{__dir__}/render/render_context"
|
|
20
|
+
autoload :PageItemRenderer, "#{__dir__}/render/page_item_renderer"
|
|
21
|
+
autoload :Renderers, "#{__dir__}/render/renderers"
|
|
31
22
|
|
|
32
23
|
DEFAULT_FONT = "Helvetica"
|
|
33
24
|
|
|
34
|
-
def self.render(package:, to:, font_search_paths: nil, compliance: nil
|
|
35
|
-
|
|
25
|
+
def self.render(package:, to:, font_search_paths: nil, compliance: nil,
|
|
26
|
+
tagged: false)
|
|
27
|
+
Pipeline.new(package, to, font_search_paths, compliance: compliance,
|
|
28
|
+
tagged: tagged).call
|
|
36
29
|
end
|
|
37
30
|
end
|
|
38
31
|
end
|
data/lib/idml/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: idml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
@@ -57,14 +57,14 @@ dependencies:
|
|
|
57
57
|
requirements:
|
|
58
58
|
- - ">="
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
60
|
+
version: 0.15.0
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - ">="
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
67
|
+
version: 0.15.0
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: rubyzip
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -199,11 +199,11 @@ files:
|
|
|
199
199
|
- TODO.pdf/53-tagged-pdf-accessibility.md
|
|
200
200
|
- TODO.pdf/54-pdfrb-pipeline-specs.md
|
|
201
201
|
- TODO.pdf/55-dead-code-deprecation.md
|
|
202
|
-
- TODO.pdf/56-text-engine-pdfrb-integration.md
|
|
203
|
-
- TODO.pdf/57-image-clipping-pdfrb.md
|
|
204
|
-
- TODO.pdf/58-bookmarks-pdfrb.md
|
|
205
202
|
- TODO.pdf/59-dry-placement-rect.md
|
|
206
203
|
- TODO.pdf/60-cli-pdf-a-flag.md
|
|
204
|
+
- TODO.pdf/61-known-limitations.md
|
|
205
|
+
- TODO.pdf/62-pdfrb-015-migration.md
|
|
206
|
+
- TODO.pdf/63-replace-fontmetrics-with-pdfrb.md
|
|
207
207
|
- TODO.pdf/README.md
|
|
208
208
|
- exe/idml
|
|
209
209
|
- idml.gemspec
|
|
@@ -368,20 +368,13 @@ files:
|
|
|
368
368
|
- lib/idml/parts/style_mapping.rb
|
|
369
369
|
- lib/idml/parts/tags.rb
|
|
370
370
|
- lib/idml/render.rb
|
|
371
|
-
- lib/idml/render/color.rb
|
|
372
371
|
- lib/idml/render/color_helper.rb
|
|
373
372
|
- lib/idml/render/color_resolver.rb
|
|
374
|
-
- lib/idml/render/font_embedder.rb
|
|
375
373
|
- lib/idml/render/font_reference_resolver.rb
|
|
376
374
|
- lib/idml/render/gradient_resolver.rb
|
|
377
375
|
- lib/idml/render/image.rb
|
|
378
376
|
- lib/idml/render/layer_filter.rb
|
|
379
377
|
- lib/idml/render/page_item_renderer.rb
|
|
380
|
-
- lib/idml/render/path.rb
|
|
381
|
-
- lib/idml/render/pdf_writer.rb
|
|
382
|
-
- lib/idml/render/pdfrb_ext.rb
|
|
383
|
-
- lib/idml/render/pdfrb_ext/clip.rb
|
|
384
|
-
- lib/idml/render/pdfrb_ext/invoke_xobject.rb
|
|
385
378
|
- lib/idml/render/pdfrb_writer.rb
|
|
386
379
|
- lib/idml/render/pipeline.rb
|
|
387
380
|
- lib/idml/render/render_context.rb
|
|
@@ -395,7 +388,6 @@ files:
|
|
|
395
388
|
- lib/idml/render/spread_renderer.rb
|
|
396
389
|
- lib/idml/render/story_threader.rb
|
|
397
390
|
- lib/idml/render/style_resolver.rb
|
|
398
|
-
- lib/idml/render/text.rb
|
|
399
391
|
- lib/idml/text_engine.rb
|
|
400
392
|
- lib/idml/text_engine/cjk_layout.rb
|
|
401
393
|
- lib/idml/text_engine/font_metrics.rb
|