New <foliate-webtoon> custom element: every page stacked in one
scrolling column (max-width 900px centered on wide screens), the
standard long-strip manga reading mode.
- Pages lazy-load through an IntersectionObserver with a 150% root
margin so they're ready before scrolling into view; placeholders
carry an estimated min-height until the image loads, then the real
aspect-ratio — set on the placeholder element — so geometry stays
stable across unloads and the scrollbar never jumps.
- Pages more than 12 positions from the reading point are unloaded
(image removed, section blob URL revoked) to bound memory on long
webtoons; they simply reload if the user scrolls back.
- Relocate events ({reason:'scroll', index, fraction, size:1}) fire on
rAF-throttled scroll with the viewport-center page as index and the
visible position within it as fraction — compatible with view.js's
SectionProgress enrichment, so progress saving/restoring, the
slider, and the back-stack all work unchanged.
- Renderer contract mirrors fixed-layout: goTo(await {index}) scrolls
the page into view; next/prev page by ~one screen (view.init()'s
fresh-start probe is a no-op that reports location); goLeft/goRight
map to prev/next (vertical flow is direction-independent).
No zoom/magnifier APIs — the host already gates those on the flow.
- Page images honor --fx-filter from the host for the new
brightness/contrast/invert controls.
view.js picks the renderer when book.format === 'comic' (now tagged
by makeComicBook) and options.comic.flow === 'webtoon'.
Adds a parallel annotation pipeline for PDF/comic pages (the CFI
overlayer pipeline only exists for the reflowable paginator):
- addRectAnnotation({key, index, rects, color}) /
removeRectAnnotation(key): rects are page-fraction [x,y,w,h]
quads, stored per key and rendered into a full-bleed SVG injected
into the page iframe. The SVG uses viewBox 0 0 100 100 with
preserveAspectRatio none, so fraction rects stay aligned through
iframe CSS-zoom (comics), the host transform-based pan/zoom, and
PDF hi-res re-renders (pdf.js rebuilds canvas/textLayer but not
body children) — no re-anchoring hooks needed anywhere.
- Frames carry their section index; annotations re-render into each
freshly created iframe (#showSpread destroys and recreates frames
on every spread change).
- Clicks are hit-tested against the fraction rects (in iframe
coordinate space, denominator = img or documentElement bounding
rect so PDF's devicePixelRatio transform cancels) and emit
show-rect-annotation with host-space popover coordinates. Skipped
while a text selection is active so drag-selecting text doesn't
pop the editor.
- Comic page img is now display:block so the document box equals
the image box (no inline-baseline gap inflating denominators).
- Single finger: pan while zoomed; horizontal swipe pages at fit
(direction mapped through next()/prev() so RTL manga reads
correctly); drag on PDF text still defers to selection via the
existing smart-detection (realTarget).
- Two fingers: pinch-zoom around the midpoint (through the shared
zoom machinery, so PDF re-render scheduling works) plus
midpoint-pan; lifts back to single-finger pan when one lifts.
- Double-tap: zoom 2.5x at the point / reset to fit.
- Touch events forwarded from page iframes with converted
coordinates; preventDefault only when the engine actually consumes
the gesture so native selection/taps stay intact.
- touch-action: none on :host and in comic/pdf page documents so the
browser does not fight the gesture engine inside iframes.
Ensures browsers use highest-quality interpolation when scaling
raster comic book images during zoom. No effect on browsers that
don't support this value (they fall back to default bilinear).