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
2019-01-27 11:28:38 -0500
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
bd8bc15617e01c34a49b75421637a08f459a6158
bd8bc156
1 parent
ca2ef029
Add arcs to SVG drawShape
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
179 additions
and
8 deletions
pdf/CHANGELOG.md
pdf/lib/pdf.dart
pdf/lib/src/graphics.dart
pdf/test/complex_test.dart
pdf/CHANGELOG.md
View file @
bd8bc15
...
...
@@ -2,6 +2,7 @@
*
Improve PdfPoint and PdfRect
*
Change PdfColor.fromInt to const constructor
*
Fix drawShape Bézier curves
*
Add arcs to SVG drawShape
# 1.1.0
*
Rename classes to satisfy Dart conventions
...
...
pdf/lib/pdf.dart
View file @
bd8bc15
...
...
@@ -20,6 +20,7 @@ library pdf;
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
;
import
'package:utf/utf.dart'
;
...
...
pdf/lib/src/graphics.dart
View file @
bd8bc15
...
...
@@ -215,13 +215,150 @@ class PdfGraphics {
buf
.
putString
(
" m
\n
"
);
}
/// Draw a bézier curve
/// Draw a cubic bézier curve from the current point to (x3,y3)
/// using (x1,y1) as the control point at the beginning of the curve
/// and (x2,y2) as the control point at the end of the curve.
///
/// @param x1 first control point
/// @param y1 first control point
/// @param x2 second control point
/// @param y2 second control point
/// @param x3 end point
/// @param y3 end point
void
curveTo
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
x3
,
double
y3
)
{
buf
.
putNumList
(<
double
>[
x1
,
y1
,
x2
,
y2
,
x3
,
y3
]);
buf
.
putString
(
" c
\n
"
);
}
double
_vectorAngle
(
double
ux
,
double
uy
,
double
vx
,
double
vy
)
{
final
d
=
math
.
sqrt
(
ux
*
ux
+
uy
*
uy
)
*
math
.
sqrt
(
vx
*
vx
+
vy
*
vy
);
if
(
d
==
0.0
)
return
0.0
;
var
c
=
(
ux
*
vx
+
uy
*
vy
)
/
d
;
if
(
c
<
-
1.0
)
{
c
=
-
1.0
;
}
else
if
(
c
>
1.0
)
c
=
1.0
;
final
s
=
ux
*
vy
-
uy
*
vx
;
c
=
math
.
acos
(
c
);
return
c
.
sign
==
s
.
sign
?
c
:
-
c
;
}
void
_endToCenterParameters
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
bool
large
,
bool
sweep
,
double
rx
,
double
ry
)
{
// See http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes F.6.5
rx
=
rx
.
abs
();
ry
=
ry
.
abs
();
final
x1d
=
0.5
*
(
x1
-
x2
);
final
y1d
=
0.5
*
(
y1
-
y2
);
var
r
=
x1d
*
x1d
/
(
rx
*
rx
)
+
y1d
*
y1d
/
(
ry
*
ry
);
if
(
r
>
1.0
)
{
var
rr
=
math
.
sqrt
(
r
);
rx
*=
rr
;
ry
*=
rr
;
r
=
x1d
*
x1d
/
(
rx
*
rx
)
+
y1d
*
y1d
/
(
ry
*
ry
);
}
else
if
(
r
!=
0.0
)
r
=
1.0
/
r
-
1.0
;
if
(-
1
e
-
10
<
r
&&
r
<
0.0
)
r
=
0.0
;
r
=
math
.
sqrt
(
r
);
if
(
large
==
sweep
)
r
=
-
r
;
final
cxd
=
(
r
*
rx
*
y1d
)
/
ry
;
final
cyd
=
-(
r
*
ry
*
x1d
)
/
rx
;
final
cx
=
cxd
+
0.5
*
(
x1
+
x2
);
final
cy
=
cyd
+
0.5
*
(
y1
+
y2
);
final
theta
=
_vectorAngle
(
1.0
,
0.0
,
(
x1d
-
cxd
)
/
rx
,
(
y1d
-
cyd
)
/
ry
);
var
dTheta
=
_vectorAngle
((
x1d
-
cxd
)
/
rx
,
(
y1d
-
cyd
)
/
ry
,
(-
x1d
-
cxd
)
/
rx
,
(-
y1d
-
cyd
)
/
ry
)
%
(
math
.
pi
*
2.0
);
if
(
sweep
==
false
&&
dTheta
>
0.0
)
dTheta
-=
math
.
pi
*
2.0
;
else
if
(
sweep
==
true
&&
dTheta
<
0.0
)
dTheta
+=
math
.
pi
*
2.0
;
_bezierArcFromCentre
(
cx
,
cy
,
rx
,
ry
,
-
theta
,
-
dTheta
);
}
void
_bezierArcFromCentre
(
double
cx
,
double
cy
,
double
rx
,
double
ry
,
double
startAngle
,
double
extent
)
{
int
fragmentsCount
;
double
fragmentsAngle
;
if
(
extent
.
abs
()
<=
math
.
pi
/
2.0
)
{
fragmentsCount
=
1
;
fragmentsAngle
=
extent
;
}
else
{
fragmentsCount
=
(
extent
.
abs
()
/
(
math
.
pi
/
2.0
)).
ceil
().
toInt
();
fragmentsAngle
=
extent
/
fragmentsCount
.
toDouble
();
}
if
(
fragmentsAngle
==
0.0
)
{
return
;
}
final
halfFragment
=
fragmentsAngle
*
0.5
;
var
kappa
=
(
4.0
/
3.0
*
(
1.0
-
math
.
cos
(
halfFragment
))
/
math
.
sin
(
halfFragment
))
.
abs
();
if
(
fragmentsAngle
<
0.0
)
kappa
=
-
kappa
;
var
theta
=
startAngle
;
final
startFragment
=
theta
+
fragmentsAngle
;
var
c1
=
math
.
cos
(
theta
);
var
s1
=
math
.
sin
(
theta
);
for
(
var
i
=
0
;
i
<
fragmentsCount
;
i
++)
{
final
c0
=
c1
;
final
s0
=
s1
;
theta
=
startFragment
+
i
*
fragmentsAngle
;
c1
=
math
.
cos
(
theta
);
s1
=
math
.
sin
(
theta
);
curveTo
(
cx
+
rx
*
(
c0
-
kappa
*
s0
),
cy
-
ry
*
(
s0
+
kappa
*
c0
),
cx
+
rx
*
(
c1
+
kappa
*
s1
),
cy
-
ry
*
(
s1
-
kappa
*
c1
),
cx
+
rx
*
c1
,
cy
-
ry
*
s1
);
}
}
/// Draws an elliptical arc from (x1, y1) to (x2, y2).
/// The size and orientation of the ellipse are defined by two radii (rx, ry)
/// The center (cx, cy) of the ellipse is calculated automatically to satisfy
/// the constraints imposed by the other parameters. large and sweep flags
/// contribute to the automatic calculations and help determine how the arc is drawn.
void
_bezierArc
(
double
x1
,
double
y1
,
double
rx
,
double
ry
,
double
x2
,
double
y2
,
{
large
=
false
,
sweep
=
false
,
phi
=
0.0
})
{
if
(
x1
==
x2
&&
y1
==
y2
)
{
// From https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes:
// If the endpoints (x1, y1) and (x2, y2) are identical, then this is
// equivalent to omitting the elliptical arc segment entirely.
return
;
}
if
(
rx
.
abs
()
<=
1
e
-
10
||
ry
.
abs
()
<=
1
e
-
10
)
{
lineTo
(
x2
,
y2
);
return
;
}
if
(
phi
!=
0.0
)
{
// Our box bézier arcs can't handle rotations directly
// move to a well known point, eliminate phi and transform the other point
final
mat
=
Matrix4
.
identity
();
mat
.
translate
(-
x1
,
-
y1
);
mat
.
rotateZ
(-
phi
);
final
tr
=
mat
.
transform3
(
Vector3
(
x2
,
y2
,
0.0
));
_endToCenterParameters
(
0.0
,
0.0
,
tr
[
0
],
tr
[
1
],
large
,
sweep
,
rx
,
ry
);
}
else
{
_endToCenterParameters
(
x1
,
y1
,
x2
,
y2
,
large
,
sweep
,
rx
,
ry
);
}
}
/// https://github.com/deeplook/svglib/blob/master/svglib/svglib.py#L911
void
drawShape
(
String
d
,
{
stroke
=
true
})
{
final
exp
=
RegExp
(
r"([MmZzLlHhVvCcSsQqTtAaE])|(-[\.0-9]+)|([\.0-9]+)"
);
...
...
@@ -348,10 +485,32 @@ class PdfGraphics {
// break;
// case 't': // quadratic bezier, relative
// break;
// case 'A': // elliptical arc, absolute
// break;
// case 'a': // elliptical arc, relative
// break;
case
'A'
:
// elliptical arc, absolute
var
len
=
0
;
while
(
len
<
points
.
length
)
{
_bezierArc
(
lastPoint
.
x
,
lastPoint
.
y
,
points
[
len
+
0
],
points
[
len
+
1
],
points
[
len
+
5
],
points
[
len
+
6
],
phi:
points
[
len
+
2
]
*
math
.
pi
/
180.0
,
large:
points
[
len
+
3
]
!=
0.0
,
sweep:
points
[
len
+
4
]
!=
0.0
);
lastPoint
=
PdfPoint
(
points
[
len
+
5
],
points
[
len
+
6
]);
len
+=
7
;
}
break
;
case
'a'
:
// elliptical arc, relative
var
len
=
0
;
while
(
len
<
points
.
length
)
{
points
[
len
+
5
]
+=
lastPoint
.
x
;
points
[
len
+
6
]
+=
lastPoint
.
y
;
_bezierArc
(
lastPoint
.
x
,
lastPoint
.
y
,
points
[
len
+
0
],
points
[
len
+
1
],
points
[
len
+
5
],
points
[
len
+
6
],
phi:
points
[
len
+
2
]
*
math
.
pi
/
180.0
,
large:
points
[
len
+
3
]
!=
0.0
,
sweep:
points
[
len
+
4
]
!=
0.0
);
lastPoint
=
PdfPoint
(
points
[
len
+
5
],
points
[
len
+
6
]);
len
+=
7
;
}
break
;
case
'Z'
:
// close path
case
'z'
:
// close path
if
(
stroke
)
closePath
();
...
...
pdf/test/complex_test.dart
View file @
bd8bc15
...
...
@@ -23,8 +23,8 @@ void main() {
g
.
saveContext
();
var
tm
=
Matrix4
.
identity
();
tm
.
translate
(
50.0
,
290.0
);
tm
.
rotateZ
(
pi
);
tm
.
translate
(
10.0
,
290.0
);
tm
.
scale
(
1.0
,
-
1.0
);
g
.
setTransform
(
tm
);
g
.
setColor
(
PdfColor
(
0.0
,
0.0
,
0.0
));
g
.
drawShape
(
...
...
@@ -33,6 +33,16 @@ void main() {
g
.
fillPath
();
g
.
restoreContext
();
g
.
saveContext
();
tm
=
Matrix4
.
identity
();
tm
.
translate
(
200.0
,
290.0
);
tm
.
scale
(.
1
,
-.
1
);
g
.
setTransform
(
tm
);
g
.
setColor
(
PdfColor
(
0.0
,
0.0
,
0.0
));
g
.
drawShape
(
"M300,200 h-150 a150,150 0 1,0 150,-150 z M275,175 v-150 a150,150 0 0,0 -150,150 z"
);
g
.
restoreContext
();
var
font1
=
g
.
defaultFont
;
var
font2
=
PdfTtfFont
(
...
...
@@ -70,7 +80,7 @@ void main() {
g
.
restoreContext
();
}
var
file
=
File
(
'
file
.pdf'
);
var
file
=
File
(
'
complex
.pdf'
);
file
.
writeAsBytesSync
(
pdf
.
save
());
});
}
...
...
Please
register
or
login
to post a comment