David PHAM-VAN

Format source

... ... @@ -23,3 +23,7 @@ build/
printing/android/local.properties
.idea
*.iml
.flutter-plugins
printing/*.log
printing/ios/Flutter
printing/ios/Runner
... ...
# Copyright (C) 2018, David PHAM-VAN <dev.nfet.net@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General License for more details.
#
# You should have received a copy of the GNU Lesser General
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
DART_SRC=$(shell find . -name '*.dart')
CLNG_SRC=$(shell find . -name '*.java' -o -name '*.m' -o -name '*.h')
all: pdf/open-sans.ttf format
pdf/open-sans.ttf:
curl -L "https://github.com/google/fonts/raw/master/apache/opensans/OpenSans-Regular.ttf" > $@
format: format-dart format-clang
format-dart: $(DART_SRC)
dartfmt -w $^
format-clang: $(CLNG_SRC)
clang-format -style=Chromium -i $^
test: pdf/open-sans.ttf
cd pdf; for TEST in $(shell cd pdf; find test -name '*.dart'); do dart $$TEST; done
cd printing; flutter test
clean:
git clean -fdx
.PHONY: test format format-dart format-clang clean
... ...
# 1.0.4
* Updated homepage
* Update source formatting
# 1.0.3
* Remove dependency to ttf_parser
... ...
... ... @@ -10,13 +10,13 @@ void main() {
final top = page.pageFormat.height;
g.setColor(new PDFColor(0.0, 1.0, 1.0));
g.drawRect(50.0 * PDFPageFormat.MM, top - 80.0 * PDFPageFormat.MM, 100.0 * PDFPageFormat.MM,
50.0 * PDFPageFormat.MM);
g.drawRect(50.0 * PDFPageFormat.MM, top - 80.0 * PDFPageFormat.MM,
100.0 * PDFPageFormat.MM, 50.0 * PDFPageFormat.MM);
g.fillPath();
g.setColor(new PDFColor(0.3, 0.3, 0.3));
g.drawString(
font, 12.0, "Hello World!", 10.0 * PDFPageFormat.MM, top - 10.0 * PDFPageFormat.MM);
g.drawString(font, 12.0, "Hello World!", 10.0 * PDFPageFormat.MM,
top - 10.0 * PDFPageFormat.MM);
var file = new File('example.pdf');
file.writeAsBytesSync(pdf.save());
... ...
... ... @@ -91,7 +91,8 @@ class PDFAnnot extends PDFObject {
/// @param r Right coordinate
/// @param t Top coordinate
/// @param s Text for this annotation
factory PDFAnnot.text(PDFPage pdfPage, double l, double b, double r, double t, String s) =>
factory PDFAnnot.text(
PDFPage pdfPage, double l, double b, double r, double t, String s) =>
new PDFAnnot(pdfPage, type: "/Text", l: l, b: b, r: r, t: t, s: s);
/// Creates a link annotation
... ... @@ -106,14 +107,23 @@ class PDFAnnot extends PDFObject {
/// @param ft Top coordinate
/// <br><br>Rectangle describing what part of the page to be displayed
/// (must be in User Coordinates)
factory PDFAnnot.link(
PDFPage pdfPage, double l, double b, double r, double t, PDFObject dest,
factory PDFAnnot.link(PDFPage pdfPage, double l, double b, double r, double t,
PDFObject dest,
[double fl = FULL_PAGE,
double fb = FULL_PAGE,
double fr = FULL_PAGE,
double ft = FULL_PAGE]) =>
new PDFAnnot(pdfPage,
type: "/Link", l: l, b: b, r: r, t: t, dest: dest, fl: fl, fb: fb, fr: fr, ft: ft);
type: "/Link",
l: l,
b: b,
r: r,
t: t,
dest: dest,
fl: fl,
fb: fb,
fr: fr,
ft: ft);
/// Sets the border for the annotation. By default, no border is defined.
///
... ...
... ... @@ -50,6 +50,7 @@ class PDFCatalog extends PDFObject {
}
// the /PageMode setting
params["/PageMode"] = PDFStream.string(PDFDocument._PDF_PAGE_MODES[pageMode.index]);
params["/PageMode"] =
PDFStream.string(PDFDocument._PDF_PAGE_MODES[pageMode.index]);
}
}
... ...
... ... @@ -29,8 +29,11 @@ class PDFColor {
PDFColor(this.r, this.g, this.b, [this.a = 1.0]);
factory PDFColor.fromInt(int color) {
return new PDFColor((color >> 16 & 0xff) / 255.0, (color >> 8 & 0xff) / 255.0,
(color & 0xff) / 255.0, (color >> 24 & 0xff) / 255.0);
return new PDFColor(
(color >> 16 & 0xff) / 255.0,
(color >> 8 & 0xff) / 255.0,
(color & 0xff) / 255.0,
(color >> 24 & 0xff) / 255.0);
}
factory PDFColor.fromHex(String color) {
... ...
... ... @@ -32,7 +32,8 @@ class PDFFont extends PDFObject {
/// @param type The pdf type, ie /Type1
/// @param font The font name, ie Helvetica
/// @param style The java.awt.Font style, ie: Font.PLAIN
PDFFont(PDFDocument pdfDocument, {this.subtype = "/Type1", this.baseFont = "/Helvetica"})
PDFFont(PDFDocument pdfDocument,
{this.subtype = "/Type1", this.baseFont = "/Helvetica"})
: super(pdfDocument, "/Font") {
pdfDocument.fonts.add(this);
}
... ...
... ... @@ -22,7 +22,8 @@ class PDFFontDescriptor extends PDFObject {
final PDFObjectStream file;
final PDFTTFFont ttfFont;
PDFFontDescriptor(this.ttfFont, this.file) : super(ttfFont.pdfDocument, "/FontDescriptor");
PDFFontDescriptor(this.ttfFont, this.file)
: super(ttfFont.pdfDocument, "/FontDescriptor");
@override
void prepare() {
... ... @@ -32,8 +33,12 @@ class PDFFontDescriptor extends PDFObject {
params["/FontFile2"] = file.ref();
params["/Flags"] = PDFStream.intNum(32);
params["/FontBBox"] = new PDFStream()
..putStringArray(
[ttfFont.font.xMin, ttfFont.font.yMin, ttfFont.font.xMax, ttfFont.font.yMax]);
..putStringArray([
ttfFont.font.xMin,
ttfFont.font.yMin,
ttfFont.font.xMax,
ttfFont.font.yMax
]);
params["/Ascent"] = PDFStream.intNum(ttfFont.font.ascent);
params["/Descent"] = PDFStream.intNum(ttfFont.font.descent);
params["/ItalicAngle"] = PDFStream.intNum(0);
... ...
... ... @@ -133,10 +133,14 @@ class PDFGraphics {
// Starting point
moveTo(x, y - r2);
buf.putString("${x + m4 * r1} ${y - r2} ${x + r1} ${y - m4 * r2} ${x + r1} $y c\n");
buf.putString("${x + r1} ${y + m4 * r2} ${x + m4 * r1} ${y + r2} $x ${y + r2} c\n");
buf.putString("${x - m4 * r1} ${y + r2} ${x - r1} ${y + m4 * r2} ${x - r1} $y c\n");
buf.putString("${x - r1} ${y - m4 * r2} ${x - m4 * r1} ${y - r2} $x ${y - r2} c\n");
buf.putString(
"${x + m4 * r1} ${y - r2} ${x + r1} ${y - m4 * r2} ${x + r1} $y c\n");
buf.putString(
"${x + r1} ${y + m4 * r2} ${x + m4 * r1} ${y + r2} $x ${y + r2} c\n");
buf.putString(
"${x - m4 * r1} ${y + r2} ${x - r1} ${y + m4 * r2} ${x - r1} $y c\n");
buf.putString(
"${x - r1} ${y - m4 * r2} ${x - m4 * r1} ${y - r2} $x ${y - r2} c\n");
}
/// We override Graphics.drawRect as it doesn't join the 4 lines.
... ... @@ -174,7 +178,8 @@ class PDFGraphics {
///
/// @param c Color to use
void setColor(PDFColor color) {
buf.putString("${color.r} ${color.g} ${color.b} rg ${color.r} ${color.g} ${color.b} RG\n");
buf.putString(
"${color.r} ${color.g} ${color.b} rg ${color.r} ${color.g} ${color.b} RG\n");
}
/// Set the transformation Matrix
... ...
... ... @@ -62,7 +62,11 @@ class PDFImage extends PDFXObject {
if (alphaChannel == false && alpha) {
var _sMask = new PDFImage(pdfDocument,
image: image, width: width, height: height, alpha: alpha, alphaChannel: true);
image: image,
width: width,
height: height,
alpha: alpha,
alphaChannel: true);
params["/SMask"] = PDFStream.string("${_sMask.objser} 0 R");
}
... ...
... ... @@ -34,7 +34,8 @@ class PDFObject {
/// This is usually called by extensors to this class, and sets the
/// PDF Object Type
/// @param type the PDF Object Type
PDFObject(this.pdfDocument, [String type]) : objser = pdfDocument._genSerial() {
PDFObject(this.pdfDocument, [String type])
: objser = pdfDocument._genSerial() {
if (type != null) {
params["/Type"] = PDFStream.string(type);
}
... ...
... ... @@ -52,7 +52,8 @@ class PDFOutline extends PDFObject {
/// @param b bottom coordinate
/// @param r right coordinate
/// @param t top coordinate
PDFOutline(PDFDocument pdfDocument, {this.title, this.dest, this.l, this.b, this.r, this.t})
PDFOutline(PDFDocument pdfDocument,
{this.title, this.dest, this.l, this.b, this.r, this.t})
: super(pdfDocument, "/Outlines");
/// This method creates an outline, and attaches it to this one.
... ...
... ... @@ -48,7 +48,8 @@ class PDFPage extends PDFObject {
/// @see PageFormat#LANDSCAPE
/// @see PageFormat#REVERSE_LANDSCAPE
/// @param pageFormat PageFormat describing the page size
PDFPage(PDFDocument pdfDocument, {this.pageFormat}) : super(pdfDocument, "/Page") {
PDFPage(PDFDocument pdfDocument, {this.pageFormat})
: super(pdfDocument, "/Page") {
pdfDocument.pdfPageList.pages.add(this);
if (pageFormat == null) pageFormat = PDFPageFormat.A4;
}
... ... @@ -125,8 +126,8 @@ class PDFPage extends PDFObject {
var xy2 = cxy(x + w, y);
var xy3 = cxy(vx, vy + vh);
var xy4 = cxy(vx + vw, vy);
PDFAnnot ob =
new PDFAnnot.link(this, xy1.w, xy1.h, xy2.w, xy2.h, dest, xy3.w, xy3.h, xy4.w, xy4.h);
PDFAnnot ob = new PDFAnnot.link(
this, xy1.w, xy1.h, xy2.w, xy2.h, dest, xy3.w, xy3.h, xy4.w, xy4.h);
return ob;
}
... ... @@ -138,7 +139,8 @@ class PDFPage extends PDFObject {
/// @param w Width of region
/// @param h Height coordinate of region
/// @return PDFOutline object created, for addSubOutline if required.
PDFOutline addOutline(String title, {double x, double y, double w, double h}) {
PDFOutline addOutline(String title,
{double x, double y, double w, double h}) {
PDFPoint xy1 = cxy(x, y + h);
PDFPoint xy2 = cxy(x + w, y);
PDFOutline outline = new PDFOutline(pdfDocument,
... ...
... ... @@ -107,7 +107,8 @@ class PDFStream {
putString("[" + values.join(" ") + "]");
}
static PDFStream array(List<PDFStream> values) => new PDFStream()..putArray(values);
static PDFStream array(List<PDFStream> values) =>
new PDFStream()..putArray(values);
void putDictionary(Map<String, PDFStream> values) {
putString("<< ");
... ...
... ... @@ -86,8 +86,8 @@ class TTFParser {
int offset = bytes.getUint16(pos + 10);
pos += 12;
if (platformID == 1 && nameID == 6) {
_fontName = utf8
.decode(bytes.buffer.asUint8List(basePosition + stringOffset + offset, length));
_fontName = utf8.decode(bytes.buffer
.asUint8List(basePosition + stringOffset + offset, length));
}
}
}
... ... @@ -164,7 +164,8 @@ class TTFParser {
if (idRangeOffset == 0) {
glyphIndex = (idDelta + c) % 65536;
} else {
final glyphIndexAddress = idRangeOffset + 2 * (c - startCode) + idRangeOffsetAddress;
final glyphIndexAddress =
idRangeOffset + 2 * (c - startCode) + idRangeOffsetAddress;
glyphIndex = bytes.getUint16(glyphIndexAddress);
}
charToGlyphIndexMap[c] = glyphIndex;
... ...
... ... @@ -36,8 +36,9 @@ class PDFXref {
/// @return The xref in the format of the xref section in the PDF file
String ref() {
String rs =
offset.toString().padLeft(10, '0') + " " + generation.toString().padLeft(5, '0');
String rs = offset.toString().padLeft(10, '0') +
" " +
generation.toString().padLeft(5, '0');
if (generation == 65535) return rs + " f ";
return rs + " n ";
... ...
# 1.0.3
* Update source formatting
# 1.0.2
* Add License file
* Updated homepage
... ...
... ... @@ -20,5 +20,4 @@ package net.nfet.flutter.printing;
import android.support.v4.content.FileProvider;
public class PrintFileProvider extends FileProvider {
}
public class PrintFileProvider extends FileProvider {}
... ...
... ... @@ -49,118 +49,121 @@ import io.flutter.plugin.common.PluginRegistry.Registrar;
* PrintingPlugin
*/
public class PrintingPlugin implements MethodCallHandler {
private static PrintManager printManager;
private final Activity activity;
private PrintingPlugin(Activity activity) {
this.activity = activity;
}
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "printing");
channel.setMethodCallHandler(new PrintingPlugin(registrar.activity()));
printManager = (PrintManager) registrar.activity().getSystemService(Context.PRINT_SERVICE);
}
@Override
public void onMethodCall(MethodCall call, Result result) {
switch (call.method) {
case "printPdf":
printPdf((byte[]) call.argument("doc"));
result.success(0);
break;
case "sharePdf":
sharePdf((byte[]) call.argument("doc"));
result.success(0);
break;
default:
result.notImplemented();
break;
}
}
private void printPdf(final byte[] badgeData) {
PrintDocumentAdapter pda = new PrintDocumentAdapter() {
PrintedPdfDocument mPdfDocument;
@Override
public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor parcelFileDescriptor, CancellationSignal cancellationSignal, WriteResultCallback writeResultCallback) {
OutputStream output = null;
try {
output = new FileOutputStream(parcelFileDescriptor.getFileDescriptor());
output.write(badgeData, 0, badgeData.length);
writeResultCallback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
// Create a new PdfDocument with the requested page attributes
mPdfDocument = new PrintedPdfDocument(activity, newAttributes);
// Respond to cancellation request
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
// Return print information to print framework
PrintDocumentInfo info = new PrintDocumentInfo
.Builder("badge.pdf")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(1).build();
// Content layout reflow is complete
callback.onLayoutFinished(info, true);
}
@Override
public void onFinish() {
//noinspection ResultOfMethodCallIgnored
}
};
String jobName = "Badge";
printManager.print(jobName, pda, null);
}
private void sharePdf(byte[] data) {
try {
final File externalFilesDirectory = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File shareFile = File.createTempFile("badge", ".pdf", externalFilesDirectory);
FileOutputStream stream = new FileOutputStream(shareFile);
stream.write(data);
stream.close();
Uri apkURI = FileProvider.getUriForFile(activity,
activity.getApplicationContext().getPackageName() + ".flutter.printing", shareFile);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
shareIntent.putExtra(Intent.EXTRA_STREAM, apkURI);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent chooserIntent = Intent.createChooser(shareIntent, null);
activity.startActivity(chooserIntent);
shareFile.deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
}
}
private static PrintManager printManager;
private final Activity activity;
private PrintingPlugin(Activity activity) {
this.activity = activity;
}
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "printing");
channel.setMethodCallHandler(new PrintingPlugin(registrar.activity()));
printManager = (PrintManager) registrar.activity().getSystemService(Context.PRINT_SERVICE);
}
@Override
public void onMethodCall(MethodCall call, Result result) {
switch (call.method) {
case "printPdf":
printPdf((byte[]) call.argument("doc"));
result.success(0);
break;
case "sharePdf":
sharePdf((byte[]) call.argument("doc"));
result.success(0);
break;
default:
result.notImplemented();
break;
}
}
private void printPdf(final byte[] badgeData) {
PrintDocumentAdapter pda = new PrintDocumentAdapter() {
PrintedPdfDocument mPdfDocument;
@Override
public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor parcelFileDescriptor,
CancellationSignal cancellationSignal,
WriteResultCallback writeResultCallback) {
OutputStream output = null;
try {
output = new FileOutputStream(parcelFileDescriptor.getFileDescriptor());
output.write(badgeData, 0, badgeData.length);
writeResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES});
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
CancellationSignal cancellationSignal, LayoutResultCallback callback,
Bundle extras) {
// Create a new PdfDocument with the requested page attributes
mPdfDocument = new PrintedPdfDocument(activity, newAttributes);
// Respond to cancellation request
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
// Return print information to print framework
PrintDocumentInfo info =
new PrintDocumentInfo.Builder("badge.pdf")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(1)
.build();
// Content layout reflow is complete
callback.onLayoutFinished(info, true);
}
@Override
public void onFinish() {
// noinspection ResultOfMethodCallIgnored
}
};
String jobName = "Badge";
printManager.print(jobName, pda, null);
}
private void sharePdf(byte[] data) {
try {
final File externalFilesDirectory =
activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File shareFile = File.createTempFile("badge", ".pdf", externalFilesDirectory);
FileOutputStream stream = new FileOutputStream(shareFile);
stream.write(data);
stream.close();
Uri apkURI = FileProvider.getUriForFile(activity,
activity.getApplicationContext().getPackageName() + ".flutter.printing",
shareFile);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
shareIntent.putExtra(Intent.EXTRA_STREAM, apkURI);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent chooserIntent = Intent.createChooser(shareIntent, null);
activity.startActivity(chooserIntent);
shareFile.deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
}
}
}
... ...
... ... @@ -22,8 +22,8 @@ class MyApp extends StatelessWidget {
g.fillPath();
g.setColor(new PDFColor(0.3, 0.3, 0.3));
g.drawString(
font, 12.0, "Hello World!", 10.0 * PDFPageFormat.MM, top - 10.0 * PDFPageFormat.MM);
g.drawString(font, 12.0, "Hello World!", 10.0 * PDFPageFormat.MM,
top - 10.0 * PDFPageFormat.MM);
return pdf;
}
... ... @@ -39,9 +39,12 @@ class MyApp extends StatelessWidget {
final pdf = _generateDocument();
// Calculate the widget center for iPad sharing popup position
final RenderBox referenceBox = shareWidget.currentContext.findRenderObject();
final topLeft = referenceBox.localToGlobal(referenceBox.paintBounds.topLeft);
final bottomRight = referenceBox.localToGlobal(referenceBox.paintBounds.bottomRight);
final RenderBox referenceBox =
shareWidget.currentContext.findRenderObject();
final topLeft =
referenceBox.localToGlobal(referenceBox.paintBounds.topLeft);
final bottomRight =
referenceBox.localToGlobal(referenceBox.paintBounds.bottomRight);
final bounds = new Rect.fromPoints(topLeft, bottomRight);
Printing.sharePdf(document: pdf, bounds: bounds);
... ... @@ -57,9 +60,12 @@ class MyApp extends StatelessWidget {
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new RaisedButton(child: new Text('Print Document'), onPressed: _printPdf),
new RaisedButton(
key: shareWidget, child: new Text('Share Document'), onPressed: _sharePdf),
child: new Text('Print Document'), onPressed: _printPdf),
new RaisedButton(
key: shareWidget,
child: new Text('Share Document'),
onPressed: _sharePdf),
],
),
),
... ...
... ... @@ -18,5 +18,6 @@
#import <Flutter/Flutter.h>
@interface PrintingPlugin : NSObject<FlutterPlugin, UIPrintInteractionControllerDelegate>
@interface PrintingPlugin
: NSObject <FlutterPlugin, UIPrintInteractionControllerDelegate>
@end
... ...
... ... @@ -20,9 +20,9 @@
@implementation PrintingPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"printing"
binaryMessenger:[registrar messenger]];
FlutterMethodChannel* channel =
[FlutterMethodChannel methodChannelWithName:@"printing"
binaryMessenger:[registrar messenger]];
PrintingPlugin* instance = [[PrintingPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
... ... @@ -32,72 +32,89 @@
[self printPdf:[call.arguments objectForKey:@"doc"]];
result(@1);
} else if ([@"sharePdf" isEqualToString:call.method]) {
[self
sharePdf:[call.arguments objectForKey:@"doc"]
withSourceRect:CGRectMake(
[[call.arguments objectForKey:@"x"] floatValue],
[[call.arguments objectForKey:@"y"] floatValue],
[[call.arguments objectForKey:@"w"] floatValue],
[[call.arguments objectForKey:@"h"] floatValue])];
[self sharePdf:[call.arguments objectForKey:@"doc"]
withSourceRect:CGRectMake(
[[call.arguments objectForKey:@"x"] floatValue],
[[call.arguments objectForKey:@"y"] floatValue],
[[call.arguments objectForKey:@"w"] floatValue],
[[call.arguments objectForKey:@"h"] floatValue])];
result(@1);
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)printPdf:(nonnull FlutterStandardTypedData *)data {
BOOL printing = [UIPrintInteractionController isPrintingAvailable];
if (!printing) {
NSLog(@"printing not available");
return;
}
BOOL dataOK = [UIPrintInteractionController canPrintData:[data data]];
if (!dataOK) NSLog(@"data not ok to be printed");
UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
[controller setDelegate:self];
[controller setPrintingItem:[data data]];
- (void)printPdf:(nonnull FlutterStandardTypedData*)data {
BOOL printing = [UIPrintInteractionController isPrintingAvailable];
if (!printing) {
NSLog(@"printing not available");
return;
}
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if(!completed && error){
NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, (unsigned int)error.code);
BOOL dataOK = [UIPrintInteractionController canPrintData:[data data]];
if (!dataOK)
NSLog(@"data not ok to be printed");
UIPrintInteractionController* controller =
[UIPrintInteractionController sharedPrintController];
[controller setDelegate:self];
[controller setPrintingItem:[data data]];
UIPrintInteractionCompletionHandler completionHandler =
^(UIPrintInteractionController* printController, BOOL completed,
NSError* error) {
if (!completed && error) {
NSLog(@"FAILED! due to error in domain %@ with error code %u",
error.domain, (unsigned int)error.code);
}
};
};
[controller presentAnimated:YES completionHandler:completionHandler];
[controller presentAnimated:YES completionHandler:completionHandler];
}
- (void)sharePdf:(nonnull FlutterStandardTypedData *)data withSourceRect:(CGRect)rect {
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
- (void)sharePdf:(nonnull FlutterStandardTypedData*)data
withSourceRect:(CGRect)rect {
NSURL* tmpDirURL =
[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
CFUUIDRef uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
CFUUIDRef uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
assert(uuidStr != NULL);
CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
assert(uuidStr != NULL);
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:[NSString stringWithFormat:@"pdf-%@", uuidStr]] URLByAppendingPathExtension:@"pdf"];
assert(fileURL != NULL);
NSURL* fileURL = [[tmpDirURL
URLByAppendingPathComponent:[NSString
stringWithFormat:@"pdf-%@", uuidStr]]
URLByAppendingPathExtension:@"pdf"];
assert(fileURL != NULL);
CFRelease(uuidStr);
CFRelease(uuid);
CFRelease(uuidStr);
CFRelease(uuid);
NSString *path = [fileURL path];
NSString* path = [fileURL path];
NSError *error;
if (![[data data] writeToFile:path options:NSDataWritingAtomic error:&error]) {
NSLog(@"sharePdf error: %@", [error localizedDescription]);
return;
}
NSError* error;
if (!
[[data data] writeToFile:path options:NSDataWritingAtomic error:&error]) {
NSLog(@"sharePdf error: %@", [error localizedDescription]);
return;
}
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[fileURL] applicationActivities:nil];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;
activityViewController.popoverPresentationController.sourceView = controller.view;
activityViewController.popoverPresentationController.sourceRect = rect;
}
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:activityViewController animated:YES completion:nil];
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:@[ fileURL ]
applicationActivities:nil];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIViewController* controller =
[UIApplication sharedApplication].keyWindow.rootViewController;
activityViewController.popoverPresentationController.sourceView =
controller.view;
activityViewController.popoverPresentationController.sourceRect = rect;
}
[[UIApplication sharedApplication].keyWindow.rootViewController
presentViewController:activityViewController
animated:YES
completion:nil];
}
@end
... ...
... ... @@ -38,7 +38,8 @@ class Printing {
await _channel.invokeMethod('printPdf', params);
}
static Future<Null> sharePdf({PDFDocument document, List<int> bytes, Rect bounds}) async {
static Future<Null> sharePdf(
{PDFDocument document, List<int> bytes, Rect bounds}) async {
assert(document != null || bytes != null);
assert(!(document == null && bytes == null));
... ...
... ... @@ -2,7 +2,7 @@ name: printing
author: David PHAM-VAN <dev.nfet.net@gmail.com>
description: Plugin that allows Flutter apps to generate and print documents to android or ios compatible printers
homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing
version: 1.0.2
version: 1.0.3
environment:
sdk: ">=1.19.0 <3.0.0"
... ...