idml 0.9.1 → 0.9.3
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/.github/workflows/release.yml +5 -3
- data/TODO.pdf/104-table-schema-completion.md +16 -6
- data/TODO.pdf/116-justification-last-line.md +31 -0
- data/TODO.pdf/117-endnote-support.md +45 -0
- data/TODO.pdf/118-table-band-fills.md +33 -0
- data/lib/idml/elements/endnote.rb +22 -0
- data/lib/idml/elements/endnote_range.rb +21 -0
- data/lib/idml/elements/story_inner.rb +5 -0
- data/lib/idml/elements/table.rb +369 -1
- data/lib/idml/elements.rb +2 -0
- data/lib/idml/render/footnote.rb +10 -2
- data/lib/idml/render/renderers/table_renderer.rb +99 -2
- data/lib/idml/render/renderers/text_frame_renderer.rb +19 -8
- data/lib/idml/text_engine/justifier.rb +16 -5
- data/lib/idml/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b5306c44be037a52666aa508b9cdb76978561403d72bc43896ea8575b3f61340
|
|
4
|
+
data.tar.gz: 1d46f1c6de5f53f564f69ccfc41349d48d12b5f3522b7dfae1d01dc79f92ae00
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4d6830d86be109139a52ee6c2d780f31c33488eee4090b6a64ca938c871fd78429d9da7dbd9b7911d2a814e6908c1a05d53b6083abbb6b74c9d04fec141fcf18
|
|
7
|
+
data.tar.gz: '0886ff7d2aea4389f5bd0779151be35e6dd40473c2bec635ca4ff25f10321b196c09b171d104f405c4133ab699cfc008773a11533ad43fd870e755cd29b2e168'
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
# Managed by Cimas; trusted-publishing change is intentional (2026-08-18):
|
|
2
|
+
# publish via RubyGems OIDC Trusted Publishing instead of the API key
|
|
3
|
+
# (the API-key path is blocked by rubygems.org MFA OTP demands).
|
|
4
|
+
# See https://github.com/metanorma/ci — the reusable workflow uses its
|
|
5
|
+
# OIDC path whenever the rubygems-api-key secret is not passed.
|
|
3
6
|
name: release
|
|
4
7
|
|
|
5
8
|
on:
|
|
@@ -20,6 +23,5 @@ jobs:
|
|
|
20
23
|
with:
|
|
21
24
|
next_version: ${{ github.event.inputs.next_version }}
|
|
22
25
|
secrets:
|
|
23
|
-
rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
|
|
24
26
|
pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
|
|
25
27
|
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
# TODO PDF 104: Schema-faithful Table model completion
|
|
2
2
|
|
|
3
|
-
## Status:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
## Status: COMPLETE — implemented 2026-08-18
|
|
4
|
+
|
|
5
|
+
All 171 Table_Object attributes from
|
|
6
|
+
`reference-docs/schemas/package/Stories/Story.rnc` are declared on
|
|
7
|
+
`Elements::Table` (the prior rendering-relevant subset plus the 155
|
|
8
|
+
remaining: border tints/gaps/overprints, default row/column strokes,
|
|
9
|
+
alternating fills, cell insets, diagonal lines, caption settings,
|
|
10
|
+
…), generated with `scripts/rnc_to_lutaml.rb` in schema order.
|
|
11
|
+
|
|
12
|
+
Drift defense: `spec/idml/elements/table_spec.rb` reads the RNC at
|
|
13
|
+
spec time and asserts a Table built with every schema attribute
|
|
14
|
+
round-trips every attribute — any attribute dropped from the model
|
|
15
|
+
fails the spec.
|
|
16
|
+
|
|
17
|
+
The renderer still consults only the rendering-relevant subset; the
|
|
18
|
+
rest are carried for round-trip and downstream-tool fidelity.
|
|
9
19
|
|
|
10
20
|
## Problem
|
|
11
21
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# TODO PDF 116: Justified-text last-line handling
|
|
2
|
+
|
|
3
|
+
## Status: COMPLETE — implemented 2026-08-18
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
`TextEngine::Justifier` spread slack across inter-word spaces for
|
|
8
|
+
`:justified` paragraphs on EVERY line, including each paragraph's
|
|
9
|
+
final line — InDesign (and standard typography) leaves the last line
|
|
10
|
+
of a justified paragraph ragged. Every fully-justified paragraph
|
|
11
|
+
rendered with its final line stretched across the full column width.
|
|
12
|
+
|
|
13
|
+
## What was done
|
|
14
|
+
|
|
15
|
+
- `Justifier.justify` takes `last_line:`; when true, a `:justified`
|
|
16
|
+
line falls back to left alignment (no space stretching). All other
|
|
17
|
+
alignments unchanged.
|
|
18
|
+
- `TextFrameRenderer.layout_run` passes `last_line:` true for the
|
|
19
|
+
final line of the paragraph's FINAL run (`paragraph_last:` flag
|
|
20
|
+
threaded from `render_runs_for_paragraph`, which knows the run
|
|
21
|
+
list). Mid-paragraph run breaks still justify — only the true
|
|
22
|
+
paragraph-final line goes ragged.
|
|
23
|
+
- Footnote layout (`Render::Footnote.layout_paragraph`) applies the
|
|
24
|
+
same rule for the final line of the final run.
|
|
25
|
+
|
|
26
|
+
## Known limitations
|
|
27
|
+
|
|
28
|
+
- Justification adjusts inter-word spaces only; letter spacing and
|
|
29
|
+
glyph scaling (Minimum/Maximum/DesiredGlyphScaling, tracking) are
|
|
30
|
+
not applied. ToBinding / RTL binding alignment remains mapped to
|
|
31
|
+
left.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# TODO PDF 117: Endnote support
|
|
2
|
+
|
|
3
|
+
## Status: OPEN (modeling COMPLETE 2026-08-18; rendering OPEN pending
|
|
4
|
+
a real fixture)
|
|
5
|
+
|
|
6
|
+
## Problem
|
|
7
|
+
|
|
8
|
+
IDML endnotes use a reference architecture unlike footnotes: the
|
|
9
|
+
main story carries `<Endnote Self="..." EndnoteTextRange="..."/>`
|
|
10
|
+
plus `<EndnoteRange SourceEndnote="..."/>` markers (both at Story
|
|
11
|
+
level, per Story.rnc), while the endnote TEXT lives in a separate
|
|
12
|
+
story flagged `IsEndnoteStory="true"`. Documents with endnotes
|
|
13
|
+
(scholarly publishing) currently drop endnote text entirely.
|
|
14
|
+
|
|
15
|
+
## What is done (2026-08-18)
|
|
16
|
+
|
|
17
|
+
- `Elements::Endnote` (Self, EndnoteTextRange) and
|
|
18
|
+
`Elements::EndnoteRange` (Self, SourceEndnote) — schema-faithful
|
|
19
|
+
models, wired into `StoryInner` (`endnote`, `endnote_range`
|
|
20
|
+
collections). Round-trip + parse specs.
|
|
21
|
+
- `StoryInner#is_endnote_story` already parsed, so endnote stories
|
|
22
|
+
are identifiable.
|
|
23
|
+
|
|
24
|
+
## Design for rendering (needs a real InDesign fixture to validate)
|
|
25
|
+
|
|
26
|
+
1. Marker: story-level `Endnote`/`EndnoteRange` pairs delimit the
|
|
27
|
+
anchor range; marker position requires story text-offset
|
|
28
|
+
bookkeeping the extraction layer doesn't currently track (unlike
|
|
29
|
+
footnotes, which sit inside a CSR). A range-aware extraction is
|
|
30
|
+
the prerequisite.
|
|
31
|
+
2. Endnote text: resolve `EndnoteTextRange` → the endnote story
|
|
32
|
+
(IsEndnoteStory) → its paragraphs.
|
|
33
|
+
3. Placement: per EndnoteOption Scope — end of story / end of
|
|
34
|
+
section / end of document; end-of-story is the tractable default
|
|
35
|
+
(append after the referencing story's last paragraph).
|
|
36
|
+
4. Numbering: endnotes number separately from footnotes
|
|
37
|
+
(FootnoteOption vs EndnoteOption StartAt/Prefix/Suffix — the
|
|
38
|
+
Endnote preference object is not yet modeled in Preferences).
|
|
39
|
+
|
|
40
|
+
## Why rendering is deferred
|
|
41
|
+
|
|
42
|
+
The marker-position machinery (text-range resolution) cannot be
|
|
43
|
+
validated without a real fixture; blind implementation risks wrong
|
|
44
|
+
anchor placement on production files. Schema modeling + round-trip
|
|
45
|
+
is complete and verified.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# TODO PDF 118: Table alternating row/column band fills
|
|
2
|
+
|
|
3
|
+
## Status: COMPLETE — implemented 2026-08-18
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
IDML tables declare table-level alternating fills —
|
|
8
|
+
StartRowFillColor/Count + EndRowFillColor/Count (row banding),
|
|
9
|
+
StartColumnFillColor/Count + EndColumnFillColor/Count (column
|
|
10
|
+
banding), ColumnFillsPriority (true = column banding wins),
|
|
11
|
+
SkipFirst/LastAlternatingFillRows/Columns (edge suppression), and
|
|
12
|
+
per-band tints. All attributes are modeled (TODO 104) but the
|
|
13
|
+
renderer only honored per-Cell FillColor, so banded tables (zebra
|
|
14
|
+
stripes, ledger shading) rendered without their backgrounds.
|
|
15
|
+
|
|
16
|
+
## What was done
|
|
17
|
+
|
|
18
|
+
- `SchemaLayout#band_fill(col, row)` computes the effective band
|
|
19
|
+
color + tint for a cell position: row banding by default; column
|
|
20
|
+
banding when ColumnFillsPriority is true or row banding is
|
|
21
|
+
unconfigured; SkipFirst/Last offsets suppress banding at the
|
|
22
|
+
table edges; "Color/None" band colors render nothing.
|
|
23
|
+
- `TableRenderer` paints the band rect behind each cell BEFORE the
|
|
24
|
+
cell's own background — an explicit Cell FillColor overrides the
|
|
25
|
+
band, matching InDesign.
|
|
26
|
+
- `each_cell` now also yields the cell's column/row indices.
|
|
27
|
+
|
|
28
|
+
## Acceptance criteria
|
|
29
|
+
|
|
30
|
+
- [x] Rows alternate Start/End colors in the declared counts.
|
|
31
|
+
- [x] Cell-level fill overrides the band.
|
|
32
|
+
- [x] Column banding wins when ColumnFillsPriority is true.
|
|
33
|
+
- [x] SkipFirstAlternatingFillRows suppresses leading bands.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Idml
|
|
4
|
+
module Elements
|
|
5
|
+
# `<Endnote>` — a story-level endnote reference. The endnote's
|
|
6
|
+
# TEXT lives in a separate story flagged `IsEndnoteStory="true"`;
|
|
7
|
+
# this element points at it via `EndnoteTextRange` (schema:
|
|
8
|
+
# Endnote_Object in Stories/Story.rnc — Self plus the range
|
|
9
|
+
# reference; no inline content). Rendering design in
|
|
10
|
+
# TODO.pdf/117-endnote-support.md.
|
|
11
|
+
class Endnote < Lutaml::Model::Serializable
|
|
12
|
+
attribute :self_attr, :string
|
|
13
|
+
attribute :endnote_text_range, :string
|
|
14
|
+
|
|
15
|
+
xml do
|
|
16
|
+
root "Endnote"
|
|
17
|
+
map_attribute "Self", to: :self_attr
|
|
18
|
+
map_attribute "EndnoteTextRange", to: :endnote_text_range
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Idml
|
|
4
|
+
module Elements
|
|
5
|
+
# `<EndnoteRange>` — marks the text range in the main story that
|
|
6
|
+
# an endnote references, linking back via `SourceEndnote`
|
|
7
|
+
# (schema: EndnoteRange_Object in Stories/Story.rnc). Pairs with
|
|
8
|
+
# Elements::Endnote; rendering design in
|
|
9
|
+
# TODO.pdf/117-endnote-support.md.
|
|
10
|
+
class EndnoteRange < Lutaml::Model::Serializable
|
|
11
|
+
attribute :self_attr, :string
|
|
12
|
+
attribute :source_endnote, :string
|
|
13
|
+
|
|
14
|
+
xml do
|
|
15
|
+
root "EndnoteRange"
|
|
16
|
+
map_attribute "Self", to: :self_attr
|
|
17
|
+
map_attribute "SourceEndnote", to: :source_endnote
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -313,6 +313,9 @@ module Idml
|
|
|
313
313
|
attribute :content, Idml::Elements::Content, collection: true
|
|
314
314
|
attribute :xml_element, Idml::Elements::XmlElement, collection: true
|
|
315
315
|
attribute :footnote, Idml::Elements::Footnote, collection: true
|
|
316
|
+
attribute :endnote, Idml::Elements::Endnote, collection: true
|
|
317
|
+
attribute :endnote_range, Idml::Elements::EndnoteRange,
|
|
318
|
+
collection: true
|
|
316
319
|
|
|
317
320
|
xml do
|
|
318
321
|
root "Story"
|
|
@@ -678,6 +681,8 @@ module Idml
|
|
|
678
681
|
map_element "Content", to: :content
|
|
679
682
|
map_element "XMLElement", to: :xml_element
|
|
680
683
|
map_element "Footnote", to: :footnote
|
|
684
|
+
map_element "Endnote", to: :endnote
|
|
685
|
+
map_element "EndnoteRange", to: :endnote_range
|
|
681
686
|
end
|
|
682
687
|
|
|
683
688
|
def text_content
|
data/lib/idml/elements/table.rb
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
module Idml
|
|
4
4
|
module Elements
|
|
5
5
|
# `<Table>` — a table page item. Carries geometry, body/header
|
|
6
|
-
# row counts, column layout, and border styling.
|
|
6
|
+
# row counts, column layout, and border styling. Declares every
|
|
7
|
+
# attribute of Table_Object in Stories/Story.rnc (171 schema
|
|
8
|
+
# attributes). Two child
|
|
7
9
|
# collections hold the table's content:
|
|
8
10
|
#
|
|
9
11
|
# - `row` — schema-faithful `<Row>` siblings (real IDML).
|
|
@@ -43,6 +45,167 @@ module Idml
|
|
|
43
45
|
attribute :right_border_stroke_weight, :float
|
|
44
46
|
attribute :right_border_stroke_color, :string
|
|
45
47
|
|
|
48
|
+
# The remaining Table_Object attributes (border tints/gaps/
|
|
49
|
+
# overprints, default row/column strokes, alternating fills,
|
|
50
|
+
# cell insets, diagonal lines, caption settings, …) in schema
|
|
51
|
+
# order — generated by `scripts/rnc_to_lutaml.rb` from
|
|
52
|
+
# reference-docs/schemas/package/Stories/Story.rnc.
|
|
53
|
+
attribute :top_border_stroke_type, :string
|
|
54
|
+
attribute :top_border_stroke_tint, :float
|
|
55
|
+
attribute :top_border_stroke_overprint, :boolean
|
|
56
|
+
attribute :top_border_stroke_gap_color, :string
|
|
57
|
+
attribute :top_border_stroke_gap_tint, :float
|
|
58
|
+
attribute :top_border_stroke_gap_overprint, :boolean
|
|
59
|
+
attribute :left_border_stroke_type, :string
|
|
60
|
+
attribute :left_border_stroke_tint, :float
|
|
61
|
+
attribute :left_border_stroke_overprint, :boolean
|
|
62
|
+
attribute :left_border_stroke_gap_color, :string
|
|
63
|
+
attribute :left_border_stroke_gap_tint, :float
|
|
64
|
+
attribute :left_border_stroke_gap_overprint, :boolean
|
|
65
|
+
attribute :bottom_border_stroke_type, :string
|
|
66
|
+
attribute :bottom_border_stroke_tint, :float
|
|
67
|
+
attribute :bottom_border_stroke_overprint, :boolean
|
|
68
|
+
attribute :bottom_border_stroke_gap_color, :string
|
|
69
|
+
attribute :bottom_border_stroke_gap_tint, :float
|
|
70
|
+
attribute :bottom_border_stroke_gap_overprint, :boolean
|
|
71
|
+
attribute :right_border_stroke_type, :string
|
|
72
|
+
attribute :right_border_stroke_tint, :float
|
|
73
|
+
attribute :right_border_stroke_overprint, :boolean
|
|
74
|
+
attribute :right_border_stroke_gap_color, :string
|
|
75
|
+
attribute :right_border_stroke_gap_tint, :float
|
|
76
|
+
attribute :right_border_stroke_gap_overprint, :boolean
|
|
77
|
+
attribute :space_before, :float
|
|
78
|
+
attribute :space_after, :float
|
|
79
|
+
attribute :skip_first_alternating_stroke_rows, :integer
|
|
80
|
+
attribute :skip_last_alternating_stroke_rows, :integer
|
|
81
|
+
attribute :start_row_stroke_count, :integer
|
|
82
|
+
attribute :start_row_stroke_color, :string
|
|
83
|
+
attribute :start_row_stroke_weight, :float
|
|
84
|
+
attribute :start_row_stroke_type, :string
|
|
85
|
+
attribute :start_row_stroke_tint, :float
|
|
86
|
+
attribute :start_row_stroke_gap_overprint, :boolean
|
|
87
|
+
attribute :start_row_stroke_gap_color, :string
|
|
88
|
+
attribute :start_row_stroke_gap_tint, :float
|
|
89
|
+
attribute :start_row_stroke_overprint, :boolean
|
|
90
|
+
attribute :end_row_stroke_count, :integer
|
|
91
|
+
attribute :end_row_stroke_color, :string
|
|
92
|
+
attribute :end_row_stroke_weight, :float
|
|
93
|
+
attribute :end_row_stroke_type, :string
|
|
94
|
+
attribute :end_row_stroke_tint, :float
|
|
95
|
+
attribute :end_row_stroke_overprint, :boolean
|
|
96
|
+
attribute :end_row_stroke_gap_color, :string
|
|
97
|
+
attribute :end_row_stroke_gap_tint, :float
|
|
98
|
+
attribute :end_row_stroke_gap_overprint, :boolean
|
|
99
|
+
attribute :skip_first_alternating_stroke_columns, :integer
|
|
100
|
+
attribute :skip_last_alternating_stroke_columns, :integer
|
|
101
|
+
attribute :start_column_stroke_count, :integer
|
|
102
|
+
attribute :start_column_stroke_color, :string
|
|
103
|
+
attribute :start_column_stroke_weight, :float
|
|
104
|
+
attribute :start_column_stroke_type, :string
|
|
105
|
+
attribute :start_column_stroke_tint, :float
|
|
106
|
+
attribute :start_column_stroke_overprint, :boolean
|
|
107
|
+
attribute :start_column_stroke_gap_color, :string
|
|
108
|
+
attribute :start_column_stroke_gap_tint, :float
|
|
109
|
+
attribute :start_column_stroke_gap_overprint, :boolean
|
|
110
|
+
attribute :end_column_stroke_count, :integer
|
|
111
|
+
attribute :end_column_stroke_color, :string
|
|
112
|
+
attribute :end_column_stroke_weight, :float
|
|
113
|
+
attribute :end_column_line_style, :string
|
|
114
|
+
attribute :end_column_stroke_tint, :float
|
|
115
|
+
attribute :end_column_stroke_overprint, :boolean
|
|
116
|
+
attribute :end_column_stroke_gap_color, :string
|
|
117
|
+
attribute :end_column_stroke_gap_tint, :float
|
|
118
|
+
attribute :end_column_stroke_gap_overprint, :boolean
|
|
119
|
+
attribute :column_fills_priority, :boolean
|
|
120
|
+
attribute :skip_first_alternating_fill_rows, :integer
|
|
121
|
+
attribute :skip_last_alternating_fill_rows, :integer
|
|
122
|
+
attribute :start_row_fill_color, :string
|
|
123
|
+
attribute :start_row_fill_count, :integer
|
|
124
|
+
attribute :start_row_fill_tint, :float
|
|
125
|
+
attribute :start_row_fill_overprint, :boolean
|
|
126
|
+
attribute :end_row_fill_count, :integer
|
|
127
|
+
attribute :end_row_fill_color, :string
|
|
128
|
+
attribute :end_row_fill_tint, :float
|
|
129
|
+
attribute :end_row_fill_overprint, :boolean
|
|
130
|
+
attribute :skip_first_alternating_fill_columns, :integer
|
|
131
|
+
attribute :skip_last_alternating_fill_columns, :integer
|
|
132
|
+
attribute :start_column_fill_count, :integer
|
|
133
|
+
attribute :start_column_fill_color, :string
|
|
134
|
+
attribute :start_column_fill_tint, :float
|
|
135
|
+
attribute :start_column_fill_overprint, :boolean
|
|
136
|
+
attribute :end_column_fill_count, :integer
|
|
137
|
+
attribute :end_column_fill_color, :string
|
|
138
|
+
attribute :end_column_fill_tint, :float
|
|
139
|
+
attribute :end_column_fill_overprint, :boolean
|
|
140
|
+
attribute :break_headers, :string
|
|
141
|
+
attribute :break_footers, :string
|
|
142
|
+
attribute :skip_first_header, :boolean
|
|
143
|
+
attribute :skip_last_footer, :boolean
|
|
144
|
+
attribute :stroke_order, :string
|
|
145
|
+
attribute :default_row_stroke_weight, :float
|
|
146
|
+
attribute :default_row_stroke_type, :string
|
|
147
|
+
attribute :default_row_stroke_color, :string
|
|
148
|
+
attribute :default_row_stroke_tint, :float
|
|
149
|
+
attribute :default_row_stroke_overprint, :boolean
|
|
150
|
+
attribute :default_row_stroke_gap_color, :string
|
|
151
|
+
attribute :default_row_stroke_gap_tint, :float
|
|
152
|
+
attribute :default_row_stroke_gap_overprint, :boolean
|
|
153
|
+
attribute :default_column_stroke_weight, :float
|
|
154
|
+
attribute :default_column_stroke_type, :string
|
|
155
|
+
attribute :default_column_stroke_color, :string
|
|
156
|
+
attribute :default_column_stroke_tint, :float
|
|
157
|
+
attribute :default_column_stroke_overprint, :boolean
|
|
158
|
+
attribute :default_column_stroke_gap_color, :string
|
|
159
|
+
attribute :default_column_stroke_gap_tint, :float
|
|
160
|
+
attribute :default_column_stroke_gap_overprint, :boolean
|
|
161
|
+
attribute :top_inset, :float
|
|
162
|
+
attribute :left_inset, :float
|
|
163
|
+
attribute :bottom_inset, :float
|
|
164
|
+
attribute :right_inset, :float
|
|
165
|
+
attribute :fill_tint, :float
|
|
166
|
+
attribute :overprint_fill, :boolean
|
|
167
|
+
attribute :top_left_diagonal_line, :boolean
|
|
168
|
+
attribute :top_right_diagonal_line, :boolean
|
|
169
|
+
attribute :diagonal_line_in_front, :boolean
|
|
170
|
+
attribute :diagonal_line_stroke_weight, :float
|
|
171
|
+
attribute :diagonal_line_stroke_type, :string
|
|
172
|
+
attribute :diagonal_line_stroke_color, :string
|
|
173
|
+
attribute :diagonal_line_stroke_tint, :float
|
|
174
|
+
attribute :diagonal_line_stroke_overprint, :boolean
|
|
175
|
+
attribute :diagonal_line_stroke_gap_color, :string
|
|
176
|
+
attribute :diagonal_line_stroke_gap_tint, :float
|
|
177
|
+
attribute :diagonal_line_stroke_gap_overprint, :boolean
|
|
178
|
+
attribute :clip_content_to_cell, :boolean
|
|
179
|
+
attribute :first_baseline_offset, :string
|
|
180
|
+
attribute :vertical_justification, :string
|
|
181
|
+
attribute :paragraph_spacing_limit, :float
|
|
182
|
+
attribute :minimum_first_baseline_offset, :float
|
|
183
|
+
attribute :rotation_angle, :float
|
|
184
|
+
attribute :writing_direction, :boolean
|
|
185
|
+
attribute :minimum_height, :float
|
|
186
|
+
attribute :maximum_height, :float
|
|
187
|
+
attribute :keep_with_next_row, :boolean
|
|
188
|
+
attribute :start_row, :string
|
|
189
|
+
attribute :auto_grow, :boolean
|
|
190
|
+
attribute :num_header_columns, :integer
|
|
191
|
+
attribute :header_columns_position, :string
|
|
192
|
+
attribute :caption_paragraph_count, :integer
|
|
193
|
+
attribute :caption_position, :string
|
|
194
|
+
attribute :graphic_left_inset, :float
|
|
195
|
+
attribute :graphic_top_inset, :float
|
|
196
|
+
attribute :graphic_right_inset, :float
|
|
197
|
+
attribute :graphic_bottom_inset, :float
|
|
198
|
+
attribute :clip_content_to_graphic_cell, :boolean
|
|
199
|
+
attribute :text_top_inset, :float
|
|
200
|
+
attribute :text_left_inset, :float
|
|
201
|
+
attribute :text_bottom_inset, :float
|
|
202
|
+
attribute :text_right_inset, :float
|
|
203
|
+
attribute :clip_content_to_text_cell, :boolean
|
|
204
|
+
attribute :single_row_height, :float
|
|
205
|
+
attribute :applied_table_style, :string
|
|
206
|
+
attribute :display_collapsed, :boolean
|
|
207
|
+
attribute :display_order, :string
|
|
208
|
+
|
|
46
209
|
attribute :table_row, Idml::Elements::TableRow, collection: true
|
|
47
210
|
attribute :cell, Idml::Elements::Cell, collection: true
|
|
48
211
|
attribute :row, Idml::Elements::Row, collection: true
|
|
@@ -75,6 +238,211 @@ module Idml
|
|
|
75
238
|
to: :bottom_border_stroke_color
|
|
76
239
|
map_attribute "RightBorderStrokeWeight", to: :right_border_stroke_weight
|
|
77
240
|
map_attribute "RightBorderStrokeColor", to: :right_border_stroke_color
|
|
241
|
+
map_attribute "TopBorderStrokeType", to: :top_border_stroke_type
|
|
242
|
+
map_attribute "TopBorderStrokeTint", to: :top_border_stroke_tint
|
|
243
|
+
map_attribute "TopBorderStrokeOverprint",
|
|
244
|
+
to: :top_border_stroke_overprint
|
|
245
|
+
map_attribute "TopBorderStrokeGapColor",
|
|
246
|
+
to: :top_border_stroke_gap_color
|
|
247
|
+
map_attribute "TopBorderStrokeGapTint", to: :top_border_stroke_gap_tint
|
|
248
|
+
map_attribute "TopBorderStrokeGapOverprint",
|
|
249
|
+
to: :top_border_stroke_gap_overprint
|
|
250
|
+
map_attribute "LeftBorderStrokeType", to: :left_border_stroke_type
|
|
251
|
+
map_attribute "LeftBorderStrokeTint", to: :left_border_stroke_tint
|
|
252
|
+
map_attribute "LeftBorderStrokeOverprint",
|
|
253
|
+
to: :left_border_stroke_overprint
|
|
254
|
+
map_attribute "LeftBorderStrokeGapColor",
|
|
255
|
+
to: :left_border_stroke_gap_color
|
|
256
|
+
map_attribute "LeftBorderStrokeGapTint",
|
|
257
|
+
to: :left_border_stroke_gap_tint
|
|
258
|
+
map_attribute "LeftBorderStrokeGapOverprint",
|
|
259
|
+
to: :left_border_stroke_gap_overprint
|
|
260
|
+
map_attribute "BottomBorderStrokeType", to: :bottom_border_stroke_type
|
|
261
|
+
map_attribute "BottomBorderStrokeTint", to: :bottom_border_stroke_tint
|
|
262
|
+
map_attribute "BottomBorderStrokeOverprint",
|
|
263
|
+
to: :bottom_border_stroke_overprint
|
|
264
|
+
map_attribute "BottomBorderStrokeGapColor",
|
|
265
|
+
to: :bottom_border_stroke_gap_color
|
|
266
|
+
map_attribute "BottomBorderStrokeGapTint",
|
|
267
|
+
to: :bottom_border_stroke_gap_tint
|
|
268
|
+
map_attribute "BottomBorderStrokeGapOverprint",
|
|
269
|
+
to: :bottom_border_stroke_gap_overprint
|
|
270
|
+
map_attribute "RightBorderStrokeType", to: :right_border_stroke_type
|
|
271
|
+
map_attribute "RightBorderStrokeTint", to: :right_border_stroke_tint
|
|
272
|
+
map_attribute "RightBorderStrokeOverprint",
|
|
273
|
+
to: :right_border_stroke_overprint
|
|
274
|
+
map_attribute "RightBorderStrokeGapColor",
|
|
275
|
+
to: :right_border_stroke_gap_color
|
|
276
|
+
map_attribute "RightBorderStrokeGapTint",
|
|
277
|
+
to: :right_border_stroke_gap_tint
|
|
278
|
+
map_attribute "RightBorderStrokeGapOverprint",
|
|
279
|
+
to: :right_border_stroke_gap_overprint
|
|
280
|
+
map_attribute "SpaceBefore", to: :space_before
|
|
281
|
+
map_attribute "SpaceAfter", to: :space_after
|
|
282
|
+
map_attribute "SkipFirstAlternatingStrokeRows",
|
|
283
|
+
to: :skip_first_alternating_stroke_rows
|
|
284
|
+
map_attribute "SkipLastAlternatingStrokeRows",
|
|
285
|
+
to: :skip_last_alternating_stroke_rows
|
|
286
|
+
map_attribute "StartRowStrokeCount", to: :start_row_stroke_count
|
|
287
|
+
map_attribute "StartRowStrokeColor", to: :start_row_stroke_color
|
|
288
|
+
map_attribute "StartRowStrokeWeight", to: :start_row_stroke_weight
|
|
289
|
+
map_attribute "StartRowStrokeType", to: :start_row_stroke_type
|
|
290
|
+
map_attribute "StartRowStrokeTint", to: :start_row_stroke_tint
|
|
291
|
+
map_attribute "StartRowStrokeGapOverprint",
|
|
292
|
+
to: :start_row_stroke_gap_overprint
|
|
293
|
+
map_attribute "StartRowStrokeGapColor", to: :start_row_stroke_gap_color
|
|
294
|
+
map_attribute "StartRowStrokeGapTint", to: :start_row_stroke_gap_tint
|
|
295
|
+
map_attribute "StartRowStrokeOverprint", to: :start_row_stroke_overprint
|
|
296
|
+
map_attribute "EndRowStrokeCount", to: :end_row_stroke_count
|
|
297
|
+
map_attribute "EndRowStrokeColor", to: :end_row_stroke_color
|
|
298
|
+
map_attribute "EndRowStrokeWeight", to: :end_row_stroke_weight
|
|
299
|
+
map_attribute "EndRowStrokeType", to: :end_row_stroke_type
|
|
300
|
+
map_attribute "EndRowStrokeTint", to: :end_row_stroke_tint
|
|
301
|
+
map_attribute "EndRowStrokeOverprint", to: :end_row_stroke_overprint
|
|
302
|
+
map_attribute "EndRowStrokeGapColor", to: :end_row_stroke_gap_color
|
|
303
|
+
map_attribute "EndRowStrokeGapTint", to: :end_row_stroke_gap_tint
|
|
304
|
+
map_attribute "EndRowStrokeGapOverprint",
|
|
305
|
+
to: :end_row_stroke_gap_overprint
|
|
306
|
+
map_attribute "SkipFirstAlternatingStrokeColumns",
|
|
307
|
+
to: :skip_first_alternating_stroke_columns
|
|
308
|
+
map_attribute "SkipLastAlternatingStrokeColumns",
|
|
309
|
+
to: :skip_last_alternating_stroke_columns
|
|
310
|
+
map_attribute "StartColumnStrokeCount", to: :start_column_stroke_count
|
|
311
|
+
map_attribute "StartColumnStrokeColor", to: :start_column_stroke_color
|
|
312
|
+
map_attribute "StartColumnStrokeWeight", to: :start_column_stroke_weight
|
|
313
|
+
map_attribute "StartColumnStrokeType", to: :start_column_stroke_type
|
|
314
|
+
map_attribute "StartColumnStrokeTint", to: :start_column_stroke_tint
|
|
315
|
+
map_attribute "StartColumnStrokeOverprint",
|
|
316
|
+
to: :start_column_stroke_overprint
|
|
317
|
+
map_attribute "StartColumnStrokeGapColor",
|
|
318
|
+
to: :start_column_stroke_gap_color
|
|
319
|
+
map_attribute "StartColumnStrokeGapTint",
|
|
320
|
+
to: :start_column_stroke_gap_tint
|
|
321
|
+
map_attribute "StartColumnStrokeGapOverprint",
|
|
322
|
+
to: :start_column_stroke_gap_overprint
|
|
323
|
+
map_attribute "EndColumnStrokeCount", to: :end_column_stroke_count
|
|
324
|
+
map_attribute "EndColumnStrokeColor", to: :end_column_stroke_color
|
|
325
|
+
map_attribute "EndColumnStrokeWeight", to: :end_column_stroke_weight
|
|
326
|
+
map_attribute "EndColumnLineStyle", to: :end_column_line_style
|
|
327
|
+
map_attribute "EndColumnStrokeTint", to: :end_column_stroke_tint
|
|
328
|
+
map_attribute "EndColumnStrokeOverprint",
|
|
329
|
+
to: :end_column_stroke_overprint
|
|
330
|
+
map_attribute "EndColumnStrokeGapColor",
|
|
331
|
+
to: :end_column_stroke_gap_color
|
|
332
|
+
map_attribute "EndColumnStrokeGapTint", to: :end_column_stroke_gap_tint
|
|
333
|
+
map_attribute "EndColumnStrokeGapOverprint",
|
|
334
|
+
to: :end_column_stroke_gap_overprint
|
|
335
|
+
map_attribute "ColumnFillsPriority", to: :column_fills_priority
|
|
336
|
+
map_attribute "SkipFirstAlternatingFillRows",
|
|
337
|
+
to: :skip_first_alternating_fill_rows
|
|
338
|
+
map_attribute "SkipLastAlternatingFillRows",
|
|
339
|
+
to: :skip_last_alternating_fill_rows
|
|
340
|
+
map_attribute "StartRowFillColor", to: :start_row_fill_color
|
|
341
|
+
map_attribute "StartRowFillCount", to: :start_row_fill_count
|
|
342
|
+
map_attribute "StartRowFillTint", to: :start_row_fill_tint
|
|
343
|
+
map_attribute "StartRowFillOverprint", to: :start_row_fill_overprint
|
|
344
|
+
map_attribute "EndRowFillCount", to: :end_row_fill_count
|
|
345
|
+
map_attribute "EndRowFillColor", to: :end_row_fill_color
|
|
346
|
+
map_attribute "EndRowFillTint", to: :end_row_fill_tint
|
|
347
|
+
map_attribute "EndRowFillOverprint", to: :end_row_fill_overprint
|
|
348
|
+
map_attribute "SkipFirstAlternatingFillColumns",
|
|
349
|
+
to: :skip_first_alternating_fill_columns
|
|
350
|
+
map_attribute "SkipLastAlternatingFillColumns",
|
|
351
|
+
to: :skip_last_alternating_fill_columns
|
|
352
|
+
map_attribute "StartColumnFillCount", to: :start_column_fill_count
|
|
353
|
+
map_attribute "StartColumnFillColor", to: :start_column_fill_color
|
|
354
|
+
map_attribute "StartColumnFillTint", to: :start_column_fill_tint
|
|
355
|
+
map_attribute "StartColumnFillOverprint",
|
|
356
|
+
to: :start_column_fill_overprint
|
|
357
|
+
map_attribute "EndColumnFillCount", to: :end_column_fill_count
|
|
358
|
+
map_attribute "EndColumnFillColor", to: :end_column_fill_color
|
|
359
|
+
map_attribute "EndColumnFillTint", to: :end_column_fill_tint
|
|
360
|
+
map_attribute "EndColumnFillOverprint", to: :end_column_fill_overprint
|
|
361
|
+
map_attribute "BreakHeaders", to: :break_headers
|
|
362
|
+
map_attribute "BreakFooters", to: :break_footers
|
|
363
|
+
map_attribute "SkipFirstHeader", to: :skip_first_header
|
|
364
|
+
map_attribute "SkipLastFooter", to: :skip_last_footer
|
|
365
|
+
map_attribute "StrokeOrder", to: :stroke_order
|
|
366
|
+
map_attribute "DefaultRowStrokeWeight", to: :default_row_stroke_weight
|
|
367
|
+
map_attribute "DefaultRowStrokeType", to: :default_row_stroke_type
|
|
368
|
+
map_attribute "DefaultRowStrokeColor", to: :default_row_stroke_color
|
|
369
|
+
map_attribute "DefaultRowStrokeTint", to: :default_row_stroke_tint
|
|
370
|
+
map_attribute "DefaultRowStrokeOverprint",
|
|
371
|
+
to: :default_row_stroke_overprint
|
|
372
|
+
map_attribute "DefaultRowStrokeGapColor",
|
|
373
|
+
to: :default_row_stroke_gap_color
|
|
374
|
+
map_attribute "DefaultRowStrokeGapTint",
|
|
375
|
+
to: :default_row_stroke_gap_tint
|
|
376
|
+
map_attribute "DefaultRowStrokeGapOverprint",
|
|
377
|
+
to: :default_row_stroke_gap_overprint
|
|
378
|
+
map_attribute "DefaultColumnStrokeWeight",
|
|
379
|
+
to: :default_column_stroke_weight
|
|
380
|
+
map_attribute "DefaultColumnStrokeType", to: :default_column_stroke_type
|
|
381
|
+
map_attribute "DefaultColumnStrokeColor",
|
|
382
|
+
to: :default_column_stroke_color
|
|
383
|
+
map_attribute "DefaultColumnStrokeTint", to: :default_column_stroke_tint
|
|
384
|
+
map_attribute "DefaultColumnStrokeOverprint",
|
|
385
|
+
to: :default_column_stroke_overprint
|
|
386
|
+
map_attribute "DefaultColumnStrokeGapColor",
|
|
387
|
+
to: :default_column_stroke_gap_color
|
|
388
|
+
map_attribute "DefaultColumnStrokeGapTint",
|
|
389
|
+
to: :default_column_stroke_gap_tint
|
|
390
|
+
map_attribute "DefaultColumnStrokeGapOverprint",
|
|
391
|
+
to: :default_column_stroke_gap_overprint
|
|
392
|
+
map_attribute "TopInset", to: :top_inset
|
|
393
|
+
map_attribute "LeftInset", to: :left_inset
|
|
394
|
+
map_attribute "BottomInset", to: :bottom_inset
|
|
395
|
+
map_attribute "RightInset", to: :right_inset
|
|
396
|
+
map_attribute "FillTint", to: :fill_tint
|
|
397
|
+
map_attribute "OverprintFill", to: :overprint_fill
|
|
398
|
+
map_attribute "TopLeftDiagonalLine", to: :top_left_diagonal_line
|
|
399
|
+
map_attribute "TopRightDiagonalLine", to: :top_right_diagonal_line
|
|
400
|
+
map_attribute "DiagonalLineInFront", to: :diagonal_line_in_front
|
|
401
|
+
map_attribute "DiagonalLineStrokeWeight",
|
|
402
|
+
to: :diagonal_line_stroke_weight
|
|
403
|
+
map_attribute "DiagonalLineStrokeType", to: :diagonal_line_stroke_type
|
|
404
|
+
map_attribute "DiagonalLineStrokeColor", to: :diagonal_line_stroke_color
|
|
405
|
+
map_attribute "DiagonalLineStrokeTint", to: :diagonal_line_stroke_tint
|
|
406
|
+
map_attribute "DiagonalLineStrokeOverprint",
|
|
407
|
+
to: :diagonal_line_stroke_overprint
|
|
408
|
+
map_attribute "DiagonalLineStrokeGapColor",
|
|
409
|
+
to: :diagonal_line_stroke_gap_color
|
|
410
|
+
map_attribute "DiagonalLineStrokeGapTint",
|
|
411
|
+
to: :diagonal_line_stroke_gap_tint
|
|
412
|
+
map_attribute "DiagonalLineStrokeGapOverprint",
|
|
413
|
+
to: :diagonal_line_stroke_gap_overprint
|
|
414
|
+
map_attribute "ClipContentToCell", to: :clip_content_to_cell
|
|
415
|
+
map_attribute "FirstBaselineOffset", to: :first_baseline_offset
|
|
416
|
+
map_attribute "VerticalJustification", to: :vertical_justification
|
|
417
|
+
map_attribute "ParagraphSpacingLimit", to: :paragraph_spacing_limit
|
|
418
|
+
map_attribute "MinimumFirstBaselineOffset",
|
|
419
|
+
to: :minimum_first_baseline_offset
|
|
420
|
+
map_attribute "RotationAngle", to: :rotation_angle
|
|
421
|
+
map_attribute "WritingDirection", to: :writing_direction
|
|
422
|
+
map_attribute "MinimumHeight", to: :minimum_height
|
|
423
|
+
map_attribute "MaximumHeight", to: :maximum_height
|
|
424
|
+
map_attribute "KeepWithNextRow", to: :keep_with_next_row
|
|
425
|
+
map_attribute "StartRow", to: :start_row
|
|
426
|
+
map_attribute "AutoGrow", to: :auto_grow
|
|
427
|
+
map_attribute "NumHeaderColumns", to: :num_header_columns
|
|
428
|
+
map_attribute "HeaderColumnsPosition", to: :header_columns_position
|
|
429
|
+
map_attribute "CaptionParagraphCount", to: :caption_paragraph_count
|
|
430
|
+
map_attribute "CaptionPosition", to: :caption_position
|
|
431
|
+
map_attribute "GraphicLeftInset", to: :graphic_left_inset
|
|
432
|
+
map_attribute "GraphicTopInset", to: :graphic_top_inset
|
|
433
|
+
map_attribute "GraphicRightInset", to: :graphic_right_inset
|
|
434
|
+
map_attribute "GraphicBottomInset", to: :graphic_bottom_inset
|
|
435
|
+
map_attribute "ClipContentToGraphicCell",
|
|
436
|
+
to: :clip_content_to_graphic_cell
|
|
437
|
+
map_attribute "TextTopInset", to: :text_top_inset
|
|
438
|
+
map_attribute "TextLeftInset", to: :text_left_inset
|
|
439
|
+
map_attribute "TextBottomInset", to: :text_bottom_inset
|
|
440
|
+
map_attribute "TextRightInset", to: :text_right_inset
|
|
441
|
+
map_attribute "ClipContentToTextCell", to: :clip_content_to_text_cell
|
|
442
|
+
map_attribute "SingleRowHeight", to: :single_row_height
|
|
443
|
+
map_attribute "AppliedTableStyle", to: :applied_table_style
|
|
444
|
+
map_attribute "DisplayCollapsed", to: :display_collapsed
|
|
445
|
+
map_attribute "DisplayOrder", to: :display_order
|
|
78
446
|
map_element "TableRow", to: :table_row
|
|
79
447
|
map_element "Cell", to: :cell
|
|
80
448
|
map_element "Row", to: :row
|
data/lib/idml/elements.rb
CHANGED
|
@@ -43,6 +43,8 @@ module Idml
|
|
|
43
43
|
autoload :DocumentPreference, "idml/elements/pref_document_preference"
|
|
44
44
|
autoload :DottedStrokeStyle, "idml/elements/dotted_stroke_style"
|
|
45
45
|
autoload :DropShadowSetting, "idml/elements/drop_shadow_setting"
|
|
46
|
+
autoload :Endnote, "idml/elements/endnote"
|
|
47
|
+
autoload :EndnoteRange, "idml/elements/endnote_range"
|
|
46
48
|
autoload :EPubExportPreference, "idml/elements/pref_e_pub_export_preference"
|
|
47
49
|
autoload :EPubFixedLayoutExportPreference,
|
|
48
50
|
"idml/elements/pref_e_pub_fixed_layout_export_preference"
|
data/lib/idml/render/footnote.rb
CHANGED
|
@@ -128,10 +128,11 @@ module Idml
|
|
|
128
128
|
size: size)
|
|
129
129
|
lines = TextEngine::LineBreaker.break(glyphs: glyphs,
|
|
130
130
|
frame_width: wrap_width)
|
|
131
|
-
lines.
|
|
131
|
+
lines.each_with_index do |line, index|
|
|
132
132
|
TextEngine::Justifier.justify(
|
|
133
133
|
line: line, frame_width: wrap_width,
|
|
134
|
-
alignment: paragraph.alignment || :left
|
|
134
|
+
alignment: paragraph.alignment || :left,
|
|
135
|
+
last_line: last_line?(paragraph, run, index, lines)
|
|
135
136
|
)
|
|
136
137
|
end
|
|
137
138
|
leading = TextEngine::VerticalLayout.leading_for(
|
|
@@ -150,6 +151,13 @@ module Idml
|
|
|
150
151
|
end
|
|
151
152
|
private_class_method :layout_paragraph
|
|
152
153
|
|
|
154
|
+
# True for the final line of the footnote paragraph's final
|
|
155
|
+
# run — kept ragged under full justification.
|
|
156
|
+
def self.last_line?(paragraph, run, index, lines)
|
|
157
|
+
run.equal?(paragraph.runs.last) && index == lines.length - 1
|
|
158
|
+
end
|
|
159
|
+
private_class_method :last_line?
|
|
160
|
+
|
|
153
161
|
# Height to reserve at the frame bottom for the entries:
|
|
154
162
|
# separator gap + the measured paragraph stack.
|
|
155
163
|
def self.reserved_height(entries, font, frame, option = nil)
|
|
@@ -70,7 +70,10 @@ module Idml
|
|
|
70
70
|
# derived from `column_count` attribute or max col + 1.
|
|
71
71
|
def self.render_schema_faithful(canvas, table, box, context)
|
|
72
72
|
layout = SchemaLayout.new(table: table, box: box)
|
|
73
|
-
layout.each_cell do |cell_x, cell_y, cell_w, cell_h, cell
|
|
73
|
+
layout.each_cell do |cell_x, cell_y, cell_w, cell_h, cell,
|
|
74
|
+
col_idx, row_idx|
|
|
75
|
+
render_band_background(canvas, cell, layout, col_idx, row_idx,
|
|
76
|
+
cell_x, cell_y, cell_w, cell_h, context)
|
|
74
77
|
render_cell_background(canvas, cell, cell_x, cell_y, cell_w, cell_h,
|
|
75
78
|
context)
|
|
76
79
|
render_cell_border(canvas, cell_x, cell_y, cell_w, cell_h)
|
|
@@ -79,6 +82,27 @@ module Idml
|
|
|
79
82
|
end
|
|
80
83
|
private_class_method :render_schema_faithful
|
|
81
84
|
|
|
85
|
+
# Table-level alternating band fill behind a cell. An
|
|
86
|
+
# explicit Cell FillColor wins; Color/None bands and zero
|
|
87
|
+
# tints render nothing.
|
|
88
|
+
def self.render_band_background(canvas, cell, layout, col_idx,
|
|
89
|
+
row_idx, x, y, w, h, context)
|
|
90
|
+
return if cell_fill_color(cell, context)
|
|
91
|
+
|
|
92
|
+
name, tint = layout.band_fill(col_idx, row_idx)
|
|
93
|
+
return unless name
|
|
94
|
+
return if name == "Color/None"
|
|
95
|
+
|
|
96
|
+
color = context.color_resolver&.resolve(name)
|
|
97
|
+
return unless color
|
|
98
|
+
|
|
99
|
+
color = ColorHelper.apply_tint(color, tint)
|
|
100
|
+
canvas.fill_color(ColorHelper.to_canvas(color))
|
|
101
|
+
canvas.rectangle(x, y, w, h)
|
|
102
|
+
canvas.fill
|
|
103
|
+
end
|
|
104
|
+
private_class_method :render_band_background
|
|
105
|
+
|
|
82
106
|
def self.render_cell_background(canvas, cell, x, y, w, h, context)
|
|
83
107
|
color = cell_fill_color(cell, context)
|
|
84
108
|
return unless color
|
|
@@ -244,7 +268,7 @@ module Idml
|
|
|
244
268
|
|
|
245
269
|
yield cell_x(col_idx), cell_y(row_idx, col_span, row_span),
|
|
246
270
|
cell_w(col_idx, col_span), cell_h(row_idx, row_span),
|
|
247
|
-
cell
|
|
271
|
+
cell, col_idx, row_idx
|
|
248
272
|
end
|
|
249
273
|
end
|
|
250
274
|
end
|
|
@@ -269,6 +293,79 @@ module Idml
|
|
|
269
293
|
table.row
|
|
270
294
|
end
|
|
271
295
|
|
|
296
|
+
# Table-level alternating band fill for a cell position:
|
|
297
|
+
# [color_name, tint] or nil. Row banding by default; column
|
|
298
|
+
# banding when ColumnFillsPriority is true or rows are
|
|
299
|
+
# unconfigured.
|
|
300
|
+
def band_fill(col, row)
|
|
301
|
+
column_band = column_band_fill(col)
|
|
302
|
+
return column_band if column_band &&
|
|
303
|
+
(table.column_fills_priority || row_band_fill(row).nil?)
|
|
304
|
+
|
|
305
|
+
row_band_fill(row)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def row_band_fill(row)
|
|
309
|
+
band_pair(table.start_row_fill_color, table.start_row_fill_count,
|
|
310
|
+
table.end_row_fill_color, table.end_row_fill_count,
|
|
311
|
+
table.start_row_fill_tint, table.end_row_fill_tint,
|
|
312
|
+
row, row_count,
|
|
313
|
+
table.skip_first_alternating_fill_rows,
|
|
314
|
+
table.skip_last_alternating_fill_rows)
|
|
315
|
+
end
|
|
316
|
+
private :row_band_fill
|
|
317
|
+
|
|
318
|
+
def column_band_fill(col)
|
|
319
|
+
band_pair(table.start_column_fill_color,
|
|
320
|
+
table.start_column_fill_count,
|
|
321
|
+
table.end_column_fill_color,
|
|
322
|
+
table.end_column_fill_count,
|
|
323
|
+
table.start_column_fill_tint,
|
|
324
|
+
table.end_column_fill_tint,
|
|
325
|
+
col, col_count,
|
|
326
|
+
table.skip_first_alternating_fill_columns,
|
|
327
|
+
table.skip_last_alternating_fill_columns)
|
|
328
|
+
end
|
|
329
|
+
private :column_band_fill
|
|
330
|
+
|
|
331
|
+
# Alternating band for one axis: the first `start_count`
|
|
332
|
+
# positions take the start color, the next `end_count` the
|
|
333
|
+
# end color, repeating from after the skipped edge rows.
|
|
334
|
+
# Zero-count cycles band nothing.
|
|
335
|
+
def band_pair(start_color, start_count, end_color, end_count,
|
|
336
|
+
start_tint, end_tint, index, total,
|
|
337
|
+
skip_first, skip_last)
|
|
338
|
+
return nil unless start_color
|
|
339
|
+
return nil if suppressed?(index, total, skip_first, skip_last)
|
|
340
|
+
|
|
341
|
+
cycle = band_cycle(start_count, end_count)
|
|
342
|
+
return nil unless cycle.positive?
|
|
343
|
+
|
|
344
|
+
if in_start_band?(index, skip_first, cycle, start_count)
|
|
345
|
+
[start_color, start_tint]
|
|
346
|
+
else
|
|
347
|
+
[end_color, end_tint]
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
private :band_pair
|
|
351
|
+
|
|
352
|
+
def band_cycle(start_count, end_count)
|
|
353
|
+
(start_count || 1) + (end_count || 1)
|
|
354
|
+
end
|
|
355
|
+
private :band_cycle
|
|
356
|
+
|
|
357
|
+
def in_start_band?(index, skip_first, cycle, start_count)
|
|
358
|
+
((index - (skip_first || 0)) % cycle) < (start_count || 1)
|
|
359
|
+
end
|
|
360
|
+
private :in_start_band?
|
|
361
|
+
|
|
362
|
+
# Banding suppressed at the leading/trailing edges.
|
|
363
|
+
def suppressed?(index, total, skip_first, skip_last)
|
|
364
|
+
index < (skip_first || 0) ||
|
|
365
|
+
index >= total - (skip_last || 0)
|
|
366
|
+
end
|
|
367
|
+
private :suppressed?
|
|
368
|
+
|
|
272
369
|
def cells
|
|
273
370
|
table.cell
|
|
274
371
|
end
|
|
@@ -511,7 +511,8 @@ module Idml
|
|
|
511
511
|
canvas, run, paragraph, context, layout_frame, font,
|
|
512
512
|
run_wrap, cursor_y, space_before,
|
|
513
513
|
para_attrs[:first_line_indent], para_attrs[:left_indent],
|
|
514
|
-
char_cursor, bottom_limit
|
|
514
|
+
char_cursor, bottom_limit,
|
|
515
|
+
paragraph_last: run.equal?(runs.last)
|
|
515
516
|
)
|
|
516
517
|
char_cursor += positioned.length
|
|
517
518
|
cursor_y = next_y
|
|
@@ -712,7 +713,7 @@ module Idml
|
|
|
712
713
|
def self.layout_run(canvas, run, paragraph, context, layout_frame,
|
|
713
714
|
font, wrap_width, cursor_y, space_before,
|
|
714
715
|
first_line_indent, left_indent,
|
|
715
|
-
char_cursor, bottom_limit)
|
|
716
|
+
char_cursor, bottom_limit, paragraph_last: false)
|
|
716
717
|
size = run.point_size || DEFAULT_SIZE
|
|
717
718
|
glyphs = TextEngine::Shaper.shape(
|
|
718
719
|
text: run.text, font: font, size: size,
|
|
@@ -720,12 +721,7 @@ module Idml
|
|
|
720
721
|
lines = TextEngine::LineBreaker.break(
|
|
721
722
|
glyphs: glyphs, frame_width: wrap_width,
|
|
722
723
|
)
|
|
723
|
-
lines
|
|
724
|
-
TextEngine::Justifier.justify(
|
|
725
|
-
line: line, frame_width: wrap_width,
|
|
726
|
-
alignment: paragraph.alignment || :left
|
|
727
|
-
)
|
|
728
|
-
end
|
|
724
|
+
justify_lines(lines, paragraph, wrap_width, paragraph_last)
|
|
729
725
|
leading = leading_for(paragraph, size)
|
|
730
726
|
|
|
731
727
|
positioned, next_y = TextEngine::VerticalLayout.layout_block(
|
|
@@ -745,6 +741,21 @@ module Idml
|
|
|
745
741
|
end
|
|
746
742
|
private_class_method :layout_run
|
|
747
743
|
|
|
744
|
+
# Justifies the run's lines; only the final line of the
|
|
745
|
+
# paragraph's final run stays ragged under full
|
|
746
|
+
# justification.
|
|
747
|
+
def self.justify_lines(lines, paragraph, wrap_width,
|
|
748
|
+
paragraph_last)
|
|
749
|
+
lines.each_with_index do |line, index|
|
|
750
|
+
TextEngine::Justifier.justify(
|
|
751
|
+
line: line, frame_width: wrap_width,
|
|
752
|
+
alignment: paragraph.alignment || :left,
|
|
753
|
+
last_line: paragraph_last && index == lines.length - 1
|
|
754
|
+
)
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
private_class_method :justify_lines
|
|
758
|
+
|
|
748
759
|
# Emits the run's positioned lines (clipped at the bottom
|
|
749
760
|
# limit), recording positions and annotating the first line
|
|
750
761
|
# with the run's ruby when present.
|
|
@@ -4,19 +4,22 @@ module Idml
|
|
|
4
4
|
module TextEngine
|
|
5
5
|
# Distributes slack space within a line per the paragraph's
|
|
6
6
|
# alignment. Adjusts x_offset and optionally scales inter-word
|
|
7
|
-
# spaces for justified text.
|
|
7
|
+
# spaces for justified text. `last_line:` (the paragraph's final
|
|
8
|
+
# line) keeps ragged right under :justified, as InDesign does.
|
|
8
9
|
class Justifier
|
|
9
|
-
def self.justify(line:, frame_width:, alignment: :left
|
|
10
|
-
|
|
10
|
+
def self.justify(line:, frame_width:, alignment: :left,
|
|
11
|
+
last_line: false)
|
|
12
|
+
new(frame_width, alignment, last_line).justify(line)
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def initialize(frame_width, alignment)
|
|
15
|
+
def initialize(frame_width, alignment, last_line)
|
|
14
16
|
@frame_width = frame_width
|
|
15
17
|
@alignment = alignment
|
|
18
|
+
@last_line = last_line
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
def justify(line)
|
|
19
|
-
case
|
|
22
|
+
case effective_alignment
|
|
20
23
|
when :left, :start then line.x_offset = 0
|
|
21
24
|
when :center, :middle
|
|
22
25
|
line.x_offset = (@frame_width - line.width) / 2
|
|
@@ -29,6 +32,14 @@ module Idml
|
|
|
29
32
|
|
|
30
33
|
private
|
|
31
34
|
|
|
35
|
+
# The paragraph's last line stays ragged under full
|
|
36
|
+
# justification.
|
|
37
|
+
def effective_alignment
|
|
38
|
+
return :left if @alignment == :justified && @last_line
|
|
39
|
+
|
|
40
|
+
@alignment
|
|
41
|
+
end
|
|
42
|
+
|
|
32
43
|
def justify_line(line)
|
|
33
44
|
spaces = line.glyphs.count(&:is_space)
|
|
34
45
|
slack = @frame_width - line.width
|
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.9.
|
|
4
|
+
version: 0.9.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
@@ -173,6 +173,9 @@ files:
|
|
|
173
173
|
- TODO.pdf/114-text-wrap-around-shapes.md
|
|
174
174
|
- TODO.pdf/115-bullet-numbered-lists.md
|
|
175
175
|
- TODO.pdf/116-applied-style-resolution.md
|
|
176
|
+
- TODO.pdf/116-justification-last-line.md
|
|
177
|
+
- TODO.pdf/117-endnote-support.md
|
|
178
|
+
- TODO.pdf/118-table-band-fills.md
|
|
176
179
|
- TODO.pdf/12-idml-to-pdf-pipeline.md
|
|
177
180
|
- TODO.pdf/13-cjk-text-layout.md
|
|
178
181
|
- TODO.pdf/14-page-item-element-models.md
|
|
@@ -291,6 +294,8 @@ files:
|
|
|
291
294
|
- lib/idml/elements/document_object.rb
|
|
292
295
|
- lib/idml/elements/dotted_stroke_style.rb
|
|
293
296
|
- lib/idml/elements/drop_shadow_setting.rb
|
|
297
|
+
- lib/idml/elements/endnote.rb
|
|
298
|
+
- lib/idml/elements/endnote_range.rb
|
|
294
299
|
- lib/idml/elements/feather_setting.rb
|
|
295
300
|
- lib/idml/elements/fill_transparency_setting.rb
|
|
296
301
|
- lib/idml/elements/flex_layout_attribute_option.rb
|