fromWidget static method
Future<WidgetWrapper>
fromWidget({
- required BuildContext context,
- required Widget widget,
- required BoxConstraints constraints,
- double pixelRatio = 1.0,
- PdfImageOrientation? orientation,
- double? dpi,
Wrap a Flutter Widget to an ImageProvider.
final wrapped = await WidgetWrapper.fromWidget(
widget: Container(
color: Colors.white,
child: Text(
'Hello world !',
style: TextStyle(color: Colors.amber),
),
),
constraints: BoxConstraints(maxWidth: 100, maxHeight: 400),
pixelRatio: 3,
);
pdf.addPage(
pw.Page(
pageFormat: format,
build: (context) {
return pw.Image(wrapped, width: 100);
},
),
);
Implementation
static Future<WidgetWrapper> fromWidget({
required BuildContext context,
required Widget widget,
required BoxConstraints constraints,
double pixelRatio = 1.0,
PdfImageOrientation? orientation,
double? dpi,
}) async {
assert(pixelRatio > 0);
if (!constraints.hasBoundedHeight || !constraints.hasBoundedHeight) {
throw Exception(
'Unable to convert an unbounded widget. Add maxWidth and maxHeight to the constraints.');
}
widget = ConstrainedBox(
constraints: constraints,
child: widget,
);
final prop = DiagnosticPropertiesBuilder();
widget.debugFillProperties(prop);
if (prop.properties.isEmpty) {
throw ErrorDescription('Unable to get the widget properties');
}
final computedConstraints = prop.properties
.whereType<DiagnosticsProperty<BoxConstraints>>()
.first
.value;
if (computedConstraints == null ||
!computedConstraints.hasBoundedWidth ||
!computedConstraints.hasBoundedWidth) {
throw Exception('Unable to convert an unbounded widget.');
}
final repaintBoundary = RenderRepaintBoundary();
// Flutter 3.9
// final view = View.of(context);
final view = WidgetsBinding.instance.window;
final renderView = RenderView(
child: RenderPositionedBox(
alignment: Alignment.center, child: repaintBoundary),
configuration: ViewConfiguration(
size:
Size(computedConstraints.maxWidth, computedConstraints.maxHeight),
devicePixelRatio: view.devicePixelRatio),
window: view,
);
final pipelineOwner = PipelineOwner()..rootNode = renderView;
renderView.prepareInitialFrame();
final buildOwner = BuildOwner(focusManager: FocusManager());
final rootElement = RenderObjectToWidgetAdapter<RenderBox>(
container: repaintBoundary,
child: Directionality(
textDirection: TextDirection.ltr,
child: IntrinsicHeight(child: IntrinsicWidth(child: widget)),
),
).attachToRenderTree(buildOwner);
buildOwner
..buildScope(rootElement)
..finalizeTree();
pipelineOwner
..flushLayout()
..flushCompositingBits()
..flushPaint();
final image = await repaintBoundary.toImage(pixelRatio: pixelRatio);
final bytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
if (bytes == null) {
throw Exception('Unable to read image data');
}
return WidgetWrapper._(
bytes.buffer.asUint8List(),
image.width,
image.height,
orientation ?? PdfImageOrientation.topLeft,
dpi,
);
}