From 5bf52142b7d1cf3f728b657af68156bd6cf4bc64 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 13 Oct 2017 23:41:46 +0200 Subject: [PATCH] ODPresentation Writer : Support for rotation for RichText --- docs/changes/1.2.0.md | 7 +-- samples/Sample_11_Shape.php | 20 ++++++++ samples/Sample_Header.php | 1 + src/PhpPresentation/AbstractShape.php | 14 ++---- .../Writer/ODPresentation/Content.php | 47 ++++++++++++++++++- .../Writer/PowerPoint2007/AbstractSlide.php | 6 +-- .../Writer/ODPresentation/ContentTest.php | 14 ++++++ 7 files changed, 91 insertions(+), 18 deletions(-) diff --git a/docs/changes/1.2.0.md b/docs/changes/1.2.0.md index 5ed1d7578..859495618 100644 --- a/docs/changes/1.2.0.md +++ b/docs/changes/1.2.0.md @@ -4,12 +4,13 @@ ## Enhancements -- `phpoffice/phpspreadsheet`: Allow version 1.9 or 2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#790](https://github.com/PHPOffice/PHPPresentation/pull/790), [#812](https://github.com/PHPOffice/PHPPresentation/pull/812) in [#816](https://github.com/PHPOffice/PHPPresentation/pull/816) +- `phpoffice/phpspreadsheet`: Allow version 1.9 or 2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#790](https://github.com/PHPOffice/PHPPresentation/issues/790), [#812](https://github.com/PHPOffice/PHPPresentation/pull/812) in [#816](https://github.com/PHPOffice/PHPPresentation/pull/816) - Group Shape: moving the shape now moves all contained shapes. Offsets and size are calculated based on the contained shapes by [@DennisBirkholz](https://github.com/DennisBirkholz) in [#690](https://github.com/PHPOffice/PHPPresentation/pull/690) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#839](https://github.com/PHPOffice/PHPPresentation/pull/839) -- `phpoffice/phpspreadsheet`: Allow version 3.0 by [@Progi1984](https://github.com/Progi1984) fixing [#836](https://github.com/PHPOffice/PHPPresentation/pull/836) in [#839](https://github.com/PHPOffice/PHPPresentation/pull/839) +- `phpoffice/phpspreadsheet`: Allow version 3.0 by [@Progi1984](https://github.com/Progi1984) fixing [#836](https://github.com/PHPOffice/PHPPresentation/issues/836) in [#839](https://github.com/PHPOffice/PHPPresentation/pull/839) - `createAutoShape` : Add method to create geometric shapes by [@mhasanshahid](https://github.com/mhasanshahid) & [@Progi1984](https://github.com/Progi1984) in [#848](https://github.com/PHPOffice/PHPPresentation/pull/848) -- Reader : Option to not load images by [@Progi1984](https://github.com/Progi1984) fixing [#795](https://github.com/PHPOffice/PHPPresentation/pull/795) in [#850](https://github.com/PHPOffice/PHPPresentation/pull/850) +- Reader : Option to not load images by [@Progi1984](https://github.com/Progi1984) fixing [#795](https://github.com/PHPOffice/PHPPresentation/issues/795) in [#850](https://github.com/PHPOffice/PHPPresentation/pull/850) +- ODPresentation Writer : Support for rotation for RichText by [@Progi1984](https://github.com/Progi1984) fixing [#279](https://github.com/PHPOffice/PHPPresentation/pull/279) in [#409](https://github.com/PHPOffice/PHPPresentation/pull/409) ## Bug fixes diff --git a/samples/Sample_11_Shape.php b/samples/Sample_11_Shape.php index af3059f2b..003746480 100644 --- a/samples/Sample_11_Shape.php +++ b/samples/Sample_11_Shape.php @@ -81,6 +81,25 @@ function fnSlideRichTextLineSpacing(PhpPresentation $objPHPPresentation): void $shape->createTextRun('Line Spacing 300'); } +function fnSlideRichTextRotation(PhpPresentation $objPHPPresentation): void +{ + // Create templated slide + echo date('H:i:s') . ' Create templated slide' . EOL; + $currentSlide = createTemplatedSlide($objPHPPresentation); + + // Create a shape (text) + echo date('H:i:s') . ' Create a shape (rich text) with rotation' . EOL; + $shape = $currentSlide->createRichTextShape(); + $shape->setHeight(100); + $shape->setWidth(200); + $shape->setOffsetX(200); + $shape->setOffsetY(200); + $shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); + $shape->setRotation(90); + + $shape->createTextRun('RichText with rotation'); +} + function fnSlideRichTextShadow(PhpPresentation $objPHPPresentation): void { // Create templated slide @@ -143,6 +162,7 @@ function fnSlideRichTextList(PhpPresentation $objPHPPresentation): void fnSlideRichText($objPHPPresentation); fnSlideRichTextLineSpacing($objPHPPresentation); +fnSlideRichTextRotation($objPHPPresentation); fnSlideRichTextShadow($objPHPPresentation); fnSlideRichTextList($objPHPPresentation); diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 86e2fa334..4a86a4100 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -92,6 +92,7 @@ if (preg_match('/^Sample_\d+_/', $file)) { $name = str_replace('_', ' ', preg_replace('/(Sample_|\.php)/', '', $file)); $group = substr($name, 0, 1); + $id = substr($name, 0, 2); if (!isset($files[$group])) { $files[$group] = []; } diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index f91a3b401..e71fefbac 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -85,7 +85,7 @@ abstract class AbstractShape implements ComparableInterface * * @var int */ - protected $rotation; + protected $rotation = 0; /** * Shadow. @@ -123,7 +123,7 @@ abstract class AbstractShape implements ComparableInterface */ public function __construct() { - $this->offsetX = $this->offsetY = $this->width = $this->height = $this->rotation = 0; + $this->offsetX = $this->offsetY = $this->width = $this->height = 0; $this->fill = new Fill(); $this->shadow = new Shadow(); $this->border = new Border(); @@ -319,22 +319,16 @@ public function setWidthAndHeight(int $width = 0, int $height = 0) /** * Get Rotation. - * - * @return int */ - public function getRotation() + public function getRotation(): int { return $this->rotation; } /** * Set Rotation. - * - * @param int $pValue - * - * @return $this */ - public function setRotation($pValue = 0) + public function setRotation(int $pValue = 0): self { $this->rotation = $pValue; diff --git a/src/PhpPresentation/Writer/ODPresentation/Content.php b/src/PhpPresentation/Writer/ODPresentation/Content.php index 3ee509495..6f785a6e6 100644 --- a/src/PhpPresentation/Writer/ODPresentation/Content.php +++ b/src/PhpPresentation/Writer/ODPresentation/Content.php @@ -501,8 +501,19 @@ protected function writeShapeTxt(XMLWriter $objWriter, RichText $shape): void $objWriter->writeAttribute('draw:style-name', 'gr' . $this->shapeId); $objWriter->writeAttribute('svg:width', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getWidth()), 3) . 'cm'); $objWriter->writeAttribute('svg:height', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getHeight()), 3) . 'cm'); - $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetX()), 3) . 'cm'); - $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetY()), 3) . 'cm'); + if ($shape->getRotation() != 0) { + $rotRad = deg2rad($shape->getRotation()); + + $translateX = Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetY()), 3) . 'cm'; + $translateY = Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetX()), 3) . 'cm'; + $objWriter->writeAttribute( + 'draw:transform', + 'rotate (-' . $rotRad . ') translate (' . $translateX . ' ' . $translateY . ')' + ); + } else { + $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetX()), 3) . 'cm'); + $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters((int) $shape->getOffsetY()), 3) . 'cm'); + } // draw:text-box $objWriter->startElement('draw:text-box'); @@ -642,6 +653,38 @@ protected function writeShapeTxt(XMLWriter $objWriter, RichText $shape): void } } + if ($shape->getRotation() != 0) { + $objWriter->startElement('draw:enhanced-geometry'); + $objWriter->writeAttribute('draw:mirror-horizontal', 'false'); + $objWriter->writeAttribute('draw:mirror-vertical', 'false'); + $objWriter->writeAttribute('svg:viewBox', '0 0 0 0'); + $objWriter->writeAttribute('draw:text-areas', '0 0 ?f3 ?f2'); + $objWriter->writeAttribute('draw:type', 'ooxml-rect'); + $objWriter->writeAttribute('draw:enhanced-path', 'M 0 0 L ?f3 0 ?f3 ?f2 0 ?f2 Z N'); + + $objWriter->startElement('draw:equation'); + $objWriter->writeAttribute('draw:name', 'f0'); + $objWriter->writeAttribute('draw:formula', 'logwidth/2'); + $objWriter->endElement(); + + $objWriter->startElement('draw:equation'); + $objWriter->writeAttribute('draw:name', 'f1'); + $objWriter->writeAttribute('draw:formula', 'logheight/2'); + $objWriter->endElement(); + + $objWriter->startElement('draw:equation'); + $objWriter->writeAttribute('draw:name', 'f2'); + $objWriter->writeAttribute('draw:formula', 'logheight'); + $objWriter->endElement(); + + $objWriter->startElement('draw:equation'); + $objWriter->writeAttribute('draw:name', 'f3'); + $objWriter->writeAttribute('draw:formula', 'logwidth'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + // > draw:text-box $objWriter->endElement(); // > draw:frame diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index e6d085ac7..38dc4eec4 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -1170,7 +1170,7 @@ protected function writeShapeAutoShape(XMLWriter $objWriter, AutoShape $shape, i // p:sp\p:spPr\a:xfrm $objWriter->startElement('a:xfrm'); - $objWriter->writeAttributeIf($shape->getRotation() != 0, 'rot', CommonDrawing::degreesToAngle((int) $shape->getRotation())); + $objWriter->writeAttributeIf($shape->getRotation() != 0, 'rot', CommonDrawing::degreesToAngle($shape->getRotation())); // p:sp\p:spPr\a:xfrm\a:off $objWriter->startElement('a:off'); $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX())); @@ -1264,7 +1264,7 @@ protected function writeShapeChart(XMLWriter $objWriter, ShapeChart $shape, int $objWriter->endElement(); // p:xfrm $objWriter->startElement('p:xfrm'); - $objWriter->writeAttributeIf(0 != $shape->getRotation(), 'rot', CommonDrawing::degreesToAngle((int) $shape->getRotation())); + $objWriter->writeAttributeIf(0 != $shape->getRotation(), 'rot', CommonDrawing::degreesToAngle($shape->getRotation())); // a:off $objWriter->startElement('a:off'); $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX())); @@ -1427,7 +1427,7 @@ protected function writeShapePic(XMLWriter $objWriter, AbstractGraphic $shape, i $objWriter->startElement('p:spPr'); // a:xfrm $objWriter->startElement('a:xfrm'); - $objWriter->writeAttributeIf(0 != $shape->getRotation(), 'rot', CommonDrawing::degreesToAngle((int) $shape->getRotation())); + $objWriter->writeAttributeIf(0 != $shape->getRotation(), 'rot', CommonDrawing::degreesToAngle($shape->getRotation())); // a:off $objWriter->startElement('a:off'); diff --git a/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php b/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php index a483d7ad9..4fd1cedf1 100644 --- a/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php +++ b/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php @@ -507,6 +507,20 @@ public function testRichTextBorder(): void $this->assertIsSchemaOpenDocumentValid('1.2'); } + public function testRichTextRotation(): void + { + $expectedValue = mt_rand(1, 360); + $oRichText1 = $this->oPresentation->getActiveSlide()->createRichTextShape(); + $oRichText1->setRotation($expectedValue); + + $element = '/office:document-content/office:body/office:presentation/draw:page/draw:frame'; + $this->assertZipXmlElementExists('content.xml', $element); + $this->assertZipXmlAttributeExists('content.xml', $element, 'draw:transform'); + $this->assertZipXmlAttributeEquals('content.xml', $element, 'draw:transform', 'rotate (-' . deg2rad($expectedValue) . ') translate (0.000cm 0.000cm)'); + $element = '/office:document-content/office:body/office:presentation/draw:page/draw:frame/draw:text-box/draw:enhanced-geometry'; + $this->assertZipXmlElementExists('content.xml', $element); + } + public function testRichTextShadow(): void { $randAlpha = mt_rand(0, 100);