• Direction graph: gap 2, char gap 0.6, alignment 1.5, font ratio 1.5, aspect tolerance 1; connected-component majority assigns horizontal/vertical.
• Merge graph: aspect tolerance 1.3, font ratio 2, char gaps 1/3; rotated candidates require angle ≤15° and relative font delta ≤0.25.
• For 3+ lines, build complete weighted graph → Kruskal MST → keep if max edge ≤ mean + 2σ or ≤1.5× font; else cut largest edge and recurse.
• Assemble blocks top-to-bottom or right-to-left; CJK joins without spaces; minimum line font wins; angle <3° snaps to zero; fit minimum-area rectangle.
• BubbleLayoutService: single-bubble expansion with font fit gate; clean single-axis X/Y partition for connected lobes (gap ≥6px); diagonal/complex lobes fall back to Disabled.
• Font fitter: 5% inset, line height 1.2, search 6 px…max; Pass 1 clean binary fit; Pass 2 tall-box geometric cap when H/W ≥2.0.
• Pass 3 scans down with six-stage hyphenation for words ≥7 chars when H/W ≥1.5; Pass 4 runs fallback binary search to the 6 px floor.