32
1
mirror of https://github.com/vdm-io/tcpdf.git synced 2024-11-22 21:05:10 +00:00
This commit is contained in:
nicolaasuni 2011-07-07 15:10:33 +02:00
parent 18ccc5f668
commit fdc3f42c4e
4 changed files with 212 additions and 43 deletions

View File

@ -1,3 +1,8 @@
5.9.101 (2011-07-07)
- Support for JPEG and PNG ICC Color Profiles was added.
- Method addEmptySignatureAppearance() was added to add empty signature fields (see example n. 52).
- Bug item #3354332 "Strange line spacing with reduced font-size in writeHTML" was fixed.
5.9.100 (2011-06-29)
- An SVG bug has been fixed.

View File

@ -8,8 +8,8 @@ http://sourceforge.net/donate/index.php?group_id=128076
------------------------------------------------------------
Name: TCPDF
Version: 5.9.100
Release date: 2011-06-29
Version: 5.9.101
Release date: 2011-07-07
Author: Nicola Asuni
Copyright (c) 2002-2011:
@ -37,7 +37,7 @@ Main Features:
* images, graphic (geometric figures) and transformation methods;
* supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http: www.imagemagick.org/www/formats.html)
* 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, QR-Code, PDF417;
* Grayscale, RGB, CMYK, Spot Colors and Transparencies;
* JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;
* automatic page header and footer management;
* document encryption up to 256 bit and digital signature certifications;
* transactions to UNDO commands;

View File

@ -2,7 +2,7 @@
//============================================================+
// File name : example_052.php
// Begin : 2009-05-07
// Last Update : 2010-08-08
// Last Update : 2011-07-06
//
// Description : Example 052 for TCPDF class
// Certification Signature (experimental)
@ -97,13 +97,19 @@ $pdf->AddPage();
$text = 'This is a <b color="#FF0000">digitally signed document</b> using the default (example) <b>tcpdf.crt</b> certificate.<br />To validate this signature you have to load the <b color="#006600">tcpdf.fdf</b> on the Arobat Reader to add the certificate to <i>List of Trusted Identities</i>.<br /><br />For more information check the source code of this example and the source code documentation for the <i>setSignature()</i> method.<br /><br /><a href="http://www.tcpdf.org">www.tcpdf.org</a>';
$pdf->writeHTML($text, true, 0, true, 0);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// *** set signature appearance ***
// create content for signature (image and/or text)
$pdf->Image($file='../images/tcpdf_signature.png', $x=180, $y=60, $w=15, $h=15, $type='PNG');
$pdf->Image('../images/tcpdf_signature.png', 180, 60, 15, 15, 'PNG');
// define active area for signature appearance
$pdf->setSignatureAppearance($x=180, $y=60, $w=15, $h=15);
$pdf->setSignatureAppearance(180, 60, 15, 15);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// *** set an empty signature appearance ***
$pdf->addEmptySignatureAppearance(180, 80, 15, 15);
// ---------------------------------------------------------

228
tcpdf.php
View File

@ -1,9 +1,9 @@
<?php
//============================================================+
// File name : tcpdf.php
// Version : 5.9.100
// Version : 5.9.101
// Begin : 2002-08-03
// Last Update : 2011-06-29
// Last Update : 2011-07-07
// Author : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
// License : http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT GNU-LGPLv3 + YOU CAN'T REMOVE ANY TCPDF COPYRIGHT NOTICE OR LINK FROM THE GENERATED PDF DOCUMENTS.
// -------------------------------------------------------------------
@ -49,7 +49,7 @@
// * images, graphic (geometric figures) and transformation methods;
// * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/www/formats.html)
// * 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, QR-Code, PDF417;
// * Grayscale, RGB, CMYK, Spot Colors and Transparencies;
// * JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;
// * automatic page header and footer management;
// * document encryption up to 256 bit and digital signature certifications;
// * transactions to UNDO commands;
@ -114,7 +114,7 @@
* <li>images, graphic (geometric figures) and transformation methods;
* <li>supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/www/formats.html)</li>
* <li>1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, QR-Code, PDF417;</li>
* <li>Grayscale, RGB, CMYK, Spot Colors and Transparencies;</li>
* <li>JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;</li>
* <li>automatic page header and footer management;</li>
* <li>document encryption up to 256 bit and digital signature certifications;</li>
* <li>transactions to UNDO commands;</li>
@ -134,7 +134,7 @@
* Tools to encode your unicode fonts are on fonts/utils directory.</p>
* @package com.tecnick.tcpdf
* @author Nicola Asuni
* @version 5.9.100
* @version 5.9.101
*/
// Main configuration file. Define the K_TCPDF_EXTERNAL_CONFIG constant to skip this file.
@ -146,7 +146,7 @@ require_once(dirname(__FILE__).'/config/tcpdf_config.php');
* TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br>
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
* @version 5.9.100
* @version 5.9.101
* @author Nicola Asuni - info@tecnick.com
*/
class TCPDF {
@ -157,7 +157,7 @@ class TCPDF {
* Current TCPDF version.
* @private
*/
private $tcpdf_version = '5.9.100';
private $tcpdf_version = '5.9.101';
// Protected properties
@ -1334,6 +1334,13 @@ class TCPDF {
*/
protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0');
/**
* Array of empty digital signature appearances.
* @protected
* @since 5.9.101 (2011-07-06)
*/
protected $empty_signature_appearance = array();
/**
* Regular expression used to find blank characters (required for word-wrapping).
* @protected
@ -1939,6 +1946,7 @@ class TCPDF {
$this->ur['ef'] = '/Create/Delete/Modify/Import';
$this->ur['formex'] = '';
$this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0');
$this->empty_signature_appearance = array();
// set default JPEG quality
$this->jpeg_quality = 75;
// initialize some settings
@ -7849,16 +7857,63 @@ class TCPDF {
if ($a[2] != 2) {
$this->Error('Not a JPEG file: '.$file);
}
if ((!isset($a['channels'])) OR ($a['channels'] == 3)) {
$colspace = 'DeviceRGB';
} elseif ($a['channels'] == 4) {
$colspace = 'DeviceCMYK';
// bits per pixel
$bpc = isset($a['bits']) ? intval($a['bits']) : 8;
// number of image channels
if (!isset($a['channels'])) {
$channels = 3;
} else {
$colspace = 'DeviceGray';
$channels = intval($a['channels']);
}
$bpc = isset($a['bits']) ? $a['bits'] : 8;
// default colour space
switch ($channels) {
case 1: {
$colspace = 'DeviceGray';
break;
}
case 3: {
$colspace = 'DeviceRGB';
break;
}
case 4: {
$colspace = 'DeviceCMYK';
break;
}
default: {
$channels = 3;
$colspace = 'DeviceRGB';
break;
}
}
// get file content
$data = file_get_contents($file);
return array('w' => $a[0], 'h' => $a[1], 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
// check for embedded ICC profile
$icc = array();
$offset = 0;
while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
// get ICC sequence lenght
$length = ($this->_getUSHORT($data, ($pos - 2)) - 16);
// marker sequence number
$msn = max(1, ord($data{($pos + 12)}));
// number of markers (total of APP2 used)
$nom = max(1, ord($data{($pos + 13)}));
// get sequence segment
$icc[($msn - 1)] = substr($data, ($pos + 14), $length);
// move forward to next sequence
$offset = ($pos + 14 + $length);
}
// order and compact ICC segments
if (count($icc) > 0) {
ksort($icc);
$icc = implode('', $icc);
if ((ord($icc{36}) != 0x61) OR (ord($icc{37}) != 0x63) OR (ord($icc{38}) != 0x73) OR (ord($icc{39}) != 0x70)) {
// invalid ICC profile
$icc = false;
}
} else {
$icc = false;
}
return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
}
/**
@ -7917,25 +7972,27 @@ class TCPDF {
return false;
}
fread($f, 4);
$parms = '/DecodeParms << /Predictor 15 /Colors '.($ct == 2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
$channels = ($ct == 2 ? 3 : 1);
$parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
//Scan chunks looking for palette, transparency and image data
$pal = '';
$trns = '';
$data = '';
$icc = false;
do {
$n = $this->_freadint($f);
$type = fread($f, 4);
if ($type == 'PLTE') {
//Read palette
// read palette
$pal = $this->rfread($f, $n);
fread($f, 4);
} elseif ($type == 'tRNS') {
//Read transparency info
// read transparency info
$t = $this->rfread($f, $n);
if ($ct == 0) {
$trns = array(ord(substr($t, 1, 1)));
$trns = array(ord($t{1}));
} elseif ($ct == 2) {
$trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
$trns = array(ord($t{1}), ord($t{3}), ord($t{5}));
} else {
$pos = strpos($t, chr(0));
if ($pos !== false) {
@ -7944,9 +8001,26 @@ class TCPDF {
}
fread($f, 4);
} elseif ($type == 'IDAT') {
//Read image data block
// read image data block
$data .= $this->rfread($f, $n);
fread($f, 4);
} elseif ($type == 'iCCP') {
// skip profile name and null separator
$len = 0;
while ((ord(fread($f, 1)) > 0) AND ($len < 80)) {
++$len;
}
// get compression method
if (ord(fread($f, 1)) != 0) {
//$this->Error('Unknown filter method: '.$file);
fclose($f);
return false;
}
// read ICC Color Profile
$icc = $this->rfread($f, ($n - $len - 2));
// decompress profile
$icc = gzuncompress($icc);
fread($f, 4);
} elseif ($type == 'IEND') {
break;
} else {
@ -7959,7 +8033,7 @@ class TCPDF {
return false;
}
fclose($f);
return array('w' => $w, 'h' => $h, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
}
/**
@ -8807,6 +8881,14 @@ class TCPDF {
// set reference for signature object
$out .= ' '.$this->sig_obj_id.' 0 R';
}
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $esa) {
if ($esa['page'] == $n) {
// set reference for empty signature objects
$out .= ' '.$esa['objid'].' 0 R';
}
}
}
$out .= ' ]';
return $out;
}
@ -10749,13 +10831,21 @@ class TCPDF {
if (array_key_exists('masked', $info)) {
$out .= ' /SMask '.($this->n - 1).' 0 R';
}
if ($info['cs'] == 'Indexed') {
// set color space
$icc = false;
if (isset($info['icc']) AND ($info['icc'] !== false)) {
// ICC Colour Space
$icc = true;
$out .= ' /ColorSpace [/ICCBased '.($this->n + 1).' 0 R]';
} elseif ($info['cs'] == 'Indexed') {
// Indexed Colour Space
$out .= ' /ColorSpace [/Indexed /DeviceRGB '.((strlen($info['pal']) / 3) - 1).' '.($this->n + 1).' 0 R]';
} else {
// Device Colour Space
$out .= ' /ColorSpace /'.$info['cs'];
if ($info['cs'] == 'DeviceCMYK') {
$out .= ' /Decode [1 0 1 0 1 0 1 0]';
}
}
if ($info['cs'] == 'DeviceCMYK') {
$out .= ' /Decode [1 0 1 0 1 0 1 0]';
}
$out .= ' /BitsPerComponent '.$info['bpc'];
if (isset($altoid) AND ($altoid > 0)) {
@ -10779,7 +10869,7 @@ class TCPDF {
$out .= ' '.$info['parms'];
}
if (isset($info['trns']) AND is_array($info['trns'])) {
$trns='';
$trns = '';
$count_info = count($info['trns']);
for ($i=0; $i < $count_info; ++$i) {
$trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
@ -10792,8 +10882,14 @@ class TCPDF {
}
$out .= "\n".'endobj';
$this->_out($out);
//Palette
if ($info['cs'] == 'Indexed') {
if ($icc) {
// ICC colour profile
$this->_newobj();
$icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc'];
$icc = $this->_getrawstream($icc);
$this->_out('<</N '.$info['ch'].' /Alternate /'.$info['cs'].' '.$filter.'/Length '.strlen($icc).'>> stream'."\n".$icc."\n".'endstream'."\n".'endobj');
} elseif ($info['cs'] == 'Indexed') {
// colour palette
$this->_newobj();
$pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
$pal = $this->_getrawstream($pal);
@ -11083,8 +11179,15 @@ class TCPDF {
$out .= ' /AcroForm <<';
$objrefs = '';
if ($this->sign AND isset($this->signature_data['cert_type'])) {
// set reference for signature object
$objrefs .= $this->sig_obj_id.' 0 R';
}
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $esa) {
// set reference for empty signature objects
$objrefs .= ' '.$esa['objid'].' 0 R';
}
}
if (!empty($this->form_obj_id)) {
foreach($this->form_obj_id as $objid) {
$objrefs .= ' '.$objid.' 0 R';
@ -11226,6 +11329,25 @@ class TCPDF {
$this->_putheader();
$this->_putpages();
$this->_putresources();
// empty signature fields
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $key => $esa) {
// widget annotation for empty signature
$out = $this->_getobj($esa['objid'])."\n";
$out .= '<< /Type /Annot';
$out .= ' /Subtype /Widget';
$out .= ' /Rect ['.$esa['rect'].']';
$out .= ' /P '.$this->page_obj_id[($esa['page'])].' 0 R'; // link to signature appearance page
$out .= ' /F 4';
$out .= ' /FT /Sig';
$signame = sprintf('Signature_%03d', ($key + 1));
$out .= ' /T '.$this->_textstring($signame, $esa['objid']);
$out .= ' /Ff 0';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
}
// Signature
if ($this->sign AND isset($this->signature_data['cert_type'])) {
// widget annotation for signature
@ -11236,7 +11358,7 @@ class TCPDF {
$out .= ' /P '.$this->page_obj_id[($this->signature_appearance['page'])].' 0 R'; // link to signature appearance page
$out .= ' /F 4';
$out .= ' /FT /Sig';
$out .= ' /T '.$this->_textstring('Signature', $this->sig_obj_id);
$out .= ' /T '.$this->_textstring('Signature_000', $this->sig_obj_id);
$out .= ' /Ff 0';
$out .= ' /V '.($this->sig_obj_id + 1).' 0 R';
$out .= ' >>';
@ -16093,16 +16215,50 @@ class TCPDF {
* @since 5.3.011 (2010-06-17)
*/
public function setSignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1) {
$this->signature_appearance = $this->getSignatureAppearanceArray($x, $y, $w, $h, $page);
}
/**
* Add an empty digital signature appearance (a cliccable rectangle area to get signature properties)
* @param $x (float) Abscissa of the upper-left corner.
* @param $y (float) Ordinate of the upper-left corner.
* @param $w (float) Width of the signature area.
* @param $h (float) Height of the signature area.
* @param $page (int) option page number (if < 0 the current page is used).
* @public
* @author Nicola Asuni
* @since 5.9.101 (2011-07-06)
*/
public function addEmptySignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1) {
++$this->n;
$this->empty_signature_appearance[] = array('objid' => $this->n) + $this->getSignatureAppearanceArray($x, $y, $w, $h, $page);
}
/**
* Get the array that defines the signature appearance (page and rectangle coordinates).
* @param $x (float) Abscissa of the upper-left corner.
* @param $y (float) Ordinate of the upper-left corner.
* @param $w (float) Width of the signature area.
* @param $h (float) Height of the signature area.
* @param $page (int) option page number (if < 0 the current page is used).
* @return (array) Array defining page and rectangle coordinates of signature appearance.
* @protected
* @author Nicola Asuni
* @since 5.9.101 (2011-07-06)
*/
protected function getSignatureAppearanceArray($x=0, $y=0, $w=0, $h=0, $page=-1) {
$sigapp = array();
if (($page < 1) OR ($page > $this->numpages)) {
$this->signature_appearance['page'] = $this->page;
$sigapp['page'] = $this->page;
} else {
$this->signature_appearance['page'] = intval($page);
$sigapp['page'] = intval($page);
}
$a = $x * $this->k;
$b = $this->pagedim[($this->signature_appearance['page'])]['h'] - (($y + $h) * $this->k);
$b = $this->pagedim[($sigapp['page'])]['h'] - (($y + $h) * $this->k);
$c = $w * $this->k;
$d = $h * $this->k;
$this->signature_appearance['rect'] = sprintf('%.2F %.2F %.2F %.2F', $a, $b, $a+$c, $b+$d);
$sigapp['rect'] = sprintf('%.2F %.2F %.2F %.2F', $a, $b, ($a + $c), ($b + $d));
return $sigapp;
}
/**
@ -20102,7 +20258,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$fontsize = isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize;
$fontascent = $this->getFontAscent($fontname, $fontstyle, $fontsize);
$fontdescent = $this->getFontDescent($fontname, $fontstyle, $fontsize);
if ( ($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize)
if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize)
OR ($this->cell_height_ratio != $dom[$key]['line-height'])
OR ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) ) {
if (($key < ($maxel - 1)) AND (
@ -20154,7 +20310,9 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$dom[$key]['line-height'] = $this->cell_height_ratio;
}
if (!$dom[$key]['block']) {
$this->y += (((($curfontsize * $this->cell_height_ratio ) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2;
if (!(isset($dom[($key + 1)]) AND $dom[($key + 1)]['tag'] AND (!$dom[($key + 1)]['opening']) AND ($dom[($key + 1)]['value'] != 'li') AND $dom[$key]['tag'] AND (!$dom[$key]['opening']))) {
$this->y += (((($curfontsize * $this->cell_height_ratio) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2;
}
if (($dom[$key]['value'] != 'sup') AND ($dom[$key]['value'] != 'sub')) {
$minstartliney = min($this->y, $minstartliney);
$maxbottomliney = max(($this->y + (($fontsize * $this->cell_height_ratio) / $this->k)), $maxbottomliney);