Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
require_once(HTML2PS_DIR.'css.constants.inc.php');
4
 
5
class CSSPageSelector {
6
  var $_type;
7
 
8
  function CSSPageSelector($type) {
9
    $this->set_type($type);
10
  }
11
 
12
  function get_type() {
13
    return $this->_type;
14
  }
15
 
16
  function set_type($type) {
17
    $this->_type = $type;
18
  }
19
}
20
 
21
class CSSPageSelectorAll extends CSSPageSelector {
22
  function CSSPageSelectorAll() {
23
    $this->CSSPageSelector(CSS_PAGE_SELECTOR_ALL);
24
  }
25
}
26
 
27
class CSSPageSelectorNamed extends CSSPageSelector  {
28
  var $_name;
29
 
30
  function CSSPageSelectorNamed($name) {
31
    $this->CSSPageSelector(CSS_PAGE_SELECTOR_NAMED);
32
    $this->set_name($name);
33
  }
34
 
35
  function get_name() {
36
    return $this->_name;
37
  }
38
 
39
  function set_name($name) {
40
    $this->_name = $name;
41
  }
42
}
43
 
44
class CSSPageSelectorFirst extends CSSPageSelector {
45
  function CSSPageSelectorFirst() {
46
    $this->CSSPageSelector(CSS_PAGE_SELECTOR_FIRST);
47
  }
48
}
49
 
50
class CSSPageSelectorLeft extends CSSPageSelector {
51
  function CSSPageSelectorLeft() {
52
    $this->CSSPageSelector(CSS_PAGE_SELECTOR_LEFT);
53
  }
54
}
55
 
56
class CSSPageSelectorRight extends CSSPageSelector {
57
  function CSSPageSelectorRight() {
58
    $this->CSSPageSelector(CSS_PAGE_SELECTOR_RIGHT);
59
  }
60
}
61
 
62
class CSSAtRulePage {
63
  var $selector;
64
  var $margin_boxes;
65
  var $css;
66
 
67
  function CSSAtRulePage($selector, &$pipeline) {
68
    $this->selector = $selector;
69
    $this->margin_boxes = array();
70
 
71
    $this->css =& new CSSPropertyCollection();
72
  }
73
 
74
  function &getSelector() {
75
    return $this->selector;
76
  }
77
 
78
  function getAtRuleMarginBoxes() {
79
    return $this->margin_boxes;
80
  }
81
 
82
  /**
83
   * Note that only one margin box rule could be added; subsequent adds
84
   * will overwrite existing data
85
   */
86
  function addAtRuleMarginBox($rule) {
87
    $this->margin_boxes[$rule->getSelector()] = $rule;
88
  }
89
 
90
  function setCSSProperty($property) {
91
    $this->css->add_property($property);
92
  }
93
}
94
 
95
class CSSAtRuleMarginBox {
96
  var $selector;
97
  var $css;
98
 
99
  /**
100
   * TODO: CSS_TEXT_ALIGN should get  top/bottom values by default for
101
   * left-top, left-bottom, right-top and right-bottom boxes
102
   */
103
  function CSSAtRuleMarginBox($selector, &$pipeline) {
104
    $this->selector = $selector;
105
 
106
    $css = "-html2ps-html-content: ''; content: ''; width: auto; height: auto; margin: 0; border: none; padding: 0; font: auto;";
107
    $css = $css . $this->_getCSSDefaults($selector);
108
 
109
    $this->css = new CSSRule(array(
110
                                   array(SELECTOR_ANY),
111
                                   parse_css_properties($css, $null),
112
                                   '',
113
                                   null),
114
                             $pipeline);
115
  }
116
 
117
  function getSelector() {
118
    return $this->selector;
119
  }
120
 
121
  function _getCSSDefaults($selector) {
122
    $text_align_handler =& CSS::get_handler(CSS_TEXT_ALIGN);
123
    $vertical_align_handler =& CSS::get_handler(CSS_VERTICAL_ALIGN);
124
 
125
    switch ($selector) {
126
    case CSS_MARGIN_BOX_SELECTOR_TOP:
127
      return 'text-align: left; vertical-align: middle';
128
    case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER:
129
      return 'text-align: right; vertical-align: middle';
130
    case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT:
131
      return 'text-align: left; vertical-align: middle';
132
    case CSS_MARGIN_BOX_SELECTOR_TOP_CENTER:
133
      return 'text-align: center; vertical-align: middle';
134
    case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT:
135
      return 'text-align: right; vertical-align: middle';
136
    case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER:
137
      return 'text-align: left; vertical-align: middle';
138
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM:
139
      return 'text-align: left; vertical-align: middle';
140
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER:
141
      return 'text-align: right; vertical-align: middle';
142
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT:
143
      return 'text-align: left; vertical-align: middle';
144
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER:
145
      return 'text-align: center; vertical-align: middle';
146
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT:
147
      return 'text-align: right; vertical-align: middle';
148
    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER:
149
      return 'text-align: left; vertical-align: middle';
150
    case CSS_MARGIN_BOX_SELECTOR_LEFT_TOP:
151
      return 'text-align: center; vertical-align: top';
152
    case CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE:
153
      return 'text-align: center; vertical-align: middle';
154
    case CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM:
155
      return 'text-align: center; vertical-align: bottom';
156
    case CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP:
157
      return 'text-align: center; vertical-align: top';
158
    case CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE:
159
      return 'text-align: center; vertical-align: middle';
160
    case CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM:
161
      return 'text-align: center; vertical-align: bottom';
162
    };
163
  }
164
 
165
  function setCSSProperty($property) {
166
    $this->css->add_property($property);
167
  }
168
 
169
  function &get_css_property($code) {
170
    return $this->css->get_property($code);
171
  }
172
}
173
 
