StepAnsicht: fix font size and row spacing to match original
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 43s
CI / test-go-edu-search (push) Successful in 40s
CI / test-nodejs-website (push) Has been cancelled
CI / test-python-agent-core (push) Has been cancelled
CI / test-python-klausur (push) Has been cancelled
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 43s
CI / test-go-edu-search (push) Successful in 40s
CI / test-nodejs-website (push) Has been cancelled
CI / test-python-agent-core (push) Has been cancelled
CI / test-python-klausur (push) Has been cancelled
- Font: use font_size_suggestion_px * scale directly (removed 0.85 factor) - Row height: calculate from row-to-row spacing (y_min of next row minus y_min of current row) instead of text height (y_max - y_min). This produces correct line spacing matching the original layout. - Multi-line cells: height multiplied by line count Content zone should now span from ~250 to ~2050 matching the original. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -71,7 +71,8 @@ export function StepAnsicht({ sessionId, onNext }: StepAnsichtProps) {
|
|||||||
const panelHeight = imgH * scale
|
const panelHeight = imgH * scale
|
||||||
|
|
||||||
const baseFontPx = (grid as any).layout_metrics?.font_size_suggestion_px || 14
|
const baseFontPx = (grid as any).layout_metrics?.font_size_suggestion_px || 14
|
||||||
const scaledFont = Math.max(7, baseFontPx * scale * 0.85)
|
const avgRowH = (grid as any).layout_metrics?.avg_row_height_px || 31
|
||||||
|
const scaledFont = Math.max(7, baseFontPx * scale)
|
||||||
|
|
||||||
// Collect all word boxes for OCR overlay
|
// Collect all word boxes for OCR overlay
|
||||||
const allWordBoxes = grid.zones.flatMap((z) =>
|
const allWordBoxes = grid.zones.flatMap((z) =>
|
||||||
@@ -161,7 +162,7 @@ export function StepAnsicht({ sessionId, onNext }: StepAnsichtProps) {
|
|||||||
|
|
||||||
{/* Rendered zones */}
|
{/* Rendered zones */}
|
||||||
{grid.zones.map((zone) => (
|
{grid.zones.map((zone) => (
|
||||||
<ZoneRenderer key={zone.zone_index} zone={zone} scale={scale} fontSize={scaledFont} />
|
<ZoneRenderer key={zone.zone_index} zone={zone} scale={scale} fontSize={scaledFont} avgRowH={avgRowH} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* Coordinate grid */}
|
{/* Coordinate grid */}
|
||||||
@@ -208,8 +209,8 @@ function CoordinateGrid({ imgW, imgH, scale, spacing }: {
|
|||||||
// Zone renderer (reconstruction side)
|
// Zone renderer (reconstruction side)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function ZoneRenderer({ zone, scale, fontSize }: {
|
function ZoneRenderer({ zone, scale, fontSize, avgRowH }: {
|
||||||
zone: GridZone; scale: number; fontSize: number
|
zone: GridZone; scale: number; fontSize: number; avgRowH: number
|
||||||
}) {
|
}) {
|
||||||
const isBox = zone.zone_type === 'box'
|
const isBox = zone.zone_type === 'box'
|
||||||
const boxColor = (zone as any).box_bg_hex || '#6b7280'
|
const boxColor = (zone as any).box_bg_hex || '#6b7280'
|
||||||
@@ -253,10 +254,22 @@ function ZoneRenderer({ zone, scale, fontSize }: {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: scaledColWidths.map((w) => `${w.toFixed(1)}px`).join(' ') }}>
|
<div style={{ display: 'grid', gridTemplateColumns: scaledColWidths.map((w) => `${w.toFixed(1)}px`).join(' ') }}>
|
||||||
{zone.rows.map((row) => {
|
{zone.rows.map((row, rowIdx) => {
|
||||||
const isSpanning = zone.cells.some((c) => c.row_index === row.index && c.col_type === 'spanning_header')
|
const isSpanning = zone.cells.some((c) => c.row_index === row.index && c.col_type === 'spanning_header')
|
||||||
const measuredH = (row.y_max_px ?? 0) - (row.y_min_px ?? 0)
|
|
||||||
const rowH = Math.max(fontSize * 1.3, measuredH * scale)
|
// Row height = distance to next row's start (not text height)
|
||||||
|
// This produces correct line spacing matching the original
|
||||||
|
const nextRow = rowIdx + 1 < zone.rows.length ? zone.rows[rowIdx + 1] : null
|
||||||
|
const rowStartY = row.y_min_px ?? row.y_min ?? 0
|
||||||
|
const nextStartY = nextRow ? (nextRow.y_min_px ?? nextRow.y_min ?? 0) : rowStartY + avgRowH
|
||||||
|
const rowSpacing = nextStartY - rowStartY
|
||||||
|
const rowH = Math.max(fontSize * 1.3, rowSpacing * scale)
|
||||||
|
|
||||||
|
// Multi-line cells need more height
|
||||||
|
const maxLines = Math.max(1, ...zone.cells
|
||||||
|
.filter((c) => c.row_index === row.index)
|
||||||
|
.map((c) => (c.text ?? '').split('\n').length))
|
||||||
|
const effectiveRowH = rowH * Math.max(1, maxLines)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={row.index} style={{ display: 'contents' }}>
|
<div key={row.index} style={{ display: 'contents' }}>
|
||||||
@@ -273,7 +286,7 @@ function ZoneRenderer({ zone, scale, fontSize }: {
|
|||||||
className={`px-0.5 overflow-hidden ${row.is_header ? 'font-bold' : ''}`}
|
className={`px-0.5 overflow-hidden ${row.is_header ? 'font-bold' : ''}`}
|
||||||
style={{
|
style={{
|
||||||
gridColumn: `${cell.col_index + 1} / ${cell.col_index + 1 + colspan}`,
|
gridColumn: `${cell.col_index + 1} / ${cell.col_index + 1 + colspan}`,
|
||||||
minHeight: `${rowH}px`,
|
minHeight: `${effectiveRowH}px`,
|
||||||
color: color || undefined,
|
color: color || undefined,
|
||||||
whiteSpace: 'pre-wrap',
|
whiteSpace: 'pre-wrap',
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user