Exemple #1
0
 function &create(&$root, &$pipeline)
 {
     $name = $root->get_attribute('name');
     $value = $root->get_attribute('value');
     $url_autofix = new AutofixUrl();
     $src = $url_autofix->apply(trim($root->get_attribute("src")));
     $src_img = ImageFactory::get($pipeline->guess_url($src), $pipeline);
     if (is_null($src_img)) {
         error_log(sprintf("Cannot open image at '%s'", $src));
         if ($root->has_attribute('width')) {
             $width = px2pt($root->get_attribute('width'));
         } else {
             $width = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
         }
         if ($root->has_attribute('height')) {
             $height = px2pt($root->get_attribute('height'));
         } else {
             $height = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
         }
         $alt = $root->get_attribute('alt');
         $css_state =& $pipeline->get_current_css_state();
         $box =& new ButtonBrokenImagebox($width, $height, $alt, $name, $value, $css_state->get_property(CSS_HTML2PS_FORM_ACTION));
         $box->readCSS($css_state);
         return $box;
     }
     $css_state =& $pipeline->get_current_css_state();
     $box =& new ButtonImageBox($src_img, $name, $value, $css_state->get_property(CSS_HTML2PS_FORM_ACTION));
     $box->readCSS($css_state);
     $box->_setupSize();
     return $box;
 }