174
/**
175
 * Handle  @page rules  in  current CSS  media  As parse_css_media  is
176
 * called for  selected media  only, we can  store data to  global CSS
177
 * state - no data should be ignored
178
 *
179
 * at-page rules will be removed after parsing
180
 *
181
 * @param $css String contains raw CSS data to be processed
182
 * @return String CSS text without at-page rules
183
 */
184
function parse_css_atpage_rules($css, &$css_ruleset) {
185
  while (preg_match('/^(.*?)@page(.*)/is', $css, $matches)) {
186
    $data = $matches[2];
187
    $css = $matches[1].parse_css_atpage_rule(trim($data), $css_ruleset);
188
  };
189
  return $css;
190
}
191
 
192
function parse_css_atpage_rule($css, &$css_ruleset) {
193
  /**
194
   * Extract selector and left bracket
195
   */
196
  if (!preg_match('/^(.*?){(.*)$/is', $css, $matches)) {
197
    error_log('No selector and/or open bracket found in @page rule');
198
    return $css;
199
  };
200
  $raw_selector = trim($matches[1]);
201
  $css          = trim($matches[2]);
202
 
203
  $selector =& parse_css_atpage_selector($raw_selector);
204
  $at_rule =& new CSSAtRulePage($selector, $css_ruleset);
205
 
206
  /**
207
   * The body of @page rule may contain declaraction (detected by ';'),
208
   * margin box at-rule (detected by @top and similar tokens) or } indicating termination of
209
   * @page rule
210
   */
211
  while (preg_match('/^(.*?)(;|@|})(.*)$/is', $css, $matches)) {
212
    $raw_prefix = trim($matches[1]);
213
    $raw_token  = trim($matches[2]);
214
    $raw_suffix = trim($matches[3]);
215
 
216
    switch ($raw_token) {
217
    case ';':
218
      /**
219
       * Normal declaration (text contained in $raw_prefix
220
       */
221
      parse_css_atpage_declaration($raw_prefix, $at_rule, $css_ruleset);
222
      $css = $raw_suffix;
223
      break;
224
 
225
    case '@':
226
      /**
227
       * Margin box at-rule
228
       */
229
      $css = parse_css_atpage_margin_box($raw_suffix, $at_rule, $css_ruleset);
230
      break;
231
 
232
    case '}':
233
      /**
234
       * End-of-rule
235
       */
236
      $css_ruleset->add_at_rule_page($at_rule);
237
      return $raw_suffix;
238
    };
239
  };
240
 
241
  /**
242
   * Note that we should normally exit via '}' token handler above
243
   */
244
  error_log('No close bracket found in @page rule');
245
  $css_ruleset->add_at_rule_page($at_rule);
246
  return $css;
247
}
248
 
249
/**
250
 * Parses CSS at-page rule selector; syntax of this selector can be seen in
251
 * CSS 3 specification at http://www.w3.org/TR/css3-page/#syntax-page-selector
252
 *
253
 *
254
 */
255
function &parse_css_atpage_selector($selector) {
256
  switch ($selector) {
257
  case '':
258
    $selector =& new CSSPageSelectorAll();
259
    return $selector;
260
  case ':first':
261
    $selector =& new CSSPageSelectorFirst();
262
    return $selector;
263
  case ':left':
264
    $selector =& new CSSPageSelectorLeft();
265
    return $selector;
266
  case ':right':
267
    $selector =& new CSSPageSelectorRight();
268
    return $selector;
269
  default:
270
    if (CSS::is_identifier($selector)) {
271
      $selector =& new CSSPageSelectorNamed($selector);
272
      return $selector;
273
    } else {
274
      error_log(sprintf('Unknown page selector in @page rule: \'%s\'', $selector));
275
      $selector =& new CSSPageSelectorAll();
276
      return $selector;
277
    };
278
  };
279
}
280
 
