buildIncrement method

Future<Uint8List> buildIncrement()

Implementation

Future<Uint8List> buildIncrement() async {
  final BytesBuilder out = BytesBuilder(copy: false);
  final int base = document.source.length;
  final Map<int, int> offsets = <int, int>{};
  final List<int> numbers = _changed.keys.toList()..sort();
  final UPdfEncryption? encryption = document.encryption;
  out.add("\n".codeUnits);
  int cursor = base + 1;
  for (final int number in numbers) {
    final Object? value = _changed[number];
    final BytesBuilder body = BytesBuilder(copy: false);
    body.add("$number 0 obj\n".codeUnits);
    if (value == null) {
      body.add("null".codeUnits);
    } else {
      UPdfSerializer.write(body, value, encryption: encryption, objectNumber: number);
    }
    body.add("\nendobj\n".codeUnits);
    final Uint8List bytes = body.takeBytes();
    offsets[number] = value == null ? -1 : cursor;
    cursor += bytes.length;
    out.add(bytes);
  }
  final int xrefOffset = cursor;
  final BytesBuilder table = BytesBuilder(copy: false);
  table.add("xref\n".codeUnits);
  final List<List<int>> runs = <List<int>>[];
  for (final int number in numbers) {
    if (runs.isNotEmpty && runs.last.last + 1 == number) {
      runs.last.add(number);
    } else {
      runs.add(<int>[number]);
    }
  }
  for (final List<int> run in runs) {
    table.add("${run.first} ${run.length}\n".codeUnits);
    for (final int number in run) {
      final int offset = offsets[number] ?? -1;
      if (offset < 0) {
        table.add("0000000000 65535 f \n".codeUnits);
      } else {
        table.add("${offset.toString().padLeft(10, "0")} 00000 n \n".codeUnits);
      }
    }
  }
  int highest = 0;
  for (final int number in numbers) {
    if (number > highest) highest = number;
  }
  for (final int number in document.xref.entries.keys) {
    if (number > highest) highest = number;
  }
  final UPdfDict trailer = UPdfDict(<String, Object?>{
    "Size": highest + 1,
    if (document.xref.trailer?["Root"] != null) "Root": document.xref.trailer!["Root"],
    if (document.xref.trailer?["Info"] != null) "Info": document.xref.trailer!["Info"],
    if (document.xref.trailer?["Encrypt"] != null) "Encrypt": document.xref.trailer!["Encrypt"],
    if (document.xref.trailer?["ID"] != null) "ID": document.xref.trailer!["ID"],
    if (document.startXrefOffset >= 0) "Prev": document.startXrefOffset,
  });
  table.add("trailer\n".codeUnits);
  UPdfSerializer.write(table, trailer);
  table.add("\nstartxref\n$xrefOffset\n%%EOF\n".codeUnits);
  out.add(table.takeBytes());
  return out.takeBytes();
}