function units2pt($value, $font_size = null)
{
    $unit = Value::unit_from_string($value);
    switch ($unit) {
        case UNIT_PT:
            return pt2pt((double) $value);
        case UNIT_PX:
            return px2pt((double) $value);
        case UNIT_MM:
            return pt2pt(mm2pt((double) $value));
        case UNIT_CM:
            return pt2pt(mm2pt((double) $value * 10));
        case UNIT_EM:
            return em2pt((double) $value, $font_size);
        case UNIT_EX:
            return ex2pt((double) $value, $font_size);
        case UNIT_IN:
            return pt2pt((double) $value * 72);
            // points used by CSS 2.1 are equal to 1/72nd of an inch.
        // points used by CSS 2.1 are equal to 1/72nd of an inch.
        case UNIT_PC:
            return pt2pt((double) $value * 12);
            // 1 pica equals to 12 points.
        // 1 pica equals to 12 points.
        default:
            global $g_config;
            if ($g_config['mode'] === 'quirks') {
                return px2pt((double) $value);
            } else {
                return 0;
            }
    }
}
 function testWidthAbsolutePositioned1()
 {
     $media = null;
     $pipeline = null;
     $tree = $this->runPipeline(file_get_contents('test.width.absolute.positioned.1.html'), $media, $pipeline);
     $font_size = $tree->getCSSProperty(CSS_FONT_SIZE);
     $base = $font_size->getPoints();
     $element =& $tree->get_element_by_id('div1');
     $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('No positioning data at all', 'Times-Roman', 'iso-8859-1', $base), 0);
     $element =& $tree->get_element_by_id('div2');
     $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('Left', 'Times-Roman', 'iso-8859-1', $base), 0);
     $element =& $tree->get_element_by_id('div3');
     $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(200));
     $element =& $tree->get_element_by_id('div4');
     $this->assertEqual($element->get_width(), px2pt(100));
     $element =& $tree->get_element_by_id('div5');
     $this->assertEqual($element->get_width(), px2pt(100));
     $element =& $tree->get_element_by_id('div6');
     $this->assertEqual($element->get_width(), px2pt(100));
     $element =& $tree->get_element_by_id('div7');
     $this->assertEqual($element->get_width(), px2pt(100));
     $element =& $tree->get_element_by_id('div8');
     $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('Right', 'Times-Roman', 'iso-8859-1', $base), 0);
     $element =& $tree->get_element_by_id('div9');
     $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(100), 'DIV with long text and "left" property has incorrect width [%s]');
     $element =& $tree->get_element_by_id('div10');
     $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(100), 'DIV with long text and "right" property has incorrect width [%s]');
     $element =& $tree->get_element_by_id('div11');
     $this->assertEqual($element->get_width(), mm2pt($media->real_width()), 'DIV with long text and no positioning properties has incorrect width [%s]');
     $element =& $tree->get_element_by_id('div12');
     $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(200), 'DIV with long text and both "left" and "right" properties has incorrect width [%s]');
 }
 function testPositionHorizontalbsolutePositioned1()
 {
     $media = null;
     $pipeline = null;
     $tree = $this->runPipeline(file_get_contents('test.position.horizontal.absolute.positioned.1.html'), $media, $pipeline);
     $font_size = $tree->getCSSProperty(CSS_FONT_SIZE);
     $base = $font_size->getPoints();
     $element =& $tree->get_element_by_id('div1');
     $this->assertEqual($element->get_left(), mm2pt($media->margins['left']), 'DIV with no positioning is positioned incorrectly [%s]');
     $element =& $tree->get_element_by_id('div2');
     $this->assertEqual($element->get_left(), mm2pt($media->margins['left']) + px2pt(100), 'DIV with "left" property is positioned incorrectly [%s]');
     $element =& $tree->get_element_by_id('div3');
     $this->assertEqual($element->get_right(), mm2pt($media->width() - $media->margins['right']) - px2pt(100), 'DIV with "right" property is positioned incorrectly [%s]');
     $element =& $tree->get_element_by_id('div4');
     $this->assertEqual($element->get_left(), mm2pt($media->margins['left']), 'DIV with long text and "right" property is positioned incorrectly [%s]');
     $element =& $tree->get_element_by_id('div5');
     $this->assertEqual($element->get_left(), mm2pt($media->margins['left']) + px2pt(100), 'DIV with long text and "left" property is positioned incorrectly [%s]');
 }
 function parse_col(&$root, $index)
 {
     if ($root->has_attribute('width')) {
         // The value if 'width' attrubute is "multi-length";
         // it means that it could be:
         // 1. absolute value (10)
         // 2. percentage value (10%)
         // 3. relative value (3* or just *)
         //
         // TODO: support for relative values
         $value = $root->get_attribute('width');
         if (is_percentage($value)) {
             $this->cwc[$index] = new WCFraction((int) $value / 100);
         } else {
             $this->cwc[$index] = new WCConstant(px2pt((int) $value));
         }
     }
 }
 function &create(&$root, &$pipeline)
 {
     $name = $root->get_attribute('name');
     $value = $root->get_attribute('value');
     $src = trim($root->get_attribute("src"));
     $src_img = Image::get($pipeline->guess_url($src), $pipeline);
     if (is_null($src_img)) {
         error_log(sprintf("Cannot open image at '%s'", $src));
         if ($root->has_attribute('width')) {
             $width = px2pt($root->get_attribute('width'));
         } else {
             $width = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
         }
         if ($root->has_attribute('height')) {
             $height = px2pt($root->get_attribute('height'));
         } else {
             $height = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
         }
         $alt = $root->get_attribute('alt');
         $box =& new ButtonBrokenImagebox($width, $height, $alt, $name, $value);
         return $box;
     }
     $box =& new ButtonImageBox($src_img, $name, $value);
     // Proportional scaling
     if ($root->has_attribute('width') && !$root->has_attribute('height')) {
         $box->scale = SCALE_WIDTH;
         // Only 'width' attribute given
         $size = $box->src_width / $box->src_height * $box->get_width();
         $box->put_height($size);
         // Update baseline according to constrained image height
         $box->default_baseline = $box->get_height();
     } elseif (!$root->has_attribute('width') && $root->has_attribute('height')) {
         $box->scale = SCALE_HEIGHT;
         // Only 'height' attribute given
         $size = $box->src_height / $box->src_width * $box->get_height();
         $box->put_width($size);
         $box->put_width_constraint(new WCConstant($size));
         $box->default_baseline = $box->get_height();
     }
     return $box;
 }
 function testBorderBottom1()
 {
     $tree = $this->runPipeline(file_get_contents('test.border-bottom.1.html'));
     $element =& $tree->get_element_by_id('div1');
     $border =& $element->getCSSProperty(CSS_BORDER);
     $top =& $border->get_top();
     $this->assertEqual($top->get_style(), BS_NONE);
     $left =& $border->get_left();
     $this->assertEqual($left->get_style(), BS_NONE);
     $right =& $border->get_right();
     $this->assertEqual($right->get_style(), BS_NONE);
     $bottom =& $border->get_bottom();
     $this->assertEqual($bottom->get_style(), BS_SOLID);
     $width =& $bottom->get_width();
     $this->assertEqual($width, px2pt(1));
     $color =& $bottom->get_color();
     $this->assertEqual($color->r, 0);
     $this->assertEqual($color->g, 0);
     $this->assertEqual($color->b, 0);
     $element =& $tree->get_element_by_id('div2');
     $border =& $element->getCSSProperty(CSS_BORDER);
     $top =& $border->get_top();
     $this->assertEqual($top->get_style(), BS_NONE);
     $left =& $border->get_left();
     $this->assertEqual($left->get_style(), BS_NONE);
     $right =& $border->get_right();
     $this->assertEqual($right->get_style(), BS_NONE);
     $bottom =& $border->get_bottom();
     $this->assertEqual($bottom->get_style(), BS_SOLID);
     $width =& $bottom->get_width();
     $this->assertEqual($width, px2pt(1));
     $color =& $bottom->get_color();
     $this->assertEqual($color->r, 0);
     $this->assertEqual($color->g, 0);
     $this->assertEqual($color->b, 0);
 }
 function image_ry($image, $x, $y, $height, $bottom, $ox, $oy, $scale)
 {
     $tmpname = $this->_mktempimage($image);
     // Fill part to the bottom
     $cy = $y;
     while ($cy + $height > $bottom) {
         $tx = $x;
         $ty = $cy + px2pt(imagesy($image));
         $this->_coords2pdf($tx, $ty);
         $this->pdf->Image($tmpname, $tx, $ty, imagesx($image) * $scale, imagesy($image) * $scale, "png");
         $cy -= $height;
     }
     // Fill part to the top
     $cy = $y;
     while ($cy - $height < $y + $oy) {
         $tx = $x;
         $ty = $cy + px2pt(imagesy($image));
         $this->_coords2pdf($tx, $ty);
         $this->pdf->Image($tmpname, $tx, $ty, imagesx($image) * $scale, imagesy($image) * $scale, "png");
         $cy += $height;
     }
     unlink($tmpname);
 }
 function _setupSize()
 {
     $this->put_width(px2pt($this->image->sx()));
     $this->put_height(px2pt($this->image->sy()));
     $this->default_baseline = $this->get_full_height();
     $this->src_height = $this->image->sx();
     $this->src_width = $this->image->sy();
     $wc = $this->getCSSProperty(CSS_WIDTH);
     $hc = $this->get_height_constraint();
     // Proportional scaling
     if ($wc && $hc->is_null() && !$wc->isNull()) {
         $this->scale = SCALE_WIDTH;
         // Only 'width' attribute given
         $size = $this->src_width / $this->src_height * $this->get_width();
         $this->put_height($size);
         // Update baseline according to constrained image height
         $this->default_baseline = $this->get_full_height();
     } elseif (!$hc->is_null() && $wc->isNull()) {
         $this->scale = SCALE_HEIGHT;
         // Only 'height' attribute given
         $size = $this->src_height / $this->src_width * $this->get_height();
         $this->put_width($size);
         $this->setCSSProperty(CSS_WIDTH, new WCConstant($size));
         $this->default_baseline = $this->get_full_height();
     }
 }
