1<?php
2
3class CSSState {
4  var $_state;
5  var $_stateDefaultFlags;
6  var $_handlerSet;
7  var $_baseFontSize;
8
9  function CSSState(&$handlerSet) {
10    $this->_handlerSet        =& $handlerSet;
11    $this->_state             =  array($this->_getDefaultState());
12    $this->_stateDefaultFlags =  array($this->_getDefaultStateFlags());
13
14    /**
15     * Note that default state should contain font size in absolute units (e.g. 11pt),
16     * so we may pass any value as a base font size parameter of 'toPt' method call
17     */
18    $this->_baseFontSize      =  array($this->_state[0][CSS_FONT]->size->toPt(0));
19  }
20
21  function _getDefaultState() {
22    return $this->_handlerSet->_getDefaultState();
23  }
24
25  function _getDefaultStateFlags() {
26    return $this->_handlerSet->_getDefaultStateFlags();
27  }
28
29  function replaceParsed($property_data, $property_list) {
30    foreach ($property_list as $property) {
31      $this->set_property($property, $property_data->get_css_property($property));
32    };
33  }
34
35  function popState() {
36    array_shift($this->_state);
37    array_shift($this->_stateDefaultFlags);
38    array_shift($this->_baseFontSize);
39  }
40
41  function getStoredState(&$base_font_size, &$state, &$state_default_flags) {
42    $base_font_size      = array_shift($this->_baseFontSize);
43    $state               = array_shift($this->_state);
44    $state_default_flags = array_shift($this->_stateDefaultFlags);
45  }
46
47  function pushStoredState($base_font_size, $state, $state_default_flags) {
48    array_unshift($this->_baseFontSize,      $base_font_size);
49    array_unshift($this->_state,             $state);
50    array_unshift($this->_stateDefaultFlags, $state_default_flags);
51  }
52
53  function pushState() {
54    $base_size = $this->getBaseFontSize();
55    /**
56     * Only computed font-size values are inherited; this means that
57     * base font size value should not be recalculated if font-size was not set explicitly
58     */
59    if ($this->get_propertyDefaultFlag(CSS_FONT_SIZE)) {
60      array_unshift($this->_baseFontSize, $base_size);
61    } else {
62      $size = $this->getInheritedProperty(CSS_FONT_SIZE);
63      array_unshift($this->_baseFontSize, $size->toPt($base_size));
64    };
65
66    array_unshift($this->_state, $this->getState());
67    array_unshift($this->_stateDefaultFlags, $this->_getDefaultStateFlags());
68  }
69
70  function pushDefaultState() {
71    $this->pushState();
72    $this->_state[0] = $this->_getDefaultState();
73
74    $handlers = $this->_handlerSet->getInheritableHandlers();
75
76    foreach ($handlers as $property => $handler) {
77      $handler->inherit($this->_state[1], $this->_state[0]);
78    };
79  }
80
81  function pushDefaultTextState() {
82    $state = $this->getState();
83
84    $this->pushState();
85    $this->_state[0] = $this->_getDefaultState();
86    $new_state =& $this->getState();
87
88    $handlers = $this->_handlerSet->getInheritableTextHandlers();
89    foreach ($handlers as $property => $handler) {
90      $handler->inherit_text($state, $new_state);
91    }
92  }
93
94  function &getStateDefaultFlags() {
95    return $this->_stateDefaultFlags[0];
96  }
97
98  function &getState() {
99    return $this->_state[0];
100  }
101
102  function &getInheritedProperty($code) {
103    $handler =& CSS::get_handler($code);
104
105    $size = count($this->_state);
106    for ($i=0; $i<$size; $i++) {
107      $value =& $handler->get($this->_state[$i]);
108      if ($value != CSS_PROPERTY_INHERIT) {
109        return $value;
110      };
111
112      // Prevent taking  the font-size property; as,  according to CSS
113      // standard,  'inherit'  should mean  calculated  value, we  use
114      // '1em' instead,  forcing the script to  take parent calculated
115      // value later
116      if ($code == CSS_FONT_SIZE) {
117        $value =& Value::fromData(1, UNIT_EM);
118        return $value;
119      };
120    };
121
122    $null = null;
123    return $null;
124  }
125
126  function get_propertyOnLevel($code, $level) {
127    return $this->_state[$level][$code];
128  }
129
130  /**
131   * Optimization notice: this function is called very often,
132   * so even a slight overhead for the 'getState() and CSS::get_handler
133   * accumulates in a significiant processing delay.
134   *
135   * getState was replaced with direct $this->_state[0] access,
136   * get_handler call results are cached in static var
137   */
138  function &get_property($code) {
139    static $cache = array();
140    if (!isset($cache[$code])) {
141      $cache[$code] =& CSS::get_handler($code);
142    };
143    $value =& $cache[$code]->get($this->_state[0]);
144    return $value;
145  }
146
147  function get_propertyDefaultFlag($code) {
148    return $this->_stateDefaultFlags[0][$code];
149  }
150
151  function set_property_on_level($code, $level, $value) {
152    $this->_state[$level][$code] = $value;
153  }
154
155  function set_propertyDefault($code, $value) {
156    $state =& $this->getState();
157    $state[$code] = $value;
158  }
159
160  /**
161   * see get_property for optimization description
162   */
163  function set_property($code, $value) {
164    $this->set_propertyDefault($code, $value);
165
166    static $cache = array();
167    if (!isset($cache[$code])) {
168      $cache[$code] =& CSS::get_handler($code);
169    };
170
171    $cache[$code]->clearDefaultFlags($this);
172  }
173
174  function set_propertyDefaultFlag($code, $value) {
175    $state_flags =& $this->getStateDefaultFlags();
176    $state_flags[$code] = $value;
177  }
178
179  function getBaseFontSize() {
180    return $this->_baseFontSize[0];
181  }
182}
183
184?>