Tyler Denniston
Committed by David PHAM-VAN

Add support for custom fonts in SVGs.

This adds the interface `SvgCustomFonts` and a corresponding parameter
to the SvgImage widget. This provides a mechanism to support SVGs that
have known fonts referenced in them.

Closes #1731.
# Changelog
## 3.11.2
- Add support for custom fonts in SVGs. [Tyler Denniston]
## 3.11.1
- Fixed display problems with textfields [ilaurillard]
... ...
... ... @@ -16,6 +16,7 @@
import '../../pdf.dart';
import '../widgets/font.dart';
import '../widgets/svg.dart';
import 'brush.dart';
import 'color.dart';
import 'group.dart';
... ... @@ -26,8 +27,9 @@ class SvgPainter {
this.parser,
this._canvas,
this.document,
this.boundingBox,
);
this.boundingBox, {
this.customFontLookup,
});
final SvgParser parser;
... ... @@ -37,6 +39,8 @@ class SvgPainter {
final PdfRect boundingBox;
final SvgCustomFontLookup? customFontLookup;
void paint() {
final brush = parser.colorFilter == null
? SvgBrush.defaultContext
... ... @@ -59,6 +63,12 @@ class SvgPainter {
}
Font getFont(String fontFamily, String fontStyle, String fontWeight) {
final customFont =
customFontLookup?.call(fontFamily, fontStyle, fontWeight);
if (customFont != null) {
return customFont;
}
switch (fontFamily) {
case 'serif':
switch (fontStyle) {
... ...
... ... @@ -32,6 +32,7 @@ class SvgImage extends Widget {
double? width,
double? height,
PdfColor? colorFilter,
SvgCustomFontLookup? customFontLookup,
}) {
final xml = XmlDocument.parse(svg);
final parser = SvgParser(
... ... @@ -46,6 +47,7 @@ class SvgImage extends Widget {
clip,
width,
height,
customFontLookup,
);
}
... ... @@ -56,6 +58,7 @@ class SvgImage extends Widget {
this.clip,
this.width,
this.height,
this.customFontLookup,
);
final SvgParser _svgParser;
... ... @@ -70,6 +73,8 @@ class SvgImage extends Widget {
final double? height;
final SvgCustomFontLookup? customFontLookup;
late FittedSizes sizes;
@override
... ... @@ -126,6 +131,7 @@ class SvgImage extends Widget {
context.page.pageFormat.width,
context.page.pageFormat.height,
),
customFontLookup: customFontLookup,
);
painter.paint();
context.canvas.restoreContext();
... ... @@ -154,3 +160,6 @@ class DecorationSvgImage extends DecorationGraphic {
);
}
}
typedef SvgCustomFontLookup = Font? Function(
String fontFamily, String fontStyle, String fontWeight);
... ...
... ... @@ -12,7 +12,7 @@ topics:
- print
- printing
- report
version: 3.11.1
version: 3.11.2
environment:
sdk: ">=2.19.0 <4.0.0"
... ...
... ... @@ -20,6 +20,8 @@ import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
import 'package:test/test.dart';
import 'utils.dart';
late Document pdf;
void main() {
... ... @@ -195,6 +197,31 @@ void main() {
);
});
test('SVG Widgets Text custom fonts', () {
const customFamilyName1 = 'Test-Font-Family1';
const customFamilyName2 = 'Test-Font-Family2';
final customFont1 = loadFont('open-sans-bold.ttf');
final customFont2 = loadFont('genyomintw.ttf');
pdf.addPage(
Page(
build: (context) => SvgImage(
svg:
'<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg viewBox="0 0 1000 300" xmlns="http://www.w3.org/2000/svg" version="1.1"><text x="367.055" y="168.954" font-size="55" fill="darkgreen" font-family="$customFamilyName1" >Custom <tspan font-family="$customFamilyName2">fonts</tspan></text><rect x="1" y="1" width="998" height="298" fill="none" stroke="purple" stroke-width="2" /></svg>',
customFontLookup:
(String fontFamily, String fontStyle, String fontWeight) {
switch (fontFamily) {
case customFamilyName1:
return customFont1;
case customFamilyName2:
return customFont2;
default:
return null;
}
}),
),
);
});
tearDownAll(() async {
final file = File('widgets-svg.pdf');
await file.writeAsBytes(await pdf.save());
... ...