/**
 * Calculated  the actual  size of  frameset rows/columns  using value
 * specified in 'rows'  of 'cols' attribute. This value  is defined as
 * "MultiLength"; according to HTML 4.01 6.6:
 *
 * MultiLength:  The  value (  %MultiLength;  in  the  DTD) may  be  a
 * %Length; or a relative length. A relative length has the form "i*",
 * where  "i"  is an  integer.  When  allotting  space among  elements
 * competing for  that space, user  agents allot pixel  and percentage
 * lengths  first,  then divide  up  remaining  available space  among
 * relative lengths.  Each relative length  receives a portion  of the
 * available space  that is proportional to the  integer preceding the
 * "*". The  value "*" is  equivalent to "1*".  Thus, if 60  pixels of
 * space  are  available  after   the  user  agent  allots  pixel  and
 * percentage space,  and the competing  relative lengths are  1*, 2*,
 * and 3*, the 1* will be alloted 10 pixels, the 2* will be alloted 20
 * pixels, and the 3* will be alloted 30 pixels.
 *
 * @param $lengths_src String source Multilength value
 * @param $total Integer total space to be filled
 * 
 * @return Array list of calculated lengths 
 */
function guess_lengths($lengths_src, $total)
{
    /**
     * Initialization: the comma-separated list is exploded to the array
     * of  distinct values,  list of  calculated lengths  is initialized
     * with default (zero) values
     */
    $lengths = explode(",", $lengths_src);
    $values = array();
    foreach ($lengths as $length) {
        $values[] = 0;
    }
    /**
     * First pass: fixed-width sizes (%Length). There's two types of 
     * fixed widths: pixel widths and percentage widths
     *
     * According to HTML 4.01, 6.6:
     *
     * Length: The value  (%Length; in the DTD) may  be either a %Pixel;
     * or  a   percentage  of  the  available   horizontal  or  vertical
     * space. Thus, the value "50%" means half of the available space.
     *
     * Pixels:  The value  (%Pixels;  in  the DTD)  is  an integer  that
     * represents  the   number  of   pixels  of  the   canvas  (screen,
     * paper). Thus,  the value "50"  means fifty pixels.  For normative
     * information  about  the definition  of  a  pixel, please  consult
     * [CSS1].
     */
    for ($i = 0; $i < count($lengths); $i++) {
        /**
         * Remove leading/trailing spaces from current text value
         */
        $length_src = trim($lengths[$i]);
        if (substr($length_src, strlen($length_src) - 1, 1) == "%") {
            /**
             * Percentage value
             */
            $fraction = substr($length_src, 0, strlen($length_src) - 1) / 100;
            $values[$i] = $total * $fraction;
        } elseif (substr($length_src, strlen($length_src) - 1, 1) != "*") {
            /**
             * Pixel value
             */
            $values[$i] = px2pt($length_src);
        }
    }
    // Second pass: relative-width columns
    $rest = $total - array_sum($values);
    $parts = 0;
    foreach ($lengths as $length_src) {
        if (substr($length_src, strlen($length_src) - 1, 1) == "*") {
            $parts += max(1, substr($length_src, 0, strlen($length) - 1));
        }
    }
    if ($parts > 0) {
        $part_size = $rest / $parts;
        for ($i = 0; $i < count($lengths); $i++) {
            $length = $lengths[$i];
            if (substr($length, strlen($length) - 1, 1) == "*") {
                $values[$i] = $part_size * max(1, substr($length, 0, strlen($length) - 1));
            }
        }
    }
    // Fix over/underconstrained framesets
    $width = array_sum($values);
    if ($width > 0) {
        $koeff = $total / $width;
        for ($i = 0; $i < count($values); $i++) {
            $values[$i] *= $koeff;
        }
    }
    return $values;
}
 /**
  * Renders the backgroung image using the specified output driver.
  * 
  * @param OutputDriver $driver an output driver object
  * @param GenericFormattedBox $box an box owning this background image
  * @param int $repeat the 'background-repeat' value
  * @param BackgroundPosition $position the 'background-position' value
  *
  * @uses BackgroundPosition
  * @uses OutputDriver
  */
 function show(&$driver, $box, $repeat, $position, $attachment)
 {
     /**
      * If no image should be rendered, just return
      * @see BackgroundImage::$_url
      */
     if (is_null($this->_url)) {
         return;
     }
     if (is_null($this->_image)) {
         return;
     }
     if ($attachment == BACKGROUND_ATTACHMENT_FIXED && $box->getCSSProperty(CSS_DISPLAY) == '-body') {
         $media =& $driver->get_media();
         $left = $box->get_left_background();
         $right = $box->get_right_background();
         $top = $driver->offset + mm2pt($media->margins['bottom']) + mm2pt($media->real_height());
         $bottom = $driver->offset + mm2pt($media->margins['bottom']);
     } else {
         $left = $box->get_left_background();
         $right = $box->get_right_background();
         $top = $box->get_top_background();
         $bottom = $box->get_bottom_background();
     }
     /**
      * Setup clipping region for padding area. Note that background image is drawn in the padding 
      * area which in generic case is greater than content area.
      * 
      * @see OutputDriver::clip()
      *
      * @link http://www.w3.org/TR/CSS21/box.html#box-padding-area CSS 2.1 definition of padding area
      */
     $driver->save();
     $driver->moveto($left, $top);
     $driver->lineto($right, $top);
     $driver->lineto($right, $bottom);
     $driver->lineto($left, $bottom);
     $driver->closepath();
     $driver->clip();
     /**
      * get real image size in device points
      *
      * @see pt2pt()
      * @see px2pt()
      */
     $image_height = px2pt(imagesy($this->_image));
     $image_width = px2pt(imagesx($this->_image));
     /**
      * Get dimensions of the rectangle to be filled with the background image
      */
     $padding_width = $right - $left;
     $padding_height = $top - $bottom;
     /**
      * Calculate the vertical offset from the top padding edge to the background image top edge using current 
      * 'background-position' value. 
      * 
      * @link file:///C:/docs/css/colors.html#propdef-background-position CSS 2 'background-position' description
      */
     if ($position->x_percentage) {
         $x_offset = ($padding_width - $image_width) * $position->x / 100;
     } else {
         $x_offset = $position->x;
     }
     /**
      * Calculate the horizontal offset from the left padding edge to the background image left edge using current 
      * 'background-position' value
      * 
      * @link file:///C:/docs/css/colors.html#propdef-background-position CSS 2 'background-position' description
      */
     if ($position->y_percentage) {
         $y_offset = ($padding_height - $image_height) * $position->y / 100;
     } else {
         $y_offset = $position->y;
     }
     /**
      * Output the image (probably tiling it; depends on current value of 'background-repeat') using 
      * current output driver's tiled image output functions. Note that px2pt(1) is an image scaling factor; as all
      * page element are scaled to fit the media, background images should be scaled too!
      * 
      * @see OutputDriver::image()
      * @see OutputDriver::image_rx()
      * @see OutputDriver::image_ry()
      * @see OutputDriver::image_rxry()
      *
      * @link file:///C:/docs/css/colors.html#propdef-background-repeat CSS 2.1 'background-repeat' property description
      */
     switch ($repeat) {
         case BR_NO_REPEAT:
             /**
              * 'background-repeat: no-repeat' case; no tiling at all
              */
             $driver->image($this->_image, $left + $x_offset, $top - $image_height - $y_offset, px2pt(1));
             break;
         case BR_REPEAT_X:
             /**
              * 'background-repeat: repeat-x' case; horizontal tiling
              */
             $driver->image_rx($this->_image, $left + $x_offset, $top - $image_height - $y_offset, $image_width, $right, $x_offset, $y_offset, px2pt(1));
             break;
         case BR_REPEAT_Y:
             /**
              * 'background-repeat: repeat-y' case; vertical tiling
              */
             $driver->image_ry($this->_image, $left + $x_offset, $top - $image_height - $y_offset, $image_height, $bottom, $x_offset, $y_offset, px2pt(1));
             break;
         case BR_REPEAT:
             /**
              * 'background-repeat: repeat' case; full tiling
              */
             $driver->image_rx_ry($this->_image, $left + $x_offset, $top - $image_height + $y_offset, $image_width, $image_height, $right, $bottom, $x_offset, $y_offset, px2pt(1));
             break;
     }
     /**
      * Restore the previous clipping area
      * 
      * @see OutputDriver::clip()
      * @see OutputDriver::restore()
      */
     $driver->restore();
 }
 function show(&$viewport, &$box, $x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $hilight)
 {
     // If this border have 'transparent' color value, we just will not draw it
     //
     if ($this->color->transparent) {
         return;
     }
     switch ($this->style) {
         case BS_SOLID:
             $this->color->apply($viewport);
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             break;
         case BS_INSET:
             if ($hilight) {
                 $this->color->apply($viewport);
             } else {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             }
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             break;
         case BS_GROOVE:
             /**
              * Draw outer part
              */
             if ($hilight) {
                 $this->color->apply($viewport);
             } else {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             }
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             /**
              * Draw inner part
              */
             if ($hilight) {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             } else {
                 $this->color->apply($viewport);
             }
             $x1a = ($x1 + $x4) / 2;
             $y1a = ($y1 + $y4) / 2;
             $x2a = ($x2 + $x3) / 2;
             $y2a = ($y2 + $y3) / 2;
             $viewport->moveto($x1a, $y1a);
             $viewport->lineto($x2a, $y2a);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             break;
         case BS_RIDGE:
             /**
              * Draw outer part
              */
             if ($hilight) {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             } else {
                 $this->color->apply($viewport);
             }
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             /**
              * Draw inner part
              */
             if ($hilight) {
                 $this->color->apply($viewport);
             } else {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             }
             $x1a = ($x1 + $x4) / 2;
             $y1a = ($y1 + $y4) / 2;
             $x2a = ($x2 + $x3) / 2;
             $y2a = ($y2 + $y3) / 2;
             $viewport->moveto($x1a, $y1a);
             $viewport->lineto($x2a, $y2a);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             break;
         case BS_OUTSET:
             if (!$hilight) {
                 $this->color->apply($viewport);
             } else {
                 $color = $this->color->copy();
                 $color->blend(new Color(array(255, 255, 255), false), HILIGHT_COLOR_ALPHA);
                 $color->apply($viewport);
             }
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->lineto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->closepath();
             $viewport->fill();
             break;
         case BS_DASHED:
             $this->color->apply($viewport);
             $viewport->dash($this->width->getPoints() * 4, $this->width->getPoints() * 5);
             $viewport->setlinewidth($this->width->getPoints());
             $viewport->moveto(($x1 + $x4) / 2, ($y1 + $y4) / 2);
             $viewport->lineto(($x2 + $x3) / 2, ($y2 + $y3) / 2);
             $viewport->stroke();
             // Restore solid line
             $viewport->dash(1, 0);
             break;
         case BS_DOTTED:
             $this->color->apply($viewport);
             $viewport->dash($this->width->getPoints(), $this->width->getPoints() * 2);
             $viewport->setlinewidth($this->width->getPoints());
             $viewport->moveto(($x1 + $x4) / 2, ($y1 + $y4) / 2);
             $viewport->lineto(($x2 + $x3) / 2, ($y2 + $y3) / 2);
             $viewport->stroke();
             // Restore solid line
             $viewport->dash(1, 0);
             break;
         case BS_DOUBLE:
             $this->color->apply($viewport);
             $viewport->setlinewidth(px2pt(1));
             $viewport->moveto($x1, $y1);
             $viewport->lineto($x2, $y2);
             $viewport->stroke();
             $viewport->moveto($x3, $y3);
             $viewport->lineto($x4, $y4);
             $viewport->stroke();
             break;
         case BS_NONE:
         default:
             break;
     }
 }
    function TestInputText1()
    {
        $tree = $this->runPipeline('
<style type="text/css">
.input1 {
  font-size: 10px;
}

.input2 {
  font-size: 20px;
}
</style>

<input id="i1" class="input1" type="text" size="0"/><br/>
<div style="width: 122px; height: 10px; background: green;">&nbsp;</div>

<input id="i2" class="input1" type="text" size="1"/><br/>
<div style="width: 27px; height: 10px; background: green;">&nbsp;</div>

<input id="i3" class="input1" type="text" size="2"/><br/>
<div style="width: 32px; height: 10px; background: green;">&nbsp;</div>

<input id="i4" class="input1" type="text" size="3"/><br/>
<div style="width: 37px; height: 10px; background: green;">&nbsp;</div>

<input id="i5" class="input1" type="text" size="4"/><br/>
<div style="width: 42px; height: 10px; background: green;">&nbsp;</div>

<input id="i6" class="input1" type="text" size="5"/><br/>
<div style="width: 47px; height: 10px; background: green;">&nbsp;</div>

<input id="i7" class="input1" type="text" size="10"/><br/>
<div style="width: 72px; height: 10px; background: green;">&nbsp;</div>

<input id="i8" class="input1" type="text" size="15"/><br/>
<div style="width: 97px; height: 10px; background: green;">&nbsp;</div>

<input id="i9" class="input1" type="text" size="20"/><br/>
<div style="width: 122px; height: 10px; background: green;">&nbsp;</div>

<input id="i10" class="input1" type="text" size="25"/><br/>
<div style="width: 147px; height: 10px; background: green;">&nbsp;</div>

<input id="i11" class="input2" type="text" size="0"/><br/>
<div style="width: 219px; height: 10px; background: green;">&nbsp;</div>

<input id="i12" class="input2" type="text" size="1"/><br/>
<div style="width: 48px; height: 10px; background: green;">&nbsp;</div>

<input id="i13" class="input2" type="text" size="2"/><br/>
<div style="width: 57px; height: 10px; background: green;">&nbsp;</div>

<input id="i14" class="input2" type="text" size="3"/><br/>
<div style="width: 66px; height: 10px; background: green;">&nbsp;</div>

<input id="i15" class="input2" type="text" size="4"/><br/>
<div style="width: 75px; height: 10px; background: green;">&nbsp;</div>

<input id="i16" class="input2" type="text" size="5"/><br/>
<div style="width: 84px; height: 10px; background: green;">&nbsp;</div>

<input id="i17" class="input2" type="text" size="10"/><br/>
<div style="width: 129px; height: 10px; background: green;">&nbsp;</div>

<input id="i18" class="input2" type="text" size="15"/><br/>
<div style="width: 174px; height: 10px; background: green;">&nbsp;</div>

<input id="i19" class="input2" type="text" size="20"/><br/>
<div style="width: 219px; height: 10px; background: green;">&nbsp;</div>

<input id="i20" class="input2" type="text" size="25"/><br/>
<div style="width: 264px; height: 10px; background: green;">&nbsp;</div>
');
        $widths = array(122, 27, 32, 37, 42, 47, 72, 97, 122, 147, 219, 48, 57, 66, 75, 84, 129, 174, 219, 264);
        for ($i = 0; $i < 20; $i++) {
            $element =& $tree->get_element_by_id(sprintf('i%d', $i + 1));
            $this->assertEqual($element->get_full_width(), px2pt($widths[$i]), sprintf('Invalid input No %i width [%%s]', $i + 1));
        }
    }
 function toPt($font_size)
 {
     switch ($this->_unit) {
         case UNIT_PT:
             return pt2pt($this->_number);
         case UNIT_PX:
             return px2pt($this->_number);
         case UNIT_MM:
             return pt2pt(mm2pt($this->_number));
         case UNIT_CM:
             return pt2pt(mm2pt($this->_number * 10));
         case UNIT_EM:
             return em2pt($this->_number, $font_size);
         case UNIT_EX:
             return ex2pt($this->_number, $font_size);
         case UNIT_IN:
             return pt2pt($this->_number * 72);
             // points used by CSS 2.1 are equal to 1/72nd of an inch.
         // points used by CSS 2.1 are equal to 1/72nd of an inch.
         case UNIT_PC:
             return pt2pt($this->_number * 12);
             // 1 pica equals to 12 points.
         // 1 pica equals to 12 points.
         default:
             global $g_config;
             if ($g_config['mode'] === 'quirks') {
                 return px2pt($this->_number);
             } else {
                 return 0;
             }
     }
 }
 function ImgBox($img)
 {
     $this->src_encoding = DEFAULT_ENCODING;
     $this->scale = SCALE_NONE;
     // Call parent constructor
     $this->GenericFormattedBox();
     // Store image for further processing
     $this->image = $img;
     $this->put_width(px2pt(imagesx($img)));
     $hc = $this->get_height_constraint();
     if ($hc->is_null()) {
         $this->put_height(px2pt(imagesy($img)));
     }
     $this->default_baseline = $this->get_height();
     $this->src_height = imagesx($img);
     $this->src_width = imagesy($img);
 }
function units2pt($value, $font_size = null)
{
    $units = substr($value, strlen($value) - 2, 2);
    switch ($units) {
        case "pt":
            return pt2pt((double) $value);
        case "px":
            return px2pt((double) $value);
        case "mm":
            return mm2pt((double) $value);
        case "cm":
            return mm2pt((double) $value * 10);
            // FIXME: check if it will work correcty in all situations (order of css rule application may vary).
        // FIXME: check if it will work correcty in all situations (order of css rule application may vary).
        case "em":
            if (is_null($font_size)) {
                $fs = get_font_size();
                //       $fs_parts = explode(" ", $fs);
                //       if (count($fs_parts) == 2) {
                //         return units2pt(((double)$value) * $fs_parts[0]*EM_KOEFF . $fs_parts[1]);
                //       } else {
                return pt2pt((double) $value * $fs * EM_KOEFF);
                //       };
            } else {
                return $font_size * (double) $value * EM_KOEFF;
            }
        case "ex":
            if (is_null($font_size)) {
                $fs = get_font_size();
                //       $fs_parts = explode(" ", $fs);
                //       if (count($fs_parts) == 2) {
                //         return units2pt(((double)$value) * $fs_parts[0]*EX_KOEFF . $fs_parts[1]);
                //       } else {
                return pt2pt((double) $value * $fs * EX_KOEFF);
                //       };
            } else {
                return $font_size * (double) $value * EX_KOEFF;
            }
        default:
            global $g_config;
            if ($g_config['mode'] === 'quirks') {
                return px2pt((double) $value);
            } else {
                return 0;
            }
    }
}