1<?php
2// $Header: /cvsroot/html2ps/html.attrs.inc.php,v 1.63 2007/03/15 18:37:32 Konstantin Exp $
3
4global $g_tag_attrs;
5$g_tag_attrs = array(
6                     /**
7                      * Attribute handlers applicable to all tags
8                      */
9                     '*'       => array(
10                                        'id'   => 'attr_id',
11                                        ),
12
13                     /**
14                      * Tag-specific attribute handlers
15                      */
16                     'a'       => array(
17                                        'href' => 'attr_href',
18                                        'name' => 'attr_name'
19                                        ),
20                     'body'    => array(
21                                        'background'   => 'attr_background',
22                                        'bgcolor'      => 'attr_bgcolor',
23                                        'dir'          => 'attr_dir',
24                                        'text'         => 'attr_body_text',
25                                        'link'         => 'attr_body_link',
26                                        'topmargin'    => 'attr_body_topmargin',
27                                        'leftmargin'   => 'attr_body_leftmargin',
28                                        'marginheight' => 'attr_body_marginheight',
29                                        'marginwidth'  => 'attr_body_marginwidth'
30                                        ),
31                     'div'     => array(
32                                        'align' => 'attr_align'
33                                        ),
34                     'font'    => array(
35                                        'size'  => 'attr_font_size',
36                                        'color' => 'attr_font_color',
37                                        'face'  => 'attr_font_face'
38                                        ),
39                     'form'    => array(
40                                          'action'  => 'attr_form_action'
41                                          ),
42                     'frame'   => array(
43                                        'frameborder'  => 'attr_frameborder',
44                                        'marginwidth'  => 'attr_iframe_marginwidth',
45                                        'marginheight' => 'attr_iframe_marginheight'
46                                        ),
47                     'frameset'=> array(
48                                        'frameborder' => 'attr_frameborder'
49                                        ),
50                     'h1'      => array(
51                                        'align' => 'attr_align'
52                                        ),
53                     'h2'      => array(
54                                        'align' => 'attr_align'
55                                        ),
56                     'h3'      => array(
57                                        'align' => 'attr_align'
58                                        ),
59                     'h4'      => array(
60                                        'align' => 'attr_align'
61                                        ),
62                     'h5'      => array(
63                                        'align' => 'attr_align'
64                                        ),
65                     'h6'      => array(
66                                        'align' => 'attr_align'
67                                        ),
68                     'hr'      => array(
69                                        'align' => 'attr_self_align',
70                                        'width' => 'attr_width',
71                                        'color' => 'attr_hr_color'
72                                        ),
73                     'input'   => array(
74                                        'name'  => 'attr_input_name',
75                                        'size'  => 'attr_input_size'
76                                        ),
77                     'iframe'  => array(
78                                        'frameborder'  => 'attr_frameborder',
79                                        'marginwidth'  => 'attr_iframe_marginwidth',
80                                        'marginheight' => 'attr_iframe_marginheight',
81                                        'height'       => 'attr_height_required',
82                                        'width'        => 'attr_width'
83                                        ),
84                     'img'     => array(
85                                        'width'  => 'attr_width',
86                                        'height' => 'attr_height_required',
87                                        'border' => 'attr_border',
88                                        'hspace' => 'attr_hspace',
89                                        'vspace' => 'attr_vspace',
90                                        'align'  => 'attr_img_align'
91                                        ),
92                     'marquee' => array(
93                                        'width'  => 'attr_width',
94                                        'height' => 'attr_height_required'
95                                        ),
96                     'object'  => array(
97                                        'width'  => 'attr_width',
98                                        'height' => 'attr_height'
99                                        ),
100                     'ol'      => array(
101                                        'start' => 'attr_start',
102                                        'type' => 'attr_ol_type'
103                                        ),
104                     'p'       => array(
105                                        'align' => 'attr_align'
106                                        ),
107                     'table'   => array(
108                                        'border'      => 'attr_table_border',
109                                        'bordercolor' => 'attr_table_bordercolor',
110                                        'align'       => 'attr_table_float_align',
111                                        'bgcolor'     => 'attr_bgcolor',
112                                        'width'       => 'attr_width',
113                                        'background'  => 'attr_background',
114                                        'height'      => 'attr_height',
115                                        'cellspacing' => 'attr_cellspacing',
116                                        'cellpadding' => 'attr_cellpadding',
117                                        'rules'       => 'attr_table_rules' // NOTE that 'rules' should appear _after_ 'border' handler!
118                                        ),
119                     'td'      => array(
120                                        'align'      => 'attr_align',
121                                        'valign'     => 'attr_valign',
122                                        'height'     => 'attr_height',
123                                        'background' => 'attr_background',
124                                        'bgcolor'    => 'attr_bgcolor',
125                                        'nowrap'     => 'attr_nowrap',
126                                        'width'      => 'attr_width'
127                                        ),
128                     'textarea'=> array(
129                                        'rows'       => 'attr_textarea_rows',
130                                        'cols'       => 'attr_textarea_cols'
131                                        ),
132                     'th'      => array(
133                                        'align'      => 'attr_align',
134                                        'valign'     => 'attr_valign',
135                                        'height'     => 'attr_height',
136                                        'background' => 'attr_background',
137                                        'bgcolor'    => 'attr_bgcolor',
138                                        'nowrap'     => 'attr_nowrap',
139                                        'width'      => 'attr_width'
140                                        ),
141                     'tr'      => array(
142                                        'align'   => 'attr_align',
143                                        'bgcolor' => 'attr_bgcolor',
144                                        'valign'  => 'attr_row_valign',
145                                        'height'  => 'attr_height'
146                                        ),
147                     'ul'      => array(
148                                        'start' => 'attr_start',
149                                        'type' => 'attr_ul_type'
150                                        )
151);
152
153
154function execute_attrs_before($root, &$pipeline) { execute_attrs($root, '_before', $pipeline); }
155function execute_attrs_after($root, &$pipeline) { execute_attrs($root, '_after', $pipeline); }
156function execute_attrs_after_styles($root, &$pipeline) { execute_attrs($root, '_after_styles', $pipeline); }
157
158function execute_attrs(&$root, $suffix, &$pipeline) {
159  global $g_tag_attrs;
160
161  foreach ($g_tag_attrs['*'] as $attr => $fun) {
162    if ($root->has_attribute($attr)) {
163      $fun = $fun.$suffix;
164      $fun($root, $pipeline);
165    };
166  };
167
168  if (array_key_exists($root->tagname(), $g_tag_attrs)) {
169    foreach ($g_tag_attrs[$root->tagname()] as $attr => $fun) {
170      if ($root->has_attribute($attr)) {
171        $fun = $fun.$suffix;
172        $fun($root, $pipeline);
173      };
174    };
175  };
176};
177
178// ========= Handlers
179
180// A NAME
181function attr_name_before(&$root, &$pipeline) {
182  $handler =& CSS::get_handler(CSS_HTML2PS_LINK_DESTINATION);
183  $handler->css($root->get_attribute('name'), $pipeline);
184}
185function attr_name_after_styles(&$root, &$pipeline) {};
186function attr_name_after(&$root, &$pipeline) {};
187
188// A ID
189function attr_id_before(&$root, &$pipeline) {
190  $handler =& CSS::get_handler(CSS_HTML2PS_LINK_DESTINATION);
191  $handler->css($root->get_attribute('id'), $pipeline);
192}
193function attr_id_after_styles(&$root, &$pipeline) {};
194function attr_id_after(&$root, &$pipeline) {};
195
196
197// A HREF
198function attr_href_before(&$root, &$pipeline) {
199  $handler =& CSS::get_handler(CSS_HTML2PS_LINK_TARGET);
200  $handler->css($root->get_attribute('href'), $pipeline);
201}
202function attr_href_after_styles(&$root, &$pipeline) {};
203function attr_href_after(&$root, &$pipeline) {};
204
205// IFRAME
206function attr_frameborder_before(&$root, &$pipeline) {
207  $css_state =& $pipeline->get_current_css_state();
208  $handler =& CSS::get_handler(CSS_BORDER);
209
210  switch ($root->get_attribute('frameborder')) {
211  case '1':
212    $handler->css('inset black 1px', $pipeline);
213    break;
214  case '0':
215    $handler->css('none', $pipeline);
216    break;
217  };
218}
219function attr_frameborder_after_styles(&$root, &$pipeline) {};
220function attr_frameborder_after(&$root, &$pipeline) {};
221
222function attr_iframe_marginheight_before(&$root, &$pipeline) {
223  $handler =& CSS::get_handler(CSS_PADDING_TOP);
224  $handler->css((int)$root->get_attribute('marginheight').'px',$pipeline);
225  $handler =& CSS::get_handler(CSS_PADDING_BOTTOM);
226  $handler->css((int)$root->get_attribute('marginheight').'px',$pipeline);
227}
228function attr_iframe_marginheight_after_styles(&$root, &$pipeline) {};
229function attr_iframe_marginheight_after(&$root, &$pipeline) {};
230
231function attr_iframe_marginwidth_before(&$root, &$pipeline) {
232  $handler =& CSS::get_handler(CSS_PADDING_RIGHT);
233  $handler->css((int)$root->get_attribute('marginwidth').'px',$pipeline);
234  $handler =& CSS::get_handler(CSS_PADDING_LEFT);
235  $handler->css((int)$root->get_attribute('marginwidth').'px',$pipeline);
236}
237function attr_iframe_marginwidth_after_styles(&$root, &$pipeline) {};
238function attr_iframe_marginwidth_after(&$root, &$pipeline) {};
239
240
241// BODY-specific
242function attr_body_text_before(&$root, &$pipeline) {
243  $handler =& CSS::get_handler(CSS_COLOR);
244  $handler->css($root->get_attribute('text'),$pipeline);
245}
246function attr_body_text_after_styles(&$root, &$pipeline) {};
247function attr_body_text_after(&$root, &$pipeline) {};
248
249function attr_body_link_before(&$root, &$pipeline) {
250  $color = $root->get_attribute('link');
251
252  // -1000 means priority modifier; so, any real CSS rule will have more priority than
253  // this fake rule
254
255  $collection = new CSSPropertyCollection();
256  $collection->add_property(CSSPropertyDeclaration::create(CSS_COLOR, $color, $pipeline));
257  $rule = array(array(SELECTOR_SEQUENCE, array(array(SELECTOR_TAG, 'a'),
258                                               array(SELECTOR_PSEUDOCLASS_LINK_LOW_PRIORITY))),
259                $collection,
260                '',
261                -1000);
262
263  $css =& $pipeline->get_current_css();
264  $css->add_rule($rule, $pipeline);
265}
266function attr_body_link_after_styles(&$root, &$pipeline) {};
267function attr_body_link_after(&$root, &$pipeline) {};
268
269function attr_body_topmargin_before(&$root, &$pipeline) {
270  $handler =& CSS::get_handler(CSS_MARGIN_TOP);
271  $handler->css((int)$root->get_attribute('topmargin').'px',$pipeline);
272}
273function attr_body_topmargin_after_styles(&$root, &$pipeline) {};
274function attr_body_topmargin_after(&$root, &$pipeline) {};
275
276function attr_body_leftmargin_before(&$root, &$pipeline) {
277  $handler =& CSS::get_handler(CSS_MARGIN_LEFT);
278  $handler->css((int)$root->get_attribute('leftmargin').'px',$pipeline);
279}
280function attr_body_leftmargin_after_styles(&$root, &$pipeline) {};
281function attr_body_leftmargin_after(&$root, &$pipeline) {};
282
283function attr_body_marginheight_before(&$root, &$pipeline) {
284  $css_state =& $pipeline->get_current_css_state();
285
286  $h_top    =& CSS::get_handler(CSS_MARGIN_TOP);
287  $h_bottom =& CSS::get_handler(CSS_MARGIN_BOTTOM);
288
289  $top       = $h_top->get($css_state->getState());
290
291  $h_bottom->css(((int)$root->get_attribute('marginheight') - $top->value).'px',$pipeline);
292}
293function attr_body_marginheight_after_styles(&$root, &$pipeline) {};
294function attr_body_marginheight_after(&$root, &$pipeline) {};
295
296function attr_body_marginwidth_before(&$root, &$pipeline) {
297  $css_state =& $pipeline->get_current_css_state();
298
299  $h_left  =& CSS::get_handler(CSS_MARGIN_LEFT);
300  $h_right =& CSS::get_handler(CSS_MARGIN_RIGHT);
301
302  $left = $h_left->get($css_state->getState());
303
304  $h_right->css(((int)$root->get_attribute('marginwidth') - $left->value).'px',$pipeline);
305}
306function attr_body_marginwidth_after_styles(&$root, &$pipeline) {};
307function attr_body_marginwidth_after(&$root, &$pipeline) {};
308
309// === nowrap
310function attr_nowrap_before(&$root, &$pipeline) {
311  $css_state =& $pipeline->get_current_css_state();
312  $css_state->set_property(CSS_HTML2PS_NOWRAP, NOWRAP_NOWRAP);
313}
314
315function attr_nowrap_after_styles(&$root, &$pipeline) {}
316function attr_nowrap_after(&$root, &$pipeline) {}
317
318// === hspace
319
320function attr_hspace_before(&$root, &$pipeline) {
321  $handler =& CSS::get_handler(CSS_PADDING_LEFT);
322  $handler->css((int)$root->get_attribute('hspace').'px',$pipeline);
323  $handler =& CSS::get_handler(CSS_PADDING_RIGHT);
324  $handler->css((int)$root->get_attribute('hspace').'px',$pipeline);
325}
326
327function attr_hspace_after_styles(&$root, &$pipeline) {}
328
329function attr_hspace_after(&$root, &$pipeline) {}
330
331// === vspace
332
333function attr_vspace_before(&$root, &$pipeline) {
334  $handler =& CSS::get_handler(CSS_PADDING_TOP);
335  $handler->css((int)$root->get_attribute('vspace').'px',$pipeline);
336  $handler =& CSS::get_handler(CSS_PADDING_BOTTOM);
337  $handler->css((int)$root->get_attribute('vspace').'px',$pipeline);
338}
339
340function attr_vspace_after_styles(&$root, &$pipeline) {}
341function attr_vspace_after(&$root, &$pipeline) {}
342
343// === background
344
345function attr_background_before(&$root, &$pipeline) {
346  $handler =& CSS::get_handler(CSS_BACKGROUND_IMAGE);
347  $handler->css('url('.$root->get_attribute('background').')',$pipeline);
348}
349function attr_background_after_styles(&$root, &$pipeline) {}
350function attr_background_after(&$root, &$pipeline) {}
351
352// === align
353
354function attr_table_float_align_before(&$root, &$pipeline) {}
355function attr_table_float_align_after_styles(&$root, &$pipeline) {
356  if ($root->get_attribute('align') === 'center') {
357    $margin_left =& CSS::get_handler(CSS_MARGIN_LEFT);
358    $margin_left->css('auto',$pipeline);
359
360    $margin_right =& CSS::get_handler(CSS_MARGIN_RIGHT);
361    $margin_right->css('auto',$pipeline);
362  } else {
363    $float =& CSS::get_handler(CSS_FLOAT);
364    $css_state =& $pipeline->get_current_css_state();
365    $float->replace($float->parse($root->get_attribute('align')),
366                    $css_state);
367  };
368}
369function attr_table_float_align_after(&$root, &$pipeline) {}
370
371function attr_img_align_before(&$root, &$pipeline) {
372  if (preg_match('/left|right/', $root->get_attribute('align'))) {
373    $float =& CSS::get_handler(CSS_FLOAT);
374    $css_state =& $pipeline->get_current_css_state();
375    $float->replace($float->parse($root->get_attribute('align')),
376                    $css_state);
377  } else {
378    $handler =& CSS::get_handler(CSS_VERTICAL_ALIGN);
379    $css_state =& $pipeline->get_current_css_state();
380    $handler->replace($handler->parse($root->get_attribute('align')),
381                      $css_state);
382  };
383}
384function attr_img_align_after_styles(&$root, &$pipeline) {}
385function attr_img_align_after(&$root, &$pipeline) {}
386
387function attr_self_align_before(&$root, &$pipeline) {
388  $handler =& CSS::get_handler(CSS_HTML2PS_LOCALALIGN);
389  $css_state =& $pipeline->get_current_css_state();
390
391  switch ($root->get_attribute('align')) {
392  case 'left':
393    $handler->replace(LA_LEFT,
394                      $css_state);
395    break;
396  case 'center':
397    $handler->replace(LA_CENTER,
398                      $css_state);
399    break;
400  case 'right':
401    $handler->replace(LA_RIGHT,
402                      $css_state);
403    break;
404  default:
405    $handler->replace(LA_LEFT,
406                      $css_state);
407    break;
408  };
409}
410
411function attr_self_align_after_styles(&$root, &$pipeline) {}
412function attr_self_align_after(&$root, &$pipeline) {}
413
414// === bordercolor
415
416function attr_table_bordercolor_before(&$root, &$pipeline) {
417  $color = parse_color_declaration($root->get_attribute('bordercolor'));
418
419  $css_state =& $pipeline->get_current_css_state();
420  $border =& $css_state->get_property(CSS_HTML2PS_TABLE_BORDER);
421  $border =& $border->copy();
422
423  $border->left->color   = $color;
424  $border->right->color  = $color;
425  $border->top->color    = $color;
426  $border->bottom->color = $color;
427
428//   $css_state->pushState();
429//   $css_state->set_property(CSS_HTML2PS_TABLE_BORDER, $border);
430
431//   $css_state->pushState();
432//   $css_state->set_property(CSS_BORDER, $border);
433}
434
435function attr_table_bordercolor_after_styles(&$root, &$pipeline) {
436//   $css_state =& $pipeline->get_current_css_state();
437//   $css_state->popState();
438}
439
440function attr_table_bordercolor_after(&$root, &$pipeline) {
441//   $css_state =& $pipeline->get_current_css_state();
442//   $css_state->popState();
443}
444
445// === border
446
447function attr_border_before(&$root, &$pipeline) {
448  $width = (int)$root->get_attribute('border');
449
450  $css_state =& $pipeline->get_current_css_state();
451  $border =& $css_state->get_property(CSS_BORDER);
452  $border =& $border->copy();
453
454  $border->left->width   = Value::fromData($width, UNIT_PX);
455  $border->right->width  = Value::fromData($width, 'px');
456  $border->top->width    = Value::fromData($width, 'px');
457  $border->bottom->width = Value::fromData($width, 'px');
458
459  $border->left->style   = BS_SOLID;
460  $border->right->style  = BS_SOLID;
461  $border->top->style    = BS_SOLID;
462  $border->bottom->style = BS_SOLID;
463
464  $css_state->set_property(CSS_BORDER, $border);
465}
466
467function attr_border_after_styles(&$root, &$pipeline) {}
468function attr_border_after(&$root, &$pipeline) {}
469
470// === rules (table)
471
472function attr_table_rules_before(&$root, &$pipeline) {
473  /**
474   * Handle 'rules' attribute
475   */
476  $rules = $root->get_attribute('rules');
477
478  $css_state =& $pipeline->get_current_css_state();
479  $border = $css_state->get_property(CSS_HTML2PS_TABLE_BORDER);
480
481  switch ($rules) {
482  case 'none':
483    $border->left->style   = BS_NONE;
484    $border->right->style  = BS_NONE;
485    $border->top->style    = BS_NONE;
486    $border->bottom->style = BS_NONE;
487    break;
488  case 'groups':
489    // Not supported
490    break;
491  case 'rows':
492    $border->left->style   = BS_NONE;
493    $border->right->style  = BS_NONE;
494    break;
495  case 'cols':
496    $border->top->style    = BS_NONE;
497    $border->bottom->style = BS_NONE;
498    break;
499  case 'all':
500    break;
501  };
502
503  $css_state->set_property(CSS_HTML2PS_TABLE_BORDER, $border);
504}
505
506function attr_table_rules_after_styles(&$root, &$pipeline) {}
507function attr_table_rules_after(&$root, &$pipeline) {}
508
509// === border (table)
510
511function attr_table_border_before(&$root, &$pipeline) {
512  $width = (int)$root->get_attribute('border');
513
514  $css_state =& $pipeline->get_current_css_state();
515  $border =& $css_state->get_property(CSS_HTML2PS_TABLE_BORDER);
516  $border =& $border->copy();
517
518  $border->left->width   = Value::fromData($width, UNIT_PX);
519  $border->right->width  = Value::fromData($width, UNIT_PX);
520  $border->top->width    = Value::fromData($width, UNIT_PX);
521  $border->bottom->width = Value::fromData($width, UNIT_PX);
522
523  $border->left->style   = BS_SOLID;
524  $border->right->style  = BS_SOLID;
525  $border->top->style    = BS_SOLID;
526  $border->bottom->style = BS_SOLID;
527
528  $css_state->set_property(CSS_BORDER, $border);
529
530  $css_state->pushState();
531  $border =& $border->copy();
532  $css_state->set_property(CSS_HTML2PS_TABLE_BORDER, $border);
533}
534
535function attr_table_border_after_styles(&$root, &$pipeline) {}
536
537function attr_table_border_after(&$root, &$pipeline) {
538  $css_state =& $pipeline->get_current_css_state();
539  $css_state->popState();
540}
541
542// === dir
543function attr_dir_before(&$root, &$pipeline) {
544  $handler =& CSS::get_handler(CSS_TEXT_ALIGN);
545  switch (strtolower($root->get_attribute('dir'))) {
546  case 'ltr':
547    $handler->css('left',$pipeline);
548    return;
549  case 'rtl':
550    $handler->css('right',$pipeline);
551    return;
552  };
553}
554
555function attr_dir_after_styles(&$root, &$pipeline) {}
556function attr_dir_after(&$root, &$pipeline) {}
557
558// === align
559function attr_align_before(&$root, &$pipeline) {
560  $handler =& CSS::get_handler(CSS_TEXT_ALIGN);
561  $handler->css($root->get_attribute('align'),$pipeline);
562
563  $handler =& CSS::get_handler(CSS_HTML2PS_ALIGN);
564  $handler->css($root->get_attribute('align'),$pipeline);
565}
566
567function attr_align_after_styles(&$root, &$pipeline) {}
568
569function attr_align_after(&$root, &$pipeline) {}
570
571// valign
572// 'valign' attribute value for table rows is inherited
573function attr_row_valign_before(&$root, &$pipeline) {
574  $handler =& CSS::get_handler(CSS_VERTICAL_ALIGN);
575  $handler->css($root->get_attribute('valign'),$pipeline);
576}
577function attr_row_valign_after_styles(&$root, &$pipeline) {}
578function attr_row_valign_after(&$root, &$pipeline) {}
579
580// 'valign' attribute value for boxes other than table rows is not inherited
581function attr_valign_before(&$root, &$pipeline) {
582  $handler =& CSS::get_handler(CSS_VERTICAL_ALIGN);
583  $handler->css($root->get_attribute('valign'),
584                $pipeline);
585}
586
587function attr_valign_after_styles(&$root, &$pipeline) {}
588function attr_valign_after(&$root, &$pipeline) {}
589
590// bgcolor
591
592function attr_bgcolor_before(&$root, &$pipeline) {
593  $handler =& CSS::get_handler(CSS_BACKGROUND_COLOR);
594  $handler->css($root->get_attribute('bgcolor'), $pipeline);
595}
596function attr_bgcolor_after_styles(&$root, &$pipeline) {}
597function attr_bgcolor_after(&$root, &$pipeline) {}
598
599// width
600
601function attr_width_before(&$root, &$pipeline) {
602  $width =& CSS::get_handler(CSS_WIDTH);
603
604  $value = $root->get_attribute('width');
605  if (preg_match('/^\d+$/', $value)) { $value .= 'px'; };
606
607  $width->css($value,$pipeline);
608}
609
610function attr_width_after_styles(&$root, &$pipeline) {}
611function attr_width_after(&$root, &$pipeline) {}
612
613// height
614
615// Difference between 'attr_height' and 'attr_height_required':
616// attr_height sets the minimal box height so that is cal be expanded by it content;
617// a good example is table rows and cells; on the other side, attr_height_required
618// sets the fixed box height - it is useful for boxes which content height can be greater
619// that box height - marquee or iframe, for example
620
621function attr_height_required_before(&$root, &$pipeline) {
622  $handler =& CSS::get_handler(CSS_HEIGHT);
623
624  $value = $root->get_attribute('height');
625  if (preg_match('/^\d+$/', $value)) { $value .= 'px'; };
626  $handler->css($value,$pipeline);
627}
628
629function attr_height_required_after_styles(&$root, &$pipeline) {}
630
631function attr_height_required_after(&$root, &$pipeline) {}
632
633function attr_height_before(&$root, &$pipeline) {
634  $handler =& CSS::get_handler(CSS_MIN_HEIGHT);
635
636  $value = $root->get_attribute('height');
637  if (preg_match('/^\d+$/', $value)) { $value .= 'px'; };
638  $handler->css($value,$pipeline);
639}
640
641function attr_height_after_styles(&$root, &$pipeline) {}
642function attr_height_after(&$root, &$pipeline) {}
643
644// FONT attributes
645function attr_font_size_before(&$root, &$pipeline) {
646  $size = $root->get_attribute('size');
647
648  /**
649   * Check if attribute value is empty; no actions will be taken in this case
650   */
651  if ($size == '') { return; };
652
653  if ($size{0} == '-') {
654    $koeff = 1;
655    $repeats = (int)substr($size,1);
656    for ($i=0; $i<$repeats; $i++) {
657      $koeff *= 1/1.2;
658    };
659    $newsize = sprintf('%.2fem', round($koeff, 2));
660  } else if ($size{0} == '+') {
661    $koeff = 1;
662    $repeats = (int)substr($size,1);
663    for ($i=0; $i<$repeats; $i++) {
664      $koeff *= 1.2;
665    };
666    $newsize = sprintf('%.2fem', round($koeff, 2));
667  } else {
668    switch ((int)$size) {
669    case 1:
670      $newsize = BASE_FONT_SIZE_PT/1.2/1.2;
671      break;
672    case 2:
673      $newsize = BASE_FONT_SIZE_PT/1.2;
674      break;
675    case 3:
676      $newsize = BASE_FONT_SIZE_PT;
677      break;
678    case 4:
679      $newsize = BASE_FONT_SIZE_PT*1.2;
680      break;
681    case 5:
682      $newsize = BASE_FONT_SIZE_PT*1.2*1.2;
683      break;
684    case 6:
685      $newsize = BASE_FONT_SIZE_PT*1.2*1.2*1.2;
686      break;
687    case 7:
688      $newsize = BASE_FONT_SIZE_PT*1.2*1.2*1.2*1.2;
689      break;
690    default:
691      $newsize = BASE_FONT_SIZE_PT;
692      break;
693    };
694    $newsize = $newsize . 'pt';
695  };
696
697  $handler =& CSS::get_handler(CSS_FONT_SIZE);
698  $handler->css($newsize, $pipeline);
699}
700function attr_font_size_after_styles(&$root, &$pipeline) {}
701function attr_font_size_after(&$root, &$pipeline) {}
702
703function attr_font_color_before(&$root, &$pipeline) {
704  $handler =& CSS::get_handler(CSS_COLOR);
705  $handler->css($root->get_attribute('color'),$pipeline);
706}
707function attr_font_color_after_styles(&$root, &$pipeline) {}
708function attr_font_color_after(&$root, &$pipeline) {}
709
710function attr_font_face_before(&$root, &$pipeline) {
711  $handler =& CSS::get_handler(CSS_FONT_FAMILY);
712  $handler->css($root->get_attribute('face'), $pipeline);
713}
714function attr_font_face_after_styles(&$root, &$pipeline) {}
715function attr_font_face_after(&$root, &$pipeline) {}
716
717function attr_form_action_before(&$root, &$pipeline) {
718  $handler =& CSS::get_handler(CSS_HTML2PS_FORM_ACTION);
719  if ($root->has_attribute('action')) {
720    $handler->css($pipeline->guess_url($root->get_attribute('action')),$pipeline);
721  } else {
722    $handler->css(null,$pipeline);
723  };
724}
725function attr_form_action_after_styles(&$root, &$pipeline) {}
726function attr_form_action_after(&$root, &$pipeline) {}
727
728function attr_input_name_before(&$root, &$pipeline) {
729  $handler =& CSS::get_handler(CSS_HTML2PS_FORM_RADIOGROUP);
730  if ($root->has_attribute('name')) {
731    $handler->css($root->get_attribute('name'),$pipeline);
732  };
733}
734function attr_input_name_after_styles(&$root, &$pipeline) {}
735function attr_input_name_after(&$root, &$pipeline) {}
736
737function attr_input_size_before(&$root, &$pipeline) {
738  // Check if current node has 'size' attribute
739  if (!$root->has_attribute('size')) {
740    return;
741  };
742  $size = $root->get_attribute('size');
743
744  // Get the exact type of the input node, as 'size' has
745  // different meanings for different input types
746  $type = 'text';
747  if ($root->has_attribute('type')) {
748    $type = strtolower($root->get_attribute('type'));
749  };
750
751  switch ($type) {
752  case 'text':
753  case 'password':
754    $handler =& CSS::get_handler(CSS_WIDTH);
755    $width = sprintf('%.2fem', INPUT_SIZE_BASE_EM + $size*INPUT_SIZE_EM_KOEFF);
756    $handler->css($width, $pipeline);
757    break;
758  };
759};
760
761function attr_input_size_after_styles(&$root, &$pipeline) {}
762function attr_input_size_after(&$root, &$pipeline) {}
763
764// TABLE
765
766function attr_cellspacing_before(&$root, &$pipeline) {
767  $css_state =& $pipeline->get_current_css_state();
768  $handler =& CSS::get_handler(CSS_HTML2PS_CELLSPACING);
769  $handler->replace(Value::fromData((int)$root->get_attribute('cellspacing'), UNIT_PX),
770                    $css_state);
771}
772function attr_cellspacing_after_styles(&$root, &$pipeline) {}
773function attr_cellspacing_after(&$root, &$pipeline) {}
774
775function attr_cellpadding_before(&$root, &$pipeline) {
776  $css_state =& $pipeline->get_current_css_state();
777  $handler =& CSS::get_handler(CSS_HTML2PS_CELLPADDING);
778  $handler->replace(Value::fromData((int)$root->get_attribute('cellpadding'), UNIT_PX),
779                    $css_state);
780}
781function attr_cellpadding_after_styles(&$root, &$pipeline) {}
782function attr_cellpadding_after(&$root, &$pipeline) {}
783
784// UL/OL 'start' attribute
785function attr_start_before(&$root, &$pipeline) {
786  $handler =& CSS::get_handler(CSS_HTML2PS_LIST_COUNTER);
787  $css_state =& $pipeline->get_current_css_state();
788  $handler->replace((int)$root->get_attribute('start'),
789                    $css_state);
790}
791function attr_start_after_styles(&$root, &$pipeline) {}
792function attr_start_after(&$root, &$pipeline) {}
793
794// UL 'type' attribute
795//
796// For  the UL  element, possible  values for  the type  attribute are
797// disc, square, and circle. The default value depends on the level of
798// nesting of the current list. These values are case-insensitive.
799//
800// How each value is presented  depends on the user agent. User agents
801// should attempt to  present a "disc" as a  small filled-in circle, a
802// "circle"  as a  small circle  outline, and  a "square"  as  a small
803// square outline.
804//
805function attr_ul_type_before(&$root, &$pipeline) {
806  $type = (string)$root->get_attribute('type');
807  $handler =& CSS::get_handler(CSS_LIST_STYLE_TYPE);
808  $css_state =& $pipeline->get_current_css_state();
809
810  switch (strtolower($type)) {
811  case 'disc':
812    $handler->replace(LST_DISC, $css_state);
813    break;
814  case 'circle':
815    $handler->replace(LST_CIRCLE, $css_state);
816    break;
817  case 'square':
818    $handler->replace(LST_SQUARE, $css_state);
819    break;
820  };
821}
822function attr_ul_type_after_styles(&$root, &$pipeline) {}
823function attr_ul_type_after(&$root, &$pipeline) {}
824
825// OL 'type' attribute
826//
827// For the OL element, possible values for the type attribute are summarized in the table below (they are case-sensitive):
828// Type 	Numbering style
829// 1 	arabic numbers 	1, 2, 3, ...
830// a 	lower alpha 	a, b, c, ...
831// A 	upper alpha 	A, B, C, ...
832// i 	lower roman 	i, ii, iii, ...
833// I 	upper roman 	I, II, III, ...
834//
835function attr_ol_type_before(&$root, &$pipeline) {
836  $type = (string)$root->get_attribute('type');
837  $handler =& CSS::get_handler(CSS_LIST_STYLE_TYPE);
838  $css_state =& $pipeline->get_current_css_state();
839
840  switch ($type) {
841  case '1':
842    $handler->replace(LST_DECIMAL, $css_state);
843    break;
844  case 'a':
845    $handler->replace(LST_LOWER_LATIN, $css_state);
846    break;
847  case 'A':
848    $handler->replace(LST_UPPER_LATIN, $css_state);
849    break;
850  case 'i':
851    $handler->replace(LST_LOWER_ROMAN, $css_state);
852    break;
853  case 'I':
854    $handler->replace(LST_UPPER_ROMAN, $css_state);
855    break;
856  };
857}
858function attr_ol_type_after_styles(&$root, &$pipeline) {}
859function attr_ol_type_after(&$root, &$pipeline) {}
860
861// Textarea
862
863function attr_textarea_rows_before(&$root, &$pipeline) {
864  $handler =& CSS::get_handler(CSS_HEIGHT);
865  $handler->css(sprintf('%dem', (int)$root->get_attribute('rows')*1.40),$pipeline);
866}
867function attr_textarea_rows_after_styles(&$root, &$pipeline) {}
868function attr_textarea_rows_after(&$root, &$pipeline) {}
869
870function attr_textarea_cols_before(&$root, &$pipeline) {
871  $handler =& CSS::get_handler(CSS_WIDTH);
872  $handler->css(sprintf('%dem', (int)$root->get_attribute('cols')*0.675),$pipeline);
873}
874function attr_textarea_cols_after_styles(&$root, &$pipeline) {}
875function attr_textarea_cols_after(&$root, &$pipeline) {}
876
877/**
878 * HR-specific attributes
879 */
880function attr_hr_color_before(&$root, &$pipeline) {
881  $handler =& CSS::get_handler(CSS_BORDER_COLOR);
882  $handler->css($root->get_attribute('color'), $pipeline);
883}
884function attr_hr_color_after_styles(&$root, &$pipeline) {}
885function attr_hr_color_after(&$root, &$pipeline) {}
886
887
888?>