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-02-18 07:58:33 -0500
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
bb57f3951b0b38772d7a37f9fa5c75e3132eaff5
bb57f395
1 parent
2576431b
Add RichText Widget
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
199 additions
and
61 deletions
pdf/CHANGELOG.md
pdf/lib/widgets/text.dart
pdf/test/widget_test.dart
pdf/CHANGELOG.md
View file @
bb57f39
# 1.3.3
*
Fix dart lint warnings
*
Improve font bounds calculation
*
Add RichText Widget
# 1.3.2
*
Update Readme
...
...
pdf/lib/widgets/text.dart
View file @
bb57f39
...
...
@@ -34,14 +34,18 @@ class TextStyle {
final
PdfFont
font
;
// font height, in pdf unit
final
double
fontSize
;
static
const
double
_defaultFontSize
=
12.0
*
PdfPageFormat
.
point
;
// spacing between letters, 1.0 being natural spacing
final
double
letterSpacing
;
// spacing between lines, in pdf unit
final
double
lineSpacing
;
// spacing between words, 1.0 being natural spacing
final
double
wordSpacing
;
final
double
height
;
...
...
@@ -69,37 +73,96 @@ class TextStyle {
background:
background
??
this
.
background
,
);
}
@override
String
toString
()
=>
'TextStyle(color:
$color
font:
$font
letterSpacing:
$letterSpacing
wordSpacing:
$wordSpacing
lineSpacing:
$lineSpacing
height:
$height
background:
$background
)'
;
}
enum
TextAlign
{
left
,
right
,
center
,
justify
}
class
_Word
{
_Word
(
this
.
text
,
this
.
_box
);
_Word
(
this
.
text
,
this
.
style
,
this
.
metrics
);
final
String
text
;
PdfRect
_box
;
final
TextStyle
style
;
final
PdfFontMetrics
metrics
;
PdfPoint
offset
=
PdfPoint
.
zero
;
@override
String
toString
()
{
return
'Word
$text
$_box
'
;
return
'Word "
$text
" offset:
$offset
metrics:
$metrics
style:
$style
'
;
}
void
debugPaint
(
Context
context
,
double
textScaleFactor
,
PdfRect
globalBox
)
{
const
double
deb
=
5.0
;
context
.
canvas
..
drawRect
(
globalBox
.
x
+
offset
.
x
+
metrics
.
left
,
globalBox
.
top
+
offset
.
y
+
metrics
.
top
,
metrics
.
width
,
metrics
.
height
)
..
setStrokeColor
(
PdfColor
.
orange
)
..
strokePath
()
..
drawLine
(
globalBox
.
x
+
offset
.
x
-
deb
,
globalBox
.
top
+
offset
.
y
,
globalBox
.
x
+
offset
.
x
+
metrics
.
right
+
deb
,
globalBox
.
top
+
offset
.
y
)
..
setStrokeColor
(
PdfColor
.
deepPurple
)
..
strokePath
();
}
}
class
Text
extends
Widget
{
Text
(
this
.
data
,
{
this
.
style
,
class
TextSpan
{
const
TextSpan
({
this
.
style
,
this
.
text
,
this
.
children
});
final
TextStyle
style
;
final
String
text
;
final
List
<
TextSpan
>
children
;
String
toPlainText
()
{
final
StringBuffer
buffer
=
StringBuffer
();
visitTextSpan
((
TextSpan
span
)
{
buffer
.
write
(
span
.
text
);
return
true
;
});
return
buffer
.
toString
();
}
bool
visitTextSpan
(
bool
visitor
(
TextSpan
span
))
{
if
(
text
!=
null
)
{
if
(!
visitor
(
this
))
{
return
false
;
}
}
if
(
children
!=
null
)
{
for
(
TextSpan
child
in
children
)
{
if
(!
child
.
visitTextSpan
(
visitor
))
{
return
false
;
}
}
}
return
true
;
}
}
class
RichText
extends
Widget
{
RichText
(
{
@required
this
.
text
,
this
.
textAlign
=
TextAlign
.
left
,
bool
softWrap
=
true
,
this
.
textScaleFactor
=
1.0
,
int
maxLines
,
})
:
maxLines
=
!
softWrap
?
1
:
maxLines
,
assert
(
data
!=
null
);
int
maxLines
})
:
maxLines
=
!
softWrap
?
1
:
maxLines
,
assert
(
text
!=
null
);
final
String
data
;
static
const
bool
debug
=
false
;
TextStyle
style
;
final
TextSpan
text
;
final
TextAlign
textAlign
;
...
...
@@ -109,12 +172,13 @@ class Text extends Widget {
final
List
<
_Word
>
_words
=
<
_Word
>[];
double
_realignLine
(
List
<
_Word
>
words
,
double
totalWidth
,
double
wordsWidth
,
bool
last
)
{
double
_realignLine
(
List
<
_Word
>
words
,
double
totalWidth
,
double
wordsWidth
,
bool
last
,
double
baseline
)
{
double
delta
=
0.0
;
switch
(
textAlign
)
{
case
TextAlign
.
left
:
return
wordsWidth
;
totalWidth
=
wordsWidth
;
break
;
case
TextAlign
.
right
:
delta
=
totalWidth
-
wordsWidth
;
break
;
...
...
@@ -123,20 +187,20 @@ class Text extends Widget {
break
;
case
TextAlign
.
justify
:
if
(
last
)
{
return
wordsWidth
;
totalWidth
=
wordsWidth
;
break
;
}
delta
=
(
totalWidth
-
wordsWidth
)
/
(
words
.
length
-
1
);
double
x
=
0.0
;
for
(
_Word
word
in
words
)
{
word
.
_box
=
PdfRect
(
word
.
_box
.
x
+
x
,
word
.
_box
.
y
,
word
.
_box
.
width
,
word
.
_box
.
height
);
word
.
offset
=
word
.
offset
.
translate
(
x
,
-
baseline
);
x
+=
delta
;
}
return
totalWidth
;
}
for
(
_Word
word
in
words
)
{
word
.
_box
=
PdfRect
(
word
.
_box
.
x
+
delta
,
word
.
_box
.
y
,
word
.
_box
.
width
,
word
.
_box
.
height
);
word
.
offset
=
word
.
offset
.
translate
(
delta
,
-
baseline
);
}
return
totalWidth
;
}
...
...
@@ -146,74 +210,89 @@ class Text extends Widget {
{
bool
parentUsesSize
=
false
})
{
_words
.
clear
();
style
??
=
Theme
.
of
(
context
).
defaultTextStyle
;
final
TextStyle
defaultstyle
=
Theme
.
of
(
context
).
defaultTextStyle
;
final
double
c
w
=
constraints
.
hasBoundedWidth
final
double
c
onstraintWidth
=
constraints
.
hasBoundedWidth
?
constraints
.
maxWidth
:
constraints
.
constrainWidth
();
final
double
c
h
=
constraints
.
hasBoundedHeight
final
double
c
onstraintHeight
=
constraints
.
hasBoundedHeight
?
constraints
.
maxHeight
:
constraints
.
constrainHeight
();
double
x
=
0.0
;
double
y
=
0.0
;
double
w
=
0.0
;
double
h
=
0.0
;
double
lh
=
0.0
;
final
PdfRect
space
=
style
.
font
.
stringBounds
(
' '
)
*
(
style
.
fontSize
*
textScaleFactor
);
double
offsetX
=
0.0
;
double
offsetY
=
0.0
;
double
width
=
0.0
;
double
top
;
double
bottom
;
int
lines
=
1
;
int
wCount
=
0
;
int
lineStart
=
0
;
for
(
String
word
in
data
.
split
(
' '
))
{
final
PdfRect
box
=
style
.
font
.
stringBounds
(
word
)
*
(
style
.
fontSize
*
textScaleFactor
);
text
.
visitTextSpan
((
TextSpan
span
)
{
if
(
span
.
text
==
null
)
{
return
true
;
}
final
TextStyle
style
=
span
.
style
??
defaultstyle
;
final
double
ww
=
box
.
width
;
final
double
wh
=
box
.
height
;
final
PdfFontMetrics
space
=
style
.
font
.
stringMetrics
(
' '
)
*
(
style
.
fontSize
*
textScaleFactor
);
if
(
x
+
ww
>
cw
)
{
for
(
String
word
in
span
.
text
.
split
(
' '
))
{
if
(
word
.
isEmpty
)
{
offsetX
+=
space
.
width
;
continue
;
}
final
PdfFontMetrics
metrics
=
style
.
font
.
stringMetrics
(
word
)
*
(
style
.
fontSize
*
textScaleFactor
);
if
(
offsetX
+
metrics
.
width
>
constraintWidth
)
{
if
(
wCount
==
0
)
{
break
;
}
w
=
math
.
max
(
w
,
_realignLine
(
_words
.
sublist
(
lineStart
),
cw
,
x
-
space
.
width
,
false
));
width
=
math
.
max
(
width
,
_realignLine
(
_words
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
-
space
.
width
,
false
,
bottom
));
lineStart
+=
wCount
;
if
(
maxLines
!=
null
&&
++
lines
>
maxLines
)
{
break
;
}
x
=
0.0
;
y
+=
lh
+
style
.
lineSpacing
;
h
+=
lh
+
style
.
lineSpacing
;
lh
=
0.0
;
if
(
y
>
ch
)
{
break
;
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
+
style
.
lineSpacing
;
top
=
null
;
bottom
=
null
;
if
(
offsetY
>
constraintHeight
)
{
return
false
;
}
wCount
=
0
;
}
final
double
wx
=
x
;
final
double
wy
=
y
;
top
=
math
.
min
(
top
??
metrics
.
top
,
metrics
.
top
);
bottom
=
math
.
max
(
bottom
??
metrics
.
bottom
,
metrics
.
bottom
);
x
+=
ww
+
space
.
width
;
lh
=
math
.
max
(
lh
,
wh
);
final
_Word
wd
=
_Word
(
word
,
style
,
metrics
);
wd
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
);
final
_Word
wd
=
_Word
(
word
,
PdfRect
(
box
.
x
+
wx
,
box
.
y
+
wy
+
wh
,
ww
,
wh
));
_words
.
add
(
wd
);
wCount
++;
offsetX
+=
metrics
.
width
+
space
.
advanceWidth
;
}
w
=
math
.
max
(
w
,
_realignLine
(
_words
.
sublist
(
lineStart
),
cw
,
x
-
space
.
width
,
true
));
h
+=
lh
;
box
=
PdfRect
(
0.0
,
0.0
,
constraints
.
constrainWidth
(
w
),
constraints
.
constrainHeight
(
h
));
offsetX
-=
space
.
width
;
return
true
;
});
width
=
math
.
max
(
width
,
_realignLine
(
_words
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
,
true
,
bottom
));
box
=
PdfRect
(
0.0
,
0.0
,
constraints
.
constrainWidth
(
width
),
constraints
.
constrainHeight
(
offsetY
+
bottom
-
top
));
}
@override
...
...
@@ -227,11 +306,48 @@ class Text extends Widget {
@override
void
paint
(
Context
context
)
{
super
.
paint
(
context
);
context
.
canvas
.
setFillColor
(
style
.
color
);
TextStyle
currentStyle
;
PdfColor
currentColor
;
for
(
_Word
word
in
_words
)
{
context
.
canvas
.
drawString
(
style
.
font
,
style
.
fontSize
*
textScaleFactor
,
word
.
text
,
box
.
x
+
word
.
_box
.
x
,
box
.
y
+
box
.
height
-
word
.
_box
.
y
);
assert
(()
{
if
(
Document
.
debug
&&
RichText
.
debug
)
{
word
.
debugPaint
(
context
,
textScaleFactor
,
box
);
}
return
true
;
}());
if
(
word
.
style
!=
currentStyle
)
{
currentStyle
=
word
.
style
;
if
(
currentStyle
.
color
!=
currentColor
)
{
currentColor
=
currentStyle
.
color
;
context
.
canvas
.
setFillColor
(
currentColor
);
}
}
context
.
canvas
.
drawString
(
currentStyle
.
font
,
currentStyle
.
fontSize
*
textScaleFactor
,
word
.
text
,
box
.
x
+
word
.
offset
.
x
,
box
.
top
+
word
.
offset
.
y
);
}
}
}
class
Text
extends
RichText
{
Text
(
String
text
,
{
TextStyle
style
,
TextAlign
textAlign
=
TextAlign
.
left
,
bool
softWrap
=
true
,
double
textScaleFactor
=
1.0
,
int
maxLines
,
})
:
assert
(
text
!=
null
),
super
(
text:
TextSpan
(
text:
text
,
style:
style
),
textAlign:
textAlign
,
softWrap:
softWrap
,
textScaleFactor:
textScaleFactor
,
maxLines:
maxLines
);
}
...
...
pdf/test/widget_test.dart
View file @
bb57f39
...
...
@@ -16,6 +16,7 @@
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'package:pdf/pdf.dart'
;
import
'package:pdf/widgets.dart'
;
...
...
@@ -97,6 +98,10 @@ void main() {
children:
List
<
Widget
>.
generate
(
9
,
(
int
n
)
=>
FittedBox
(
child:
Text
(
'
${n + 1}
'
)))))));
final
Uint8List
robotoData
=
File
(
'open-sans.ttf'
).
readAsBytesSync
();
final
PdfTtfFont
roboto
=
PdfTtfFont
(
pdf
.
document
,
robotoData
.
buffer
.
asByteData
());
pdf
.
addPage
(
MultiPage
(
pageFormat:
const
PdfPageFormat
(
400.0
,
200.0
),
margin:
const
EdgeInsets
.
all
(
10.0
),
...
...
@@ -141,6 +146,22 @@ void main() {
..
drawRRect
(
0
,
0
,
size
.
x
,
size
.
y
,
10
,
10
)
..
fillPath
();
}),
RichText
(
text:
TextSpan
(
text:
'Hello '
,
style:
Theme
.
of
(
context
).
defaultTextStyle
,
children:
<
TextSpan
>[
TextSpan
(
text:
'bold'
,
style:
Theme
.
of
(
context
)
.
defaultTextStyleBold
.
copyWith
(
fontSize:
20
,
color:
PdfColor
.
blue
)),
const
TextSpan
(
text:
' world!'
,
),
],
),
)
]));
final
File
file
=
File
(
'widgets.pdf'
);
...
...
Please
register
or
login
to post a comment