set_anchor_locator(new FeatureTocAnchorLocatorHeaders());
$this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
}
function handle_after_parse($params) {
$pipeline =& $params['pipeline'];
$document =& $params['document'];
$media =& $params['media'];
$toc =& $this->find_toc_anchors($pipeline, $media, $document);
$this->update_document($toc, $pipeline, $media, $document);
}
function handle_before_document($params) {
$pipeline =& $params['pipeline'];
$document =& $params['document'];
$media =& $params['media'];
$page_heights =& $params['page-heights'];
$toc =& $this->find_toc_anchors($pipeline, $media, $document);
$this->update_page_numbers($toc, $pipeline, $document, $page_heights, $media);
}
function &find_toc_anchors(&$pipeline, &$media, &$document) {
$locator =& $this->get_anchor_locator();
$toc =& $locator->run($pipeline, $media, $document);
return $toc;
}
function &get_anchor_locator() {
return $this->_anchor_locator;
}
function &get_document_updater() {
return $this->_document_updater;
}
function guess_page(&$element, $page_heights, &$media) {
$page_index = 0;
$bottom = mm2pt($media->height() - $media->margins['top']);
do {
$bottom -= $page_heights[$page_index];
$page_index ++;
} while ($element->get_top() < $bottom);
return $page_index;
}
function install(&$pipeline, $params) {
$dispatcher =& $pipeline->get_dispatcher();
$dispatcher->add_observer('after-parse', array(&$this, 'handle_after_parse'));
$dispatcher->add_observer('before-document', array(&$this, 'handle_before_document'));
if (isset($params['location'])) {
switch ($params['location']) {
case 'placeholder':
$this->set_document_updater(new FeatureTocDocumentUpdaterPlaceholder());
break;
case 'before':
$this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
break;
case 'after':
default:
$this->set_document_updater(new FeatureTocDocumentUpdaterAppendPage());
break;
};
};
}
function set_anchor_locator(&$locator) {
$this->_anchor_locator =& $locator;
}
function set_document_updater(&$updater) {
$this->_document_updater =& $updater;
}
function make_toc_name_element_id($index) {
return sprintf('html2ps-toc-name-%d', $index);
}
function make_toc_page_element_id($index) {
return sprintf('html2ps-toc-page-%d', $index);
}
function update_document(&$toc, &$pipeline, &$media, &$document) {
$code = '';
$index = 1;
foreach ($toc as $toc_element) {
$code .= sprintf('
%s',
$index,
$toc_element['level'],
$this->make_toc_name_element_id($index),
$toc_element['level'],
$toc_element['anchor'],
$toc_element['name'],
$this->make_toc_page_element_id($index),
$toc_element['level'],
"\n");
$index++;
};
$toc_box_document =& $pipeline->parser->process(''.$code.'
', $pipeline, $media);
$context =& new FlowContext();
$pipeline->layout_engine->process($toc_box_document, $media, $pipeline->get_output_driver(), $context);
$toc_box =& $toc_box_document->content[0];
$document_updater =& $this->get_document_updater();
$document_updater->run($toc_box, $media, $document);
}
function update_page_numbers(&$toc, &$pipeline, &$document, &$page_heights, &$media) {
for ($i = 0, $size = count($toc); $i < $size; $i++) {
$toc_element =& $document->get_element_by_id($this->make_toc_page_element_id($i+1));
$element =& $toc[$i]['element'];
$toc_element->content[0]->content[0]->words[0] = $this->guess_page($element, $page_heights, $media);
};
}
}
class FeatureTocAnchorLocatorHeaders {
var $_locations;
var $_last_generated_anchor_id;
function FeatureTocAnchorLocatorHeaders() {
$this->set_locations(array());
$this->_last_generated_anchor_id = 0;
}
function generate_toc_anchor_id() {
$this->_last_generated_anchor_id++;
$id = $this->_last_generated_anchor_id;
return sprintf('html2ps-toc-element-%d', $id);
}
function get_locations() {
return $this->_locations;
}
function process_node($params) {
$node =& $params['node'];
if (preg_match('/^h(\d)$/i', $node->get_tagname(), $matches)) {
if (!$node->get_id()) {
$id = $this->generate_toc_anchor_id();
$node->set_id($id);
};
$this->_locations[] = array('name' => $node->get_content(),
'level' => (int)$matches[1],
'anchor' => $node->get_id(),
'element' => &$node);
};
}
function &run(&$pipeline, &$media, &$document) {
$this->set_locations(array());
$walker =& new TreeWalkerDepthFirst(array(&$this, 'process_node'));
$walker->run($document);
$locations = $this->get_locations();
foreach ($locations as $location) {
$location['element']->setCSSProperty(CSS_HTML2PS_LINK_DESTINATION, $location['element']->get_id());
// $id = $location['element']->get_id();
// $pipeline->output_driver->anchors[$id] =& $location['element']->make_anchor($media, $id);
};
return $locations;
}
function set_locations($locations) {
$this->_locations = $locations;
}
}
class FeatureTocDocumentUpdaterAppendPage {
function FeatureTocDocumentUpdaterAppendPage() {
}
function run(&$toc_box, &$media, &$document) {
$toc_box->setCSSProperty(CSS_PAGE_BREAK_BEFORE, PAGE_BREAK_ALWAYS);
$document->append_child($toc_box);
}
}
class FeatureTocDocumentUpdaterPrependPage {
function FeatureTocDocumentUpdaterPrependPage() {
}
function run(&$toc_box, &$media, &$document) {
$toc_box->setCSSProperty(CSS_PAGE_BREAK_AFTER, PAGE_BREAK_ALWAYS);
$document->insert_before($toc_box, $document->content[0]);
}
}
class FeatureTocDocumentUpdaterPlaceholder {
function FeatureTocDocumentUpdaterPlaceholder() {
}
function run(&$toc_box, &$media, &$document) {
$placeholder =& $document->get_element_by_id('html2ps-toc');
$placeholder->append_child($toc_box);
}
}
?>