diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT
index 511b231..77793d8 100755
--- a/CHANGELOG.TXT
+++ b/CHANGELOG.TXT
@@ -1,3 +1,7 @@
+5.9.097 (2011-06-23)
+ - The method setHtmlVSpace() now can be used also for tags: div, li, br, dt and dd.
+ - The Named Destination feature was added (check the example n. 15) - thanks to Christian Deligant.
+
5.9.096 (2011-06-19)
- Bug item #3322234 "Surrogate pairs codes in arrUTF8ToUTF16BE" was fixed.
diff --git a/README.TXT b/README.TXT
index 6ede262..6434dbe 100755
--- a/README.TXT
+++ b/README.TXT
@@ -8,8 +8,8 @@ http://sourceforge.net/donate/index.php?group_id=128076
------------------------------------------------------------
Name: TCPDF
-Version: 5.9.096
-Release date: 2011-06-19
+Version: 5.9.097
+Release date: 2011-06-23
Author: Nicola Asuni
Copyright (c) 2002-2011:
@@ -45,7 +45,7 @@ Main Features:
* text rendering modes (fill, stroke and clipping);
* multiple columns mode;
* no-write page regions;
- * bookmarks and table of content;
+ * bookmarks, named destinations and table of content;
* text hyphenation;
* text stretching and spacing (tracking/kerning);
* automatic page break, line break and text alignments including justification;
@@ -64,7 +64,7 @@ Source Code Documentation:
http://www.tcpdf.org/doc/
For Additional Documentation:
- http: www.tcpdf.org
+ http://www.tcpdf.org
License
Copyright (C) 2002-2011 Nicola Asuni - Tecnick.com S.r.l.
diff --git a/examples/example_015.php b/examples/example_015.php
index 58c9424..3a79301 100755
--- a/examples/example_015.php
+++ b/examples/example_015.php
@@ -6,6 +6,7 @@
//
// Description : Example 015 for TCPDF class
// Bookmarks (Table of Content)
+// and Named Destinations.
//
// Author: Nicola Asuni
//
@@ -81,7 +82,8 @@ $pdf->Bookmark('Chapter 1', 0, 0, '', 'B', array(0,64,128));
$pdf->Cell(0, 10, 'Chapter 1', 0, 1, 'L');
$pdf->SetFont('times', 'I', 14);
-$pdf->Write(0, 'You can set PDF Bookmarks using the Bookmark() method.');
+$pdf->Write(0, 'You can set PDF Bookmarks using the Bookmark() method.
+You can set PDF Named Destinations using the setDestination() method.');
$pdf->SetFont('times', 'B', 20);
@@ -104,13 +106,25 @@ $pdf->Bookmark('Paragraph 1.3', 1, 0, '', '', array(0,0,0));
$pdf->Cell(0, 10, 'Paragraph 1.3', 0, 1, 'L');
$pdf->AddPage();
+// add a named destination so you can open this document at this page using the link: "example_015.pdf#chapter2"
+$pdf->setDestination('chapter2', 0, '');
$pdf->Bookmark('Chapter 2', 0, 0, '', 'BI', array(128,0,0));
$pdf->Cell(0, 10, 'Chapter 2', 0, 1, 'L');
+$pdf->SetFont('times', 'I', 14);
+$pdf->Write(0, 'Once saved, you can open this document at this page using the link: "example_015.pdf#chapter2".');
$pdf->AddPage();
+$pdf->setDestination('chapter3', 0, '');
+$pdf->SetFont('times', 'B', 20);
$pdf->Bookmark('Chapter 3', 0, 0, '', 'B', array(0,64,128));
$pdf->Cell(0, 10, 'Chapter 3', 0, 1, 'L');
+$pdf->AddPage();
+$pdf->setDestination('chapter4', 0, '');
+$pdf->SetFont('times', 'B', 20);
+$pdf->Bookmark('Chapter 4', 0, 0, '', 'B', array(0,64,128));
+$pdf->Cell(0, 10, 'Chapter 4', 0, 1, 'L');
+
// ---------------------------------------------------------
//Close and output PDF document
diff --git a/tcpdf.php b/tcpdf.php
index 15e3793..5ffafa6 100755
--- a/tcpdf.php
+++ b/tcpdf.php
@@ -1,9 +1,9 @@
text rendering modes (fill, stroke and clipping);
*
multiple columns mode;
* no-write page regions;
- * bookmarks and table of content;
+ * bookmarks, named destinations and table of content;
* text hyphenation;
* text stretching and spacing (tracking/kerning);
* automatic page break, line break and text alignments including justification;
@@ -134,7 +134,7 @@
* Tools to encode your unicode fonts are on fonts/utils directory.
* @package com.tecnick.tcpdf
* @author Nicola Asuni
- * @version 5.9.096
+ * @version 5.9.097
*/
// 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.
* @package com.tecnick.tcpdf
* @brief PHP class for generating PDF documents without requiring external extensions.
- * @version 5.9.096
+ * @version 5.9.097
* @author Nicola Asuni - info@tecnick.com
*/
class TCPDF {
@@ -157,7 +157,7 @@ class TCPDF {
* Current TCPDF version.
* @private
*/
- private $tcpdf_version = '5.9.096';
+ private $tcpdf_version = '5.9.097';
// Protected properties
@@ -1628,6 +1628,13 @@ class TCPDF {
*/
protected $pdflayers = false;
+ /**
+ * A dictionary of names and corresponding destinations (Dests key on document Catalog).
+ * @protected
+ * @since 5.9.097 (2011-06-23)
+ */
+ protected $dests = array();
+
/**
* Directory used for the last SVG image.
* @protected
@@ -10971,7 +10978,34 @@ class TCPDF {
protected function _putcatalog() {
$oid = $this->_newobj();
$out = '<< /Type /Catalog';
+ $out .= ' /Version /'.$this->PDFVersion;
+ //$out .= ' /Extensions <<>>';
$out .= ' /Pages 1 0 R';
+ //$out .= ' /PageLabels ' //...;
+ $out .= ' /Names <<';
+ if ((!empty($this->javascript)) OR (!empty($this->js_objects))) {
+ $out .= ' /JavaScript '.($this->n_js).' 0 R';
+ }
+ $out .= ' >>';
+ if (!empty($this->dests)) {
+ $out .= ' /Dests <<';
+ foreach($this->dests as $name => $o) {
+ $out .= ' /'.$name.' '.sprintf('[%u 0 R /XYZ 0 %.2F null]', $this->page_obj_id[($o['p'])], ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k)));
+ }
+ $out .= ' >>';
+ }
+ $out .= $this->_putviewerpreferences();
+ if (isset($this->LayoutMode) AND (!$this->empty_string($this->LayoutMode))) {
+ $out .= ' /PageLayout /'.$this->LayoutMode;
+ }
+ if (isset($this->PageMode) AND (!$this->empty_string($this->PageMode))) {
+ $out .= ' /PageMode /'.$this->PageMode;
+ }
+ if (count($this->outlines) > 0) {
+ $out .= ' /Outlines '.$this->OutlineRoot.' 0 R';
+ $out .= ' /PageMode /UseOutlines';
+ }
+ //$out .= ' /Threads []';
if ($this->ZoomMode == 'fullpage') {
$out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /Fit]';
} elseif ($this->ZoomMode == 'fullwidth') {
@@ -10979,27 +11013,19 @@ class TCPDF {
} elseif ($this->ZoomMode == 'real') {
$out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null 1]';
} elseif (!is_string($this->ZoomMode)) {
- $out .= sprintf(' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null %.2F]',($this->ZoomMode / 100));
- }
- if (isset($this->LayoutMode) AND (!$this->empty_string($this->LayoutMode))) {
- $out .= ' /PageLayout /'.$this->LayoutMode;
- }
- if (isset($this->PageMode) AND (!$this->empty_string($this->PageMode))) {
- $out .= ' /PageMode /'.$this->PageMode;
+ $out .= sprintf(' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null %.2F]', ($this->ZoomMode / 100));
}
+ //$out .= ' /AA <<>>';
+ //$out .= ' /URI <<>>';
+ //$out .= ' /Metadata X Y R';
+ //$out .= ' /StructTreeRoot <<>>';
+ //$out .= ' /MarkInfo <<>>';
if (isset($this->l['a_meta_language'])) {
$out .= ' /Lang '.$this->_textstring($this->l['a_meta_language'], $oid);
}
- $out .= ' /Names <<';
- if ((!empty($this->javascript)) OR (!empty($this->js_objects))) {
- $out .= ' /JavaScript '.($this->n_js).' 0 R';
- }
- $out .= ' >>';
- if (count($this->outlines) > 0) {
- $out .= ' /Outlines '.$this->OutlineRoot.' 0 R';
- $out .= ' /PageMode /UseOutlines';
- }
- $out .= ' '.$this->_putviewerpreferences();
+ //$out .= ' /SpiderInfo <<>>';
+ //$out .= ' /OutputIntents []';
+ //$out .= ' /PieceInfo <<>>';
if ($this->pdflayers) {
$p = $this->n_ocg_print.' 0 R';
$v = $this->n_ocg_view.' 0 R';
@@ -11053,6 +11079,10 @@ class TCPDF {
}
}
}
+ //$out .= ' /Legal <<>>';
+ //$out .= ' /Requirements []';
+ //$out .= ' /Collection <<>>';
+ //$out .= ' /NeedsRendering true';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
@@ -11067,7 +11097,7 @@ class TCPDF {
* @protected
*/
protected function _putviewerpreferences() {
- $out = '/ViewerPreferences <<';
+ $out = ' /ViewerPreferences <<';
if ($this->rtl) {
$out .= ' /Direction /R2L';
} else {
@@ -14560,11 +14590,88 @@ class TCPDF {
// END OF BIDIRECTIONAL TEXT SECTION -------------------
/**
- * Adds a bookmark.
- * @param $txt (string) bookmark description.
- * @param $level (int) bookmark level (minimum value is 0).
+ * Encode a name object.
+ * @param $name (string) Name object to encode.
+ * @return (string) Encoded name object.
+ * @protected
+ * @author Nicola Asuni
+ * @since 5.9.097 (2011-06-23)
+ */
+ protected function encodeNameObject($name) {
+ $escname = '';
+ $length = strlen($name);
+ for ($i = 0; $i < $length; ++$i) {
+ $chr = $name{$i};
+ if (preg_match('/[0-9a-zA-Z]/', $chr) == 1) {
+ $escname .= $chr;
+ } else {
+ $escname .= sprintf('#%02X', ord($chr));
+ }
+ }
+ return $escname;
+ }
+
+ /**
+ * Add a Named Destination.
+ * NOTE: destination names are unique, so only last entry will be saved.
+ * @param $name (string) Destination name.
+ * @param $y (float) Y position in user units of the destiantion on the selected page (default = -1 = current position; 0 = page start;).
+ * @param $page (int) Target page number (leave empty for current page).
+ * @return (string) Stripped named destination identifier or false in case of error.
+ * @public
+ * @author Christian Deligant, Nicola Asuni
+ * @since 5.9.097 (2011-06-23)
+ */
+ public function setDestination($name, $y=-1, $page='') {
+ // remove unsupported characters
+ $name = $this->encodeNameObject($name);
+ if ($this->empty_string($name)) {
+ return false;
+ }
+ if ($y == -1) {
+ $y = $this->GetY();
+ }
+ if (empty($page)) {
+ $page = $this->PageNo();
+ if (empty($page)) {
+ return;
+ }
+ }
+ $this->dests[$name] = array('y' => $y, 'p' => $page);
+ return $name;
+ }
+
+ /**
+ * Return the Named Destination array.
+ * @return (array) Named Destination array.
+ * @public
+ * @author Nicola Asuni
+ * @since 5.9.097 (2011-06-23)
+ */
+ public function getDestination() {
+ return $this->dests;
+ }
+
+ /**
+ * Adds a bookmark - alias for Bookmark().
+ * @param $txt (string) Bookmark description.
+ * @param $level (int) Bookmark level (minimum value is 0).
* @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;).
- * @param $page (int) target page number (leave empty for current page).
+ * @param $page (int) Target page number (leave empty for current page).
+ * @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic.
+ * @param $color (array) RGB color array (values from 0 to 255).
+ * @public
+ */
+ public function setBookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0)) {
+ $this->Bookmark($txt, $level, $y, $page, $style, $color);
+ }
+
+ /**
+ * Adds a bookmark.
+ * @param $txt (string) Bookmark description.
+ * @param $level (int) Bookmark level (minimum value is 0).
+ * @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;).
+ * @param $page (int) Target page number (leave empty for current page).
* @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic.
* @param $color (array) RGB color array (values from 0 to 255).
* @public
@@ -21121,7 +21228,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
} else {
$n = 1;
}
- $hb = ($n * $cur_h);
+ if ((!isset($this->tagvspaces[$tag['value']])) AND (in_array($tag['value'], array('div', 'dt', 'dd', 'li', 'br')))) {
+ $hb = 0;
+ } else {
+ $hb = ($n * $cur_h);
+ }
if (($this->htmlvspace <= 0) AND ($n > 0)) {
if (isset($parent['fontsize'])) {
$hbz = (($parent['fontsize'] / $this->k) * $this->cell_height_ratio);
@@ -21327,7 +21438,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
break;
}
case 'dt': {
- $this->addHTMLVertSpace($hbz, 0, $cell, $firsttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'dd': {
@@ -21337,7 +21448,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$this->lMargin += $this->listindent;
}
++$this->listindentlevel;
- $this->addHTMLVertSpace($hbz, 0, $cell, $firsttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'ul':
@@ -21372,7 +21483,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
}
case 'li': {
if ($key > 2) {
- $this->addHTMLVertSpace($hbz, 0, $cell, $firsttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
}
if ($this->listordered[$this->listnum]) {
// ordered item
@@ -21414,11 +21525,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
break;
}
case 'br': {
- $this->addHTMLVertSpace($hbz, 0, $cell, $firsttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'div': {
- $this->addHTMLVertSpace($hbz, 0, $cell, $firsttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'p': {
@@ -21742,7 +21853,11 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
} else {
$n = 1;
}
- $hb = ($n * $pre_h);
+ if ((!isset($this->tagvspaces[$tag['value']])) AND ($tag['value'] == 'div')) {
+ $hb = 0;
+ } else {
+ $hb = ($n * $pre_h);
+ }
if ($maxbottomliney > $this->PageBreakTrigger) {
$hbz = ($this->FontSize * $this->cell_height_ratio);
} elseif ($this->y < $maxbottomliney) {
@@ -22127,7 +22242,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
break;
}
case 'div': {
- $this->addHTMLVertSpace($hbz, 0, $cell, false, $lasttag);
+ $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
break;
}
case 'blockquote': {
@@ -23470,6 +23585,15 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
$this->outlines[$key]['p'] = $topage;
}
}
+ // adjust dests
+ $tmpdests = $this->dests;
+ foreach ($tmpdests as $key => $dest) {
+ if (($dest['p'] >= $topage) AND ($dest['p'] < $frompage)) {
+ $this->dests[$key]['p'] = $dest['p'] + 1;
+ } elseif ($dest['p'] == $frompage) {
+ $this->dests[$key]['p'] = $topage;
+ }
+ }
// adjust links
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {
@@ -23629,6 +23753,15 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value:
unset($this->outlines[$key]);
}
}
+ // adjust dests
+ $tmpdests = $this->dests;
+ foreach ($tmpdests as $key => $dest) {
+ if ($dest['p'] > $page) {
+ $this->dests[$key]['p'] = $dest['p'] - 1;
+ } elseif ($dest['p'] == $page) {
+ unset($this->dests[$key]);
+ }
+ }
// adjust links
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {