1.What's exactly the license of FPDF? Are there any usage restrictions?
+FPDF is released under a permissive license: there is no usage restriction. You may embed it
+freely in your application (commercial or not), with or without modifications.
+
+
+
+
2.When I try to create a PDF, a lot of weird characters show on the screen. Why?
+These "weird" characters are in fact the actual content of your PDF. This behavior is a bug of
+IE6. When it first receives an HTML page, then a PDF from the same URL, it displays it directly
+without launching Acrobat. This happens frequently during the development stage: on the least
+script error, an HTML page is sent, and after correction, the PDF arrives.
+
+To solve the problem, simply quit and restart IE. You can also go to another URL and come
+back.
+
+To avoid this kind of inconvenience during the development, you can generate the PDF directly
+to a file and open it through the explorer.
+
+
+
+
3.I try to generate a PDF and IE displays a blank page. What happens?
+First of all, check that you send nothing to the browser after the PDF (not even a space or a
+carriage return). You can put an exit statement just after the call to the Output() method to
+be sure. If it still doesn't work, it means you're a victim of the "blank page syndrome". IE
+used in conjunction with the Acrobat plug-in suffers from many bugs. To avoid these problems
+in a reliable manner, two main techniques exist:
+
+
+- Disable the plug-in and use Acrobat as a helper application. To do this, launch Acrobat, go
+to the Edit menu, Preferences, Internet, and uncheck "Display PDF in browser". Then, the next
+time you load a PDF in IE, it displays the dialog box "Open it" or "Save it to disk". Uncheck
+the option "Always ask before opening this type of file" and choose Open. From now on, PDF files
+will open automatically in an external Acrobat window.
+
+The drawback of the method is that you need to alter the client configuration, which you can do
+in an intranet environment but not for the Internet.
+
+
+- Use a redirection technique. It consists in generating the PDF in a temporary file on the server
+and redirect the client to it. For example, at the end of the script, you can put the following:
+
+
//Determine a temporary file name in the current directory
+$file = basename(tempnam('.', 'tmp'));
+rename($file, $file.'.pdf');
+$file .= '.pdf';
+//Save PDF to file
+$pdf->Output($file, 'F');
+//Redirect
+header('Location: '.$file);
+
+This method turns the dynamic PDF into a static one and avoids all troubles. But you have to do
+some cleaning in order to delete the temporary files. For example:
+
+This function deletes all files of the form tmp*.pdf older than an hour in the specified
+directory. You may call it where you want, for example in the script which generates the PDF.
+
+
+
+
4.I can't make line breaks work. I put \n in the string printed by MultiCell but it doesn't work.
+You have to enclose your string with double quotes, not single ones.
+
+
+
+
5.I try to display a variable in the Header method but nothing prints.
+You have to use the global keyword to access global variables, for example:
+
6.I defined the Header and Footer methods in my PDF class but nothing appears.
+You have to create an object from the PDF class, not FPDF:
+
+
$pdf = new PDF();
+
+
+
+
+
7.Accented characters are replaced by some strange characters like é.
+Don't use UTF-8 encoding. Standard FPDF fonts use ISO-8859-1 or Windows-1252.
+It is possible to perform a conversion to ISO-8859-1 with utf8_decode():
+
+
$str = utf8_decode($str);
+
+But some characters such as Euro won't be translated correctly. If the iconv extension is available, the
+right way to do it is the following:
+
+
$str = iconv('UTF-8', 'windows-1252', $str);
+
+
+
+
+
8.I try to display the Euro symbol but it doesn't work.
+The standard fonts have the Euro character at position 128. You can define a constant like this
+for convenience:
+
+
define('EURO', chr(128));
+
+
+
+
+
9.I get the following error when I try to generate a PDF: Some data has already been output, can't send PDF file
+You must send nothing to the browser except the PDF itself: no HTML, no space, no carriage return. A common
+case is having extra blank at the end of an included script file.
+If you can't figure out where the problem comes from, this other message appearing just before can help you:
+
+Warning: Cannot modify header information - headers already sent by (output started at script.php:X)
+
+It means that script.php outputs something at line X. Go to this line and fix it.
+In case the message doesn't show, first check that you didn't disable warnings, then add this at the very
+beginning of your script:
+
+
ob_end_clean();
+
+If you still don't see it, disable zlib.output_compression in your php.ini and it should appear.
+
+
+
+
10.I draw a frame with very precise dimensions, but when printed I notice some differences.
+To respect dimensions, select "None" for the Page Scaling setting instead of "Shrink to Printable Area" in the print dialog box.
+
+
+
+
11.I'd like to use the whole surface of the page, but when printed I always have some margins. How can I get rid of them?
+Printers have physical margins (different depending on the models); it is therefore impossible to remove
+them and print on the whole surface of the paper.
+
+
+
+
12.How can I put a background in my PDF?
+For a picture, call Image() in the Header() method, before any other output. To set a background color, use Rect().
+
+
+
+
13.How can I set a specific header or footer on the first page?
16.What's the limit of the file sizes I can generate with FPDF?
+There is no particular limit. There are some constraints, however:
+
+
+- The maximum memory size allocated to PHP scripts is usually 8MB. For very big documents,
+especially with images, this limit may be reached (the file being built into memory). The
+parameter is configured in the php.ini file.
+
+
+- The maximum execution time allocated defaults to 30 seconds. This limit can of course be easily
+reached. It is configured in php.ini and may be altered dynamically with set_time_limit().
+
+
+- Browsers generally have a 5 minute time-out. If you send the PDF directly to the browser and
+reach the limit, it will be lost. It is therefore advised for very big documents to
+generate them in a file, and to send some data to the browser from time to time (with a call
+to flush() to force the output). When the document is finished, you can send a redirection to
+it or create a link.
+
+Remark: even if the browser times out, the script may continue to run on the server.
+
18.I'd like to make a search engine in PHP and index PDF files. Can I do it with FPDF?
+No. But a GPL C utility does exist, pdftotext, which is able to extract the textual content from
+a PDF. It is provided with the Xpdf package:
+
+http://www.foolabs.com/xpdf/
+
+
+
+
19.Can I convert an HTML page to PDF with FPDF?
+Not real-world pages. But a GPL C utility does exist, htmldoc, which allows to do it and gives good results:
+
+http://www.htmldoc.org
+
+
+
+
20.Can I concatenate PDF files with FPDF?
+Not directly, but it is possible to use FPDI
+to perform this task. Some free command-line tools also exist:
+
+mbtPdfAsm
+pdftk
+
+- The MakeFont utility has been completely rewritten and doesn't depend on ttf2pt1 anymore.
+- Alpha channel is now supported for PNGs.
+- When inserting an image, it's now possible to specify its resolution.
+- Default resolution for images was increased from 72 to 96 dpi.
+- When inserting a GIF image, no temporary file is used anymore if the PHP version is 5.1 or higher.
+- When output buffering is enabled and the PDF is about to be sent, the buffer is now cleared if it contains only a UTF-8 BOM and/or whitespace (instead of throwing an error).
+- Symbol and ZapfDingbats fonts now support underline style.
+- Custom page sizes are now checked to ensure that width is smaller than height.
+- Standard font files were changed to use the same format as user fonts.
+- A bug in the embedding of Type1 fonts was fixed.
+- A bug related to SetDisplayMode() and the current locale was fixed.
+- A display issue occurring with the Adobe Reader X plug-in was fixed.
+- An issue related to transparency with some versions of Adobe Reader was fixed.
+- The Content-Length header was removed because it caused an issue when the HTTP server applies compression.
+
+
v1.6 (2008-08-03)
+
+- PHP 4.3.10 or higher is now required.
+- GIF image support.
+- Images can now trigger page breaks.
+- Possibility to have different page formats in a single document.
+- Document properties (author, creator, keywords, subject and title) can now be specified in UTF-8.
+- Fixed a bug: when a PNG was inserted through a URL, an error sometimes occurred.
+- An automatic page break in Header() doesn't cause an infinite loop any more.
+- Removed some warning messages appearing with recent PHP versions.
+- Added HTTP headers to reduce problems with IE.
+
+
v1.53 (2004-12-31)
+
+- When the font subdirectory is in the same directory as fpdf.php, it's no longer necessary to define the FPDF_FONTPATH constant.
+- The array $HTTP_SERVER_VARS is no longer used. It could cause trouble on PHP5-based configurations with the register_long_arrays option disabled.
+- Fixed a problem related to Type1 font embedding which caused trouble to some PDF processors.
+- The file name sent to the browser could not contain a space character.
+- The Cell() method could not print the number 0 (you had to pass the string '0').
+
+
v1.52 (2003-12-30)
+
+- Image() now displays the image at 72 dpi if no dimension is given.
+- Output() takes a string as second parameter to indicate destination.
+- Open() is now called automatically by AddPage().
+- Inserting remote JPEG images doesn't generate an error any longer.
+- Decimal separator is forced to dot in the constructor.
+- Added several encodings (Turkish, Thai, Hebrew, Ukrainian and Vietnamese).
+- The last line of a right-aligned MultiCell() was not correctly aligned if it was terminated by a carriage return.
+- No more error message about already sent headers when outputting the PDF to the standard output from the command line.
+- The underlining was going too far for text containing characters \, ( or ).
+- $HTTP_ENV_VARS has been replaced by $HTTP_SERVER_VARS.
+
+
v1.51 (2002-08-03)
+
+- Type1 font support.
+- Added Baltic encoding.
+- The class now works internally in points with the origin at the bottom in order to avoid two bugs occurring with Acrobat 5 : * The line thickness was too large when printed under Windows 98 SE and ME. * TrueType fonts didn't appear immediately inside the plug-in (a substitution font was used), one had to cause a window refresh to make them show up.
+- It's no longer necessary to set the decimal separator as dot to produce valid documents.
+- The clickable area in a cell was always on the left independently from the text alignment.
+- JPEG images in CMYK mode appeared in inverted colors.
+- Transparent PNG images in grayscale or true color mode were incorrectly handled.
+- Adding new fonts now works correctly even with the magic_quotes_runtime option set to on.
+
+
v1.5 (2002-05-28)
+
+- TrueType font (AddFont()) and encoding support (Western and Eastern Europe, Cyrillic and Greek).
+- Added Write() method.
+- Added underlined style.
+- Internal and external link support (AddLink(), SetLink(), Link()).
+- Added right margin management and methods SetRightMargin(), SetTopMargin().
+- Modification of SetDisplayMode() to select page layout.
+- The border parameter of MultiCell() now lets choose borders to draw as Cell().
+- When a document contains no page, Close() now calls AddPage() instead of causing a fatal error.
+
+
v1.41 (2002-03-13)
+
+- Fixed SetDisplayMode() which no longer worked (the PDF viewer used its default display).
+
+
v1.4 (2002-03-02)
+
+- PHP3 is no longer supported.
+- Page compression (SetCompression()).
+- Choice of page format and possibility to change orientation inside document.
+- Added AcceptPageBreak() method.
+- Ability to print the total number of pages (AliasNbPages()).
+- Choice of cell borders to draw.
+- New mode for Cell(): the current position can now move under the cell.
+- Ability to include an image by specifying height only (width is calculated automatically).
+- Fixed a bug: when a justified line triggered a page break, the footer inherited the corresponding word spacing.
+
+
v1.31 (2002-01-12)
+
+- Fixed a bug in drawing frame with MultiCell(): the last line always started from the left margin.
+- Removed Expires HTTP header (gives trouble in some situations).
+- Added Content-disposition HTTP header (seems to help in some situations).
+
+
v1.3 (2001-12-03)
+
+- Line break and text justification support (MultiCell()).
+- Color support (SetDrawColor(), SetFillColor(), SetTextColor()). Possibility to draw filled rectangles and paint cell background.
+- A cell whose width is declared null extends up to the right margin of the page.
+- Line width is now retained from page to page and defaults to 0.2 mm.
+- Added SetXY() method.
+- Fixed a passing by reference done in a deprecated manner for PHP4.
+
+
v1.2 (2001-11-11)
+
+- Added font metric files and GetStringWidth() method.
+- Centering and right-aligning text in cells.
+- Display mode control (SetDisplayMode()).
+- Added methods to set document properties (SetAuthor(), SetCreator(), SetKeywords(), SetSubject(), SetTitle()).
+- Possibility to force PDF download by browser.
+- Added SetX() and GetX() methods.
+- During automatic page break, current abscissa is now retained.
+
+
v1.11 (2001-10-20)
+
+- PNG support doesn't require PHP4/zlib any more. Data are now put directly into PDF without any decompression/recompression stage.
+- Image insertion now works correctly even with magic_quotes_runtime option set to on.
+
+
v1.1 (2001-10-07)
+
+- JPEG and PNG image support.
+
+
v1.01 (2001-10-03)
+
+- Fixed a bug involving page break: in case when Header() doesn't specify a font, the one from previous page was not restored and produced an incorrect document.
+
+Whenever a page break condition is met, the method is called, and the break is issued or not
+depending on the returned value. The default implementation returns a value according to the
+mode selected by SetAutoPageBreak().
+
+This method is called automatically and should not be called directly by the application.
+
Example
+The method is overriden in an inherited class in order to obtain a 3 column layout:
+
+
class PDF extends FPDF
+{
+var $col = 0;
+
+function SetCol($col)
+{
+ // Move position to a column
+ $this->col = $col;
+ $x = 10+$col*65;
+ $this->SetLeftMargin($x);
+ $this->SetX($x);
+}
+
+function AcceptPageBreak()
+{
+ if($this->col<2)
+ {
+ // Go to next column
+ $this->SetCol($this->col+1);
+ $this->SetY(10);
+ return false;
+ }
+ else
+ {
+ // Go back to first column and issue page break
+ $this->SetCol(0);
+ return true;
+ }
+}
+}
+
+$pdf = new PDF();
+$pdf->AddPage();
+$pdf->SetFont('Arial','',12);
+for($i=1;$i<=300;$i++)
+ $pdf->Cell(0,5,"Line $i",0,1);
+$pdf->Output();
+AddFont(string family [, string style [, string file]])
+
Description
+Imports a TrueType, OpenType or Type1 font and makes it available. It is necessary to generate a font
+definition file first with the MakeFont utility.
+
+The definition file (and the font file itself when embedding) must be present in the font directory.
+If it is not found, the error "Could not include font definition file" is raised.
+
Parameters
+
+
family
+
+Font family. The name can be chosen arbitrarily. If it is a standard family name, it will
+override the corresponding font.
+
+
style
+
+Font style. Possible values are (case insensitive):
+
+
empty string: regular
+
B: bold
+
I: italic
+
BI or IB: bold italic
+
+The default value is regular.
+
+
file
+
+The font definition file.
+
+By default, the name is built from the family and style, in lower case with no space.
+
+Creates a new internal link and returns its identifier. An internal link is a clickable area
+which directs to another place within the document.
+
+The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is
+defined with SetLink().
+
+Adds a new page to the document. If a page is already present, the Footer() method is called
+first to output the footer. Then the page is added, the current position set to the top-left
+corner according to the left and top margins, and Header() is called to display the header.
+
+The font which was set before calling is automatically restored. There is no need to call
+SetFont() again if you want to continue with the same font. The same is true for colors and
+line width.
+
+The origin of the coordinate system is at the top-left corner and increasing ordinates go
+downwards.
+
Parameters
+
+
orientation
+
+Page orientation. Possible values are (case insensitive):
+
+
P or Portrait
+
L or Landscape
+
+The default value is the one passed to the constructor.
+
+
size
+
+Page size. It can be either one of the following values (case insensitive):
+
+
A3
+
A4
+
A5
+
Letter
+
Legal
+
+or an array containing the width and the height (expressed in user unit).
+
+The default value is the one passed to the constructor.
+
+Defines an alias for the total number of pages. It will be substituted as the document is
+closed.
+
Parameters
+
+
alias
+
+The alias. Default value: {nb}.
+
+
+
Example
+
+
class PDF extends FPDF
+{
+function Footer()
+{
+ // Go to 1.5 cm from bottom
+ $this->SetY(-15);
+ // Select Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Print current and total page numbers
+ $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
+}
+}
+
+$pdf = new PDF();
+$pdf->AliasNbPages();
+Cell(float w [, float h [, string txt [, mixed border [, int ln [, string align [, boolean fill [, mixed link]]]]]]])
+
Description
+Prints a cell (rectangular area) with optional borders, background color and character string.
+The upper-left corner of the cell corresponds to the current position. The text can be aligned
+or centered. After the call, the current position moves to the right or to the next line. It is
+possible to put a link on the text.
+
+If automatic page breaking is enabled and the cell goes beyond the limit, a page break is
+done before outputting.
+
Parameters
+
+
w
+
+Cell width. If 0, the cell extends up to the right margin.
+
+
h
+
+Cell height.
+Default value: 0.
+
+
txt
+
+String to print.
+Default value: empty string.
+
+
border
+
+Indicates if borders must be drawn around the cell. The value can be either a number:
+
+
0: no border
+
1: frame
+
+or a string containing some or all of the following characters (in any order):
+
+
L: left
+
T: top
+
R: right
+
B: bottom
+
+Default value: 0.
+
+
ln
+
+Indicates where the current position should go after the call. Possible values are:
+
+
0: to the right
+
1: to the beginning of the next line
+
2: below
+
+Putting 1 is equivalent to putting 0 and calling Ln() just after.
+Default value: 0.
+
+
align
+
+Allows to center or align the text. Possible values are:
+
+
L or empty string: left align (default value)
+
C: center
+
R: right align
+
+
+
fill
+
+Indicates if the cell background must be painted (true) or transparent (false).
+Default value: false.
+
+
link
+
+URL or identifier returned by AddLink().
+
+
+
Example
+
+
// Set font
+$pdf->SetFont('Arial','B',16);
+// Move to 8 cm to the right
+$pdf->Cell(80);
+// Centered text in a framed 20*10 mm cell and line break
+$pdf->Cell(20,10,'Title',1,1,'C');
+Terminates the PDF document. It is not necessary to call this method explicitly because Output()
+does it automatically.
+
+If the document contains no page, AddPage() is called to prevent from getting an invalid document.
+
+This method is automatically called in case of fatal error; it simply outputs the message
+and halts the execution. An inherited class may override it to customize the error handling
+but should always halt the script, or the resulting document would probably be invalid.
+
+This method is used to render the page footer. It is automatically called by AddPage() and
+Close() and should not be called directly by the application. The implementation in FPDF is
+empty, so you have to subclass it and override the method if you want a specific processing.
+
Example
+
+
class PDF extends FPDF
+{
+function Footer()
+{
+ // Go to 1.5 cm from bottom
+ $this->SetY(-15);
+ // Select Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Print centered page number
+ $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
+}
+}
+FPDF([string orientation [, string unit [, mixed size]]])
+
Description
+This is the class constructor. It allows to set up the page size, the orientation and the
+unit of measure used in all methods (except for font sizes).
+
Parameters
+
+
orientation
+
+Default page orientation. Possible values are (case insensitive):
+
+
P or Portrait
+
L or Landscape
+
+Default value is P.
+
+
unit
+
+User unit. Possible values are:
+
+
pt: point
+
mm: millimeter
+
cm: centimeter
+
in: inch
+
+A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This
+is a very common unit in typography; font sizes are expressed in that unit.
+
+
+Default value is mm.
+
+
size
+
+The size used for pages. It can be either one of the following values (case insensitive):
+
+
A3
+
A4
+
A5
+
Letter
+
Legal
+
+or an array containing the width and the height (expressed in the unit given by unit).
+
+Default value is A4.
+
+This method is used to render the page header. It is automatically called by AddPage() and
+should not be called directly by the application. The implementation in FPDF is empty, so
+you have to subclass it and override the method if you want a specific processing.
+
Example
+
+
class PDF extends FPDF
+{
+function Header()
+{
+ // Select Arial bold 15
+ $this->SetFont('Arial','B',15);
+ // Move to the right
+ $this->Cell(80);
+ // Framed title
+ $this->Cell(30,10,'Title',1,0,'C');
+ // Line break
+ $this->Ln(20);
+}
+}
+Image(string file [, float x [, float y [, float w [, float h [, string type [, mixed link]]]]]])
+
Description
+Puts an image. The size it will take on the page can be specified in different ways:
+
+
explicit width and height (expressed in user unit or dpi)
+
one explicit dimension, the other being calculated automatically in order to keep the original proportions
+
no explicit dimension, in which case the image is put at 96 dpi
+
+Supported formats are JPEG, PNG and GIF. The GD extension is required for GIF.
+
+
+For JPEGs, all flavors are allowed:
+
+
gray scales
+
true colors (24 bits)
+
CMYK (32 bits)
+
+For PNGs, are allowed:
+
+
gray scales on at most 8 bits (256 levels)
+
indexed colors
+
true colors (24 bits)
+
+For GIFs: in case of an animated GIF, only the first frame is displayed.
+
+Transparency is supported.
+
+The format can be specified explicitly or inferred from the file extension.
+
+It is possible to put a link on the image.
+
+Remark: if an image is used several times, only one copy is embedded in the file.
+
Parameters
+
+
file
+
+Path or URL of the image.
+
+
x
+
+Abscissa of the upper-left corner. If not specified or equal to null, the current abscissa
+is used.
+
+
y
+
+Ordinate of the upper-left corner. If not specified or equal to null, the current ordinate
+is used; moreover, a page break is triggered first if necessary (in case automatic page breaking is enabled)
+and, after the call, the current ordinate is moved to the bottom of the image.
+
+
w
+
+Width of the image in the page. There are three cases:
+
+
If the value is positive, it represents the width in user unit
+
If the value is negative, the absolute value represents the horizontal resolution in dpi
+
If the value is not specified or equal to zero, it is automatically calculated
+
+
+
h
+
+Height of the image in the page. There are three cases:
+
+
If the value is positive, it represents the height in user unit
+
If the value is negative, the absolute value represents the vertical resolution in dpi
+
If the value is not specified or equal to zero, it is automatically calculated
+
+
+
type
+
+Image format. Possible values are (case insensitive): JPG, JPEG, PNG and GIF.
+If not specified, the type is inferred from the file extension.
+
+
link
+
+URL or identifier returned by AddLink().
+
+
+
Example
+
+
// Insert a logo in the top-left corner at 300 dpi
+$pdf->Image('logo.png',10,10,-300);
+// Insert a dynamic image from a URL
+$pdf->Image('http://chart.googleapis.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World',60,30,90,0,'PNG');
+AcceptPageBreak - accept or not automatic page break
+AddFont - add a new font
+AddLink - create an internal link
+AddPage - add a new page
+AliasNbPages - define an alias for number of pages
+Cell - print a cell
+Close - terminate the document
+Error - fatal error
+Footer - page footer
+FPDF - constructor
+GetStringWidth - compute string length
+GetX - get current x position
+GetY - get current y position
+Header - page header
+Image - output an image
+Line - draw a line
+Link - put a link
+Ln - line break
+MultiCell - print text with line breaks
+Output - save or send the document
+PageNo - page number
+Rect - draw a rectangle
+SetAuthor - set the document author
+SetAutoPageBreak - set the automatic page breaking mode
+SetCompression - turn compression on or off
+SetCreator - set document creator
+SetDisplayMode - set display mode
+SetDrawColor - set drawing color
+SetFillColor - set filling color
+SetFont - set font
+SetFontSize - set font size
+SetKeywords - associate keywords with document
+SetLeftMargin - set left margin
+SetLineWidth - set line width
+SetLink - set internal link destination
+SetMargins - set margins
+SetRightMargin - set right margin
+SetSubject - set document subject
+SetTextColor - set text color
+SetTitle - set document title
+SetTopMargin - set top margin
+SetX - set current x position
+SetXY - set current x and y positions
+SetY - set current y position
+Text - print a string
+Write - print flowing text
+
+
diff --git a/vendor/fpdf/doc/line.htm b/vendor/fpdf/doc/line.htm
new file mode 100644
index 0000000..ceb4e07
--- /dev/null
+++ b/vendor/fpdf/doc/line.htm
@@ -0,0 +1,38 @@
+
+
+
+
+Line
+
+
+
+
+Puts a link on a rectangular area of the page. Text or image links are generally put via Cell(),
+Write() or Image(), but this method can be useful for instance to define a clickable area inside
+an image.
+
Parameters
+
+
x
+
+Abscissa of the upper-left corner of the rectangle.
+
+
y
+
+Ordinate of the upper-left corner of the rectangle.
+
+This method allows printing text with line breaks. They can be automatic (as soon as the
+text reaches the right border of the cell) or explicit (via the \n character). As many cells
+as necessary are output, one below the other.
+
+Text can be aligned, centered or justified. The cell block can be framed and the background
+painted.
+
Parameters
+
+
w
+
+Width of cells. If 0, they extend up to the right margin of the page.
+
+
h
+
+Height of cells.
+
+
txt
+
+String to print.
+
+
border
+
+Indicates if borders must be drawn around the cell block. The value can be either a number:
+
+
0: no border
+
1: frame
+
+or a string containing some or all of the following characters (in any order):
+
+
L: left
+
T: top
+
R: right
+
B: bottom
+
+Default value: 0.
+
+
align
+
+Sets the text alignment. Possible values are:
+
+
L: left alignment
+
C: center
+
R: right alignment
+
J: justification (default value)
+
+
+
fill
+
+Indicates if the cell background must be painted (true) or transparent (false).
+Default value: false.
+
+Send the document to a given destination: browser, file or string. In the case of browser, the
+plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.
+
+The method first calls Close() if necessary to terminate the document.
+
Parameters
+
+
name
+
+The name of the file. If not specified, the document will be sent to the browser
+(destination I) with the name doc.pdf.
+
+
dest
+
+Destination where to send the document. It can take one of the following values:
+
+
I: send the file inline to the browser. The plug-in is used if available.
+The name given by name is used when one selects the "Save as" option on the
+link generating the PDF.
+
D: send to the browser and force a file download with the name given by
+name.
+
F: save to a local file with the name given by name (may include a path).
+
S: return the document as a string. name is ignored.
+SetAutoPageBreak(boolean auto [, float margin])
+
Description
+Enables or disables the automatic page breaking mode. When enabling, the second parameter is
+the distance from the bottom of the page that defines the triggering limit. By default, the
+mode is on and the margin is 2 cm.
+
Parameters
+
+
auto
+
+Boolean indicating if mode should be on or off.
+
+Activates or deactivates page compression. When activated, the internal representation of
+each page is compressed, which leads to a compression ratio of about 2 for the resulting
+document.
+
+Compression is on by default.
+
+
+Note: the Zlib extension is required for this feature. If not present, compression
+will be turned off.
+
Parameters
+
+
compress
+
+Boolean indicating if compression must be enabled.
+
+Defines the way the document is to be displayed by the viewer. The zoom level can be set: pages can be
+displayed entirely on screen, occupy the full width of the window, use real size, be scaled by a
+specific zooming factor or use viewer default (configured in the Preferences menu of Adobe Reader).
+The page layout can be specified too: single at once, continuous display, two columns or viewer
+default.
+
Parameters
+
+
zoom
+
+The zoom to use. It can be one of the following string values:
+
+
fullpage: displays the entire page on screen
+
fullwidth: uses maximum width of window
+
real: uses real size (equivalent to 100% zoom)
+
default: uses viewer default mode
+
+or a number indicating the zooming factor to use.
+
+Defines the color used for all drawing operations (lines, rectangles and cell borders). It
+can be expressed in RGB components or gray scale. The method can be called before the first
+page is created and the value is retained from page to page.
+
Parameters
+
+
r
+
+If g et b are given, red component; if not, indicates the gray level.
+Value between 0 and 255.
+
+Defines the color used for all filling operations (filled rectangles and cell backgrounds).
+It can be expressed in RGB components or gray scale. The method can be called before the first
+page is created and the value is retained from page to page.
+
Parameters
+
+
r
+
+If g and b are given, red component; if not, indicates the gray level.
+Value between 0 and 255.
+
+SetFont(string family [, string style [, float size]])
+
Description
+Sets the font used to print character strings. It is mandatory to call this method
+at least once before printing text or the resulting document would not be valid.
+
+The font can be either a standard one or a font added via the AddFont() method. Standard fonts
+use the Windows encoding cp1252 (Western Europe).
+
+The method can be called before the first page is created and the font is kept from page
+to page.
+
+If you just wish to change the current font size, it is simpler to call SetFontSize().
+
+
+Note: the font definition files must be accessible. They are searched successively in:
+
+
The directory defined by the FPDF_FONTPATH constant (if this constant is defined)
+
The font directory located in the same directory as fpdf.php (if it exists)
+If the file corresponding to the requested font is not found, the error "Could not include font
+definition file" is raised.
+
Parameters
+
+
family
+
+Family font. It can be either a name defined by AddFont() or one of the standard families (case
+insensitive):
+
+
Courier (fixed-width)
+
Helvetica or Arial (synonymous; sans serif)
+
Times (serif)
+
Symbol (symbolic)
+
ZapfDingbats (symbolic)
+
+It is also possible to pass an empty string. In that case, the current family is kept.
+
+
style
+
+Font style. Possible values are (case insensitive):
+
+
empty string: regular
+
B: bold
+
I: italic
+
U: underline
+
+or any combination. The default value is regular.
+Bold and italic styles do not apply to Symbol and ZapfDingbats.
+
+
size
+
+Font size in points.
+
+The default value is the current size. If no size has been specified since the beginning of
+the document, the value taken is 12.
+
+
+
Example
+
+
// Times regular 12
+$pdf->SetFont('Times');
+// Arial bold 14
+$pdf->SetFont('Arial','B',14);
+// Removes bold
+$pdf->SetFont('');
+// Times bold, italic and underlined 14
+$pdf->SetFont('Times','BIU');
+Defines the left margin. The method can be called before creating the first page.
+
+If the current abscissa gets out of page, it is brought back to the margin.
+
+Defines the line width. By default, the value equals 0.2 mm. The method can be called before
+the first page is created and the value is retained from page to page.
+
+Defines the color used for text. It can be expressed in RGB components or gray scale. The
+method can be called before the first page is created and the value is retained from page to
+page.
+
Parameters
+
+
r
+
+If g et b are given, red component; if not, indicates the gray level.
+Value between 0 and 255.
+
+Defines the abscissa and ordinate of the current position. If the passed values are negative,
+they are relative respectively to the right and bottom of the page.
+
+Moves the current abscissa back to the left margin and sets the ordinate. If the passed value
+is negative, it is relative to the bottom of the page.
+
+Prints a character string. The origin is on the left of the first character, on the baseline.
+This method allows to place a string precisely on the page, but it is usually easier to use
+Cell(), MultiCell() or Write() which are the standard methods to print text.
+
+This method prints text from the current position. When the right margin is reached (or the \n
+character is met) a line break occurs and text continues from the left margin. Upon method exit,
+the current position is left just at the end of the text.
+
+It is possible to put a link on the text.
+
Parameters
+
+
h
+
+Line height.
+
+
txt
+
+String to print.
+
+
link
+
+URL or identifier returned by AddLink().
+
+
+
Example
+
+
// Begin with regular font
+$pdf->SetFont('Arial','',14);
+$pdf->Write(5,'Visit ');
+// Then put a blue underlined link
+$pdf->SetTextColor(0,0,255);
+$pdf->SetFont('','U');
+$pdf->Write(5,'www.fpdf.org','http://www.fpdf.org');
+After including the library file, we create an FPDF object.
+The FPDF() constructor is used here with the default values: pages are in A4 portrait and
+the unit of measure is millimeter. It could have been specified explicitly with:
+
+
$pdf = new FPDF('P','mm','A4');
+
+
+It's possible to use landscape (L), other page sizes (such as Letter and
+Legal) and units (pt, cm, in).
+
+
+There's no page at the moment, so we have to add one with AddPage(). The origin
+is at the upper-left corner and the current position is by default set at 1 cm from the
+borders; the margins can be changed with SetMargins().
+
+
+Before we can print text, it's mandatory to select a font with SetFont(), otherwise the
+document would be invalid. We choose Arial bold 16:
+
+
$pdf->SetFont('Arial','B',16);
+
+
+We could have specified italics with I, underlined with U or a regular font with an empty string
+(or any combination). Note that the font size is given in points, not millimeters (or another user
+unit); it's the only exception. The other standard fonts are Times, Courier, Symbol and ZapfDingbats.
+
+
+We can now print a cell with Cell(). A cell is a rectangular area, possibly framed,
+which contains a line of text. It is output at the current position. We specify its dimensions,
+its text (centered or aligned), if borders should be drawn, and where the current position
+moves after it (to the right, below or to the beginning of the next line). To add a frame, we would do this:
+
+
$pdf->Cell(40,10,'Hello World !',1);
+
+
+To add a new cell next to it with centered text and go to the next line, we would do:
+
+
$pdf->Cell(60,10,'Powered by FPDF.',0,1,'C');
+
+
+Remark: the line break can also be done with Ln(). This method additionnaly allows to specify
+the height of the break.
+
+
+Finally, the document is closed and sent to the browser with Output(). We could have saved
+it to a file by passing the desired file name.
+
+
+Caution: in case when the PDF is sent to the browser, nothing else must be output by the
+script, neither before nor after (no HTML, not even a space or a carriage return). If you send something
+before, you will get the error message: "Some data has already been output, can't send PDF file". If you
+send something after, the document might not display.
+
+
diff --git a/vendor/fpdf/tutorial/tuto1.php b/vendor/fpdf/tutorial/tuto1.php
new file mode 100644
index 0000000..3ab55a1
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto1.php
@@ -0,0 +1,9 @@
+AddPage();
+$pdf->SetFont('Arial','B',16);
+$pdf->Cell(40,10,'Hello World!');
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto2.htm b/vendor/fpdf/tutorial/tuto2.htm
new file mode 100644
index 0000000..c402cf4
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto2.htm
@@ -0,0 +1,80 @@
+
+
+
+
+Header, footer, page break and image
+
+
+
+
Header, footer, page break and image
+Here's a two page example with header, footer and logo:
+
+
<?php
+require('fpdf.php');
+
+class PDF extends FPDF
+{
+// Page header
+function Header()
+{
+ // Logo
+ $this->Image('logo.png',10,6,30);
+ // Arial bold 15
+ $this->SetFont('Arial','B',15);
+ // Move to the right
+ $this->Cell(80);
+ // Title
+ $this->Cell(30,10,'Title',1,0,'C');
+ // Line break
+ $this->Ln(20);
+}
+
+// Page footer
+function Footer()
+{
+ // Position at 1.5 cm from bottom
+ $this->SetY(-15);
+ // Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Page number
+ $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
+}
+}
+
+// Instanciation of inherited class
+$pdf = new PDF();
+$pdf->AliasNbPages();
+$pdf->AddPage();
+$pdf->SetFont('Times','',12);
+for($i=1;$i<=40;$i++)
+ $pdf->Cell(0,10,'Printing line number '.$i,0,1);
+$pdf->Output();
+?>
+This example makes use of the Header() and Footer() methods to process page headers and
+footers. They are called automatically. They already exist in the FPDF class but do nothing,
+therefore we have to extend the class and override them.
+
+
+The logo is printed with the Image() method by specifying its upper-left corner and
+its width. The height is calculated automatically to respect the image proportions.
+
+
+To print the page number, a null value is passed as the cell width. It means that the cell
+should extend up to the right margin of the page; this is handy to center text. The current page
+number is returned by the PageNo() method; as for the total number of pages, it's obtained
+via the special value {nb} which is substituted when the document is finished
+(provided you first called AliasNbPages()).
+
+Note the use of the SetY() method which allows to set position at an absolute location in
+the page, starting from the top or the bottom.
+
+
+Another interesting feature is used here: the automatic page breaking. As soon as a cell would
+cross a limit in the page (at 2 centimeters from the bottom by default), a break is issued
+and the font restored. Although the header and footer select their own font (Arial), the body
+continues with Times. This mechanism of automatic restoration also applies to colors and line
+width. The limit which triggers page breaks can be set with SetAutoPageBreak().
+
+
diff --git a/vendor/fpdf/tutorial/tuto2.php b/vendor/fpdf/tutorial/tuto2.php
new file mode 100644
index 0000000..6a1b4f8
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto2.php
@@ -0,0 +1,41 @@
+Image('logo.png',10,6,30);
+ // Arial bold 15
+ $this->SetFont('Arial','B',15);
+ // Move to the right
+ $this->Cell(80);
+ // Title
+ $this->Cell(30,10,'Title',1,0,'C');
+ // Line break
+ $this->Ln(20);
+}
+
+// Page footer
+function Footer()
+{
+ // Position at 1.5 cm from bottom
+ $this->SetY(-15);
+ // Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Page number
+ $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
+}
+}
+
+// Instanciation of inherited class
+$pdf = new PDF();
+$pdf->AliasNbPages();
+$pdf->AddPage();
+$pdf->SetFont('Times','',12);
+for($i=1;$i<=40;$i++)
+ $pdf->Cell(0,10,'Printing line number '.$i,0,1);
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto3.htm b/vendor/fpdf/tutorial/tuto3.htm
new file mode 100644
index 0000000..5d8363f
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto3.htm
@@ -0,0 +1,115 @@
+
+
+
+
+Line breaks and colors
+
+
+
+
Line breaks and colors
+Let's continue with an example which prints justified paragraphs. It also illustrates the use
+of colors.
+
+
<?php
+require('fpdf.php');
+
+class PDF extends FPDF
+{
+function Header()
+{
+ global $title;
+
+ // Arial bold 15
+ $this->SetFont('Arial','B',15);
+ // Calculate width of title and position
+ $w = $this->GetStringWidth($title)+6;
+ $this->SetX((210-$w)/2);
+ // Colors of frame, background and text
+ $this->SetDrawColor(0,80,180);
+ $this->SetFillColor(230,230,0);
+ $this->SetTextColor(220,50,50);
+ // Thickness of frame (1 mm)
+ $this->SetLineWidth(1);
+ // Title
+ $this->Cell($w,9,$title,1,1,'C',true);
+ // Line break
+ $this->Ln(10);
+}
+
+function Footer()
+{
+ // Position at 1.5 cm from bottom
+ $this->SetY(-15);
+ // Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Text color in gray
+ $this->SetTextColor(128);
+ // Page number
+ $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
+}
+
+function ChapterTitle($num, $label)
+{
+ // Arial 12
+ $this->SetFont('Arial','',12);
+ // Background color
+ $this->SetFillColor(200,220,255);
+ // Title
+ $this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
+ // Line break
+ $this->Ln(4);
+}
+
+function ChapterBody($file)
+{
+ // Read text file
+ $txt = file_get_contents($file);
+ // Times 12
+ $this->SetFont('Times','',12);
+ // Output justified text
+ $this->MultiCell(0,5,$txt);
+ // Line break
+ $this->Ln();
+ // Mention in italics
+ $this->SetFont('','I');
+ $this->Cell(0,5,'(end of excerpt)');
+}
+
+function PrintChapter($num, $title, $file)
+{
+ $this->AddPage();
+ $this->ChapterTitle($num,$title);
+ $this->ChapterBody($file);
+}
+}
+
+$pdf = new PDF();
+$title = '20000 Leagues Under the Seas';
+$pdf->SetTitle($title);
+$pdf->SetAuthor('Jules Verne');
+$pdf->PrintChapter(1,'A RUNAWAY REEF','20k_c1.txt');
+$pdf->PrintChapter(2,'THE PROS AND CONS','20k_c2.txt');
+$pdf->Output();
+?>
+The GetStringWidth() method allows to determine the length of a string in the current font,
+which is used here to calculate the position and the width of the frame surrounding the title.
+Then colors are set (via SetDrawColor(), SetFillColor() and SetTextColor()) and the
+thickness of the line is set to 1 mm (instead of 0.2 by default) with SetLineWidth(). Finally,
+we output the cell (the last parameter true indicates that the background must
+be filled).
+
+
+The method used to print the paragraphs is MultiCell(). Each time a line reaches the
+right extremity of the cell or a carriage return character is met, a line break is issued
+and a new cell automatically created under the current one. Text is justified by default.
+
+
+Two document properties are defined: the title (SetTitle()) and the author (SetAuthor()).
+There are several ways to view them in Adobe Reader. The first one is to open the file directly with
+the reader, go to the File menu and choose the Properties option. The second one, also available from
+the plug-in, is to right-click and select Document Properties. The third method is to type the Ctrl+D
+key combination.
+
+
diff --git a/vendor/fpdf/tutorial/tuto3.php b/vendor/fpdf/tutorial/tuto3.php
new file mode 100644
index 0000000..3316ddb
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto3.php
@@ -0,0 +1,81 @@
+SetFont('Arial','B',15);
+ // Calculate width of title and position
+ $w = $this->GetStringWidth($title)+6;
+ $this->SetX((210-$w)/2);
+ // Colors of frame, background and text
+ $this->SetDrawColor(0,80,180);
+ $this->SetFillColor(230,230,0);
+ $this->SetTextColor(220,50,50);
+ // Thickness of frame (1 mm)
+ $this->SetLineWidth(1);
+ // Title
+ $this->Cell($w,9,$title,1,1,'C',true);
+ // Line break
+ $this->Ln(10);
+}
+
+function Footer()
+{
+ // Position at 1.5 cm from bottom
+ $this->SetY(-15);
+ // Arial italic 8
+ $this->SetFont('Arial','I',8);
+ // Text color in gray
+ $this->SetTextColor(128);
+ // Page number
+ $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
+}
+
+function ChapterTitle($num, $label)
+{
+ // Arial 12
+ $this->SetFont('Arial','',12);
+ // Background color
+ $this->SetFillColor(200,220,255);
+ // Title
+ $this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
+ // Line break
+ $this->Ln(4);
+}
+
+function ChapterBody($file)
+{
+ // Read text file
+ $txt = file_get_contents($file);
+ // Times 12
+ $this->SetFont('Times','',12);
+ // Output justified text
+ $this->MultiCell(0,5,$txt);
+ // Line break
+ $this->Ln();
+ // Mention in italics
+ $this->SetFont('','I');
+ $this->Cell(0,5,'(end of excerpt)');
+}
+
+function PrintChapter($num, $title, $file)
+{
+ $this->AddPage();
+ $this->ChapterTitle($num,$title);
+ $this->ChapterBody($file);
+}
+}
+
+$pdf = new PDF();
+$title = '20000 Leagues Under the Seas';
+$pdf->SetTitle($title);
+$pdf->SetAuthor('Jules Verne');
+$pdf->PrintChapter(1,'A RUNAWAY REEF','20k_c1.txt');
+$pdf->PrintChapter(2,'THE PROS AND CONS','20k_c2.txt');
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto4.htm b/vendor/fpdf/tutorial/tuto4.htm
new file mode 100644
index 0000000..18a2108
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto4.htm
@@ -0,0 +1,134 @@
+
+
+
+
+Multi-columns
+
+
+
+
Multi-columns
+This example is a variant of the previous one showing how to lay the text across multiple
+columns.
+
+
<?php
+require('fpdf.php');
+
+class PDF extends FPDF
+{
+// Current column
+var $col = 0;
+// Ordinate of column start
+var $y0;
+
+function Header()
+{
+ // Page header
+ global $title;
+
+ $this->SetFont('Arial','B',15);
+ $w = $this->GetStringWidth($title)+6;
+ $this->SetX((210-$w)/2);
+ $this->SetDrawColor(0,80,180);
+ $this->SetFillColor(230,230,0);
+ $this->SetTextColor(220,50,50);
+ $this->SetLineWidth(1);
+ $this->Cell($w,9,$title,1,1,'C',true);
+ $this->Ln(10);
+ // Save ordinate
+ $this->y0 = $this->GetY();
+}
+
+function Footer()
+{
+ // Page footer
+ $this->SetY(-15);
+ $this->SetFont('Arial','I',8);
+ $this->SetTextColor(128);
+ $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
+}
+
+function SetCol($col)
+{
+ // Set position at a given column
+ $this->col = $col;
+ $x = 10+$col*65;
+ $this->SetLeftMargin($x);
+ $this->SetX($x);
+}
+
+function AcceptPageBreak()
+{
+ // Method accepting or not automatic page break
+ if($this->col<2)
+ {
+ // Go to next column
+ $this->SetCol($this->col+1);
+ // Set ordinate to top
+ $this->SetY($this->y0);
+ // Keep on page
+ return false;
+ }
+ else
+ {
+ // Go back to first column
+ $this->SetCol(0);
+ // Page break
+ return true;
+ }
+}
+
+function ChapterTitle($num, $label)
+{
+ // Title
+ $this->SetFont('Arial','',12);
+ $this->SetFillColor(200,220,255);
+ $this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
+ $this->Ln(4);
+ // Save ordinate
+ $this->y0 = $this->GetY();
+}
+
+function ChapterBody($file)
+{
+ // Read text file
+ $txt = file_get_contents($file);
+ // Font
+ $this->SetFont('Times','',12);
+ // Output text in a 6 cm width column
+ $this->MultiCell(60,5,$txt);
+ $this->Ln();
+ // Mention
+ $this->SetFont('','I');
+ $this->Cell(0,5,'(end of excerpt)');
+ // Go back to first column
+ $this->SetCol(0);
+}
+
+function PrintChapter($num, $title, $file)
+{
+ // Add chapter
+ $this->AddPage();
+ $this->ChapterTitle($num,$title);
+ $this->ChapterBody($file);
+}
+}
+
+$pdf = new PDF();
+$title = '20000 Leagues Under the Seas';
+$pdf->SetTitle($title);
+$pdf->SetAuthor('Jules Verne');
+$pdf->PrintChapter(1,'A RUNAWAY REEF','20k_c1.txt');
+$pdf->PrintChapter(2,'THE PROS AND CONS','20k_c2.txt');
+$pdf->Output();
+?>
+The key method used is AcceptPageBreak(). It allows to accept or not an automatic page
+break. By refusing it and altering the margin and current position, the desired column layout
+is achieved.
+
+For the rest, not many changes; two properties have been added to the class to save the current
+column number and the position where columns begin, and the MultiCell() call specifies a
+6 centimeter width.
+
+
diff --git a/vendor/fpdf/tutorial/tuto4.php b/vendor/fpdf/tutorial/tuto4.php
new file mode 100644
index 0000000..c326982
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto4.php
@@ -0,0 +1,111 @@
+SetFont('Arial','B',15);
+ $w = $this->GetStringWidth($title)+6;
+ $this->SetX((210-$w)/2);
+ $this->SetDrawColor(0,80,180);
+ $this->SetFillColor(230,230,0);
+ $this->SetTextColor(220,50,50);
+ $this->SetLineWidth(1);
+ $this->Cell($w,9,$title,1,1,'C',true);
+ $this->Ln(10);
+ // Save ordinate
+ $this->y0 = $this->GetY();
+}
+
+function Footer()
+{
+ // Page footer
+ $this->SetY(-15);
+ $this->SetFont('Arial','I',8);
+ $this->SetTextColor(128);
+ $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
+}
+
+function SetCol($col)
+{
+ // Set position at a given column
+ $this->col = $col;
+ $x = 10+$col*65;
+ $this->SetLeftMargin($x);
+ $this->SetX($x);
+}
+
+function AcceptPageBreak()
+{
+ // Method accepting or not automatic page break
+ if($this->col<2)
+ {
+ // Go to next column
+ $this->SetCol($this->col+1);
+ // Set ordinate to top
+ $this->SetY($this->y0);
+ // Keep on page
+ return false;
+ }
+ else
+ {
+ // Go back to first column
+ $this->SetCol(0);
+ // Page break
+ return true;
+ }
+}
+
+function ChapterTitle($num, $label)
+{
+ // Title
+ $this->SetFont('Arial','',12);
+ $this->SetFillColor(200,220,255);
+ $this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
+ $this->Ln(4);
+ // Save ordinate
+ $this->y0 = $this->GetY();
+}
+
+function ChapterBody($file)
+{
+ // Read text file
+ $txt = file_get_contents($file);
+ // Font
+ $this->SetFont('Times','',12);
+ // Output text in a 6 cm width column
+ $this->MultiCell(60,5,$txt);
+ $this->Ln();
+ // Mention
+ $this->SetFont('','I');
+ $this->Cell(0,5,'(end of excerpt)');
+ // Go back to first column
+ $this->SetCol(0);
+}
+
+function PrintChapter($num, $title, $file)
+{
+ // Add chapter
+ $this->AddPage();
+ $this->ChapterTitle($num,$title);
+ $this->ChapterBody($file);
+}
+}
+
+$pdf = new PDF();
+$title = '20000 Leagues Under the Seas';
+$pdf->SetTitle($title);
+$pdf->SetAuthor('Jules Verne');
+$pdf->PrintChapter(1,'A RUNAWAY REEF','20k_c1.txt');
+$pdf->PrintChapter(2,'THE PROS AND CONS','20k_c2.txt');
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto5.htm b/vendor/fpdf/tutorial/tuto5.htm
new file mode 100644
index 0000000..f90102b
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto5.htm
@@ -0,0 +1,134 @@
+
+
+
+
+Tables
+
+
+
+
Tables
+This tutorial shows different ways to make tables.
+
+A table being just a collection of cells, it's natural to build one from them. The first
+example is achieved in the most basic way possible: simple framed cells, all of the same size
+and left aligned. The result is rudimentary but very quick to obtain.
+
+
+The second table brings some improvements: each column has its own width, headings are centered,
+and numbers right aligned. Moreover, horizontal lines have been removed. This is done by means
+of the border parameter of the Cell() method, which specifies which sides of the
+cell must be drawn. Here we want the left (L) and right (R) ones. It remains
+the problem of the horizontal line to finish the table. There are two possibilities: either
+check for the last line in the loop, in which case we use LRB for the border
+parameter; or, as done here, add the line once the loop is over.
+
+
+The third table is similar to the second one but uses colors. Fill, text and line colors are
+simply specified. Alternate coloring for rows is obtained by using alternatively transparent
+and filled cells.
+
+
diff --git a/vendor/fpdf/tutorial/tuto5.php b/vendor/fpdf/tutorial/tuto5.php
new file mode 100644
index 0000000..252b70f
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto5.php
@@ -0,0 +1,102 @@
+Cell(40,7,$col,1);
+ $this->Ln();
+ // Data
+ foreach($data as $row)
+ {
+ foreach($row as $col)
+ $this->Cell(40,6,$col,1);
+ $this->Ln();
+ }
+}
+
+// Better table
+function ImprovedTable($header, $data)
+{
+ // Column widths
+ $w = array(40, 35, 40, 45);
+ // Header
+ for($i=0;$iCell($w[$i],7,$header[$i],1,0,'C');
+ $this->Ln();
+ // Data
+ foreach($data as $row)
+ {
+ $this->Cell($w[0],6,$row[0],'LR');
+ $this->Cell($w[1],6,$row[1],'LR');
+ $this->Cell($w[2],6,number_format($row[2]),'LR',0,'R');
+ $this->Cell($w[3],6,number_format($row[3]),'LR',0,'R');
+ $this->Ln();
+ }
+ // Closing line
+ $this->Cell(array_sum($w),0,'','T');
+}
+
+// Colored table
+function FancyTable($header, $data)
+{
+ // Colors, line width and bold font
+ $this->SetFillColor(255,0,0);
+ $this->SetTextColor(255);
+ $this->SetDrawColor(128,0,0);
+ $this->SetLineWidth(.3);
+ $this->SetFont('','B');
+ // Header
+ $w = array(40, 35, 40, 45);
+ for($i=0;$iCell($w[$i],7,$header[$i],1,0,'C',true);
+ $this->Ln();
+ // Color and font restoration
+ $this->SetFillColor(224,235,255);
+ $this->SetTextColor(0);
+ $this->SetFont('');
+ // Data
+ $fill = false;
+ foreach($data as $row)
+ {
+ $this->Cell($w[0],6,$row[0],'LR',0,'L',$fill);
+ $this->Cell($w[1],6,$row[1],'LR',0,'L',$fill);
+ $this->Cell($w[2],6,number_format($row[2]),'LR',0,'R',$fill);
+ $this->Cell($w[3],6,number_format($row[3]),'LR',0,'R',$fill);
+ $this->Ln();
+ $fill = !$fill;
+ }
+ // Closing line
+ $this->Cell(array_sum($w),0,'','T');
+}
+}
+
+$pdf = new PDF();
+// Column headings
+$header = array('Country', 'Capital', 'Area (sq km)', 'Pop. (thousands)');
+// Data loading
+$data = $pdf->LoadData('countries.txt');
+$pdf->SetFont('Arial','',14);
+$pdf->AddPage();
+$pdf->BasicTable($header,$data);
+$pdf->AddPage();
+$pdf->ImprovedTable($header,$data);
+$pdf->AddPage();
+$pdf->FancyTable($header,$data);
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto6.htm b/vendor/fpdf/tutorial/tuto6.htm
new file mode 100644
index 0000000..59ef177
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto6.htm
@@ -0,0 +1,165 @@
+
+
+
+
+Links and flowing text
+
+
+
+
Links and flowing text
+This tutorial explains how to insert links (internal and external) and shows a new text writing
+mode. It also contains a basic HTML parser.
+
+
<?php
+require('fpdf.php');
+
+class PDF extends FPDF
+{
+var $B;
+var $I;
+var $U;
+var $HREF;
+
+function PDF($orientation='P', $unit='mm', $size='A4')
+{
+ // Call parent constructor
+ $this->FPDF($orientation,$unit,$size);
+ // Initialization
+ $this->B = 0;
+ $this->I = 0;
+ $this->U = 0;
+ $this->HREF = '';
+}
+
+function WriteHTML($html)
+{
+ // HTML parser
+ $html = str_replace("\n",' ',$html);
+ $a = preg_split('/<(.*)>/U',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
+ foreach($a as $i=>$e)
+ {
+ if($i%2==0)
+ {
+ // Text
+ if($this->HREF)
+ $this->PutLink($this->HREF,$e);
+ else
+ $this->Write(5,$e);
+ }
+ else
+ {
+ // Tag
+ if($e[0]=='/')
+ $this->CloseTag(strtoupper(substr($e,1)));
+ else
+ {
+ // Extract attributes
+ $a2 = explode(' ',$e);
+ $tag = strtoupper(array_shift($a2));
+ $attr = array();
+ foreach($a2 as $v)
+ {
+ if(preg_match('/([^=]*)=["\']?([^"\']*)/',$v,$a3))
+ $attr[strtoupper($a3[1])] = $a3[2];
+ }
+ $this->OpenTag($tag,$attr);
+ }
+ }
+ }
+}
+
+function OpenTag($tag, $attr)
+{
+ // Opening tag
+ if($tag=='B' || $tag=='I' || $tag=='U')
+ $this->SetStyle($tag,true);
+ if($tag=='A')
+ $this->HREF = $attr['HREF'];
+ if($tag=='BR')
+ $this->Ln(5);
+}
+
+function CloseTag($tag)
+{
+ // Closing tag
+ if($tag=='B' || $tag=='I' || $tag=='U')
+ $this->SetStyle($tag,false);
+ if($tag=='A')
+ $this->HREF = '';
+}
+
+function SetStyle($tag, $enable)
+{
+ // Modify style and select corresponding font
+ $this->$tag += ($enable ? 1 : -1);
+ $style = '';
+ foreach(array('B', 'I', 'U') as $s)
+ {
+ if($this->$s>0)
+ $style .= $s;
+ }
+ $this->SetFont('',$style);
+}
+
+function PutLink($URL, $txt)
+{
+ // Put a hyperlink
+ $this->SetTextColor(0,0,255);
+ $this->SetStyle('U',true);
+ $this->Write(5,$txt,$URL);
+ $this->SetStyle('U',false);
+ $this->SetTextColor(0);
+}
+}
+
+$html = 'You can now easily print text mixing different styles: <b>bold</b>, <i>italic</i>,
+<u>underlined</u>, or <b><i><u>all at once</u></i></b>!<br><br>You can also insert links on
+text, such as <a href="http://www.fpdf.org">www.fpdf.org</a>, or on an image: click on the logo.';
+
+$pdf = new PDF();
+// First page
+$pdf->AddPage();
+$pdf->SetFont('Arial','',20);
+$pdf->Write(5,"To find out what's new in this tutorial, click ");
+$pdf->SetFont('','U');
+$link = $pdf->AddLink();
+$pdf->Write(5,'here',$link);
+$pdf->SetFont('');
+// Second page
+$pdf->AddPage();
+$pdf->SetLink($link);
+$pdf->Image('logo.png',10,12,30,0,'','http://www.fpdf.org');
+$pdf->SetLeftMargin(45);
+$pdf->SetFontSize(14);
+$pdf->WriteHTML($html);
+$pdf->Output();
+?>
+The new method to print text is Write(). It's very close to MultiCell(); the differences are:
+
+
The end of line is at the right margin and the next line begins at the left one
+
The current position moves at the end of the text
+
+So it allows to write a chunk of text, alter the font style, then continue from the exact
+place we left it. On the other hand, you cannot justify it.
+
+
+The method is used on the first page to put a link pointing to the second one. The beginning of
+the sentence is written in regular style, then we switch to underline and finish it. The link
+is created with AddLink(), which returns a link identifier. The identifier is
+passed as third parameter of Write(). Once the second page is created, we use SetLink() to
+make the link point to the beginning of the current page.
+
+
+Then we put an image with an external link on it. An external link is just a URL. It's passed as
+last parameter of Image().
+
+
+Finally, the left margin is moved after the image with SetLeftMargin() and some text in
+HTML format is output. A very simple HTML parser is used for this, based on regular expressions.
+Recognized tags are <b>, <i>, <u>, <a> and <br>; the others are
+ignored. The parser also makes use of the Write() method. An external link is put the same way as
+an internal one (third parameter of Write()). Note that Cell() also allows to put links.
+
+
diff --git a/vendor/fpdf/tutorial/tuto6.php b/vendor/fpdf/tutorial/tuto6.php
new file mode 100644
index 0000000..d933556
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto6.php
@@ -0,0 +1,124 @@
+FPDF($orientation,$unit,$size);
+ // Initialization
+ $this->B = 0;
+ $this->I = 0;
+ $this->U = 0;
+ $this->HREF = '';
+}
+
+function WriteHTML($html)
+{
+ // HTML parser
+ $html = str_replace("\n",' ',$html);
+ $a = preg_split('/<(.*)>/U',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
+ foreach($a as $i=>$e)
+ {
+ if($i%2==0)
+ {
+ // Text
+ if($this->HREF)
+ $this->PutLink($this->HREF,$e);
+ else
+ $this->Write(5,$e);
+ }
+ else
+ {
+ // Tag
+ if($e[0]=='/')
+ $this->CloseTag(strtoupper(substr($e,1)));
+ else
+ {
+ // Extract attributes
+ $a2 = explode(' ',$e);
+ $tag = strtoupper(array_shift($a2));
+ $attr = array();
+ foreach($a2 as $v)
+ {
+ if(preg_match('/([^=]*)=["\']?([^"\']*)/',$v,$a3))
+ $attr[strtoupper($a3[1])] = $a3[2];
+ }
+ $this->OpenTag($tag,$attr);
+ }
+ }
+ }
+}
+
+function OpenTag($tag, $attr)
+{
+ // Opening tag
+ if($tag=='B' || $tag=='I' || $tag=='U')
+ $this->SetStyle($tag,true);
+ if($tag=='A')
+ $this->HREF = $attr['HREF'];
+ if($tag=='BR')
+ $this->Ln(5);
+}
+
+function CloseTag($tag)
+{
+ // Closing tag
+ if($tag=='B' || $tag=='I' || $tag=='U')
+ $this->SetStyle($tag,false);
+ if($tag=='A')
+ $this->HREF = '';
+}
+
+function SetStyle($tag, $enable)
+{
+ // Modify style and select corresponding font
+ $this->$tag += ($enable ? 1 : -1);
+ $style = '';
+ foreach(array('B', 'I', 'U') as $s)
+ {
+ if($this->$s>0)
+ $style .= $s;
+ }
+ $this->SetFont('',$style);
+}
+
+function PutLink($URL, $txt)
+{
+ // Put a hyperlink
+ $this->SetTextColor(0,0,255);
+ $this->SetStyle('U',true);
+ $this->Write(5,$txt,$URL);
+ $this->SetStyle('U',false);
+ $this->SetTextColor(0);
+}
+}
+
+$html = 'You can now easily print text mixing different styles: bold, italic,
+underlined, or all at once!
You can also insert links on
+text, such as www.fpdf.org, or on an image: click on the logo.';
+
+$pdf = new PDF();
+// First page
+$pdf->AddPage();
+$pdf->SetFont('Arial','',20);
+$pdf->Write(5,"To find out what's new in this tutorial, click ");
+$pdf->SetFont('','U');
+$link = $pdf->AddLink();
+$pdf->Write(5,'here',$link);
+$pdf->SetFont('');
+// Second page
+$pdf->AddPage();
+$pdf->SetLink($link);
+$pdf->Image('logo.png',10,12,30,0,'','http://www.fpdf.org');
+$pdf->SetLeftMargin(45);
+$pdf->SetFontSize(14);
+$pdf->WriteHTML($html);
+$pdf->Output();
+?>
diff --git a/vendor/fpdf/tutorial/tuto7.htm b/vendor/fpdf/tutorial/tuto7.htm
new file mode 100644
index 0000000..2863018
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto7.htm
@@ -0,0 +1,241 @@
+
+
+
+
+Adding new fonts and encoding support
+
+
+
+
+
Adding new fonts and encoding support
+This tutorial explains how to use TrueType, OpenType and Type1 fonts so that you are not limited to
+the standard fonts any more. The other benefit is that you can choose the font encoding, which allows
+you to use other languages than the Western ones (the standard fonts having too few available characters).
+
+
+Remark: for OpenType, only the format based on TrueType is supported (not the one based on Type1).
+
+
+There are two ways to use a new font: embedding it in the PDF or not. When a font is not
+embedded, it is searched in the system. The advantage is that the PDF file is lighter; on the other
+hand, if it's not available, a substitution font is used. So it's preferable to ensure that the
+needed font is installed on the client systems. If the file is to be viewed by a large audience,
+it's highly recommended to embed.
+
+
+Adding a new font requires two steps:
+
+
Generation of the font definition file
+
Declaration of the font in the script
+
+For Type1, you need the corresponding AFM file. It's usually provided with the font.
+
+
Generation of the font definition file
+The first step consists in generating a PHP file containing all the information needed by FPDF;
+in addition, the font file is compressed. To do this, a helper script is provided in the makefont
+directory of the package: makefont.php. It contains the following function:
+
+
+MakeFont(string fontfile, [, string enc [, boolean embed]])
+
+
fontfile
+
+
Path to the .ttf, .otf or .pfb file.
+
+
enc
+
+
Name of the encoding to use. Default value: cp1252.
+
+
embed
+
+
Whether to embed the font or not. Default value: true.
+
+
+The first parameter is the name of the font file. The extension must be either .ttf, .otf or .pfb and
+determines the font type. If your Type1 font is in ASCII format (.pfa), you can convert it to binary
+(.pfb) with the help of t1utils.
+
+
+For Type1 fonts, the corresponding .afm file must be present in the same directory.
+
+
+The encoding defines the association between a code (from 0 to 255) and a character. The first 128 are
+always the same and correspond to ASCII; the following are variable. Encodings are stored in .map
+files. The available ones are:
+
+
cp1250 (Central Europe)
+
cp1251 (Cyrillic)
+
cp1252 (Western Europe)
+
cp1253 (Greek)
+
cp1254 (Turkish)
+
cp1255 (Hebrew)
+
cp1257 (Baltic)
+
cp1258 (Vietnamese)
+
cp874 (Thai)
+
ISO-8859-1 (Western Europe)
+
ISO-8859-2 (Central Europe)
+
ISO-8859-4 (Baltic)
+
ISO-8859-5 (Cyrillic)
+
ISO-8859-7 (Greek)
+
ISO-8859-9 (Turkish)
+
ISO-8859-11 (Thai)
+
ISO-8859-15 (Western Europe)
+
ISO-8859-16 (Central Europe)
+
KOI8-R (Russian)
+
KOI8-U (Ukrainian)
+
+Of course, the font must contain the characters corresponding to the chosen encoding.
+
+
+Remark: the standard fonts use cp1252.
+
+
+After you have called the function (create a new file for this and include makefont.php), a .php file
+is created, with the same name as the font file. You may rename it if you wish. If the case of embedding,
+the font file is compressed and gives a second file with .z as extension (except if the compression
+function is not available, it requires Zlib). You may rename it too, but in this case you have to change
+the variable $file in the .php file accordingly.
+
+
+Example:
+
+which gives the files comic.php and comic.z.
+
+
+Then copy the generated files to the font directory. If the font file could not be compressed, copy
+it directly instead of the .z version.
+
+
+Another way to call MakeFont() is through the command line:
+
+
+php makefont\makefont.php c:\Windows\Fonts\comic.ttf cp1252
+
+
+Finally, for TrueType and OpenType fonts, you can also generate the files
+online instead of doing it manually.
+
+
Declaration of the font in the script
+The second step is simple. You just need to call the AddFont() method:
+
+
$pdf->AddFont('Comic','','comic.php');
+
+
+And the font is now available (in regular and underlined styles), usable like the others. If we
+had worked with Comic Sans MS Bold (comicbd.ttf), we would have written:
+
+
$pdf->AddFont('Comic','B','comicbd.php');
+
+
+
+
Example
+Let's now see a complete example. We will use the font Calligrapher.
+The first step is the generation of the font files:
+
+The script gives the following report:
+
+
+Warning: character Euro is missing
+Warning: character zcaron is missing
+Font file compressed: calligra.z
+Font definition file generated: calligra.php
+
+The euro character is not present in the font (it's too old). Another character is missing too.
+
+
+Alternatively we could have used the command line:
+
+
+php makefont\makefont.php calligra.ttf cp1252
+
+
+or used the online generator.
+
+
+We can now copy the two generated files to the font directory and write the script:
+
+
<?php
+require('fpdf.php');
+
+$pdf = new FPDF();
+$pdf->AddFont('Calligrapher','','calligra.php');
+$pdf->AddPage();
+$pdf->SetFont('Calligrapher','',35);
+$pdf->Write(10,'Enjoy new fonts with FPDF!');
+$pdf->Output();
+?>
+The euro character is not present in all encodings, and is not always placed at the same position:
+
+
Encoding
Position
+
cp1250
128
+
cp1251
136
+
cp1252
128
+
cp1253
128
+
cp1254
128
+
cp1255
128
+
cp1257
128
+
cp1258
128
+
cp874
128
+
ISO-8859-1
N/A
+
ISO-8859-2
N/A
+
ISO-8859-4
N/A
+
ISO-8859-5
N/A
+
ISO-8859-7
N/A
+
ISO-8859-9
N/A
+
ISO-8859-11
N/A
+
ISO-8859-15
164
+
ISO-8859-16
164
+
KOI8-R
N/A
+
KOI8-U
N/A
+
+ISO-8859-1 is widespread but does not include the euro sign. If you need it, the simplest thing
+to do is to use cp1252 or ISO-8859-15 instead, which are nearly identical but contain the precious
+symbol.
+
+
Reducing the size of TrueType fonts
+Font files are often quite voluminous; this is due to the fact that they contain the characters
+corresponding to many encodings. Zlib compression reduces them but they remain fairly big. A
+technique exists to reduce them further. It consists in converting the font to the Type1 format
+with ttf2pt1 (the Windows binary is
+available here) while specifying the encoding
+you are interested in; all other characters will be discarded.
+
+For example, the arial.ttf font that ships with Windows Vista weights 748 KB (it contains 3381 characters).
+After compression it drops to 411. Let's convert it to Type1 by keeping only cp1250 characters:
+
+
+ttf2pt1 -b -L cp1250.map c:\Windows\Fonts\arial.ttf arial
+
+
+The .map files are located in the makefont directory of the package. The command produces
+arial.pfb and arial.afm. The arial.pfb file weights only 57 KB, and 53 after compression.
+
+
+It's possible to go even further. If you are interested only by a subset of the encoding (you
+probably don't need all 217 characters), you can open the .map file and remove the lines you are
+not interested in. This will reduce the file size accordingly.
+
+
diff --git a/vendor/fpdf/tutorial/tuto7.php b/vendor/fpdf/tutorial/tuto7.php
new file mode 100644
index 0000000..a7acb47
--- /dev/null
+++ b/vendor/fpdf/tutorial/tuto7.php
@@ -0,0 +1,11 @@
+AddFont('Calligrapher','','calligra.php');
+$pdf->AddPage();
+$pdf->SetFont('Calligrapher','',35);
+$pdf->Cell(0,10,'Enjoy new fonts with FPDF!');
+$pdf->Output();
+?>
diff --git a/vendor/fpdi/filters/FilterASCII85.php b/vendor/fpdi/filters/FilterASCII85.php
new file mode 100644
index 0000000..59bc845
--- /dev/null
+++ b/vendor/fpdi/filters/FilterASCII85.php
@@ -0,0 +1,114 @@
+ ord('~'),
+ 'z' => ord('z'),
+ 'u' => ord('u'),
+ 'z' => ord('z'),
+ '!' => ord('!')
+ );
+
+ $out = '';
+ $state = 0;
+ $chn = null;
+
+ $l = strlen($in);
+
+ for ($k = 0; $k < $l; ++$k) {
+ $ch = ord($in[$k]) & 0xff;
+
+ if ($ch == $ord['~']) {
+ break;
+ }
+ if (preg_match('/^\s$/',chr($ch))) {
+ continue;
+ }
+ if ($ch == $ord['z'] && $state == 0) {
+ $out .= chr(0) . chr(0) . chr(0) . chr(0);
+ continue;
+ }
+ if ($ch < $ord['!'] || $ch > $ord['u']) {
+ throw new Exception('Illegal character in ASCII85Decode.');
+ }
+
+ $chn[$state++] = $ch - $ord['!'];
+
+ if ($state == 5) {
+ $state = 0;
+ $r = 0;
+ for ($j = 0; $j < 5; ++$j)
+ $r = $r * 85 + $chn[$j];
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ $out .= chr($r);
+ }
+ }
+ $r = 0;
+
+ if ($state == 1) {
+ throw new Exception('Illegal length in ASCII85Decode.');
+ }
+
+ if ($state == 2) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85;
+ $out .= chr($r >> 24);
+
+ } else if ($state == 3) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+
+ } else if ($state == 4) {
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ;
+ $out .= chr($r >> 24);
+ $out .= chr($r >> 16);
+ $out .= chr($r >> 8);
+ }
+
+ return $out;
+ }
+
+ /**
+ * NOT IMPLEMENTED
+ *
+ * @param string $in
+ * @return string
+ * @throws LogicException
+ */
+ public function encode($in)
+ {
+ throw new LogicException("ASCII85 encoding not implemented.");
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/filters/FilterASCIIHexDecode.php b/vendor/fpdi/filters/FilterASCIIHexDecode.php
new file mode 100644
index 0000000..4040302
--- /dev/null
+++ b/vendor/fpdi/filters/FilterASCIIHexDecode.php
@@ -0,0 +1,52 @@
+'));
+ if ((strlen($data) % 2) == 1) {
+ $data .= '0';
+ }
+
+ return pack('H*', $data);
+ }
+
+ /**
+ * Converts a string into ASCII hexadecimal representation.
+ *
+ * @param string $data The input string
+ * @param boolean $leaveEOD
+ * @return string
+ */
+ public function encode($data, $leaveEOD = false)
+ {
+ return current(unpack('H*', $data)) . ($leaveEOD ? '' : '>');
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/filters/FilterLZW.php b/vendor/fpdi/filters/FilterLZW.php
new file mode 100644
index 0000000..b4dfbe8
--- /dev/null
+++ b/vendor/fpdi/filters/FilterLZW.php
@@ -0,0 +1,173 @@
+_initsTable();
+
+ $this->_data = $data;
+ $this->_dataLength = strlen($data);
+
+ // Initialize pointers
+ $this->_bytePointer = 0;
+ $this->_bitPointer = 0;
+
+ $this->_nextData = 0;
+ $this->_nextBits = 0;
+
+ $oldCode = 0;
+
+ $unCompData = '';
+
+ while (($code = $this->_getNextCode()) != 257) {
+ if ($code == 256) {
+ $this->_initsTable();
+ $code = $this->_getNextCode();
+
+ if ($code == 257) {
+ break;
+ }
+
+ if (!isset($this->_sTable[$code])) {
+ throw new Exception('Error while decompression LZW compressed data.');
+ }
+
+ $unCompData .= $this->_sTable[$code];
+ $oldCode = $code;
+
+ } else {
+
+ if ($code < $this->_tIdx) {
+ $string = $this->_sTable[$code];
+ $unCompData .= $string;
+
+ $this->_addStringToTable($this->_sTable[$oldCode], $string[0]);
+ $oldCode = $code;
+ } else {
+ $string = $this->_sTable[$oldCode];
+ $string = $string . $string[0];
+ $unCompData .= $string;
+
+ $this->_addStringToTable($string);
+ $oldCode = $code;
+ }
+ }
+ }
+
+ return $unCompData;
+ }
+
+
+ /**
+ * Initialize the string table.
+ */
+ protected function _initsTable()
+ {
+ $this->_sTable = array();
+
+ for ($i = 0; $i < 256; $i++)
+ $this->_sTable[$i] = chr($i);
+
+ $this->_tIdx = 258;
+ $this->_bitsToGet = 9;
+ }
+
+ /**
+ * Add a new string to the string table.
+ */
+ protected function _addStringToTable($oldString, $newString = '')
+ {
+ $string = $oldString . $newString;
+
+ // Add this new String to the table
+ $this->_sTable[$this->_tIdx++] = $string;
+
+ if ($this->_tIdx == 511) {
+ $this->_bitsToGet = 10;
+ } else if ($this->_tIdx == 1023) {
+ $this->_bitsToGet = 11;
+ } else if ($this->_tIdx == 2047) {
+ $this->_bitsToGet = 12;
+ }
+ }
+
+ /**
+ * Returns the next 9, 10, 11 or 12 bits
+ *
+ * @return int
+ */
+ protected function _getNextCode()
+ {
+ if ($this->_bytePointer == $this->_dataLength) {
+ return 257;
+ }
+
+ $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
+ $this->_nextBits += 8;
+
+ if ($this->_nextBits < $this->_bitsToGet) {
+ $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff);
+ $this->_nextBits += 8;
+ }
+
+ $code = ($this->_nextData >> ($this->_nextBits - $this->_bitsToGet)) & $this->_andTable[$this->_bitsToGet-9];
+ $this->_nextBits -= $this->_bitsToGet;
+
+ return $code;
+ }
+
+ /**
+ * NOT IMPLEMENTED
+ *
+ * @param string $in
+ * @return string
+ * @throws LogicException
+ */
+ public function encode($in)
+ {
+ throw new LogicException("LZW encoding not implemented.");
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/fpdf_tpl.php b/vendor/fpdi/fpdf_tpl.php
new file mode 100644
index 0000000..5da77af
--- /dev/null
+++ b/vendor/fpdi/fpdf_tpl.php
@@ -0,0 +1,555 @@
+page <= 0) {
+ throw new LogicException("You have to add at least a page first!");
+ }
+
+ if ($x == null)
+ $x = 0;
+ if ($y == null)
+ $y = 0;
+ if ($w == null)
+ $w = $this->w;
+ if ($h == null)
+ $h = $this->h;
+
+ // Save settings
+ $this->tpl++;
+ $tpl =& $this->_tpls[$this->tpl];
+ $tpl = array(
+ 'o_x' => $this->x,
+ 'o_y' => $this->y,
+ 'o_AutoPageBreak' => $this->AutoPageBreak,
+ 'o_bMargin' => $this->bMargin,
+ 'o_tMargin' => $this->tMargin,
+ 'o_lMargin' => $this->lMargin,
+ 'o_rMargin' => $this->rMargin,
+ 'o_h' => $this->h,
+ 'o_w' => $this->w,
+ 'o_FontFamily' => $this->FontFamily,
+ 'o_FontStyle' => $this->FontStyle,
+ 'o_FontSizePt' => $this->FontSizePt,
+ 'o_FontSize' => $this->FontSize,
+ 'buffer' => '',
+ 'x' => $x,
+ 'y' => $y,
+ 'w' => $w,
+ 'h' => $h
+ );
+
+ $this->SetAutoPageBreak(false);
+
+ // Define own high and width to calculate correct positions
+ $this->h = $h;
+ $this->w = $w;
+
+ $this->_inTpl = true;
+ $this->SetXY($x + $this->lMargin, $y + $this->tMargin);
+ $this->SetRightMargin($this->w - $w + $this->rMargin);
+
+ if ($this->CurrentFont) {
+ $fontKey = $this->FontFamily . $this->FontStyle;
+ if ($fontKey) {
+ $this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey];
+ $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
+ }
+ }
+
+ return $this->tpl;
+ }
+
+ /**
+ * End template.
+ *
+ * This method ends a template and reset initiated variables collected in {@link beginTemplate()}.
+ *
+ * @return int|boolean If a template is opened, the id is returned. If not a false is returned.
+ */
+ public function endTemplate()
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args);
+ }
+
+ if ($this->_inTpl) {
+ $this->_inTpl = false;
+ $tpl = $this->_tpls[$this->tpl];
+ $this->SetXY($tpl['o_x'], $tpl['o_y']);
+ $this->tMargin = $tpl['o_tMargin'];
+ $this->lMargin = $tpl['o_lMargin'];
+ $this->rMargin = $tpl['o_rMargin'];
+ $this->h = $tpl['o_h'];
+ $this->w = $tpl['o_w'];
+ $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']);
+
+ $this->FontFamily = $tpl['o_FontFamily'];
+ $this->FontStyle = $tpl['o_FontStyle'];
+ $this->FontSizePt = $tpl['o_FontSizePt'];
+ $this->FontSize = $tpl['o_FontSize'];
+
+ $fontKey = $this->FontFamily . $this->FontStyle;
+ if ($fontKey)
+ $this->CurrentFont =& $this->fonts[$fontKey];
+
+ return $this->tpl;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Use a template in current page or other template.
+ *
+ * You can use a template in a page or in another template.
+ * You can give the used template a new size.
+ * All parameters are optional. The width or height is calculated automatically
+ * if one is given. If no parameter is given the origin size as defined in
+ * {@link beginTemplate()} method is used.
+ *
+ * The calculated or used width and height are returned as an array.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $x The x-position
+ * @param int $y The y-position
+ * @param int $w The new width of the template
+ * @param int $h The new height of the template
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ * @throws LogicException|InvalidArgumentException
+ */
+ public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0)
+ {
+ if ($this->page <= 0) {
+ throw new LogicException('You have to add at least a page first!');
+ }
+
+ if (!isset($this->_tpls[$tplIdx])) {
+ throw new InvalidArgumentException('Template does not exist!');
+ }
+
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx];
+ }
+
+ $tpl = $this->_tpls[$tplIdx];
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+
+ if ($x == null) {
+ $x = 0;
+ }
+
+ if ($y == null) {
+ $y = 0;
+ }
+
+ $x += $tpl['x'];
+ $y += $tpl['y'];
+
+ $wh = $this->getTemplateSize($tplIdx, $w, $h);
+ $w = $wh['w'];
+ $h = $wh['h'];
+
+ $tplData = array(
+ 'x' => $this->x,
+ 'y' => $this->y,
+ 'w' => $w,
+ 'h' => $h,
+ 'scaleX' => ($w / $_w),
+ 'scaleY' => ($h / $_h),
+ 'tx' => $x,
+ 'ty' => ($this->h - $y - $h),
+ 'lty' => ($this->h - $y - $h) - ($this->h - $_h) * ($h / $_h)
+ );
+
+ $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm',
+ $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k)
+ ); // Translate
+ $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx));
+
+ $this->lastUsedTemplateData = $tplData;
+
+ return array('w' => $w, 'h' => $h);
+ }
+
+ /**
+ * Get the calculated size of a template.
+ *
+ * If one size is given, this method calculates the other one.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $w The width of the template
+ * @param int $h The height of the template
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ */
+ public function getTemplateSize($tplIdx, $w = 0, $h = 0)
+ {
+ if (!isset($this->_tpls[$tplIdx]))
+ return false;
+
+ $tpl = $this->_tpls[$tplIdx];
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+
+ if ($w == 0 && $h == 0) {
+ $w = $_w;
+ $h = $_h;
+ }
+
+ if ($w == 0)
+ $w = $h * $_w / $_h;
+ if($h == 0)
+ $h = $w * $_h / $_w;
+
+ return array("w" => $w, "h" => $h);
+ }
+
+ /**
+ * Sets the font used to print character strings.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * @see http://fpdf.org/en/doc/setfont.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045
+ */
+ public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::SetFont'), $args);
+ }
+
+ parent::SetFont($family, $style, $size);
+
+ $fontkey = $this->FontFamily . $this->FontStyle;
+
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey];
+ } else {
+ $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey];
+ }
+ }
+
+ /**
+ * Puts an image.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * @see http://fpdf.org/en/doc/image.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352
+ */
+ public function Image(
+ $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false,
+ $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false,
+ $hidden = false, $fitonpage = false, $alt = false, $altimgs = array()
+ )
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::Image'), $args);
+ }
+
+ $ret = parent::Image($file, $x, $y, $w, $h, $type, $link);
+ if ($this->_inTpl) {
+ $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file];
+ } else {
+ $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Adds a new page to the document.
+ *
+ * See FPDF/TCPDF documentation.
+ *
+ * This method cannot be used if you'd started a template.
+ *
+ * @see http://fpdf.org/en/doc/addpage.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced
+ */
+ public function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::AddPage'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Adding pages in templates is not possible!');
+ }
+
+ parent::AddPage($orientation, $format);
+ }
+
+ /**
+ * Puts a link on a rectangular area of the page.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/link.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994
+ */
+ public function Link($x, $y, $w, $h, $link, $spaces = 0)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::Link'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Using links in templates is not posible!');
+ }
+
+ parent::Link($x, $y, $w, $h, $link);
+ }
+
+ /**
+ * Creates a new internal link and returns its identifier.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/addlink.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e
+ */
+ public function AddLink()
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::AddLink'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Adding links in templates is not possible!');
+ }
+
+ return parent::AddLink();
+ }
+
+ /**
+ * Defines the page and position a link points to.
+ *
+ * Overwritten because adding links in a template will not work.
+ *
+ * @see http://fpdf.org/en/doc/setlink.htm
+ * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae
+ */
+ public function SetLink($link, $y = 0, $page = -1)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'TCPDF::SetLink'), $args);
+ }
+
+ if ($this->_inTpl) {
+ throw new LogicException('Setting links in templates is not possible!');
+ }
+
+ parent::SetLink($link, $y, $page);
+ }
+
+ /**
+ * Writes the form XObjects to the PDF document.
+ */
+ protected function _putformxobjects()
+ {
+ $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
+ reset($this->_tpls);
+
+ foreach($this->_tpls AS $tplIdx => $tpl) {
+ $this->_newobj();
+ $this->_tpls[$tplIdx]['n'] = $this->n;
+ $this->_out('<<'.$filter.'/Type /XObject');
+ $this->_out('/Subtype /Form');
+ $this->_out('/FormType 1');
+ $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
+ // llx
+ $tpl['x'] * $this->k,
+ // lly
+ -$tpl['y'] * $this->k,
+ // urx
+ ($tpl['w'] + $tpl['x']) * $this->k,
+ // ury
+ ($tpl['h'] - $tpl['y']) * $this->k
+ ));
+
+ if ($tpl['x'] != 0 || $tpl['y'] != 0) {
+ $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]',
+ -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2
+ ));
+ }
+
+ $this->_out('/Resources ');
+ $this->_out('<_res['tpl'][$tplIdx])) {
+ $res = $this->_res['tpl'][$tplIdx];
+ if (isset($res['fonts']) && count($res['fonts'])) {
+ $this->_out('/Font <<');
+
+ foreach($res['fonts'] as $font) {
+ $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
+ }
+
+ $this->_out('>>');
+ }
+
+ if(isset($res['images']) || isset($res['tpls'])) {
+ $this->_out('/XObject <<');
+
+ if (isset($res['images'])) {
+ foreach($res['images'] as $image)
+ $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
+ }
+
+ if (isset($res['tpls'])) {
+ foreach($res['tpls'] as $i => $_tpl)
+ $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
+ }
+
+ $this->_out('>>');
+ }
+ }
+
+ $this->_out('>>');
+
+ $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_putstream($buffer);
+ $this->_out('endobj');
+ }
+ }
+
+ /**
+ * Output images.
+ *
+ * Overwritten to add {@link _putformxobjects()} after _putimages().
+ */
+ public function _putimages()
+ {
+ parent::_putimages();
+ $this->_putformxobjects();
+ }
+
+ /**
+ * Writes the references of XObject resources to the document.
+ *
+ * Overwritten to add the the templates to the XObject resource dictionary.
+ */
+ public function _putxobjectdict()
+ {
+ parent::_putxobjectdict();
+
+ foreach($this->_tpls as $tplIdx => $tpl) {
+ $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']));
+ }
+ }
+
+ /**
+ * Writes bytes to the resulting document.
+ *
+ * Overwritten to delegate the data to the template buffer.
+ *
+ * @param string $s
+ */
+ public function _out($s)
+ {
+ if ($this->state == 2 && $this->_inTpl) {
+ $this->_tpls[$this->tpl]['buffer'] .= $s . "\n";
+ } else {
+ parent::_out($s);
+ }
+ }
+}
diff --git a/vendor/fpdi/fpdi.php b/vendor/fpdi/fpdi.php
new file mode 100644
index 0000000..957c505
--- /dev/null
+++ b/vendor/fpdi/fpdi.php
@@ -0,0 +1,695 @@
+currentFilename = $filename;
+
+ if (!isset($this->parsers[$filename])) {
+ $this->parsers[$filename] = $this->_getPdfParser($filename);
+ $this->setPdfVersion(
+ max($this->getPdfVersion(), $this->parsers[$filename]->getPdfVersion())
+ );
+ }
+
+ $this->currentParser =& $this->parsers[$filename];
+
+ return $this->parsers[$filename]->getPageCount();
+ }
+
+ /**
+ * Returns a PDF parser object
+ *
+ * @param string $filename
+ * @return fpdi_pdf_parser
+ */
+ protected function _getPdfParser($filename)
+ {
+ require_once('fpdi_pdf_parser.php');
+ return new fpdi_pdf_parser($filename);
+ }
+
+ /**
+ * Get the current PDF version.
+ *
+ * @return string
+ */
+ public function getPdfVersion()
+ {
+ return $this->PDFVersion;
+ }
+
+ /**
+ * Set the PDF version.
+ *
+ * @param string $version
+ */
+ public function setPdfVersion($version = '1.3')
+ {
+ $this->PDFVersion = sprintf('%.1F', $version);
+ }
+
+ /**
+ * Import a page.
+ *
+ * The second parameter defines the bounding box that should be used to transform the page into a
+ * form XObject.
+ *
+ * Following values are available: MediaBox, CropBox, BleedBox, TrimBox, ArtBox.
+ * If a box is not especially defined its default box will be used:
+ *
+ *
+ *
CropBox: Default -> MediaBox
+ *
BleedBox: Default -> CropBox
+ *
TrimBox: Default -> CropBox
+ *
ArtBox: Default -> CropBox
+ *
+ *
+ * It is possible to get the used page box by the {@link getLastUsedPageBox()} method.
+ *
+ * @param int $pageNo The page number
+ * @param string $boxName The boundary box to use when transforming the page into a form XObject
+ * @param boolean $groupXObject Define the form XObject as a group XObject to support transparency (if used)
+ * @return int An id of the imported page/template to use with e.g. fpdf_tpl::useTemplate()
+ * @throws LogicException|InvalidArgumentException
+ * @see getLastUsedPageBox()
+ */
+ public function importPage($pageNo, $boxName = 'CropBox', $groupXObject = true)
+ {
+ if ($this->_inTpl) {
+ throw new LogicException('Please import the desired pages before creating a new template.');
+ }
+
+ $fn = $this->currentFilename;
+ $boxName = '/' . ltrim($boxName, '/');
+
+ // check if page already imported
+ $pageKey = $fn . '-' . ((int)$pageNo) . $boxName;
+ if (isset($this->_importedPages[$pageKey])) {
+ return $this->_importedPages[$pageKey];
+ }
+
+ $parser = $this->parsers[$fn];
+ $parser->setPageNo($pageNo);
+
+ if (!in_array($boxName, $parser->availableBoxes)) {
+ throw new InvalidArgumentException(sprintf('Unknown box: %s', $boxName));
+ }
+
+ $pageBoxes = $parser->getPageBoxes($pageNo, $this->k);
+
+ /**
+ * MediaBox
+ * CropBox: Default -> MediaBox
+ * BleedBox: Default -> CropBox
+ * TrimBox: Default -> CropBox
+ * ArtBox: Default -> CropBox
+ */
+ if (!isset($pageBoxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox'))
+ $boxName = '/CropBox';
+ if (!isset($pageBoxes[$boxName]) && $boxName == '/CropBox')
+ $boxName = '/MediaBox';
+
+ if (!isset($pageBoxes[$boxName]))
+ return false;
+
+ $this->lastUsedPageBox = $boxName;
+
+ $box = $pageBoxes[$boxName];
+
+ $this->tpl++;
+ $this->_tpls[$this->tpl] = array();
+ $tpl =& $this->_tpls[$this->tpl];
+ $tpl['parser'] = $parser;
+ $tpl['resources'] = $parser->getPageResources();
+ $tpl['buffer'] = $parser->getContent();
+ $tpl['box'] = $box;
+ $tpl['groupXObject'] = $groupXObject;
+ if ($groupXObject) {
+ $this->setPdfVersion(max($this->getPdfVersion(), 1.4));
+ }
+
+ // To build an array that can be used by PDF_TPL::useTemplate()
+ $this->_tpls[$this->tpl] = array_merge($this->_tpls[$this->tpl], $box);
+
+ // An imported page will start at 0,0 all the time. Translation will be set in _putformxobjects()
+ $tpl['x'] = 0;
+ $tpl['y'] = 0;
+
+ // handle rotated pages
+ $rotation = $parser->getPageRotation($pageNo);
+ $tpl['_rotationAngle'] = 0;
+ if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) {
+ $steps = $angle / 90;
+
+ $_w = $tpl['w'];
+ $_h = $tpl['h'];
+ $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
+ $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
+
+ if ($angle < 0)
+ $angle += 360;
+
+ $tpl['_rotationAngle'] = $angle * -1;
+ }
+
+ $this->_importedPages[$pageKey] = $this->tpl;
+
+ return $this->tpl;
+ }
+
+ /**
+ * Returns the last used page boundary box.
+ *
+ * @return string The used boundary box: MediaBox, CropBox, BleedBox, TrimBox or ArtBox
+ */
+ public function getLastUsedPageBox()
+ {
+ return $this->lastUsedPageBox;
+ }
+
+ /**
+ * Use a template or imported page in current page or other template.
+ *
+ * You can use a template in a page or in another template.
+ * You can give the used template a new size. All parameters are optional.
+ * The width or height is calculated automatically if one is given. If no
+ * parameter is given the origin size as defined in beginTemplate() or of
+ * the imported page is used.
+ *
+ * The calculated or used width and height are returned as an array.
+ *
+ * @param int $tplIdx A valid template-id
+ * @param int $x The x-position
+ * @param int $y The y-position
+ * @param int $w The new width of the template
+ * @param int $h The new height of the template
+ * @param boolean $adjustPageSize If set to true the current page will be resized to fit the dimensions
+ * of the template
+ *
+ * @return array The height and width of the template (array('w' => ..., 'h' => ...))
+ * @throws LogicException|InvalidArgumentException
+ */
+ public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0, $adjustPageSize = false)
+ {
+ if ($adjustPageSize == true && is_null($x) && is_null($y)) {
+ $size = $this->getTemplateSize($tplIdx, $w, $h);
+ $orientation = $size['w'] > $size['h'] ? 'L' : 'P';
+ $size = array($size['w'], $size['h']);
+
+ if (is_subclass_of($this, 'TCPDF')) {
+ $this->setPageFormat($size, $orientation);
+ } else {
+ $size = $this->_getpagesize($size);
+
+ if($orientation != $this->CurOrientation ||
+ $size[0] != $this->CurPageSize[0] ||
+ $size[1] != $this->CurPageSize[1]
+ ) {
+ // New size or orientation
+ if ($orientation=='P') {
+ $this->w = $size[0];
+ $this->h = $size[1];
+ } else {
+ $this->w = $size[1];
+ $this->h = $size[0];
+ }
+ $this->wPt = $this->w * $this->k;
+ $this->hPt = $this->h * $this->k;
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
+ $this->CurOrientation = $orientation;
+ $this->CurPageSize = $size;
+ $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
+ }
+ }
+ }
+
+ $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values
+ $size = parent::useTemplate($tplIdx, $x, $y, $w, $h);
+ $this->_out('Q');
+
+ return $size;
+ }
+
+ /**
+ * Copy all imported objects to the resulting document.
+ */
+ protected function _putimportedobjects()
+ {
+ foreach($this->parsers AS $filename => $p) {
+ $this->currentParser =& $p;
+ if (!isset($this->_objStack[$filename]) || !is_array($this->_objStack[$filename])) {
+ continue;
+ }
+ while(($n = key($this->_objStack[$filename])) !== null) {
+ try {
+ $nObj = $this->currentParser->resolveObject($this->_objStack[$filename][$n][1]);
+ } catch (Exception $e) {
+ $nObj = array(pdf_parser::TYPE_OBJECT, pdf_parser::TYPE_NULL);
+ }
+
+ $this->_newobj($this->_objStack[$filename][$n][0]);
+
+ if ($nObj[0] == pdf_parser::TYPE_STREAM) {
+ $this->_writeValue($nObj);
+ } else {
+ $this->_writeValue($nObj[1]);
+ }
+
+ $this->_out("\nendobj");
+ $this->_objStack[$filename][$n] = null; // free memory
+ unset($this->_objStack[$filename][$n]);
+ reset($this->_objStack[$filename]);
+ }
+ }
+ }
+
+ /**
+ * Writes the form XObjects to the PDF document.
+ */
+ protected function _putformxobjects()
+ {
+ $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
+ reset($this->_tpls);
+ foreach($this->_tpls AS $tplIdx => $tpl) {
+ $this->_newobj();
+ $currentN = $this->n; // TCPDF/Protection: rem current "n"
+
+ $this->_tpls[$tplIdx]['n'] = $this->n;
+ $this->_out('<<' . $filter . '/Type /XObject');
+ $this->_out('/Subtype /Form');
+ $this->_out('/FormType 1');
+
+ $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
+ (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x']) * $this->k,
+ (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y']) * $this->k,
+ (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x']) * $this->k,
+ (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h'] - $tpl['y']) * $this->k
+ ));
+
+ $c = 1;
+ $s = 0;
+ $tx = 0;
+ $ty = 0;
+
+ if (isset($tpl['box'])) {
+ $tx = -$tpl['box']['llx'];
+ $ty = -$tpl['box']['lly'];
+
+ if ($tpl['_rotationAngle'] <> 0) {
+ $angle = $tpl['_rotationAngle'] * M_PI/180;
+ $c = cos($angle);
+ $s = sin($angle);
+
+ switch($tpl['_rotationAngle']) {
+ case -90:
+ $tx = -$tpl['box']['lly'];
+ $ty = $tpl['box']['urx'];
+ break;
+ case -180:
+ $tx = $tpl['box']['urx'];
+ $ty = $tpl['box']['ury'];
+ break;
+ case -270:
+ $tx = $tpl['box']['ury'];
+ $ty = -$tpl['box']['llx'];
+ break;
+ }
+ }
+ } else if ($tpl['x'] != 0 || $tpl['y'] != 0) {
+ $tx = -$tpl['x'] * 2;
+ $ty = $tpl['y'] * 2;
+ }
+
+ $tx *= $this->k;
+ $ty *= $this->k;
+
+ if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) {
+ $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]',
+ $c, $s, -$s, $c, $tx, $ty
+ ));
+ }
+
+ $this->_out('/Resources ');
+
+ if (isset($tpl['resources'])) {
+ $this->currentParser = $tpl['parser'];
+ $this->_writeValue($tpl['resources']); // "n" will be changed
+ } else {
+
+ $this->_out('<_res['tpl'][$tplIdx])) {
+ $res = $this->_res['tpl'][$tplIdx];
+
+ if (isset($res['fonts']) && count($res['fonts'])) {
+ $this->_out('/Font <<');
+ foreach ($res['fonts'] as $font)
+ $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
+ $this->_out('>>');
+ }
+ if (isset($res['images']) && count($res['images']) ||
+ isset($res['tpls']) && count($res['tpls']))
+ {
+ $this->_out('/XObject <<');
+ if (isset($res['images'])) {
+ foreach ($res['images'] as $image)
+ $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
+ }
+ if (isset($res['tpls'])) {
+ foreach ($res['tpls'] as $i => $_tpl)
+ $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R');
+ }
+ $this->_out('>>');
+ }
+ $this->_out('>>');
+ }
+ }
+
+ if (isset($tpl['groupXObject']) && $tpl['groupXObject']) {
+ $this->_out('/Group <>');
+ }
+
+ $newN = $this->n; // TCPDF: rem new "n"
+ $this->n = $currentN; // TCPDF: reset to current "n"
+
+ $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
+
+ if (is_subclass_of($this, 'TCPDF')) {
+ $buffer = $this->_getrawstream($buffer);
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_out("stream\n" . $buffer . "\nendstream");
+ } else {
+ $this->_out('/Length ' . strlen($buffer) . ' >>');
+ $this->_putstream($buffer);
+ }
+ $this->_out('endobj');
+ $this->n = $newN; // TCPDF: reset to new "n"
+ }
+
+ $this->_putimportedobjects();
+ }
+
+ /**
+ * Creates and optionally write the object definition to the document.
+ *
+ * Rewritten to handle existing own defined objects
+ *
+ * @param bool $objId
+ * @param bool $onlyNewObj
+ * @return bool|int
+ */
+ public function _newobj($objId = false, $onlyNewObj = false)
+ {
+ if (!$objId) {
+ $objId = ++$this->n;
+ }
+
+ //Begin a new object
+ if (!$onlyNewObj) {
+ $this->offsets[$objId] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
+ $this->_out($objId . ' 0 obj');
+ $this->_currentObjId = $objId; // for later use with encryption
+ }
+
+ return $objId;
+ }
+
+ /**
+ * Writes a PDF value to the resulting document.
+ *
+ * Needed to rebuild the source document
+ *
+ * @param mixed $value A PDF-Value. Structure of values see cases in this method
+ */
+ protected function _writeValue(&$value)
+ {
+ if (is_subclass_of($this, 'TCPDF')) {
+ parent::_prepareValue($value);
+ }
+
+ switch ($value[0]) {
+
+ case pdf_parser::TYPE_TOKEN:
+ $this->_straightOut($value[1] . ' ');
+ break;
+ case pdf_parser::TYPE_NUMERIC:
+ case pdf_parser::TYPE_REAL:
+ if (is_float($value[1]) && $value[1] != 0) {
+ $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ');
+ } else {
+ $this->_straightOut($value[1] . ' ');
+ }
+ break;
+
+ case pdf_parser::TYPE_ARRAY:
+
+ // An array. Output the proper
+ // structure and move on.
+
+ $this->_straightOut('[');
+ for ($i = 0; $i < count($value[1]); $i++) {
+ $this->_writeValue($value[1][$i]);
+ }
+
+ $this->_out(']');
+ break;
+
+ case pdf_parser::TYPE_DICTIONARY:
+
+ // A dictionary.
+ $this->_straightOut('<<');
+
+ reset ($value[1]);
+
+ while (list($k, $v) = each($value[1])) {
+ $this->_straightOut($k . ' ');
+ $this->_writeValue($v);
+ }
+
+ $this->_straightOut('>>');
+ break;
+
+ case pdf_parser::TYPE_OBJREF:
+
+ // An indirect object reference
+ // Fill the object stack if needed
+ $cpfn =& $this->currentParser->filename;
+ if (!isset($this->_doneObjStack[$cpfn][$value[1]])) {
+ $this->_newobj(false, true);
+ $this->_objStack[$cpfn][$value[1]] = array($this->n, $value);
+ $this->_doneObjStack[$cpfn][$value[1]] = array($this->n, $value);
+ }
+ $objId = $this->_doneObjStack[$cpfn][$value[1]][0];
+
+ $this->_out($objId . ' 0 R');
+ break;
+
+ case pdf_parser::TYPE_STRING:
+
+ // A string.
+ $this->_straightOut('(' . $value[1] . ')');
+
+ break;
+
+ case pdf_parser::TYPE_STREAM:
+
+ // A stream. First, output the
+ // stream dictionary, then the
+ // stream data itself.
+ $this->_writeValue($value[1]);
+ $this->_out('stream');
+ $this->_out($value[2][1]);
+ $this->_straightOut("endstream");
+ break;
+
+ case pdf_parser::TYPE_HEX:
+ $this->_straightOut('<' . $value[1] . '>');
+ break;
+
+ case pdf_parser::TYPE_BOOLEAN:
+ $this->_straightOut($value[1] ? 'true ' : 'false ');
+ break;
+
+ case pdf_parser::TYPE_NULL:
+ // The null object.
+
+ $this->_straightOut('null ');
+ break;
+ }
+ }
+
+
+ /**
+ * Modified _out() method so not each call will add a newline to the output.
+ */
+ protected function _straightOut($s)
+ {
+ if (!is_subclass_of($this, 'TCPDF')) {
+ if ($this->state == 2) {
+ $this->pages[$this->page] .= $s;
+ } else {
+ $this->buffer .= $s;
+ }
+
+ } else {
+ if ($this->state == 2) {
+ if ($this->inxobj) {
+ // we are inside an XObject template
+ $this->xobjects[$this->xobjid]['outdata'] .= $s;
+ } else if ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
+ // puts data before page footer
+ $pagebuff = $this->getPageBuffer($this->page);
+ $page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
+ $footer = substr($pagebuff, -$this->footerlen[$this->page]);
+ $this->setPageBuffer($this->page, $page . $s . $footer);
+ // update footer position
+ $this->footerpos[$this->page] += strlen($s);
+ } else {
+ // set page data
+ $this->setPageBuffer($this->page, $s, true);
+ }
+ } else if ($this->state > 0) {
+ // set general data
+ $this->setBuffer($s);
+ }
+ }
+ }
+
+ /**
+ * Ends the document
+ *
+ * Overwritten to close opened parsers
+ */
+ public function _enddoc()
+ {
+ parent::_enddoc();
+ $this->_closeParsers();
+ }
+
+ /**
+ * Close all files opened by parsers.
+ *
+ * @return boolean
+ */
+ protected function _closeParsers()
+ {
+ if ($this->state > 2) {
+ $this->cleanUp();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes cycled references and closes the file handles of the parser objects.
+ */
+ public function cleanUp()
+ {
+ while (($parser = array_pop($this->parsers)) !== null) {
+ /**
+ * @var fpdi_pdf_parser $parser
+ */
+ $parser->closeFile();
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/fpdi_bridge.php b/vendor/fpdi/fpdi_bridge.php
new file mode 100644
index 0000000..f89822d
--- /dev/null
+++ b/vendor/fpdi/fpdi_bridge.php
@@ -0,0 +1,215 @@
+_tpls as $tplIdx => $tpl) {
+ $out .= sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']);
+ }
+
+ return $out;
+ }
+
+ /**
+ * Writes a PDF value to the resulting document.
+ *
+ * Prepares the value for encryption of imported data by FPDI
+ *
+ * @param array $value
+ */
+ protected function _prepareValue(&$value)
+ {
+ switch ($value[0]) {
+ case pdf_parser::TYPE_STRING:
+ if ($this->encrypted) {
+ $value[1] = $this->_unescape($value[1]);
+ $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
+ $value[1] = TCPDF_STATIC::_escape($value[1]);
+ }
+ break;
+
+ case pdf_parser::TYPE_STREAM:
+ if ($this->encrypted) {
+ $value[2][1] = $this->_encrypt_data($this->_currentObjId, $value[2][1]);
+ $value[1][1]['/Length'] = array(
+ pdf_parser::TYPE_NUMERIC,
+ strlen($value[2][1])
+ );
+ }
+ break;
+
+ case pdf_parser::TYPE_HEX:
+ if ($this->encrypted) {
+ $value[1] = $this->hex2str($value[1]);
+ $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]);
+
+ // remake hexstring of encrypted string
+ $value[1] = $this->str2hex($value[1]);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Un-escapes a PDF string
+ *
+ * @param string $s
+ * @return string
+ */
+ protected function _unescape($s)
+ {
+ $out = '';
+ for ($count = 0, $n = strlen($s); $count < $n; $count++) {
+ if ($s[$count] != '\\' || $count == $n-1) {
+ $out .= $s[$count];
+ } else {
+ switch ($s[++$count]) {
+ case ')':
+ case '(':
+ case '\\':
+ $out .= $s[$count];
+ break;
+ case 'f':
+ $out .= chr(0x0C);
+ break;
+ case 'b':
+ $out .= chr(0x08);
+ break;
+ case 't':
+ $out .= chr(0x09);
+ break;
+ case 'r':
+ $out .= chr(0x0D);
+ break;
+ case 'n':
+ $out .= chr(0x0A);
+ break;
+ case "\r":
+ if ($count != $n-1 && $s[$count+1] == "\n")
+ $count++;
+ break;
+ case "\n":
+ break;
+ default:
+ // Octal-Values
+ if (ord($s[$count]) >= ord('0') &&
+ ord($s[$count]) <= ord('9')) {
+ $oct = ''. $s[$count];
+
+ if (ord($s[$count+1]) >= ord('0') &&
+ ord($s[$count+1]) <= ord('9')) {
+ $oct .= $s[++$count];
+
+ if (ord($s[$count+1]) >= ord('0') &&
+ ord($s[$count+1]) <= ord('9')) {
+ $oct .= $s[++$count];
+ }
+ }
+
+ $out .= chr(octdec($oct));
+ } else {
+ $out .= $s[$count];
+ }
+ }
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Hexadecimal to string
+ *
+ * @param string $data
+ * @return string
+ */
+ public function hex2str($data)
+ {
+ $data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>'));
+ if ((strlen($data) % 2) == 1) {
+ $data .= '0';
+ }
+
+ return pack('H*', $data);
+ }
+
+ /**
+ * String to hexadecimal
+ *
+ * @param string $str
+ * @return string
+ */
+ public function str2hex($str)
+ {
+ return current(unpack('H*', $str));
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/fpdi_pdf_parser.php b/vendor/fpdi/fpdi_pdf_parser.php
new file mode 100644
index 0000000..9e76341
--- /dev/null
+++ b/vendor/fpdi/fpdi_pdf_parser.php
@@ -0,0 +1,354 @@
+resolveObject($this->_root[1][1]['/Pages']);
+
+ // Read pages
+ $this->_readPages($pages, $this->_pages);
+
+ // count pages;
+ $this->_pageCount = count($this->_pages);
+ }
+
+ /**
+ * Get page count from source file.
+ *
+ * @return int
+ */
+ public function getPageCount()
+ {
+ return $this->_pageCount;
+ }
+
+ /**
+ * Set the page number.
+ *
+ * @param int $pageNo Page number to use
+ * @throws InvalidArgumentException
+ */
+ public function setPageNo($pageNo)
+ {
+ $pageNo = ((int) $pageNo) - 1;
+
+ if ($pageNo < 0 || $pageNo >= $this->getPageCount()) {
+ throw new InvalidArgumentException('Invalid page number!');
+ }
+
+ $this->pageNo = $pageNo;
+ }
+
+ /**
+ * Get page-resources from current page
+ *
+ * @return array|boolean
+ */
+ public function getPageResources()
+ {
+ return $this->_getPageResources($this->_pages[$this->pageNo]);
+ }
+
+ /**
+ * Get page-resources from a /Page dictionary.
+ *
+ * @param array $obj Array of pdf-data
+ * @return array|boolean
+ */
+ protected function _getPageResources($obj)
+ {
+ $obj = $this->resolveObject($obj);
+
+ // If the current object has a resources
+ // dictionary associated with it, we use
+ // it. Otherwise, we move back to its
+ // parent object.
+ if (isset($obj[1][1]['/Resources'])) {
+ $res = $this->resolveObject($obj[1][1]['/Resources']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ if (!isset($obj[1][1]['/Parent'])) {
+ return false;
+ }
+
+ $res = $this->_getPageResources($obj[1][1]['/Parent']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ /**
+ * Get content of current page.
+ *
+ * If /Contents is an array, the streams are concatenated
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ $buffer = '';
+
+ if (isset($this->_pages[$this->pageNo][1][1]['/Contents'])) {
+ $contents = $this->_getPageContent($this->_pages[$this->pageNo][1][1]['/Contents']);
+ foreach ($contents AS $tmpContent) {
+ $buffer .= $this->_unFilterStream($tmpContent) . ' ';
+ }
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Resolve all content objects.
+ *
+ * @param array $contentRef
+ * @return array
+ */
+ protected function _getPageContent($contentRef)
+ {
+ $contents = array();
+
+ if ($contentRef[0] == pdf_parser::TYPE_OBJREF) {
+ $content = $this->resolveObject($contentRef);
+ if ($content[1][0] == pdf_parser::TYPE_ARRAY) {
+ $contents = $this->_getPageContent($content[1]);
+ } else {
+ $contents[] = $content;
+ }
+ } else if ($contentRef[0] == pdf_parser::TYPE_ARRAY) {
+ foreach ($contentRef[1] AS $tmp_content_ref) {
+ $contents = array_merge($contents, $this->_getPageContent($tmp_content_ref));
+ }
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Get a boundary box from a page
+ *
+ * Array format is same as used by FPDF_TPL.
+ *
+ * @param array $page a /Page dictionary
+ * @param string $boxIndex Type of box {see {@link $availableBoxes})
+ * @param float Scale factor from user space units to points
+ *
+ * @return array|boolean
+ */
+ protected function _getPageBox($page, $boxIndex, $k)
+ {
+ $page = $this->resolveObject($page);
+ $box = null;
+ if (isset($page[1][1][$boxIndex])) {
+ $box = $page[1][1][$boxIndex];
+ }
+
+ if (!is_null($box) && $box[0] == pdf_parser::TYPE_OBJREF) {
+ $tmp_box = $this->resolveObject($box);
+ $box = $tmp_box[1];
+ }
+
+ if (!is_null($box) && $box[0] == pdf_parser::TYPE_ARRAY) {
+ $b = $box[1];
+ return array(
+ 'x' => $b[0][1] / $k,
+ 'y' => $b[1][1] / $k,
+ 'w' => abs($b[0][1] - $b[2][1]) / $k,
+ 'h' => abs($b[1][1] - $b[3][1]) / $k,
+ 'llx' => min($b[0][1], $b[2][1]) / $k,
+ 'lly' => min($b[1][1], $b[3][1]) / $k,
+ 'urx' => max($b[0][1], $b[2][1]) / $k,
+ 'ury' => max($b[1][1], $b[3][1]) / $k,
+ );
+ } else if (!isset($page[1][1]['/Parent'])) {
+ return false;
+ } else {
+ return $this->_getPageBox($this->resolveObject($page[1][1]['/Parent']), $boxIndex, $k);
+ }
+ }
+
+ /**
+ * Get all page boundary boxes by page number
+ *
+ * @param int $pageNo The page number
+ * @param float $k Scale factor from user space units to points
+ * @return array
+ * @throws InvalidArgumentException
+ */
+ public function getPageBoxes($pageNo, $k)
+ {
+ if (!isset($this->_pages[$pageNo - 1])) {
+ throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
+ }
+
+ return $this->_getPageBoxes($this->_pages[$pageNo - 1], $k);
+ }
+
+ /**
+ * Get all boxes from /Page dictionary
+ *
+ * @param array $page A /Page dictionary
+ * @param float $k Scale factor from user space units to points
+ * @return array
+ */
+ protected function _getPageBoxes($page, $k)
+ {
+ $boxes = array();
+
+ foreach($this->availableBoxes AS $box) {
+ if ($_box = $this->_getPageBox($page, $box, $k)) {
+ $boxes[$box] = $_box;
+ }
+ }
+
+ return $boxes;
+ }
+
+ /**
+ * Get the page rotation by page number
+ *
+ * @param integer $pageNo
+ * @throws InvalidArgumentException
+ * @return array
+ */
+ public function getPageRotation($pageNo)
+ {
+ if (!isset($this->_pages[$pageNo - 1])) {
+ throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.');
+ }
+
+ return $this->_getPageRotation($this->_pages[$pageNo - 1]);
+ }
+
+ /**
+ * Get the rotation value of a page
+ *
+ * @param array $obj A /Page dictionary
+ * @return array|bool
+ */
+ protected function _getPageRotation($obj)
+ {
+ $obj = $this->resolveObject($obj);
+ if (isset($obj[1][1]['/Rotate'])) {
+ $res = $this->resolveObject($obj[1][1]['/Rotate']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+ return $res;
+ }
+
+ if (!isset($obj[1][1]['/Parent'])) {
+ return false;
+ }
+
+ $res = $this->_getPageRotation($obj[1][1]['/Parent']);
+ if ($res[0] == pdf_parser::TYPE_OBJECT)
+ return $res[1];
+
+ return $res;
+ }
+
+ /**
+ * Read all pages
+ *
+ * @param array $pages /Pages dictionary
+ * @param array $result The result array
+ * @throws Exception
+ */
+ protected function _readPages(&$pages, &$result)
+ {
+ // Get the kids dictionary
+ $_kids = $this->resolveObject($pages[1][1]['/Kids']);
+
+ if (!is_array($_kids)) {
+ throw new Exception('Cannot find /Kids in current /Page-Dictionary');
+ }
+
+ if ($_kids[0] === self::TYPE_OBJECT) {
+ $_kids = $_kids[1];
+ }
+
+ $kids = $_kids[1];
+
+ foreach ($kids as $v) {
+ $pg = $this->resolveObject($v);
+ if ($pg[1][1]['/Type'][1] === '/Pages') {
+ // If one of the kids is an embedded
+ // /Pages array, resolve it as well.
+ $this->_readPages($pg, $result);
+ } else {
+ $result[] = $pg;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/pdf_context.php b/vendor/fpdi/pdf_context.php
new file mode 100644
index 0000000..88f3aed
--- /dev/null
+++ b/vendor/fpdi/pdf_context.php
@@ -0,0 +1,153 @@
+file =& $f;
+ if (is_string($this->file))
+ $this->_mode = 1;
+
+ $this->reset();
+ }
+
+ /**
+ * Get the position in the file stream
+ *
+ * @return int
+ */
+ public function getPos()
+ {
+ if ($this->_mode == 0) {
+ return ftell($this->file);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Reset the position in the file stream.
+ *
+ * Optionally move the file pointer to a new location and reset the buffered data.
+ *
+ * @param null $pos
+ * @param int $l
+ */
+ public function reset($pos = null, $l = 100)
+ {
+ if ($this->_mode == 0) {
+ if (!is_null($pos)) {
+ fseek ($this->file, $pos);
+ }
+
+ $this->buffer = $l > 0 ? fread($this->file, $l) : '';
+ $this->length = strlen($this->buffer);
+ if ($this->length < $l)
+ $this->increaseLength($l - $this->length);
+ } else {
+ $this->buffer = $this->file;
+ $this->length = strlen($this->buffer);
+ }
+ $this->offset = 0;
+ $this->stack = array();
+ }
+
+ /**
+ * Make sure that there is at least one character beyond the current offset in the buffer.
+ *
+ * To prevent the tokenizer from attempting to access data that does not exist.
+ *
+ * @return bool
+ */
+ public function ensureContent()
+ {
+ if ($this->offset >= $this->length - 1) {
+ return $this->increaseLength();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Forcefully read more data into the buffer
+ *
+ * @param int $l
+ * @return bool
+ */
+ public function increaseLength($l = 100)
+ {
+ if ($this->_mode == 0 && feof($this->file)) {
+ return false;
+ } else if ($this->_mode == 0) {
+ $totalLength = $this->length + $l;
+ do {
+ $toRead = $totalLength - $this->length;
+ if ($toRead < 1)
+ break;
+
+ $this->buffer .= fread($this->file, $toRead);
+ } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file));
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/fpdi/pdf_parser.php b/vendor/fpdi/pdf_parser.php
new file mode 100644
index 0000000..a1c82de
--- /dev/null
+++ b/vendor/fpdi/pdf_parser.php
@@ -0,0 +1,913 @@
+filename = $filename;
+
+ $this->_f = @fopen($this->filename, 'rb');
+
+ if (!$this->_f) {
+ throw new InvalidArgumentException(sprintf('Cannot open %s !', $filename));
+ }
+
+ $this->getPdfVersion();
+
+ require_once('pdf_context.php');
+ $this->_c = new pdf_context($this->_f);
+
+ // Read xref-Data
+ $this->_xref = array();
+ $this->_readXref($this->_xref, $this->_findXref());
+
+ // Check for Encryption
+ $this->getEncryption();
+
+ // Read root
+ $this->_readRoot();
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ $this->closeFile();
+ }
+
+ /**
+ * Close the opened file
+ */
+ public function closeFile()
+ {
+ if (isset($this->_f) && is_resource($this->_f)) {
+ fclose($this->_f);
+ unset($this->_f);
+ }
+ }
+
+ /**
+ * Check Trailer for Encryption
+ *
+ * @throws Exception
+ */
+ public function getEncryption()
+ {
+ if (isset($this->_xref['trailer'][1]['/Encrypt'])) {
+ throw new Exception('File is encrypted!');
+ }
+ }
+
+ /**
+ * Get PDF-Version
+ *
+ * @return string
+ */
+ public function getPdfVersion()
+ {
+ if ($this->_pdfVersion === null) {
+ fseek($this->_f, 0);
+ preg_match('/\d\.\d/', fread($this->_f, 16), $m);
+ if (isset($m[0]))
+ $this->_pdfVersion = $m[0];
+ }
+
+ return $this->_pdfVersion;
+ }
+
+ /**
+ * Read the /Root dictionary
+ */
+ protected function _readRoot()
+ {
+ if ($this->_xref['trailer'][1]['/Root'][0] != self::TYPE_OBJREF) {
+ throw new Exception('Wrong Type of Root-Element! Must be an indirect reference');
+ }
+
+ $this->_root = $this->resolveObject($this->_xref['trailer'][1]['/Root']);
+ }
+
+ /**
+ * Find the xref table
+ *
+ * @return integer
+ * @throws Exception
+ */
+ protected function _findXref()
+ {
+ $toRead = self::$searchForStartxrefLength;
+
+ $stat = fseek($this->_f, -$toRead, SEEK_END);
+ if ($stat === -1) {
+ fseek($this->_f, 0);
+ }
+
+ $data = fread($this->_f, $toRead);
+
+ $keywordPos = strpos(strrev($data), strrev('startxref'));
+ if (false === $keywordPos) {
+ $keywordPos = strpos(strrev($data), strrev('startref'));
+ }
+
+ if (false === $keywordPos) {
+ throw new Exception('Unable to find "startxref" keyword.');
+ }
+
+ $pos = strlen($data) - $keywordPos;
+ $data = substr($data, $pos);
+
+ if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) {
+ throw new Exception('Unable to find pointer to xref table.');
+ }
+
+ return (int) $matches[1];
+ }
+
+ /**
+ * Read the xref table
+ *
+ * @param array $result Array of xref table entries
+ * @param integer $offset of xref table
+ * @return boolean
+ * @throws Exception
+ */
+ protected function _readXref(&$result, $offset)
+ {
+ $tempPos = $offset - min(20, $offset);
+ fseek($this->_f, $tempPos); // set some bytes backwards to fetch corrupted docs
+
+ $data = fread($this->_f, 100);
+
+ $xrefPos = strrpos($data, 'xref');
+
+ if ($xrefPos === false) {
+ $this->_c->reset($offset);
+ $xrefStreamObjDec = $this->_readValue($this->_c);
+
+ if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == self::TYPE_OBJDEC) {
+ throw new Exception(
+ sprintf(
+ 'This document (%s) probably uses a compression technique which is not supported by the ' .
+ 'free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)',
+ $this->filename
+ )
+ );
+ } else {
+ throw new Exception('Unable to find xref table.');
+ }
+ }
+
+ if (!isset($result['xrefLocation'])) {
+ $result['xrefLocation'] = $tempPos + $xrefPos;
+ $result['maxObject'] = 0;
+ }
+
+ $cycles = -1;
+ $bytesPerCycle = 100;
+
+ fseek($this->_f, $tempPos = $tempPos + $xrefPos + 4); // set the handle directly after the "xref"-keyword
+ $data = fread($this->_f, $bytesPerCycle);
+
+ while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle * $cycles++, 0))) === false && !feof($this->_f)) {
+ $data .= fread($this->_f, $bytesPerCycle);
+ }
+
+ if ($trailerPos === false) {
+ throw new Exception('Trailer keyword not found after xref table');
+ }
+
+ $data = ltrim(substr($data, 0, $trailerPos));
+
+ // get Line-Ending
+ preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for line breaks
+
+ $differentLineEndings = count(array_unique($m[0]));
+ if ($differentLineEndings > 1) {
+ $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY);
+ } else {
+ $lines = explode($m[0][0], $data);
+ }
+
+ $data = $differentLineEndings = $m = null;
+ unset($data, $differentLineEndings, $m);
+
+ $linesCount = count($lines);
+
+ $start = 1;
+
+ for ($i = 0; $i < $linesCount; $i++) {
+ $line = trim($lines[$i]);
+ if ($line) {
+ $pieces = explode(' ', $line);
+ $c = count($pieces);
+ switch($c) {
+ case 2:
+ $start = (int)$pieces[0];
+ $end = $start + (int)$pieces[1];
+ if ($end > $result['maxObject'])
+ $result['maxObject'] = $end;
+ break;
+ case 3:
+ if (!isset($result['xref'][$start]))
+ $result['xref'][$start] = array();
+
+ if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) {
+ $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null;
+ }
+ $start++;
+ break;
+ default:
+ throw new Exception('Unexpected data in xref table');
+ }
+ }
+ }
+
+ $lines = $pieces = $line = $start = $end = $gen = null;
+ unset($lines, $pieces, $line, $start, $end, $gen);
+
+ $this->_c->reset($tempPos + $trailerPos + 7);
+ $trailer = $this->_readValue($this->_c);
+
+ if (!isset($result['trailer'])) {
+ $result['trailer'] = $trailer;
+ }
+
+ if (isset($trailer[1]['/Prev'])) {
+ $this->_readXref($result, $trailer[1]['/Prev'][1]);
+ }
+
+ $trailer = null;
+ unset($trailer);
+
+ return true;
+ }
+
+ /**
+ * Reads a PDF value
+ *
+ * @param pdf_context $c
+ * @param string $token A token
+ * @return mixed
+ */
+ protected function _readValue(&$c, $token = null)
+ {
+ if (is_null($token)) {
+ $token = $this->_readToken($c);
+ }
+
+ if ($token === false) {
+ return false;
+ }
+
+ switch ($token) {
+ case '<':
+ // This is a hex string.
+ // Read the value, then the terminator
+
+ $pos = $c->offset;
+
+ while(1) {
+
+ $match = strpos ($c->buffer, '>', $pos);
+
+ // If you can't find it, try
+ // reading more data from the stream
+
+ if ($match === false) {
+ if (!$c->increaseLength()) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+
+ $result = substr ($c->buffer, $c->offset, $match - $c->offset);
+ $c->offset = $match + 1;
+
+ return array (self::TYPE_HEX, $result);
+ }
+ break;
+
+ case '<<':
+ // This is a dictionary.
+
+ $result = array();
+
+ // Recurse into this function until we reach
+ // the end of the dictionary.
+ while (($key = $this->_readToken($c)) !== '>>') {
+ if ($key === false) {
+ return false;
+ }
+
+ if (($value = $this->_readValue($c)) === false) {
+ return false;
+ }
+
+ // Catch missing value
+ if ($value[0] == self::TYPE_TOKEN && $value[1] == '>>') {
+ $result[$key] = array(self::TYPE_NULL);
+ break;
+ }
+
+ $result[$key] = $value;
+ }
+
+ return array (self::TYPE_DICTIONARY, $result);
+
+ case '[':
+ // This is an array.
+
+ $result = array();
+
+ // Recurse into this function until we reach
+ // the end of the array.
+ while (($token = $this->_readToken($c)) !== ']') {
+ if ($token === false) {
+ return false;
+ }
+
+ if (($value = $this->_readValue($c, $token)) === false) {
+ return false;
+ }
+
+ $result[] = $value;
+ }
+
+ return array (self::TYPE_ARRAY, $result);
+
+ case '(':
+ // This is a string
+ $pos = $c->offset;
+
+ $openBrackets = 1;
+ do {
+ for (; $openBrackets != 0 && $pos < $c->length; $pos++) {
+ switch (ord($c->buffer[$pos])) {
+ case 0x28: // '('
+ $openBrackets++;
+ break;
+ case 0x29: // ')'
+ $openBrackets--;
+ break;
+ case 0x5C: // backslash
+ $pos++;
+ }
+ }
+ } while($openBrackets != 0 && $c->increaseLength());
+
+ $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1);
+ $c->offset = $pos;
+
+ return array (self::TYPE_STRING, $result);
+
+ case 'stream':
+ $tempPos = $c->getPos() - strlen($c->buffer);
+ $tempOffset = $c->offset;
+
+ $c->reset($startPos = $tempPos + $tempOffset);
+
+ $e = 0; // ensure line breaks in front of the stream
+ if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13))
+ $e++;
+ if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10))
+ $e++;
+
+ if ($this->_currentObj[1][1]['/Length'][0] == self::TYPE_OBJREF) {
+ $tmpLength = $this->resolveObject($this->_currentObj[1][1]['/Length']);
+ $length = $tmpLength[1][1];
+ } else {
+ $length = $this->_currentObj[1][1]['/Length'][1];
+ }
+
+ if ($length > 0) {
+ $c->reset($startPos + $e, $length);
+ $v = $c->buffer;
+ } else {
+ $v = '';
+ }
+
+ $c->reset($startPos + $e + $length);
+ $endstream = $this->_readToken($c);
+
+ if ($endstream != 'endstream') {
+ $c->reset($startPos + $e + $length + 9); // 9 = strlen("endstream")
+ // We don't throw an error here because the next
+ // round trip will start at a new offset
+ }
+
+ return array(self::TYPE_STREAM, $v);
+
+ default :
+ if (is_numeric($token)) {
+ // A numeric token. Make sure that
+ // it is not part of something else.
+ if (($tok2 = $this->_readToken($c)) !== false) {
+ if (is_numeric($tok2)) {
+
+ // Two numeric tokens in a row.
+ // In this case, we're probably in
+ // front of either an object reference
+ // or an object specification.
+ // Determine the case and return the data
+ if (($tok3 = $this->_readToken($c)) !== false) {
+ switch ($tok3) {
+ case 'obj':
+ return array(self::TYPE_OBJDEC, (int)$token, (int)$tok2);
+ case 'R':
+ return array(self::TYPE_OBJREF, (int)$token, (int)$tok2);
+ }
+ // If we get to this point, that numeric value up
+ // there was just a numeric value. Push the extra
+ // tokens back into the stack and return the value.
+ array_push($c->stack, $tok3);
+ }
+ }
+
+ array_push($c->stack, $tok2);
+ }
+
+ if ($token === (string)((int)$token))
+ return array(self::TYPE_NUMERIC, (int)$token);
+ else
+ return array(self::TYPE_REAL, (float)$token);
+ } else if ($token == 'true' || $token == 'false') {
+ return array(self::TYPE_BOOLEAN, $token == 'true');
+ } else if ($token == 'null') {
+ return array(self::TYPE_NULL);
+ } else {
+ // Just a token. Return it.
+ return array(self::TYPE_TOKEN, $token);
+ }
+ }
+ }
+
+ /**
+ * Resolve an object
+ *
+ * @param array $objSpec The object-data
+ * @return array|boolean
+ * @throws Exception
+ */
+ public function resolveObject($objSpec)
+ {
+ $c = $this->_c;
+
+ // Exit if we get invalid data
+ if (!is_array($objSpec)) {
+ return false;
+ }
+
+ if ($objSpec[0] == self::TYPE_OBJREF) {
+
+ // This is a reference, resolve it
+ if (isset($this->_xref['xref'][$objSpec[1]][$objSpec[2]])) {
+
+ // Save current file position
+ // This is needed if you want to resolve
+ // references while you're reading another object
+ // (e.g.: if you need to determine the length
+ // of a stream)
+
+ $oldPos = $c->getPos();
+
+ // Reposition the file pointer and
+ // load the object header.
+
+ $c->reset($this->_xref['xref'][$objSpec[1]][$objSpec[2]]);
+
+ $header = $this->_readValue($c);
+
+ if ($header[0] != self::TYPE_OBJDEC || $header[1] != $objSpec[1] || $header[2] != $objSpec[2]) {
+ $toSearchFor = $objSpec[1] . ' ' . $objSpec[2] . ' obj';
+ if (preg_match('/' . $toSearchFor . '/', $c->buffer)) {
+ $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor);
+ // reset stack
+ $c->stack = array();
+ } else {
+ throw new Exception(
+ sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2])
+ );
+ }
+ }
+
+ // If we're being asked to store all the information
+ // about the object, we add the object ID and generation
+ // number for later use
+ $result = array (
+ self::TYPE_OBJECT,
+ 'obj' => $objSpec[1],
+ 'gen' => $objSpec[2]
+ );
+
+ $this->_currentObj =& $result;
+
+ // Now simply read the object data until
+ // we encounter an end-of-object marker
+ while (true) {
+ $value = $this->_readValue($c);
+ if ($value === false || count($result) > 4) {
+ // in this case the parser couldn't find an "endobj" so we break here
+ break;
+ }
+
+ if ($value[0] == self::TYPE_TOKEN && $value[1] === 'endobj') {
+ break;
+ }
+
+ $result[] = $value;
+ }
+
+ $c->reset($oldPos);
+
+ if (isset($result[2][0]) && $result[2][0] == self::TYPE_STREAM) {
+ $result[0] = self::TYPE_STREAM;
+ }
+
+ } else {
+ throw new Exception(
+ sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2])
+ );
+ }
+
+ return $result;
+ } else {
+ return $objSpec;
+ }
+ }
+
+ /**
+ * Reads a token from the context
+ *
+ * @param pdf_context $c
+ * @return mixed
+ */
+ protected function _readToken($c)
+ {
+ // If there is a token available
+ // on the stack, pop it out and
+ // return it.
+
+ if (count($c->stack)) {
+ return array_pop($c->stack);
+ }
+
+ // Strip away any whitespace
+
+ do {
+ if (!$c->ensureContent()) {
+ return false;
+ }
+ $c->offset += strspn($c->buffer, "\x20\x0A\x0C\x0D\x09\x00", $c->offset);
+ } while ($c->offset >= $c->length - 1);
+
+ // Get the first character in the stream
+
+ $char = $c->buffer[$c->offset++];
+
+ switch ($char) {
+
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+
+ // This is either an array or literal string
+ // delimiter, Return it
+
+ return $char;
+
+ case '<':
+ case '>':
+
+ // This could either be a hex string or
+ // dictionary delimiter. Determine the
+ // appropriate case and return the token
+
+ if ($c->buffer[$c->offset] == $char) {
+ if (!$c->ensureContent()) {
+ return false;
+ }
+ $c->offset++;
+ return $char . $char;
+ } else {
+ return $char;
+ }
+
+ case '%':
+
+ // This is a comment - jump over it!
+
+ $pos = $c->offset;
+ while(1) {
+ $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos);
+ if ($match === 0) {
+ if (!$c->increaseLength()) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+
+ $c->offset = $m[0][1] + strlen($m[0][0]);
+
+ return $this->_readToken($c);
+ }
+
+ default:
+
+ // This is "another" type of token (probably
+ // a dictionary entry or a numeric value)
+ // Find the end and return it.
+
+ if (!$c->ensureContent()) {
+ return false;
+ }
+
+ while(1) {
+
+ // Determine the length of the token
+
+ $pos = strcspn($c->buffer, "\x20%[]<>()/\x0A\x0C\x0D\x09\x00", $c->offset);
+
+ if ($c->offset + $pos <= $c->length - 1) {
+ break;
+ } else {
+ // If the script reaches this point,
+ // the token may span beyond the end
+ // of the current buffer. Therefore,
+ // we increase the size of the buffer
+ // and try again--just to be safe.
+
+ $c->increaseLength();
+ }
+ }
+
+ $result = substr($c->buffer, $c->offset - 1, $pos + 1);
+
+ $c->offset += $pos;
+
+ return $result;
+ }
+ }
+
+ /**
+ * Un-filter a stream object
+ *
+ * @param array $obj
+ * @return string
+ * @throws Exception
+ */
+ protected function _unFilterStream($obj)
+ {
+ $filters = array();
+
+ if (isset($obj[1][1]['/Filter'])) {
+ $filter = $obj[1][1]['/Filter'];
+
+ if ($filter[0] == pdf_parser::TYPE_OBJREF) {
+ $tmpFilter = $this->resolveObject($filter);
+ $filter = $tmpFilter[1];
+ }
+
+ if ($filter[0] == pdf_parser::TYPE_TOKEN) {
+ $filters[] = $filter;
+ } else if ($filter[0] == pdf_parser::TYPE_ARRAY) {
+ $filters = $filter[1];
+ }
+ }
+
+ $stream = $obj[2][1];
+
+ foreach ($filters AS $filter) {
+ switch ($filter[1]) {
+ case '/FlateDecode':
+ case '/Fl':
+ if (function_exists('gzuncompress')) {
+ $oStream = $stream;
+ $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : '';
+ } else {
+ throw new Exception(
+ sprintf('To handle %s filter, please compile php with zlib support.', $filter[1])
+ );
+ }
+
+ if ($stream === false) {
+ $tries = 0;
+ while ($tries < 8 && ($stream === false || strlen($stream) < strlen($oStream))) {
+ $oStream = substr($oStream, 1);
+ $stream = @gzinflate($oStream);
+ $tries++;
+ }
+
+ if ($stream === false) {
+ throw new Exception('Error while decompressing stream.');
+ }
+ }
+ break;
+ case '/LZWDecode':
+ require_once('filters/FilterLZW.php');
+ $decoder = new FilterLZW();
+ $stream = $decoder->decode($stream);
+ break;
+ case '/ASCII85Decode':
+ require_once('filters/FilterASCII85.php');
+ $decoder = new FilterASCII85();
+ $stream = $decoder->decode($stream);
+ break;
+ case '/ASCIIHexDecode':
+ require_once('filters/FilterASCIIHexDecode.php');
+ $decoder = new FilterASCIIHexDecode();
+ $stream = $decoder->decode($stream);
+ break;
+ case null:
+ break;
+ default:
+ throw new Exception(sprintf('Unsupported Filter: %s', $filter[1]));
+ }
+ }
+
+ return $stream;
+ }
+}
\ No newline at end of file