```/* <![CDATA[ */
function get_sym_list(){return [["Variable","xv",[["constant",47],["max",49],["min",48]]],["Class","xc",[["HCConstraint",46]]],["Function","xf",[["HCConstraint",178],["_fix_value",86],["applicable",51],["applicable_value",76],["apply",200],["apply_max",192],["apply_min",184],["create",136],["is_min_null",215],["is_null",223],["merge_height_constraint",13]]]];} /* ]]> */1<?php
2// Height constraint "merging" function.
3//
4// Constraints have the following precedece:
5// 1. constant constraint
6// 2. diapason constraint
7// 3. no constraint
8//
9// If both constraints are constant, the first one is choosen;
10//
11// If both constraints are diapason constraints the first one is choosen
12//
13function merge_height_constraint(\$hc1, \$hc2) {
14  // First constraint is constant; return this, as second constraint
15  // will never override it
16  if (!is_null(\$hc1->constant)) { return \$hc1; };
17
18  // Second constraint is constant; first is not constant;
19  // return second, as it is more important
20  if (!is_null(\$hc2->constant)) { return \$hc2; };
21
22  // Ok, both constraints are not constant. Check if there's any diapason
23  // constraints
24
25  // Second constraint is free constraint, return first one, as
26  // if it is a non-free it should have precedence, otherwise
27  // it will be free constraint too
28  if (is_null(\$hc2->min) && is_null(\$hc2->max)) { return \$hc1; };
29
30  // The same rule applied if the first constraint is free constraint
31  if (is_null(\$hc1->min) && is_null(\$hc1->max)) { return \$hc2; };
32
33  // If we got here it means both constraints are diapason constraints.
34  return \$hc1;
35}
36
37// Height constraint class
38//
39// Height could be constrained as a percentage of the parent height OR
40// as a constant value. Note that in most cases percentage constraint
41// REQUIRE parent height to be constrained.
42//
43// Note that constraint can be given as a diapason from min to max height
44// It is applied only of no strict height constraint is given
45//
46class HCConstraint {
47  var \$constant;
48  var \$min;
49  var \$max;
50
51  function applicable(&\$box) {
52    if (!is_null(\$this->constant)) {
53      return \$this->applicable_value(\$this->constant, \$box);
54    }
55
56    \$applicable_min = false;
57    if (!is_null(\$this->min)) {
58      \$applicable_min = \$this->applicable_value(\$this->min, \$box);
59    };
60
61    \$applicable_max = false;
62    if (!is_null(\$this->max)) {
63      \$applicable_max = \$this->applicable_value(\$this->max, \$box);
64    };
65
66    return \$applicable_min || \$applicable_max;
67  }
68
69  /**
70   * Since we decided to calculate percentage constraints of the top-level boxes using
71   * the page height as the basis, all height constraint values will be applicable.
72   *
73   * In older version, percentage height constraints on top-level boxes were silently ignored and
74   * height was determined by box content
75   */
76  function applicable_value(\$value, &\$box) {
77    return true;
78
79    // Constant constraints always applicable
80//     if (!\$value[1]) { return true; };
81
82//     if (!\$box->parent) { return false; };
83//     return \$box->parent->_height_constraint->applicable(\$box->parent);
84  }
85
86  function _fix_value(\$value, &\$box, \$default, \$no_table_recursion) {
87    // A percentage or immediate value?
88    if (\$value[1]) {
89      // CSS 2.1: The percentage  is calculated with respect to the height of the generated box's containing block.
90      // If the height of the containing  block is not specified explicitly (i.e., it  depends on  content height),
91      // and this  element is  not absolutely positioned, the value is interpreted like 'auto'.
92
93      /**
94       * Check if parent exists. If there's no parent, calculate percentage relatively to the page
95       * height (excluding top/bottom margins, of course)
96       */
97      if (!isset(\$box->parent) || !\$box->parent) {
98        global \$g_media;
99        return mm2pt(\$g_media->real_height()) * \$value[0] / 100;
100      }
101
102      if (!isset(\$box->parent->parent) || !\$box->parent->parent) {
103        global \$g_media;
104        return mm2pt(\$g_media->real_height()) * \$value[0] / 100;
105      }
106
107//       if (!isset(\$box->parent)) { return null; }
108//       if (!\$box->parent) { return null; }
109
110      // if parent does not have constrained height, return null - no height constraint can be applied
111      // Table cells should be processed separately
112      if (!\$box->parent->isCell() &&
113          is_null(\$box->parent->_height_constraint->constant) &&
114          is_null(\$box->parent->_height_constraint->min) &&
115          is_null(\$box->parent->_height_constraint->max)) {
116        return \$default;
117      };
118
119      if (\$box->parent->isCell()) {
120        if (!\$no_table_recursion) {
121          \$rhc = \$box->parent->parent->get_rhc(\$box->parent->row);
122          if (\$rhc->is_null()) { return \$default; };
123          return \$rhc->apply(\$box->parent->get_height(), \$box, true) * \$value[0] / 100;
124        } else {
125          return \$box->parent->parent->get_height() * \$value[0] / 100;
126        };
127      };
128
129      return \$box->parent->get_height() * \$value[0] / 100;
130    } else {
131      // Immediate
132      return \$value[0];
133    }
134  }
135
136  function &create(&\$box) {
137    // Determine if there's constant restriction
138    \$value = \$box->get_css_property(CSS_HEIGHT);
139
140    if (\$value->isAuto(\$value)) {
141      \$constant = null;
142    } elseif (\$value->isPercentage()) {
143      \$constant = array(\$value->getPercentage(), true);
144    } else {
145      \$constant = array(\$value->getPoints(), false);
146    };
147
148    // Determine if there's min restriction
149    \$value = \$box->get_css_property(CSS_MIN_HEIGHT);
150    if (\$value->isAuto(\$value)) {
151      \$min = null;
152    } elseif (\$value->isPercentage()) {
153      \$min = array(\$value->getPercentage(), true);
154    } else {
155      \$min = array(\$value->getPoints(), false);
156    };
157
158    // Determine if there's max restriction
159    \$value = \$box->get_css_property(CSS_MAX_HEIGHT);
160    if (\$value->isAuto(\$value)) {
161      \$max = null;
162    } elseif (\$value->isPercentage()) {
163      \$max = array(\$value->getPercentage(), true);
164    } else {
165      \$max = array(\$value->getPoints(), false);
166    };
167
168    \$constraint =& new HCConstraint(\$constant, \$min, \$max);
169    return \$constraint;
170  }
171
172  // Height constraint constructor
173  //
174  // @param \$constant value of constant constraint or null of none
175  // @param \$min value of minimal box height or null if none
176  // @param \$max value of maximal box height or null if none
177  //
178  function HCConstraint(\$constant, \$min, \$max) {
179    \$this->constant = \$constant;
180    \$this->min = \$min;
181    \$this->max = \$max;
182  }
183
184  function apply_min(\$value, &\$box, \$no_table_recursion) {
185    if (is_null(\$this->min)) {
186      return \$value;
187    } else {
188      return max(\$this->_fix_value(\$this->min, \$box, \$value, \$no_table_recursion), \$value);
189    }
190  }
191
192  function apply_max(\$value, &\$box, \$no_table_recursion) {
193    if (is_null(\$this->max)) {
194      return \$value;
195    } else {
196      return min(\$this->_fix_value(\$this->max, \$box, \$value, \$no_table_recursion), \$value);
197    }
198  }
199
200  function apply(\$value, &\$box, \$no_table_recursion = false) {
201    if (!is_null(\$this->constant)) {
202      \$height = \$this->_fix_value(\$this->constant, \$box, \$value, \$no_table_recursion);
203    } else {
204      \$height =  \$this->apply_min(\$this->apply_max(\$value, \$box, \$no_table_recursion), \$box, \$no_table_recursion);
205    }
206
207    // Table cells contained in tables with border-collapse: separate
208    // have padding included in the 'height' value. So, we'll need to subtract
209    // vertical-extra from the current value to get the actual content height
210    // TODO
211
212    return \$height;
213  }
214
215  function is_min_null() {
216    if (is_null(\$this->min)) {
217      return true;
218    };
219
220    return \$this->min[0] == 0;
221  }
222
223  function is_null() {
224    return
225      is_null(\$this->max) &&
226      \$this->is_min_null() &&
227      is_null(\$this->constant);
228  }
229}
230?>```