exportPagePng function
Future<Uint8List>
exportPagePng({
- required DraftDocument document,
- required PageComponent page,
- ExportDpi dpi = ExportDpi.d150,
- Set<
Handle> omitOwners = const {}, - List<
PageUnderlayFill> underlay = const [],
The page of document as a PNG at dpi (spec 13 D5).
- The image is
round(effW / 25.4 · dpi)×round(effH / 25.4 · dpi)pixels; the drawing goes through the page camera atu = dpi / 25.4, unrounded, so the last column or row is a part pixel at most. - An opaque white ground is filled first; the resolver's foreground is black and level of detail is off, as for exportPagePdf.
- The drawing goes through a CanvasDrawSink, whose paths are
anti-aliased, with a FlutterTextMeasurer of the export's own for its
paragraphs, cleared before this returns. The painter lays every text
box out with
document.textMeasurer, as on the screen. - A leaf whose direct owner is in
omitOwnersis not drawn (spec D6). underlayis drawn after the ground and before the document (plan colours spec PC-7); empty, the bytes are today's.- The PNG carries exactly one
pHYschunk, right afterIHDR: pixels per metreround(dpi / 0.0254)on both axes, unit metre.
The export reads document and writes nothing to it: its codec bytes,
its stateId and its dispatcher's mutation hooks are as they were (see
_withExportIndex), on a throw as well. Only the paint runs under the
export's index; toImage and the encoding run after it is gone.
Implementation
Future<Uint8List> exportPagePng({
required DraftDocument document,
required PageComponent page,
ExportDpi dpi = ExportDpi.d150,
Set<Handle> omitOwners = const {},
List<PageUnderlayFill> underlay = const [],
}) async {
final dotsPerInch = dpi.value;
final camera = pageCamera(page, dotsPerInch / 25.4);
final width = (page.effectiveWidthMm / 25.4 * dotsPerInch).round();
final height = (page.effectiveHeightMm / 25.4 * dotsPerInch).round();
final measurer = FlutterTextMeasurer();
ui.Picture? picture;
ui.Image? image;
try {
final recorder = ui.PictureRecorder();
try {
final canvas = ui.Canvas(recorder)
..drawPaint(ui.Paint()..color = const ui.Color(0xFFFFFFFF));
_withExportIndex(document, (index) {
final sink = CanvasDrawSink(
canvas: canvas,
pixelsPerPaperMm: camera.pixelsPerPaperMm,
measurer: measurer,
textStyleOf: document.textStyleOf,
);
if (underlay.isNotEmpty) {
drawPageUnderlay(sink, camera.camera, underlay);
}
DraftPainter(
document: document,
index: index,
resolver: DocumentStyleResolver(document, foreground: 0x000000),
minTextCapPixels: 0.0,
omitOwners: omitOwners,
).paint(sink, camera.camera, camera.size);
});
} finally {
picture = recorder.endRecording();
}
image = await picture.toImage(width, height);
final data = await image.toByteData(format: ui.ImageByteFormat.png);
if (data == null) {
throw StateError('the engine encoded no PNG');
}
return withPhysChunk(
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes),
dotsPerInch,
);
} finally {
image?.dispose();
picture?.dispose();
measurer.clear();
}
}