diff options
author | Kore Nordmann <github@kore-nordmann.de> | 2009-02-03 18:23:28 +0000 |
---|---|---|
committer | Kore Nordmann <github@kore-nordmann.de> | 2009-02-03 18:23:28 +0000 |
commit | 1849ff7d52b3576da2d16c0095dcfa5090fbfc72 (patch) | |
tree | ea544d5612ec48204f500bd18f687fb45c39ce2f /src/renderer | |
parent | af6c8b78b44a48da82b94c0f47b248a66f54d275 (diff) | |
download | zetacomponents-graph-1849ff7d52b3576da2d16c0095dcfa5090fbfc72.zip zetacomponents-graph-1849ff7d52b3576da2d16c0095dcfa5090fbfc72.tar.gz |
- Refactored axis space handling in a BC compatible way. Fixes division by zero
errors with axis space equals 0. Partly resolves #013631.
- Added more tests for axis label renderers
# Several SVGs changed because of slight reordering of SVG elements which
# causes no visual differences.
Diffstat (limited to 'src/renderer')
-rw-r--r-- | src/renderer/2d.php | 266 | ||||
-rw-r--r-- | src/renderer/axis_label_boxed.php | 39 | ||||
-rw-r--r-- | src/renderer/axis_label_centered.php | 37 | ||||
-rw-r--r-- | src/renderer/axis_label_exact.php | 27 | ||||
-rw-r--r-- | src/renderer/axis_label_rotated.php | 39 |
5 files changed, 263 insertions, 145 deletions
diff --git a/src/renderer/2d.php b/src/renderer/2d.php index ac2ef93..b207ec1 100644 --- a/src/renderer/2d.php +++ b/src/renderer/2d.php @@ -1285,6 +1285,214 @@ class ezcGraphRenderer2d ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphChartElementAxis $axis, + ezcGraphAxisLabelRenderer $labelClass = null, + ezcGraphBoundings $innerBoundings = null ) + { + // Legacy axis drawing for BC reasons + if ( $innerBoundings === null ) + { + return $this->legacyDrawAxis( $boundings, $start, $end, $axis, $labelClass ); + } + + // Calculate axis start and end points depending on inner boundings + if ( ( $axis->position === ezcGraph::TOP ) || + ( $axis->position === ezcGraph::BOTTOM ) ) + { + $innerStart = new ezcGraphCoordinate( + $start->x + $boundings->x0, + ( $axis->position === ezcGraph::TOP ? $innerBoundings->y0 : $innerBoundings->y1 ) + ); + $innerEnd = new ezcGraphCoordinate( + $end->x + $boundings->x0, + ( $axis->position === ezcGraph::TOP ? $innerBoundings->y1 : $innerBoundings->y0 ) + ); + } + else + { + $innerStart = new ezcGraphCoordinate( + ( $axis->position === ezcGraph::LEFT ? $innerBoundings->x0 : $innerBoundings->x1 ), + $start->y + $boundings->y0 + ); + $innerEnd = new ezcGraphCoordinate( + ( $axis->position === ezcGraph::LEFT ? $innerBoundings->x1 : $innerBoundings->x0 ), + $end->y + $boundings->y0 + ); + } + + // Shorten axis, if requested + if ( $this->options->shortAxis ) + { + $start = clone $innerStart; + $end = clone $innerEnd; + } + else + { + $start->x += $boundings->x0; + $start->y += $boundings->y0; + $end->x += $boundings->x0; + $end->y += $boundings->y0; + } + + // Determine normalized direction + $direction = new ezcGraphVector( + $start->x - $end->x, + $start->y - $end->y + ); + $direction->unify(); + + // Draw axis + $this->driver->drawLine( + $start, + $end, + $axis->border, + 1 + ); + + // Draw small arrowhead + $this->drawAxisArrowHead( + $end, + $direction, + max( + $axis->minArrowHeadSize, + min( + $axis->maxArrowHeadSize, + abs( ceil( ( ( $end->x - $start->x ) + ( $end->y - $start->y ) ) * $axis->axisSpace / 4 ) ) + ) + ), + $axis->border + ); + + // Draw axis label, if set + $this->drawAxisLabel( $end, $innerBoundings, $axis ); + + // If font should not be synchronized, use font configuration from + // each axis + if ( $this->options->syncAxisFonts === false ) + { + $this->driver->options->font = $axis->font; + } + + $labelClass->renderLabels( + $this, + $boundings, + $innerStart, + $innerEnd, + $axis, + $innerBoundings + ); + } + + /** + * Draw axis label + * + * Draw labels at the end of an axis. + * + * @param ezcGraphCoordinate $position + * @param ezcGraphBoundings $boundings + * @param ezcGraphChartElementAxis $axis + * @return void + */ + protected function drawAxisLabel( ezcGraphCoordinate $position, ezcGraphBoundings $boundings, ezcGraphChartElementAxis $axis ) + { + if ( $axis->label === false ) + { + return; + } + + $width = $boundings->width; + switch ( $axis->position ) + { + case ezcGraph::TOP: + $this->driver->drawTextBox( + $axis->label, + new ezcGraphCoordinate( + $position->x + $axis->labelMargin - $width * ( 1 - $axis->axisSpace * 2 ), + $position->y - $axis->labelMargin - $axis->labelSize + ), + $width * ( 1 - $axis->axisSpace * 2 ) - $axis->labelMargin, + $axis->labelSize, + ezcGraph::TOP | ezcGraph::RIGHT + ); + break; + case ezcGraph::BOTTOM: + $this->driver->drawTextBox( + $axis->label, + new ezcGraphCoordinate( + $position->x + $axis->labelMargin, + $position->y + $axis->labelMargin + ), + $width * ( 1 - $axis->axisSpace * 2 ) - $axis->labelMargin, + $axis->labelSize, + ezcGraph::TOP | ezcGraph::LEFT + ); + break; + case ezcGraph::LEFT: + $this->driver->drawTextBox( + $axis->label, + new ezcGraphCoordinate( + $position->x - $width, + $position->y - $axis->labelSize - $axis->labelMargin + ), + $width - $axis->labelMargin, + $axis->labelSize, + ezcGraph::BOTTOM | ezcGraph::RIGHT + ); + break; + case ezcGraph::RIGHT: + $this->driver->drawTextBox( + $axis->label, + new ezcGraphCoordinate( + $position->x, + $position->y - $axis->labelSize - $axis->labelMargin + ), + $width - $axis->labelMargin, + $axis->labelSize, + ezcGraph::BOTTOM | ezcGraph::LEFT + ); + break; + } + } + + /** + * Draw axis + * + * Draws an axis form the provided start point to the end point. A specific + * angle of the axis is not required. + * + * For the labeleing of the axis a sorted array with major steps and an + * array with minor steps is expected, which are build like this: + * array( + * array( + * 'position' => (float), + * 'label' => (string), + * ) + * ) + * where the label is optional. + * + * The label renderer class defines how the labels are rendered. For more + * documentation on this topic have a look at the basic label renderer + * class. + * + * Additionally it can be specified if a major and minor grid are rendered + * by defining a color for them. The axis label is used to add a caption + * for the axis. + * + * This function is deprecated and will be removed in favor of its + * reimplementation using the innerBoundings parameter. + * + * @param ezcGraphBoundings $boundings Boundings of axis + * @param ezcGraphCoordinate $start Start point of axis + * @param ezcGraphCoordinate $end Endpoint of axis + * @param ezcGraphChartElementAxis $axis Axis to render + * @param ezcGraphAxisLabelRenderer $labelClass Used label renderer + * @apichange + * @return void + */ + protected function legacyDrawAxis( + ezcGraphBoundings $boundings, + ezcGraphCoordinate $start, + ezcGraphCoordinate $end, + ezcGraphChartElementAxis $axis, ezcGraphAxisLabelRenderer $labelClass = null ) { // Store axis space for use by label renderer @@ -1368,62 +1576,8 @@ class ezcGraphRenderer2d $axis->border ); - // Draw axis label - if ( $axis->label !== false ) - { - $width = $boundings->width; - switch ( $axis->position ) - { - case ezcGraph::TOP: - $this->driver->drawTextBox( - $axis->label, - new ezcGraphCoordinate( - $end->x + $axis->labelMargin - $width * ( 1 - $axis->axisSpace * 2 ), - $end->y - $axis->labelMargin - $axis->labelSize - ), - $width * ( 1 - $axis->axisSpace * 2 ) - $axis->labelMargin, - $axis->labelSize, - ezcGraph::TOP | ezcGraph::RIGHT - ); - break; - case ezcGraph::BOTTOM: - $this->driver->drawTextBox( - $axis->label, - new ezcGraphCoordinate( - $end->x + $axis->labelMargin, - $end->y + $axis->labelMargin - ), - $width * ( 1 - $axis->axisSpace * 2 ) - $axis->labelMargin, - $axis->labelSize, - ezcGraph::TOP | ezcGraph::LEFT - ); - break; - case ezcGraph::LEFT: - $this->driver->drawTextBox( - $axis->label, - new ezcGraphCoordinate( - $end->x - $width, - $end->y - $axis->labelSize - $axis->labelMargin - ), - $width - $axis->labelMargin, - $axis->labelSize, - ezcGraph::BOTTOM | ezcGraph::RIGHT - ); - break; - case ezcGraph::RIGHT: - $this->driver->drawTextBox( - $axis->label, - new ezcGraphCoordinate( - $end->x, - $end->y - $axis->labelSize - $axis->labelMargin - ), - $width - $axis->labelMargin, - $axis->labelSize, - ezcGraph::BOTTOM | ezcGraph::LEFT - ); - break; - } - } + // Draw axis label, if set + $this->drawAxisLabel( $end, $boundings, $axis ); // Collect axis labels and draw, when all axisSpaces are collected $this->axisLabels[] = array( diff --git a/src/renderer/axis_label_boxed.php b/src/renderer/axis_label_boxed.php index d542944..4309d4c 100644 --- a/src/renderer/axis_label_boxed.php +++ b/src/renderer/axis_label_boxed.php @@ -74,7 +74,8 @@ class ezcGraphAxisBoxedLabelRenderer extends ezcGraphAxisLabelRenderer ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, - ezcGraphChartElementAxis $axis ) + ezcGraphChartElementAxis $axis, + ezcGraphBoundings $innerBoundings = null ) { // receive rendering parameters from axis $steps = $axis->getSteps(); @@ -87,24 +88,14 @@ class ezcGraphAxisBoxedLabelRenderer extends ezcGraphAxisLabelRenderer // Determine normalized axis direction $this->direction = new ezcGraphVector( - $start->x - $end->x, - $start->y - $end->y + $end->x - $start->x, + $end->y - $start->y ); $this->direction->unify(); - if ( $this->outerGrid ) - { - $gridBoundings = $boundings; - } - else - { - $gridBoundings = new ezcGraphBoundings( - $boundings->x0 + $renderer->xAxisSpace * abs( $this->direction->y ), - $boundings->y0 + $renderer->yAxisSpace * abs( $this->direction->x ), - $boundings->x1 - $renderer->xAxisSpace * abs( $this->direction->y ), - $boundings->y1 - $renderer->yAxisSpace * abs( $this->direction->x ) - ); - } + // Get axis space + $gridBoundings = null; + list( $xSpace, $ySpace ) = $this->getAxisSpace( $renderer, $boundings, $axis, $innerBoundings, $gridBoundings ); // Determine additional required axis space by boxes $firstStep = reset( $steps ); @@ -133,30 +124,30 @@ class ezcGraphAxisBoxedLabelRenderer extends ezcGraphAxisLabelRenderer switch ( true ) { case ( abs( $this->direction->x ) > abs( $this->direction->y ) ) && - ( $this->direction->x <= 0 ): + ( $this->direction->x > 0 ): $labelBoundings = new ezcGraphBoundings( $position->x - $stepSize->x + $this->labelPadding, $position->y + $this->labelPadding, $position->x - $this->labelPadding, - $position->y + $renderer->yAxisSpace - $this->labelPadding + $position->y + $ySpace - $this->labelPadding ); $alignement = ezcGraph::CENTER | ezcGraph::TOP; break; case ( abs( $this->direction->x ) > abs( $this->direction->y ) ) && - ( $this->direction->x > 0 ): + ( $this->direction->x < 0 ): $labelBoundings = new ezcGraphBoundings( $position->x + $this->labelPadding, $position->y + $this->labelPadding, $position->x + $stepSize->x - $this->labelPadding, - $position->y + $renderer->yAxisSpace - $this->labelPadding + $position->y + $ySpace - $this->labelPadding ); $alignement = ezcGraph::CENTER | ezcGraph::TOP; break; - case ( $this->direction->y <= 0 ): + case ( $this->direction->y > 0 ): $labelBoundings = new ezcGraphBoundings( - $position->x - $renderer->xAxisSpace + $this->labelPadding, + $position->x - $xSpace + $this->labelPadding, $position->y - $stepSize->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y - $this->labelPadding @@ -164,9 +155,9 @@ class ezcGraphAxisBoxedLabelRenderer extends ezcGraphAxisLabelRenderer $alignement = ezcGraph::MIDDLE | ezcGraph::RIGHT; break; - case ( $this->direction->y > 0 ): + case ( $this->direction->y < 0 ): $labelBoundings = new ezcGraphBoundings( - $position->x - $renderer->xAxisSpace + $this->labelPadding, + $position->x - $xSpace + $this->labelPadding, $position->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $stepSize->y - $this->labelPadding diff --git a/src/renderer/axis_label_centered.php b/src/renderer/axis_label_centered.php index e0568da..065b75e 100644 --- a/src/renderer/axis_label_centered.php +++ b/src/renderer/axis_label_centered.php @@ -85,7 +85,8 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, - ezcGraphChartElementAxis $axis ) + ezcGraphChartElementAxis $axis, + ezcGraphBoundings $innerBoundings = null ) { // receive rendering parameters from axis $steps = $axis->getSteps(); @@ -97,24 +98,14 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer // Determine normalized axis direction $direction = new ezcGraphVector( - $start->x - $end->x, - $start->y - $end->y + $end->x - $start->x, + $end->y - $start->y ); $direction->unify(); - - if ( $this->outerGrid ) - { - $gridBoundings = $boundings; - } - else - { - $gridBoundings = new ezcGraphBoundings( - $boundings->x0 + $renderer->xAxisSpace * abs( $direction->y ), - $boundings->y0 + $renderer->yAxisSpace * abs( $direction->x ), - $boundings->x1 - $renderer->xAxisSpace * abs( $direction->y ), - $boundings->y1 - $renderer->yAxisSpace * abs( $direction->x ) - ); - } + + // Get axis space + $gridBoundings = null; + list( $xSpace, $ySpace ) = $this->getAxisSpace( $renderer, $boundings, $axis, $innerBoundings, $gridBoundings ); // Draw steps and grid foreach ( $steps as $nr => $step ) @@ -165,14 +156,14 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer case ( $nr === 0 ): // First label $labelSize = min( - $renderer->xAxisSpace * 2, + $xSpace * 2, $step->width * $axisBoundings->width ); break; case ( $step->isLast ): // Last label $labelSize = min( - $renderer->xAxisSpace * 2, + $xSpace * 2, $steps[$nr - 1]->width * $axisBoundings->width ); break; @@ -188,7 +179,7 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer $position->x - $labelSize / 2 + $this->labelPadding, $position->y + $this->labelPadding, $position->x + $labelSize / 2 - $this->labelPadding, - $position->y + $renderer->yAxisSpace - $this->labelPadding + $position->y + $ySpace - $this->labelPadding ); $alignement = ezcGraph::CENTER | ezcGraph::TOP; @@ -201,14 +192,14 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer case ( $nr === 0 ): // First label $labelSize = min( - $renderer->yAxisSpace * 2, + $ySpace * 2, $step->width * $axisBoundings->height ); break; case ( $step->isLast ): // Last label $labelSize = min( - $renderer->yAxisSpace * 2, + $ySpace * 2, $steps[$nr - 1]->width * $axisBoundings->height ); break; @@ -221,7 +212,7 @@ class ezcGraphAxisCenteredLabelRenderer extends ezcGraphAxisLabelRenderer } $labelBoundings = new ezcGraphBoundings( - $position->x - $renderer->xAxisSpace + $this->labelPadding, + $position->x - $xSpace + $this->labelPadding, $position->y - $labelSize / 2 + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $labelSize / 2 - $this->labelPadding diff --git a/src/renderer/axis_label_exact.php b/src/renderer/axis_label_exact.php index c8189de..a09543d 100644 --- a/src/renderer/axis_label_exact.php +++ b/src/renderer/axis_label_exact.php @@ -92,7 +92,8 @@ class ezcGraphAxisExactLabelRenderer extends ezcGraphAxisLabelRenderer ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, - ezcGraphChartElementAxis $axis ) + ezcGraphChartElementAxis $axis, + ezcGraphBoundings $innerBoundings = null ) { // receive rendering parameters from axis $steps = $axis->getSteps(); @@ -104,24 +105,14 @@ class ezcGraphAxisExactLabelRenderer extends ezcGraphAxisLabelRenderer // Determine normalized axis direction $direction = new ezcGraphVector( - $start->x - $end->x, - $start->y - $end->y + $end->x - $start->x, + $end->y - $start->y ); $direction->unify(); - if ( $this->outerGrid ) - { - $gridBoundings = $boundings; - } - else - { - $gridBoundings = new ezcGraphBoundings( - $boundings->x0 + $renderer->xAxisSpace * abs( $direction->y ), - $boundings->y0 + $renderer->yAxisSpace * abs( $direction->x ), - $boundings->x1 - $renderer->xAxisSpace * abs( $direction->y ), - $boundings->y1 - $renderer->yAxisSpace * abs( $direction->x ) - ); - } + // Get axis space + $gridBoundings = null; + list( $xSpace, $ySpace ) = $this->getAxisSpace( $renderer, $boundings, $axis, $innerBoundings, $gridBoundings ); // Draw steps and grid foreach ( $steps as $nr => $step ) @@ -169,7 +160,7 @@ class ezcGraphAxisExactLabelRenderer extends ezcGraphAxisLabelRenderer $labelWidth = $axisBoundings->width * $steps[$nr - $step->isLast]->width / ( $this->showLastValue + 1 ); - $labelHeight = $renderer->yAxisSpace; + $labelHeight = $ySpace; if ( ( $this->renderLastOutside === true ) && ( $step->isLast === true ) ) @@ -180,7 +171,7 @@ class ezcGraphAxisExactLabelRenderer extends ezcGraphAxisLabelRenderer case ezcGraph::BOTTOM: case ezcGraph::TOP: - $labelWidth = $renderer->xAxisSpace; + $labelWidth = $xSpace; $labelHeight = $axisBoundings->height * $steps[$nr - $step->isLast]->width / ( $this->showLastValue + 1 ); diff --git a/src/renderer/axis_label_rotated.php b/src/renderer/axis_label_rotated.php index de37691..8acbed7 100644 --- a/src/renderer/axis_label_rotated.php +++ b/src/renderer/axis_label_rotated.php @@ -130,7 +130,8 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, - ezcGraphChartElementAxis $axis ) + ezcGraphChartElementAxis $axis, + ezcGraphBoundings $innerBoundings = null ) { // receive rendering parameters from axis $steps = $axis->getSteps(); @@ -149,19 +150,9 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer $this->direction->unify(); $axisAngle = -$this->direction->angle( new ezcGraphVector( 1, 0 ) ); - if ( $this->outerGrid ) - { - $gridBoundings = $boundings; - } - else - { - $gridBoundings = new ezcGraphBoundings( - $boundings->x0 + $renderer->xAxisSpace, - $boundings->y0 + $renderer->yAxisSpace, - $boundings->x1 - $renderer->xAxisSpace, - $boundings->y1 - $renderer->yAxisSpace - ); - } + // Get axis space + $gridBoundings = null; + list( $xSpace, $ySpace ) = $this->getAxisSpace( $renderer, $boundings, $axis, $innerBoundings, $gridBoundings ); // Determine optimal angle if none specified if ( $this->angle === null ) @@ -181,8 +172,8 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer $axisBoundings->height * $minimumStepWidth * $this->direction->y ); $height = abs( - $renderer->yAxisSpace * $this->direction->x + - $renderer->xAxisSpace * $this->direction->y + $ySpace * $this->direction->x + + $xSpace * $this->direction->y ); $length = sqrt( pow( $width, 2 ) + pow( $height, 2 ) ); @@ -218,9 +209,9 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer $axisSpaceFactor = abs( ( $this->direction->x == 0 ? 0 : - $this->direction->x * $renderer->yAxisSpace / $axisBoundings->width ) + + $this->direction->x * $ySpace / $axisBoundings->width ) + ( $this->direction->y == 0 ? 0 : - $this->direction->y * $renderer->xAxisSpace / $axisBoundings->height ) + $this->direction->y * $xSpace / $axisBoundings->height ) ); $start = new ezcGraphCoordinate( @@ -234,11 +225,11 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer $labelLength = sqrt( pow( - $renderer->xAxisSpace * $this->direction->y + + $xSpace * $this->direction->y + $axisSpaceFactor * $this->offset * ( $end->x - $start->x ), 2 ) + pow( - $renderer->yAxisSpace * $this->direction->x + + $ySpace * $this->direction->x + $axisSpaceFactor * $this->offset * ( $end->y - $start->y ), 2 ) ); @@ -264,8 +255,8 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer case ( $nr === 0 ): $labelSize = min( abs( - $renderer->xAxisSpace * 2 * $this->direction->x + - $renderer->yAxisSpace * 2 * $this->direction->y ), + $xSpace * 2 * $this->direction->x + + $ySpace * 2 * $this->direction->y ), abs( $step->width * $axisBoundings->width * $this->direction->x + $step->width * $axisBoundings->height * $this->direction->y ) @@ -274,8 +265,8 @@ class ezcGraphAxisRotatedLabelRenderer extends ezcGraphAxisLabelRenderer case ( $step->isLast ): $labelSize = min( abs( - $renderer->xAxisSpace * 2 * $this->direction->x + - $renderer->yAxisSpace * 2 * $this->direction->y ), + $xSpace * 2 * $this->direction->x + + $ySpace * 2 * $this->direction->y ), abs( $steps[$nr - 1]->width * $axisBoundings->width * $this->direction->x + $steps[$nr - 1]->width * $axisBoundings->height * $this->direction->y ) |