Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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
//
13
function 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
//
46
class 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
?>