1<?php 2// $Header: /cvsroot/html2ps/css.font.inc.php,v 1.28 2006/11/11 13:43:52 Konstantin Exp $ 3 4require_once(HTML2PS_DIR.'value.font.class.php'); 5require_once(HTML2PS_DIR.'font.resolver.class.php'); 6require_once(HTML2PS_DIR.'font.constants.inc.php'); 7 8require_once(HTML2PS_DIR.'css.font-family.inc.php'); 9require_once(HTML2PS_DIR.'css.font-style.inc.php'); 10require_once(HTML2PS_DIR.'css.font-weight.inc.php'); 11require_once(HTML2PS_DIR.'css.font-size.inc.php'); 12require_once(HTML2PS_DIR.'css.line-height.inc.php'); 13 14require_once(HTML2PS_DIR.'value.font.class.php'); 15 16define('FONT_VALUE_STYLE',0); 17define('FONT_VALUE_WEIGHT',1); 18define('FONT_VALUE_SIZE',2); 19define('FONT_VALUE_FAMILY',3); 20 21function detect_font_value_type($value) { 22 if (preg_match("/^normal|italic|oblique$/",$value)) { return FONT_VALUE_STYLE; } 23 if (preg_match("/^normal|bold|bolder|lighter|[1-9]00$/",$value)) { return FONT_VALUE_WEIGHT; } 24 25 if (preg_match("#/#",$value)) { return FONT_VALUE_SIZE; } 26 if (preg_match("#^\d+\.?\d*%$#",$value)) { return FONT_VALUE_SIZE; } 27 if (preg_match("#^(xx-small|x-small|small|medium|large|x-large|xx-large)$#",$value)) { return FONT_VALUE_SIZE; } 28 if (preg_match("#^(larger|smaller)$#",$value)) { return FONT_VALUE_SIZE; } 29 if (preg_match("#^(\d*(.\d*)?(pt|pc|in|mm|cm|px|em|ex))$#",$value)) { return FONT_VALUE_SIZE; } 30 31 return FONT_VALUE_FAMILY; 32} 33 34// ---- 35 36class CSSFont extends CSSPropertyHandler { 37 var $_defaultValue; 38 39 function CSSFont() { 40 $this->CSSPropertyHandler(true, true); 41 42 $this->_defaultValue = null; 43 } 44 45 function default_value() { 46 if (is_null($this->_defaultValue)) { 47 $this->_defaultValue = new ValueFont; 48 49 $size_handler = CSS::get_handler(CSS_FONT_SIZE); 50 $default_size = $size_handler->default_value(); 51 52 $this->_defaultValue->size = $default_size->copy(); 53 $this->_defaultValue->weight = CSSFontWeight::default_value(); 54 $this->_defaultValue->style = CSSFontStyle::default_value(); 55 $this->_defaultValue->family = CSSFontFamily::default_value(); 56 $this->_defaultValue->line_height = CSS::getDefaultValue(CSS_LINE_HEIGHT); 57 }; 58 59 return $this->_defaultValue; 60 } 61 62 function parse($value) { 63 $font = CSS::getDefaultValue(CSS_FONT); 64 65 if ($value === 'inherit') { 66 $font->style = CSS_PROPERTY_INHERIT; 67 $font->weight = CSS_PROPERTY_INHERIT; 68 $font->size = CSS_PROPERTY_INHERIT; 69 $font->family = CSS_PROPERTY_INHERIT; 70 $font->line_height = CSS_PROPERTY_INHERIT; 71 72 return $font; 73 }; 74 75 76 // according to CSS 2.1 standard, 77 // value of 'font' CSS property can be represented as follows: 78 // [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | 79 // caption | icon | menu | message-box | small-caption | status-bar | inherit 80 81 // Note that font-family value, unlike other values, can contain spaces (in this case it should be quoted) 82 // Breaking value by spaces, we'll break such multi-word families. 83 84 // Replace all white space sequences with only one space; 85 // Remove spaces after commas; it will allow us 86 // to split value correctly using look-backward expressions 87 $value = preg_replace("/\s+/"," ",$value); 88 $value = preg_replace("/,\s+/",",",$value); 89 $value = preg_replace("#\s*/\s*#","/",$value); 90 91 // Split value to subvalues by all whitespaces NOT preceeded by comma; 92 // thus, we'll keep all alternative font-families together instead of breaking them. 93 // Still we have a problem with multi-word family names. 94 $subvalues = preg_split("/ /",$value); 95 96 // Let's scan subvalues we've received and join values containing multiword family names 97 $family_start = 0; 98 $family_running = false; 99 $family_double_quote = false;; 100 101 for ($i=0, $num_subvalues = count($subvalues); $i < $num_subvalues; $i++) { 102 $current_value = $subvalues[$i]; 103 104 if ($family_running) { 105 $subvalues[$family_start] .= " " . $subvalues[$i]; 106 107 // Remove this subvalues from the subvalue list at all 108 array_splice($subvalues, $i, 1); 109 110 $num_subvalues--; 111 $i--; 112 } 113 114 // Check if current subvalue contains beginning of multi-word family name 115 // We can detect it by searching for single or double quote without pair 116 if ($family_running && $family_double_quote && !preg_match('/^[^"]*("[^"]*")*[^"]*$/',$current_value)) { 117 $family_running = false; 118 } elseif ($family_running && !$family_double_quote && !preg_match("/^[^']*('[^']*')*[^']*$/",$current_value)) { 119 $family_running = false; 120 } elseif (!$family_running && !preg_match("/^[^']*('[^']*')*[^']*$/",$current_value)) { 121 $family_running = true; 122 $family_start = $i; 123 $family_double_quote = false; 124 } elseif (!$family_running && !preg_match('/^[^"]*("[^"]*")*[^"]*$/',$current_value)) { 125 $family_running = true; 126 $family_start = $i; 127 $family_double_quote = true; 128 } 129 }; 130 131 // Now process subvalues one-by-one. 132 foreach ($subvalues as $subvalue) { 133 $subvalue = trim(strtolower($subvalue)); 134 $subvalue_type = detect_font_value_type($subvalue); 135 136 switch ($subvalue_type) { 137 case FONT_VALUE_STYLE: 138 $font->style = CSSFontStyle::parse($subvalue); 139 break; 140 case FONT_VALUE_WEIGHT: 141 $font->weight = CSSFontWeight::parse($subvalue); 142 break; 143 case FONT_VALUE_SIZE: 144 $size_subvalues = explode('/', $subvalue); 145 $font->size = CSSFontSize::parse($size_subvalues[0]); 146 if (isset($size_subvalues[1])) { 147 $handler =& CSS::get_handler(CSS_LINE_HEIGHT); 148 $font->line_height = $handler->parse($size_subvalues[1]); 149 }; 150 break; 151 case FONT_VALUE_FAMILY: 152 $font->family = CSSFontFamily::parse($subvalue); 153 break; 154 }; 155 }; 156 157 return $font; 158 } 159 160 function get_property_code() { 161 return CSS_FONT; 162 } 163 164 function get_property_name() { 165 return 'font'; 166 } 167 168 function clearDefaultFlags(&$state) { 169 parent::clearDefaultFlags($state); 170 $state->set_propertyDefaultFlag(CSS_FONT_SIZE, false); 171 $state->set_propertyDefaultFlag(CSS_FONT_STYLE, false); 172 $state->set_propertyDefaultFlag(CSS_FONT_WEIGHT, false); 173 $state->set_propertyDefaultFlag(CSS_FONT_FAMILY, false); 174 $state->set_propertyDefaultFlag(CSS_LINE_HEIGHT, false); 175 } 176} 177 178$font = new CSSFont; 179CSS::register_css_property($font); 180CSS::register_css_property(new CSSFontSize($font, 'size')); 181CSS::register_css_property(new CSSFontStyle($font, 'style')); 182CSS::register_css_property(new CSSFontWeight($font, 'weight')); 183CSS::register_css_property(new CSSFontFamily($font, 'family')); 184CSS::register_css_property(new CSSLineHeight($font, 'line_height')); 185 186?>