fixed printing content orientation according to page format
This commit is contained in:
parent
2f8d870811
commit
bb7f300a43
2 changed files with 62 additions and 25 deletions
|
@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
- rendering of SVG with large header
|
- rendering of SVG with large header
|
||||||
- stopping video playback when changing device orientation on Android >=13
|
- stopping video playback when changing device orientation on Android >=13
|
||||||
|
- printing content orientation according to page format
|
||||||
|
|
||||||
## <a id="v1.10.9"></a>[v1.10.9] - 2024-04-14
|
## <a id="v1.10.9"></a>[v1.10.9] - 2024-04-14
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:aves/model/entry/entry.dart';
|
import 'package:aves/model/entry/entry.dart';
|
||||||
import 'package:aves/model/entry/extensions/images.dart';
|
import 'package:aves/model/entry/extensions/images.dart';
|
||||||
|
@ -9,45 +10,66 @@ import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:pdf/pdf.dart';
|
||||||
import 'package:pdf/widgets.dart' as pdf;
|
import 'package:pdf/widgets.dart' as pdf;
|
||||||
import 'package:printing/printing.dart';
|
import 'package:printing/printing.dart';
|
||||||
|
|
||||||
class EntryPrinter with FeedbackMixin {
|
class EntryPrinter with FeedbackMixin {
|
||||||
final AvesEntry entry;
|
final AvesEntry entry;
|
||||||
|
|
||||||
|
static const _fit = pdf.BoxFit.contain;
|
||||||
|
|
||||||
EntryPrinter(this.entry);
|
EntryPrinter(this.entry);
|
||||||
|
|
||||||
Future<void> print(BuildContext context) async {
|
Future<void> print(BuildContext context) async {
|
||||||
final documentName = entry.bestTitle ?? context.l10n.appName;
|
final documentName = entry.bestTitle ?? context.l10n.appName;
|
||||||
final doc = pdf.Document(title: documentName);
|
|
||||||
|
|
||||||
final pages = await _buildPages(context);
|
final imageWidgets = await _buildImageWidgets(context);
|
||||||
if (pages.isNotEmpty) {
|
if (imageWidgets.isNotEmpty) {
|
||||||
pages.forEach(doc.addPage);
|
|
||||||
unawaited(Printing.layoutPdf(
|
unawaited(Printing.layoutPdf(
|
||||||
onLayout: (format) => doc.save(),
|
onLayout: (pageFormat) {
|
||||||
|
final doc = pdf.Document(title: documentName);
|
||||||
|
imageWidgets.map((v) => _buildPdfPage(v, pageFormat)).forEach(doc.addPage);
|
||||||
|
return doc.save();
|
||||||
|
},
|
||||||
name: documentName,
|
name: documentName,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<pdf.Page>> _buildPages(BuildContext context) async {
|
pdf.Page _buildPdfPage(pdf.Widget imageWidget, PdfPageFormat pageFormat) {
|
||||||
final pages = <pdf.Page>[];
|
|
||||||
|
|
||||||
void _addPdfPage(pdf.Widget? pdfChild) {
|
|
||||||
if (pdfChild == null) return;
|
|
||||||
final displaySize = entry.displaySize;
|
final displaySize = entry.displaySize;
|
||||||
pages.add(pdf.Page(
|
final pageTheme = pdf.PageTheme(
|
||||||
|
pageFormat: pageFormat,
|
||||||
orientation: displaySize.height > displaySize.width ? pdf.PageOrientation.portrait : pdf.PageOrientation.landscape,
|
orientation: displaySize.height > displaySize.width ? pdf.PageOrientation.portrait : pdf.PageOrientation.landscape,
|
||||||
|
margin: pdf.EdgeInsets.zero,
|
||||||
|
theme: null,
|
||||||
|
clip: false,
|
||||||
|
textDirection: null,
|
||||||
|
);
|
||||||
|
final mustRotate = pageTheme.mustRotate;
|
||||||
|
final childSize = mustRotate ? Size(displaySize.height, displaySize.width) : displaySize;
|
||||||
|
return pdf.Page(
|
||||||
|
pageTheme: pageTheme,
|
||||||
build: (context) => pdf.FullPage(
|
build: (context) => pdf.FullPage(
|
||||||
ignoreMargins: true,
|
ignoreMargins: true,
|
||||||
child: pdf.Center(
|
child: pdf.Center(
|
||||||
child: pdfChild,
|
child: pdf.Transform.scale(
|
||||||
|
scale: min(pageFormat.availableWidth / childSize.width, pageFormat.availableHeight / childSize.height),
|
||||||
|
child: pdf.Transform.rotateBox(
|
||||||
|
angle: pageTheme.mustRotate ? -0.5 * pi : 0,
|
||||||
|
unconstrained: true,
|
||||||
|
child: imageWidget,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<pdf.Widget>> _buildImageWidgets(BuildContext context) async {
|
||||||
|
final widgets = <pdf.Widget>[];
|
||||||
|
|
||||||
if (entry.isMultiPage && !entry.isMotionPhoto) {
|
if (entry.isMultiPage && !entry.isMotionPhoto) {
|
||||||
final multiPageInfo = await entry.getMultiPageInfo();
|
final multiPageInfo = await entry.getMultiPageInfo();
|
||||||
if (multiPageInfo != null) {
|
if (multiPageInfo != null) {
|
||||||
|
@ -61,17 +83,25 @@ class EntryPrinter with FeedbackMixin {
|
||||||
));
|
));
|
||||||
for (var page = 0; page < pageCount; page++) {
|
for (var page = 0; page < pageCount; page++) {
|
||||||
final pageEntry = multiPageInfo.getPageEntryByIndex(page);
|
final pageEntry = multiPageInfo.getPageEntryByIndex(page);
|
||||||
_addPdfPage(await _buildPageImage(pageEntry));
|
final widget = await _buildPageImage(pageEntry);
|
||||||
|
if (widget != null) {
|
||||||
|
widgets.add(widget);
|
||||||
|
}
|
||||||
streamController.add(pageEntry);
|
streamController.add(pageEntry);
|
||||||
}
|
}
|
||||||
await streamController.close();
|
await streamController.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pages.isEmpty) {
|
|
||||||
_addPdfPage(await _buildPageImage(entry));
|
if (widgets.isEmpty) {
|
||||||
|
final widget = await _buildPageImage(entry);
|
||||||
|
if (widget != null) {
|
||||||
|
widgets.add(widget);
|
||||||
}
|
}
|
||||||
return pages;
|
}
|
||||||
|
|
||||||
|
return widgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<pdf.Widget?> _buildPageImage(AvesEntry entry) async {
|
Future<pdf.Widget?> _buildPageImage(AvesEntry entry) async {
|
||||||
|
@ -82,10 +112,16 @@ class EntryPrinter with FeedbackMixin {
|
||||||
sizeBytes: entry.sizeBytes,
|
sizeBytes: entry.sizeBytes,
|
||||||
);
|
);
|
||||||
if (data.isNotEmpty) {
|
if (data.isNotEmpty) {
|
||||||
return pdf.SvgImage(svg: utf8.decode(data));
|
return pdf.SvgImage(
|
||||||
|
svg: utf8.decode(data),
|
||||||
|
fit: _fit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return pdf.Image(await flutterImageProvider(entry.uriImage));
|
return pdf.Image(
|
||||||
|
await flutterImageProvider(entry.uriImage),
|
||||||
|
fit: _fit,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue