Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
// $Header: /cvsroot/html2ps/box.generic.php,v 1.73 2007/05/06 18:49:29 Konstantin Exp $
3
 
4
require_once(HTML2PS_DIR.'globals.php');
5
 
6
class GenericBox {
7
  var $_cache;
8
  var $_css;
9
  var $_left;
10
  var $_top;
11
  var $_parent;
12
  var $baseline;
13
  var $default_baseline;
14
  var $_tagname;
15
  var $_id;
16
 
17
  var $_cached_base_font_size;
18
 
19
  function GenericBox() {
20
    $this->_cache = array();
21
    $this->_css   = array();
22
    $this->_cached_base_font_size = null;
23
 
24
    $this->_left   = 0;
25
    $this->_top    = 0;
26
 
27
    $this->_parent = null;
28
 
29
    $this->baseline = 0;
30
    $this->default_baseline = 0;
31
 
32
    $this->set_tagname(null);
33
 
34
    /**
35
     * Assign an unique box identifier
36
     */
37
    $GLOBALS['g_box_uid']++;
38
    $this->uid = $GLOBALS['g_box_uid'];
39
 
40
    $this->_id = null;
41
  }
42
 
43
  function destroy() {
44
    unset($this->_cache);
45
    unset($this->_css);
46
    unset($this->_left);
47
    unset($this->_top);
48
    unset($this->_parent);
49
    unset($this->baseline);
50
    unset($this->default_baseline);
51
  }
52
 
53
  /**
54
   * see get_property for optimization description
55
   */
56
  function setCSSProperty($code, $value) {
57
    static $cache = array();
58
    if (!isset($cache[$code])) {
59
      $cache[$code] =& CSS::get_handler($code);
60
    };
61
 
62
    $cache[$code]->replace_array($value, $this->_css);
63
  }
64
 
65
  /**
66
   * Optimization: this function is called very often,
67
   * so even a slight overhead for CSS::get_handler call
68
   * accumulates in a significiant processing delay.
69
   */
70
  function &get_css_property($code) {
71
    static $cache = array();
72
    if (!isset($cache[$code])) {
73
      $cache[$code] =& CSS::get_handler($code);
74
    };
75
 
76
    $value =& $cache[$code]->get($this->_css);
77
    return $value;
78
  }
79
 
80
  function get_tagname() {
81
    return $this->_tagname;
82
  }
83
 
84
  function set_tagname($tagname) {
85
    $this->_tagname = $tagname;
86
  }
87
 
88
  function get_content() {
89
    return '';
90
  }
91
 
92
  function show_postponed(&$driver) {
93
    $this->show($driver);
94
  }
95
 
96
  function copy_style(&$box) {
97
    // TODO: object references
98
    $this->_css = $box->_css;
99
  }
100
 
101
  /**
102
   * Optimization: _readCSSLength is usually called several times
103
   * while initializing box object. $base_font_size cound be calculated
104
   * only once and stored in a static variable.
105
   */
106
  function _readCSSLengths($state, $property_list) {
107
    if (is_null($this->_cached_base_font_size)) {
108
      $font =& $this->get_css_property(CSS_FONT);
109
      $this->_cached_base_font_size = $font->size->getPoints();
110
    };
111
 
112
    foreach ($property_list as $property) {
113
      $value =& $state->get_property($property);
114
 
115
      if ($value === CSS_PROPERTY_INHERIT) {
116
        $value =& $state->getInheritedProperty($property);
117
      };
118
 
119
      if (is_object($value)) {
120
        $value =& $value->copy();
121
        $value->doInherit($state);
122
        $value->units2pt($this->_cached_base_font_size);
123
      };
124
 
125
      $this->setCSSProperty($property, $value);
126
    }
127
  }
128
 
129
  function _readCSS($state, $property_list) {
130
    foreach ($property_list as $property) {
131
      $value = $state->get_property($property);
132
 
133
      // Note that order is important; composite object-value could be inherited and
134
      // object itself could contain subvalues with 'inherit' value
135
 
136
      if ($value === CSS_PROPERTY_INHERIT) {
137
        $value = $state->getInheritedProperty($property);
138
      };
139
 
140
      if (is_object($value)) {
141
        $value = $value->copy();
142
        $value->doInherit($state);
143
      };
144
 
145
      $this->setCSSProperty($property, $value);
146
    }
147
  }
148
 
149
  function readCSS(&$state) {
150
    /**
151
     * Determine font size to be used in this box (required for em/ex units)
152
     */
153
    $value = $state->get_property(CSS_FONT);
154
    if ($value === CSS_PROPERTY_INHERIT) {
155
      $value = $state->getInheritedProperty(CSS_FONT);
156
    };
157
    $base_font_size = $state->getBaseFontSize();
158
 
159
    if (is_object($value)) {
160
      $value = $value->copy();
161
      $value->doInherit($state);
162
      $value->units2pt($base_font_size);
163
    };
164
 
165
    $this->setCSSProperty(CSS_FONT, $value);
166
 
167
    /**
168
     * Continue working with other properties
169
     */
170
 
171
    $this->_readCSS($state,
172
                    array(CSS_COLOR,
173
                          CSS_DISPLAY,
174
                          CSS_VISIBILITY));
175
 
176
    $this->_readCSSLengths($state,
177
                           array(CSS_VERTICAL_ALIGN));
178
 
179
    // '-html2ps-link-destination'
180
    global $g_config;
181
    if ($g_config["renderlinks"]) {
182
      $this->_readCSS($state,
183
                      array(CSS_HTML2PS_LINK_DESTINATION));
184
    };
185
 
186
    // Save ID attribute value
187
    $id = $state->get_property(CSS_HTML2PS_LINK_DESTINATION);
188
    if (!is_null($id)) {
189
      $this->set_id($id);
190
    };
191
  }
192
 
193
  function set_id($id) {
194
    $this->_id = $id;
195
 
196
    if (!isset($GLOBALS['__html_box_id_map'][$id])) {
197
      $GLOBALS['__html_box_id_map'][$id] =& $this;
198
    };
199
  }
200
 
201
  function get_id() {
202
    return $this->_id;
203
  }
204
 
205
  function show(&$driver) {
206
    // If debugging mode is on, draw the box outline
207
    global $g_config;
208
    if ($g_config['debugbox']) {
209
      // Copy the border object of current box
210
      $driver->setlinewidth(0.1);
211
      $driver->setrgbcolor(0,0,0);
212
      $driver->rect($this->get_left(), $this->get_top(), $this->get_width(), -$this->get_height());
213
      $driver->stroke();
214
    }
215
 
216
    // Set current text color
217
    // Note that text color is used not only for text drawing (for example, list item markers
218
    // are drawn with text color)
219
    $color = $this->get_css_property(CSS_COLOR);
220
    $color->apply($driver);
221
  }
222
 
223
  /**
224
   * Render box having position: fixed or contained in such box
225
   * (Default behaviour)
226
   */
227
  function show_fixed(&$driver) {
228
    return $this->show($driver);
229
  }
230
 
231
  function pre_reflow_images() {}
232
 
233
  function set_top($value) {
234
    $this->_top = $value;
235
  }
236
 
237
  function set_left($value) {
238
    $this->_left = $value;
239
  }
240
 
241
  function offset($dx, $dy) {
242
    $this->_left += $dx;
243
    $this->_top  += $dy;
244
  }
245
 
246
  // Calculate the content upper-left corner position in curent flow
247
  function guess_corner(&$parent) {
248
    $this->put_left($parent->_current_x + $this->get_extra_left());
249
    $this->put_top($parent->_current_y - $this->get_extra_top());
250
  }
251
 
252
  function put_left($value) {
253
    $this->_left = $value;
254
  }
255
 
256
  function put_top($value)  {
257
    $this->_top = $value + $this->getBaselineOffset();
258
  }
259
 
260
  /**
261
   * Get Y coordinate of the top content area edge
262
   */
263
  function get_top() {
264
    return
265
      $this->_top -
266
      $this->getBaselineOffset();
267
  }
268
 
269
  function get_right() {
270
    return $this->get_left() + $this->get_width();
271
  }
272
 
273
  function get_left() {
274
    return $this->_left;
275
  }
276
 
277
  function get_bottom() {
278
    return $this->get_top() - $this->get_height();
279
  }
280
 
281
  function getBaselineOffset() {
282
    return $this->baseline - $this->default_baseline;
283
  }
284
 
285
  function &make_anchor(&$media, $link_destination, $page_heights) {
286
    $page_index = 0;
287
    $pages_count = count($page_heights);
288
    $bottom = mm2pt($media->height() - $media->margins['top']);
289
    do {
290
      $bottom -= $page_heights[$page_index];
291
      $page_index ++;
292
    } while ($this->get_top() < $bottom && $page_index < $pages_count);
293
 
294
    /**
295
     * Now let's calculate the coordinates on this particular page
296
     *
297
     * X coordinate calculation is pretty straightforward (and, actually, unused, as it would be
298
     * a bad idea to scroll PDF horiaontally).
299
     */
300
    $x = $this->get_left();
301
 
302
    /**
303
     * Y coordinate should be calculated relatively to the bottom page edge
304
     */
305
    $y = ($this->get_top() - $bottom) + (mm2pt($media->real_height()) - $page_heights[$page_index-1]) + mm2pt($media->margins['bottom']);
306
 
307
    $anchor =& new Anchor($link_destination,
308
                          $page_index,
309
                          $x,
310
                          $y);
311
    return $anchor;
312
  }
313
 
314
  function reflow_anchors(&$driver, &$anchors, $page_heights) {
315
    if ($this->is_null()) {
316
      return;
317
    };
318
 
319
    $link_destination = $this->get_css_property(CSS_HTML2PS_LINK_DESTINATION);
320
    if (!is_null($link_destination)) {
321
      $anchors[$link_destination] =& $this->make_anchor($driver->media, $link_destination, $page_heights);
322
    };
323
  }
324
 
325
  function reflow(&$parent, &$context) {}
326
 
327
  function reflow_inline() { }
328
 
329
  function out_of_flow() {
330
    return false;
331
  }
332
 
333
  function get_bottom_margin() { return $this->get_bottom(); }
334
 
335
  function get_top_margin() {
336
    return $this->get_top();
337
  }
338
 
339
  function get_full_height() { return $this->get_height(); }
340
  function get_width() { return $this->width; }
341
 
342
  function get_full_width() {
343
    return $this->width;
344
  }
345
 
346
  function get_height() {
347
    return $this->height;
348
  }
349
 
350
  function get_baseline() {
351
    return $this->baseline;
352
  }
353
 
354
  function is_container() { return false; }
355
 
356
  function isVisibleInFlow() { return true; }
357
 
358
  function reflow_text() { return true; }
359
 
360
  /**
361
   * Note that linebox is started by any non-whitespace inline element; all whitespace elements before
362
   * that moment should be ignored.
363
   *
364
   * @param boolean $linebox_started Flag indicating that a new line box have just started and it already contains
365
   * some inline elements
366
   * @param boolean $previous_whitespace Flag indicating that a previous inline element was an whitespace element.
367
   */
368
  function reflow_whitespace(&$linebox_started, &$previous_whitespace) {
369
    return;
370
  }
371
 
372
  function is_null() {
373
    return false;
374
  }
375
 
376
  function isCell() {
377
    return false;
378
  }
379
 
380
  function isTableRow() {
381
    return false;
382
  }
383
 
384
  function isTableSection() {
385
    return false;
386
  }
387
 
388
  // CSS 2.1:
389
  // 9.2.1 Block-level elements and block boxes
390
  // Block-level elements are those elements of the source document that are formatted visually as blocks
391
  // (e.g., paragraphs). Several values of the 'display' property make an element block-level:
392
  // 'block', 'list-item', 'compact' and 'run-in' (part of the time; see compact and run-in boxes), and 'table'.
393
  //
394
  function isBlockLevel() {
395
    return false;
396
  }
397
 
398
  function hasAbsolutePositionedParent() {
399
    if (is_null($this->parent)) {
400
      return false;
401
    };
402
 
403
    return
404
      $this->parent->get_css_property(CSS_POSITION) == POSITION_ABSOLUTE ||
405
      $this->parent->hasAbsolutePositionedParent();
406
  }
407
 
408
  function hasFixedPositionedParent() {
409
    if (is_null($this->parent)) {
410
      return false;
411
    };
412
 
413
    return
414
      $this->parent->get_css_property(CSS_POSITION) == POSITION_FIXED ||
415
      $this->parent->hasFixedPositionedParent();
416
  }
417
 
418
  /**
419
   * Box can be expanded if it has no width constrains and
420
   * all it parents has no width constraints
421
   */
422
  function mayBeExpanded() {
423
    $wc = $this->get_css_property(CSS_WIDTH);
424
    if (!$wc->isNull()) { return false; };
425
 
426
    if ($this->get_css_property(CSS_FLOAT) <> FLOAT_NONE) {
427
      return true;
428
    };
429
 
430
    if ($this->get_css_property(CSS_POSITION) <> POSITION_STATIC &&
431
        $this->get_css_property(CSS_POSITION) <> POSITION_RELATIVE) {
432
      return true;
433
    };
434
 
435
    if (is_null($this->parent)) {
436
      return true;
437
    };
438
 
439
    return $this->parent->mayBeExpanded();
440
  }
441
 
442
  function isLineBreak() {
443
    return false;
444
  }
445
 
446
  function get_min_width_natural($context) {
447
    return $this->get_min_width($context);
448
  }
449
 
450
  function is_note_call() {
451
    return isset($this->note_call);
452
  }
453
 
454
  /* DOM compatibility */
455
  function &get_parent_node() {
456
    return $this->parent;
457
  }
458
}
459
?>