fix(exam): match app's per-page ceil so shapes don't drift up on long papers
Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled

The app sets canvas.height = Math.ceil(viewport.height) per page and stacks pages by those
heights; the backend page_top used the raw float, so it fell ~1px/page short, compounding to a
visible upward shape shift on later pages (~36px over 40 pages). Ceil rendered_h to match exactly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
CC Worker 2026-06-08 20:11:28 +00:00
parent 5434a5bf21
commit 6c73174829

View File

@ -13,6 +13,7 @@ join keys (spec §2).
from __future__ import annotations from __future__ import annotations
import json import json
import math
import os import os
import tempfile import tempfile
import time import time
@ -369,7 +370,10 @@ def _pdf_page_geometry(pdf_bytes: bytes) -> List[Dict[str, float]]:
# pages by those heights. Previously rendered_w/h were left in PDF points (~595x842), # pages by those heights. Previously rendered_w/h were left in PDF points (~595x842),
# so every shape landed shrunk (~0.76x) and shifted up-left on the 780-wide canvas. # so every shape landed shrunk (~0.76x) and shifted up-left on the 780-wide canvas.
rendered_w = CANVAS_PAGE_WIDTH rendered_w = CANVAS_PAGE_WIDTH
rendered_h = CANVAS_PAGE_WIDTH * page_pt_h / page_pt_w # Mirror the app's canvas.height = Math.ceil(viewport.height) EXACTLY (pdfLoader.ts),
# so page_top accumulates identically. Using the raw float drifts ~1px/page, compounding
# to a visible upward shift on later pages of long papers (~36px over 40 pages).
rendered_h = float(math.ceil(CANVAS_PAGE_WIDTH * page_pt_h / page_pt_w))
pages.append({ pages.append({
"media_x0": float(media.x0), "media_x0": float(media.x0),
"crop_x0": float(crop.x0), "crop_x0": float(crop.x0),
@ -397,7 +401,7 @@ def _pdf_page_geometry(pdf_bytes: bytes) -> List[Dict[str, float]]:
def _page_geom(pages: List[Dict[str, float]], page_number: int) -> Dict[str, float]: def _page_geom(pages: List[Dict[str, float]], page_number: int) -> Dict[str, float]:
if 1 <= page_number <= len(pages): if 1 <= page_number <= len(pages):
return pages[page_number - 1] return pages[page_number - 1]
_fallback_h = CANVAS_PAGE_WIDTH * 842.0 / 595.0 _fallback_h = float(math.ceil(CANVAS_PAGE_WIDTH * 842.0 / 595.0))
return { return {
"media_x0": 0.0, "crop_x0": 0.0, "crop_y0": 0.0, "media_x0": 0.0, "crop_x0": 0.0, "crop_y0": 0.0,
"page_pt_w": 595.0, "page_pt_h": 842.0, "page_pt_w": 595.0, "page_pt_h": 842.0,