saveDrawing method
Future<void>
saveDrawing({
- required dynamic pdfFile,
- required int totalPages,
- required BuildContext context,
- required DrawingController drawingController,
- required ImageController imageController,
- required TextBoxController textBoxController,
- required HighlightController highlightController,
- required UnderlineController underlineController,
- required Function refresh,
Saves the current edits (drawings, images, annotations, and text boxes) to a new PDF file.
pdfFile - the original PDF file,
totalPages - number of pages in the document,
context - BuildContext for getting MediaQuery,
drawingController, imageController, textBoxController,
highlightController, underlineController - various controllers
managing different edit types,
refresh - callback to refresh UI if needed.
Implementation
Future<void> saveDrawing({
required pdfFile,
required int totalPages,
required BuildContext context,
required DrawingController drawingController,
required ImageController imageController,
required TextBoxController textBoxController,
required HighlightController highlightController,
required UnderlineController underlineController,
required Function refresh,
}) async {
if (isSaving) {
return;
}
try {
isSaving = true; // Start loading
final pdfDoc = PdfDocument(inputBytes: await pdfFile.readAsBytes());
for (int i = 0; i < totalPages; i++) {
// Set the current page in the drawing controller
drawingController.setPage(i + 1);
PdfPage page = pdfDoc.pages[i];
// Allow time for page switch to complete
await Future.delayed(const Duration(milliseconds: 200));
// --- Add highlight annotations ---
for (AnnotationAction action
in highlightController.getHighlightHistory[i + 1] ?? []) {
if (action.isAdd) {
for (int j = 0; j < action.pdfAnnotation.length; j++) {
if (i < pdfDoc.pages.count) {
pdfDoc.pages[i].annotations.add(action.pdfAnnotation[j]);
}
}
}
}
// --- Add underline annotations ---
for (AnnotationAction action
in underlineController.getUnderlineHistory[i + 1] ?? []) {
if (action.isAdd) {
for (int j = 0; j < action.pdfAnnotation.length; j++) {
if (i < pdfDoc.pages.count) {
pdfDoc.pages[i].annotations.add(action.pdfAnnotation[j]);
}
}
}
}
// --- Add images onto PDF page ---
for (var imageBox in imageController.getAllImageBoxes()[i + 1] ?? []) {
final imgData = await _convertImageToUint8List(imageBox.image);
final PdfImage pdfImage = PdfBitmap(imgData);
final double scaleFactorX =
page.getClientSize().width / MediaQuery.of(context).size.width;
final double scaleFactorY =
page.getClientSize().height /
(MediaQuery.of(context).size.width * 1.414);
double scaledX = imageBox.position.dx * scaleFactorX;
double scaledY = imageBox.position.dy * scaleFactorY;
double scaledWidth = imageBox.width * scaleFactorX;
double scaledHeight = imageBox.height * scaleFactorY;
// Save the current graphics state before transformations
page.graphics.save();
// Apply rotation and translation
page.graphics.translateTransform(
scaledX + scaledWidth / 2,
scaledY + scaledHeight / 2,
);
page.graphics.rotateTransform(imageBox.rotation * (180 / pi));
// Draw the image
page.graphics.drawImage(
pdfImage,
Rect.fromLTWH(
(-scaledWidth / 2) + 14,
(-scaledHeight / 2) + 14,
scaledWidth,
scaledHeight,
),
);
// Restore the graphics state
page.graphics.restore();
}
// --- Add freehand drawing on the PDF page ---
ByteData? imageData = await drawingController.getImageData(i + 1);
if (imageData != null) {
final PdfImage image = PdfBitmap(imageData.buffer.asUint8List());
final double pageWidth = page.getClientSize().width;
final double pageHeight = page.getClientSize().height;
page.graphics.drawImage(
image,
Rect.fromLTWH(0, 0, pageWidth, pageHeight),
);
}
// --- Add text boxes on the PDF page ---
for (TextBox textBox
in textBoxController.getAllTextBoxes()[i + 1] ?? []) {
final double scaleFactorX =
page.getClientSize().width / MediaQuery.of(context).size.width;
final double scaleFactorY =
page.getClientSize().height /
(MediaQuery.of(context).size.width * 1.414);
double scaledX = textBox.position.dx * scaleFactorX;
double scaledY = textBox.position.dy * scaleFactorY;
double scaledWidth = textBox.width * scaleFactorX;
double scaledHeight = textBox.height * scaleFactorY;
page.graphics.drawString(
textBox.text,
PdfStandardFont(PdfFontFamily.helvetica, textBox.fontSize),
brush: PdfSolidBrush(
PdfColor(
textBox.color?.red ?? 0,
textBox.color?.green ?? 0,
textBox.color?.blue ?? 0,
),
),
bounds: Rect.fromLTWH(
scaledX + 10, // Padding for better text visibility
scaledY + 10,
scaledWidth,
scaledHeight,
),
format: PdfStringFormat(
alignment: PdfTextAlignment.center,
lineAlignment: PdfVerticalAlignment.middle,
),
);
}
}
// --- Save the modified PDF file ---
final output = await getTemporaryDirectory();
final String originalName = pdfFile.path.split('/').last.split('.').first;
final String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
final String savedPath = '${output.path}/${originalName}_$timestamp.pdf';
final file = File(savedPath);
await file.writeAsBytes(await pdfDoc.save());
pdfDoc.dispose();
// Pop with result file
Navigator.pop(context, file);
// Optionally, you can open the saved file
// OpenFile.open(savedPath);
} catch (e) {
debugPrint('Error while saving drawing and text: $e');
} finally {
isSaving = false; // End loading
}
}