1<?php
2// $Header: /cvsroot/html2ps/box.list-item.php,v 1.34 2006/09/07 18:38:12 Konstantin Exp $
3
4class ListItemBox extends BlockBox {
5  var $size;
6
7  function &create(&$root, &$pipeline) {
8    $box = new ListItemBox($root, $pipeline);
9    $box->readCSS($pipeline->get_current_css_state());
10
11    /**
12     * Create text box containing item number
13     */
14    $css_state =& $pipeline->get_current_css_state();
15    $css_state->pushState();
16    //    $css_state->set_property(CSS_COLOR, CSSColor::parse('transparent'));
17
18    $list_style = $css_state->get_property(CSS_LIST_STYLE);
19    $box->str_number_box = TextBox::create(CSSListStyleType::format_number($list_style->type,
20                                                                           $css_state->get_property(CSS_HTML2PS_LIST_COUNTER)).". ",
21                                            'iso-8859-1',
22                                            $pipeline);
23    $box->str_number_box->readCSS($pipeline->get_current_css_state());
24    $box->str_number_box->baseline = $box->str_number_box->default_baseline;
25
26    $css_state->popState();
27
28    /**
29     * Create nested items
30     */
31    $box->create_content($root, $pipeline);
32
33    return $box;
34  }
35
36  function readCSS(&$state) {
37    parent::readCSS($state);
38
39    $this->_readCSS($state,
40                    array(CSS_LIST_STYLE));
41
42    // Pseudo-CSS properties
43    // '-list-counter'
44
45    // increase counter value
46    $value = $state->get_property(CSS_HTML2PS_LIST_COUNTER) + 1;
47    $state->set_property(CSS_HTML2PS_LIST_COUNTER, $value);
48    $state->set_property_on_level(CSS_HTML2PS_LIST_COUNTER, CSS_PROPERTY_LEVEL_PARENT, $value);
49
50    // open the marker image if specified
51    $list_style = $this->get_css_property(CSS_LIST_STYLE);
52
53    if (!$list_style->image->is_default()) {
54      $this->marker_image = new ImgBox($list_style->image->_image);
55      $state->pushDefaultState();
56      $this->marker_image->readCSS($state);
57      $state->popState();
58      $this->marker_image->_setupSize();
59    } else {
60      $this->marker_image = null;
61    };
62  }
63
64  function ListItemBox(&$root, &$pipeline) {
65    // Call parent constructor
66    $this->BlockBox($root);
67  }
68
69  function reflow(&$parent, &$context) {
70    $list_style = $this->get_css_property(CSS_LIST_STYLE);
71
72    // If list-style-position is inside, we'll need to move marker box inside the
73    // list-item box and offset all content by its size;
74    if ($list_style->position === LSP_INSIDE) {
75      // Add marker box width to text-indent value
76      $this->_additional_text_indent = $this->get_marker_box_width();
77    };
78
79    // Procees with normal block box flow algorithm
80    BlockBox::reflow($parent, $context);
81  }
82
83  function reflow_text(&$driver) {
84    if (is_null($this->str_number_box->reflow_text($driver))) {
85      return null;
86    };
87
88    return GenericContainerBox::reflow_text($driver);
89  }
90
91  function show(&$viewport) {
92    // draw generic block box
93    if (is_null(BlockBox::show($viewport))) {
94      return null;
95    };
96
97    // Draw marker
98    /**
99     * Determine the marker box base X coordinate
100     * If possible, the marker box should be drawn immediately to the left of the first word in this
101     * box; this means that marker should be tied to the first text box, not to the left
102     * edge of the list block box
103     */
104    $child = $this->get_first_data();
105    if (is_null($child)) {
106      $x = $this->get_left();
107
108      $list_style = $this->get_css_property(CSS_LIST_STYLE);
109
110      // If list-style-position is inside, we'll need to move marker box inside the
111      // list-item box and offset all content by its size;
112      if ($list_style->position === LSP_INSIDE) {
113        $x += $this->get_marker_box_width();
114      };
115    } else {
116      $x = $child->get_left();
117    };
118
119    // Determine the base Y coordinate of marker box
120    $element = $this->get_first_data();
121
122    if ($element) {
123      $y = $element->get_top() - $element->default_baseline;
124    } else {
125      $y = $this->get_top();
126    }
127
128    if (!is_null($this->marker_image)) {
129      $this->mb_image($viewport, $x, $y);
130    } else {
131      $list_style = $this->get_css_property(CSS_LIST_STYLE);
132
133      switch ($list_style->type) {
134      case LST_NONE:
135        // No marker at all
136        break;
137      case LST_DISC:
138        $this->mb_disc($viewport, $x, $y);
139        break;
140      case LST_CIRCLE:
141        $this->mb_circle($viewport, $x, $y);
142        break;
143      case LST_SQUARE:
144        $this->mb_square($viewport, $x, $y);
145        break;
146      default:
147        $this->mb_string($viewport, $x, $y);
148        break;
149      }
150    };
151
152    return true;
153  }
154
155  function get_marker_box_width() {
156    $list_style = $this->get_css_property(CSS_LIST_STYLE);
157
158    switch ($list_style->type) {
159    case LST_NONE:
160      // no marker box will be rendered at all
161      return 0;
162    case LST_DISC:
163    case LST_CIRCLE:
164    case LST_SQUARE:
165      //  simple graphic marker
166      $font = $this->get_css_property(CSS_FONT);
167      return $font->size->getPoints();
168    default:
169      // string marker. Return the width of the marker text
170      return $this->str_number_box->get_full_width();
171    };
172  }
173
174  function mb_string(&$viewport, $x, $y) {
175    $this->str_number_box->put_top($y + $this->str_number_box->default_baseline);
176    $this->str_number_box->put_left($x - $this->str_number_box->get_full_width());
177
178    $this->str_number_box->show($viewport);
179  }
180
181  function mb_disc(&$viewport, $x, $y) {
182    $color = $this->get_css_property(CSS_COLOR);
183    $color->apply($viewport);
184
185    $font = $this->get_css_property(CSS_FONT);
186
187    $viewport->circle( $x - $font->size->getPoints()*0.5, $y + $font->size->getPoints()*0.4*HEIGHT_KOEFF, $font->size->getPoints() * BULLET_SIZE_KOEFF);
188    $viewport->fill();
189  }
190
191  function mb_circle(&$viewport, $x, $y) {
192    $color = $this->get_css_property(CSS_COLOR);
193    $color->apply($viewport);
194
195    $viewport->setlinewidth(0.1);
196
197    $font = $this->get_css_property(CSS_FONT);
198    $viewport->circle( $x - $font->size->getPoints()*0.5, $y + $font->size->getPoints()*0.4*HEIGHT_KOEFF, $font->size->getPoints() * BULLET_SIZE_KOEFF);
199    $viewport->stroke();
200  }
201
202  function mb_square(&$viewport, $x, $y) {
203    $color = $this->get_css_property(CSS_COLOR);
204    $color->apply($viewport);
205
206    $font = $this->get_css_property(CSS_FONT);
207    $viewport->rect($x - $font->size->getPoints()*0.512, $y + $font->size->getPoints()*0.3*HEIGHT_KOEFF, $font->size->getPoints() * 0.25, $font->size->getPoints() * 0.25);
208    $viewport->fill();
209  }
210
211  function mb_image(&$viewport, $x, $y) {
212    $font = $this->get_css_property(CSS_FONT);
213
214    $imagebox =& $this->marker_image;
215    $imagebox->moveto($x - $font->size->getPoints()*0.5 - $imagebox->get_width()/2,
216                      $y + $font->size->getPoints()*0.4*HEIGHT_KOEFF + $imagebox->get_height()/2);
217    $imagebox->show($viewport);
218  }
219
220  function isBlockLevel() {
221    return true;
222  }
223}
224
225?>