Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
dart_pdf
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
David PHAM-VAN
2021-02-13 08:08:15 -0400
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
81634e17db81d45314960ff9991b2f4273c57855
81634e17
1 parent
aeabce87
Implement dynamic layout on iOS and macOS
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
202 additions
and
77 deletions
printing/CHANGELOG.md
printing/ios/Classes/PrintJob.swift
printing/ios/Classes/PrintingPlugin.swift
printing/lib/src/method_channel.dart
printing/lib/src/method_channel_ffi.dart
printing/macos/Classes/PrintJob.swift
printing/macos/Classes/PrintingPlugin.swift
printing/pubspec.yaml
printing/CHANGELOG.md
View file @
81634e1
...
...
@@ -5,6 +5,7 @@
-
Add imageFromAssetBundle and networkImage
-
Add Page orientation on PdfPreview
-
Improve PrintJob object
-
Implement dynamic layout on iOS and macOS
## 5.0.0-nullsafety.1
...
...
printing/ios/Classes/PrintJob.swift
View file @
81634e1
...
...
@@ -28,6 +28,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
private
var
urlObservation
:
NSKeyValueObservation
?
private
var
jobName
:
String
?
private
var
orientation
:
UIPrintInfo
.
Orientation
?
private
let
semaphore
=
DispatchSemaphore
(
value
:
0
)
public
init
(
printing
:
PrintingPlugin
,
index
:
Int
)
{
self
.
printing
=
printing
...
...
@@ -46,9 +47,9 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
}
}
func
cancelJob
(
_
error
:
String
?)
{
func
cancelJob
(
_
:
String
?)
{
pdfDocument
=
nil
printing
.
onCompleted
(
printJob
:
self
,
completed
:
false
,
error
:
error
as
NSString
?
)
semaphore
.
signal
(
)
}
func
setDocument
(
_
data
:
Data
?)
{
...
...
@@ -57,24 +58,25 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
let
dataProvider
=
CGDataProvider
(
dataInfo
:
nil
,
data
:
bytesPointer
,
size
:
data
?
.
count
??
0
,
releaseData
:
dataProviderReleaseDataCallback
)
pdfDocument
=
CGPDFDocument
(
dataProvider
!
)
let
controller
=
UIPrintInteractionController
.
shared
controller
.
delegate
=
self
let
printInfo
=
UIPrintInfo
.
printInfo
()
printInfo
.
jobName
=
jobName
!
printInfo
.
outputType
=
.
general
if
orientation
!=
nil
{
printInfo
.
orientation
=
orientation
!
orientation
=
nil
}
controller
.
printInfo
=
printInfo
controller
.
printPageRenderer
=
self
controller
.
present
(
animated
:
true
,
completionHandler
:
completionHandler
)
// Unblock the main thread
semaphore
.
signal
()
}
override
public
var
numberOfPages
:
Int
{
let
pages
=
pdfDocument
?
.
numberOfPages
??
0
return
pages
printing
.
onLayout
(
printJob
:
self
,
width
:
paperRect
.
size
.
width
,
height
:
paperRect
.
size
.
height
,
marginLeft
:
printableRect
.
origin
.
x
,
marginTop
:
printableRect
.
origin
.
y
,
marginRight
:
paperRect
.
size
.
width
-
(
printableRect
.
origin
.
x
+
printableRect
.
size
.
width
),
marginBottom
:
paperRect
.
size
.
height
-
(
printableRect
.
origin
.
y
+
printableRect
.
size
.
height
)
)
// Block the main thread, waiting for a document
semaphore
.
wait
()
return
pdfDocument
?
.
numberOfPages
??
0
}
func
completionHandler
(
printController
_
:
UIPrintInteractionController
,
completed
:
Bool
,
error
:
Error
?)
{
...
...
@@ -110,7 +112,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
controller
.
print
(
to
:
printer
,
completionHandler
:
completionHandler
)
}
func
printPdf
(
name
:
String
,
withPageSize
size
:
CGSize
,
andMargin
margin
:
CGRect
)
{
func
printPdf
(
name
:
String
,
withPageSize
size
:
CGSize
,
andMargin
_
:
CGRect
)
{
let
printing
=
UIPrintInteractionController
.
isPrintingAvailable
if
!
printing
{
self
.
printing
.
onCompleted
(
printJob
:
self
,
completed
:
false
,
error
:
"Printing not available"
)
...
...
@@ -123,15 +125,21 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
jobName
=
name
self
.
printing
.
onLayout
(
printJob
:
self
,
width
:
size
.
width
,
height
:
size
.
height
,
marginLeft
:
margin
.
minX
,
marginTop
:
margin
.
minY
,
marginRight
:
size
.
width
-
margin
.
maxX
,
marginBottom
:
size
.
height
-
margin
.
maxY
)
let
controller
=
UIPrintInteractionController
.
shared
controller
.
delegate
=
self
let
printInfo
=
UIPrintInfo
.
printInfo
()
printInfo
.
jobName
=
jobName
!
printInfo
.
outputType
=
.
general
if
orientation
!=
nil
{
printInfo
.
orientation
=
orientation
!
orientation
=
nil
}
controller
.
printInfo
=
printInfo
controller
.
showsPaperSelectionForLoadedPapers
=
true
controller
.
printPageRenderer
=
self
controller
.
present
(
animated
:
true
,
completionHandler
:
completionHandler
)
}
static
func
sharePdf
(
data
:
Data
,
withSourceRect
rect
:
CGRect
,
andName
name
:
String
)
{
...
...
@@ -287,7 +295,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
public
static
func
printingInfo
()
->
NSDictionary
{
let
data
:
NSDictionary
=
[
"directPrint"
:
true
,
"dynamicLayout"
:
fals
e
,
"dynamicLayout"
:
tru
e
,
"canPrint"
:
true
,
"canConvertHtml"
:
true
,
"canShare"
:
true
,
...
...
printing/ios/Classes/PrintingPlugin.swift
View file @
81634e1
...
...
@@ -17,12 +17,29 @@
import
Flutter
import
Foundation
// Dart:ffi API
private
var
_printingPlugin
:
PrintingPlugin
?
@_cdecl("net_nfet_printing_set_document")
func
setDocument
(
job
:
UInt32
,
doc
:
UnsafePointer
<
UInt8
>
,
size
:
UInt64
)
{
_printingPlugin
!.
jobs
[
job
]?
.
setDocument
(
Data
(
bytes
:
doc
,
count
:
Int
(
size
)))
}
@_cdecl("net_nfet_printing_set_error")
func
setError
(
job
:
UInt32
,
message
:
UnsafePointer
<
CChar
>
)
{
_printingPlugin
!.
jobs
[
job
]?
.
cancelJob
(
String
(
cString
:
message
))
}
// End of Dart:ffi API
public
class
PrintingPlugin
:
NSObject
,
FlutterPlugin
{
private
var
channel
:
FlutterMethodChannel
public
var
jobs
=
[
UInt32
:
PrintJob
]()
init
(
_
channel
:
FlutterMethodChannel
)
{
self
.
channel
=
channel
super
.
init
()
_printingPlugin
=
self
}
/// Entry point
...
...
@@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
let
marginRight
=
CGFloat
((
args
[
"marginRight"
]
as?
NSNumber
)?
.
floatValue
??
0.0
)
let
marginBottom
=
CGFloat
((
args
[
"marginBottom"
]
as?
NSNumber
)?
.
floatValue
??
0.0
)
let
printJob
=
PrintJob
(
printing
:
self
,
index
:
args
[
"job"
]
as!
Int
)
jobs
[
args
[
"job"
]
as!
UInt32
]
=
printJob
printJob
.
printPdf
(
name
:
name
,
withPageSize
:
CGSize
(
width
:
width
,
...
...
@@ -137,19 +155,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job"
:
printJob
.
index
,
]
as
[
String
:
Any
]
channel
.
invokeMethod
(
"onLayout"
,
arguments
:
arg
,
result
:
{
(
result
:
Any
?)
->
Void
in
if
result
as?
Bool
==
false
{
printJob
.
cancelJob
(
nil
)
}
else
if
result
is
FlutterError
{
let
error
=
result
as!
FlutterError
printJob
.
cancelJob
(
error
.
message
)
}
else
if
result
is
FlutterStandardTypedData
{
let
object
=
result
as!
FlutterStandardTypedData
printJob
.
setDocument
(
object
.
data
)
}
else
{
printJob
.
cancelJob
(
"Unknown data type"
)
}
})
channel
.
invokeMethod
(
"onLayout"
,
arguments
:
arg
)
}
/// send completion status to flutter
...
...
@@ -160,6 +166,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job"
:
printJob
.
index
,
]
channel
.
invokeMethod
(
"onCompleted"
,
arguments
:
data
)
jobs
.
removeValue
(
forKey
:
UInt32
(
printJob
.
index
))
}
/// send html to pdf data result to flutter
...
...
printing/lib/src/method_channel.dart
View file @
81634e1
...
...
@@ -15,11 +15,13 @@
*/
import
'dart:async'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'package:flutter/rendering.dart'
show
Rect
;
import
'package:flutter/services.dart'
;
import
'package:pdf/pdf.dart'
;
import
'package:printing/src/method_channel_ffi.dart'
;
import
'callback.dart'
;
import
'interface.dart'
;
...
...
@@ -56,7 +58,20 @@ class MethodChannelPrinting extends PrintingPlatform {
marginBottom:
call
.
arguments
[
'marginBottom'
],
);
final
bytes
=
await
job
.
onLayout
!(
format
);
Uint8List
bytes
;
try
{
bytes
=
await
job
.
onLayout
!(
format
);
}
catch
(
e
)
{
if
(
Platform
.
isMacOS
||
Platform
.
isIOS
)
{
return
setErrorFfi
(
job
,
e
.
toString
());
}
rethrow
;
}
if
(
Platform
.
isMacOS
||
Platform
.
isIOS
)
{
return
setDocumentFfi
(
job
,
bytes
);
}
return
Uint8List
.
fromList
(
bytes
);
case
'onCompleted'
:
...
...
printing/lib/src/method_channel_ffi.dart
0 → 100644
View file @
81634e1
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
'dart:ffi'
as
ffi
;
import
'dart:io'
as
io
;
import
'dart:typed_data'
;
import
'package:ffi/ffi.dart'
as
ffi
;
import
'print_job.dart'
;
/// Load the dynamic library
final
ffi
.
DynamicLibrary
_dynamicLibrary
=
_open
();
ffi
.
DynamicLibrary
_open
(
)
{
if
(
io
.
Platform
.
isMacOS
||
io
.
Platform
.
isIOS
)
{
return
ffi
.
DynamicLibrary
.
process
();
}
throw
UnsupportedError
(
'This platform is not supported.'
);
}
/// Set the Pdf document data
void
setDocumentFfi
(
PrintJob
job
,
Uint8List
data
)
{
final
nativeBytes
=
ffi
.
allocate
<
ffi
.
Uint8
>(
count:
data
.
length
);
nativeBytes
.
asTypedList
(
data
.
length
).
setAll
(
0
,
data
);
_setDocument
(
job
.
index
,
nativeBytes
,
data
.
length
);
}
final
_SetDocument_Dart
_setDocument
=
_dynamicLibrary
.
lookupFunction
<
_SetDocument_C
,
_SetDocument_Dart
>(
'net_nfet_printing_set_document'
,
);
typedef
_SetDocument_C
=
ffi
.
Void
Function
(
ffi
.
Uint32
job
,
ffi
.
Pointer
<
ffi
.
Uint8
>
data
,
ffi
.
Uint64
size
,
);
typedef
_SetDocument_Dart
=
void
Function
(
int
job
,
ffi
.
Pointer
<
ffi
.
Uint8
>
data
,
int
size
,
);
/// Set the Pdf Error message
void
setErrorFfi
(
PrintJob
job
,
String
message
)
{
_setError
(
job
.
index
,
ffi
.
Utf8
.
toUtf8
(
message
));
}
final
_SetError_Dart
_setError
=
_dynamicLibrary
.
lookupFunction
<
_SetError_C
,
_SetError_Dart
>(
'net_nfet_printing_set_error'
,
);
typedef
_SetError_C
=
ffi
.
Void
Function
(
ffi
.
Uint32
job
,
ffi
.
Pointer
<
ffi
.
Utf8
>
message
,
);
typedef
_SetError_Dart
=
void
Function
(
int
job
,
ffi
.
Pointer
<
ffi
.
Utf8
>
message
,
);
...
...
printing/macos/Classes/PrintJob.swift
View file @
81634e1
...
...
@@ -29,6 +29,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
private
var
printOperation
:
NSPrintOperation
?
private
var
pdfDocument
:
CGPDFDocument
?
private
var
page
:
CGPDFPage
?
private
let
semaphore
=
DispatchSemaphore
(
value
:
0
)
public
init
(
printing
:
PrintingPlugin
,
index
:
Int
)
{
self
.
printing
=
printing
...
...
@@ -47,7 +48,29 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
setFrameSize
(
size
)
setBoundsSize
(
size
)
range
.
pointee
.
length
=
pdfDocument
?
.
numberOfPages
??
0
printing
.
onLayout
(
printJob
:
self
,
width
:
printOperation
!.
printInfo
.
paperSize
.
width
,
height
:
printOperation
!.
printInfo
.
paperSize
.
height
,
marginLeft
:
printOperation
!.
printInfo
.
leftMargin
,
marginTop
:
printOperation
!.
printInfo
.
topMargin
,
marginRight
:
printOperation
!.
printInfo
.
rightMargin
,
marginBottom
:
printOperation
!.
printInfo
.
bottomMargin
)
// Block the main thread, waiting for a document
semaphore
.
wait
()
if
pdfDocument
!=
nil
{
range
.
pointee
.
length
=
pdfDocument
!.
numberOfPages
let
page
=
pdfDocument
!.
page
(
at
:
1
)
let
size
=
page
?
.
getBoxRect
(
CGPDFBox
.
mediaBox
)
??
NSZeroRect
setFrameSize
(
size
.
size
)
setBoundsSize
(
size
.
size
)
}
else
{
range
.
pointee
.
length
=
0
}
return
true
}
...
...
@@ -67,8 +90,8 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
let
dataProvider
=
CGDataProvider
(
dataInfo
:
nil
,
data
:
bytesPointer
,
size
:
data
?
.
count
??
0
,
releaseData
:
dataProviderReleaseDataCallback
)
pdfDocument
=
CGPDFDocument
(
dataProvider
!
)
let
window
=
NSApplication
.
shared
.
mainWindow
!
printOperation
!.
runModal
(
for
:
window
,
delegate
:
self
,
didRun
:
#selector(
printOperationDidRun(printOperation:success:contextInfo:)
)
,
contextInfo
:
nil
)
// Unblock the main thread
semaphore
.
signal
()
}
override
public
func
draw
(
_
:
NSRect
)
{
...
...
@@ -136,21 +159,15 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
// Print the custom view
printOperation
=
NSPrintOperation
(
view
:
self
,
printInfo
:
printInfo
)
printOperation
!.
jobTitle
=
name
printOperation
!.
printPanel
.
options
=
[
.
showsPreview
]
printOperation
!.
printPanel
.
options
=
[
.
showsPreview
,
.
showsPaperSize
,
.
showsOrientation
]
printing
.
onLayout
(
printJob
:
self
,
width
:
printOperation
!.
printInfo
.
paperSize
.
width
,
height
:
printOperation
!.
printInfo
.
paperSize
.
height
,
marginLeft
:
printOperation
!.
printInfo
.
leftMargin
,
marginTop
:
printOperation
!.
printInfo
.
topMargin
,
marginRight
:
printOperation
!.
printInfo
.
rightMargin
,
marginBottom
:
printOperation
!.
printInfo
.
bottomMargin
)
let
window
=
NSApplication
.
shared
.
mainWindow
!
printOperation
!.
runModal
(
for
:
window
,
delegate
:
self
,
didRun
:
#selector(
printOperationDidRun(printOperation:success:contextInfo:)
)
,
contextInfo
:
nil
)
}
func
cancelJob
(
_
error
:
String
?)
{
printing
.
onCompleted
(
printJob
:
self
,
completed
:
false
,
error
:
error
as
NSString
?)
func
cancelJob
(
_
:
String
?)
{
pdfDocument
=
nil
semaphore
.
signal
()
}
public
static
func
sharePdf
(
data
:
Data
,
withSourceRect
rect
:
CGRect
,
andName
name
:
String
)
{
...
...
printing/macos/Classes/PrintingPlugin.swift
View file @
81634e1
...
...
@@ -17,12 +17,29 @@
import
FlutterMacOS
import
Foundation
// Dart:ffi API
private
var
_printingPlugin
:
PrintingPlugin
?
@_cdecl("net_nfet_printing_set_document")
func
setDocument
(
job
:
UInt32
,
doc
:
UnsafePointer
<
UInt8
>
,
size
:
UInt64
)
{
_printingPlugin
!.
jobs
[
job
]?
.
setDocument
(
Data
(
bytes
:
doc
,
count
:
Int
(
size
)))
}
@_cdecl("net_nfet_printing_set_error")
func
setError
(
job
:
UInt32
,
message
:
UnsafePointer
<
CChar
>
)
{
_printingPlugin
!.
jobs
[
job
]?
.
cancelJob
(
String
(
cString
:
message
))
}
// End of Dart:ffi API
public
class
PrintingPlugin
:
NSObject
,
FlutterPlugin
{
private
var
channel
:
FlutterMethodChannel
public
var
jobs
=
[
UInt32
:
PrintJob
]()
init
(
_
channel
:
FlutterMethodChannel
)
{
self
.
channel
=
channel
super
.
init
()
_printingPlugin
=
self
}
/// Entry point
...
...
@@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
let
marginRight
=
CGFloat
((
args
[
"marginRight"
]
as?
NSNumber
)?
.
floatValue
??
0.0
)
let
marginBottom
=
CGFloat
((
args
[
"marginBottom"
]
as?
NSNumber
)?
.
floatValue
??
0.0
)
let
printJob
=
PrintJob
(
printing
:
self
,
index
:
args
[
"job"
]
as!
Int
)
jobs
[
args
[
"job"
]
as!
UInt32
]
=
printJob
printJob
.
printPdf
(
name
:
name
,
withPageSize
:
CGSize
(
width
:
width
,
...
...
@@ -108,13 +126,6 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
andBaseUrl
:
args
[
"baseUrl"
]
as?
String
==
nil
?
nil
:
URL
(
string
:
args
[
"baseUrl"
]
as!
String
)
)
result
(
NSNumber
(
value
:
1
))
// } else if call.method == "pickPrinter" {
// PrintJob.pickPrinter(result: result, withSourceRect: CGRect(
// x: CGFloat((args["x"] as? NSNumber)?.floatValue ?? 0.0),
// y: CGFloat((args["y"] as? NSNumber)?.floatValue ?? 0.0),
// width: CGFloat((args["w"] as? NSNumber)?.floatValue ?? 0.0),
// height: CGFloat((args["h"] as? NSNumber)?.floatValue ?? 0.0)
// ))
}
else
if
call
.
method
==
"printingInfo"
{
result
(
PrintJob
.
printingInfo
())
}
else
if
call
.
method
==
"rasterPdf"
{
...
...
@@ -143,19 +154,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job"
:
printJob
.
index
,
]
as
[
String
:
Any
]
channel
.
invokeMethod
(
"onLayout"
,
arguments
:
arg
,
result
:
{
(
result
:
Any
?)
->
Void
in
if
result
as?
Bool
==
false
{
printJob
.
cancelJob
(
nil
)
}
else
if
result
is
FlutterError
{
let
error
=
result
as!
FlutterError
printJob
.
cancelJob
(
error
.
message
)
}
else
if
result
is
FlutterStandardTypedData
{
let
object
=
result
as!
FlutterStandardTypedData
printJob
.
setDocument
(
object
.
data
)
}
else
{
printJob
.
cancelJob
(
"Unknown data type"
)
}
})
channel
.
invokeMethod
(
"onLayout"
,
arguments
:
arg
)
}
/// send completion status to flutter
...
...
@@ -166,6 +165,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job"
:
printJob
.
index
,
]
channel
.
invokeMethod
(
"onCompleted"
,
arguments
:
data
)
jobs
.
removeValue
(
forKey
:
UInt32
(
printJob
.
index
))
}
/// send html to pdf data result to flutter
...
...
printing/pubspec.yaml
View file @
81634e1
...
...
@@ -11,6 +11,7 @@ environment:
flutter
:
"
>=1.16.0"
dependencies
:
ffi
:
"
>=0.2.0-nullsafety
<2.0.0"
flutter
:
sdk
:
flutter
flutter_web_plugins
:
...
...
Please
register
or
login
to post a comment