Showing
3 changed files
with
129 additions
and
2 deletions
| 1 | # Changelog | 1 | # Changelog |
| 2 | 2 | ||
| 3 | -## 5.5.1 | 3 | +## 5.6.0 |
| 4 | 4 | ||
| 5 | - Update Google fonts | 5 | - Update Google fonts |
| 6 | - Fix typo in README | 6 | - Fix typo in README |
| @@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
| 9 | - Fix error while loading shared libraries on Linux | 9 | - Fix error while loading shared libraries on Linux |
| 10 | - Update pdfium library to 4627 | 10 | - Update pdfium library to 4627 |
| 11 | - Apply Flutter 2.5 coding style | 11 | - Apply Flutter 2.5 coding style |
| 12 | +- Add WidgetWraper.fromWidget() | ||
| 12 | 13 | ||
| 13 | ## 5.5.0 | 14 | ## 5.5.0 |
| 14 | 15 |
| @@ -20,6 +20,7 @@ import 'dart:ui' as ui; | @@ -20,6 +20,7 @@ import 'dart:ui' as ui; | ||
| 20 | 20 | ||
| 21 | import 'package:flutter/material.dart'; | 21 | import 'package:flutter/material.dart'; |
| 22 | import 'package:flutter/rendering.dart'; | 22 | import 'package:flutter/rendering.dart'; |
| 23 | +import 'package:flutter/widgets.dart'; | ||
| 23 | import 'package:pdf/pdf.dart'; | 24 | import 'package:pdf/pdf.dart'; |
| 24 | import 'package:pdf/widgets.dart' as pw; | 25 | import 'package:pdf/widgets.dart' as pw; |
| 25 | 26 | ||
| @@ -100,6 +101,118 @@ class WidgetWraper extends pw.ImageProvider { | @@ -100,6 +101,118 @@ class WidgetWraper extends pw.ImageProvider { | ||
| 100 | ); | 101 | ); |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 104 | + /// Wrap a Flutter Widget to an ImageProvider. | ||
| 105 | + /// | ||
| 106 | + /// ``` | ||
| 107 | + /// final wrapped = await WidgetWraper.fromWidget( | ||
| 108 | + /// widget: Container( | ||
| 109 | + /// color: Colors.white, | ||
| 110 | + /// child: Text( | ||
| 111 | + /// 'Hello world !', | ||
| 112 | + /// style: TextStyle(color: Colors.amber), | ||
| 113 | + /// ), | ||
| 114 | + /// ), | ||
| 115 | + /// constraints: BoxConstraints(maxWidth: 100, maxHeight: 400), | ||
| 116 | + /// pixelRatio: 3, | ||
| 117 | + /// ); | ||
| 118 | + /// | ||
| 119 | + /// pdf.addPage( | ||
| 120 | + /// pw.Page( | ||
| 121 | + /// pageFormat: format, | ||
| 122 | + /// build: (context) { | ||
| 123 | + /// return pw.Image(wrapped, width: 100); | ||
| 124 | + /// }, | ||
| 125 | + /// ), | ||
| 126 | + /// ); | ||
| 127 | + /// ``` | ||
| 128 | + static Future<WidgetWraper> fromWidget({ | ||
| 129 | + required Widget widget, | ||
| 130 | + required BoxConstraints constraints, | ||
| 131 | + double pixelRatio = 1.0, | ||
| 132 | + PdfImageOrientation? orientation, | ||
| 133 | + double? dpi, | ||
| 134 | + }) async { | ||
| 135 | + assert(pixelRatio > 0); | ||
| 136 | + | ||
| 137 | + if (!constraints.hasBoundedHeight || !constraints.hasBoundedHeight) { | ||
| 138 | + throw Exception( | ||
| 139 | + 'Unable to convert an unbounded widget. Add maxWidth and maxHeight to the constraints.'); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + widget = ConstrainedBox( | ||
| 143 | + constraints: constraints, | ||
| 144 | + child: widget, | ||
| 145 | + ); | ||
| 146 | + | ||
| 147 | + final _properties = DiagnosticPropertiesBuilder(); | ||
| 148 | + widget.debugFillProperties(_properties); | ||
| 149 | + | ||
| 150 | + if (_properties.properties.isEmpty) { | ||
| 151 | + throw ErrorDescription('Unable to get the widget properties'); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + final _constraints = _properties.properties | ||
| 155 | + .whereType<DiagnosticsProperty<BoxConstraints>>() | ||
| 156 | + .first | ||
| 157 | + .value; | ||
| 158 | + | ||
| 159 | + if (_constraints == null || | ||
| 160 | + !_constraints.hasBoundedWidth || | ||
| 161 | + !_constraints.hasBoundedWidth) { | ||
| 162 | + throw Exception('Unable to convert an unbounded widget.'); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + final _repaintBoundary = RenderRepaintBoundary(); | ||
| 166 | + | ||
| 167 | + final renderView = RenderView( | ||
| 168 | + child: RenderPositionedBox( | ||
| 169 | + alignment: Alignment.center, child: _repaintBoundary), | ||
| 170 | + configuration: ViewConfiguration( | ||
| 171 | + size: Size(_constraints.maxWidth, _constraints.maxHeight), | ||
| 172 | + devicePixelRatio: ui.window.devicePixelRatio), | ||
| 173 | + window: _FlutterView( | ||
| 174 | + configuration: ui.ViewConfiguration( | ||
| 175 | + devicePixelRatio: ui.window.devicePixelRatio, | ||
| 176 | + ), | ||
| 177 | + ), | ||
| 178 | + ); | ||
| 179 | + | ||
| 180 | + final pipelineOwner = PipelineOwner()..rootNode = renderView; | ||
| 181 | + renderView.prepareInitialFrame(); | ||
| 182 | + | ||
| 183 | + final buildOwner = BuildOwner(focusManager: FocusManager()); | ||
| 184 | + final _rootElement = RenderObjectToWidgetAdapter<RenderBox>( | ||
| 185 | + container: _repaintBoundary, | ||
| 186 | + child: Directionality( | ||
| 187 | + textDirection: TextDirection.ltr, | ||
| 188 | + child: IntrinsicHeight(child: IntrinsicWidth(child: widget)), | ||
| 189 | + ), | ||
| 190 | + ).attachToRenderTree(buildOwner); | ||
| 191 | + | ||
| 192 | + buildOwner | ||
| 193 | + ..buildScope(_rootElement) | ||
| 194 | + ..finalizeTree(); | ||
| 195 | + | ||
| 196 | + pipelineOwner | ||
| 197 | + ..flushLayout() | ||
| 198 | + ..flushCompositingBits() | ||
| 199 | + ..flushPaint(); | ||
| 200 | + | ||
| 201 | + final image = await _repaintBoundary.toImage(pixelRatio: pixelRatio); | ||
| 202 | + final bytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba); | ||
| 203 | + if (bytes == null) { | ||
| 204 | + throw Exception('Unable to read image data'); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + return WidgetWraper._( | ||
| 208 | + bytes.buffer.asUint8List(), | ||
| 209 | + image.width, | ||
| 210 | + image.height, | ||
| 211 | + orientation ?? PdfImageOrientation.topLeft, | ||
| 212 | + dpi, | ||
| 213 | + ); | ||
| 214 | + } | ||
| 215 | + | ||
| 103 | /// The image data | 216 | /// The image data |
| 104 | final Uint8List bytes; | 217 | final Uint8List bytes; |
| 105 | 218 | ||
| @@ -114,3 +227,16 @@ class WidgetWraper extends pw.ImageProvider { | @@ -114,3 +227,16 @@ class WidgetWraper extends pw.ImageProvider { | ||
| 114 | ); | 227 | ); |
| 115 | } | 228 | } |
| 116 | } | 229 | } |
| 230 | + | ||
| 231 | +class _FlutterView extends ui.FlutterView { | ||
| 232 | + _FlutterView({required this.configuration}); | ||
| 233 | + | ||
| 234 | + final ui.ViewConfiguration configuration; | ||
| 235 | + | ||
| 236 | + @override | ||
| 237 | + ui.PlatformDispatcher get platformDispatcher => | ||
| 238 | + ui.PlatformDispatcher.instance; | ||
| 239 | + | ||
| 240 | + @override | ||
| 241 | + ui.ViewConfiguration get viewConfiguration => configuration; | ||
| 242 | +} |
| @@ -6,7 +6,7 @@ description: > | @@ -6,7 +6,7 @@ description: > | ||
| 6 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing | 6 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing |
| 7 | repository: https://github.com/DavBfr/dart_pdf | 7 | repository: https://github.com/DavBfr/dart_pdf |
| 8 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 8 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
| 9 | -version: 5.5.1 | 9 | +version: 5.6.0 |
| 10 | 10 | ||
| 11 | environment: | 11 | environment: |
| 12 | sdk: ">=2.12.0 <3.0.0" | 12 | sdk: ">=2.12.0 <3.0.0" |
-
Please register or login to post a comment