1<?php
2
3/**
4 * @package HTML2PS
5 * @subpackage Document
6 * Contains information about the background image to be rendered.
7 *
8 * If box does not have any background image it will still contain the
9 * BackgroundImage object having $_url member set to NULL.
10 *
11 * @see GenericFormattedBox
12 * @see CSSBackgroundImage
13
14 * @link http://www.w3.org/TR/CSS21/colors.html#q2 CSS 2.1 "The background"
15 */
16class BackgroundImage {
17  /**
18   * @var string URL of the background image file (may be NULL in case no background image specified).
19   * @access private
20   */
21  var $_url;
22
23  /**
24   * @var Resource image to be displayed
25   * @access private
26   */
27  var $_image;
28
29  /**
30   * Constructs new BackgroundImage object
31   *
32   * @param string $url URL of the image file (or NULL of no image should be rendered at all)
33   * @param resource $image image object to be displayed
34   */
35  function BackgroundImage($url, $image) {
36    $this->_url = $url;
37    $this->_image = $image;
38  }
39
40  /**
41   * "Deep copy" routine; it is required for compatibility with PHP 5
42   *
43   * @return BackgroundImage A copy of current object
44   */
45  function &copy() {
46    $value =& new BackgroundImage($this->_url, $this->_image);
47    return $value;
48  }
49
50  /**
51   * Checks if this value is equivalent to default value. According to CSS2, default value
52   * if the 'background-image' is 'none' - no image at all; in this case $_url member should
53   * contain NULL value.
54   *
55   * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-image CSS 2 'background-image' description
56   *
57   * @return boolean flag indicating whether this background image value is equivalent to default value
58   *
59   * @see CSSProperty::is_default()
60   * @see CSSBackgroundImage::default_value()
61   */
62  function is_default() {
63    return is_null($this->_url);
64  }
65
66  /**
67   * Renders the backgroung image using the specified output driver.
68   *
69   * @param OutputDriver $driver an output driver object
70   * @param GenericFormattedBox $box an box owning this background image
71   * @param int $repeat the 'background-repeat' value
72   * @param BackgroundPosition $position the 'background-position' value
73   *
74   * @uses BackgroundPosition
75   * @uses OutputDriver
76   */
77  function show(&$driver, $box, $repeat, $position, $attachment) {
78    /**
79     * If no image should be rendered, just return
80     * @see BackgroundImage::$_url
81     */
82    if (is_null($this->_url)) {
83      return;
84    };
85
86    if (is_null($this->_image)) {
87      return;
88    };
89
90    if ($attachment == BACKGROUND_ATTACHMENT_FIXED &&
91        $box->get_css_property(CSS_DISPLAY) == '-body') {
92      $media =& $driver->get_media();
93      $left = $box->get_left_background();
94      $right = $box->get_right_background();
95      $top = $driver->offset + mm2pt($media->margins['bottom']) + mm2pt($media->real_height());
96      $bottom = $driver->offset + mm2pt($media->margins['bottom']);
97    } else {
98      $left = $box->get_left_background();
99      $right = $box->get_right_background();
100      $top = $box->get_top_background();
101      $bottom = $box->get_bottom_background();
102    };
103
104    $driver->save();
105
106    if (!$GLOBALS['g_config']['debugnoclip']) {
107      /**
108       * Setup clipping region for padding area. Note that background image is drawn in the padding
109       * area which in generic case is greater than content area.
110       *
111       * @see OutputDriver::clip()
112       *
113       * @link http://www.w3.org/TR/CSS21/box.html#box-padding-area CSS 2.1 definition of padding area
114       */
115      $driver->moveto($left,  $top);
116      $driver->lineto($right, $top);
117      $driver->lineto($right, $bottom);
118      $driver->lineto($left,  $bottom);
119      $driver->closepath();
120      $driver->clip();
121    };
122
123    /**
124     * get real image size in device points
125     *
126     * @see pt2pt()
127     * @see px2pt()
128     */
129    $image_height = px2pt($this->_image->sy());
130    $image_width  = px2pt($this->_image->sx());
131
132    /**
133     * Get dimensions of the rectangle to be filled with the background image
134     */
135    $padding_width  = $right - $left;
136    $padding_height = $top - $bottom;
137
138    /**
139     * Calculate the vertical offset from the top padding edge to the background image top edge using current
140     * 'background-position' value.
141     *
142     * @link file:///C:/docs/css/colors.html#propdef-background-position CSS 2 'background-position' description
143     */
144    if ($position->x_percentage) {
145      $x_offset = ($padding_width  - $image_width)  * $position->x / 100;
146    } else {
147      $x_offset = $position->x;
148    }
149
150    /**
151     * Calculate the horizontal offset from the left padding edge to the background image left edge using current
152     * 'background-position' value
153     *
154     * @link file:///C:/docs/css/colors.html#propdef-background-position CSS 2 'background-position' description
155     */
156    if ($position->y_percentage) {
157      $y_offset = ($padding_height - $image_height) * $position->y / 100;
158    } else {
159      $y_offset = $position->y;
160    };
161
162    /**
163     * Output the image (probably tiling it; depends on current value of 'background-repeat') using
164     * current output driver's tiled image output functions. Note that px2pt(1) is an image scaling factor; as all
165     * page element are scaled to fit the media, background images should be scaled too!
166     *
167     * @see OutputDriver::image()
168     * @see OutputDriver::image_rx()
169     * @see OutputDriver::image_ry()
170     * @see OutputDriver::image_rxry()
171     *
172     * @link file:///C:/docs/css/colors.html#propdef-background-repeat CSS 2.1 'background-repeat' property description
173     */
174    switch ($repeat) {
175    case BR_NO_REPEAT:
176      /**
177       * 'background-repeat: no-repeat' case; no tiling at all
178       */
179      $driver->image($this->_image,
180                     $left + $x_offset,
181                     $top - $image_height - $y_offset,
182                     px2pt(1));
183      break;
184    case BR_REPEAT_X:
185      /**
186       * 'background-repeat: repeat-x' case; horizontal tiling
187       */
188      $driver->image_rx($this->_image,
189                        $left + $x_offset,
190                        $top - $image_height - $y_offset,
191                        $image_width,
192                        $right,
193                        $x_offset,
194                        $y_offset,
195                        px2pt(1));
196      break;
197    case BR_REPEAT_Y:
198      /**
199       * 'background-repeat: repeat-y' case; vertical tiling
200       */
201      $driver->image_ry($this->_image,
202                        $left + $x_offset,
203                        $top - $image_height - $y_offset,
204                        $image_height,
205                        $bottom,
206                        $x_offset,
207                        $y_offset,
208                        px2pt(1));
209      break;
210    case BR_REPEAT:
211      /**
212       * 'background-repeat: repeat' case; full tiling
213       */
214      $driver->image_rx_ry($this->_image,
215                           $left + $x_offset,
216                           $top - $image_height + $y_offset,
217                           $image_width,
218                           $image_height,
219                           $right,
220                           $bottom,
221                           $x_offset,
222                           $y_offset,
223                           px2pt(1));
224      break;
225    };
226
227    /**
228     * Restore the previous clipping area
229     *
230     * @see OutputDriver::clip()
231     * @see OutputDriver::restore()
232     */
233    $driver->restore();
234  }
235}
236
237?>