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-07-21 12:58:40 -0400
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
48b633ac08c8d852b2a511c022aa8cd226fe066c
48b633ac
1 parent
0aff57a8
Implement InlineSpan and WidgetSpan
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
264 additions
and
55 deletions
pdf/CHANGELOG.md
pdf/lib/widgets/text.dart
pdf/pubspec.yaml
pdf/test/widget_text_test.dart
pdf/CHANGELOG.md
View file @
48b633a
# Changelog
## 1.3.18
-
Implement InlineSpan and WidgetSpan
## 1.3.17
-
Fix MultiPage with multiple save() calls
...
...
pdf/lib/widgets/text.dart
View file @
48b633a
...
...
@@ -18,25 +18,85 @@ part of widget;
enum
TextAlign
{
left
,
right
,
center
,
justify
}
class
_Word
{
_Word
(
this
.
text
,
this
.
style
,
this
.
metrics
,
this
.
annotation
);
final
String
text
;
abstract
class
_Span
{
_Span
(
this
.
style
,
this
.
annotation
);
final
TextStyle
style
;
final
PdfFontMetrics
metrics
;
final
AnnotationBuilder
annotation
;
PdfPoint
offset
=
PdfPoint
.
zero
;
final
AnnotationBuilder
annotation
;
double
left
;
double
top
;
double
width
;
double
height
;
@override
String
toString
()
{
return
'Span "offset:
$offset
'
;
}
void
debugPaint
(
Context
context
,
double
textScaleFactor
,
PdfRect
globalBox
,
)
{}
void
paint
(
Context
context
,
TextStyle
style
,
double
textScaleFactor
,
PdfPoint
point
,
);
}
class
_Word
extends
_Span
{
_Word
(
this
.
text
,
TextStyle
style
,
this
.
metrics
,
AnnotationBuilder
annotation
)
:
super
(
style
,
annotation
);
final
String
text
;
final
PdfFontMetrics
metrics
;
@override
double
get
left
=>
metrics
.
left
;
@override
double
get
top
=>
metrics
.
top
;
@override
double
get
width
=>
metrics
.
width
;
@override
double
get
height
=>
metrics
.
height
;
@override
String
toString
()
{
return
'Word "
$text
" offset:
$offset
metrics:
$metrics
style:
$style
'
;
}
void
debugPaint
(
Context
context
,
double
textScaleFactor
,
PdfRect
globalBox
)
{
@override
void
paint
(
Context
context
,
TextStyle
style
,
double
textScaleFactor
,
PdfPoint
point
,
)
{
context
.
canvas
.
drawString
(
style
.
font
.
getFont
(
context
),
style
.
fontSize
*
textScaleFactor
,
text
,
point
.
x
+
offset
.
x
,
point
.
y
+
offset
.
y
);
}
@override
void
debugPaint
(
Context
context
,
double
textScaleFactor
,
PdfRect
globalBox
,
)
{
const
double
deb
=
5
;
context
.
canvas
...
...
@@ -54,27 +114,122 @@ class _Word {
}
}
class
TextSpan
{
const
TextSpan
({
this
.
style
,
this
.
text
,
this
.
children
,
this
.
annotation
});
class
_WidgetSpan
extends
_Span
{
_WidgetSpan
(
this
.
widget
,
TextStyle
style
,
AnnotationBuilder
annotation
)
:
assert
(
widget
!=
null
),
assert
(
style
!=
null
),
super
(
style
,
annotation
);
final
TextStyle
style
;
final
Widget
widget
;
final
String
text
;
@override
double
get
left
=>
0
;
@override
double
get
top
=>
0
;
@override
double
get
width
=>
widget
.
box
.
width
;
@override
double
get
height
=>
widget
.
box
.
height
;
final
List
<
TextSpan
>
children
;
@override
PdfPoint
get
offset
=>
widget
.
box
.
offset
;
@override
set
offset
(
PdfPoint
value
)
{
widget
.
box
=
PdfRect
.
fromPoints
(
value
,
widget
.
box
.
size
);
}
@override
String
toString
()
{
return
'Widget "
$widget
" offset:
$offset
'
;
}
@override
void
paint
(
Context
context
,
TextStyle
style
,
double
textScaleFactor
,
PdfPoint
point
,
)
{
widget
.
box
=
PdfRect
.
fromPoints
(
PdfPoint
(
point
.
x
+
widget
.
box
.
offset
.
x
,
point
.
y
+
widget
.
box
.
offset
.
y
),
widget
.
box
.
size
);
widget
.
paint
(
context
);
}
}
@immutable
abstract
class
InlineSpan
{
const
InlineSpan
({
this
.
style
,
this
.
baseline
,
this
.
annotation
});
final
TextStyle
style
;
final
double
baseline
;
final
AnnotationBuilder
annotation
;
String
toPlainText
()
{
final
StringBuffer
buffer
=
StringBuffer
();
visitTextSpan
((
TextSpan
span
,
TextStyle
style
)
{
visitChildren
((
InlineSpan
span
,
TextStyle
style
)
{
if
(
span
is
TextSpan
)
{
buffer
.
write
(
span
.
text
);
}
return
true
;
},
null
);
return
buffer
.
toString
();
}
bool
visitTextSpan
(
bool
visitor
(
TextSpan
span
,
TextStyle
parentStyle
),
bool
visitChildren
(
bool
visitor
(
InlineSpan
span
,
TextStyle
parentStyle
),
TextStyle
parentStyle
);
}
class
WidgetSpan
extends
InlineSpan
{
/// Creates a [WidgetSpan] with the given values.
const
WidgetSpan
({
@required
this
.
child
,
double
baseline
=
0
,
TextStyle
style
,
AnnotationBuilder
annotation
,
})
:
assert
(
child
!=
null
),
super
(
style:
style
,
baseline:
baseline
,
annotation:
annotation
);
/// The widget to embed inline within text.
final
Widget
child
;
/// Calls `visitor` on this [WidgetSpan]. There are no children spans to walk.
@override
bool
visitChildren
(
bool
visitor
(
InlineSpan
span
,
TextStyle
parentStyle
),
TextStyle
parentStyle
)
{
final
TextStyle
_style
=
parentStyle
?.
merge
(
style
);
if
(
child
!=
null
)
{
if
(!
visitor
(
this
,
_style
))
{
return
false
;
}
}
return
true
;
}
}
class
TextSpan
extends
InlineSpan
{
const
TextSpan
({
TextStyle
style
,
this
.
text
,
double
baseline
=
0
,
this
.
children
,
AnnotationBuilder
annotation
,
})
:
super
(
style:
style
,
baseline:
baseline
,
annotation:
annotation
);
final
String
text
;
final
List
<
InlineSpan
>
children
;
@override
bool
visitChildren
(
bool
visitor
(
InlineSpan
span
,
TextStyle
parentStyle
),
TextStyle
parentStyle
)
{
final
TextStyle
_style
=
parentStyle
?.
merge
(
style
);
...
...
@@ -84,8 +239,8 @@ class TextSpan {
}
}
if
(
children
!=
null
)
{
for
(
TextSpan
child
in
children
)
{
if
(!
child
.
visitTextSpan
(
visitor
,
_style
))
{
for
(
InlineSpan
child
in
children
)
{
if
(!
child
.
visitChildren
(
visitor
,
_style
))
{
return
false
;
}
}
...
...
@@ -105,7 +260,7 @@ class RichText extends Widget {
static
bool
debug
=
false
;
final
Text
Span
text
;
final
Inline
Span
text
;
final
TextAlign
textAlign
;
...
...
@@ -115,9 +270,9 @@ class RichText extends Widget {
final
int
maxLines
;
final
List
<
_
Word
>
_words
=
<
_Word
>[];
final
List
<
_
Span
>
_spans
=
<
_Span
>[];
double
_realignLine
(
List
<
_
Word
>
word
s
,
double
totalWidth
,
double
wordsWidth
,
double
_realignLine
(
List
<
_
Span
>
span
s
,
double
totalWidth
,
double
wordsWidth
,
bool
last
,
double
baseline
)
{
double
delta
=
0
;
switch
(
textAlign
)
{
...
...
@@ -135,17 +290,17 @@ class RichText extends Widget {
totalWidth
=
wordsWidth
;
break
;
}
delta
=
(
totalWidth
-
wordsWidth
)
/
(
word
s
.
length
-
1
);
delta
=
(
totalWidth
-
wordsWidth
)
/
(
span
s
.
length
-
1
);
double
x
=
0
;
for
(
_Word
word
in
words
)
{
word
.
offset
=
word
.
offset
.
translate
(
x
,
-
baseline
);
for
(
_Span
span
in
spans
)
{
span
.
offset
=
span
.
offset
.
translate
(
x
,
-
baseline
);
x
+=
delta
;
}
return
totalWidth
;
}
for
(
_Word
word
in
words
)
{
word
.
offset
=
word
.
offset
.
translate
(
delta
,
-
baseline
);
for
(
_Span
span
in
spans
)
{
span
.
offset
=
span
.
offset
.
translate
(
delta
,
-
baseline
);
}
return
totalWidth
;
}
...
...
@@ -153,7 +308,7 @@ class RichText extends Widget {
@override
void
layout
(
Context
context
,
BoxConstraints
constraints
,
{
bool
parentUsesSize
=
false
})
{
_
word
s
.
clear
();
_
span
s
.
clear
();
final
TextStyle
defaultstyle
=
Theme
.
of
(
context
).
defaultTextStyle
;
...
...
@@ -174,7 +329,8 @@ class RichText extends Widget {
int
wCount
=
0
;
int
lineStart
=
0
;
text
.
visitTextSpan
((
TextSpan
span
,
TextStyle
style
)
{
text
.
visitChildren
((
InlineSpan
span
,
TextStyle
style
)
{
if
(
span
is
TextSpan
)
{
if
(
span
.
text
==
null
)
{
return
true
;
}
...
...
@@ -199,7 +355,7 @@ class RichText extends Widget {
width
=
math
.
max
(
width
,
_realignLine
(
_word
s
.
sublist
(
lineStart
),
_span
s
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
,
false
,
...
...
@@ -222,13 +378,16 @@ class RichText extends Widget {
wCount
=
0
;
}
top
=
math
.
min
(
top
??
metrics
.
top
,
metrics
.
top
);
bottom
=
math
.
max
(
bottom
??
metrics
.
bottom
,
metrics
.
bottom
);
final
double
baseline
=
span
.
baseline
*
textScaleFactor
;
top
=
math
.
min
(
top
??
metrics
.
top
+
baseline
,
metrics
.
top
+
baseline
);
bottom
=
math
.
max
(
bottom
??
metrics
.
bottom
+
baseline
,
metrics
.
bottom
+
baseline
);
final
_Word
wd
=
_Word
(
word
,
style
,
metrics
,
span
.
annotation
);
wd
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
);
wd
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_word
s
.
add
(
wd
);
_span
s
.
add
(
wd
);
wCount
++;
offsetX
+=
metrics
.
advanceWidth
+
space
.
advanceWidth
*
style
.
wordSpacing
;
...
...
@@ -238,7 +397,7 @@ class RichText extends Widget {
width
=
math
.
max
(
width
,
_realignLine
(
_word
s
.
sublist
(
lineStart
),
_span
s
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
,
false
,
...
...
@@ -267,13 +426,55 @@ class RichText extends Widget {
}
offsetX
-=
space
.
advanceWidth
*
style
.
wordSpacing
;
}
else
if
(
span
is
WidgetSpan
)
{
span
.
child
.
layout
(
context
,
BoxConstraints
.
tight
(
PdfPoint
(
double
.
infinity
,
style
.
fontSize
*
textScaleFactor
,
)));
final
_WidgetSpan
ws
=
_WidgetSpan
(
span
.
child
,
style
,
span
.
annotation
);
if
(
offsetX
+
ws
.
width
>
constraintWidth
&&
wCount
>
0
)
{
width
=
math
.
max
(
width
,
_realignLine
(
_spans
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
,
false
,
bottom
));
lineStart
+=
wCount
;
if
(
maxLines
!=
null
&&
++
lines
>
maxLines
)
{
return
false
;
}
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
+
style
.
lineSpacing
;
top
=
null
;
bottom
=
null
;
if
(
offsetY
>
constraintHeight
)
{
return
false
;
}
wCount
=
0
;
}
final
double
baseline
=
span
.
baseline
*
textScaleFactor
;
top
=
math
.
min
(
top
??
baseline
,
baseline
);
bottom
=
math
.
max
(
bottom
??
ws
.
height
+
baseline
,
ws
.
height
+
baseline
);
ws
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_spans
.
add
(
ws
);
wCount
++;
offsetX
+=
ws
.
left
+
ws
.
width
;
}
return
true
;
},
defaultstyle
);
width
=
math
.
max
(
width
,
_realignLine
(
_
word
s
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
,
true
,
bottom
));
_
span
s
.
sublist
(
lineStart
),
constraintWidth
,
offsetX
,
true
,
bottom
));
bottom
??=
0.0
;
top
??=
0.0
;
...
...
@@ -296,37 +497,34 @@ class RichText extends Widget {
TextStyle
currentStyle
;
PdfColor
currentColor
;
for
(
_
Word
word
in
_word
s
)
{
for
(
_
Span
span
in
_span
s
)
{
assert
(()
{
if
(
Document
.
debug
&&
RichText
.
debug
)
{
word
.
debugPaint
(
context
,
textScaleFactor
,
box
);
span
.
debugPaint
(
context
,
textScaleFactor
,
box
);
}
return
true
;
}());
if
(
word
.
style
!=
currentStyle
)
{
currentStyle
=
word
.
style
;
if
(
span
.
style
!=
currentStyle
)
{
currentStyle
=
span
.
style
;
if
(
currentStyle
.
color
!=
currentColor
)
{
currentColor
=
currentStyle
.
color
;
context
.
canvas
.
setFillColor
(
currentColor
);
}
}
if
(
word
.
annotation
!=
null
)
{
final
PdfRect
wordBox
=
PdfRect
(
box
.
x
+
word
.
offset
.
x
+
word
.
metrics
.
left
,
box
.
top
+
word
.
offset
.
y
+
word
.
metrics
.
top
,
word
.
metrics
.
width
,
word
.
metrics
.
height
);
word
.
annotation
.
build
(
context
,
wordBox
);
if
(
span
.
annotation
!=
null
)
{
final
PdfRect
spanBox
=
PdfRect
(
box
.
x
+
span
.
offset
.
x
+
span
.
left
,
box
.
top
+
span
.
offset
.
y
+
span
.
top
,
span
.
width
,
span
.
height
);
span
.
annotation
.
build
(
context
,
spanBox
);
}
context
.
canvas
.
drawString
(
currentStyle
.
font
.
getFont
(
context
),
currentStyle
.
fontSize
*
textScaleFactor
,
word
.
text
,
box
.
x
+
word
.
offset
.
x
,
box
.
top
+
word
.
offset
.
y
);
span
.
paint
(
context
,
currentStyle
,
textScaleFactor
,
PdfPoint
(
box
.
left
,
box
.
top
),
);
}
}
}
...
...
pdf/pubspec.yaml
View file @
48b633a
...
...
@@ -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.3.1
7
version
:
1.3.1
8
environment
:
sdk
:
"
>=2.1.0
<3.0.0"
...
...
pdf/test/widget_text_test.dart
View file @
48b633a
...
...
@@ -169,17 +169,24 @@ void main() {
font:
ttf
,
fontSize:
20
,
),
children:
<
Text
Span
>[
children:
<
Inline
Span
>[
TextSpan
(
text:
'bold'
,
style:
TextStyle
(
font:
ttfBold
,
fontSize:
40
,
color:
PdfColors
.
blue
)),
font:
ttfBold
,
fontSize:
40
,
color:
PdfColors
.
blue
),
children:
<
InlineSpan
>[
const
TextSpan
(
text:
'*'
,
baseline:
20
),
WidgetSpan
(
child:
PdfLogo
(),
baseline:
-
10
),
]),
TextSpan
(
text:
' world!
\n
'
,
children:
spans
,
),
WidgetSpan
(
child:
PdfLogo
(),
annotation:
AnnotationUrl
(
'https://github.com/DavBfr/dart_pdf'
,
)),
],
),
),
...
...
Please
register
or
login
to post a comment