diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index 9c588df707..22c90b738d 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -103,6 +103,12 @@ abstract class AbstractShape implements ComparableInterface */ protected $placeholder; + /** + * List of effect apply to shape + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + /** * Hash index * @@ -110,6 +116,13 @@ abstract class AbstractShape implements ComparableInterface */ private $hashIndex; + /** + * Name + * + * @var string + */ + protected $name; + /** * Create a new self */ @@ -122,9 +135,11 @@ public function __construct() $this->width = 0; $this->height = 0; $this->rotation = 0; + $this->name = ''; $this->fill = new Style\Fill(); $this->border = new Style\Border(); $this->shadow = new Style\Shadow(); + $this->effectCollection = null; $this->border->setLineStyle(Style\Border::LINE_NONE); } @@ -135,9 +150,27 @@ public function __construct() public function __clone() { $this->container = null; - $this->fill = clone $this->fill; - $this->border = clone $this->border; - $this->shadow = clone $this->shadow; + $this->name = $this->name; + if (isset($this->fill)) { + $this->fill = clone $this->fill; + } + if (isset($this->border)) { + $this->border = clone $this->border; + } + if (isset($this->shadow)) { + $this->shadow = clone $this->shadow; + } + if (isset($this->placeholder)) { + $this->placeholder = clone $this->placeholder; + } + if (isset($this->hyperlink)) { + $this->hyperlink = clone $this->hyperlink; + } + // Clone each effect + if (isset($this->effectCollection)) { + foreach ($this->effectCollection as &$effect) { + $effect = clone $effect; + }} } /** @@ -190,6 +223,28 @@ public function setContainer(ShapeContainerInterface $pValue = null, $pOverrideO return $this; } + /** + * Get Name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set Name + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Shape\AbstractGraphic + */ + public function setName($pValue = '') + { + $this->name = $pValue; + return $this; + } + /** * Get OffsetX * @@ -407,6 +462,46 @@ public function setHyperlink(Hyperlink $pHyperlink = null) $this->hyperlink = $pHyperlink; return $this; } + + /** + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } /** * Get hash code diff --git a/src/PhpPresentation/DocumentProperties.php b/src/PhpPresentation/DocumentProperties.php index c9344fed25..0d523e15ba 100644 --- a/src/PhpPresentation/DocumentProperties.php +++ b/src/PhpPresentation/DocumentProperties.php @@ -91,7 +91,20 @@ class DocumentProperties * @var string */ private $company; - + + /** + * revision + * + * @var string + */ + private $revision; + + /** + * status + * + * @var string + */ + private $status; /** * Create a new \PhpOffice\PhpPresentation\DocumentProperties */ @@ -108,6 +121,8 @@ public function __construct() $this->keywords = ''; $this->category = ''; $this->company = 'Microsoft Corporation'; + $this->revision = ''; + $this->status = ''; } /** @@ -345,4 +360,50 @@ public function setCompany($pValue = '') return $this; } + + /** + * Get Revision + * + * @return string + */ + public function getRevision() + { + return $this->revision; + } + + /** + * Set Revision + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\DocumentProperties + */ + public function setRevision($pValue = '') + { + $this->revision = $pValue; + + return $this; + } + + /** + * Get Status + * + * @return string + */ + public function getStatus() + { + return $this->status; + } + + /** + * Set Status + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\DocumentProperties + */ + public function setStatus($pValue = '') + { + $this->status = $pValue; + + return $this; + } } diff --git a/src/PhpPresentation/PresentationProperties.php b/src/PhpPresentation/PresentationProperties.php index 05b6dbf82d..ba3ab4683a 100644 --- a/src/PhpPresentation/PresentationProperties.php +++ b/src/PhpPresentation/PresentationProperties.php @@ -29,6 +29,8 @@ class PresentationProperties const VIEW_SLIDE_MASTER = 'sldMasterView'; const VIEW_SLIDE_SORTER = 'sldSorterView'; const VIEW_SLIDE_THUMBNAIL = 'sldThumbnailView'; + const THUMBNAIL_FILE = 'file'; // Thumbnail path is out of PPT + const THUMBNAIL_ZIP = 'zip'; // Thumbnail path point to an image store into file loaded protected $arrayView = array( self::VIEW_HANDOUT, @@ -53,9 +55,19 @@ class PresentationProperties protected $markAsFinal = false; /* - * @var string + * @var string Define the thumbnail content (if content into zip file) + */ + protected $thumbnail = null; + + /* + * @var string Define the thumbnail place + */ + protected $thumbnailPath = ''; + + /* + * @var string Define if thumbnail is out of PPT or previouly store into PPT */ - protected $thumbnail; + protected $thumbnailType = self::THUMBNAIL_FILE; /** * Zoom @@ -99,7 +111,27 @@ public function setLoopContinuouslyUntilEsc($value = false) */ public function getThumbnailPath() { + return $this->thumbnailPath; + } + + /** + * Return the content of thumbnail + * + * @return binary Content of image + */ + public function getThumbnail() + { + // Return content of local file + if ($this->getThumbnailType() == self::THUMBNAIL_FILE) { + if (file_exists($this->getThumbnailPath())) + return file_get_contents($this->getThumbnailPath()); + } + // Return content of image stored into zip file + if ($this->getThumbnailType() == self::THUMBNAIL_ZIP) { return $this->thumbnail; + } + // Return null if no thumbnail + return null; } /** @@ -107,14 +139,29 @@ public function getThumbnailPath() * @param string $path * @return \PhpOffice\PhpPresentation\PresentationProperties */ - public function setThumbnailPath($path = '') + public function setThumbnailPath($path = '', $type = self::THUMBNAIL_FILE, $content = null) { - if (file_exists($path)) { - $this->thumbnail = $path; + if (file_exists($path) && ($type == self::THUMBNAIL_FILE)) { + $this->thumbnailPath = $path; + $this->thumbnailType = $type; + } + if (($path != '') && ($type == self::THUMBNAIL_ZIP)) { + $this->thumbnailPath = $path; + $this->thumbnailType = $type; + $this->thumbnail = $content; } return $this; } + /** + * Return the thumbnail type + * @return string + */ + public function getThumbnailType() + { + return $this->thumbnailType; + } + /** * Mark a document as final * @param bool $state diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index aa3b847acc..e1f4253e7c 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -147,6 +147,11 @@ protected function loadFile($pFilename) $this->loadDocumentProperties($docPropsCore); } + $docThumbnail = $this->oZip->getFromName('_rels/.rels'); + if ($docThumbnail !== false) { + $this->loadThumbnailProperties($docThumbnail); + } + $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml'); if ($docPropsCustom !== false) { $this->loadCustomProperties($docPropsCustom); @@ -211,6 +216,8 @@ protected function loadDocumentProperties($sPart) '/cp:coreProperties/cp:category' => 'setCategory', '/cp:coreProperties/dcterms:created' => 'setCreated', '/cp:coreProperties/dcterms:modified' => 'setModified', + '/cp:coreProperties/cp:revision' => 'setRevision', + '/cp:coreProperties/cp:contentStatus' => 'setStatus', ); $oProperties = $this->oPhpPresentation->getDocumentProperties(); foreach ($arrayProperties as $path => $property) { @@ -228,6 +235,26 @@ protected function loadDocumentProperties($sPart) } } + /** + * Read information of the document thumbnail + * @param string $sPart Content of XML file for retrieving data + */ + protected function loadThumbnailProperties($sPart) + { + $xmlReader = new XMLReader(); + if ($xmlReader->getDomFromString($sPart)) { + $oElement = $xmlReader->getElement('*[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); + if ($oElement instanceof \DOMElement) { + $path = $oElement->getAttribute('Target'); + $this->oPhpPresentation + ->getPresentationProperties() + ->setThumbnailPath($path + , \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP + , $this->oZip->getFromName($path)); + } + } + } + /** * Read Custom Properties * @param string $sPart @@ -762,9 +789,11 @@ protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, Abst $imageFile = $this->oZip->getFromName($pathImage); if (!empty($imageFile)) { $info = getimagesizefromstring($imageFile); - $oShape->setMimeType($info['mime']); - $oShape->setRenderingFunction(str_replace('/', '', $info['mime'])); - $oShape->setImageResource(imagecreatefromstring($imageFile)); + if (is_array($info)) { + $oShape->setMimeType($info['mime']); + $oShape->setRenderingFunction(str_replace('/', '', $info['mime'])); + $oShape->setImageResource(imagecreatefromstring($imageFile)); + } } } } @@ -801,46 +830,81 @@ protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, Abst $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy'))); } } - - $oElement = $document->getElement('p:spPr/a:effectLst', $node); - if ($oElement instanceof \DOMElement) { - $oShape->getShadow()->setVisible(true); - - $oSubElement = $document->getElement('a:outerShdw', $oElement); - if ($oSubElement instanceof \DOMElement) { - if ($oSubElement->hasAttribute('blurRad')) { - $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad'))); - } - if ($oSubElement->hasAttribute('dist')) { - $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist'))); - } - if ($oSubElement->hasAttribute('dir')) { - $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir'))); - } - if ($oSubElement->hasAttribute('algn')) { - $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn')); - } - } - - $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement); - if ($oSubElement instanceof \DOMElement) { - if ($oSubElement->hasAttribute('val')) { - $oColor = new Color(); - $oColor->setRGB($oSubElement->getAttribute('val')); - $oShape->getShadow()->setColor($oColor); - } - } - - $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement); - if ($oSubElement instanceof \DOMElement) { - if ($oSubElement->hasAttribute('val')) { - $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000); - } - } + // Load shape effects + $oEffect = $document->getElement('p:spPr/a:effectLst', $node); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oShape->setEffectCollection($aEffect); + } } - $oSlide->addShape($oShape); } + + /** + * Load Effect for shape or paragraph + * + * @param XMLReader $document + * @param \DOMElement $node + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected function loadEffect(XMLReader $document, \DOMElement $nodeEffect) + { + $aEffect = null; + if ($nodeEffect instanceof \DOMElement) { + + $aNodes = $document->getElements('*', $nodeEffect); + foreach ($aNodes as $node) { + + $type = explode(':', $node->tagName); + $type = array_pop($type); + if ( $type == 'outerShdw' + || $type == 'innerShdw') { +// @TODO || $type == 'reflection') { + + // Create a new effect + $effect = new \PhpOffice\PhpPresentation\Style\Effect($type); + // load blur radius + if ($node->hasAttribute('blurRad')) { + $effect->setBlurRadius(CommonDrawing::emuToPixels($node->getAttribute('blurRad'))); + } + // load distance + if ($node->hasAttribute('dist')) { + $effect->setDistance(CommonDrawing::emuToPixels($node->getAttribute('dist'))); + } + // load direction + if ($node->hasAttribute('dir')) { + $effect->setDirection(CommonDrawing::angleToDegrees($node->getAttribute('dir'))); + } + // load alignment + if ($node->hasAttribute('algn')) { + $effect->setAlignment($node->getAttribute('algn')); + } + + // Get color define by prstClr + $oSubElement = $document->getElement('a:prstClr', $node); + if ($oSubElement instanceof \DOMElement && $oSubElement->hasAttribute('val')) { + $oColor = new Color(); + $oColor->setRGB($oSubElement->getAttribute('val')); + $effect->setColor($oColor); + // Get Alpha + $oSubElt = $document->getElement('a:alpha', $oSubElement); + if ($oSubElt instanceof \DOMElement && $oSubElt->hasAttribute('val')) { + $effect->setAlpha((int)$oSubElt->getAttribute('val') / 1000); + } + } + // Load reflection atributs +// @TODO future implementation + if ($node->tagName == 'a:reflection') { + } + + if (!isset($aEffect)) $aEffect = array(); + $aEffect[] = $effect; + } + } + } + return $aEffect; + } /** * @param XMLReader $document @@ -850,9 +914,6 @@ protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, Abst */ protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide) { - if (!$document->elementExists('p:txBody/a:p/a:r', $node)) { - return; - } // Core $oShape = $oSlide->createRichTextShape(); $oShape->setParagraphs(array()); @@ -861,6 +922,10 @@ protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oS $this->fileRels = $oSlide->getRelsIndex(); } + $oElement = $document->getElement('p:nvSpPr/p:cNvPr', $node); + if ($oElement instanceof \DOMElement) + $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : ''); + $oElement = $document->getElement('p:spPr/a:xfrm', $node); if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) { $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot'))); @@ -894,11 +959,47 @@ protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oS } } + // Load shape effects + $oEffect = $document->getElement('p:spPr/a:effectLst', $node); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oShape->setEffectCollection($aEffect); + } + } + +// FBU-20210202+ Read body definitions + $bodyPr = $document->getElement('p:txBody/a:bodyPr', $node); + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('lIns')) { + $oShape->setInsetLeft((int)$bodyPr->getAttribute('lIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('tIns')) { + $oShape->setInsetTop((int)$bodyPr->getAttribute('tIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('rIns')) { + $oShape->setInsetRight((int)$bodyPr->getAttribute('rIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('bIns')) { + $oShape->setInsetBottom((int)$bodyPr->getAttribute('bIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchor')) { + $oShape->setVerticalAlignment($bodyPr->getAttribute('anchor')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchorCtr')) { + $oShape->setVerticalAlignCenter((int)$bodyPr->getAttribute('anchorCtr')); + } + $arrayElements = $document->getElements('p:txBody/a:p', $node); foreach ($arrayElements as $oElement) { $this->loadParagraph($document, $oElement, $oShape); } + $oElement = $document->getElement('p:spPr', $node); + if ($oElement instanceof \DOMElement) { + $oFill = $this->loadStyleFill($document, $oElement); + $oShape->setFill($oFill); + } + if (count($oShape->getParagraphs()) > 0) { $oShape->setActiveParagraph(0); } @@ -1135,7 +1236,7 @@ protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oS $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false); } if ($oElementrPr->hasAttribute('strike')) { - $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true); + $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike')); } if ($oElementrPr->hasAttribute('sz')) { $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100)); @@ -1143,6 +1244,19 @@ protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oS if ($oElementrPr->hasAttribute('u')) { $oText->getFont()->setUnderline($oElementrPr->getAttribute('u')); } + if ($oElementrPr->hasAttribute('lang')) { + $oText->setLanguage($oElementrPr->getAttribute('lang')); + } + if ($oElementrPr->hasAttribute('baseline')) { + if ((int)$oElementrPr->getAttribute('baseline')>0) { + $oText->getFont()->setSuperScript((int)$oElementrPr->getAttribute('baseline')); + } else if ((int)$oElementrPr->getAttribute('baseline')<0) { + $oText->getFont()->setSubScript((int)$oElementrPr->getAttribute('baseline')); + } + } + if ($oElementrPr->hasAttribute('cap')) { + $oText->getFont()->setCapitalize($oElementrPr->getAttribute('cap')); + } // Color $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr); if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) { @@ -1160,7 +1274,29 @@ protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oS $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']); } } - //} else { + // Font definition + $oElementFont = $document->getElement('a:latin', $oElementrPr); + if (is_object($oElementFont) && $oElementFont->hasAttribute('typeface')) { + $oText->getFont()->setName($oElementFont->getAttribute('typeface')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('panose')) { + $oText->getFont()->setPanose($oElementFont->getAttribute('panose')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('pitchFamily')) { + $oText->getFont()->setPitchFamily($oElementFont->getAttribute('pitchFamily')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('charset')) { + $oText->getFont()->setCharset($oElementFont->getAttribute('charset')); + } + // Load shape effects + $oEffect = $document->getElement('a:effectLst', $oElementrPr); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oText->setEffectCollection($aEffect); + } + } + //} else { // $oText = $oParagraph->createText(); $oSubSubElement = $document->getElement('a:t', $oSubElement); diff --git a/src/PhpPresentation/Shape/AbstractGraphic.php b/src/PhpPresentation/Shape/AbstractGraphic.php index 982a08b228..5618021502 100644 --- a/src/PhpPresentation/Shape/AbstractGraphic.php +++ b/src/PhpPresentation/Shape/AbstractGraphic.php @@ -39,13 +39,6 @@ abstract class AbstractGraphic extends AbstractShape implements ComparableInterf */ private $imageIndex = 0; - /** - * Name - * - * @var string - */ - protected $name; - /** * Description * @@ -103,28 +96,6 @@ public function getImageIndex() return $this->imageIndex; } - /** - * Get Name - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Set Name - * - * @param string $pValue - * @return $this - */ - public function setName($pValue = '') - { - $this->name = $pValue; - return $this; - } - /** * Get Description * diff --git a/src/PhpPresentation/Shape/Drawing/Gd.php b/src/PhpPresentation/Shape/Drawing/Gd.php index d4509d922d..854fa21939 100644 --- a/src/PhpPresentation/Shape/Drawing/Gd.php +++ b/src/PhpPresentation/Shape/Drawing/Gd.php @@ -75,8 +75,8 @@ public function setImageResource($value = null) if (!is_null($this->imageResource)) { // Get width/height - $this->width = imagesx($this->imageResource); - $this->height = imagesy($this->imageResource); + $this->width = (int)@imagesx($this->imageResource); + $this->height = (int)@imagesy($this->imageResource); } return $this; diff --git a/src/PhpPresentation/Shape/RichText.php b/src/PhpPresentation/Shape/RichText.php index d7cc341523..38f9da14f2 100644 --- a/src/PhpPresentation/Shape/RichText.php +++ b/src/PhpPresentation/Shape/RichText.php @@ -40,6 +40,15 @@ class RichText extends AbstractShape implements ComparableInterface /** Overflow */ const OVERFLOW_CLIP = 'clip'; const OVERFLOW_OVERFLOW = 'overflow'; + + /** Vertical alignment */ + const VALIGN_TOP = 't'; + const VALIGN_MIDDLE = 'ctr'; + const VALIGN_BOTTOM = 'b'; + + /** Vertical alignment center */ + const VALIGN_CENTER = 1; + const VALIGN_NOTCENTER = 0; /** * Rich text paragraphs @@ -155,6 +164,17 @@ class RichText extends AbstractShape implements ComparableInterface * @var float */ private $lnSpcReduction; + + /** + * Define vertical text position into shape (top,center,bottom) + * @var string + */ + private $verticalAlign = self::VALIGN_TOP; + /** + * Define vertical text center position into shape (center,not center) + * @var int + */ + private $verticalAlignCenter = self::VALIGN_NOTCENTER; /** * Create a new \PhpOffice\PhpPresentation\Shape\RichText instance @@ -171,6 +191,20 @@ public function __construct() parent::__construct(); } + /** + * Magic Method : clone + */ + public function __clone() + { + // Call perent clonage for heritage + parent::__clone(); + // Clone each paragraph + if (isset($this->richTextParagraphs)) { + foreach ($this->richTextParagraphs as &$paragraph) { + $paragraph = clone $paragraph; + }} + } + /** * Get active paragraph index * @@ -528,6 +562,59 @@ public function setVertical($value = false) return $this; } + + /** + * Define the vertical alignment + * + * @param string|null $value top,center,bottom + * @return $this + * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM + */ + public function setVerticalAlignment(?string $value) + { + if (isset($value)) { + $this->verticalAlign = $value; + } else { + $this->verticalAlign = self::VALIGN_TOP; + } + return $this; + } + + /** + * Get the vertical alignment + * + * @return string + * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM + */ + public function getVerticalAlignment():string + { + return $this->verticalAlign; + } + + /** + * Define the vertical alignment if centered or not + * @param int|null $value 1=center 0=not center + * @return $this + * @see self::VALIGN_CENTER, self::VALIGN_NOTCENTER + */ + public function setVerticalAlignCenter(?int $value) + { + if (isset($value)) { + $this->verticalAlignCenter = $value; + } else { + $this->verticalAlignCenter = self::VALIGN_NOTCENTER; + } + return $this; + } + + /** + * Get the vertical alignment center + * @return int + */ + public function getVerticalAlignCenter():int + { + return $this->verticalAlignCenter; + } /** * Get columns diff --git a/src/PhpPresentation/Shape/RichText/Paragraph.php b/src/PhpPresentation/Shape/RichText/Paragraph.php index ab64b706ab..02fe28f4c6 100644 --- a/src/PhpPresentation/Shape/RichText/Paragraph.php +++ b/src/PhpPresentation/Shape/RichText/Paragraph.php @@ -60,6 +60,12 @@ class Paragraph implements ComparableInterface */ private $lineSpacing = 100; + /** + * List of effect apply to paragraph + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + /** * Hash index * @@ -77,6 +83,24 @@ public function __construct() $this->alignment = new Alignment(); $this->font = new Font(); $this->bulletStyle = new Bullet(); + $this->effectCollection = null; + } + + /** + * Magic Method : clone + */ + public function __clone() + { + // Clone each text + if (isset($this->richTextElements)) { + foreach ($this->richTextElements as &$txtElt) { + $txtElt = clone $txtElt; + }} + // Clone each effect + if (isset($this->effectCollection)) { + foreach ($this->effectCollection as &$effect) { + $effect = clone $effect; + }} } /** @@ -266,6 +290,46 @@ public function setRichTextElements($pElements = null) return $this; } + /** + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } + /** * Get hash code * diff --git a/src/PhpPresentation/Shape/RichText/Run.php b/src/PhpPresentation/Shape/RichText/Run.php index 97455c0f11..cfc318deb8 100644 --- a/src/PhpPresentation/Shape/RichText/Run.php +++ b/src/PhpPresentation/Shape/RichText/Run.php @@ -31,6 +31,12 @@ class Run extends TextElement implements TextElementInterface */ private $font; + /** + * List of effect apply to paragraph + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + /** * Create a new \PhpOffice\PhpPresentation\Shape\RichText\Run instance * @@ -41,6 +47,7 @@ public function __construct($pText = '') // Initialise variables $this->setText($pText); $this->font = new Font(); + $this->effectCollection = null; } /** @@ -67,6 +74,46 @@ public function setFont(Font $pFont = null) return $this; } + /** + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } + /** * Get hash code * diff --git a/src/PhpPresentation/Slide.php b/src/PhpPresentation/Slide.php index 473d7b73b4..b27b3a5d36 100644 --- a/src/PhpPresentation/Slide.php +++ b/src/PhpPresentation/Slide.php @@ -136,6 +136,29 @@ public function setSlideMasterId($masterId = 1) return $this; } + + public function __clone() + { + // Set parent + $this->parent = clone $this->parent; + // Shape collection + if (isset($this->shapeCollection)) { + $this->shapeCollection = clone $this->shapeCollection; + foreach ($this->shapeCollection as &$shape) { + $shape = clone $shape; + } + } + // Transition object + if (isset($this->slideTransition)) { + $this->slideTransition = clone $this->slideTransition; + } + // Note object + if (isset($this->slideNote)) { + $this->slideNote = clone $this->slideNote; + } + + } + /** * Copy slide (!= clone!) * diff --git a/src/PhpPresentation/Slide/AbstractSlide.php b/src/PhpPresentation/Slide/AbstractSlide.php index 3e1c5c1730..30b44137ca 100644 --- a/src/PhpPresentation/Slide/AbstractSlide.php +++ b/src/PhpPresentation/Slide/AbstractSlide.php @@ -106,6 +106,24 @@ public function getShapeCollection() return $this->shapeCollection; } + /** + * Search into collection of shapes for a name (eventually filtered by type ex: RichText) + * + * @param string $name The name to find into the shape collection + * @param PhpOffice\PhpPresentation\Shape\RichText | PhpOffice\PhpPresentation\Shape\... $type Type of the class + * @return \ArrayObject|\PhpOffice\PhpPresentation\AbstractShape[] + */ + public function searchShapeByName(string $name, ?string $type=null) + { + if (isset($this->shapeCollection)) { + foreach ($this->shapeCollection as $shape) { + if ($shape->getName() == $name) { + if (!isset($type) || get_class($shape) == $type) { + return $shape; + }}}} + return null; + } + /** * Get collection of shapes * diff --git a/src/PhpPresentation/Style/Effect.php b/src/PhpPresentation/Style/Effect.php new file mode 100644 index 0000000000..5c25ca4f4a --- /dev/null +++ b/src/PhpPresentation/Style/Effect.php @@ -0,0 +1,310 @@ +effectType = $type; + $this->blurRadius = 6; + $this->distance = 2; + $this->direction = 0; + $this->alignment = self::SHADOW_BOTTOM_RIGHT; + $this->color = new Color(Color::COLOR_BLACK); + $this->alpha = 50; + } + + /** + * Define the type effect + * + * @param string $type + * @return $this + * @see self::EFFECT_SHADOW_INNER, self::EFFECT_SHADOW_OUTER, self::EFFECT_REFLECTION + */ + public function setEffectType(string $type) + { + $this->effectType = $type; + return $this; + } + + /** + * Get the effect type + * + * @return string + */ + public function getEffectType():string + { + return $this->effectType; + } + + /** + * Set the direction + * + * @param int $dir + * @return $this + */ + public function setDirection(?int $dir) + { + if (!isset($dir)) $dir = 0; + $this->direction = (int)$dir; + return $this; + } + + /** + * Get the direction + * + * @return int + */ + public function getDirection():int + { + return $this->direction; + } + + /** + * Set the blur radius + * + * @param int $radius + * @return $this + */ + public function setBlurRadius(?int $radius) + { + if (!isset($radius)) $radius = 6; + $this->blurRadius = $radius; + return $this; + } + + /** + * Get the blur radius + * + * @return int + */ + public function getBlurRadius():int + { + return $this->blurRadius; + } + + /** + * Get Shadow distance + * + * @return int + */ + public function getDistance():int + { + return $this->distance; + } + + /** + * Set Shadow distance + * + * @param int $distance + * @return $this + */ + public function setDistance(int $distance = 2) + { + $this->distance = $distance; + + return $this; + } + + /** + * Set the effect alignment + * + * @param string $align + * @return $this + */ + public function setAlignment(?string $align) + { + if (!isset($align)) $align = self::SHADOW_BOTTOM_RIGHT; + $this->align = $align; + return $this; + } + + /** + * Get the effect alignment + * + * @return string + */ + public function getAlignment():string + { + return $this->align; + } + + /** + * Set Color + * + * @param \PhpOffice\PhpPresentation\Style\Color $color + * @return $this + */ + public function setColor(Color $color = null) + { + $this->color = $color; + + return $this; + } + + /** + * Get Color + * + * @return \PhpOffice\PhpPresentation\Style\Color + */ + public function getColor() + { + return $this->color; + } + + /** + * Set Alpha + * + * @param int $alpha + * @return $this + */ + public function setAlpha(?int $alpha) + { + if (!isset($alpha)) $alpha = 0; + $this->alpha = $alpha; + + return $this; + } + + /** + * Get Alpha + * + * @return int + */ + public function getAlpha():int + { + return $this->alpha; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + return md5($this->effectType . $this->blurRadius . $this->distance . $this->direction . $this->alignment . $this->color->getHashCode() . $this->alpha . __CLASS__); + } + + /** + * Get hash index + * + * Note that this index may vary during script execution! Only reliable moment is + * while doing a write of a workbook and when changes are not allowed. + * + * @return string Hash index + */ + public function getHashIndex() + { + return $this->hashIndex; + } + + /** + * Set hash index + * + * Note that this index may vary during script execution! Only reliable moment is + * while doing a write of a workbook and when changes are not allowed. + * + * @param string $value Hash index + */ + public function setHashIndex($value) + { + $this->hashIndex = $value; + } + +} diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index e4b49d0f36..a467ab60a6 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -43,6 +43,20 @@ class Font implements ComparableInterface const UNDERLINE_WAVYDOUBLE = 'wavyDbl'; const UNDERLINE_WAVYHEAVY = 'wavyHeavy'; const UNDERLINE_WORDS = 'words'; + + /* Strike types */ + const STRIKE_NONE = 'noStrike'; + const STRIKE_SINGLE = 'sngStrike'; + const STRIKE_DOUBLE = 'dblStrike'; + + /* Script sub and super values */ + const SCRIPT_SUPER = 30000; + const SCRIPT_SUB = -25000; + + /* Capitalize types */ + const CAPS_NONE = ''; + const CAPS_SMALL = 'small'; + const CAPS_ALL = 'all'; /** * Name @@ -51,6 +65,25 @@ class Font implements ComparableInterface */ private $name; + /** + * panose + * + * @var string + */ + private $panose; + /** + * pitchFamily + * + * @var string + */ + private $pitchFamily; + /** + * charset + * + * @var string + */ + private $charset; + /** * Font Size * @@ -121,6 +154,13 @@ class Font implements ComparableInterface */ private $hashIndex; + /** + * Capitalize type + * + * @var string + */ + private $capitalize; + /** * Create a new \PhpOffice\PhpPresentation\Style\Font */ @@ -132,11 +172,12 @@ public function __construct() $this->characterSpacing = 0; $this->bold = false; $this->italic = false; - $this->superScript = false; - $this->subScript = false; + $this->superScript = 0; + $this->subScript = 0; $this->underline = self::UNDERLINE_NONE; - $this->strikethrough = false; + $this->strikethrough = self::STRIKE_NONE; $this->color = new Color(Color::COLOR_BLACK); + $this->capitalize = self::CAPS_NONE; } /** @@ -161,6 +202,81 @@ public function setName($pValue = 'Calibri') $pValue = 'Calibri'; } $this->name = $pValue; + return $this; + } + + /** + * Get panose + * + * @return string + */ + public function getPanose() + { + return $this->panose; + } + + /** + * Set panose + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setPanose($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->panose = $pValue; + + return $this; + } + /** + * Get pitchFamily + * + * @return string + */ + public function getPitchFamily() + { + return $this->pitchFamily; + } + + /** + * Set pitchFamily + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setPitchFamily($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->pitchFamily = $pValue; + + return $this; + } + /** + * Get charset + * + * @return string + */ + public function getCharset() + { + return $this->charset; + } + + /** + * Set charset + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setCharset($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->charset = $pValue; return $this; } @@ -272,7 +388,7 @@ public function setItalic($pValue = false) /** * Get SuperScript * - * @return boolean + * @return integer */ public function isSuperScript() { @@ -282,20 +398,20 @@ public function isSuperScript() /** * Set SuperScript * - * @param boolean $pValue + * @param integer $pValue * @return \PhpOffice\PhpPresentation\Style\Font */ - public function setSuperScript($pValue = false) + public function setSuperScript($pValue = 0) { if ($pValue == '') { - $pValue = false; + $pValue = 0; } $this->superScript = $pValue; // Set SubScript at false only if SuperScript is true - if ($pValue === true) { - $this->subScript = false; + if ($pValue != 0) { + $this->subScript = 0; } return $this; @@ -304,7 +420,7 @@ public function setSuperScript($pValue = false) /** * Get SubScript * - * @return boolean + * @return integer */ public function isSubScript() { @@ -314,20 +430,20 @@ public function isSubScript() /** * Set SubScript * - * @param boolean $pValue + * @param integer $pValue * @return \PhpOffice\PhpPresentation\Style\Font */ - public function setSubScript($pValue = false) + public function setSubScript($pValue = 0) { if ($pValue == '') { - $pValue = false; + $pValue = 0; } $this->subScript = $pValue; // Set SuperScript at false only if SubScript is true - if ($pValue === true) { - $this->superScript = false; + if ($pValue != 0) { + $this->superScript = 0; } return $this; @@ -375,10 +491,10 @@ public function isStrikethrough() * @param boolean $pValue * @return \PhpOffice\PhpPresentation\Style\Font */ - public function setStrikethrough($pValue = false) + public function setStrikethrough($pValue = self::STRIKE_NONE) { if ($pValue == '') { - $pValue = false; + $pValue = self::STRIKE_NONE; } $this->strikethrough = $pValue; @@ -447,4 +563,28 @@ public function setHashIndex($value) { $this->hashIndex = $value; } + + /** + * Set Capitalize + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setCapitalize($value = self::CAPS_NONE) + { + $this->capitalize = $value; + return $this; + } + /** + * Get Capitalize + * + * @return string + */ + public function getCapitalize() + { + return $this->capitalize; + } + + + } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 0c220f00f0..b055abed22 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -167,7 +167,7 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, $shapeI if ($shape->isPlaceholder()) { $objWriter->writeAttribute('name', 'Placeholder for ' . $shape->getPlaceholder()->getType()); } else { - $objWriter->writeAttribute('name', ''); + $objWriter->writeAttribute('name', $shape->getName()); } // Hyperlink if ($shape->hasHyperlink()) { @@ -224,7 +224,7 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, $shapeI } $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeShadow($objWriter, $shape->getShadow()); + $this->writeEffect($objWriter, $shape->getEffectCollection()); // > p:sp\p:spPr $objWriter->endElement(); @@ -254,10 +254,16 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, $shapeI if ($shape->isVertical()) { $objWriter->writeAttribute('vert', 'vert'); } + else { + $objWriter->writeAttribute('vert', 'horz'); + } $objWriter->writeAttribute('bIns', CommonDrawing::pixelsToEmu($shape->getInsetBottom())); $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft())); $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight())); $objWriter->writeAttribute('tIns', CommonDrawing::pixelsToEmu($shape->getInsetTop())); + // Vertical alignment + $objWriter->writeAttribute('anchor', $shape->getVerticalAlignment()); + $objWriter->writeAttribute('anchorCtr', (int)$shape->getVerticalAlignCenter()); if ($shape->getColumns() <> 1) { $objWriter->writeAttribute('numCol', $shape->getColumns()); } @@ -581,21 +587,31 @@ protected function writeParagraphs(XMLWriter $objWriter, $paragraphs, $bIsPlaceh $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->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', $element->getFont()->isStrikethrough()); $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100)); $objWriter->writeAttribute('spc', $element->getFont()->getCharacterSpacing()); $objWriter->writeAttribute('u', $element->getFont()->getUnderline()); - $objWriter->writeAttributeIf($element->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($element->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($element->getFont()->isSuperScript()!=0, 'baseline', (int)$element->getFont()->isSuperScript()); + $objWriter->writeAttributeIf($element->getFont()->isSubScript()!=0, 'baseline', (int)$element->getFont()->isSubScript()); + if ($element->getFont()->getCapitalize()!='') + $objWriter->writeAttribute('cap', $element->getFont()->getCapitalize()); // Color - a:solidFill $objWriter->startElement('a:solidFill'); $this->writeColor($objWriter, $element->getFont()->getColor()); $objWriter->endElement(); - + // Write Effects + $this->writeEffect($objWriter, $element->getEffectCollection(), 'srgbClr'); + // Font - a:latin $objWriter->startElement('a:latin'); $objWriter->writeAttribute('typeface', $element->getFont()->getName()); + if ($element->getFont()->getPanose()!="") + $objWriter->writeAttribute('panose', $element->getFont()->getPanose()); + if ($element->getFont()->getPitchFamily()!="") + $objWriter->writeAttribute('pitchFamily', $element->getFont()->getPitchFamily()); + if ($element->getFont()->getCharset()!="") + $objWriter->writeAttribute('charset', $element->getFont()->getCharset()); $objWriter->endElement(); // a:hlinkClick @@ -745,6 +761,54 @@ protected function writeShadow(XMLWriter $objWriter, $oShadow) $objWriter->endElement(); } + /** + * Write Effect + * @param XMLWriter $objWriter + * @param array \PhpOffice\PhpPresentation\Style\Effect[] + * @param Shadow $oShadow + */ + protected function writeEffect(XMLWriter $objWriter, ?array $aEffect, ?string $tagClr=null) + { + // NO Effect => return + if (!isset($aEffect) && !is_array($aEffect)) { + return; + } + if (!isset($tagClr)) { + $tagClr = 'prstClr'; + } + + // a:effectLst + $objWriter->startElement('a:effectLst'); + // Write each effect + foreach($aEffect as $effect) { + // a: + if ( $effect->getEffectType() == 'outerShdw' + || $effect->getEffectType() == 'innerShdw') { +// @TODO || $effect->getEffectType() == 'reflection') { + + $objWriter->startElement('a:'.$effect->getEffectType()); + $objWriter->writeAttribute('blurRad', CommonDrawing::pixelsToEmu($effect->getBlurRadius())); + $objWriter->writeAttribute('dist', CommonDrawing::pixelsToEmu($effect->getDistance())); + $objWriter->writeAttribute('dir', CommonDrawing::degreesToAngle($effect->getDirection())); + $objWriter->writeAttribute('algn', $effect->getAlignment()); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:prstClr + $objWriter->startElement('a:'.$tagClr); + $objWriter->writeAttribute('val', $effect->getColor()->getRGB()); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', $effect->getAlpha() * 1000); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + /** * Write hyperlink * @@ -1210,7 +1274,7 @@ protected function writeShapePic(XMLWriter $objWriter, AbstractGraphic $shape, $ $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeShadow($objWriter, $shape->getShadow()); + $this->writeEffect($objWriter, $shape->getEffectCollection()); $objWriter->endElement(); $objWriter->endElement(); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php index 591f42be12..d1665ef926 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php @@ -56,6 +56,12 @@ public function render() // cp:keywords $objWriter->writeElement('cp:keywords', $this->oPresentation->getDocumentProperties()->getKeywords()); + // cp:revision + $objWriter->writeElement('cp:revision', $this->oPresentation->getDocumentProperties()->getRevision()); + + // cp:contentStatus + $objWriter->writeElement('cp:contentStatus', $this->oPresentation->getDocumentProperties()->getStatus()); + // cp:category $objWriter->writeElement('cp:category', $this->oPresentation->getDocumentProperties()->getCategory()); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php index 64308a41ce..6110bcc700 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php @@ -11,8 +11,10 @@ class DocPropsThumbnail extends AbstractDecoratorWriter public function render() { $pathThumbnail = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); + $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); - if ($pathThumbnail) { + // From local file + if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { $fileThumbnail = file_get_contents($pathThumbnail); $gdImage = imagecreatefromstring($fileThumbnail); if ($gdImage) { @@ -21,7 +23,19 @@ public function render() $imageContents = ob_get_contents(); ob_end_clean(); imagedestroy($gdImage); - + $this->getZip()->addFromString('docProps/thumbnail.jpeg', $imageContents); + } + } + + // From ZIP original file + if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { + $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + if ($gdImage) { + ob_start(); + imagejpeg($gdImage); + $imageContents = ob_get_contents(); + ob_end_clean(); + imagedestroy($gdImage); $this->getZip()->addFromString('docProps/thumbnail.jpeg', $imageContents); } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php index ccc5768592..74da18f4af 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php @@ -49,8 +49,11 @@ public function writeRelationships() $idxRelation = 5; // Thumbnail - if ($this->getPresentation()->getPresentationProperties()->getThumbnailPath()) { - $pathThumbnail = file_get_contents($this->getPresentation()->getPresentationProperties()->getThumbnailPath()); + $path = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); + $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); + // From local file + if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { + $pathThumbnail = file_get_contents($path); $gdImage = imagecreatefromstring($pathThumbnail); if ($gdImage) { imagedestroy($gdImage); @@ -58,6 +61,15 @@ public function writeRelationships() $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); } } + // From ZIP original file + if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { + $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + if ($gdImage) { + imagedestroy($gdImage); + // Relationship docProps/thumbnail.jpeg + $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); + } + } // ++$idxRelation $objWriter->endElement();