idml 0.4.6 → 0.4.7

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: 64f0fb65e931a0ba911043cdc0a885dab5d79257519b519896c07f8a8de9cc14
4
- data.tar.gz: c25ece7b2f8d61ee13e7e572a3e4089cda665f307e20831a7a46cfa7c7c2ff52
3
+ metadata.gz: 83554bfc44e2eb23732f64f5283c221965a70823f48db100abdcb953306681e2
4
+ data.tar.gz: c3a13c6b72cd20fb5280f863db1712c10df2e636adbb777dd0d393a3042fe5cb
5
5
  SHA512:
6
- metadata.gz: e2113e93725afbf9d5c025b1d0b50d698b4bd0ef47815f7fda87a703e007627b769bbb1118b924ce6d932cf78aff23877d20de303b60f3a9df1cd51f53947849
7
- data.tar.gz: 856b9aa6fad47550fd6da61a1ebbc348be2752cde9eb5a1a165beadfd8b16c5d2ed763d0b5af68af6252b2631561b1c521200cadae00bfdafb0a15a0807d702e
6
+ metadata.gz: 798716bc9426f8ad558255e8cdca0130bc9fbc4df0b982bf052108c8ad985d8512acc478fe420c629a6823e9b474864dd6570942a95db95ecd91277dba60a36a
7
+ data.tar.gz: c3e14713c820726f1bc07ebbad6186a4f9d5f3e8a163a175f3b2905ca4183be595f5ccadf219647859fa172e754407f11fa137a6cea64074156d209ad3a31d36
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- idml (0.4.6)
4
+ idml (0.4.7)
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.4.6)
186
+ idml (0.4.7)
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
@@ -3,10 +3,22 @@
3
3
  module Idml
4
4
  module Render
5
5
  module Renderers
6
- # Renders an IDML Table. Draws the cell grid via rectangle ops,
7
- # then renders inline `<CharacterStyleRange>` text in each cell
8
- # via `canvas.text_rich`. Cells with no text render as empty
6
+ # Renders an IDML Table. Draws the cell grid via rectangle
7
+ # ops, then renders inline text in each cell via
8
+ # `canvas.text_rich`. Cells with no text render as empty
9
9
  # rectangles.
10
+ #
11
+ # Two table layouts are supported:
12
+ #
13
+ # 1. **Schema-faithful** (real IDML): `Table` has `cell`
14
+ # and `row` sibling collections. Cell `Name` encodes
15
+ # column and row as `"col:row"`. Row order determines
16
+ # vertical position; cell Name determines horizontal.
17
+ # 2. **Legacy** (synthetic test fixture): `Table` has a
18
+ # `table_row` collection, each `TableRow` has a
19
+ # `table_cell` collection. Nested structure.
20
+ #
21
+ # The renderer auto-detects which layout is present.
10
22
  class TableRenderer
11
23
  DEFAULT_SIZE = 10.0
12
24
  INSET = 4.0
@@ -14,37 +26,60 @@ module Idml
14
26
  def self.render(canvas, context)
15
27
  table = context.item
16
28
  return if table.visible == false
17
- return if table.table_row.empty?
18
29
 
19
30
  box = Placement.box(table, context.page_height)
20
31
  return unless box
21
32
 
22
- row_count = table.table_row.length
23
- row_height = box[:height] / row_count
24
-
25
33
  canvas.save_graphics_state do
26
- table.table_row.each_with_index do |row, row_index|
27
- render_row(canvas, row, row_index, row_count, box, row_height,
28
- context)
34
+ if schema_faithful?(table)
35
+ render_schema_faithful(canvas, table, box, context)
36
+ else
37
+ render_legacy(canvas, table, box, context)
29
38
  end
30
39
  end
31
40
  end
32
41
 
33
- def self.render_row(canvas, row, row_index, row_count, box, row_height,
34
- context)
35
- row_y = box[:y] + ((row_count - 1 - row_index) * row_height)
36
- cell_count = row.table_cell.length
37
- return unless cell_count.positive?
42
+ def self.schema_faithful?(table)
43
+ !table.cell.empty? || !table.row.empty?
44
+ end
45
+ private_class_method :schema_faithful?
38
46
 
