idml 0.5.5 → 0.6.0

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: ce8ffd92b6fd96bc1b018ed0875a0344e4c96692b18a12f3ab7999db3bc0c257
4
- data.tar.gz: b454cdc91f17dabacd2c35a8f1b808aacbb23b40a91b7b392eab68c7b109935c
3
+ metadata.gz: b96b3531c996da57cb6d46da274a55b9abbd352329617065da6a98b8176868a1
4
+ data.tar.gz: 9e8dfa3c572ab6b2f96e90194321cfd212160baf408016c829abf16e8e8f60dc
5
5
  SHA512:
6
- metadata.gz: 9d1c153af76705ddef5cdf58334d1f23010dd0a88c3559f9fd7da87cf94a52f2a48c386dddd6a443f2877c0df25e9ae618a3388e117d5c825b99814ee2d35973
7
- data.tar.gz: 86eaa92d00b471cb085dc32f81e6c7618a856583ff340bd88f5b535378cfa8e46c73685d5fb6090a10be22e3c3425066b54859ce98be78cb31a2dcfc598a71b2
6
+ metadata.gz: dcbcb115a524896a38c1f9c44bdbde7bbac2a504f574388555702c3ffafc97908e7d3b029832e15f157903e3ab0ec1c945bd9751bc23046f7d1aeacbca6eab14
7
+ data.tar.gz: cfb3023e1c1c45408151fe02c6c02e065a0092f3aa7576d425c9637cd3e7080e6c7359b93d58e31e6bc18fdaa4795ea5b8cd01a67b5eca2f989a6bea6cbb6415
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- idml (0.5.5)
4
+ idml (0.6.0)
5
5
  bigdecimal
6
6
  lutaml-model (~> 0.8.18)
7
7
  pdfrb
@@ -183,7 +183,7 @@ CHECKSUMS
183
183
  ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496
184
184
  ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
185
185
  ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
186
- idml (0.5.5)
186
+ idml (0.6.0)
187
187
  json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a
188
188
  language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
189
189
  lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
@@ -1,6 +1,6 @@
1
1
  # TODO PDF 77: PDF/A XMP packet and Catalog /Metadata stream
2
2
 
3
- ## Status: PARTIAL — XMP packet emitted; ICC output intent deferred
3
+ ## Status: DONE — XMP + ICC output intent both implemented
4
4
 
5
5
  ## What was implemented
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO PDF 93: Per-run font resolution from CharacterStyleRange
2
2
 
3
- ## Status: PLANNED (last major rendering fidelity gap)
3
+ ## Status: DONE font_map architecture implemented
4
4
 
5
5
  ## Problem
6
6
 
@@ -50,6 +50,31 @@ module Idml
50
50
  nil
51
51
  end
52
52
 
53
+ # Pre-registers every non-missing font in the document and
54
+ # returns a map of family_name → pdfrb Symbol resource. Used
55
+ # by the renderer to resolve per-run AppliedFont references.
56
+ # Falls back to DEFAULT_FONT for families that can't be resolved.
57
+ def font_map(writer)
58
+ map = {}
59
+ return map unless @package&.fonts
60
+
61
+ @package.fonts.font_family.each do |family|
62
+ next unless family.name
63
+
64
+ map[family.name] = resource_for_family(writer, family)
65
+ end
66
+ map
67
+ end
68
+
69
+ def resource_for_family(writer, family)
70
+ path = find_font_file(family)
71
+ return DEFAULT_FONT unless path
72
+
73
+ writer.register_font(path)
74
+ rescue StandardError
75
+ DEFAULT_FONT
76
+ end
77
+
53
78
  private
54
79
 
55
80
  def resolve_document_font_path
@@ -43,12 +43,13 @@ module Idml
43
43
  font_search_paths: @font_search_paths)
44
44
  font_resource = font_setup.register(writer)
45
45
  font_metrics = font_setup.metrics_for(writer, font_resource)
46
+ font_map = font_setup.font_map(writer)
46
47
 
47
48
  page_index = -1
48
49
  @package.spreads.each do |spread|
49
50
  page_index = render_spread(writer, spread, layer_filter,
50
51
  font_ref_resolver, font_resource,
51
- font_metrics, structure,
52
+ font_metrics, font_map, structure,
52
53
  position_tracker, page_index)
53
54
  end
54
55
 
@@ -88,15 +89,15 @@ module Idml
88
89
  end
89
90
 
90
91
  def render_spread(writer, spread, layer_filter, font_ref_resolver,
91
- font_resource, font_metrics, structure,
92
+ font_resource, font_metrics, font_map, structure,
92
93
  position_tracker, page_offset)
93
94
  pages = spread.spread.flat_map(&:page)
94
95
  image_refs = ImageCollector.new(writer: writer,
95
96
  base_dir: File.dirname(@package.path),
96
97
  page_height: DEFAULT_HEIGHT).collect(spread)
97
98
  renderer = build_renderer(layer_filter, font_ref_resolver,
98
- font_resource, font_metrics, structure,
99
- position_tracker)
99
+ font_resource, font_metrics, font_map,
100
+ structure, position_tracker)
100
101
  current = page_offset
