David PHAM-VAN

First Import

  1 +# Files and directories created by pub
  2 +.dart_tool/
  3 +.packages
  4 +.pub/
  5 +build/
  6 +# If you're building an application, you may want to check-in your pubspec.lock
  7 +pubspec.lock
  8 +
  9 +# Directory created by dartdoc
  10 +# If you don't generate documentation locally you can remove this line.
  11 +doc/api/
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +library pdf;
  20 +
  21 +/// http://www.mactech.com/articles/mactech/Vol.15/15.09/PDFIntro/index.html
  22 +/// https://brendanzagaeski.appspot.com/0004.html
  23 +/// http://blog.idrsolutions.com/?s=%22Make+your+own+PDF+file%22
  24 +/// https://brendanzagaeski.appspot.com/0005.html
  25 +/// https://github.com/Setasign/FPDF
  26 +/// https://github.com/rev42/tfpdf/blob/master/src/tFPDF.php
  27 +/// http://gnujpdf.sourceforge.net
  28 +/// http://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf
  29 +/// https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
  30 +/// https://www.pdf-online.com/osa/validate.aspx
  31 +
  32 +import 'dart:convert';
  33 +import 'dart:io';
  34 +import 'dart:typed_data';
  35 +import 'package:vector_math/vector_math_64.dart';
  36 +import 'package:image/image.dart';
  37 +import 'package:ttf_parser/ttf_parser.dart';
  38 +
  39 +part 'src/ascii85.dart';
  40 +part 'src/array.dart';
  41 +part 'src/border.dart';
  42 +part 'src/catalog.dart';
  43 +part 'src/color.dart';
  44 +part 'src/document.dart';
  45 +part 'src/font.dart';
  46 +part 'src/font_descriptor.dart';
  47 +part 'src/formxobject.dart';
  48 +part 'src/info.dart';
  49 +part 'src/object.dart';
  50 +part 'src/object_stream.dart';
  51 +part 'src/outline.dart';
  52 +part 'src/output.dart';
  53 +part 'src/page.dart';
  54 +part 'src/page_format.dart';
  55 +part 'src/page_list.dart';
  56 +part 'src/point.dart';
  57 +part 'src/polygon.dart';
  58 +part 'src/annotation.dart';
  59 +part 'src/graphics.dart';
  60 +part 'src/image.dart';
  61 +part 'src/rect.dart';
  62 +part 'src/stream.dart';
  63 +part 'src/ttffont.dart';
  64 +part 'src/xobject.dart';
  65 +part 'src/xref.dart';
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFAnnot extends PDFObject {
  22 + /// Solid border. The border is drawn as a solid line.
  23 + static const SOLID = 0;
  24 +
  25 + /// The border is drawn with a dashed line.
  26 + static const DASHED = 1;
  27 +
  28 + /// The border is drawn in a beveled style (faux three-dimensional) such
  29 + /// that it looks as if it is pushed out of the page (opposite of INSET)
  30 + static const BEVELED = 2;
  31 +
  32 + /// The border is drawn in an inset style (faux three-dimensional) such
  33 + /// that it looks as if it is inset into the page (opposite of BEVELED)
  34 + static const INSET = 3;
  35 +
  36 + /// The border is drawn as a line on the bottom of the annotation rectangle
  37 + static const UNDERLINED = 4;
  38 +
  39 + /// The subtype of the outline, ie text, note, etc
  40 + final String subtype;
  41 +
  42 + /// The size of the annotation
  43 + final double l, b, r, t;
  44 +
  45 + /// The text of a text annotation
  46 + final String s;
  47 +
  48 + /// flag used to indicate that the destination should fit the screen
  49 + static const FULL_PAGE = -9999.0;
  50 +
  51 + /// Link to the Destination page
  52 + PDFObject dest;
  53 +
  54 + /// If fl!=FULL_PAGE then this is the region of the destination page shown.
  55 + /// Otherwise they are ignored.
  56 + final double fl, fb, fr, ft;
  57 +
  58 + /// the border for this annotation
  59 + PDFBorder border;
  60 +
  61 + PDFAnnot(PDFPage pdfPage,
  62 + {String type, this.s, this.l, this.b, this.r, this.t, this.subtype, this.dest, this.fl, this.fb, this.fr, this.ft})
  63 + : super(pdfPage.pdfDocument, type) {
  64 + pdfPage.annotations.add(this);
  65 + }
  66 +
  67 + /// This is used to create an annotation.
  68 + /// @param s Subtype for this annotation
  69 + /// @param l Left coordinate
  70 + /// @param b Bottom coordinate
  71 + /// @param r Right coordinate
  72 + /// @param t Top coordinate
  73 + factory PDFAnnot.annotation(PDFPage pdfPage, String s, double l, double b, double r, double t) =>
  74 + new PDFAnnot(pdfPage, type: "/Annot", s: s, l: l, b: b, r: r, t: t);
  75 +
  76 + /// Creates a text annotation
  77 + /// @param l Left coordinate
  78 + /// @param b Bottom coordinate
  79 + /// @param r Right coordinate
  80 + /// @param t Top coordinate
  81 + /// @param s Text for this annotation
  82 + factory PDFAnnot.text(PDFPage pdfPage, double l, double b, double r, double t, String s) =>
  83 + new PDFAnnot(pdfPage, type: "/Text", l: l, b: b, r: r, t: t, s: s);
  84 +
  85 + /// Creates a link annotation
  86 + /// @param l Left coordinate
  87 + /// @param b Bottom coordinate
  88 + /// @param r Right coordinate
  89 + /// @param t Top coordinate
  90 + /// @param dest Destination for this link. The page will fit the display.
  91 + /// @param fl Left coordinate
  92 + /// @param fb Bottom coordinate
  93 + /// @param fr Right coordinate
  94 + /// @param ft Top coordinate
  95 + /// <br><br>Rectangle describing what part of the page to be displayed
  96 + /// (must be in User Coordinates)
  97 + factory PDFAnnot.link(PDFPage pdfPage, double l, double b, double r, double t, PDFObject dest,
  98 + [double fl = FULL_PAGE, double fb = FULL_PAGE, double fr = FULL_PAGE, double ft = FULL_PAGE]) =>
  99 + new PDFAnnot(pdfPage, type: "/Link", l: l, b: b, r: r, t: t, dest: dest, fl: fl, fb: fb, fr: fr, ft: ft);
  100 +
  101 + /// Sets the border for the annotation. By default, no border is defined.
  102 + ///
  103 + /// <p>If the style is DASHED, then this method uses PDF's default dash
  104 + /// scheme {3}
  105 + ///
  106 + /// <p>Important: the annotation must have been added to the document before
  107 + /// this is used. If the annotation was created using the methods in
  108 + /// PDFPage, then the annotation is already in the document.
  109 + ///
  110 + /// @param style Border style SOLID, DASHED, BEVELED, INSET or UNDERLINED.
  111 + /// @param width Width of the border
  112 + /// @param dash Array of lengths, used for drawing the dashes. If this
  113 + /// is null, then the default of {3} is used.
  114 + void setBorder(double width, {int style = 0, List<double> dash}) {
  115 + border = new PDFBorder(pdfDocument, width, style: style, dash: dash);
  116 + }
  117 +
  118 + /// Output the annotation
  119 + ///
  120 + /// @param os OutputStream to send the object to
  121 + @override
  122 + void prepare() {
  123 + super.prepare();
  124 +
  125 + params["/Subtype"] = PDFStream.string(subtype);
  126 + params["/Rect"] = PDFStream.string("[$l $b $r $t]");
  127 +
  128 + // handle the border
  129 + if (border == null) {
  130 + params["/Border"] = PDFStream.string("[0 0 0]");
  131 + } else {
  132 + params["/BS"] = border.ref();
  133 + }
  134 +
  135 + // Now the annotation subtypes
  136 + if (subtype == "/Text") {
  137 + params["/Contents"] = PDFStream.string(s);
  138 + } else if (subtype == "/Link") {
  139 + var dests = new List<PDFStream>();
  140 + dests.add(dest.ref());
  141 + if (fl == FULL_PAGE)
  142 + dests.add(PDFStream.string("/Fit"));
  143 + else {
  144 + dests.add(PDFStream.string("/FitR $fl $fb $fr $ft"));
  145 + }
  146 + params["/Dest"] = PDFStream.array(dests);
  147 + }
  148 + }
  149 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFArrayObject extends PDFObject {
  22 + final List<String> values;
  23 +
  24 + PDFArrayObject(PDFDocument pdfDocument, this.values) : super(pdfDocument);
  25 +
  26 + @override
  27 + void writeContent(PDFStream os) {
  28 + super.writeContent(os);
  29 +
  30 + os.putStringArray(values);
  31 + }
  32 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class Ascii85Encoder extends Converter<Uint8List, Uint8List> {
  22 + Uint8List convert(Uint8List input) {
  23 + Uint8List buffer = new Uint8List(_maxEncodedLen(input.length) + 2);
  24 +
  25 + var b = 0;
  26 + var s = 0;
  27 +
  28 + while (s < input.length) {
  29 + buffer[b + 0] = 0;
  30 + buffer[b + 1] = 0;
  31 + buffer[b + 2] = 0;
  32 + buffer[b + 3] = 0;
  33 + buffer[b + 4] = 0;
  34 +
  35 + // Unpack 4 bytes into int to repack into base 85 5-byte.
  36 + int v = 0;
  37 +
  38 + switch (input.length - s) {
  39 + case 3:
  40 + v |= input[s + 0] << 24;
  41 + v |= input[s + 1] << 16;
  42 + v |= input[s + 2] << 8;
  43 + break;
  44 + case 2:
  45 + v |= input[s + 0] << 24;
  46 + v |= input[s + 1] << 16;
  47 + break;
  48 + case 1:
  49 + v |= input[s + 0] << 24;
  50 + break;
  51 + default:
  52 + v |= input[s + 0] << 24;
  53 + v |= input[s + 1] << 16;
  54 + v |= input[s + 2] << 8;
  55 + v |= input[s + 3];
  56 + }
  57 +
  58 + // Special case: zero (!!!!!) shortens to z.
  59 + if (v == 0 && input.length - s >= 4) {
  60 + buffer[b] = 122;
  61 + b++;
  62 + s += 4;
  63 + continue;
  64 + }
  65 +
  66 + // Otherwise, 5 base 85 digits starting at !.
  67 + for (int i = 4; i >= 0; i--) {
  68 + buffer[b + i] = 33 + v % 85;
  69 + v ~/= 85;
  70 + }
  71 +
  72 + // If input was short, discard the low destination bytes.
  73 + var m = 5;
  74 + if (input.length - s < 4) {
  75 + m -= 4 - (input.length - s);
  76 + break;
  77 + } else {
  78 + s += 4;
  79 + }
  80 +
  81 + b += m;
  82 + }
  83 +
  84 + buffer[b] = 0x7e;
  85 + buffer[b + 1] = 0x3e;
  86 +
  87 + return buffer.sublist(0, b + 2);
  88 + }
  89 +
  90 + int _maxEncodedLen(int n) => (n + 3) ~/ 4 * 5;
  91 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFBorder extends PDFObject {
  22 + /// The style of the border
  23 + final int style;
  24 +
  25 + /// The width of the border
  26 + final double width;
  27 +
  28 + /// This array allows the definition of a dotted line for the border
  29 + final List<double> dash;
  30 +
  31 + /// Creates a border using the predefined styles in PDFAnnot.
  32 + /// <p>Note: Do not use PDFAnnot.DASHED with this method.
  33 + /// Use the other constructor.
  34 + ///
  35 + /// @param width The width of the border
  36 + /// @param style The style of the border
  37 + /// @param dash The line pattern definition
  38 + /// @see PDFAnnot
  39 + PDFBorder(PDFDocument pdfDocument, this.width, {this.style = 0, this.dash}) : super(pdfDocument);
  40 +
  41 + /// @param os OutputStream to send the object to
  42 + @override
  43 + void writeContent(PDFStream os) {
  44 + super.writeContent(os);
  45 +
  46 + var data = new List<PDFStream>();
  47 + data.add(PDFStream.string("/S"));
  48 + data.add(PDFStream.string("/" + "SDBIU".substring(style, style + 1)));
  49 + data.add(PDFStream.string("/W $width"));
  50 + if (dash != null) {
  51 + data.add(PDFStream.string("/D"));
  52 + data.add(PDFStream.array(dash.map((double d) => PDFStream.num(d))));
  53 + }
  54 + os.putArray(data);
  55 + }
  56 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFCatalog extends PDFObject {
  22 + /// The pages of the document
  23 + final PDFPageList pdfPageList;
  24 +
  25 + /// The outlines of the document
  26 + PDFOutline outlines;
  27 +
  28 + /// The initial page mode
  29 + final PDFPageMode pageMode;
  30 +
  31 + /// This constructs a PDF Catalog object
  32 + ///
  33 + /// @param pdfPageList The PDFPageList object that's the root
  34 + /// of the documents page tree
  35 + /// @param pagemode How the document should appear when opened.
  36 + /// Allowed values are USENONE, USEOUTLINES, USETHUMBS or FULLSCREEN.
  37 + PDFCatalog(PDFDocument pdfDocument, this.pdfPageList, this.pageMode) : super(pdfDocument, "/Catalog");
  38 +
  39 + /// @param os OutputStream to send the object to
  40 + @override
  41 + void prepare() {
  42 + super.prepare();
  43 +
  44 + params["/Pages"] = pdfPageList.ref();
  45 +
  46 + // the Outlines object
  47 + if (outlines != null && outlines.outlines.length > 0) {
  48 + params["/Outlines"] = outlines.ref();
  49 + }
  50 +
  51 + // the /PageMode setting
  52 + params["/PageMode"] = PDFStream.string(PDFDocument._PDF_PAGE_MODES[pageMode.index]);
  53 + }
  54 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFColor {
  22 + final double a;
  23 + final double r;
  24 + final double g;
  25 + final double b;
  26 +
  27 + static var black = new PDFColor(0.0, 0.0, 0.0);
  28 +
  29 + PDFColor(this.r, this.g, this.b, [this.a = 1.0]);
  30 +
  31 + factory PDFColor.fromInt(int color) {
  32 + return new PDFColor(
  33 + (color >> 16 & 0xff) / 255.0, (color >> 8 & 0xff) / 255.0, (color & 0xff) / 255.0, (color >> 24 & 0xff) / 255.0);
  34 + }
  35 +
  36 + factory PDFColor.fromHex(String color) {
  37 + return new PDFColor(
  38 + (int.parse(color.substring(0, 1), radix: 16) >> 16 & 0xff) / 255.0,
  39 + (int.parse(color.substring(2, 3), radix: 16) >> 8 & 0xff) / 255.0,
  40 + (int.parse(color.substring(4, 5), radix: 16) & 0xff) / 255.0,
  41 + (int.parse(color.substring(6, 7), radix: 16) >> 24 & 0xff) / 255.0);
  42 + }
  43 +
  44 + int toInt() =>
  45 + ((((a * 255.0).round() & 0xff) << 24) |
  46 + (((r * 255.0).round() & 0xff) << 16) |
  47 + (((g * 255.0).round() & 0xff) << 8) |
  48 + (((b * 255.0).round() & 0xff) << 0)) &
  49 + 0xFFFFFFFF;
  50 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +enum PDFPageMode {
  22 + /// This page mode indicates that the document
  23 + /// should be opened just with the page visible. This is the default
  24 + NONE,
  25 +
  26 + /// This page mode indicates that the Outlines
  27 + /// should also be displayed when the document is opened.
  28 + OUTLINES,
  29 +
  30 + /// This page mode indicates that the Thumbnails should be visible when the
  31 + /// document first opens.
  32 + THUMBS,
  33 +
  34 + /// This page mode indicates that when the document is opened, it is displayed
  35 + /// in full-screen-mode. There is no menu bar, window controls nor any other
  36 + /// window present.
  37 + FULLSCREEN
  38 +}
  39 +
  40 +/// <p>This class is the base of the PDF generator. A PDFDocument class is
  41 +/// created for a document, and each page, object, annotation,
  42 +/// etc is added to the document.
  43 +/// Once complete, the document can be written to a Stream, and the PDF
  44 +/// document's internal structures are kept in sync.
  45 +class PDFDocument {
  46 + /// This is used to allocate objects a unique serial number in the document.
  47 + int _objser;
  48 +
  49 + /// This vector contains each indirect object within the document.
  50 + final Set<PDFObject> objects = new Set<PDFObject>();
  51 +
  52 + /// This is the Catalog object, which is required by each PDF Document
  53 + PDFCatalog catalog;
  54 +
  55 + /// This is the info object. Although this is an optional object, we
  56 + /// include it.
  57 + PDFInfo info;
  58 +
  59 + /// This is the Pages object, which is required by each PDF Document
  60 + PDFPageList pdfPageList;
  61 +
  62 + /// This is the Outline object, which is optional
  63 + PDFOutline _outline;
  64 +
  65 + /// This holds a PDFObject describing the default border for annotations.
  66 + /// It's only used when the document is being written.
  67 + PDFObject defaultOutlineBorder;
  68 +
  69 + /// True if we will compress the stream in the pdf file
  70 + final bool deflate;
  71 +
  72 + /// <p>
  73 + /// These map the page modes just defined to the pagemodes setting of PDF.
  74 + /// </p>
  75 + static const _PDF_PAGE_MODES = const ["/UseNone", "/UseOutlines", "/UseThumbs", "/FullScreen"];
  76 +
  77 + /// This holds the current fonts
  78 + final Set<PDFFont> fonts = new Set<PDFFont>();
  79 +
  80 + /// Creates a new serial number
  81 + int _genSerial() => _objser++;
  82 +
  83 + /// <p>This creates a PDF document</p>
  84 + /// @param pagemode an int, determines how the document will present itself to
  85 + /// the viewer when it first opens.
  86 + PDFDocument({PDFPageMode pageMode = PDFPageMode.NONE, this.deflate = true}) {
  87 + _objser = 1;
  88 +
  89 + // Now create some standard objects
  90 + pdfPageList = new PDFPageList(this);
  91 + catalog = new PDFCatalog(this, pdfPageList, pageMode);
  92 + info = new PDFInfo(this);
  93 + }
  94 +
  95 + /// <p>This returns a specific page. It's used mainly when using a
  96 + /// Serialized template file.</p>
  97 + ///
  98 + /// ?? How does a serialized template file work ???
  99 + ///
  100 + /// @param page page number to return
  101 + /// @return PDFPage at that position
  102 + PDFPage page(int page) {
  103 + return pdfPageList.getPage(page);
  104 + }
  105 +
  106 + /// @return the root outline
  107 + PDFOutline get outline {
  108 + if (_outline == null) {
  109 + _outline = new PDFOutline(this);
  110 + catalog.outlines = _outline;
  111 + }
  112 + return _outline;
  113 + }
  114 +
  115 + /// This writes the document to an OutputStream.
  116 + ///
  117 + /// <p><b>Note:</b> You can call this as many times as you wish, as long as
  118 + /// the calls are not running at the same time.
  119 + ///
  120 + /// <p>Also, objects can be added or amended between these calls.
  121 + ///
  122 + /// <p>Also, the OutputStream is not closed, but will be flushed on
  123 + /// completion. It is up to the caller to close the stream.
  124 + ///
  125 + /// @param os OutputStream to write the document to
  126 + void write(PDFStream os) {
  127 + PDFOutput pos = new PDFOutput(os);
  128 +
  129 + // Write each object to the PDFStream. We call via the output
  130 + // as that builds the xref table
  131 + for (PDFObject o in objects) {
  132 + pos.write(o);
  133 + }
  134 +
  135 + // Finally close the output, which writes the xref table.
  136 + pos.close();
  137 + }
  138 +
  139 + Uint8List save() {
  140 + PDFStream os = new PDFStream();
  141 + write(os);
  142 + return os.output();
  143 + }
  144 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFFont extends PDFObject {
  22 + /// The PDF type of the font, usually /Type1
  23 + final String subtype;
  24 +
  25 + /// The font's real name
  26 + String baseFont;
  27 +
  28 + /// Constructs a PDFFont. This will attempt to map the font from a known
  29 + /// Java font name to that in PDF, defaulting to Helvetica if not possible.
  30 + ///
  31 + /// @param name The document name, ie /F1
  32 + /// @param type The pdf type, ie /Type1
  33 + /// @param font The font name, ie Helvetica
  34 + /// @param style The java.awt.Font style, ie: Font.PLAIN
  35 + PDFFont(PDFDocument pdfDocument, {this.subtype = "/Type1", this.baseFont = "/Helvetica"}) : super(pdfDocument, "/Font") {
  36 + pdfDocument.fonts.add(this);
  37 + }
  38 +
  39 + String get name => "/F$objser";
  40 +
  41 + /// @param os OutputStream to send the object to
  42 + @override
  43 + void prepare() {
  44 + super.prepare();
  45 +
  46 + params["/Subtype"] = PDFStream.string(subtype);
  47 + params["/Name"] = PDFStream.string(name);
  48 + params["/BaseFont"] = PDFStream.string(baseFont);
  49 + params["/Encoding"] = PDFStream.string("/WinAnsiEncoding");
  50 + }
  51 +
  52 + double glyphAdvance(int charCode) {
  53 + return 0.454;
  54 + }
  55 +
  56 + PDFRect glyphBounds(int charCode) {
  57 + return const PDFRect(0.0, 0.0, 0.4, 1.0);
  58 + }
  59 +
  60 + PDFRect stringBounds(String s) {
  61 + var chars = LATIN1.encode(s);
  62 +
  63 + if (chars.length == 0) return const PDFRect(0.0, 0.0, 0.0, 0.0);
  64 +
  65 + var n = 0;
  66 + var c = chars[n];
  67 + var r = glyphBounds(c);
  68 + var x = r.x;
  69 + var y = r.y;
  70 + var h = r.h;
  71 + var w = n == chars.length - 1 ? r.w : glyphAdvance(c);
  72 +
  73 + while (++n < chars.length) {
  74 + c = chars[n];
  75 + r = glyphBounds(c);
  76 + if (r.y < y) y = r.y;
  77 + if (r.h > h) h = r.h;
  78 + w += n == chars.length - 1 ? r.w : glyphAdvance(c);
  79 + }
  80 +
  81 + return new PDFRect(x, y, w, h);
  82 + }
  83 +
  84 + PDFPoint stringSize(String s) {
  85 + var chars = LATIN1.encode(s);
  86 +
  87 + var w = 0.0;
  88 + var h = 0.0;
  89 +
  90 + for (var c in chars) {
  91 + var r = glyphBounds(c);
  92 + if (r.h > h) h = r.h;
  93 + w += glyphAdvance(c);
  94 + }
  95 +
  96 + return new PDFPoint(w, h);
  97 + }
  98 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFFontDescriptor extends PDFObject {
  22 + final PDFObjectStream file;
  23 + final TtfFont font;
  24 + final PDFTTFFont ttfFont;
  25 +
  26 + PDFFontDescriptor(this.ttfFont, this.file, this.font) : super(ttfFont.pdfDocument, "/FontDescriptor");
  27 +
  28 + @override
  29 + void prepare() {
  30 + super.prepare();
  31 +
  32 + params["/FontName"] = PDFStream.string(ttfFont.baseFont);
  33 + params["/FontFile2"] = file.ref();
  34 + params["/Flags"] = PDFStream.intNum(32);
  35 + params["/FontBBox"] = new PDFStream()..putStringArray([font.head.xMin, font.head.yMin, font.head.xMax, font.head.yMax]);
  36 + params["/Ascent"] = PDFStream.intNum(font.hhea.ascent);
  37 + params["/Descent"] = PDFStream.intNum(font.hhea.descent);
  38 + params["/ItalicAngle"] = PDFStream.intNum(0);
  39 + params["/CapHeight"] = PDFStream.intNum(10);
  40 + params["/StemV"] = PDFStream.intNum(79);
  41 + }
  42 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFFormXObject extends PDFXObject {
  22 + /// The fonts associated with this page
  23 + final fonts = new Map<String, PDFFont>();
  24 +
  25 + /// The xobjects or other images in the pdf
  26 + final xobjects = new Map<String, PDFXObject>();
  27 +
  28 + PDFFormXObject(PDFDocument pdfDocument) : super(pdfDocument, '/Form') {
  29 + params["/FormType"] = PDFStream.string("1");
  30 + params["/BBox"] = PDFStream.string("[0 0 1000 1000]");
  31 + }
  32 +
  33 + /// set matrix
  34 + void setMatrix(Matrix4 t) {
  35 + var s = t.storage;
  36 + params["/Matrix"] = PDFStream.string("[${s[0]} ${s[1]} ${s[4]} ${s[5]} ${s[12]} ${s[13]}]");
  37 + }
  38 +
  39 + @override
  40 + void prepare() {
  41 + super.prepare();
  42 +
  43 + // Now the resources
  44 + /// This holds any resources for this FormXObject
  45 + final resources = new Map<String, PDFStream>();
  46 +
  47 + // fonts
  48 + if (fonts.length > 0) {
  49 + resources["/Font"] = new PDFStream()..putObjectDictionary(fonts);
  50 + }
  51 +
  52 + // Now the XObjects
  53 + if (xobjects.length > 0) {
  54 + resources["/XObject"] = new PDFStream()..putObjectDictionary(xobjects);
  55 + }
  56 +
  57 + if (resources.length > 0) {
  58 + params["/Resources"] = PDFStream.dictionary(resources);
  59 + }
  60 + }
  61 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +enum PDFLineCap { JOIN_MITER, JOIN_ROUND, JOIN_BEVEL }
  22 +
  23 +class PDFGraphics {
  24 + /// Graphic context number
  25 + var _context = 0;
  26 +
  27 + final PDFPage page;
  28 +
  29 + final PDFStream buf;
  30 +
  31 + PDFGraphics(this.page, this.buf);
  32 +
  33 + PDFFont get defaultFont {
  34 + if (page.pdfDocument.fonts.length == 0) {
  35 + new PDFFont(page.pdfDocument);
  36 + }
  37 +
  38 + return page.pdfDocument.fonts.elementAt(0);
  39 + }
  40 +
  41 + void fillPath() {
  42 + buf.putString("f\n");
  43 + }
  44 +
  45 + void strokePath() {
  46 + buf.putString("S\n");
  47 + }
  48 +
  49 + void closePath() {
  50 + buf.putString("s\n");
  51 + }
  52 +
  53 + void clipPath() {
  54 + buf.putString("W n\n");
  55 + }
  56 +
  57 + /// <p>This releases any resources used by this Graphics object. You must use
  58 + /// this method once finished with it. Leaving it open will leave the PDF
  59 + /// stream in an inconsistent state, and will produce errors.</p>
  60 + /// <p>
  61 + /// <p>If this was created with Graphics.create() then the parent instance
  62 + /// can be used again. If not, then this closes the graphics operations for
  63 + /// this page when used with PDFJob.</p>
  64 + /// <p>
  65 + /// <p>When using PDFPage, you can create another fresh Graphics instance,
  66 + /// which will draw over this one.</p>
  67 + void restoreContext() {
  68 + if (_context > 0) {
  69 + // restore graphics context
  70 + buf.putString("Q\n");
  71 + _context--;
  72 + }
  73 + }
  74 +
  75 + void saveContext() {
  76 + // save graphics context
  77 + buf.putString("q\n");
  78 + _context++;
  79 + }
  80 +
  81 + /// <p>Draws an image onto the page.</p>
  82 + /// <p>
  83 + /// <p>This method is implemented with ASCIIbase85 encoding and the
  84 + /// zip stream deflater. It results in a stream that is anywhere
  85 + /// from 3 to 10 times as big as the image. This obviously needs some
  86 + /// improvement, but it works well for small images</p>
  87 + ///
  88 + /// @param img The java.awt.Image
  89 + /// @param x coordinate on page
  90 + /// @param y coordinate on page
  91 + /// @param w Width on page
  92 + /// @param h height on page
  93 + /// @param bgcolor Background colour
  94 + /// @return true if drawn
  95 + void drawImage(PDFImage img, double x, double y, [double w, double h]) {
  96 + if (w == null) w = img.width.toDouble();
  97 + if (h == null) h = img.height.toDouble() * w / img.width.toDouble();
  98 +
  99 + // The image needs to be registered in the page resources
  100 + page.xObjects[img.name] = img;
  101 +
  102 + // q w 0 0 h x y cm % the coordinate matrix
  103 + buf.putString("q $w 0 0 $h $x $y cm ${img.name} Do Q\n");
  104 + }
  105 +
  106 + /// Draws a line between two coordinates.
  107 + /// <p>
  108 + /// If the first coordinate is the same as the last one drawn
  109 + /// (i.e. a previous drawLine, moveto, etc) it is ignored.
  110 + ///
  111 + /// @param x1 coordinate
  112 + /// @param y1 coordinate
  113 + /// @param x2 coordinate
  114 + /// @param y2 coordinate
  115 + void drawLine(double x1, double y1, double x2, double y2) {
  116 + moveTo(x1, y1);
  117 + lineTo(x2, y2);
  118 + }
  119 +
  120 + /// Draws a polygon, linking the first and last coordinates.
  121 + ///
  122 + /// @param xp Array of x coordinates
  123 + /// @param yp Array of y coordinates
  124 + /// @param np number of points in polygon
  125 + void drawPolygon(Polygon p) {
  126 + _polygon(p.points);
  127 + }
  128 +
  129 + void drawEllipse(double x, double y, double r1, double r2) {
  130 + // The best 4-spline magic number
  131 + double m4 = 0.551784;
  132 +
  133 + // Starting point
  134 + moveTo(x, y - r2);
  135 +
  136 + buf.putString("${x + m4 * r1} ${y - r2} ${x + r1} ${y - m4 * r2} ${x + r1} $y c\n");
  137 + buf.putString("${x + r1} ${y + m4 * r2} ${x + m4 * r1} ${y + r2} $x ${y + r2} c\n");
  138 + buf.putString("${x - m4 * r1} ${y + r2} ${x - r1} ${y + m4 * r2} ${x - r1} $y c\n");
  139 + buf.putString("${x - r1} ${y - m4 * r2} ${x - m4 * r1} ${y - r2} $x ${y - r2} c\n");
  140 + }
  141 +
  142 + /// We override Graphics.drawRect as it doesn't join the 4 lines.
  143 + /// Also, PDF provides us with a Rectangle operator, so we will use that.
  144 + ///
  145 + /// @param x coordinate
  146 + /// @param y coordinate
  147 + /// @param w width
  148 + /// @param h height
  149 + void drawRect(
  150 + double x,
  151 + double y,
  152 + double w,
  153 + double h,
  154 + ) {
  155 + buf.putString("$x $y $w $h re\n");
  156 + }
  157 +
  158 + /// This draws a string.
  159 + ///
  160 + /// @param x coordinate
  161 + /// @param y coordinate
  162 + /// @oaran s String to draw
  163 + void drawString(PDFFont font, size, String s, double x, double y) {
  164 + if (!page.fonts.containsKey(font.name)) {
  165 + page.fonts[font.name] = font;
  166 + }
  167 +
  168 + buf.putString("BT $x $y Td ${font.name} $size Tf ");
  169 + buf.putText(s);
  170 + buf.putString(" Tj ET\n");
  171 + }
  172 +
  173 + /// Sets the color for drawing
  174 + ///
  175 + /// @param c Color to use
  176 + void setColor(PDFColor color) {
  177 + buf.putString("${color.r} ${color.g} ${color.b} rg ${color.r} ${color.g} ${color
  178 + .b} RG\n");
  179 + }
  180 +
  181 + /// Set the transformation Matrix
  182 + void setTransform(Matrix4 t) {
  183 + var s = t.storage;
  184 + buf.putString("${s[0]} ${s[1]} ${s[4]} ${s[5]} ${s[12]} ${s[13]} cm\n");
  185 + }
  186 +
  187 + /// This adds a line segment to the current path
  188 + ///
  189 + /// @param x coordinate
  190 + /// @param y coordinate
  191 + void lineTo(double x, double y) {
  192 + buf.putString("$x $y l\n");
  193 + }
  194 +
  195 + /// This moves the current drawing point.
  196 + ///
  197 + /// @param x coordinate
  198 + /// @param y coordinate
  199 + void moveTo(double x, double y) {
  200 + buf.putString("$x $y m\n");
  201 + }
  202 +
  203 + void drawShape(String d) {
  204 + var sb = new StringBuffer();
  205 +
  206 + RegExp exp = new RegExp(r"([MmZzLlHhVvCcSsQqTtAa])|(-[\.0-9]+)|([\.0-9]+)");
  207 + var matches = exp.allMatches(d);
  208 + var action;
  209 + for (var m in matches) {
  210 + var a = m.group(1);
  211 + var b = m.group(0);
  212 + print("$a, $b");
  213 + if (a != null) {
  214 + if (action != null) {
  215 + sb.write("$action ");
  216 + }
  217 + action = a;
  218 + } else {
  219 + sb.write("$b ");
  220 + }
  221 + }
  222 + print(sb);
  223 + buf.putString(sb.toString());
  224 + }
  225 +
  226 + /// This is used to add a polygon to the current path.
  227 + /// Used by drawPolygon(), drawPolyline() and fillPolygon() etal
  228 + ///
  229 + /// @param p Array of coordinates
  230 + /// @see #drawPolygon
  231 + /// @see #drawPolyline
  232 + /// @see #fillPolygon
  233 + void _polygon(List<PDFPoint> p) {
  234 + // newPath() not needed here as moveto does it ;-)
  235 + moveTo(p[0].w, p[0].h);
  236 +
  237 + for (int i = 1; i < p.length; i++) lineTo(p[i].w, p[i].h);
  238 + }
  239 +
  240 + void setLineCap(PDFLineCap cap) {
  241 + buf.putString("${cap.index} J\n");
  242 + }
  243 +
  244 + void setLineJoin(PDFLineCap join) {
  245 + buf.putString("${join.index} j\n");
  246 + }
  247 +
  248 + void setLineWidth(double width) {
  249 + buf.putString("$width w\n");
  250 + }
  251 +
  252 + void setMiterLimit(double limit) {
  253 + buf.putString("$limit M\n");
  254 + }
  255 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFImage extends PDFXObject {
  22 + final Image _img;
  23 + String _name;
  24 +
  25 + final bool _alphaChannel;
  26 +
  27 + /// Creates a new <code>PDFImage</code> instance.
  28 + ///
  29 + /// @param img an <code>Image</code> value
  30 + /// @param x an <code>int</code> value
  31 + /// @param y an <code>int</code> value
  32 + /// @param w an <code>int</code> value
  33 + /// @param h an <code>int</code> value
  34 + /// @param obs an <code>ImageObserver</code> value
  35 + PDFImage(PDFDocument pdfDocument, this._img, [this._alphaChannel = false]) : super(pdfDocument, "/Image", isBinary: true) {
  36 + _name = "/Image$objser";
  37 + params["/Width"] = PDFStream.string(_img.width.toString());
  38 + params["/Height"] = PDFStream.string(_img.height.toString());
  39 + params["/BitsPerComponent"] = PDFStream.intNum(8);
  40 + params['/Name'] = PDFStream.string(_name);
  41 +
  42 + if (_alphaChannel == false && _img.numChannels == 4) {
  43 + var _sMask = new PDFImage(pdfDocument, this._img, true);
  44 + params["/SMask"] = PDFStream.string("${_sMask.objser} 0 R");
  45 + }
  46 +
  47 + if (_alphaChannel) {
  48 + params["/ColorSpace"] = PDFStream.string("/DeviceGray");
  49 + } else {
  50 + params["/ColorSpace"] = PDFStream.string("/DeviceRGB");
  51 + }
  52 +
  53 + // write the pixels to the stream
  54 + // print("Processing image ${img.width}x${img.height} pixels");
  55 +
  56 + int w = _img.width;
  57 + int h = _img.height;
  58 + int s = w * h;
  59 +
  60 + Uint8List out = new Uint8List(_alphaChannel ? s : s * 3);
  61 +
  62 + if (_alphaChannel) {
  63 + for (int i = 0; i < s; i++) {
  64 + final p = _img.data[i];
  65 + final int alpha = (p >> 24) & 0xff;
  66 +
  67 + out[i] = alpha;
  68 + }
  69 + } else {
  70 + for (int i = 0; i < s; i++) {
  71 + final p = _img.data[i];
  72 + final int blue = (p >> 16) & 0xff;
  73 + final int green = (p >> 8) & 0xff;
  74 + final int red = p & 0xff;
  75 +
  76 + out[i * 3] = red;
  77 + out[i * 3 + 1] = green;
  78 + out[i * 3 + 2] = blue;
  79 + }
  80 + }
  81 +
  82 + buf.putBytes(out);
  83 + }
  84 +
  85 + /// Get the value of width.
  86 + /// @return value of width.
  87 + int get width => _img.width;
  88 +
  89 + /// Get the value of height.
  90 + /// @return value of height.
  91 + int get height => _img.height;
  92 +
  93 + /// Get the name
  94 + ///
  95 + /// @return a <code>String</code> value
  96 + String get name => _name;
  97 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFInfo extends PDFObject {
  22 + String author;
  23 + String creator;
  24 + String title;
  25 + String subject;
  26 + String keywords;
  27 +
  28 + /// @param title Title of this document
  29 + PDFInfo(PDFDocument pdfDocument, {this.title, this.author, this.creator, this.subject, this.keywords})
  30 + : super(pdfDocument, null) {
  31 + params["/Producer"] = PDFStream.text("dpdf - David PHAM-VAN");
  32 + }
  33 +
  34 + /// @param os OutputStream to send the object to
  35 + @override
  36 + void prepare() {
  37 + super.prepare();
  38 +
  39 + if (author != null) params["/Author"] = PDFStream.text(author);
  40 + if (creator != null) params["/Creator"] = PDFStream.text(creator);
  41 + if (title != null) params["/Title"] = PDFStream.text(title);
  42 + if (subject != null) params["/Subject"] = PDFStream.text(subject);
  43 + if (keywords != null) params["/Keywords"] = PDFStream.text(keywords);
  44 + }
  45 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFObject {
  22 + /// This is the object parameters.
  23 + final params = new Map<String, PDFStream>();
  24 +
  25 + /// This is the unique serial number for this object.
  26 + final int objser;
  27 +
  28 + /// This is the generation number for this object.
  29 + final int objgen = 0;
  30 +
  31 + /// This allows any PDF object to refer to the document being constructed.
  32 + final PDFDocument pdfDocument;
  33 +
  34 + /// This is usually called by extensors to this class, and sets the
  35 + /// PDF Object Type
  36 + /// @param type the PDF Object Type
  37 + PDFObject(this.pdfDocument, [String type]) : objser = pdfDocument._genSerial() {
  38 + if (type != null) {
  39 + params["/Type"] = PDFStream.string(type);
  40 + }
  41 +
  42 + pdfDocument.objects.add(this);
  43 + }
  44 +
  45 + /// <p>Writes the object to the output stream.
  46 + /// This method must be overidden.</p>
  47 + ///
  48 + /// <p><b>Note:</b> It should not write any other objects, even if they are
  49 + /// it's Kids, as they will be written by the calling routine.</p>
  50 + ///
  51 + /// @param os OutputStream to send the object to
  52 + void write(PDFStream os) {
  53 + prepare();
  54 + writeStart(os);
  55 + writeContent(os);
  56 + writeEnd(os);
  57 + }
  58 +
  59 + /// Prepare the object to be written to the stream
  60 + void prepare() {}
  61 +
  62 + /// The write method should call this before writing anything to the
  63 + /// OutputStream. This will send the standard header for each object.
  64 + ///
  65 + /// <p>Note: There are a few rare cases where this method is not called.
  66 + ///
  67 + /// @param os OutputStream to write to
  68 + void writeStart(PDFStream os) {
  69 + os.putString("$objser $objgen obj\n");
  70 + }
  71 +
  72 + void writeContent(PDFStream os) {
  73 + if (params.length > 0) {
  74 + os.putDictionary(params);
  75 + os.putString("\n");
  76 + }
  77 + }
  78 +
  79 + /// The write method should call this after writing anything to the
  80 + /// OutputStream. This will send the standard footer for each object.
  81 + ///
  82 + /// <p>Note: There are a few rare cases where this method is not called.
  83 + ///
  84 + /// @param os OutputStream to write to
  85 + void writeEnd(PDFStream os) {
  86 + os.putString("endobj\n");
  87 + }
  88 +
  89 + /// Returns the unique serial number in PDF format
  90 + /// @return the serial number in PDF format
  91 + PDFStream ref() => PDFStream.string("$objser $objgen R");
  92 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFObjectStream extends PDFObject {
  22 + /// This holds the stream's content.
  23 + final PDFStream buf = new PDFStream();
  24 +
  25 + /// defines if the stream needs to be converted to ascii85
  26 + final bool isBinary;
  27 +
  28 + /// Constructs a stream. The supplied type is stored in the stream's header
  29 + /// and is used by other objects that extend the PDFStream class (like
  30 + /// PDFImage).
  31 + /// <p>By default, the stream will be compressed.
  32 + /// @param type type for the stream
  33 + /// @see PDFImage
  34 + PDFObjectStream(PDFDocument pdfDocument, {String type, this.isBinary = false}) : super(pdfDocument, type);
  35 +
  36 + Uint8List _data;
  37 +
  38 + @override
  39 + void prepare() {
  40 + super.prepare();
  41 +
  42 + if (pdfDocument.deflate) {
  43 + var z = new ZLibCodec(level: ZLibOption.MAX_LEVEL);
  44 + _data = z.encode(buf.output());
  45 + params["/Filter"] = PDFStream.string("/FlateDecode");
  46 + } else if (isBinary) {
  47 + // This is a Ascii85 stream
  48 + var e = new Ascii85Encoder();
  49 + _data = e.convert(buf.output());
  50 + params["/Filter"] = PDFStream.string("/ASCII85Decode");
  51 + } else {
  52 + // This is a non-deflated stream
  53 + _data = buf.output();
  54 + }
  55 + params["/Length"] = PDFStream.intNum(_data.length);
  56 + }
  57 +
  58 + @override
  59 + void writeContent(PDFStream os) {
  60 + super.writeContent(os);
  61 +
  62 + os.putString("stream\n");
  63 + os.putBytes(_data);
  64 + os.putString("\nendstream\n");
  65 + }
  66 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFOutline extends PDFObject {
  22 + /// This holds any outlines below us
  23 + List<PDFOutline> outlines = [];
  24 +
  25 + /// For subentries, this points to it's parent outline
  26 + PDFOutline parent;
  27 +
  28 + /// This is this outlines Title
  29 + final String title;
  30 +
  31 + /// The destination page
  32 + PDFPage dest;
  33 +
  34 + /// The region on the destination page
  35 + final double l, b, r, t;
  36 +
  37 + /// When jumping to the destination, display the whole page
  38 + static const bool FITPAGE = false;
  39 +
  40 + /// When jumping to the destination, display the specified region
  41 + static const bool FITRECT = true;
  42 +
  43 + /// How the destination is handled
  44 + bool destMode = FITPAGE;
  45 +
  46 + /// Constructs a PDF Outline object. When selected, the specified region
  47 + /// is displayed.
  48 + ///
  49 + /// @param title Title of the outline
  50 + /// @param dest The destination page
  51 + /// @param l left coordinate
  52 + /// @param b bottom coordinate
  53 + /// @param r right coordinate
  54 + /// @param t top coordinate
  55 + PDFOutline(PDFDocument pdfDocument, {this.title, this.dest, this.l, this.b, this.r, this.t})
  56 + : super(pdfDocument, "/Outlines");
  57 +
  58 + /// This method creates an outline, and attaches it to this one.
  59 + /// When the outline is selected, the supplied region is displayed.
  60 + ///
  61 + /// <p>Note: the coordiates are in Java space. They are converted to User
  62 + /// space.
  63 + ///
  64 + /// <p>This allows you to have an outline for say a Chapter,
  65 + /// then under the chapter, one for each section. You are not really
  66 + /// limited on how deep you go, but it's best not to go below say 6 levels,
  67 + /// for the reader's sake.
  68 + ///
  69 + /// @param title Title of the outline
  70 + /// @param dest The destination page
  71 + /// @param x coordinate of region in Java space
  72 + /// @param y coordinate of region in Java space
  73 + /// @param w width of region in Java space
  74 + /// @param h height of region in Java space
  75 + /// @return PDFOutline object created, for creating sub-outlines
  76 + PDFOutline add({String title, PDFPage dest, double x, y, w, h}) {
  77 + var xy1 = dest.cxy(x, y + h);
  78 + var xy2 = dest.cxy(x + w, y);
  79 + PDFOutline outline = new PDFOutline(pdfDocument, title: title, dest: dest, l: xy1.w, b: xy1.h, r: xy2.w, t: xy2.h);
  80 + // Tell the outline of ourselves
  81 + outline.parent = this;
  82 + return outline;
  83 + }
  84 +
  85 + /// @param os OutputStream to send the object to
  86 + @override
  87 + void prepare() {
  88 + super.prepare();
  89 +
  90 + // These are for kids only
  91 + if (parent != null) {
  92 + params["/Title"] = PDFStream.string(title);
  93 + var dests = new List<PDFStream>();
  94 + dests.add(dest.ref());
  95 +
  96 + if (destMode == FITPAGE) {
  97 + dests.add(PDFStream.string("/Fit"));
  98 + } else {
  99 + dests.add(PDFStream.string("/FitR $l $b $r $t"));
  100 + }
  101 + params["/Parent"] = parent.ref();
  102 + params["/Dest"] = PDFStream.array(dests);
  103 +
  104 + // were a decendent, so by default we are closed. Find out how many
  105 + // entries are below us
  106 + int c = descendants();
  107 + if (c > 0) {
  108 + params["/Count"] = PDFStream.intNum(-c);
  109 + }
  110 +
  111 + int index = parent.getIndex(this);
  112 + if (index > 0) {
  113 + // Now if were not the first, then we have a /Prev node
  114 + params["/Prev"] = parent.getNode(index - 1).ref();
  115 + }
  116 +
  117 + if (index < parent.getLast()) {
  118 + // We have a /Next node
  119 + params["/Next"] = parent.getNode(index + 1).ref();
  120 + }
  121 + } else {
  122 + // the number of outlines in this document
  123 + // were the top level node, so all are open by default
  124 + params["/Count"] = PDFStream.intNum(outlines.length);
  125 + }
  126 +
  127 + // These only valid if we have children
  128 + if (outlines.length > 0) {
  129 + // the number of the first outline in list
  130 + params["/First"] = outlines[0].ref();
  131 +
  132 + // the number of the last outline in list
  133 + params["/Last"] = outlines[outlines.length - 1].ref();
  134 + }
  135 + }
  136 +
  137 + /// This is called by children to find their position in this outlines
  138 + /// tree.
  139 + ///
  140 + /// @param outline PDFOutline to search for
  141 + /// @return index within Vector
  142 + int getIndex(PDFOutline outline) => outlines.indexOf(outline);
  143 +
  144 + /// Returns the last index in this outline
  145 + /// @return last index in outline
  146 + int getLast() => outlines.length - 1;
  147 +
  148 + /// Returns the outline at a specified position.
  149 + /// @param i index
  150 + /// @return the node at index i
  151 + PDFOutline getNode(int i) => outlines[i];
  152 +
  153 + /// Returns the total number of descendants below this one.
  154 + /// @return the number of descendants below this one
  155 + int descendants() {
  156 + int c = outlines.length; // initially the number of kids
  157 +
  158 + // now call each one for their descendants
  159 + for (PDFOutline o in outlines) {
  160 + c += o.descendants();
  161 + }
  162 +
  163 + return c;
  164 + }
  165 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFOutput {
  22 + /// This is the actual PDFStream used to write to.
  23 + final PDFStream os;
  24 +
  25 + /// This vector contains offsets of each object
  26 + List<PDFXref> offsets = [];
  27 +
  28 + /// This is used to track the /Root object (catalog)
  29 + PDFObject rootID;
  30 +
  31 + /// This is used to track the /Info object (info)
  32 + PDFObject infoID;
  33 +
  34 + /// This creates a PDF PDFStream
  35 + ///
  36 + /// @param os The output stream to write the PDF file to.
  37 + PDFOutput(this.os) {
  38 + os.putString("%PDF-1.4\n");
  39 + os.putBytes([0x25, 0xC2, 0xA5, 0xC2, 0xB1, 0xC3, 0xAB, 0x0A]);
  40 + }
  41 +
  42 + /// This method writes a PDFObject to the stream.
  43 + ///
  44 + /// @param ob PDFObject Obeject to write
  45 + void write(PDFObject ob) {
  46 + // Check the object to see if it's one that is needed in the trailer
  47 + // object
  48 + if (ob is PDFCatalog) rootID = ob;
  49 + if (ob is PDFInfo) infoID = ob;
  50 +
  51 + offsets.add(new PDFXref(ob.objser, os.offset));
  52 + ob.write(os);
  53 + }
  54 +
  55 + /// This closes the Stream, writing the xref table
  56 + void close() {
  57 + // we use baos to speed things up a little.
  58 + // Also, offset is preserved, and marks the begining of this block.
  59 + // This is required by PDF at the end of the PDF file.
  60 +
  61 + int xref = os.offset;
  62 +
  63 + os.putString("xref\n");
  64 +
  65 + // Now a single subsection for object 0
  66 + //os.write("0 1\n0000000000 65535 f \n");
  67 +
  68 + // Now scan through the offsets list. The should be in sequence,
  69 + // but just in case:
  70 + int firstid = 0; // First id in block
  71 + int lastid = -1; // The last id used
  72 + var block = []; // xrefs in this block
  73 +
  74 + // We need block 0 to exist
  75 + block.add(new PDFXref(0, 0, generation: 65535));
  76 +
  77 + for (PDFXref x in offsets) {
  78 + if (firstid == -1) firstid = x.id;
  79 +
  80 + // check to see if block is in range (-1 means empty)
  81 + if (lastid > -1 && x.id != (lastid + 1)) {
  82 + // no, so write this block, and reset
  83 + writeblock(firstid, block);
  84 + block = [];
  85 + firstid = -1;
  86 + }
  87 +
  88 + // now add to block
  89 + block.add(x);
  90 + lastid = x.id;
  91 + }
  92 +
  93 + // now write the last block
  94 + if (firstid > -1) writeblock(firstid, block);
  95 +
  96 + // now the trailer object
  97 + os.putString("trailer\n<<\n");
  98 +
  99 + // the number of entries (REQUIRED)
  100 + os.putString("/Size ");
  101 + os.putString((offsets.length + 1).toString());
  102 + os.putString("\n");
  103 +
  104 + // the /Root catalog indirect reference (REQUIRED)
  105 + if (rootID != null) {
  106 + os.putString("/Root ");
  107 + os.putStream(rootID.ref());
  108 + os.putString("\n");
  109 + } else
  110 + throw new Exception("Root object is not present in document");
  111 +
  112 + // the /Info reference (OPTIONAL)
  113 + if (infoID != null) {
  114 + os.putString("/Info ");
  115 + os.putStream(infoID.ref());
  116 + os.putString("\n");
  117 + }
  118 +
  119 + // end the trailer object
  120 + os.putString(">>\nstartxref\n$xref\n%%EOF\n");
  121 + }
  122 +
  123 + /// Writes a block of references to the PDF file
  124 + /// @param firstid ID of the first reference in this block
  125 + /// @param block Vector containing the references in this block
  126 + void writeblock(int firstid, var block) {
  127 + os.putString("$firstid ${block.length}\n");
  128 + //os.write("\n0000000000 65535 f\n");
  129 +
  130 + for (PDFXref x in block) {
  131 + os.putString(x.ref());
  132 + os.putString("\n");
  133 + }
  134 + }
  135 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFPage extends PDFObject {
  22 + /// This is this page format, ie the size of the page, margins, and rotation
  23 + PDFPageFormat pageFormat;
  24 +
  25 + /// This holds the contents of the page.
  26 + List<PDFObjectStream> contents = [];
  27 +
  28 + /// Object ID that contains a thumbnail sketch of the page.
  29 + /// -1 indicates no thumbnail.
  30 + PDFObject thumbnail;
  31 +
  32 + /// This holds any Annotations contained within this page.
  33 + List<PDFAnnot> annotations = [];
  34 +
  35 + /// The fonts associated with this page
  36 + final fonts = new Map<String, PDFFont>();
  37 +
  38 + /// The xobjects or other images in the pdf
  39 + final xObjects = new Map<String, PDFXObject>();
  40 +
  41 + /// This constructs a Page object, which will hold any contents for this
  42 + /// page.
  43 + ///
  44 + /// <p>Once created, it is added to the document via the PDF.add() method.
  45 + ///
  46 + /// @param orientation Orientation: 0, 90 or 270
  47 + /// @see PageFormat#PORTRAIT
  48 + /// @see PageFormat#LANDSCAPE
  49 + /// @see PageFormat#REVERSE_LANDSCAPE
  50 + /// @param pageFormat PageFormat describing the page size
  51 + PDFPage(PDFDocument pdfDocument, {int orientation, this.pageFormat}) : super(pdfDocument, "/Page") {
  52 + pdfDocument.pdfPageList.pages.add(this);
  53 + if (pageFormat == null) pageFormat = new PDFPageFormat();
  54 + setOrientation(orientation);
  55 + }
  56 +
  57 + /// This returns a PDFGraphics object, which can then be used to render
  58 + /// on to this page. If a previous PDFGraphics object was used, this object
  59 + /// is appended to the page, and will be drawn over the top of any previous
  60 + /// objects.
  61 + ///
  62 + /// @return a new PDFGraphics object to be used to draw this page.
  63 + PDFGraphics getGraphics() {
  64 + var stream = new PDFObjectStream(pdfDocument);
  65 + var g = new PDFGraphics(this, stream.buf);
  66 + contents.add(stream);
  67 + return g;
  68 + }
  69 +
  70 + /// Returns the page's PageFormat.
  71 + /// @return PageFormat describing the page size in device units (72dpi)
  72 + PDFPageFormat getPageFormat() {
  73 + return pageFormat;
  74 + }
  75 +
  76 + /// Gets the dimensions of the page.
  77 + /// @return a Dimension object containing the width and height of the page.
  78 + PDFPoint getDimension() => new PDFPoint(pageFormat.getWidth(), pageFormat.getHeight());
  79 +
  80 + /// Sets the page's orientation.
  81 + ///
  82 + /// <p>Normally, this should be done when the page is created, to avoid
  83 + /// problems.
  84 + ///
  85 + /// @param orientation a PageFormat orientation constant:
  86 + /// PageFormat.PORTRAIT, PageFormat.LANDSACPE or PageFromat.REVERSE_LANDSACPE
  87 + void setOrientation(int orientation) {
  88 + pageFormat.setOrientation(orientation);
  89 + }
  90 +
  91 + /// Returns the pages orientation:
  92 + /// PageFormat.PORTRAIT, PageFormat.LANDSACPE or PageFromat.REVERSE_LANDSACPE
  93 + ///
  94 + /// @see java.awt.print.PageFormat
  95 + /// @return current orientation of the page
  96 + int getOrientation() => pageFormat.getOrientation();
  97 +
  98 + /// This adds an Annotation to the page.
  99 + ///
  100 + /// <p>As with other objects, the annotation must be added to the pdf
  101 + /// document using PDF.add() before adding to the page.
  102 + ///
  103 + /// @param ob Annotation to add.
  104 + void addAnnotation(PDFObject ob) {
  105 + annotations.add(ob);
  106 + }
  107 +
  108 + /// This method adds a text note to the document.
  109 + /// @param note Text of the note
  110 + /// @param x Coordinate of note
  111 + /// @param y Coordinate of note
  112 + /// @param w Width of the note
  113 + /// @param h Height of the note
  114 + /// @return Returns the annotation, so other settings can be changed.
  115 + PDFAnnot addNote(String note, double x, y, w, h) {
  116 + var xy1 = cxy(x, y + h);
  117 + var xy2 = cxy(x + w, y);
  118 + PDFAnnot ob = new PDFAnnot.text(this, xy1.w, xy1.h, xy2.w, xy2.h, note);
  119 + return ob;
  120 + }
  121 +
  122 + /// Adds a hyperlink to the document.
  123 + /// @param x Coordinate of active area
  124 + /// @param y Coordinate of active area
  125 + /// @param w Width of the active area
  126 + /// @param h Height of the active area
  127 + /// @param dest Page that will be displayed when the link is activated. When
  128 + /// displayed, the zoom factor will be changed to fit the display.
  129 + /// @param vx Coordinate of view area
  130 + /// @param vy Coordinate of view area
  131 + /// @param vw Width of the view area
  132 + /// @param vh Height of the view area
  133 + /// @return Returns the annotation, so other settings can be changed.
  134 + PDFAnnot addLink(double x, y, w, h, PDFObject dest,
  135 + [double vx = PDFAnnot.FULL_PAGE, vy = PDFAnnot.FULL_PAGE, vw = PDFAnnot.FULL_PAGE, vh = PDFAnnot.FULL_PAGE]) {
  136 + var xy1 = cxy(x, y + h);
  137 + var xy2 = cxy(x + w, y);
  138 + var xy3 = cxy(vx, vy + vh);
  139 + var xy4 = cxy(vx + vw, vy);
  140 + PDFAnnot ob = new PDFAnnot.link(this, xy1.w, xy1.h, xy2.w, xy2.h, dest, xy3.w, xy3.h, xy4.w, xy4.h);
  141 + return ob;
  142 + }
  143 +
  144 + /// This method attaches an outline to the current page being generated. When
  145 + /// selected, the outline displays the top of the page.
  146 + /// @param title Outline title to attach
  147 + /// @param x Left coordinate of region
  148 + /// @param y Bottom coordinate of region
  149 + /// @param w Width of region
  150 + /// @param h Height coordinate of region
  151 + /// @return PDFOutline object created, for addSubOutline if required.
  152 + PDFOutline addOutline(String title, {double x, double y, double w, double h}) {
  153 + PDFPoint xy1 = cxy(x, y + h);
  154 + PDFPoint xy2 = cxy(x + w, y);
  155 + PDFOutline outline = new PDFOutline(pdfDocument, title: title, dest: this, l: xy1.w, b: xy1.h, r: xy2.w, t: xy2.h);
  156 + pdfDocument.outline.outlines.add(outline);
  157 + return outline;
  158 + }
  159 +
  160 + /// @param os OutputStream to send the object to
  161 + @override
  162 + void prepare() {
  163 + super.prepare();
  164 +
  165 + // the /Parent pages object
  166 + params["/Parent"] = pdfDocument.pdfPageList.ref();
  167 +
  168 + // the /MediaBox for the page size
  169 + params["/MediaBox"] = new PDFStream()..putStringArray([0, 0, pageFormat.getWidth(), pageFormat.getHeight()]);
  170 +
  171 + // Rotation (if not zero)
  172 +// if(rotate!=0) {
  173 +// os.write("/Rotate ");
  174 +// os.write(Integer.toString(rotate).getBytes());
  175 +// os.write("\n");
  176 +// }
  177 +
  178 + // the /Contents pages object
  179 + if (contents.length > 0) {
  180 + if (contents.length == 1) {
  181 + params["/Contents"] = contents[0].ref();
  182 + } else {
  183 + params["/Contents"] = new PDFStream()..putObjectArray(contents);
  184 + }
  185 + }
  186 +
  187 + // Now the resources
  188 + /// This holds any resources for this page
  189 + final resources = new Map<String, PDFStream>();
  190 +
  191 + // fonts
  192 + if (fonts.length > 0) {
  193 + resources["/Font"] = new PDFStream()..putObjectDictionary(fonts);
  194 + }
  195 +
  196 + // Now the XObjects
  197 + if (xObjects.length > 0) {
  198 + resources["/XObject"] = new PDFStream()..putObjectDictionary(xObjects);
  199 + }
  200 +
  201 + params["/Resources"] = PDFStream.dictionary(resources);
  202 +
  203 + // The thumbnail
  204 + if (thumbnail != null) {
  205 + params["/Thumb"] = thumbnail.ref();
  206 + }
  207 +
  208 + // The /Annots object
  209 + if (annotations.length > 0) {
  210 + params["/Annots"] = new PDFStream()..putObjectArray(annotations);
  211 + }
  212 + }
  213 +
  214 + /// This utility method converts the y coordinate from Java to User space
  215 + /// within the page.
  216 + /// @param x Coordinate in Java space
  217 + /// @param y Coordinate in Java space
  218 + /// @return y Coordinate in User space
  219 + double cy(double x, double y) => cxy(x, y).h;
  220 +
  221 + /// This utility method converts the y coordinate from Java to User space
  222 + /// within the page.
  223 + /// @param x Coordinate in Java space
  224 + /// @param y Coordinate in Java space
  225 + /// @return x Coordinate in User space
  226 + double cx(double x, double y) => cxy(x, y).w;
  227 +
  228 + /// This utility method converts the Java coordinates to User space
  229 + /// within the page.
  230 + /// @param x Coordinate in Java space
  231 + /// @param y Coordinate in Java space
  232 + /// @return array containing the x & y Coordinate in User space
  233 + PDFPoint cxy(double x, double y) => new PDFPoint(x, pageFormat.getHeight() - y);
  234 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFPageFormat {
  22 + static const A4 = const [595.28, 841.89];
  23 + static const A3 = const [841.89, 1190.55];
  24 + static const A5 = const [420.94, 595.28];
  25 + static const LETTER = const [612.0, 792.0];
  26 + static const LEGAL = const [612.0, 1008.0];
  27 +
  28 + static const PT = 1.0;
  29 + static const IN = 72.0;
  30 + static const CM = IN / 2.54;
  31 + static const MM = IN / 25.4;
  32 +
  33 + double width;
  34 + double height;
  35 + double imageableX = 10.0;
  36 + double imageableY = 10.0;
  37 + double imageableWidth = 300.0;
  38 + double imageableHeight = 300.0;
  39 + int orientation = 0;
  40 +
  41 + PDFPageFormat([List<double> format]) {
  42 + if (format == null || format.length != 2) format = A4;
  43 +
  44 + width = format[0];
  45 + height = format[1];
  46 + }
  47 +
  48 + double getWidth() => width;
  49 + double getHeight() => height;
  50 +
  51 + void setOrientation(int orientation) {
  52 + this.orientation = orientation;
  53 + }
  54 +
  55 + int getOrientation() => orientation;
  56 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFPageList extends PDFObject {
  22 + /// This holds the pages
  23 + final List<PDFPage> pages = [];
  24 +
  25 + /// This constructs a PDF Pages object.
  26 + PDFPageList(PDFDocument pdfDocument) : super(pdfDocument, "/Pages");
  27 +
  28 + /// This returns a specific page. Used by the PDF class.
  29 + /// @param page page number to return
  30 + /// @return PDFPage at that position
  31 + PDFPage getPage(int page) => pages[page];
  32 +
  33 + /// @param os OutputStream to send the object to
  34 + @override
  35 + void prepare() {
  36 + super.prepare();
  37 +
  38 + params["/Kids"] = new PDFStream()..putObjectArray(pages);
  39 + params["/Count"] = PDFStream.intNum(pages.length);
  40 + }
  41 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFPoint {
  22 + final double w, h;
  23 + const PDFPoint(this.w, this.h);
  24 +
  25 + @override
  26 + String toString() => "PDFPoint($w, $h)";
  27 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class Polygon {
  22 + List<PDFPoint> points;
  23 +
  24 + Polygon(this.points);
  25 +
  26 + PDFRect getBounds() {
  27 + // TODO: Implement properly
  28 + return const PDFRect(0.0, 0.0, 0.0, 0.0);
  29 + }
  30 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFRect {
  22 + final double x, y, w, h;
  23 + const PDFRect(this.x, this.y, this.w, this.h);
  24 +
  25 + @override
  26 + String toString() => "PDFRect($x, $y, $w, $h)";
  27 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFStream {
  22 + final _stream = new BytesBuilder(copy: false);
  23 +
  24 + void putStream(PDFStream s) {
  25 + _stream.add(s._stream.toBytes());
  26 + }
  27 +
  28 + void putString(String s) {
  29 + for (int codeUnit in s.codeUnits) {
  30 + if (codeUnit <= 0x7f) {
  31 + _stream.addByte(codeUnit);
  32 + } else {
  33 + _stream.addByte(0x20);
  34 + }
  35 + }
  36 + }
  37 +
  38 + static PDFStream string(String s) => new PDFStream()..putString(s);
  39 +
  40 + void putStringUtf16(String s) {
  41 + for (int codeUnit in s.codeUnits) {
  42 + _stream.addByte(codeUnit & 0xff);
  43 + _stream.addByte((codeUnit >> 8) & 0xff);
  44 + }
  45 + }
  46 +
  47 + void putBytes(List<int> s) {
  48 + _stream.add(s);
  49 + }
  50 +
  51 + void putNum(double d) {
  52 + putString(d.toString());
  53 + }
  54 +
  55 + static PDFStream num(double d) => new PDFStream()..putNum(d);
  56 + static PDFStream intNum(int i) => new PDFStream()..putString(i.toString());
  57 +
  58 + void putText(String s) {
  59 + // Escape special characters
  60 + // \n Line feed (LF)
  61 + // \r Carriage return (CR)
  62 + // \t Horizontal tab (HT)
  63 + // \b Backspace (BS)
  64 + // \f Form feed (FF)
  65 + // \( Left parenthesis
  66 + // \) Right parenthesis
  67 + // \\ Backslash
  68 + // \ddd Character code ddd (octal)
  69 + s = s
  70 + .replaceAll('\\', '\\\\')
  71 + .replaceAll('(', '\\(')
  72 + .replaceAll(')', '\\)')
  73 + .replaceAll('\n', '\\n')
  74 + .replaceAll('\t', '\\t')
  75 + .replaceAll('\b', '\\b')
  76 + .replaceAll('\f', '\\f')
  77 + .replaceAll('\r', '\\r');
  78 +
  79 + putBytes(LATIN1.encode('(' + s + ')'));
  80 + }
  81 +
  82 + static PDFStream text(String s) => new PDFStream()..putText(s);
  83 +
  84 + void putBool(bool value) {
  85 + putString(value ? "true" : "false");
  86 + }
  87 +
  88 + void putArray(List<PDFStream> values) {
  89 + putString("[");
  90 + for (var val in values) {
  91 + putStream(val);
  92 + putString(" ");
  93 + }
  94 + putString("]");
  95 + }
  96 +
  97 + void putObjectArray(List<PDFObject> values) {
  98 + putString("[");
  99 + for (var val in values) {
  100 + putStream(val.ref());
  101 + putString(" ");
  102 + }
  103 + putString("]");
  104 + }
  105 +
  106 + void putStringArray(List<dynamic> values) {
  107 + putString("[" + values.join(" ") + "]");
  108 + }
  109 +
  110 + static PDFStream array(List<PDFStream> values) => new PDFStream()..putArray(values);
  111 +
  112 + void putDictionary(Map<String, PDFStream> values) {
  113 + putString("<< ");
  114 + values.forEach((k, v) {
  115 + putString("$k ");
  116 + putStream(v);
  117 + putString("\n");
  118 + });
  119 + putString(">>");
  120 + }
  121 +
  122 + static PDFStream dictionary(Map<String, PDFStream> values) => new PDFStream()..putDictionary(values);
  123 +
  124 + void putObjectDictionary(Map<String, PDFObject> values) {
  125 + putString("<< ");
  126 + values.forEach((k, v) {
  127 + putString("$k ");
  128 + putStream(v.ref());
  129 + putString(" ");
  130 + });
  131 + putString(">>");
  132 + }
  133 +
  134 + int get offset => _stream.length;
  135 +
  136 + Uint8List output() => _stream.toBytes();
  137 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFTTFFont extends PDFFont {
  22 + PDFObject unicodeCMap;
  23 + PDFFontDescriptor descriptor;
  24 + PDFArrayObject widthsObject;
  25 + final widths = new List<String>();
  26 + TtfFont _font;
  27 + int _charMin;
  28 + int _charMax;
  29 +
  30 + /// Constructs a PDFTTFFont
  31 + PDFTTFFont(PDFDocument pdfDocument, Uint8List bytes) : super(pdfDocument, subtype: "/TrueType") {
  32 + _font = new TtfParser().parse(bytes);
  33 + baseFont = "/" + _font.name.fontName.replaceAll(" ", "");
  34 +
  35 + PDFObjectStream file = new PDFObjectStream(pdfDocument, isBinary: true);
  36 + file.buf.putBytes(bytes);
  37 + file.params["/Length1"] = PDFStream.intNum(bytes.length);
  38 +
  39 + _charMin = 32;
  40 + _charMax = 255;
  41 +
  42 + for (var i = _charMin; i <= _charMax; i++) {
  43 + widths.add((glyphAdvance(i) * 1000.0).toString());
  44 + }
  45 +
  46 + unicodeCMap = new PDFObject(pdfDocument);
  47 + descriptor = new PDFFontDescriptor(this, file, _font);
  48 + widthsObject = new PDFArrayObject(pdfDocument, widths);
  49 + }
  50 +
  51 + @override
  52 + double glyphAdvance(int charCode) {
  53 + var g = _font.cmap.charToGlyphIndexMap[charCode];
  54 +
  55 + if (g == null) {
  56 + return super.glyphAdvance(charCode);
  57 + }
  58 +
  59 + return _font.hmtx.metrics[g].advanceWidth / _font.head.unitsPerEm;
  60 + }
  61 +
  62 + @override
  63 + PDFRect glyphBounds(int charCode) {
  64 + var g = _font.cmap.charToGlyphIndexMap[charCode];
  65 +
  66 + if (g == null) {
  67 + return super.glyphBounds(charCode);
  68 + }
  69 +
  70 + var info = _font.glyf.glyphInfoMap[g];
  71 + return new PDFRect(
  72 + info.xMin.toDouble() / _font.head.unitsPerEm,
  73 + info.yMin.toDouble() / _font.head.unitsPerEm,
  74 + (info.xMax - info.xMin).toDouble() / _font.head.unitsPerEm,
  75 + (info.yMax - info.yMin).toDouble() / _font.head.unitsPerEm);
  76 + }
  77 +
  78 + @override
  79 + void prepare() {
  80 + super.prepare();
  81 +
  82 + params["/FirstChar"] = PDFStream.intNum(_charMin);
  83 + params["/LastChar"] = PDFStream.intNum(_charMax);
  84 + params["/Widths"] = widthsObject.ref();
  85 + params["/FontDescriptor"] = descriptor.ref();
  86 +// params["/Encoding"] = PDFStream.string("/Identity-H");
  87 +// params["/ToUnicode"] = unicodeCMap.ref();
  88 + }
  89 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General Public
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFXObject extends PDFObjectStream {
  22 + PDFXObject(PDFDocument pdfDocument, String subtype, {bool isBinary = false})
  23 + : super(pdfDocument, type: '/XObject', isBinary: isBinary) {
  24 + params['/Subtype'] = PDFStream.string(subtype);
  25 + }
  26 +}
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * This library is free software; you can redistribute it and/or
  5 + * modify it under the terms of the GNU Lesser General
  6 + * License as published by the Free Software Foundation; either
  7 + * version 2.1 of the License, or (at your option) any later version.
  8 + *
  9 + * This library is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17 + */
  18 +
  19 +part of pdf;
  20 +
  21 +class PDFXref {
  22 + /// The id of a PDF Object
  23 + int id;
  24 +
  25 + /// The offset within the PDF file
  26 + int offset;
  27 +
  28 + /// The generation of the object, usually 0
  29 + int generation = 0;
  30 +
  31 + /// Creates a crossreference for a PDF Object
  32 + /// @param id The object's ID
  33 + /// @param offset The object's position in the file
  34 + /// @param generation The object's generation, usually 0
  35 + PDFXref(this.id, this.offset, {this.generation = 0});
  36 +
  37 + /// @return The xref in the format of the xref section in the PDF file
  38 + String ref() {
  39 + String rs = offset.toString().padLeft(10, '0') + " " + generation.toString().padLeft(5, '0');
  40 +
  41 + if (generation == 65535) return rs + " f ";
  42 + return rs + " n ";
  43 + }
  44 +}
  1 +name: pdf
  2 +author: David PHAM-VAN <dev.nfet.net@gmail.com>
  3 +description: A pdf producer for Dart
  4 +homepage: https://github.com/davbfr/dart_pdf
  5 +version: 1.0.0
  6 +
  7 +dependencies:
  8 + image: "^1.1.29"
  9 + ttf_parser: "^1.0.0"
  10 + vector_math:
  11 +
  12 +dev_dependencies:
  13 + test: "^0.12.32+1"
  1 +import 'dart:io';
  2 +
  3 +import 'package:pdf/pdf.dart';
  4 +import "package:test/test.dart";
  5 +
  6 +void main() {
  7 + test('Pdf1', () {
  8 + var pdf = new PDFDocument(deflate: false);
  9 + var page = new PDFPage(pdf, pageFormat: new PDFPageFormat(PDFPageFormat.A4));
  10 +
  11 + var g = page.getGraphics();
  12 + g.drawLine(30.0, 30.0, 200.0, 200.0);
  13 + g.strokePath();
  14 +
  15 + var file = new File('file1.pdf');
  16 + file.writeAsBytesSync(pdf.save());
  17 + });
  18 +}
  1 +import 'dart:io';
  2 +import 'dart:math';
  3 +
  4 +import 'package:image/image.dart';
  5 +import 'package:pdf/pdf.dart';
  6 +import 'package:test/test.dart';
  7 +import 'package:vector_math/vector_math_64.dart';
  8 +
  9 +
  10 +void main() {
  11 + test('Pdf', () {
  12 + Image img = new Image(10, 10);
  13 + img.fill(0x12345678);
  14 +
  15 + var pdf = new PDFDocument(deflate: false);
  16 + var i = pdf.info;
  17 + i.author = "David PHAM-VAN";
  18 + i.creator = i.author;
  19 + i.title = "My Title";
  20 + i.subject = "My Subject";
  21 + var page = new PDFPage(pdf, pageFormat: new PDFPageFormat([500.0, 300.0]));
  22 +
  23 + var g = page.getGraphics();
  24 + g.saveContext();
  25 + var tm = new Matrix4.identity();
  26 + tm.translate(100.0, 700.0);
  27 + g.setTransform(tm);
  28 +// g.drawShape("M37 0H9C6.24 0 4 2.24 4 5v38c0 2.76 2.24 5 5 5h28c2.76 0 5-2.24 5-5V5c0-2.76-2.24-5-5-5zM23 46c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm15-8H8V6h30v32z");
  29 + g.restoreContext();
  30 + var font1 = new PDFFont(pdf);
  31 +
  32 + var font2 = new PDFTTFFont(pdf, new File("../assets/Nunito-Regular.ttf").readAsBytesSync());
  33 + var s = "Hello World!";
  34 + var r = font2.stringBounds(s);
  35 + const FS = 20.0;
  36 + g.setColor(new PDFColor(0.0, 1.0, 1.0));
  37 + g.drawRect(50.0 + r.x * FS, 30.0 + r.y * FS, r.w * FS, r.h * FS);
  38 + g.fillPath();
  39 + g.setColor(new PDFColor(0.3, 0.3, 0.3));
  40 + g.drawString(font2, FS, s, 50.0, 30.0);
  41 +
  42 + g.setColor(new PDFColor(1.0, 0.0, 0.0));
  43 + g.drawString(font2, 20.0, "Hé (Olà)", 50.0, 10.0);
  44 + g.drawLine(30.0, 30.0, 200.0, 200.0);
  45 + g.strokePath();
  46 + g.setColor(new PDFColor(1.0, 0.0, 0.0));
  47 + g.drawRect(300.0, 150.0, 50.0, 50.0);
  48 + g.fillPath();
  49 + g.setColor(new PDFColor(0.0, 0.5, 0.0));
  50 + var image = new PDFImage(pdf, img);
  51 + for (var i = 10.0; i < 90.0; i += 5.0) {
  52 + g.saveContext();
  53 + var tm = new Matrix4.identity();
  54 + tm.rotateZ(i * PI / 360.0);
  55 + tm.translate(300.0, -100.0);
  56 + g.setTransform(tm);
  57 + g.drawString(font1, 12.0, "Hello $i", 20.0, 100.0);
  58 + g.drawImage(image, 100.0, 100.0, 80.0);
  59 + g.restoreContext();
  60 + }
  61 +
  62 + var file = new File('file.pdf');
  63 + file.writeAsBytesSync(pdf.save());
  64 + });
  65 +}