Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/1.2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- `phpoffice/phpspreadsheet`: Allow version 4.0 by [@nreynis](https://github.com/nreynis) in [#861](https://github.com/PHPOffice/PHPPresentation/pull/861)
- Smaller package size by [@nreynis](https://github.com/nreynis) in [#862](https://github.com/PHPOffice/PHPPresentation/pull/862)
- Added setFirstSliceAngle to Doughnut Chart by [@seanlynchwv](http://github.com/seanlynchwv) in [#872](https://github.com/PHPOffice/PHPPresentation/pull/872)
- Added ability to set rounded corner radius by [@seanlynchwv](http://github.com/seanlynchwv) in [#880](https://github.com/PHPOffice/PHPPresentation/pull/880)

## Bug fixes

Expand Down
27 changes: 27 additions & 0 deletions src/PhpPresentation/Shape/AutoShape.php
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,31 @@ public function setOutline(Outline $outline): self

return $this;
}

/** @var null|int */
private $roundRectAdj;

public function getRoundRectAdj(): ?int
{
return $this->roundRectAdj;
}

/**
* Set corner radius.
*/
public function setRoundRectCorner(int $pixels): self
{
$minHalf = (int) floor(min($this->width, $this->height) / 2);
if ($minHalf > 0) {
$this->roundRectAdj = max(0, min(50000, (int) round($pixels / $minHalf * 50000)));
}

return $this;
}

// override the hash so radius works
public function getHashCode(): string
{
return md5(parent::getHashCode() . $this->type . $this->text . (string) $this->roundRectAdj . __CLASS__);
}
}
18 changes: 15 additions & 3 deletions src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php
Original file line number Diff line number Diff line change
Expand Up @@ -1187,9 +1187,21 @@ protected function writeShapeAutoShape(XMLWriter $objWriter, AutoShape $shape, i
// p:sp\p:spPr\a:prstGeom
$objWriter->startElement('a:prstGeom');
$objWriter->writeAttribute('prst', $shape->getType());
// p:sp\p:spPr\a:prstGeom\a:avLst
$objWriter->writeElement('a:avLst');
// p:sp\p:spPr\a:prstGeom\

// a:avLst (+ optional adj for roundRect)
$needsAdj = ($shape->getType() === AutoShape::TYPE_ROUNDED_RECTANGLE);
$adj = $shape->getRoundRectAdj();

if ($needsAdj && $adj !== null) {
$objWriter->startElement('a:avLst');
$objWriter->startElement('a:gd');
$objWriter->writeAttribute('name', 'adj');
$objWriter->writeAttribute('fmla', 'val ' . (string) $adj); // 0..50000
$objWriter->endElement(); // a:gd
$objWriter->endElement(); // a:avLst
} else {
$objWriter->writeElement('a:avLst');
}
$objWriter->endElement();
// Fill
$this->writeFill($objWriter, $shape->getFill());
Expand Down
84 changes: 84 additions & 0 deletions tests/PhpPresentation/Tests/Shape/AutoShapeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@

namespace PhpOffice\PhpPresentation\Tests\Shape;

use PhpOffice\PhpPresentation\PhpPresentation;
use PhpOffice\PhpPresentation\Shape\AutoShape;
use PhpOffice\PhpPresentation\Style\Color;
use PhpOffice\PhpPresentation\Style\Fill;
use PhpOffice\PhpPresentation\Style\Outline;
use PhpOffice\PhpPresentation\Writer\PowerPoint2007;
use PHPUnit\Framework\TestCase;
use ZipArchive;

class AutoShapeTest extends TestCase
{
Expand Down Expand Up @@ -64,4 +69,83 @@ public function testType(): void
self::assertInstanceOf(AutoShape::class, $object->setType(AutoShape::TYPE_HEXAGON));
self::assertEquals(AutoShape::TYPE_HEXAGON, $object->getType());
}

public function testPixelSetterComputesAdjAndAffectsHash(): void
{
$width = 200; // px
$height = 100; // px
$px1 = 5; // softer radius
$px2 = 10; // larger radius

$shape1 = (new AutoShape())
->setType(AutoShape::TYPE_ROUNDED_RECTANGLE)
->setWidth($width)
->setHeight($height)
->setRoundRectCorner($px1);

$shape2 = (clone $shape1)->setRoundRectCorner($px2);

// adj expected: round(px / (min(w,h)/2) * 50000)
$minHalf = (int) floor(min($width, $height) / 2); // 50
$expectedAdj1 = (int) round($px1 / $minHalf * 50000); // 5/50 * 50000 = 5000
$expectedAdj2 = (int) round($px2 / $minHalf * 50000); // 10/50 * 50000 = 10000

self::assertSame($expectedAdj1, $shape1->getRoundRectAdj());
self::assertSame($expectedAdj2, $shape2->getRoundRectAdj());

// Hash must differ when radius differs
self::assertNotSame($shape1->getHashCode(), $shape2->getHashCode());
}

public function testNoRadiusByDefaultIsNull(): void
{
$shape = new AutoShape();
self::assertNull($shape->getRoundRectAdj());
}

public function testWriterEmitsAdjGuideForRoundRect(): void
{
$ppt = new PhpPresentation();
$slide = $ppt->getActiveSlide();

$width = 200;
$height = 100;
$padding = 5;
$minHalf = (int) floor(min($width, $height) / 2);
$expectedAdj = (int) round($padding / $minHalf * 50000); // 5000

$shape = (new AutoShape())
->setType(AutoShape::TYPE_ROUNDED_RECTANGLE)
->setWidth($width)->setHeight($height)
->setRoundRectCorner($padding);

// Give it a fill so it's an obvious shape
$shape->getFill()->setFillType(Fill::FILL_SOLID)->setStartColor(new Color('FFFFFFFF'));
$slide->addShape($shape);

$tmpFile = tempnam(sys_get_temp_dir(), 'pptx_');
$writer = new PowerPoint2007($ppt);
$writer->save($tmpFile);

// Open the pptx and read slide1.xml
$zip = new ZipArchive();
self::assertTrue($zip->open($tmpFile) === true, 'Failed to open pptx zip');
$xml = $zip->getFromName('ppt/slides/slide1.xml');
$zip->close();
@unlink($tmpFile);

self::assertIsString($xml);

// Must contain roundRect geometry and the adj guide with expected value
self::assertStringContainsString('<a:prstGeom prst="roundRect">', $xml);

// fmla="val N" (there is a space after 'val' in writer)
self::assertSame(
1,
preg_match(
sprintf('/<a:gd[^>]+name="adj"[^>]+fmla="val %d"/', $expectedAdj),
(string) $xml
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ public function testTypeAxisTickLabelPosition(): void

public function testTypeAxisUnit(): void
{
$value = mt_rand(0, 100);
$value = max(1, mt_rand(0, 100));

$series = new Series('Downloads', $this->seriesData);
$line = new Line();
Expand Down