Files
BadNote/lib/editor/pdf/pdf_document_source.dart
Akiba So 6b7cc14836
Some checks failed
CI / Windows build (push) Has been cancelled
feat(p0.5): PageDocumentSource seam + fit-to-width metrics glue (step 10)
Connects the two pure P0.5 pieces: a minimal PageDocumentSource abstraction
(pageCount + pageSize, a pdfrx PdfDocument in production) and
pageStackMetricsForWidth() which fits every page to a single column width
(continuous-single) — height = columnWidth × aspect — feeding
PageStackMetrics.visibleRange. Defensive against non-positive page width.

This makes the windowing math consumable + unit-testable against a fake source
(no pdfium/GPU); the production pdfrx adapter is the thin device-side wrapper
added with the page-mounting widget.

flutter analyze lib/editor clean; 120/120 tests (+5: fit-to-width, gap, empty,
zero-width guard, windowing composition).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 03:10:05 +08:00

46 lines
1.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// lib/editor/pdf/pdf_document_source.dart
//
// A minimal abstraction over a paginated document (a pdfrx PdfDocument in
// production) consumed by the layout + render layer. Keeping the layout math
// behind this seam lets continuous-single windowing (layout/page_viewport.dart)
// and tiling be unit-tested against a fake source — no pdfium, no GPU, no real
// PDF (the production pdfrx adapter is a thin device-side wrapper added with the
// viewport widget / page_tile renderer, which are device-gated).
import 'dart:ui' show Size;
import '../layout/page_viewport.dart';
/// Read-only page geometry for a paginated document.
abstract class PageDocumentSource {
/// Number of pages (>= 0).
int get pageCount;
/// Intrinsic size of page [index] in PDF points (width/height > 0).
Size pageSize(int index);
}
/// Builds continuous-single stacking metrics by fitting every page to a single
/// [columnWidth] (fit-to-width, the continuous-single mode): each page's
/// laid-out height is `columnWidth × (pageHeight / pageWidth)`, preserving its
/// aspect ratio. [gap] is inserted between pages (content units).
///
/// Pages reporting a non-positive width are treated as zero-height (defensive;
/// real pages always have a positive width) so a malformed page can't throw.
///
/// Returns the metrics needed by [PageStackMetrics.visibleRange]; pair this with
/// the device-gated page-mounting widget.
PageStackMetrics pageStackMetricsForWidth(
PageDocumentSource source,
double columnWidth, {
double gap = 0.0,
}) {
assert(columnWidth >= 0);
final heights = List<double>.generate(source.pageCount, (i) {
final size = source.pageSize(i);
if (size.width <= 0) return 0.0;
return columnWidth * (size.height / size.width);
});
return PageStackMetrics(pageHeights: heights, gap: gap);
}