Skip to content

Revert per-line layering contract to per-box z-index stacking - #244

Closed
Gnathonic wants to merge 16 commits into
developfrom
feat/original-mode-line-coords
Closed

Revert per-line layering contract to per-box z-index stacking#244
Gnathonic wants to merge 16 commits into
developfrom
feat/original-mode-line-coords

Conversation

@Gnathonic

Copy link
Copy Markdown
Owner

Follow-up to #243: restores z-index:11 box stacking and drops the positionedLine z-index lift.

🤖 Generated with Claude Code

Gnathonic and others added 16 commits July 4, 2026 23:23
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mokuro's block font_size is the detected line-quad width (furigana
included), median 1.2x the true character size, so block-level original
rendering overflows. Per-line quads are accurate: place each line at its
quad and fit the font size to quad_length / text_advance, capped by quad
width. Falls back to the legacy path when lines_coords is missing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Quads are often wider than the glyph column (ruby, mask slack, empty
margin) with the base glyphs near the middle; left-edge anchoring shoved
wide-quad columns into their neighbors (Dr Stone 01 p27 本物から).
Center each line on the quad's cross axis instead.

The detector also emits ~19 duplicate blocks per 1000 pages: the same
balloon as a properly segmented block plus a single whole-box synthetic
line with a huge font_size (Dr Stone 01 p29). Dedupe at render time by
identical joined text + box IoU > 0.5, keeping the better-segmented
block; applies to all font modes and already-imported volumes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A quad much wider than the block's typical line size whose text only
fits far smaller is multiple print columns captured as one OCR line —
usually base text plus its furigana reading (Dr Stone 01 p32
空は私ならだいじょうぶ: 112px quad squeezed to 14.7px). Such lines now
wrap inside their full quad bbox at (near) the block's median line size.
Clean lines keep their own fitted size: print mixes sizes within a
balloon (emphasis words like 大丈夫), so uniformity is not forced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Print keeps one size per balloon; per-quad fitted sizes vary only via
quad slack, and mixed sizes look sloppy (user feedback: Dr Stone p32
大丈夫 is 1:1 with the base line, its tall quad is just loose). All
lines now render at the block's median clean-line size, tolerating
1.15x length / 1.2x cross quad slack. Escapes: deliberately-small lines
(standalone furigana) keep their own size, and wrapped merged-column
lines pull the whole block down with them so sizes stay uniform.
wrapFitSize now searches column counts exactly instead of iterating to
a suboptimal fixpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixed 1.6x-reference quad-width wrap gate missed Dr Stone 01 p53
必要なことはう by 0.7px, leaving a merged line at a tiny 19px when two
columns at 31.5px fit. Gate on what wrapFitSize actually achieves
(>= 1.25x the single-line size) instead. And when >= 2 clean lines
agree within 1.25x, their median fixes the block size — a wrapped
line's lower fit no longer drags well-attested blocks down (it still
does for 0-1 clean-line blocks, which is what makes p32 land on the
true size).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…al size

A block whose only line is one quad covering the whole balloon (Dr
Stone 01 p87: 9 chars in 356x390) could never wrap: the reference size
derives from that same line, so the shrink gate never fired, leaving a
small single column in a huge box. When a block has no clean lines,
suspect lines now wrap at their geometry-optimal size (~sqrt(main x
cross / advance)) — p87 renders 3 columns at ~119px matching the print.
Still gated on the 1.25x benefit so genuine one-liners in loose quads
stay single. Hallucinated lines now wrap into dense contained columns
instead of rendering sub-pixel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Killing Bites 01 p42: 「百獣王」 with its katakana gloss split into two
small ruby lines around it — a plain per-line median is ruby-dominated
and dragged the 76px base text down to 31px. Lines now vote for the
block reference size proportionally to their quad ink area (the base
line holds 80% of the block's ink), so ruby fragments register as small
outliers and keep their own sizes while the base renders at its true
size.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The reconstruction supersedes the old measure-and-shrink auto mode and
is not a faithful raster either, so auto (the app default) is its
honest home. Blocks without lines_coords fall back to the legacy
hover-fit auto path; original mode reverts to raw font_size rendering.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Saki the Succubus 02 p129: the detector re-captures the same ink region
as several overlapping lines — a column alone AND a bigger quad
spanning it plus its neighbors (あれは inside あれはキスではないですよ),
or nested hallucination blobs — which rendered stacked text. When one
line bbox covers >= 70% of a smaller one: if the smaller's text is
contained in the bigger's, hide the smaller (the bigger wraps the full
region, no text lost); otherwise hide the enclosing blob and keep the
precise small captures. Hidden lines don't vote on the block size and
don't render.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hiding the enclosing blob of a hallucination cluster (Saki 02 p129)
filtered out most of the OCR text — unreadable in a new way. The user
requirement is that OCR text stays readable even when it is wrong:
diverged overlapping captures now merge into a cluster whose union bbox
is partitioned into reading-order bands weighted by text length; each
line wraps inside its own band. All text renders, ordered, nothing
stacks. Text-subsumed duplicates (あれは) still collapse losslessly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Killing Bites 01 p211: the detector assigned the middle column of one
balloon to the neighboring block (its quad slots exactly between the
victim block's columns). Per-line placement renders it at the correct
print position, but the overlapping block's whole-box white background
painted over it, hiding the text. In per-line mode the opaque backing
now lives on each line span — it still masks the printed glyphs under
the rendered text, and overlapping boxes can no longer blank out each
other's lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per-line white strips only mask print they cover — on stylized, angled
or misaligned text (Saki 02 p129) the original ink bleeds around every
strip. Restore the whole-box white panel and fix the actual p211
problem, which was paint order: text boxes no longer create stacking
contexts (z-index removed; tree order still stacks smaller boxes over
bigger), and positioned line spans get z-index 1, lifting every block's
text above every block's panel. Overlapping blocks mask robustly and
can no longer blank out each other's lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restores z-index:11 on the box and its panel and drops the
positionedLine z-index lift from f6b2aef.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mokuro-reader Building Building Preview, Comment Jul 5, 2026 5:52pm

Request Review

@Gnathonic Gnathonic closed this Jul 5, 2026
adrian-tompkins pushed a commit to adrian-tompkins/mokuro-reader that referenced this pull request Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant