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
2020-04-24 18:48:32 -0400
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
5b3957484ac3f4c57fdafee8468e362ff5a2061f
5b395748
1 parent
a54788f7
Add Gradient decoration
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
398 additions
and
23 deletions
pdf/CHANGELOG.md
pdf/lib/src/function.dart
pdf/lib/src/object_stream.dart
pdf/lib/src/shading.dart
pdf/lib/widgets/decoration.dart
pdf/lib/widgets/geometry.dart
pdf/pubspec.yaml
pdf/test/widget_container_test.dart
test/golden/widgets-container.pdf
pdf/CHANGELOG.md
View file @
5b39574
# Changelog
## 1.7.0
-
Implement Linear and Radial gradients in BoxDecoration
## 1.6.2
-
Use the Barcode library to generate QR-Codes
...
...
pdf/lib/src/function.dart
View file @
5b39574
...
...
@@ -18,7 +18,11 @@
part of
pdf
;
class
PdfFunction
extends
PdfObjectStream
{
abstract
class
PdfBaseFunction
extends
PdfObject
{
PdfBaseFunction
(
PdfDocument
pdfDocument
)
:
super
(
pdfDocument
);
}
class
PdfFunction
extends
PdfObjectStream
implements
PdfBaseFunction
{
PdfFunction
(
PdfDocument
pdfDocument
,
{
this
.
colors
,
...
...
@@ -43,6 +47,39 @@ class PdfFunction extends PdfObjectStream {
params
[
'/Order'
]
=
const
PdfNum
(
3
);
params
[
'/Domain'
]
=
PdfArray
.
fromNum
(
const
<
num
>[
0
,
1
]);
params
[
'/Range'
]
=
PdfArray
.
fromNum
(
const
<
num
>[
0
,
1
,
0
,
1
,
0
,
1
]);
params
[
'/Size'
]
=
PdfNum
(
colors
.
length
);
params
[
'/Size'
]
=
PdfArray
.
fromNum
(<
int
>[
colors
.
length
]);
}
}
class
PdfStitchingFunction
extends
PdfBaseFunction
{
PdfStitchingFunction
(
PdfDocument
pdfDocument
,
{
@required
this
.
functions
,
@required
this
.
bounds
,
this
.
domainStart
=
0
,
this
.
domainEnd
=
1
,
})
:
assert
(
functions
!=
null
),
assert
(
bounds
!=
null
),
super
(
pdfDocument
);
final
List
<
PdfFunction
>
functions
;
final
List
<
double
>
bounds
;
final
double
domainStart
;
final
double
domainEnd
;
@override
void
_prepare
()
{
super
.
_prepare
();
params
[
'/FunctionType'
]
=
const
PdfNum
(
3
);
params
[
'/Functions'
]
=
PdfArray
.
fromObjects
(
functions
);
params
[
'/Order'
]
=
const
PdfNum
(
3
);
params
[
'/Domain'
]
=
PdfArray
.
fromNum
(<
num
>[
domainStart
,
domainEnd
]);
params
[
'/Bounds'
]
=
PdfArray
.
fromNum
(
bounds
);
params
[
'/Encode'
]
=
PdfArray
.
fromNum
(
List
<
int
>.
generate
(
functions
.
length
*
2
,
(
int
i
)
=>
i
%
2
));
}
}
...
...
pdf/lib/src/object_stream.dart
View file @
5b39574
...
...
@@ -45,16 +45,24 @@ class PdfObjectStream extends PdfObject {
// The data is already in the right format
_data
=
buf
.
output
();
}
else
if
(
pdfDocument
.
deflate
!=
null
)
{
_data
=
pdfDocument
.
deflate
(
buf
.
output
());
params
[
'/Filter'
]
=
const
PdfName
(
'/FlateDecode'
);
}
else
if
(
isBinary
)
{
// This is a Ascii85 stream
final
Ascii85Encoder
e
=
Ascii85Encoder
();
_data
=
e
.
convert
(
buf
.
output
());
params
[
'/Filter'
]
=
const
PdfName
(
'/ASCII85Decode'
);
}
else
{
// This is a non-deflated stream
_data
=
buf
.
output
();
final
Uint8List
original
=
buf
.
output
();
final
Uint8List
newData
=
pdfDocument
.
deflate
(
original
);
if
(
newData
.
lengthInBytes
<
original
.
lengthInBytes
)
{
params
[
'/Filter'
]
=
const
PdfName
(
'/FlateDecode'
);
_data
=
newData
;
}
}
if
(
_data
==
null
)
{
if
(
isBinary
)
{
// This is a Ascii85 stream
final
Ascii85Encoder
e
=
Ascii85Encoder
();
_data
=
e
.
convert
(
buf
.
output
());
params
[
'/Filter'
]
=
const
PdfName
(
'/ASCII85Decode'
);
}
else
{
// This is a non-deflated stream
_data
=
buf
.
output
();
}
}
if
(
pdfDocument
.
encryption
!=
null
)
{
_data
=
pdfDocument
.
encryption
.
encrypt
(
_data
,
this
);
...
...
pdf/lib/src/shading.dart
View file @
5b39574
...
...
@@ -18,7 +18,7 @@
part of
pdf
;
enum
PdfShadingType
{
function
,
axial
,
radial
}
enum
PdfShadingType
{
axial
,
radial
}
class
PdfShading
extends
PdfObject
{
PdfShading
(
...
...
@@ -27,10 +27,17 @@ class PdfShading extends PdfObject {
@required
this
.
function
,
@required
this
.
start
,
@required
this
.
end
,
this
.
radius0
,
this
.
radius1
,
this
.
boundingBox
,
this
.
extendStart
=
false
,
this
.
extendEnd
=
false
,
})
:
assert
(
shadingType
!=
null
),
assert
(
function
!=
null
),
assert
(
start
!=
null
),
assert
(
end
!=
null
),
assert
(
extendStart
!=
null
),
assert
(
extendEnd
!=
null
),
super
(
pdfDocument
);
/// Name of the Shading object
...
...
@@ -38,23 +45,52 @@ class PdfShading extends PdfObject {
final
PdfShadingType
shadingType
;
final
PdfFunction
function
;
final
Pdf
Base
Function
function
;
final
PdfPoint
start
;
final
PdfPoint
end
;
final
PdfRect
boundingBox
;
final
bool
extendStart
;
final
bool
extendEnd
;
final
double
radius0
;
final
double
radius1
;
@override
void
_prepare
()
{
super
.
_prepare
();
params
[
'/ShadingType'
]
=
PdfNum
(
shadingType
.
index
+
1
);
params
[
'/ShadingType'
]
=
PdfNum
(
shadingType
.
index
+
2
);
if
(
boundingBox
!=
null
)
{
params
[
'/BBox'
]
=
PdfArray
.
fromNum
(<
double
>[
boundingBox
.
left
,
boundingBox
.
bottom
,
boundingBox
.
right
,
boundingBox
.
top
,
]);
}
params
[
'/AntiAlias'
]
=
const
PdfBool
(
true
);
params
[
'/ColorSpace'
]
=
const
PdfName
(
'/DeviceRGB'
);
params
[
'/Coords'
]
=
PdfArray
.
fromNum
(<
double
>[
start
.
x
,
start
.
y
,
end
.
x
,
end
.
y
]);
params
[
'/Domain'
]
=
PdfArray
.
fromNum
(<
num
>[
0
,
1
]);
params
[
'/Extend'
]
=
PdfArray
(
const
<
PdfBool
>[
PdfBool
(
true
),
PdfBool
(
true
)]);
if
(
shadingType
==
PdfShadingType
.
axial
)
{
params
[
'/Coords'
]
=
PdfArray
.
fromNum
(<
double
>[
start
.
x
,
start
.
y
,
end
.
x
,
end
.
y
]);
}
else
if
(
shadingType
==
PdfShadingType
.
radial
)
{
assert
(
radius0
!=
null
);
assert
(
radius1
!=
null
);
params
[
'/Coords'
]
=
PdfArray
.
fromNum
(
<
double
>[
start
.
x
,
start
.
y
,
radius0
,
end
.
x
,
end
.
y
,
radius1
]);
}
// params['/Domain'] = PdfArray.fromNum(<num>[0, 1]);
if
(
extendStart
||
extendEnd
)
{
params
[
'/Extend'
]
=
PdfArray
(<
PdfBool
>[
PdfBool
(
extendStart
),
PdfBool
(
extendEnd
)]);
}
params
[
'/Function'
]
=
function
.
ref
();
}
}
...
...
pdf/lib/widgets/decoration.dart
View file @
5b39574
...
...
@@ -155,6 +155,198 @@ class DecorationImage {
}
}
/// Defines what happens at the edge of the gradient.
enum
TileMode
{
/// Edge is clamped to the final color.
clamp
,
/// Edge is repeated from first color to last.
// repeated,
/// Edge is mirrored from last color to first.
// mirror,
}
/// A 2D gradient.
@immutable
abstract
class
Gradient
{
/// Initialize the gradient's colors and stops.
const
Gradient
({
@required
this
.
colors
,
this
.
stops
,
})
:
assert
(
colors
!=
null
);
final
List
<
PdfColor
>
colors
;
/// A list of values from 0.0 to 1.0 that denote fractions along the gradient.
final
List
<
double
>
stops
;
PdfBaseFunction
_buildFunction
(
Context
context
,
List
<
PdfColor
>
colors
,
List
<
double
>
stops
,
)
{
if
(
stops
==
null
)
{
return
PdfFunction
(
context
.
document
,
colors:
colors
,
);
}
final
List
<
PdfFunction
>
fn
=
<
PdfFunction
>[];
PdfColor
lc
=
colors
.
first
;
for
(
final
PdfColor
c
in
colors
.
sublist
(
1
))
{
fn
.
add
(
PdfFunction
(
context
.
document
,
colors:
<
PdfColor
>[
lc
,
c
],
));
lc
=
c
;
}
return
PdfStitchingFunction
(
context
.
document
,
functions:
fn
,
bounds:
stops
.
sublist
(
1
,
stops
.
length
-
1
),
domainStart:
stops
.
first
,
domainEnd:
stops
.
last
,
);
}
void
paint
(
Context
context
,
PdfRect
box
);
}
/// A 2D linear gradient.
class
LinearGradient
extends
Gradient
{
/// Creates a linear gradient.
const
LinearGradient
({
this
.
begin
=
Alignment
.
centerLeft
,
this
.
end
=
Alignment
.
centerRight
,
@required
List
<
PdfColor
>
colors
,
List
<
double
>
stops
,
this
.
tileMode
=
TileMode
.
clamp
,
})
:
assert
(
begin
!=
null
),
assert
(
end
!=
null
),
assert
(
tileMode
!=
null
),
super
(
colors:
colors
,
stops:
stops
);
/// The offset at which stop 0.0 of the gradient is placed.
final
Alignment
begin
;
/// The offset at which stop 1.0 of the gradient is placed.
final
Alignment
end
;
/// How this gradient should tile the plane beyond in the region before
final
TileMode
tileMode
;
@override
void
paint
(
Context
context
,
PdfRect
box
)
{
if
(
colors
.
isEmpty
)
{
return
;
}
if
(
colors
.
length
==
1
)
{
context
.
canvas
..
setFillColor
(
colors
.
first
)
..
fillPath
();
}
assert
(
stops
==
null
||
stops
.
length
==
colors
.
length
);
context
.
canvas
..
saveContext
()
..
clipPath
()
..
applyShader
(
PdfShading
(
context
.
document
,
shadingType:
PdfShadingType
.
axial
,
boundingBox:
box
,
function:
_buildFunction
(
context
,
colors
,
stops
),
start:
begin
.
withinRect
(
box
),
end:
end
.
withinRect
(
box
),
extendStart:
true
,
extendEnd:
true
,
),
)
..
restoreContext
();
}
}
/// A 2D radial gradient.
class
RadialGradient
extends
Gradient
{
/// Creates a radial gradient.
///
/// The [colors] argument must not be null. If [stops] is non-null, it must
/// have the same length as [colors].
const
RadialGradient
({
this
.
center
=
Alignment
.
center
,
this
.
radius
=
0.5
,
@required
List
<
PdfColor
>
colors
,
List
<
double
>
stops
,
this
.
tileMode
=
TileMode
.
clamp
,
this
.
focal
,
this
.
focalRadius
=
0.0
,
})
:
assert
(
center
!=
null
),
assert
(
radius
!=
null
),
assert
(
tileMode
!=
null
),
assert
(
focalRadius
!=
null
),
super
(
colors:
colors
,
stops:
stops
);
/// The center of the gradient
final
Alignment
center
;
/// The radius of the gradient
final
double
radius
;
/// How this gradient should tile the plane beyond the outer ring at [radius]
/// pixels from the [center].
final
TileMode
tileMode
;
/// The focal point of the gradient.
final
Alignment
focal
;
/// The radius of the focal point of the gradient.
final
double
focalRadius
;
@override
void
paint
(
Context
context
,
PdfRect
box
)
{
if
(
colors
.
isEmpty
)
{
return
;
}
if
(
colors
.
length
==
1
)
{
context
.
canvas
..
setFillColor
(
colors
.
first
)
..
fillPath
();
}
assert
(
stops
==
null
||
stops
.
length
==
colors
.
length
);
final
Alignment
_focal
=
focal
??
center
;
final
double
_radius
=
math
.
min
(
box
.
width
,
box
.
height
);
context
.
canvas
..
saveContext
()
..
clipPath
()
..
applyShader
(
PdfShading
(
context
.
document
,
shadingType:
PdfShadingType
.
radial
,
boundingBox:
box
,
function:
_buildFunction
(
context
,
colors
,
stops
),
start:
_focal
.
withinRect
(
box
),
end:
center
.
withinRect
(
box
),
radius0:
focalRadius
*
_radius
,
radius1:
radius
*
_radius
,
extendStart:
true
,
extendEnd:
true
,
),
)
..
restoreContext
();
}
}
enum
BoxShape
{
circle
,
rectangle
}
@immutable
...
...
@@ -163,6 +355,7 @@ class BoxDecoration {
{
this
.
color
,
this
.
border
,
this
.
borderRadius
,
this
.
gradient
,
this
.
image
,
this
.
shape
=
BoxShape
.
rectangle
})
:
assert
(
shape
!=
null
);
...
...
@@ -173,6 +366,7 @@ class BoxDecoration {
final
double
borderRadius
;
final
BoxShape
shape
;
final
DecorationImage
image
;
final
Gradient
gradient
;
void
paint
(
Context
context
,
PdfRect
box
)
{
assert
(
box
.
x
!=
null
);
...
...
@@ -200,6 +394,25 @@ class BoxDecoration {
..
fillPath
();
}
if
(
gradient
!=
null
)
{
switch
(
shape
)
{
case
BoxShape
.
rectangle
:
if
(
borderRadius
==
null
)
{
context
.
canvas
.
drawRect
(
box
.
x
,
box
.
y
,
box
.
width
,
box
.
height
);
}
else
{
context
.
canvas
.
drawRRect
(
box
.
x
,
box
.
y
,
box
.
width
,
box
.
height
,
borderRadius
,
borderRadius
);
}
break
;
case
BoxShape
.
circle
:
context
.
canvas
.
drawEllipse
(
box
.
x
+
box
.
width
/
2.0
,
box
.
y
+
box
.
height
/
2.0
,
box
.
width
/
2.0
,
box
.
height
/
2.0
);
break
;
}
gradient
.
paint
(
context
,
box
);
}
if
(
image
!=
null
)
{
context
.
canvas
.
saveContext
();
switch
(
shape
)
{
...
...
pdf/lib/widgets/geometry.dart
View file @
5b39574
...
...
@@ -332,7 +332,7 @@ class Alignment {
final
double
halfHeight
=
rect
.
height
/
2.0
;
return
PdfPoint
(
rect
.
left
+
halfWidth
+
x
*
halfWidth
,
rect
.
top
+
halfHeight
+
y
*
halfHeight
,
rect
.
bottom
+
halfHeight
+
y
*
halfHeight
,
);
}
...
...
@@ -353,6 +353,16 @@ class Alignment {
String
toString
()
=>
'(
$x
,
$y
)'
;
}
/// An offset that's expressed as a fraction of a [PdfPoint].
@immutable
class
FractionalOffset
extends
Alignment
{
/// Creates a fractional offset.
const
FractionalOffset
(
double
dx
,
double
dy
)
:
assert
(
dx
!=
null
),
assert
(
dy
!=
null
),
super
(
dx
*
2
-
1
,
1
-
dy
*
2
);
}
/// The pair of sizes returned by [applyBoxFit].
@immutable
class
FittedSizes
{
...
...
pdf/pubspec.yaml
View file @
5b39574
...
...
@@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl
homepage
:
https://github.com/DavBfr/dart_pdf/tree/master/pdf
repository
:
https://github.com/DavBfr/dart_pdf
issue_tracker
:
https://github.com/DavBfr/dart_pdf/issues
version
:
1.
6.2
version
:
1.
7.0
environment
:
sdk
:
"
>=2.3.0
<3.0.0"
...
...
pdf/test/widget_container_test.dart
View file @
5b39574
...
...
@@ -158,6 +158,73 @@ void main() {
));
});
test
(
'Container Widgets LinearGradient'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Container
(
alignment:
Alignment
.
center
,
margin:
const
EdgeInsets
.
all
(
30
),
padding:
const
EdgeInsets
.
all
(
20
),
decoration:
const
BoxDecoration
(
borderRadius:
20
,
gradient:
LinearGradient
(
colors:
<
PdfColor
>[
PdfColors
.
blue
,
PdfColors
.
red
,
PdfColors
.
yellow
,
],
begin:
Alignment
.
bottomLeft
,
end:
Alignment
.
topRight
,
stops:
<
double
>[
0
,
.
8
,
1.0
],
tileMode:
TileMode
.
clamp
,
),
border:
BoxBorder
(
color:
PdfColors
.
blue800
,
top:
true
,
left:
true
,
right:
true
,
bottom:
true
,
width:
2
,
)),
width:
200
,
height:
400
,
),
));
});
test
(
'Container Widgets RadialGradient'
,
()
{
pdf
.
addPage
(
Page
(
build:
(
Context
context
)
=>
Container
(
alignment:
Alignment
.
center
,
margin:
const
EdgeInsets
.
all
(
30
),
padding:
const
EdgeInsets
.
all
(
20
),
decoration:
const
BoxDecoration
(
borderRadius:
20
,
gradient:
RadialGradient
(
colors:
<
PdfColor
>[
PdfColors
.
blue
,
PdfColors
.
red
,
PdfColors
.
yellow
,
],
stops:
<
double
>[
0.0
,
.
2
,
1.0
],
center:
FractionalOffset
(.
7
,
.
2
),
focal:
FractionalOffset
(.
7
,
.
45
),
focalRadius:
1
,
),
border:
BoxBorder
(
color:
PdfColors
.
blue800
,
top:
true
,
left:
true
,
right:
true
,
bottom:
true
,
width:
2
,
)),
width:
200
,
height:
400
,
// child: Placeholder(),
),
));
});
tearDownAll
(()
{
final
File
file
=
File
(
'widgets-container.pdf'
);
file
.
writeAsBytesSync
(
pdf
.
save
());
...
...
test/golden/widgets-container.pdf
View file @
5b39574
No preview for this file type
Please
register
or
login
to post a comment