| 1 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
class FeatureToc {
|
|
|
4 |
var $_anchor_locator;
|
|
|
5 |
var $_document_updater;
|
|
|
6 |
|
|
|
7 |
function FeatureToc() {
|
|
|
8 |
$this->set_anchor_locator(new FeatureTocAnchorLocatorHeaders());
|
|
|
9 |
$this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
|
|
|
10 |
}
|
|
|
11 |
|
|
|
12 |
function handle_after_parse($params) {
|
|
|
13 |
$pipeline =& $params['pipeline'];
|
|
|
14 |
$document =& $params['document'];
|
|
|
15 |
$media =& $params['media'];
|
|
|
16 |
|
|
|
17 |
$toc =& $this->find_toc_anchors($pipeline, $media, $document);
|
|
|
18 |
$this->update_document($toc, $pipeline, $media, $document);
|
|
|
19 |
}
|
|
|
20 |
|
|
|
21 |
function handle_before_document($params) {
|
|
|
22 |
$pipeline =& $params['pipeline'];
|
|
|
23 |
$document =& $params['document'];
|
|
|
24 |
$media =& $params['media'];
|
|
|
25 |
$page_heights =& $params['page-heights'];
|
|
|
26 |
|
|
|
27 |
$toc =& $this->find_toc_anchors($pipeline, $media, $document);
|
|
|
28 |
$this->update_page_numbers($toc, $pipeline, $document, $page_heights, $media);
|
|
|
29 |
}
|
|
|
30 |
|
|
|
31 |
function &find_toc_anchors(&$pipeline, &$media, &$document) {
|
|
|
32 |
$locator =& $this->get_anchor_locator();
|
|
|
33 |
$toc =& $locator->run($pipeline, $media, $document);
|
|
|
34 |
return $toc;
|
|
|
35 |
}
|
|
|
36 |
|
|
|
37 |
function &get_anchor_locator() {
|
|
|
38 |
return $this->_anchor_locator;
|
|
|
39 |
}
|
|
|
40 |
|
|
|
41 |
function &get_document_updater() {
|
|
|
42 |
return $this->_document_updater;
|
|
|
43 |
}
|
|
|
44 |
|
|
|
45 |
function guess_page(&$element, $page_heights, &$media) {
|
|
|
46 |
$page_index = 0;
|
|
|
47 |
$bottom = mm2pt($media->height() - $media->margins['top']);
|
|
|
48 |
do {
|
|
|
49 |
$bottom -= $page_heights[$page_index];
|
|
|
50 |
$page_index ++;
|
|
|
51 |
} while ($element->get_top() < $bottom);
|
|
|
52 |
|
|
|
53 |
return $page_index;
|
|
|
54 |
}
|
|
|
55 |
|
|
|
56 |
function install(&$pipeline, $params) {
|
|
|
57 |
$dispatcher =& $pipeline->get_dispatcher();
|
|
|
58 |
$dispatcher->add_observer('after-parse', array(&$this, 'handle_after_parse'));
|
|
|
59 |
$dispatcher->add_observer('before-document', array(&$this, 'handle_before_document'));
|
|
|
60 |
|
|
|
61 |
if (isset($params['location'])) {
|
|
|
62 |
switch ($params['location']) {
|
|
|
63 |
case 'placeholder':
|
|
|
64 |
$this->set_document_updater(new FeatureTocDocumentUpdaterPlaceholder());
|
|
|
65 |
break;
|
|
|
66 |
case 'before':
|
|
|
67 |
$this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
|
|
|
68 |
break;
|
|
|
69 |
case 'after':
|
|
|
70 |
default:
|
|
|
71 |
$this->set_document_updater(new FeatureTocDocumentUpdaterAppendPage());
|
|
|
72 |
break;
|
|
|
73 |
};
|
|
|
74 |
};
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
function set_anchor_locator(&$locator) {
|
|
|
78 |
$this->_anchor_locator =& $locator;
|
|
|
79 |
}
|
|
|
80 |
|
|
|
81 |
function set_document_updater(&$updater) {
|
|
|
82 |
$this->_document_updater =& $updater;
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
function make_toc_name_element_id($index) {
|
|
|
86 |
return sprintf('html2ps-toc-name-%d', $index);
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
function make_toc_page_element_id($index) {
|
|
|
90 |
return sprintf('html2ps-toc-page-%d', $index);
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
function update_document(&$toc, &$pipeline, &$media, &$document) {
|
|
|
94 |
$code = '';
|
|
|
95 |
$index = 1;
|
|
|
96 |
foreach ($toc as $toc_element) {
|
|
|
97 |
$code .= sprintf('
|
|
|
98 |
<div id="html2ps-toc-%s" class="html2ps-toc-wrapper html2ps-toc-%d-wrapper">
|
|
|
99 |
<div id="%s" class="html2ps-toc-name html2ps-toc-%d-name"><a href="#%s">%s</a></div>
|
|
|
100 |
<div id="%s" class="html2ps-toc-page html2ps-toc-%d-page">0000</div>
|
|
|
101 |
</div>%s',
|
|
|
102 |
$index,
|
|
|
103 |
$toc_element['level'],
|
|
|
104 |
$this->make_toc_name_element_id($index),
|
|
|
105 |
$toc_element['level'],
|
|
|
106 |
$toc_element['anchor'],
|
|
|
107 |
$toc_element['name'],
|
|
|
108 |
$this->make_toc_page_element_id($index),
|
|
|
109 |
$toc_element['level'],
|
|
|
110 |
"\n");
|
|
|
111 |
$index++;
|
|
|
112 |
};
|
|
|
113 |
|
|
|
114 |
$toc_box_document =& $pipeline->parser->process('<body><div>'.$code.'</div></body>', $pipeline, $media);
|
|
|
115 |
$context =& new FlowContext();
|
|
|
116 |
$pipeline->layout_engine->process($toc_box_document, $media, $pipeline->get_output_driver(), $context);
|
|
|
117 |
$toc_box =& $toc_box_document->content[0];
|
|
|
118 |
|
|
|
119 |
$document_updater =& $this->get_document_updater();
|
|
|
120 |
$document_updater->run($toc_box, $media, $document);
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
function update_page_numbers(&$toc, &$pipeline, &$document, &$page_heights, &$media) {
|
|
|
124 |
for ($i = 0, $size = count($toc); $i < $size; $i++) {
|
|
|
125 |
$toc_element =& $document->get_element_by_id($this->make_toc_page_element_id($i+1));
|
|
|
126 |
$element =& $toc[$i]['element'];
|
|
|
127 |
|
|
|
128 |
$toc_element->content[0]->content[0]->words[0] = $this->guess_page($element, $page_heights, $media);
|
|
|
129 |
};
|
|
|
130 |
}
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
class FeatureTocAnchorLocatorHeaders {
|
|
|
134 |
var $_locations;
|
|
|
135 |
var $_last_generated_anchor_id;
|
|
|
136 |
|
|
|
137 |
function FeatureTocAnchorLocatorHeaders() {
|
|
|
138 |
$this->set_locations(array());
|
|
|
139 |
$this->_last_generated_anchor_id = 0;
|
|
|
140 |
}
|
|
|
141 |
|
|
|
142 |
function generate_toc_anchor_id() {
|
|
|
143 |
$this->_last_generated_anchor_id++;
|
|
|
144 |
$id = $this->_last_generated_anchor_id;
|
|
|
145 |
return sprintf('html2ps-toc-element-%d', $id);
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
function get_locations() {
|
|
|
149 |
return $this->_locations;
|
|
|
150 |
}
|
|
|
151 |
|
|
|
152 |
function process_node($params) {
|
|
|
153 |
$node =& $params['node'];
|
|
|
154 |
|
|
|
155 |
if (preg_match('/^h(\d)$/i', $node->get_tagname(), $matches)) {
|
|
|
156 |
if (!$node->get_id()) {
|
|
|
157 |
$id = $this->generate_toc_anchor_id();
|
|
|
158 |
$node->set_id($id);
|
|
|
159 |
};
|
|
|
160 |
|
|
|
161 |
$this->_locations[] = array('name' => $node->get_content(),
|
|
|
162 |
'level' => (int)$matches[1],
|
|
|
163 |
'anchor' => $node->get_id(),
|
|
|
164 |
'element' => &$node);
|
|
|
165 |
};
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
function &run(&$pipeline, &$media, &$document) {
|
|
|
169 |
$this->set_locations(array());
|
|
|
170 |
$walker =& new TreeWalkerDepthFirst(array(&$this, 'process_node'));
|
|
|
171 |
$walker->run($document);
|
|
|
172 |
$locations = $this->get_locations();
|
|
|
173 |
|
|
|
174 |
foreach ($locations as $location) {
|
|
|
175 |
$location['element']->setCSSProperty(CSS_HTML2PS_LINK_DESTINATION, $location['element']->get_id());
|
|
|
176 |
|
|
|
177 |
// $id = $location['element']->get_id();
|
|
|
178 |
// $pipeline->output_driver->anchors[$id] =& $location['element']->make_anchor($media, $id);
|
|
|
179 |
};
|
|
|
180 |
|
|
|
181 |
return $locations;
|
|
|
182 |
}
|
|
|
183 |
|
|
|
184 |
function set_locations($locations) {
|
|
|
185 |
$this->_locations = $locations;
|
|
|
186 |
}
|
|
|
187 |
}
|
|
|
188 |
|
|
|
189 |
class FeatureTocDocumentUpdaterAppendPage {
|
|
|
190 |
function FeatureTocDocumentUpdaterAppendPage() {
|
|
|
191 |
}
|
|
|
192 |
|
|
|
193 |
function run(&$toc_box, &$media, &$document) {
|
|
|
194 |
$toc_box->setCSSProperty(CSS_PAGE_BREAK_BEFORE, PAGE_BREAK_ALWAYS);
|
|
|
195 |
$document->append_child($toc_box);
|
|
|
196 |
}
|
|
|
197 |
}
|
|
|
198 |
|
|
|
199 |
class FeatureTocDocumentUpdaterPrependPage {
|
|
|
200 |
function FeatureTocDocumentUpdaterPrependPage() {
|
|
|
201 |
}
|
|
|
202 |
|
|
|
203 |
function run(&$toc_box, &$media, &$document) {
|
|
|
204 |
$toc_box->setCSSProperty(CSS_PAGE_BREAK_AFTER, PAGE_BREAK_ALWAYS);
|
|
|
205 |
$document->insert_before($toc_box, $document->content[0]);
|
|
|
206 |
}
|
|
|
207 |
}
|
|
|
208 |
|
|
|
209 |
class FeatureTocDocumentUpdaterPlaceholder {
|
|
|
210 |
function FeatureTocDocumentUpdaterPlaceholder() {
|
|
|
211 |
}
|
|
|
212 |
|
|
|
213 |
function run(&$toc_box, &$media, &$document) {
|
|
|
214 |
$placeholder =& $document->get_element_by_id('html2ps-toc');
|
|
|
215 |
$placeholder->append_child($toc_box);
|
|
|
216 |
}
|
|
|
217 |
}
|
|
|
218 |
|
|
|
219 |
?>
|