idml 0.9.7 → 0.9.8

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: 0d49d9954838f3326eab4e65e2915eab9cd18a526ce7c4dd58669e6dacb8910e
4
- data.tar.gz: 56713c3d26980c24c6baf8d080543cd2471aef5dea4ca83c33be82f73fe2e83e
3
+ metadata.gz: 29f97721ebdd63304b8c879eaa45764906dfa40b85363688aa9d860ccdd6f62c
4
+ data.tar.gz: 439a3e3454be081957617ce5107ae735a47d56c4dc206104d3e483c5a20db669
5
5
  SHA512:
6
- metadata.gz: d52298b420e04ae5c4b8292e01d951eb23d03d4e01357f463111477e842aea9dd89f6e162a88ad05dd50fa8b721faf6522f891eb66e3405dd6207769f7a9bfe8
7
- data.tar.gz: 1d7f89c274a8aac75868064826567901fbc0503ead631953fc7b24eaa282e0f1d8870d2e33f1dc6e81c834b4e3c00fc4b2b465b1a12cc349484b0e653628e63f
6
+ metadata.gz: 0c669bcf817d1e2b8ab74c116e3a0e472b8ca5529fdfeba4f0adb85d7f1ddb78da5d422c63907cbe68f4a7c381ce5862d17b674063070bce64e9664584159b97
7
+ data.tar.gz: b427dc2a77703a71074fc541eb8eea36485dc78607dea9faa8f13d3ca69c70e013a749374ef8abca81057bdf5e7563f6717bea30e45ad967a5836ead3e325d6a
@@ -0,0 +1,22 @@
1
+ # TODO PDF 125: CJK/Latin automatic script spacing (mojikumi subset)
2
+
3
+ ## Status: COMPLETE — implemented 2026-08-20
4
+
5
+ ## What was done
6
+
7
+ - `TextEngine::CjkLayout.apply_script_spacing` widens the leading
8
+ glyph by an eighth em at every CJK ↔ ASCII alphanumeric boundary
9
+ — InDesign's default inter-script auto spacing (a mojikumi
10
+ behavior).
11
+ - Wired inside `TextEngine::Shaper#shape`, so every shaping path
12
+ (horizontal frame text, footnotes, ruby, vertical columns)
13
+ applies it uniformly — one integration point, no per-caller
14
+ changes.
15
+ - Punctuation neighbors are ignored (only letters/digits form
16
+ boundaries).
17
+
18
+ ## Remaining from TODO 13
19
+
20
+ Class-based mojikumi (per-pair punctuation compression tables,
21
+ line-end punctuation hanging beyond half-em) remains a documented
22
+ stretch goal.
@@ -0,0 +1,22 @@
1
+ # TODO PDF 126: Package#part memoization
2
+
3
+ ## Status: COMPLETE — implemented 2026-08-20
4
+
5
+ ## Problem
6
+
7
+ `Package#part(name)` re-read and re-parsed the zip entry on every
8
+ call. Rendering resolves `story_by_id` per frame plus preferences
9
+ (Footnote.option), styles, and graphics repeatedly — each lookup
10
+ decompressed and re-parsed the same XML.
11
+
12
+ ## What was done
13
+
14
+ Parsed parts are memoized in a per-`Package` hash
15
+ (`parse_part` remains the single read+parse path; `each_part` /
16
+ `read_part` stay uncached raw reads for round-trip byte fidelity).
17
+
18
+ ## Acceptance criteria
19
+
20
+ - [x] Repeated `part(name)` calls return the same object.
21
+ - [x] Different parts do not share objects.
22
+ - [x] Whole-package round-trip specs unchanged (raw reads).
@@ -20,9 +20,11 @@ kinsoku shori, ruby annotations).
20
20
  frame width (previously they overflowed as one long line) — this
21
21
  also fixes horizontal CJK wrapping.
22
22
 
23
- Remaining stretch goals: tate-chu-yoko, mojikumi, Latin rotation in
24
- vertical mode, vertical ruby placement. See
25
- `lib/idml/text_engine/cjk_layout.rb` and
23
+ 2026-08-20 completions: tate-chu-yoko (TODO 124), Latin rotation
24
+ and vertical ruby (TODO 122), CJK/Latin automatic script spacing
25
+ (TODO 125, a mojikumi subset wired into Shaper). The remaining
26
+ stretch goal is full class-based mojikumi (per-pair punctuation
27
+ compression tables). See `lib/idml/text_engine/cjk_layout.rb` and
26
28
  `lib/idml/text_engine/vertical_text_layout.rb`.
27
29
 
28
30
  ## Progress 2026-08-17
data/lib/idml/package.rb CHANGED
@@ -134,13 +134,23 @@ module Idml
134
134
  # Returns a typed part instance for `name` when a class is registered
135
135
  # for that file pattern (e.g. Designmap for designmap.xml). Falls
136
136
  # back to Parts::Raw — a lossless XML wrapper — for unmodeled parts.
137
+ # Parsed parts are memoized: rendering resolves stories,
138
+ # preferences, and styles repeatedly (per frame), and each
139
+ # un-memoized read would re-decompress and re-parse the zip
140
+ # entry.
137
141
  def part(name)
142
+ @part_cache ||= {}
143
+ @part_cache[name] ||= parse_part(name)
144
+ end
145
+
146
+ def parse_part(name)
138
147
  xml = read_part(name)
139
148
  klass = Idml::Parts.class_for(name)
140
149
  return Idml::Parts::Raw.from_xml(xml) unless klass
141
150
 
142
151
  klass.from_xml(xml)
143
152
  end
153
+ private :parse_part
144
154
 
145
155
  def each_part
146
156
  return enum_for(:each_part) unless block_given?
@@ -7,6 +7,38 @@ module Idml
7
7
  module CjkLayout
8
8
  module_function
9
9
 
10
+ # Mojikumi subset: automatic inter-script spacing — an eighth
11
+ # em is inserted between adjacent CJK and ASCII alphanumeric
12
+ # glyphs (widenning the leading glyph of each pair), matching
13
+ # InDesign's default CJK/Latin auto spacing.
14
+ SCRIPT_SPACING_EM = 0.125
15
+
16
+ def apply_script_spacing(glyphs, size)
17
+ spacing = size * SCRIPT_SPACING_EM
18
+ (0...(glyphs.length - 1)).each do |index|
19
+ leading = glyphs[index]
20
+ following = glyphs[index + 1]
21
+ next unless script_boundary?(leading.codepoint,
22
+ following.codepoint)
23
+
24
+ leading.width += spacing
25
+ end
26
+ glyphs
27
+ end
28
+
29
+ # True when exactly one of the pair is CJK and the other is
30
+ # an ASCII letter or digit.
31
+ def script_boundary?(left, right)
32
+ (cjk?(left) && ascii_alnum?(right)) ||
33
+ (ascii_alnum?(left) && cjk?(right))
34
+ end
35
+
36
+ def ascii_alnum?(codepoint)
37
+ (0x30..0x39).cover?(codepoint) ||
38
+ (0x41..0x5A).cover?(codepoint) ||
39
+ (0x61..0x7A).cover?(codepoint)
40
+ end
41
+
10
42
  CJK_RANGES = [
11
43
  0x3000..0x303F, # CJK Symbols and Punctuation
12
44
  0x3040..0x309F, # Hiragana
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.9.7"
4
+ VERSION = "0.9.8"
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.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
@@ -183,6 +183,8 @@ files:
183
183
  - TODO.pdf/122-vertical-latin-ruby.md
184
184
  - TODO.pdf/123-keep-options.md
185
185
  - TODO.pdf/124-tatechuyoko-vertical.md
186
+ - TODO.pdf/125-script-spacing.md
187
+ - TODO.pdf/126-part-cache.md
186
188
  - TODO.pdf/13-cjk-text-layout.md
187
189
  - TODO.pdf/14-page-item-element-models.md
188
190
  - TODO.pdf/15-wire-spread-children.md