icingaweb2/library/Icinga/Chart/Render/RenderContext.php

227 lines
6.3 KiB
PHP

<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Chart\Render;
use DOMDocument;
/**
* Context for rendering, handles ratio based coordinate calculations.
*
* The most important functions when rendering are the toAbsolute and roRelative
* values, taking world coordinates and translating them into local coordinates.
*/
class RenderContext
{
/**
* The base size of the viewport, i.e. how many units are available on a 1:1 ratio
*
* @var array
*/
private $viewBoxSize = array(1000, 1000);
/**
* The DOMDocument for modifying the elements
*
* @var DOMDocument
*/
private $document;
/**
* If true no ratio correction will be made
*
* @var bool
*/
private $respectRatio = false;
/**
* The ratio on the x side. A x ration of 2 means that the width of the SVG is divided in 2000
* units (see $viewBox)
*
* @var int
*/
private $xratio = 1;
/**
* The ratio on the y side. A y ration of 2 means that the height of the SVG is divided in 2000
* units (see $viewBox)
*
* @var int
*/
private $yratio = 1;
/**
* Creates a new context for the given DOM Document
*
* @param DOMDocument $document The DOM document represented by this context
* @param int $width The width (may be approximate) of the document
* (only required for ratio calculation)
* @param int $height The height (may be approximate) of the document
* (only required for ratio calculation)
*/
public function __construct(DOMDocument $document, $width, $height)
{
$this->document = $document;
if ($width > $height) {
$this->xratio = $width / $height;
} elseif ($height > $width) {
$this->yratio = $height / $width;
}
}
/**
* Return the document represented by this Rendering context
*
* @return DOMDocument The DOMDocument for creating files
*/
public function getDocument()
{
return $this->document;
}
/**
* Let successive toAbsolute operations ignore ratio correction
*
* This can be called to avoid distortion on certain elements like rectangles.
*/
public function keepRatio()
{
$this->respectRatio = true;
}
/**
* Let successive toAbsolute operations perform ratio correction
*
* This will cause distortion on certain elements like rectangles.
*/
public function ignoreRatio()
{
$this->respectRatio = false;
}
/**
* Return how many unit s are available in the Y axis
*
* @return int The number of units available on the y axis
*/
public function getNrOfUnitsY()
{
return intval($this->viewBoxSize[1] * $this->yratio);
}
/**
* Return how many unit s are available in the X axis
*
* @return int The number of units available on the x axis
*/
public function getNrOfUnitsX()
{
return intval($this->viewBoxSize[0] * $this->xratio);
}
/**
* Transforms the x,y coordinate from relative coordinates to absolute world coordinates
*
* (50, 50) would be a point in the middle of the document and map to 500, 1000 on a
* 1000 x 1000 viewbox with a 1:2 ratio.
*
* @param int $x The relative x coordinate
* @param int $y The relative y coordinate
*
* @return array An x,y tuple containing absolute coordinates
* @see RenderContext::toRelative
*/
public function toAbsolute($x, $y)
{
return array($this->xToAbsolute($x), $this->yToAbsolute($y));
}
/**
* Transforms the x,y coordinate from absolute coordinates to relative world coordinates
*
* This is the inverse function of toAbsolute
*
* @param int $x The absolute x coordinate
* @param int $y The absolute y coordinate
*
* @return array An x,y tupel containing absolute coordinates
* @see RenderContext::toAbsolute
*/
public function toRelative($x, $y)
{
return array($this->xToRelative($x), $this->yToRelative($y));
}
/**
* Calculates the scale transformation required to apply the padding on an Canvas
*
* @param array $padding A 4 element array containing top, right, bottom and left padding
*
* @return array An array containing the x and y scale
*/
public function paddingToScaleFactor(array $padding)
{
list($horizontalPadding, $verticalPadding) = $this->toAbsolute(
$padding[LayoutBox::PADDING_RIGHT] + $padding[LayoutBox::PADDING_LEFT],
$padding[LayoutBox::PADDING_TOP] + $padding[LayoutBox::PADDING_BOTTOM]
);
return array(
($this->getNrOfUnitsX() - $horizontalPadding) / $this->getNrOfUnitsX(),
($this->getNrOfUnitsY() - $verticalPadding) / $this->getNrOfUnitsY()
);
}
/**
* Transform a relative x coordinate to an absolute one
*
* @param int $x A relative x coordinate
*
* @return int An absolute x coordinate
**/
public function xToAbsolute($x)
{
return $this->getNrOfUnitsX() / 100 * $x / ($this->respectRatio ? $this->xratio : 1);
}
/**
* Transform a relative y coordinate to an absolute one
*
* @param int $y A relative y coordinate
*
* @return int An absolute y coordinate
*/
public function yToAbsolute($y)
{
return $this->getNrOfUnitsY() / 100 * $y / ($this->respectRatio ? $this->yratio : 1);
}
/**
* Transform a absolute x coordinate to an relative one
*
* @param int $x An absolute x coordinate
*
* @return int A relative x coordinate
*/
public function xToRelative($x)
{
return $x / $this->getNrOfUnitsX() * 100 * ($this->respectRatio ? $this->xratio : 1);
}
/**
* Transform a absolute y coordinate to an relative one
*
* @param int $y An absolute x coordinate
*
* @return int A relative x coordinate
*/
public function yToRelative($y)
{
return $y / $this->getNrOfUnitsY() * 100 * ($this->respectRatio ? $this->yratio : 1);
}
}