101
102
 
102
103
  pages.each do |page|
@@ -125,10 +126,11 @@ module Idml
125
126
  end
126
127
 
127
128
  def build_renderer(layer_filter, font_ref_resolver, font_resource,
128
- font_metrics, structure, position_tracker)
129
+ font_metrics, font_map, structure, position_tracker)
129
130
  SpreadRenderer.new(
130
131
  font_metrics: font_metrics,
131
132
  font_ps_name: font_resource,
133
+ font_map: font_map,
132
134
  package: @package,
133
135
  layer_filter: layer_filter,
134
136
  font_ref_resolver: font_ref_resolver,
@@ -13,6 +13,7 @@ module Idml
13
13
  :font_ref_resolver,
14
14
  :color_resolver,
15
15
  :font_ps_name,
16
+ :font_map,
16
17
  :page_width,
17
18
  :page_height,
18
19
  :layer_filter,
@@ -18,6 +18,7 @@ module Idml
18
18
  font_ref_resolver: context.font_ref_resolver,
19
19
  color_resolver: context.color_resolver,
20
20
  font_ps_name: context.font_ps_name,
21
+ font_map: context.font_map,
21
22
  page_width: context.page_width,
22
23
  page_height: context.page_height,
23
24
  layer_filter: context.layer_filter,
@@ -116,7 +116,7 @@ module Idml
116
116
  line_width = line.width
117
117
  canvas.text(line_text(line),
118
118
  at: [line_x, line_y],
119
- font: context.font_ps_name,
119
+ font: font_for_run(run, context),
120
120
  size: size)
121
121
  record_position(context, line, line_x, line_y, line_width, size,
122
122
  cursor)
@@ -142,6 +142,20 @@ module Idml
142
142
  end
143
143
  private_class_method :record_position
144
144
 
145
+ # Resolves the font resource for a styled run. Checks the
146
+ # run's `applied_font` (family name from CSR's AppliedFont)
147
+ # against the document's font_map. Falls back to the document
148
+ # default when no per-run font is specified or the family
149
+ # isn registered.
150
+ def self.font_for_run(run, context)
151
+ family = run.applied_font
152
+ return context.font_ps_name unless family
153
+ return context.font_ps_name unless context.font_map
154
+
155
+ context.font_map[family] || context.font_ps_name
156
+ end
157
+ private_class_method :font_for_run
158
+
145
159
  def self.line_text(line)
146
160
  line.glyphs.map { |g| [g.codepoint].pack("U") }.join
147
161
  end
@@ -166,7 +180,7 @@ module Idml
166
180
  runs.map do |run|
167
181
  {
168
182
  text: run.text,
169
- font: context.font_ps_name,
183
+ font: font_for_run(run, context),
170
184
  size: run.point_size,
171
185
  }
172
186
  end
@@ -7,7 +7,7 @@ module Idml
7
7
  def initialize(font_metrics: nil, font_ps_name: Render::DEFAULT_FONT,
8
8
  package: nil, layer_filter: LayerFilter::EXCLUDE_NONE,
9
9
  font_ref_resolver: nil, structure: nil,
10
- position_tracker: nil)
10
+ position_tracker: nil, font_map: {})
11
11
  @font_metrics = font_metrics
12
12
  @font_ps_name = font_ps_name
13
13
  @package = package
@@ -15,6 +15,7 @@ module Idml
15
15
  @font_ref_resolver = font_ref_resolver
16
16
  @structure = structure
17
17
  @position_tracker = position_tracker
18
+ @font_map = font_map
18
19
  end
19
20
 
20
21
  def render(canvas, spread, page_width:, page_height:, image_refs: [],
@@ -25,6 +26,7 @@ module Idml
25
26
  font_ref_resolver: @font_ref_resolver,
26
27
  color_resolver: build_color_resolver,
27
28
  font_ps_name: @font_ps_name,
29
+ font_map: @font_map,
28
30
  page_width: page_width,
29
31
  page_height: page_height,
30
32
  layer_filter: @layer_filter,
data/lib/idml/render.rb CHANGED
@@ -2,16 +2,6 @@
2
2
 
3
3
  require "pdfrb"
4
4
 
5
- # pdfrb 0.6.0 autoloads OptContentUsage from opt_content_ext.rb but
6
- # that file doesn't define it, causing eager_load! to crash.
7
- # Trigger the autoload (catching the failure) then define a stub.
8
- begin
9
- Pdfrb::Model::Type::OptContentUsage
10
- rescue NameError
11
- Pdfrb::Model::Type.const_set(:OptContentUsage,
12
- Class.new(Pdfrb::Model::Cos::Dictionary))
13
- end
14
-
15
5
  module Idml
16
6
  module Render
17
7
  autoload :ColorHelper, "#{__dir__}/render/color_helper"
data/lib/idml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Idml
4
- VERSION = "0.5.5"
4
+ VERSION = "0.6.0"
5
5
  end
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.5.5
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose