PdfContent.parse constructor
PdfContent.parse(
- Uint8List bytes, {
- required PdfInflate inflate,
Reads bytes, a whole PDF file with exactly one page.
Objects are found by a sequential scan for N G obj … endobj. The
scan never looks inside a stream's data, so the xref table is not
needed.
Implementation
factory PdfContent.parse(Uint8List bytes, {required PdfInflate inflate}) {
final file = _PdfFile(latin1.decode(bytes), inflate);
final pages = [
for (final o in file.objects.values)
if (o.value case final Map<String, Object?> d
when d['/Type'] == const PdfRawName('/Page'))
d,
];
if (pages.length != 1) {
throw FormatException('expected one /Page, found ${pages.length}');
}
final page = pages.single;
final mediaBox = [
for (final v in file.resolve(page['/MediaBox']) as List<Object?>)
(file.resolve(v) as num).toDouble(),
];
// A page with nothing painted has no /Contents at all: the pdf package
// drops a content stream that painted nothing.
final contents = file.resolve(page['/Contents']);
final parts = <String>[];
for (final c in contents == null
? const <Object?>[]
: contents is List<Object?>
? contents
: [contents]) {
parts.add(latin1.decode(file.streamData(file.resolve(c))));
}
final resources =
file.resolve(page['/Resources']) as Map<String, Object?>? ?? const {};
final interpreter = _Interpreter(file, resources);
// Content streams of one page are one stream for parsing (ISO 32000-1,
// 7.8.2), separated by whitespace.
interpreter.run(parts.join('\n'));
return PdfContent._(
mediaBox,
interpreter.operators,
interpreter.paths,
interpreter.texts,
);
}