Files
server/usr/share/psa-pear/pear/php/Horde/Image/Swf.php
2026-01-07 20:52:11 +01:00

585 lines
18 KiB
PHP

<?php
/**
* Copyright 2002-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Image
*/
/**
* This class implements the Horde_Image API for SWF, using the PHP Ming
* extension.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @category Horde
* @copyright 2002-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Image
*/
class Horde_Image_Swf extends Horde_Image_Base
{
/**
* Capabilites of this driver.
*
* @var string[]
*/
protected $_capabilities = array(
'canvas',
'circle',
'dashedLine',
'line',
'polygon',
'polyline',
'rectangle',
'roundedRectangle',
'text',
);
/**
* SWF root movie.
*
* @var resource
*/
protected $_movie;
/**
* Constructor.
*
* @see Horde_Image_Base::_construct
*/
public function __construct($params, $context = array())
{
parent::__construct($params, $context);
$this->_movie = new SWFMovie();
$this->_movie->setDimension($this->_width, $this->_height);
$color = Horde_Image::getRGB($this->_background);
$this->_movie->setBackground($color[0], $color[1], $color[2]);
$this->_movie->setRate(30);
}
/**
* Returns the MIME type for this image.
*
* @return string The MIME type for this image.
*/
public function getContentType()
{
return 'application/x-shockwave-flash';
}
/**
* Displays the current image.
*/
public function display()
{
$this->headers();
$this->_movie->output();
}
/**
* Returns the raw data for this image.
*
* @return string The raw image data.
*/
public function raw()
{
ob_start();
$this->_movie->output();
$data = ob_get_clean();
return $data;
}
/**
* Creates a color that can be accessed in this object.
*
* When a color is set, the rgba values are returned in an array.
*
* @param string $name The name of the color.
*
* @return array The red, green, blue, alpha values of the color.
*/
public function allocateColor($name)
{
list($r, $g, $b) = Horde_Image::getRGB($name);
return array('red' => $r, 'green' => $g, 'blue' => $b, 'alpha' => 255);
}
/**
* Translates font names.
*
* @param string $font A font name.
*
* @return string An SWF font name.
*/
public function getFont($font)
{
switch ($font) {
case 'sans-serif':
return '_sans';
case 'serif':
return '_serif';
case 'monospace':
return '_typewriter';
default:
return $font;
}
}
/**
* Draws a text string on the image in a specified location, with the
* specified style information.
*
* @param string $text The text to draw.
* @param integer $x The left x coordinate of the start of the
* text string.
* @param integer $y The top y coordinate of the start of the text
* string.
* @param string $font The font identifier you want to use for the
* text.
* @param string $color The color that you want the text displayed in.
* @param integer $direction An integer that specifies the orientation of
* the text.
* @param string $fontsize Size of the font (small, medium, large, giant)
*/
public function text(
$string, $x, $y, $font = 'monospace', $color = 'black', $direction = 0
)
{
$color = $this->allocateColor($color);
$text = new SWFTextField(SWFTEXTFIELD_NOEDIT);
$text->setColor(
$color['red'], $color['green'], $color['blue'], $color['alpha']
);
$text->setFont(new SWFBrowserFont($this->getFont($font)));
$text->addString($string);
$t = $this->_movie->add($text);
$t->moveTo($x, $y);
$t->rotate($direction);
}
/**
* Draws a circle.
*
* @param integer $x The x co-ordinate of the centre.
* @param integer $y The y co-ordinate of the centre.
* @param integer $r The radius of the circle.
* @param string $color The line color of the circle.
* @param string $fill The color to fill the circle.
*/
public function circle($x, $y, $r, $color, $fill = 'none')
{
$s = new SWFShape();
$color = $this->allocateColor($color);
$s->setLine(
1, $color['red'], $color['green'], $color['blue'], $color['alpha']
);
if ($fill != 'none') {
$fillColor = $this->allocateColor($fill);
$f = $s->addFill(
$fillColor['red'],
$fillColor['green'],
$fillColor['blue'],
$fillColor['alpha']
);
$s->setRightFill($f);
}
$a = $r * 0.414213562; // = tan(22.5 deg)
$b = $r * 0.707106781; // = sqrt(2)/2 = sin(45 deg)
$s->movePenTo($x + $r, $y);
$s->drawCurveTo($x + $r, $y - $a, $x + $b, $y - $b);
$s->drawCurveTo($x + $a, $y - $r, $x, $y - $r);
$s->drawCurveTo($x - $a, $y - $r, $x - $b, $y - $b);
$s->drawCurveTo($x - $r, $y - $a, $x - $r, $y);
$s->drawCurveTo($x - $r, $y + $a, $x - $b, $y + $b);
$s->drawCurveTo($x - $a, $y + $r, $x, $y + $r);
$s->drawCurveTo($x + $a, $y + $r, $x + $b, $y + $b);
$s->drawCurveTo($x + $r, $y + $a, $x + $r, $y);
$this->_movie->add($s);
}
/**
* Draws a polygon based on a set of vertices.
*
* @param array $vertices An array of x and y labeled arrays
* (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
* @param string $color The color you want to draw the polygon with.
* @param string $fill The color to fill the polygon.
*/
public function polygon($verts, $color, $fill = 'none')
{
$color = $this->allocateColor($color);
if (!is_array($color) || !is_array($verts) || (sizeof($verts) <= 2)) {
return;
}
$shape = new SWFShape();
$shape->setLine(
1, $color['red'], $color['green'], $color['blue'], $color['alpha']
);
if ($fill != 'none') {
$fillColor = $this->allocateColor($fill);
$f = $shape->addFill(
$fillColor['red'],
$fillColor['green'],
$fillColor['blue'],
$fillColor['alpha']
);
$shape->setRightFill($f);
}
$first_done = false;
foreach ($verts as $value) {
if (!$first_done) {
$shape->movePenTo($value['x'], $value['y']);
$first_done = true;
$first_x = $value['x'];
$first_y = $value['y'];
}
$shape->drawLineTo($value['x'], $value['y']);
}
$shape->drawLineTo($first_x, $first_y);
$this->_movie->add($shape);
}
/**
* Draws a rectangle.
*
* @param integer $x The left x-coordinate of the rectangle.
* @param integer $y The top y-coordinate of the rectangle.
* @param integer $width The width of the rectangle.
* @param integer $height The height of the rectangle.
* @param string $color The line color of the rectangle.
* @param string $fill The color to fill the rectangle.
*/
public function rectangle($x, $y, $width, $height, $color, $fill = 'none')
{
$verts[0] = array('x' => $x, 'y' => $y);
$verts[1] = array('x' => $x + $width, 'y' => $y);
$verts[2] = array('x' => $x + $width, 'y' => $y + $height);
$verts[3] = array('x' => $x, 'y' => $y + $height);
$this->polygon($verts, $color, $fill);
}
/**
* Draws a rounded rectangle.
*
* @param integer $x The left x-coordinate of the rectangle.
* @param integer $y The top y-coordinate of the rectangle.
* @param integer $width The width of the rectangle.
* @param integer $height The height of the rectangle.
* @param integer $round The width of the corner rounding.
* @param string $color The line color of the rectangle.
* @param string $fill The color to fill the rectangle.
*/
public function roundedRectangle(
$x, $y, $width, $height, $round, $color = 'black', $fill = 'none'
)
{
if ($round <= 0) {
// Optimize out any calls with no corner rounding.
return $this->rectangle($x, $y, $width, $height, $color, $fill);
}
$s = new SWFShape();
$color = $this->allocateColor($color);
$s->setLine(
1, $color['red'], $color['green'], $color['blue'], $color['alpha']
);
if ($fill != 'none') {
$fillColor = $this->allocateColor($fill);
$f = $s->addFill(
$fillColor['red'],
$fillColor['green'],
$fillColor['blue'],
$fillColor['alpha']
);
$s->setRightFill($f);
}
// Set corner points to avoid lots of redundant math.
$x1 = $x + $round;
$y1 = $y + $round;
$x2 = $x + $width - $round;
$y2 = $y + $round;
$x3 = $x + $width - $round;
$y3 = $y + $height - $round;
$x4 = $x + $round;
$y4 = $y + $height - $round;
// Draw the upper left corner.
$s->movePenTo($x1, $y2);
$s->drawArc($round, 270, 360);
// Connect the top left and right curves.
$s->movePenTo($x1, $y);
$s->drawLineTo($x2, $y);
// Draw the upper right corner.
$s->movePenTo($x2, $y2);
$s->drawArc($round, 0, 90);
// Connect the top right and lower right curves.
$s->movePenTo($x + $width, $y2);
$s->drawLineTo($x + $width, $y3);
// Draw the lower right corner.
$s->movePenTo($x3, $y3);
$s->drawArc($round, 90, 180);
// Connect the bottom right and bottom left curves.
$s->movePenTo($x3, $y + $height);
$s->drawLineTo($x4, $y + $height);
// Draw the lower left corner.
$s->movePenTo($x4, $y4);
$s->drawArc($round, 180, 270);
// Connect the bottom left and top left curves.
$s->movePenTo($x, $y4);
$s->drawLineTo($x, $y1);
$this->_movie->add($s);
}
/**
* Draws a line.
*
* @param integer $x0 The x coordinate of the start.
* @param integer $y0 The y coordinate of the start.
* @param integer $x1 The x coordinate of the end.
* @param integer $y1 The y coordinate of the end.
* @param string $color The line color.
* @param string $width The width of the line.
*/
public function line($x1, $y1, $x2, $y2, $color = 'black', $width = 1)
{
$color = $this->allocateColor($color);
if (!is_array($color)) {
return;
}
$shape = new SWFShape();
$shape->setLine(
$width,
$color['red'],
$color['green'],
$color['blue'],
$color['alpha']
);
$shape->movePenTo($x1, $y1);
$shape->drawLineTo($x2, $y2);
$this->_movie->add($shape);
}
/**
* Draws a dashed line.
*
* @param integer $x0 The x co-ordinate of the start.
* @param integer $y0 The y co-ordinate of the start.
* @param integer $x1 The x co-ordinate of the end.
* @param integer $y1 The y co-ordinate of the end.
* @param string $color The line color.
* @param string $width The width of the line.
* @param integer $dash_length The length of a dash on the dashed line.
* @param integer $dash_space The length of a space in the dashed line.
*/
public function dashedLine(
$x0, $y0, $x1, $y1, $color = 'black', $width = 1, $dash_length = 2,
$dash_space = 2
)
{
// Get the length of the line in pixels.
$line_length = max(
ceil(sqrt(pow(($x1 - $x0), 2) + pow(($y1 - $y0), 2))),
2
);
$cosTheta = ($x1 - $x0) / $line_length;
$sinTheta = ($y1 - $y0) / $line_length;
$lastx = $x0;
$lasty = $y0;
// Draw the dashed line.
for ($i = 0; $i < $line_length; $i += ($dash_length + $dash_space)) {
$x = ($dash_length * $cosTheta) + $lastx;
$y = ($dash_length * $sinTheta) + $lasty;
$this->line($lastx, $lasty, $x, $y, $color);
$lastx = $x + ($dash_space * $cosTheta);
$lasty = $y + ($dash_space * $sinTheta);
}
}
/**
* Draws a polyline (a non-closed, non-filled polygon) based on a set of
* vertices.
*
* @param array $vertices An array of x and y labeled arrays
* (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
* @param string $color The color you want to draw the line with.
* @param string $width The width of the line.
*/
public function polyline($verts, $color, $width = 1)
{
$color = $this->allocateColor($color);
$shape = new SWFShape();
$shape->setLine(
$width,
$color['red'],
$color['green'],
$color['blue'],
$color['alpha']
);
$first_done = false;
foreach ($verts as $value) {
if (!$first_done) {
$shape->movePenTo($value['x'], $value['y']);
$first_done = true;
}
$shape->drawLineTo($value['x'], $value['y']);
}
$this->_movie->add($shape);
}
/**
* Draws an arc.
*
* @param integer $x The x co-ordinate of the centre.
* @param integer $y The y co-ordinate of the centre.
* @param integer $r The radius of the arc.
* @param integer $start The start angle of the arc.
* @param integer $end The end angle of the arc.
* @param string $color The line color of the arc.
* @param string $fill The fill color of the arc.
*/
public function arc(
$x, $y, $r, $start, $end, $color = 'black', $fill = 'none'
)
{
$s = new SWFShape();
$color = $this->allocateColor($color);
$s->setLine(
1, $color['red'], $color['green'], $color['blue'], $color['alpha']
);
if ($fill != 'none') {
$fillColor = $this->allocateColor($fill);
$s->setRightFill(
$fillColor['red'],
$fillColor['green'],
$fillColor['blue'],
$fillColor['alpha']
);
}
$pts = Horde_Image::arcPoints($r, $start, $end);
$s->movePenTo($x, $y);
$s->drawArc($r, $start + 90, $end + 90);
$s->movePenTo($x, $y);
$s->drawLineTo(round($pts['x1']) + $x, round($pts['y1']) + $y);
$s->movePenTo($x, $y);
$s->drawLineTo(round($pts['x2']) + $x, round($pts['y2']) + $y);
$this->_movie->add($s);
}
/**
* Draws a rectangle filled with a gradient.
*
* @param integer $x The left x-coordinate of the rectangle.
* @param integer $y The top y-coordinate of the rectangle.
* @param integer $width The width of the rectangle.
* @param integer $height The height of the rectangle.
* @param string $color The outline color of the rectangle.
* @param string $fill1 The name of the start color for the gradient.
* @param string $fill2 The name of the end color for the gradient.
*/
public function gradientRectangle(
$x, $y, $width, $height, $color = 'black',
$fill1 = 'black', $fill2 = 'white'
)
{
$s = new SWFShape();
if ($color != 'none') {
$color = $this->allocateColor($color);
$s->setLine(
1,
$color['red'],
$color['green'],
$color['blue'],
$color['alpha']
);
}
$fill1 = $this->allocateColor($fill1);
$fill2 = $this->allocateColor($fill2);
$gradient = new SWFGradient();
$gradient->addEntry(
0.0,
$fill1['red'],
$fill1['green'],
$fill1['blue'],
$fill1['alpha']
);
$gradient->addEntry(
1.0,
$fill2['red'],
$fill2['green'],
$fill2['blue'],
$fill2['alpha']
);
$f = $s->addFill($gradient, SWFFILL_LINEAR_GRADIENT);
$f->scaleTo($width / $this->_width);
$f->moveTo($x, $y);
$s->setRightFill($f);
$verts[0] = array('x' => $x, 'y' => $y);
$verts[1] = array('x' => $x + $width, 'y' => $y);
$verts[2] = array('x' => $x + $width, 'y' => $y + $height);
$verts[3] = array('x' => $x, 'y' => $y + $height);
$first_done = false;
foreach ($verts as $vert) {
if (!$first_done) {
$s->movePenTo($vert['x'], $vert['y']);
$first_done = true;
$first_x = $vert['x'];
$first_y = $vert['y'];
}
$s->drawLineTo($vert['x'], $vert['y']);
}
$s->drawLineTo($first_x, $first_y);
$this->_movie->add($s);
}
}