set_type($type);
}
function get_type() {
return $this->_type;
}
function set_type($type) {
$this->_type = $type;
}
}
class CSSPageSelectorAll extends CSSPageSelector {
function CSSPageSelectorAll() {
$this->CSSPageSelector(CSS_PAGE_SELECTOR_ALL);
}
}
class CSSPageSelectorNamed extends CSSPageSelector {
var $_name;
function CSSPageSelectorNamed($name) {
$this->CSSPageSelector(CSS_PAGE_SELECTOR_NAMED);
$this->set_name($name);
}
function get_name() {
return $this->_name;
}
function set_name($name) {
$this->_name = $name;
}
}
class CSSPageSelectorFirst extends CSSPageSelector {
function CSSPageSelectorFirst() {
$this->CSSPageSelector(CSS_PAGE_SELECTOR_FIRST);
}
}
class CSSPageSelectorLeft extends CSSPageSelector {
function CSSPageSelectorLeft() {
$this->CSSPageSelector(CSS_PAGE_SELECTOR_LEFT);
}
}
class CSSPageSelectorRight extends CSSPageSelector {
function CSSPageSelectorRight() {
$this->CSSPageSelector(CSS_PAGE_SELECTOR_RIGHT);
}
}
class CSSAtRulePage {
var $selector;
var $margin_boxes;
var $css;
function CSSAtRulePage($selector, &$pipeline) {
$this->selector = $selector;
$this->margin_boxes = array();
$this->css =& new CSSPropertyCollection();
}
function &getSelector() {
return $this->selector;
}
function getAtRuleMarginBoxes() {
return $this->margin_boxes;
}
/**
* Note that only one margin box rule could be added; subsequent adds
* will overwrite existing data
*/
function addAtRuleMarginBox($rule) {
$this->margin_boxes[$rule->getSelector()] = $rule;
}
function setCSSProperty($property) {
$this->css->add_property($property);
}
}
class CSSAtRuleMarginBox {
var $selector;
var $css;
/**
* TODO: CSS_TEXT_ALIGN should get top/bottom values by default for
* left-top, left-bottom, right-top and right-bottom boxes
*/
function CSSAtRuleMarginBox($selector, &$pipeline) {
$this->selector = $selector;
$css = "-html2ps-html-content: ''; content: ''; width: auto; height: auto; margin: 0; border: none; padding: 0; font: auto;";
$css = $css . $this->_getCSSDefaults($selector);
$this->css = new CSSRule(array(
array(SELECTOR_ANY),
parse_css_properties($css, $null),
'',
null),
$pipeline);
}
function getSelector() {
return $this->selector;
}
function _getCSSDefaults($selector) {
$text_align_handler =& CSS::get_handler(CSS_TEXT_ALIGN);
$vertical_align_handler =& CSS::get_handler(CSS_VERTICAL_ALIGN);
switch ($selector) {
case CSS_MARGIN_BOX_SELECTOR_TOP:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER:
return 'text-align: right; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_TOP_CENTER:
return 'text-align: center; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT:
return 'text-align: right; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER:
return 'text-align: right; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER:
return 'text-align: center; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT:
return 'text-align: right; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER:
return 'text-align: left; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_LEFT_TOP:
return 'text-align: center; vertical-align: top';
case CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE:
return 'text-align: center; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM:
return 'text-align: center; vertical-align: bottom';
case CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP:
return 'text-align: center; vertical-align: top';
case CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE:
return 'text-align: center; vertical-align: middle';
case CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM:
return 'text-align: center; vertical-align: bottom';
};
}
function setCSSProperty($property) {
$this->css->add_property($property);
}
function &get_css_property($code) {
return $this->css->get_property($code);
}
}
/**
* Handle @page rules in current CSS media As parse_css_media is
* called for selected media only, we can store data to global CSS
* state - no data should be ignored
*
* at-page rules will be removed after parsing
*
* @param $css String contains raw CSS data to be processed
* @return String CSS text without at-page rules
*/
function parse_css_atpage_rules($css, &$css_ruleset) {
while (preg_match('/^(.*?)@page(.*)/is', $css, $matches)) {
$data = $matches[2];
$css = $matches[1].parse_css_atpage_rule(trim($data), $css_ruleset);
};
return $css;
}
function parse_css_atpage_rule($css, &$css_ruleset) {
/**
* Extract selector and left bracket
*/
if (!preg_match('/^(.*?){(.*)$/is', $css, $matches)) {
error_log('No selector and/or open bracket found in @page rule');
return $css;
};
$raw_selector = trim($matches[1]);
$css = trim($matches[2]);
$selector =& parse_css_atpage_selector($raw_selector);
$at_rule =& new CSSAtRulePage($selector, $css_ruleset);
/**
* The body of @page rule may contain declaraction (detected by ';'),
* margin box at-rule (detected by @top and similar tokens) or } indicating termination of
* @page rule
*/
while (preg_match('/^(.*?)(;|@|})(.*)$/is', $css, $matches)) {
$raw_prefix = trim($matches[1]);
$raw_token = trim($matches[2]);
$raw_suffix = trim($matches[3]);
switch ($raw_token) {
case ';':
/**
* Normal declaration (text contained in $raw_prefix
*/
parse_css_atpage_declaration($raw_prefix, $at_rule, $css_ruleset);
$css = $raw_suffix;
break;
case '@':
/**
* Margin box at-rule
*/
$css = parse_css_atpage_margin_box($raw_suffix, $at_rule, $css_ruleset);
break;
case '}':
/**
* End-of-rule
*/
$css_ruleset->add_at_rule_page($at_rule);
return $raw_suffix;
};
};
/**
* Note that we should normally exit via '}' token handler above
*/
error_log('No close bracket found in @page rule');
$css_ruleset->add_at_rule_page($at_rule);
return $css;
}
/**
* Parses CSS at-page rule selector; syntax of this selector can be seen in
* CSS 3 specification at http://www.w3.org/TR/css3-page/#syntax-page-selector
*
*
*/
function &parse_css_atpage_selector($selector) {
switch ($selector) {
case '':
$selector =& new CSSPageSelectorAll();
return $selector;
case ':first':
$selector =& new CSSPageSelectorFirst();
return $selector;
case ':left':
$selector =& new CSSPageSelectorLeft();
return $selector;
case ':right':
$selector =& new CSSPageSelectorRight();
return $selector;
default:
if (CSS::is_identifier($selector)) {
$selector =& new CSSPageSelectorNamed($selector);
return $selector;
} else {
error_log(sprintf('Unknown page selector in @page rule: \'%s\'', $selector));
$selector =& new CSSPageSelectorAll();
return $selector;
};
};
}
function parse_css_atpage_margin_box($css, &$at_rule, &$pipeline) {
if (!preg_match("/^([-\w]*)\s*{(.*)/is",$css,$matches)) {
error_log("Invalid margin box at-rule format");
return $css;
};
$raw_margin_box_selector = trim($matches[1]);
$css = trim($matches[2]);
$margin_box_selector = parse_css_atpage_margin_box_selector($raw_margin_box_selector);
$at_rule_margin_box = new CSSAtRuleMarginBox($margin_box_selector, $pipeline);
/**
* The body of margin box at-rule may contain declaraction (detected
* by ';'), or } indicating termination of at-rule
*/
while (preg_match('/^(.*?)(;|})(.*)$/is', $css, $matches)) {
$raw_prefix = trim($matches[1]);
$raw_token = trim($matches[2]);
$raw_suffix = trim($matches[3]);
switch ($raw_token) {
case ';':
/**
* Normal declaration (text contained in $raw_prefix
*/
parse_css_atpage_margin_box_declaration($raw_prefix, $at_rule_margin_box, $pipeline);
$css = $raw_suffix;
break;
case '}':
/**
* End-of-rule
*/
$at_rule->addAtRuleMarginBox($at_rule_margin_box);
return $raw_suffix;
};
};
/**
* Note that we should normally exit via '}' token handler above
*/
error_log('No close bracket found in margin box at-rule');
$at_rule->addAtRuleMarginBox($at_rule_margin_box);
return $css;
}
function parse_css_atpage_margin_box_selector($css) {
switch ($css) {
case 'top':
return CSS_MARGIN_BOX_SELECTOR_TOP;
case 'top-left-corner':
return CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER;
case 'top-left':
return CSS_MARGIN_BOX_SELECTOR_TOP_LEFT;
case 'top-center':
return CSS_MARGIN_BOX_SELECTOR_TOP_CENTER;
case 'top-right':
return CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT;
case 'top-right-corner':
return CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER;
case 'bottom':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM;
case 'bottom-left-corner':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER;
case 'bottom-left':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT;
case 'bottom-center':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER;
case 'bottom-right':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT;
case 'bottom-right-corner':
return CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER;
case 'left-top':
return CSS_MARGIN_BOX_SELECTOR_LEFT_TOP;
case 'left-middle':
return CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE;
case 'left-bottom':
return CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM;
case 'right-top':
return CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP;
case 'right-middle':
return CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE;
case 'right-bottom':
return CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM;
default:
error_log(sprintf('Unrecognized margin box selector: \'%s\'', $css));
return CSS_MARGIN_BOX_SELECTOR_TOP;
}
};
function parse_css_atpage_declaration($css, &$at_rule, &$pipeline) {
$parsed =& parse_css_property($css, $pipeline);
if (!is_null($parsed)) {
$properties = $parsed->getPropertiesSortedByPriority();
foreach ($properties as $property) {
$at_rule->setCSSProperty($property);
};
};
}
function parse_css_atpage_margin_box_declaration($css, &$at_rule, &$pipeline) {
$parsed =& parse_css_property($css, $pipeline);
if (!is_null($parsed)) {
$properties = $parsed->getPropertiesSortedByPriority();
foreach ($properties as $property) {
$at_rule->setCSSProperty($property);
};
};
}
?>