From 900381c666e6ab8f511a12d24ecf1562ec88e18e Mon Sep 17 00:00:00 2001 From: Quentin Machard <quentin.machard@idix.fr> Date: Fri, 19 May 2017 11:49:08 +0200 Subject: [PATCH] Feat. Enable style and position of a Placeholder * Create SlideLayout Sample * When write a Placeholder, fetch the first element of the first paragraph to apply style --- composer.json | 4 +- samples/Sample_19_SlideMaster.php | 8 +- samples/Sample_20_SlideLayout.php | 73 +++++ ...lSlide.php => Sample_22_ExternalSlide.php} | 0 .../Writer/PowerPoint2007/AbstractSlide.php | 295 ++++++++++-------- 5 files changed, 249 insertions(+), 131 deletions(-) create mode 100644 samples/Sample_20_SlideLayout.php rename samples/{Sample_20_ExternalSlide.php => Sample_22_ExternalSlide.php} (100%) diff --git a/composer.json b/composer.json index 60cd20f7e..be83206bc 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,9 @@ "php samples/Sample_17_Comment.php", "php samples/Sample_18_Animation.php", "php samples/Sample_19_SlideMaster.php", - "php samples/Sample_20_ExternalSlide.php" + "php samples/Sample_20_SlideLayout.php", + "php samples/Sample_21_AutoShape.php", + "php samples/Sample_22_ExternalSlide.php" ] } } diff --git a/samples/Sample_19_SlideMaster.php b/samples/Sample_19_SlideMaster.php index d72b2488b..9f851ac8e 100644 --- a/samples/Sample_19_SlideMaster.php +++ b/samples/Sample_19_SlideMaster.php @@ -55,7 +55,7 @@ ->setVertical(Alignment::VERTICAL_BASE); $shape->setAutoFit(RichText::AUTOFIT_NORMAL); $textRun = $shape->createTextRun('01-02-2000')->getFont()->setSize(18); -$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_DATETIME))->getPlaceholder()->setIdx(10); +$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_DATETIME)); // Footer placeholder $shape = $oMasterSlide->createRichTextShape(); $shape->setWidthAndHeight(468, 38)->setOffsetX(246)->setOffsetY(680); @@ -64,7 +64,7 @@ ->setVertical(Alignment::VERTICAL_BASE); $shape->setAutoFit(RichText::AUTOFIT_NORMAL); $textRun = $shape->createTextRun('Placeholder for Footer')->getFont()->setSize(18); -$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_FOOTER))->getPlaceholder()->setIdx(11); +$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_FOOTER)); // Slidenumber placeholder $shape = $oMasterSlide->createRichTextShape(); $shape->setWidthAndHeight(140, 38)->setOffsetX(770)->setOffsetY(680); @@ -72,8 +72,8 @@ ->setHorizontal(Alignment::HORIZONTAL_RIGHT) ->setVertical(Alignment::VERTICAL_BASE); $shape->setAutoFit(RichText::AUTOFIT_NORMAL); -$textRun = $shape->createTextRun('')->getFont()->setSize(18); -$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_SLIDENUM))->getPlaceholder()->setIdx(12); +$textRun = $shape->createTextRun('')->getFont()->setSize(10); +$shape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_SLIDENUM)); // Create a shape (drawing) echo date('H:i:s') . ' Create a shape (drawing)' . EOL; diff --git a/samples/Sample_20_SlideLayout.php b/samples/Sample_20_SlideLayout.php new file mode 100644 index 000000000..1e18ac5b3 --- /dev/null +++ b/samples/Sample_20_SlideLayout.php @@ -0,0 +1,73 @@ +<?php + +use PhpOffice\PhpPresentation\PhpPresentation; +use PhpOffice\PhpPresentation\Shape\Placeholder; +use PhpOffice\PhpPresentation\Style\Color; + +include_once 'Sample_Header.php'; + +// Create new PHPPresentation object +echo date('H:i:s') . ' Create new PHPPresentation object' . EOL; +$objPHPPresentation = new PhpPresentation(); + +// Set properties +echo date('H:i:s') . ' Set properties' . EOL; +$objPHPPresentation->getDocumentProperties()->setCreator('PHPOffice') + ->setLastModifiedBy('PHPPresentation Team') + ->setTitle('Sample 20 SlideLayout') + ->setSubject('Sample 20 Subject') + ->setDescription('Sample 20 Description') + ->setKeywords('office 2007 openxml libreoffice odt php') + ->setCategory('Sample Category'); + +// Create slide +echo date('H:i:s') . ' Create slide' . EOL; +$currentSlide = $objPHPPresentation->getActiveSlide(); + +echo date('H:i:s') . ' Create SlideLayout' . EOL; +$slideLayout = $objPHPPresentation->getAllMasterSlides()[0]->createSlideLayout(); +$slideLayout->setLayoutName('Sample Layout'); + +echo date('H:i:s') . ' Create Footer' . EOL; +$footerTextShape = $slideLayout->createRichTextShape(); +$footerTextShape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_FOOTER)); + +$footerTextShape + ->setOffsetX(77) + ->setOffsetY(677) + ->setWidth(448) + ->setHeight(23); + +$footerTextRun = $footerTextShape->createTextRun('Footer placeholder'); +$footerTextRun->getFont() + ->setName('Calibri') + ->setSize(9) + ->setColor(new Color(Color::COLOR_DARKGREEN)) + ->setBold(true); + +echo date('H:i:s') . ' Create SlideNumber' . EOL; + +$numberTextShape = $slideLayout->createRichTextShape(); +$numberTextShape->setPlaceHolder(new Placeholder(Placeholder::PH_TYPE_SLIDENUM)); + +$numberTextShape + ->setOffsetX(43) + ->setOffsetY(677) + ->setWidth(43) + ->setHeight(23); + +$numberTextRun = $numberTextShape->createTextRun(''); +$numberTextRun->getFont() + ->setName('Calibri') + ->setSize(9) + ->setColor(new Color(Color::COLOR_DARKGREEN)) + ->setBold(true); + +echo date('H:i:s') . ' Apply Layout' . EOL; +$currentSlide->setSlideLayout($slideLayout); + +// Save file +echo write($objPHPPresentation, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_20_ExternalSlide.php b/samples/Sample_22_ExternalSlide.php similarity index 100% rename from samples/Sample_20_ExternalSlide.php rename to samples/Sample_22_ExternalSlide.php diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 45a4a35af..ebed8c96c 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -202,31 +202,30 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh // p:sp\p:spPr $objWriter->startElement('p:spPr'); - if (!$shape->isPlaceholder()) { - // p:sp\p:spPr\a:xfrm - $objWriter->startElement('a:xfrm'); - $objWriter->writeAttributeIf(0 != $shape->getRotation(), 'rot', CommonDrawing::degreesToAngle((int) $shape->getRotation())); - // p:sp\p:spPr\a:xfrm\a:off - $objWriter->startElement('a:off'); - $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX())); - $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY())); - $objWriter->endElement(); - // p:sp\p:spPr\a:xfrm\a:ext - $objWriter->startElement('a:ext'); - $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth())); - $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight())); - $objWriter->endElement(); - // > p:sp\p:spPr\a:xfrm - $objWriter->endElement(); - // p:sp\p:spPr\a:prstGeom - $objWriter->startElement('a:prstGeom'); - $objWriter->writeAttribute('prst', 'rect'); + // p:sp\p:spPr\a:xfrm + $objWriter->startElement('a:xfrm'); + $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())); + $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY())); + $objWriter->endElement(); + // p:sp\p:spPr\a:xfrm\a:ext + $objWriter->startElement('a:ext'); + $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth())); + $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight())); + $objWriter->endElement(); + // > p:sp\p:spPr\a:xfrm + $objWriter->endElement(); + // p:sp\p:spPr\a:prstGeom + $objWriter->startElement('a:prstGeom'); + $objWriter->writeAttribute('prst', 'rect'); + + // p:sp\p:spPr\a:prstGeom\a:avLst + $objWriter->writeElement('a:avLst'); - // p:sp\p:spPr\a:prstGeom\a:avLst - $objWriter->writeElement('a:avLst'); + $objWriter->endElement(); - $objWriter->endElement(); - } $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); $this->writeShadow($objWriter, $shape->getShadow()); @@ -287,11 +286,30 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh Placeholder::PH_TYPE_DATETIME == $shape->getPlaceholder()->getType()) ) { $objWriter->startElement('a:p'); + + // Paragraph Style + $paragraphs = $shape->getParagraphs(); + if (!empty($paragraphs)) { + $paragraph = &$paragraphs[0]; + $this->writeParagraphStyles($objWriter, $paragraph, true); + } + $objWriter->startElement('a:fld'); $objWriter->writeAttribute('id', $this->getGUID()); $objWriter->writeAttribute('type', ( Placeholder::PH_TYPE_SLIDENUM == $shape->getPlaceholder()->getType() ? 'slidenum' : 'datetime' )); + + if (isset($paragraph)) { + $elements = $paragraph->getRichTextElements(); + if (!empty($elements)) { + $element = &$elements[0]; + if ($element instanceof Run) { + $this->writeRunStyles($objWriter, $element); + } + } + } + $objWriter->writeElement('a:t', ( Placeholder::PH_TYPE_SLIDENUM == $shape->getPlaceholder()->getType() ? '<nr.>' : '03-04-05' )); @@ -506,7 +524,7 @@ protected function writeShapeTable(XMLWriter $objWriter, ShapeTable $shape, int * @param XMLWriter $objWriter XML Writer * @param array<Paragraph> $paragraphs */ - protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs, bool $bIsPlaceholder = false): void + protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs): void { // Loop trough paragraphs foreach ($paragraphs as $paragraph) { @@ -514,76 +532,7 @@ protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs, bool $objWriter->startElement('a:p'); // a:pPr - if (!$bIsPlaceholder) { - // a:pPr - $objWriter->startElement('a:pPr'); - $objWriter->writeAttribute('algn', $paragraph->getAlignment()->getHorizontal()); - $objWriter->writeAttribute('rtl', $paragraph->getAlignment()->isRTL() ? '1' : '0'); - $objWriter->writeAttribute('fontAlgn', $paragraph->getAlignment()->getVertical()); - $objWriter->writeAttribute('marL', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginLeft())); - $objWriter->writeAttribute('marR', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginRight())); - $objWriter->writeAttribute('indent', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getIndent())); - $objWriter->writeAttribute('lvl', $paragraph->getAlignment()->getLevel()); - - // a:pPr:a:lnSpc - $objWriter->startElement('a:lnSpc'); - if ($paragraph->getLineSpacingMode() == Paragraph::LINE_SPACING_MODE_POINT) { - $objWriter->startElement('a:spcPts'); - $objWriter->writeAttribute('val', $paragraph->getLineSpacing() * 100); - $objWriter->endElement(); - } else { - $objWriter->startElement('a:spcPct'); - $objWriter->writeAttribute('val', $paragraph->getLineSpacing() * 1000); - $objWriter->endElement(); - } - // >a:pPr:a:lnSpc - $objWriter->endElement(); - - $objWriter->startElement('a:spcBef'); - $objWriter->startElement('a:spcPts'); - $objWriter->writeAttribute('val', $paragraph->getSpacingBefore() * 100); - $objWriter->endElement(); - $objWriter->endElement(); - - $objWriter->startElement('a:spcAft'); - $objWriter->startElement('a:spcPts'); - $objWriter->writeAttribute('val', $paragraph->getSpacingAfter() * 100); - $objWriter->endElement(); - $objWriter->endElement(); - - // Bullet type specified? - if (Bullet::TYPE_NONE != $paragraph->getBulletStyle()->getBulletType()) { - // Color - // a:buClr must be before a:buFont (else PowerPoint crashes at launch) - if ($paragraph->getBulletStyle()->getBulletColor() instanceof Color) { - $objWriter->startElement('a:buClr'); - $this->writeColor($objWriter, $paragraph->getBulletStyle()->getBulletColor()); - $objWriter->endElement(); - } - - // a:buFont - $objWriter->startElement('a:buFont'); - $objWriter->writeAttribute('typeface', $paragraph->getBulletStyle()->getBulletFont()); - $objWriter->endElement(); - - if (Bullet::TYPE_BULLET == $paragraph->getBulletStyle()->getBulletType()) { - // a:buChar - $objWriter->startElement('a:buChar'); - $objWriter->writeAttribute('char', $paragraph->getBulletStyle()->getBulletChar()); - $objWriter->endElement(); - } elseif (Bullet::TYPE_NUMERIC == $paragraph->getBulletStyle()->getBulletType()) { - // a:buAutoNum - $objWriter->startElement('a:buAutoNum'); - $objWriter->writeAttribute('type', $paragraph->getBulletStyle()->getBulletNumericStyle()); - if (1 != $paragraph->getBulletStyle()->getBulletNumericStartAt()) { - $objWriter->writeAttribute('startAt', $paragraph->getBulletStyle()->getBulletNumericStartAt()); - } - $objWriter->endElement(); - } - } - - $objWriter->endElement(); - } + $this->writeParagraphStyles($objWriter, $paragraph, false); // Loop trough rich text elements $elements = $paragraph->getRichTextElements(); @@ -596,38 +545,8 @@ protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs, bool $objWriter->startElement('a:r'); // a:rPr - if ($element instanceof Run && !$bIsPlaceholder) { - // a:rPr - $objWriter->startElement('a:rPr'); - - // Lang - $objWriter->writeAttribute('lang', ($element->getLanguage() ? $element->getLanguage() : 'en-US')); - $objWriter->writeAttributeIf($element->getFont()->isBold(), 'b', '1'); - $objWriter->writeAttributeIf($element->getFont()->isItalic(), 'i', '1'); - $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', 'sngStrike'); - $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100)); - $objWriter->writeAttribute('spc', $element->getFont()->getCharacterSpacing()); - $objWriter->writeAttribute('u', $element->getFont()->getUnderline()); - $objWriter->writeAttribute('cap', $element->getFont()->getCapitalization()); - $objWriter->writeAttributeIf($element->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($element->getFont()->isSubScript(), 'baseline', '-250000'); - // Color - a:solidFill - $objWriter->startElement('a:solidFill'); - $this->writeColor($objWriter, $element->getFont()->getColor()); - $objWriter->endElement(); - - // Font - // - a:latin - // - a:ea - // - a:cs - $objWriter->startElement('a:' . $element->getFont()->getFormat()); - $objWriter->writeAttribute('typeface', $element->getFont()->getName()); - $objWriter->endElement(); - - // a:hlinkClick - $this->writeHyperlink($objWriter, $element); - - $objWriter->endElement(); + if ($element instanceof Run) { + $this->writeRunStyles($objWriter, $element); } // t @@ -643,6 +562,130 @@ protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs, bool } } + /** + * Write Paragraph Styles (a:pPr). + */ + protected function writeParagraphStyles(XMLWriter $objWriter, RichText\Paragraph $paragraph, bool $isPlaceholder = false): void + { + $objWriter->startElement('a:pPr'); + $objWriter->writeAttribute('algn', $paragraph->getAlignment()->getHorizontal()); + $objWriter->writeAttribute('rtl', $paragraph->getAlignment()->isRTL() ? '1' : '0'); + $objWriter->writeAttribute('fontAlgn', $paragraph->getAlignment()->getVertical()); + $objWriter->writeAttribute('marL', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginLeft())); + $objWriter->writeAttribute('marR', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginRight())); + $objWriter->writeAttribute('indent', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getIndent())); + $objWriter->writeAttribute('lvl', $paragraph->getAlignment()->getLevel()); + + $objWriter->startElement('a:lnSpc'); + if ($paragraph->getLineSpacingMode() == Paragraph::LINE_SPACING_MODE_POINT) { + $objWriter->startElement('a:spcPts'); + $objWriter->writeAttribute('val', $paragraph->getLineSpacing() * 100); + $objWriter->endElement(); + } else { + $objWriter->startElement('a:spcPct'); + $objWriter->writeAttribute('val', $paragraph->getLineSpacing() * 1000); + $objWriter->endElement(); + } + $objWriter->endElement(); + + $objWriter->startElement('a:spcBef'); + $objWriter->startElement('a:spcPts'); + $objWriter->writeAttribute('val', $paragraph->getSpacingBefore() * 100); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('a:spcAft'); + $objWriter->startElement('a:spcPts'); + $objWriter->writeAttribute('val', $paragraph->getSpacingAfter() * 100); + $objWriter->endElement(); + $objWriter->endElement(); + + if (!$isPlaceholder) { + // Bullet type specified? + if ($paragraph->getBulletStyle()->getBulletType() != Bullet::TYPE_NONE) { + // Color + // a:buClr must be before a:buFont (else PowerPoint crashes at launch) + if ($paragraph->getBulletStyle()->getBulletColor() instanceof Color) { + $objWriter->startElement('a:buClr'); + $this->writeColor($objWriter, $paragraph->getBulletStyle()->getBulletColor()); + $objWriter->endElement(); + } + + // a:buFont + $objWriter->startElement('a:buFont'); + $objWriter->writeAttribute('typeface', $paragraph->getBulletStyle()->getBulletFont()); + $objWriter->endElement(); + + if ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_BULLET) { + // a:buChar + $objWriter->startElement('a:buChar'); + $objWriter->writeAttribute('char', $paragraph->getBulletStyle()->getBulletChar()); + $objWriter->endElement(); + } elseif ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_NUMERIC) { + // a:buAutoNum + $objWriter->startElement('a:buAutoNum'); + $objWriter->writeAttribute('type', $paragraph->getBulletStyle()->getBulletNumericStyle()); + if ($paragraph->getBulletStyle()->getBulletNumericStartAt() != 1) { + $objWriter->writeAttribute('startAt', $paragraph->getBulletStyle()->getBulletNumericStartAt()); + } + $objWriter->endElement(); + } + } + } + + $objWriter->endElement(); + } + + /** + * Write RichTextElement Styles (a:pPr). + */ + protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): void + { + // a:rPr + $objWriter->startElement('a:rPr'); + + // Lang + $objWriter->writeAttribute('lang', ($element->getLanguage() ? $element->getLanguage() : 'en-US')); + + $objWriter->writeAttributeIf($element->getFont()->isBold(), 'b', '1'); + $objWriter->writeAttributeIf($element->getFont()->isItalic(), 'i', '1'); + $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', 'sngStrike'); + + // Size + $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100)); + + // Character spacing + $objWriter->writeAttribute('spc', $element->getFont()->getCharacterSpacing()); + + // Underline + $objWriter->writeAttribute('u', $element->getFont()->getUnderline()); + + // Capitalization + $objWriter->writeAttribute('cap', $element->getFont()->getCapitalization()); + + // Superscript / subscript + $objWriter->writeAttributeIf($element->getFont()->isSuperScript(), 'baseline', '30000'); + $objWriter->writeAttributeIf($element->getFont()->isSubScript(), 'baseline', '-25000'); + + // Color - a:solidFill + $objWriter->startElement('a:solidFill'); + $this->writeColor($objWriter, $element->getFont()->getColor()); + $objWriter->endElement(); + + // Font + // - a:latin + // - a:ea + // - a:cs + $objWriter->startElement('a:' . $element->getFont()->getFormat()); + $objWriter->writeAttribute('typeface', $element->getFont()->getName()); + $objWriter->endElement(); + + // a:hlinkClick + $this->writeHyperlink($objWriter, $element); + + $objWriter->endElement(); + } + /** * Write Line Shape. *