281
function parse_css_atpage_margin_box($css, &$at_rule, &$pipeline) {
282
  if (!preg_match("/^([-\w]*)\s*{(.*)/is",$css,$matches)) {
283
    error_log("Invalid margin box at-rule format");
284
    return $css;
285
  };
286
 
287
  $raw_margin_box_selector = trim($matches[1]);
288
  $css                     = trim($matches[2]);
289
 
290
  $margin_box_selector = parse_css_atpage_margin_box_selector($raw_margin_box_selector);
291
  $at_rule_margin_box = new CSSAtRuleMarginBox($margin_box_selector, $pipeline);
292
 
293
  /**
294
   * The body of margin box at-rule may contain declaraction (detected
295
   * by ';'), or } indicating termination of at-rule
296
   */
297
  while (preg_match('/^(.*?)(;|})(.*)$/is', $css, $matches)) {
298
    $raw_prefix = trim($matches[1]);
299
    $raw_token  = trim($matches[2]);
300
    $raw_suffix = trim($matches[3]);
301
 
302
    switch ($raw_token) {
303
    case ';':
304
      /**
305
       * Normal declaration (text contained in $raw_prefix
306
       */
307
      parse_css_atpage_margin_box_declaration($raw_prefix, $at_rule_margin_box, $pipeline);
308
      $css = $raw_suffix;
309
      break;
310
 
311
    case '}':
312
      /**
313
       * End-of-rule
314
       */
315
      $at_rule->addAtRuleMarginBox($at_rule_margin_box);
316
      return $raw_suffix;
317
    };
318
  };
319
 
320
  /**
321
   * Note that we should normally exit via '}' token handler above
322
   */
323
  error_log('No close bracket found in margin box at-rule');
324
  $at_rule->addAtRuleMarginBox($at_rule_margin_box);
325
  return $css;
326
}
327
 
328
function parse_css_atpage_margin_box_selector($css) {
329
  switch ($css) {
330
  case 'top':
331
    return CSS_MARGIN_BOX_SELECTOR_TOP;
332
  case 'top-left-corner':
333
    return CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER;
334
  case 'top-left':
335
    return CSS_MARGIN_BOX_SELECTOR_TOP_LEFT;
336
  case 'top-center':
337
    return CSS_MARGIN_BOX_SELECTOR_TOP_CENTER;
338
  case 'top-right':
339
    return CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT;
340
  case 'top-right-corner':
341
    return CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER;
342
  case 'bottom':
343
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM;
344
  case 'bottom-left-corner':
345
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER;
346
  case 'bottom-left':
347
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT;
348
  case 'bottom-center':
349
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER;
350
  case 'bottom-right':
351
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT;
352
  case 'bottom-right-corner':
353
    return CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER;
354
  case 'left-top':
355
    return CSS_MARGIN_BOX_SELECTOR_LEFT_TOP;
356
  case 'left-middle':
357
    return CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE;
358
  case 'left-bottom':
359
    return CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM;
360
  case 'right-top':
361
    return CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP;
362
  case 'right-middle':
363
    return CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE;
364
  case 'right-bottom':
365
    return CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM;
366
  default:
367
    error_log(sprintf('Unrecognized margin box selector: \'%s\'', $css));
368
    return CSS_MARGIN_BOX_SELECTOR_TOP;
369
  }
370
};
371
 
372
function parse_css_atpage_declaration($css, &$at_rule, &$pipeline) {
373
  $parsed =& parse_css_property($css, $pipeline);
374
 
375
  if (!is_null($parsed)) {
376
    $properties = $parsed->getPropertiesSortedByPriority();
377
    foreach ($properties as $property) {
378
      $at_rule->setCSSProperty($property);
379
    };
380
  };
381
}
382
 
383
function parse_css_atpage_margin_box_declaration($css, &$at_rule, &$pipeline) {
384
  $parsed =& parse_css_property($css, $pipeline);
385
 
386
  if (!is_null($parsed)) {
387
    $properties = $parsed->getPropertiesSortedByPriority();
388
    foreach ($properties as $property) {
389
      $at_rule->setCSSProperty($property);
390
    };
391
  };
392
}
393
 
394
?>