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-12-31 13:11:37 -0400
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
eefce19881500ab5abc4363badf1253d93902465
eefce198
1 parent
8ab8ebe3
Implement fallback font
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
437 additions
and
221 deletions
pdf/CHANGELOG.md
pdf/lib/src/pdf/obj/font.dart
pdf/lib/src/pdf/obj/ttffont.dart
pdf/lib/src/pdf/obj/type1_font.dart
pdf/lib/src/svg/text.dart
pdf/lib/src/widgets/annotations.dart
pdf/lib/src/widgets/barcode.dart
pdf/lib/src/widgets/font.dart
pdf/lib/src/widgets/forms.dart
pdf/lib/src/widgets/text.dart
pdf/lib/src/widgets/text_style.dart
pdf/lib/src/widgets/theme.dart
pdf/test/widget_text_test.dart
test/golden/arabic.pdf
pdf/CHANGELOG.md
View file @
eefce19
...
...
@@ -4,6 +4,7 @@
-
Move files
-
Depreciate Font.stringSize
-
Implement fallback font
## 3.6.6
...
...
pdf/lib/src/pdf/obj/font.dart
View file @
eefce19
...
...
@@ -161,6 +161,9 @@ See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management
/// Calculate the [PdfFontMetrics] for this glyph
PdfFontMetrics
glyphMetrics
(
int
charCode
);
/// is this Rune supported by this font
bool
isRuneSupported
(
int
charCode
);
/// Calculate the [PdfFontMetrics] for this string
PdfFontMetrics
stringMetrics
(
String
s
,
{
double
letterSpacing
=
0
})
{
if
(
s
.
isEmpty
)
{
...
...
pdf/lib/src/pdf/obj/ttffont.dart
View file @
eefce19
...
...
@@ -188,4 +188,9 @@ class PdfTtfFont extends PdfFont {
final
metrics
=
bytes
.
map
(
glyphMetrics
);
return
PdfFontMetrics
.
append
(
metrics
,
letterSpacing:
letterSpacing
);
}
@override
bool
isRuneSupported
(
int
charCode
)
{
return
font
.
charToGlyphIndexMap
.
containsKey
(
charCode
);
}
}
...
...
pdf/lib/src/pdf/obj/type1_font.dart
View file @
eefce19
...
...
@@ -64,6 +64,11 @@ class PdfType1Font extends PdfFont {
@override
PdfFontMetrics
glyphMetrics
(
int
charCode
)
{
if
(!
isRuneSupported
(
charCode
))
{
throw
Exception
(
'Unable to display U+
${charCode.toRadixString(16)}
with
$fontName
'
);
}
return
PdfFontMetrics
(
left:
0
,
top:
descent
,
...
...
@@ -72,4 +77,9 @@ class PdfType1Font extends PdfFont {
:
PdfFont
.
defaultGlyphWidth
,
bottom:
ascent
);
}
@override
bool
isRuneSupported
(
int
charCode
)
{
return
charCode
>=
0x00
&&
charCode
<=
0xff
;
}
}
...
...
pdf/lib/src/svg/text.dart
View file @
eefce19
...
...
@@ -66,7 +66,7 @@ class SvgText extends SvgOperation {
final
font
=
painter
.
getFontCache
(
_brush
.
fontFamily
!,
_brush
.
fontStyle
!,
_brush
.
fontWeight
!)!;
final
pdfFont
=
font
.
getFont
(
Context
(
document:
painter
.
document
))
!
;
final
pdfFont
=
font
.
getFont
(
Context
(
document:
painter
.
document
));
final
metrics
=
pdfFont
.
stringMetrics
(
text
)
*
_brush
.
fontSize
!.
sizeValue
;
offset
=
PdfPoint
((
x
??
offset
.
x
)
+
dx
,
(
y
??
offset
.
y
)
+
dy
);
...
...
pdf/lib/src/widgets/annotations.dart
View file @
eefce19
...
...
@@ -392,7 +392,7 @@ class AnnotationTextField extends AnnotationBuilder {
fieldFlags:
fieldFlags
,
value:
value
,
defaultValue:
defaultValue
,
font:
_textStyle
.
font
!.
getFont
(
context
)
!
,
font:
_textStyle
.
font
!.
getFont
(
context
),
fontSize:
_textStyle
.
fontSize
!,
textColor:
_textStyle
.
color
!,
),
...
...
pdf/lib/src/widgets/barcode.dart
View file @
eefce19
...
...
@@ -94,7 +94,7 @@ class _BarcodeWidget extends Widget {
final
font
=
textStyle
!.
font
!.
getFont
(
context
);
for
(
final
text
in
textList
)
{
final
metrics
=
font
!
.
stringMetrics
(
text
.
text
);
final
metrics
=
font
.
stringMetrics
(
text
.
text
);
final
top
=
box
!.
top
-
text
.
top
-
...
...
pdf/lib/src/widgets/font.dart
View file @
eefce19
...
...
@@ -43,7 +43,7 @@ enum Type1Fonts {
class
Font
{
Font
()
:
font
=
null
;
Font
.
type1
(
Type1Fonts
this
.
font
);
Font
.
type1
(
this
.
font
);
factory
Font
.
courier
()
=>
Font
.
type1
(
Type1Fonts
.
courier
);
factory
Font
.
courierBold
()
=>
Font
.
type1
(
Type1Fonts
.
courierBold
);
...
...
@@ -127,13 +127,13 @@ class Font {
PdfFont
?
_pdfFont
;
PdfFont
?
getFont
(
Context
context
)
{
PdfFont
getFont
(
Context
context
)
{
if
(
_pdfFont
==
null
||
_pdfFont
!.
pdfDocument
!=
context
.
document
)
{
final
pdfDocument
=
context
.
document
;
_pdfFont
=
buildFont
(
pdfDocument
);
}
return
_pdfFont
;
return
_pdfFont
!
;
}
@override
...
...
pdf/lib/src/widgets/forms.dart
View file @
eefce19
...
...
@@ -278,7 +278,7 @@ class TextField extends StatelessWidget {
fieldFlags:
fieldFlags
,
value:
value
,
defaultValue:
defaultValue
,
font:
_textStyle
.
font
!.
getFont
(
context
)
!
,
font:
_textStyle
.
font
!.
getFont
(
context
),
fontSize:
_textStyle
.
fontSize
!,
textColor:
_textStyle
.
color
!,
);
...
...
pdf/lib/src/widgets/text.dart
View file @
eefce19
...
...
@@ -21,9 +21,11 @@ import 'package:pdf/pdf.dart';
import
'package:pdf/src/pdf/font/arabic.dart'
as
arabic
;
import
'annotations.dart'
;
import
'basic.dart'
;
import
'document.dart'
;
import
'geometry.dart'
;
import
'multi_page.dart'
;
import
'placeholders.dart'
;
import
'text_style.dart'
;
import
'theme.dart'
;
import
'widget.dart'
;
...
...
@@ -170,7 +172,7 @@ class _TextDecoration {
0.05
);
if
(
style
.
decoration
!.
contains
(
TextDecoration
.
underline
))
{
final
base
=
-
font
!
.
descent
*
style
.
fontSize
!
*
textScaleFactor
/
2
;
final
base
=
-
font
.
descent
*
style
.
fontSize
!
*
textScaleFactor
/
2
;
context
.
canvas
.
drawLine
(
globalBox
!.
x
+
box
!.
left
,
...
...
@@ -209,7 +211,7 @@ class _TextDecoration {
}
if
(
style
.
decoration
!.
contains
(
TextDecoration
.
lineThrough
))
{
final
base
=
(
1
-
font
!
.
descent
)
*
style
.
fontSize
!
*
textScaleFactor
/
2
;
final
base
=
(
1
-
font
.
descent
)
*
style
.
fontSize
!
*
textScaleFactor
/
2
;
context
.
canvas
.
drawLine
(
globalBox
!.
x
+
box
!.
left
,
globalBox
.
top
+
box
.
bottom
+
base
,
...
...
@@ -281,7 +283,7 @@ class _Word extends _Span {
PdfPoint
point
,
)
{
context
.
canvas
.
drawString
(
style
.
font
!.
getFont
(
context
)
!
,
style
.
font
!.
getFont
(
context
),
style
.
fontSize
!
*
textScaleFactor
,
text
,
point
.
x
+
offset
.
x
,
...
...
@@ -316,10 +318,12 @@ class _Word extends _Span {
}
class
_WidgetSpan
extends
_Span
{
_WidgetSpan
(
this
.
widget
,
TextStyle
style
)
:
super
(
style
);
_WidgetSpan
(
this
.
widget
,
TextStyle
style
,
this
.
baseline
)
:
super
(
style
);
final
Widget
widget
;
final
double
baseline
;
@override
double
get
left
=>
0
;
...
...
@@ -365,11 +369,21 @@ class _WidgetSpan extends _Span {
double
textScaleFactor
,
PdfRect
?
globalBox
,
)
{
const
deb
=
5
;
context
.
canvas
..
setLineWidth
(.
5
)
..
drawRect
(
globalBox
!.
x
+
offset
.
x
,
globalBox
.
top
+
offset
.
y
,
width
,
height
)
..
setStrokeColor
(
PdfColors
.
orange
)
..
strokePath
()
..
drawLine
(
globalBox
.
x
+
offset
.
x
-
deb
,
globalBox
.
top
+
offset
.
y
-
baseline
,
globalBox
.
x
+
offset
.
x
+
width
+
deb
,
globalBox
.
top
+
offset
.
y
-
baseline
,
)
..
setStrokeColor
(
PdfColors
.
deepPurple
)
..
strokePath
();
}
}
...
...
@@ -382,14 +396,24 @@ typedef _VisitorCallback = bool Function(
@immutable
abstract
class
InlineSpan
{
const
InlineSpan
({
this
.
style
,
this
.
baseline
,
this
.
annotation
});
const
InlineSpan
({
this
.
style
,
required
this
.
baseline
,
this
.
annotation
,
});
final
TextStyle
?
style
;
final
double
?
baseline
;
final
double
baseline
;
final
AnnotationBuilder
?
annotation
;
InlineSpan
copyWith
({
TextStyle
?
style
,
double
?
baseline
,
AnnotationBuilder
?
annotation
,
});
String
toPlainText
()
{
final
buffer
=
StringBuffer
();
visitChildren
((
...
...
@@ -424,6 +448,19 @@ class WidgetSpan extends InlineSpan {
/// The widget to embed inline within text.
final
Widget
child
;
@override
InlineSpan
copyWith
({
TextStyle
?
style
,
double
?
baseline
,
AnnotationBuilder
?
annotation
,
})
=>
WidgetSpan
(
child:
child
,
style:
style
??
this
.
style
,
baseline:
baseline
??
this
.
baseline
,
annotation:
annotation
??
this
.
annotation
,
);
/// Calls `visitor` on this [WidgetSpan]. There are no children spans to walk.
@override
bool
visitChildren
(
...
...
@@ -452,6 +489,20 @@ class TextSpan extends InlineSpan {
final
List
<
InlineSpan
>?
children
;
@override
InlineSpan
copyWith
({
TextStyle
?
style
,
double
?
baseline
,
AnnotationBuilder
?
annotation
,
})
=>
TextSpan
(
style:
style
??
this
.
style
,
text:
text
,
baseline:
baseline
??
this
.
baseline
,
children:
children
,
annotation:
annotation
??
this
.
annotation
,
);
@override
bool
visitChildren
(
_VisitorCallback
visitor
,
TextStyle
?
parentStyle
,
...
...
@@ -624,6 +675,8 @@ class RichText extends Widget with SpanningWidget {
var
_mustClip
=
false
;
List
<
InlineSpan
>?
_preprocessed
;
void
_appendDecoration
(
bool
append
,
_TextDecoration
td
)
{
if
(
append
&&
_decorations
.
isNotEmpty
)
{
final
last
=
_decorations
.
last
;
...
...
@@ -637,6 +690,132 @@ class RichText extends Widget with SpanningWidget {
_decorations
.
add
(
td
);
}
InlineSpan
_addText
({
required
List
<
int
>
text
,
int
start
=
0
,
int
?
end
,
double
baseline
=
0
,
required
TextStyle
style
,
AnnotationBuilder
?
annotation
,
})
{
return
TextSpan
(
text:
String
.
fromCharCodes
(
text
,
start
,
end
),
style:
style
,
baseline:
baseline
,
annotation:
annotation
,
);
}
InlineSpan
_addPlaceholder
({
double
baseline
=
0
,
required
TextStyle
style
,
AnnotationBuilder
?
annotation
,
})
{
return
WidgetSpan
(
child:
SizedBox
(
height:
style
.
fontSize
,
width:
style
.
fontSize
!
/
2
,
child:
Placeholder
(
color:
style
.
color
!,
strokeWidth:
1
,
),
),
style:
style
,
baseline:
baseline
,
annotation:
annotation
,
);
}
/// Check available characters in the fonts
/// use fallback if needed and replace emojis
List
<
InlineSpan
>
_preprocessSpans
(
Context
context
)
{
final
theme
=
Theme
.
of
(
context
);
final
defaultstyle
=
theme
.
defaultTextStyle
;
final
spans
=
<
InlineSpan
>[];
text
.
visitChildren
((
InlineSpan
span
,
TextStyle
?
style
,
AnnotationBuilder
?
annotation
,
)
{
if
(
span
is
!
TextSpan
)
{
spans
.
add
(
span
.
copyWith
(
style:
style
,
annotation:
annotation
));
return
true
;
}
if
(
span
.
text
==
null
)
{
return
true
;
}
final
font
=
style
!.
font
!.
getFont
(
context
);
var
text
=
span
.
text
!.
runes
.
toList
();
for
(
var
index
=
0
;
index
<
text
.
length
;
index
++)
{
final
rune
=
text
[
index
];
if
(
rune
==
0x0a
)
{
continue
;
}
if
(!
font
.
isRuneSupported
(
rune
))
{
if
(
index
>
0
)
{
spans
.
add
(
_addText
(
text:
text
,
end:
index
,
style:
style
,
baseline:
span
.
baseline
,
annotation:
annotation
,
));
}
var
found
=
false
;
for
(
final
fb
in
style
.
fontFallback
)
{
final
font
=
fb
.
getFont
(
context
);
if
(
font
.
isRuneSupported
(
rune
))
{
spans
.
add
(
_addText
(
text:
[
rune
],
style:
style
.
copyWith
(
font:
fb
,
fontNormal:
fb
,
fontBold:
fb
,
fontBoldItalic:
fb
,
fontItalic:
fb
,
),
baseline:
span
.
baseline
,
annotation:
annotation
,
));
found
=
true
;
break
;
}
}
if
(!
found
)
{
spans
.
add
(
_addPlaceholder
(
style:
style
,
baseline:
span
.
baseline
,
annotation:
annotation
,
));
assert
(()
{
print
(
'Unable to find a font to draw "
${String.fromCharCode(rune)}
" (U+
${rune.toRadixString(16)}
) try to provide a TextStyle.fontFallback'
);
return
true
;
}());
}
text
=
text
.
sublist
(
index
+
1
);
index
=
-
1
;
}
}
spans
.
add
(
_addText
(
text:
text
,
style:
style
,
baseline:
span
.
baseline
,
annotation:
annotation
,
));
return
true
;
},
defaultstyle
,
null
);
return
spans
;
}
@override
void
layout
(
Context
context
,
BoxConstraints
constraints
,
{
bool
parentUsesSize
=
false
})
{
...
...
@@ -644,7 +823,6 @@ class RichText extends Widget with SpanningWidget {
_decorations
.
clear
();
final
theme
=
Theme
.
of
(
context
);
final
defaultstyle
=
theme
.
defaultTextStyle
;
final
_softWrap
=
softWrap
??
theme
.
softWrap
;
final
_maxLines
=
maxLines
??
theme
.
maxLines
;
_textAlign
=
textAlign
??
theme
.
textAlign
;
...
...
@@ -669,228 +847,232 @@ class RichText extends Widget with SpanningWidget {
var
spanStart
=
0
;
var
overflow
=
false
;
text
.
visitChildren
((
InlineSpan
span
,
TextStyle
?
style
,
AnnotationBuilder
?
annotation
,
)
{
if
(
span
is
TextSpan
)
{
if
(
span
.
text
==
null
)
{
return
true
;
}
_preprocessed
??=
_preprocessSpans
(
context
);
final
font
=
style
!.
font
!.
getFont
(
context
)!;
void
_buildLines
()
{
for
(
final
span
in
_preprocessed
!)
{
final
style
=
span
.
style
;
final
annotation
=
span
.
annotation
;
final
space
=
font
.
stringMetrics
(
' '
)
*
(
style
.
fontSize
!
*
textScaleFactor
);
if
(
span
is
TextSpan
)
{
if
(
span
.
text
==
null
)
{
continue
;
}
final
spanLines
=
(
_textDirection
==
TextDirection
.
rtl
?
arabic
.
convert
(
span
.
text
!)
:
span
.
text
)!
.
split
(
'
\n
'
);
final
font
=
style
!.
font
!.
getFont
(
context
);
for
(
var
line
=
0
;
line
<
spanLines
.
length
;
line
++)
{
final
words
=
spanLines
[
line
].
split
(
RegExp
(
r'\s'
));
for
(
var
index
=
0
;
index
<
words
.
length
;
index
++)
{
final
word
=
words
[
index
];
final
space
=
font
.
stringMetrics
(
' '
)
*
(
style
.
fontSize
!
*
textScaleFactor
);
if
(
word
.
isEmpty
)
{
offsetX
+=
space
.
advanceWidth
*
style
.
wordSpacing
!
+
style
.
letterSpacing
!;
continue
;
}
final
spanLines
=
(
_textDirection
==
TextDirection
.
rtl
?
arabic
.
convert
(
span
.
text
!)
:
span
.
text
)!
.
split
(
'
\n
'
);
final
metrics
=
font
.
stringMetrics
(
word
,
letterSpacing:
style
.
letterSpacing
!
/
(
style
.
fontSize
!
*
textScaleFactor
))
*
(
style
.
fontSize
!
*
textScaleFactor
);
if
(
_softWrap
&&
offsetX
+
metrics
.
width
>
constraintWidth
+
0.00001
)
{
if
(
spanCount
>
0
&&
metrics
.
width
<=
constraintWidth
)
{
overflow
=
true
;
lines
.
add
(
_Line
(
this
,
spanStart
,
spanCount
,
bottom
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!,
_textDirection
,
true
,
));
spanStart
+=
spanCount
;
spanCount
=
0
;
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
;
top
=
0
;
bottom
=
0
;
for
(
var
line
=
0
;
line
<
spanLines
.
length
;
line
++)
{
final
words
=
spanLines
[
line
].
split
(
RegExp
(
r'\s'
));
for
(
var
index
=
0
;
index
<
words
.
length
;
index
++)
{
final
word
=
words
[
index
];
if
(
_maxLines
!=
null
&&
lines
.
length
>=
_maxLines
)
{
return
false
;
}
if
(
word
.
isEmpty
)
{
offsetX
+=
space
.
advanceWidth
*
style
.
wordSpacing
!
+
style
.
letterSpacing
!;
continue
;
}
if
(
offsetY
>
constraintHeight
)
{
return
false
;
final
metrics
=
font
.
stringMetrics
(
word
,
letterSpacing:
style
.
letterSpacing
!
/
(
style
.
fontSize
!
*
textScaleFactor
))
*
(
style
.
fontSize
!
*
textScaleFactor
);
if
(
_softWrap
&&
offsetX
+
metrics
.
width
>
constraintWidth
+
0.00001
)
{
if
(
spanCount
>
0
&&
metrics
.
width
<=
constraintWidth
)
{
overflow
=
true
;
lines
.
add
(
_Line
(
this
,
spanStart
,
spanCount
,
bottom
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!,
_textDirection
,
true
,
));
spanStart
+=
spanCount
;
spanCount
=
0
;
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
;
top
=
0
;
bottom
=
0
;
if
(
_maxLines
!=
null
&&
lines
.
length
>=
_maxLines
)
{
return
;
}
if
(
offsetY
>
constraintHeight
)
{
return
;
}
offsetY
+=
style
.
lineSpacing
!
*
textScaleFactor
;
}
else
{
// One word Overflow, try to split it.
final
pos
=
_splitWord
(
word
,
font
,
style
,
constraintWidth
);
if
(
pos
<
word
.
length
)
{
words
[
index
]
=
word
.
substring
(
0
,
pos
);
words
.
insert
(
index
+
1
,
word
.
substring
(
pos
));
// Try again
index
--;
continue
;
}
}
}
offsetY
+=
style
.
lineSpacing
!
*
textScaleFactor
;
}
else
{
// One word Overflow, try to split it.
final
pos
=
_splitWord
(
word
,
font
,
style
,
constraintWidth
);
final
baseline
=
span
.
baseline
*
textScaleFactor
;
final
mt
=
tightBounds
?
metrics
.
top
:
metrics
.
descent
;
final
mb
=
tightBounds
?
metrics
.
bottom
:
metrics
.
ascent
;
top
=
math
.
min
(
top
,
mt
+
baseline
);
bottom
=
math
.
max
(
bottom
,
mb
+
baseline
);
if
(
pos
<
word
.
length
)
{
words
[
index
]
=
word
.
substring
(
0
,
pos
);
words
.
insert
(
index
+
1
,
word
.
substring
(
pos
));
final
wd
=
_Word
(
word
,
style
,
metrics
,
);
wd
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_spans
.
add
(
wd
);
spanCount
++;
_appendDecoration
(
spanCount
>
1
,
_TextDecoration
(
style
,
annotation
,
_spans
.
length
-
1
,
_spans
.
length
-
1
,
),
);
offsetX
+=
metrics
.
advanceWidth
+
space
.
advanceWidth
*
style
.
wordSpacing
!
+
style
.
letterSpacing
!;
}
// Try again
index
--;
continue
;
}
if
(
line
<
spanLines
.
length
-
1
)
{
lines
.
add
(
_Line
(
this
,
spanStart
,
spanCount
,
bottom
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!,
_textDirection
,
false
,
));
spanStart
+=
spanCount
;
offsetX
=
0.0
;
if
(
spanCount
>
0
)
{
offsetY
+=
bottom
-
top
;
}
else
{
offsetY
+=
space
.
ascent
+
space
.
descent
;
}
}
top
=
0
;
bottom
=
0
;
spanCount
=
0
;
final
baseline
=
span
.
baseline
!
*
textScaleFactor
;
final
mt
=
tightBounds
?
metrics
.
top
:
metrics
.
descent
;
final
mb
=
tightBounds
?
metrics
.
bottom
:
metrics
.
ascent
;
top
=
math
.
min
(
top
,
mt
+
baseline
);
bottom
=
math
.
max
(
bottom
,
mb
+
baseline
);
if
(
_maxLines
!=
null
&&
lines
.
length
>=
_maxLines
)
{
return
;
}
final
wd
=
_Word
(
word
,
style
,
metrics
,
);
wd
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_spans
.
add
(
wd
);
spanCount
++;
_appendDecoration
(
spanCount
>
1
,
_TextDecoration
(
style
,
annotation
,
_spans
.
length
-
1
,
_spans
.
length
-
1
,
),
);
offsetX
+=
metrics
.
advanceWidth
+
space
.
advanceWidth
*
style
.
wordSpacing
!
+
style
.
letterSpacing
!;
if
(
offsetY
>
constraintHeight
)
{
return
;
}
offsetY
+=
style
.
lineSpacing
!
*
textScaleFactor
;
}
}
if
(
line
<
spanLines
.
length
-
1
)
{
offsetX
-=
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!;
}
else
if
(
span
is
WidgetSpan
)
{
span
.
child
.
layout
(
context
,
BoxConstraints
(
maxWidth:
constraintWidth
,
maxHeight:
constraintHeight
,
));
final
ws
=
_WidgetSpan
(
span
.
child
,
style
!,
span
.
baseline
,
);
if
(
offsetX
+
ws
.
width
>
constraintWidth
&&
spanCount
>
0
)
{
overflow
=
true
;
lines
.
add
(
_Line
(
this
,
spanStart
,
spanCount
,
bottom
,
offsetX
-
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!,
offsetX
,
_textDirection
,
fals
e
,
tru
e
,
));
spanStart
+=
spanCount
;
spanCount
=
0
;
offsetX
=
0.0
;
if
(
spanCount
>
0
)
{
offsetY
+=
bottom
-
top
;
}
else
{
offsetY
+=
space
.
ascent
+
space
.
descent
;
if
(
_maxLines
!=
null
&&
lines
.
length
>
_maxLines
)
{
return
;
}
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
;
top
=
0
;
bottom
=
0
;
spanCount
=
0
;
if
(
_maxLines
!=
null
&&
lines
.
length
>=
_maxLines
)
{
return
false
;
}
if
(
offsetY
>
constraintHeight
)
{
return
false
;
return
;
}
offsetY
+=
style
.
lineSpacing
!
*
textScaleFactor
;
}
}
offsetX
-=
space
.
advanceWidth
*
style
.
wordSpacing
!
-
style
.
letterSpacing
!;
}
else
if
(
span
is
WidgetSpan
)
{
span
.
child
.
layout
(
context
,
BoxConstraints
(
maxWidth:
constraintWidth
,
maxHeight:
constraintHeight
,
));
final
ws
=
_WidgetSpan
(
span
.
child
,
style
!,
);
if
(
offsetX
+
ws
.
width
>
constraintWidth
&&
spanCount
>
0
)
{
overflow
=
true
;
lines
.
add
(
_Line
(
this
,
spanStart
,
spanCount
,
final
baseline
=
span
.
baseline
*
textScaleFactor
;
top
=
math
.
min
(
top
,
baseline
);
bottom
=
math
.
max
(
bottom
,
offsetX
,
_textDirection
,
true
,
));
spanStart
+=
spanCount
;
spanCount
=
0
;
if
(
_maxLines
!=
null
&&
lines
.
length
>
_maxLines
)
{
return
false
;
}
ws
.
height
+
baseline
,
);
offsetX
=
0.0
;
offsetY
+=
bottom
-
top
;
top
=
0
;
bottom
=
0
;
ws
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_spans
.
add
(
ws
);
spanCount
++;
if
(
offsetY
>
constraintHeight
)
{
return
false
;
}
_appendDecoration
(
spanCount
>
1
,
_TextDecoration
(
style
,
annotation
,
_spans
.
length
-
1
,
_spans
.
length
-
1
,
),
);
offset
Y
+=
style
.
lineSpacing
!
*
textScaleFactor
;
offset
X
+=
ws
.
left
+
ws
.
width
;
}
final
baseline
=
span
.
baseline
!
*
textScaleFactor
;
top
=
math
.
min
(
top
,
baseline
);
bottom
=
math
.
max
(
bottom
,
ws
.
height
+
baseline
,
);
ws
.
offset
=
PdfPoint
(
offsetX
,
-
offsetY
+
baseline
);
_spans
.
add
(
ws
);
spanCount
++;
_appendDecoration
(
spanCount
>
1
,
_TextDecoration
(
style
,
annotation
,
_spans
.
length
-
1
,
_spans
.
length
-
1
,
),
);
offsetX
+=
ws
.
left
+
ws
.
width
;
}
}
return
true
;
},
defaultstyle
,
null
);
_buildLines
();
if
(
spanCount
>
0
)
{
lines
.
add
(
_Line
(
...
...
pdf/lib/src/widgets/text_style.dart
View file @
eefce19
...
...
@@ -111,6 +111,7 @@ class TextStyle {
Font
?
fontBold
,
Font
?
fontItalic
,
Font
?
fontBoldItalic
,
this
.
fontFallback
=
const
[],
this
.
fontSize
,
this
.
fontWeight
,
this
.
fontStyle
,
...
...
@@ -165,6 +166,7 @@ class TextStyle {
fontBold:
Font
.
helveticaBold
(),
fontItalic:
Font
.
helveticaOblique
(),
fontBoldItalic:
Font
.
helveticaBoldOblique
(),
fontFallback:
const
[],
fontSize:
_defaultFontSize
,
fontWeight:
FontWeight
.
normal
,
fontStyle:
FontStyle
.
normal
,
...
...
@@ -192,7 +194,10 @@ class TextStyle {
final
Font
?
fontBoldItalic
;
// font height, in pdf unit
/// The ordered list of font to fall back on when a glyph cannot be found in a higher priority font.
final
List
<
Font
>
fontFallback
;
/// font height, in pdf unit
final
double
?
fontSize
;
/// The typeface thickness to use when painting the text (e.g., bold).
...
...
@@ -233,6 +238,7 @@ class TextStyle {
Font
?
fontBold
,
Font
?
fontItalic
,
Font
?
fontBoldItalic
,
List
<
Font
>?
fontFallback
,
double
?
fontSize
,
FontWeight
?
fontWeight
,
FontStyle
?
fontStyle
,
...
...
@@ -255,6 +261,7 @@ class TextStyle {
fontBold:
fontBold
??
this
.
fontBold
,
fontItalic:
fontItalic
??
this
.
fontItalic
,
fontBoldItalic:
fontBoldItalic
??
this
.
fontBoldItalic
,
fontFallback:
fontFallback
??
this
.
fontFallback
,
fontSize:
fontSize
??
this
.
fontSize
,
fontWeight:
fontWeight
??
this
.
fontWeight
,
fontStyle:
fontStyle
??
this
.
fontStyle
,
...
...
@@ -339,6 +346,7 @@ class TextStyle {
fontBold:
other
.
fontBold
,
fontItalic:
other
.
fontItalic
,
fontBoldItalic:
other
.
fontBoldItalic
,
fontFallback:
[...
other
.
fontFallback
,
...
fontFallback
],
fontSize:
other
.
fontSize
,
fontWeight:
other
.
fontWeight
,
fontStyle:
other
.
fontStyle
,
...
...
pdf/lib/src/widgets/theme.dart
View file @
eefce19
...
...
@@ -23,6 +23,8 @@ import 'text.dart';
import
'text_style.dart'
;
import
'widget.dart'
;
typedef
DefaultThemeDataBuilder
=
ThemeData
Function
();
@immutable
class
ThemeData
extends
Inherited
{
factory
ThemeData
({
...
...
@@ -100,6 +102,7 @@ class ThemeData extends Inherited {
Font
?
italic
,
Font
?
boldItalic
,
Font
?
icons
,
List
<
Font
>?
fontFallback
,
})
{
final
defaultStyle
=
TextStyle
.
defaultStyle
().
copyWith
(
font:
base
,
...
...
@@ -107,6 +110,7 @@ class ThemeData extends Inherited {
fontBold:
bold
,
fontItalic:
italic
,
fontBoldItalic:
boldItalic
,
fontFallback:
fontFallback
,
);
final
fontSize
=
defaultStyle
.
fontSize
!;
...
...
@@ -130,7 +134,34 @@ class ThemeData extends Inherited {
);
}
factory
ThemeData
.
base
()
=>
ThemeData
.
withFont
();
factory
ThemeData
.
base
()
=>
buildThemeData
==
null
?
ThemeData
.
withFont
()
:
buildThemeData
!();
static
DefaultThemeDataBuilder
?
buildThemeData
;
final
TextStyle
defaultTextStyle
;
final
TextStyle
paragraphStyle
;
final
TextStyle
header0
;
final
TextStyle
header1
;
final
TextStyle
header2
;
final
TextStyle
header3
;
final
TextStyle
header4
;
final
TextStyle
header5
;
final
TextStyle
bulletStyle
;
final
TextStyle
tableHeader
;
final
TextStyle
tableCell
;
final
TextAlign
textAlign
;
final
bool
softWrap
;
final
int
?
maxLines
;
final
TextOverflow
overflow
;
final
IconThemeData
iconTheme
;
ThemeData
copyWith
({
TextStyle
?
defaultTextStyle
,
...
...
@@ -168,30 +199,6 @@ class ThemeData extends Inherited {
maxLines:
maxLines
??
this
.
maxLines
,
iconTheme:
iconTheme
??
this
.
iconTheme
,
);
final
TextStyle
defaultTextStyle
;
final
TextStyle
paragraphStyle
;
final
TextStyle
header0
;
final
TextStyle
header1
;
final
TextStyle
header2
;
final
TextStyle
header3
;
final
TextStyle
header4
;
final
TextStyle
header5
;
final
TextStyle
bulletStyle
;
final
TextStyle
tableHeader
;
final
TextStyle
tableCell
;
final
TextAlign
textAlign
;
final
bool
softWrap
;
final
int
?
maxLines
;
final
TextOverflow
overflow
;
final
IconThemeData
iconTheme
;
}
class
Theme
extends
StatelessWidget
{
...
...
pdf/test/widget_text_test.dart
View file @
eefce19
...
...
@@ -24,9 +24,9 @@ import 'package:test/test.dart';
import
'utils.dart'
;
late
Document
pdf
;
Font
?
ttf
;
Font
?
ttfBold
;
Font
?
asian
;
late
Font
ttf
;
late
Font
ttfBold
;
late
Font
asian
;
Iterable
<
TextDecoration
>
permute
(
List
<
TextDecoration
>
prefix
,
List
<
TextDecoration
>
remaining
)
sync
*
{
...
...
test/golden/arabic.pdf
View file @
eefce19
No preview for this file type
Please
register
or
login
to post a comment