39
- cell_width = box[:width] / cell_count
40
- row.table_cell.each_with_index do |cell, cell_index|
41
- cell_x = box[:x] + (cell_index * cell_width)
42
- canvas.rectangle(cell_x, row_y, cell_width, row_height)
47
+ # Real IDML: Table > {Cell, Row} siblings. Cell Name is
48
+ # "col:row". Row count from `row` collection; column count
49
+ # derived from max col + 1 across cells.
50
+ def self.render_schema_faithful(canvas, table, box, context)
51
+ layout = SchemaLayout.new(table: table, box: box)
52
+ layout.each_cell do |cell_x, cell_y, cell_w, cell_h, cell|
53
+ canvas.rectangle(cell_x, cell_y, cell_w, cell_h)
43
54
  canvas.stroke
44
- render_cell_text(canvas, cell, cell_x, row_y, row_height, context)
55
+ render_cell_text(canvas, cell, cell_x, cell_y, cell_h, context)
45
56
  end
46
57
  end
47
- private_class_method :render_row
58
+ private_class_method :render_schema_faithful
59
+
60
+ # Legacy: Table > TableRow > TableCell nested.
61
+ def self.render_legacy(canvas, table, box, context)
62
+ return if table.table_row.empty?
63
+
64
+ row_count = table.table_row.length
65
+ row_height = box[:height] / row_count
66
+
67
+ table.table_row.each_with_index do |row, row_index|
68
+ row_y = box[:y] + ((row_count - 1 - row_index) * row_height)
69
+ cell_count = row.table_cell.length
70
+ next unless cell_count.positive?
71
+
72
+ cell_width = box[:width] / cell_count
73
+ row.table_cell.each_with_index do |cell, cell_index|
74
+ cell_x = box[:x] + (cell_index * cell_width)
75
+ canvas.rectangle(cell_x, row_y, cell_width, row_height)
76
+ canvas.stroke
77
+ render_cell_text(canvas, cell, cell_x, row_y, row_height,
78
+ context)
79
+ end
80
+ end
81
+ end
82
+ private_class_method :render_legacy
48
83
 
49
84
  def self.render_cell_text(canvas, cell, x, y, height, context)
50
85
  text = cell.text_content
@@ -59,6 +94,80 @@ module Idml
59
94
  canvas.text_rich(runs, at: [x + INSET, baseline])
60
95
  end
61
96
  private_class_method :render_cell_text
97
+
98
+ # Computes per-cell rects for the schema-faithful layout.
99
+ # Row heights come from `Row#single_row_height` when present,
100
+ # else fall back to evenly-divided table height. Column
101
+ # widths are evenly divided (precise column widths would
102
+ # require ColumnAttributes lookup, deferred).
103
+ SchemaLayout = Struct.new(:table, :box, keyword_init: true) do
104
+ def each_cell
105
+ row_count.times do |row_idx|
106
+ col_count.times do |col_idx|
107
+ cell = cell_at(col_idx, row_idx)
108
+ next unless cell
109
+
110
+ yield cell_x(col_idx), cell_y(row_idx), cell_w, cell_h(row_idx),
111
+ cell
112
+ end
113
+ end
114
+ end
115
+
116
+ def row_count
117
+ rows.length
118
+ end
119
+
120
+ def col_count
121
+ @col_count ||= begin
122
+ max_col = cells.filter_map(&:col_row).map(&:first).max || 0
123
+ max_col + 1
124
+ end
125
+ end
126
+
127
+ def rows
128
+ table.row
129
+ end
130
+
131
+ def cells
132
+ table.cell
133
+ end
134
+
135
+ def cell_at(col, row)
136
+ cells.find { |c| c.col_row == [col, row] }
137
+ end
138
+
139
+ def cell_x(col)
140
+ box[:x] + (col * cell_w)
141
+ end
142
+
143
+ def cell_y(row)
144
+ box[:y] + total_height - cumulative_height(row) - cell_h(row)
145
+ end
146
+
147
+ def cell_w
148
+ box[:width] / [col_count, 1].max
149
+ end
150
+
151
+ def cell_h(row_idx)
152
+ row_heights[row_idx] || (box[:height] / [row_count, 1].max)
153
+ end
154
+
155
+ def row_heights
156
+ @row_heights ||= rows.map do |row|
157
+ h = row.single_row_height
158
+ h&.positive? ? h : nil
159
+ end
160
+ end
161
+
162
+ def total_height
163
+ @total_height ||= row_count.times.sum { |i| cell_h(i) }
164
+ end
165
+
166
+ def cumulative_height(up_to_row)
167
+ up_to_row.times.sum { |i| cell_h(i) }
168
+ end
169
+ end
170
+ private_constant :SchemaLayout
62
171
  end
63
172
  end
64
173
  end
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.4.6"
4
+ VERSION = "0.4.7"
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.4.6
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose