Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
98.90% |
179 / 181 |
|
85.71% |
6 / 7 |
CRAP | |
0.00% |
0 / 1 |
| Styles | |
98.90% |
179 / 181 |
|
85.71% |
6 / 7 |
37 | |
0.00% |
0 / 1 |
| render | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| writePart | |
100.00% |
86 / 86 |
|
100.00% |
1 / 1 |
9 | |||
| writeRichTextStyle | |
100.00% |
63 / 63 |
|
100.00% |
1 / 1 |
16 | |||
| writeTableStyle | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
5 | |||
| writeGroupStyle | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
4.59 | |||
| writeGradientFill | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
1 | |||
| writeBackgroundStyle | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * This file is part of PHPPresentation - A pure PHP library for reading and writing |
| 4 | * presentations documents. |
| 5 | * |
| 6 | * PHPPresentation is free software distributed under the terms of the GNU Lesser |
| 7 | * General Public License version 3 as published by the Free Software Foundation. |
| 8 | * |
| 9 | * For the full copyright and license information, please read the LICENSE |
| 10 | * file that was distributed with this source code. For the full list of |
| 11 | * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors. |
| 12 | * |
| 13 | * @see https://github.com/PHPOffice/PHPPresentation |
| 14 | * |
| 15 | * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
| 16 | */ |
| 17 | |
| 18 | declare(strict_types=1); |
| 19 | |
| 20 | namespace PhpOffice\PhpPresentation\Writer\ODPresentation; |
| 21 | |
| 22 | use PhpOffice\Common\Adapter\Zip\ZipInterface; |
| 23 | use PhpOffice\Common\Drawing as CommonDrawing; |
| 24 | use PhpOffice\Common\Text; |
| 25 | use PhpOffice\Common\XMLWriter; |
| 26 | use PhpOffice\PhpPresentation\Shape\Group; |
| 27 | use PhpOffice\PhpPresentation\Shape\RichText; |
| 28 | use PhpOffice\PhpPresentation\Shape\Table; |
| 29 | use PhpOffice\PhpPresentation\Slide\Background\Image; |
| 30 | use PhpOffice\PhpPresentation\Style\Border; |
| 31 | use PhpOffice\PhpPresentation\Style\Fill; |
| 32 | |
| 33 | class Styles extends AbstractDecoratorWriter |
| 34 | { |
| 35 | /** |
| 36 | * Stores font styles draw:gradient nodes. |
| 37 | * |
| 38 | * @var array<int, string> |
| 39 | */ |
| 40 | protected $arrayGradient = []; |
| 41 | |
| 42 | /** |
| 43 | * Stores font styles draw:stroke-dash nodes. |
| 44 | * |
| 45 | * @var array<int, string> |
| 46 | */ |
| 47 | protected $arrayStrokeDash = []; |
| 48 | |
| 49 | public function render(): ZipInterface |
| 50 | { |
| 51 | $this->getZip()->addFromString('styles.xml', $this->writePart()); |
| 52 | |
| 53 | return $this->getZip(); |
| 54 | } |
| 55 | |
| 56 | /** |
| 57 | * Write Meta file to XML format. |
| 58 | * |
| 59 | * @return string XML Output |
| 60 | */ |
| 61 | protected function writePart(): string |
| 62 | { |
| 63 | // Create XML writer |
| 64 | $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); |
| 65 | $objWriter->startDocument('1.0', 'UTF-8'); |
| 66 | |
| 67 | // office:document-meta |
| 68 | $objWriter->startElement('office:document-styles'); |
| 69 | $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); |
| 70 | $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'); |
| 71 | $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); |
| 72 | $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'); |
| 73 | $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0'); |
| 74 | $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'); |
| 75 | $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); |
| 76 | $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); |
| 77 | $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); |
| 78 | $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'); |
| 79 | $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0'); |
| 80 | $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'); |
| 81 | $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0'); |
| 82 | $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0'); |
| 83 | $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML'); |
| 84 | $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0'); |
| 85 | $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0'); |
| 86 | $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); |
| 87 | $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer'); |
| 88 | $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc'); |
| 89 | $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events'); |
| 90 | $objWriter->writeAttribute('xmlns:smil', 'urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0'); |
| 91 | $objWriter->writeAttribute('xmlns:anim', 'urn:oasis:names:tc:opendocument:xmlns:animation:1.0'); |
| 92 | $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report'); |
| 93 | $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2'); |
| 94 | $objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); |
| 95 | $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); |
| 96 | $objWriter->writeAttribute('xmlns:officeooo', 'http://openoffice.org/2009/office'); |
| 97 | $objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table'); |
| 98 | $objWriter->writeAttribute('xmlns:drawooo', 'http://openoffice.org/2010/draw'); |
| 99 | $objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/'); |
| 100 | $objWriter->writeAttribute('office:version', '1.2'); |
| 101 | |
| 102 | // Variables |
| 103 | $stylePageLayout = $this->getPresentation()->getLayout()->getDocumentLayout(); |
| 104 | if (empty($stylePageLayout)) { |
| 105 | $stylePageLayout = 'sPL0'; |
| 106 | } |
| 107 | |
| 108 | // office:styles |
| 109 | $objWriter->startElement('office:styles'); |
| 110 | // style:style |
| 111 | $objWriter->startElement('style:style'); |
| 112 | $objWriter->writeAttribute('style:name', 'sPres0'); |
| 113 | $objWriter->writeAttribute('style:display-name', 'sPres0'); |
| 114 | $objWriter->writeAttribute('style:family', 'presentation'); |
| 115 | // style:graphic-properties |
| 116 | $objWriter->startElement('style:graphic-properties'); |
| 117 | $objWriter->writeAttribute('draw:fill-color', '#ffffff'); |
| 118 | // > style:graphic-properties |
| 119 | $objWriter->endElement(); |
| 120 | // > style:style |
| 121 | $objWriter->endElement(); |
| 122 | |
| 123 | foreach ($this->getPresentation()->getAllSlides() as $keySlide => $oSlide) { |
| 124 | foreach ($oSlide->getShapeCollection() as $shape) { |
| 125 | if ($shape instanceof Table) { |
| 126 | $this->writeTableStyle($objWriter, $shape); |
| 127 | } elseif ($shape instanceof Group) { |
| 128 | $this->writeGroupStyle($objWriter, $shape); |
| 129 | } elseif ($shape instanceof RichText) { |
| 130 | $this->writeRichTextStyle($objWriter, $shape); |
| 131 | } |
| 132 | } |
| 133 | $oBkgImage = $oSlide->getBackground(); |
| 134 | if ($oBkgImage instanceof Image) { |
| 135 | $this->writeBackgroundStyle($objWriter, $oBkgImage, $keySlide); |
| 136 | } |
| 137 | } |
| 138 | // > office:styles |
| 139 | $objWriter->endElement(); |
| 140 | |
| 141 | // office:automatic-styles |
| 142 | $objWriter->startElement('office:automatic-styles'); |
| 143 | // style:page-layout |
| 144 | $objWriter->startElement('style:page-layout'); |
| 145 | $objWriter->writeAttribute('style:name', $stylePageLayout); |
| 146 | // style:page-layout-properties |
| 147 | $objWriter->startElement('style:page-layout-properties'); |
| 148 | $objWriter->writeAttribute('fo:margin-top', '0cm'); |
| 149 | $objWriter->writeAttribute('fo:margin-bottom', '0cm'); |
| 150 | $objWriter->writeAttribute('fo:margin-left', '0cm'); |
| 151 | $objWriter->writeAttribute('fo:margin-right', '0cm'); |
| 152 | $objWriter->writeAttribute('fo:page-width', Text::numberFormat(CommonDrawing::pixelsToCentimeters(CommonDrawing::emuToPixels((int) $this->getPresentation()->getLayout()->getCX())), 1) . 'cm'); |
| 153 | $objWriter->writeAttribute('fo:page-height', Text::numberFormat(CommonDrawing::pixelsToCentimeters(CommonDrawing::emuToPixels((int) $this->getPresentation()->getLayout()->getCY())), 1) . 'cm'); |
| 154 | $printOrientation = 'portrait'; |
| 155 | if ($this->getPresentation()->getLayout()->getCX() > $this->getPresentation()->getLayout()->getCY()) { |
| 156 | $printOrientation = 'landscape'; |
| 157 | } |
| 158 | $objWriter->writeAttribute('style:print-orientation', $printOrientation); |
| 159 | $objWriter->endElement(); |
| 160 | $objWriter->endElement(); |
| 161 | $objWriter->endElement(); |
| 162 | |
| 163 | // office:master-styles |
| 164 | $objWriter->startElement('office:master-styles'); |
| 165 | // style:master-page |
| 166 | $objWriter->startElement('style:master-page'); |
| 167 | $objWriter->writeAttribute('style:name', 'Standard'); |
| 168 | $objWriter->writeAttribute('style:display-name', 'Standard'); |
| 169 | $objWriter->writeAttribute('style:page-layout-name', $stylePageLayout); |
| 170 | $objWriter->writeAttribute('draw:style-name', 'sPres0'); |
| 171 | $objWriter->endElement(); |
| 172 | $objWriter->endElement(); |
| 173 | |
| 174 | $objWriter->endElement(); |
| 175 | |
| 176 | // Return |
| 177 | return $objWriter->getData(); |
| 178 | } |
| 179 | |
| 180 | /** |
| 181 | * Write the default style information for a RichText shape. |
| 182 | */ |
| 183 | protected function writeRichTextStyle(XMLWriter $objWriter, RichText $shape): void |
| 184 | { |
| 185 | $oFill = $shape->getFill(); |
| 186 | if (Fill::FILL_GRADIENT_LINEAR == $oFill->getFillType() || Fill::FILL_GRADIENT_PATH == $oFill->getFillType()) { |
| 187 | if (!in_array($oFill->getHashCode(), $this->arrayGradient)) { |
| 188 | $this->writeGradientFill($objWriter, $oFill); |
| 189 | } |
| 190 | } |
| 191 | $oBorder = $shape->getBorder(); |
| 192 | if (Border::DASH_SOLID != $oBorder->getDashStyle()) { |
| 193 | if (!in_array($oBorder->getDashStyle(), $this->arrayStrokeDash)) { |
| 194 | $objWriter->startElement('draw:stroke-dash'); |
| 195 | $objWriter->writeAttribute('draw:name', 'strokeDash_' . $oBorder->getDashStyle()); |
| 196 | $objWriter->writeAttribute('draw:style', 'rect'); |
| 197 | switch ($oBorder->getDashStyle()) { |
| 198 | case Border::DASH_DASH: |
| 199 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 200 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 201 | $objWriter->writeAttribute('draw:dots2-length', '0.14cm'); |
| 202 | |
| 203 | break; |
| 204 | case Border::DASH_DASHDOT: |
| 205 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 206 | $objWriter->writeAttribute('draw:dots1', '1'); |
| 207 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 208 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 209 | $objWriter->writeAttribute('draw:dots2-length', '0.14cm'); |
| 210 | |
| 211 | break; |
| 212 | case Border::DASH_DOT: |
| 213 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 214 | $objWriter->writeAttribute('draw:dots1', '1'); |
| 215 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 216 | |
| 217 | break; |
| 218 | case Border::DASH_LARGEDASH: |
| 219 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 220 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 221 | $objWriter->writeAttribute('draw:dots2-length', '0.28cm'); |
| 222 | |
| 223 | break; |
| 224 | case Border::DASH_LARGEDASHDOT: |
| 225 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 226 | $objWriter->writeAttribute('draw:dots1', '1'); |
| 227 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 228 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 229 | $objWriter->writeAttribute('draw:dots2-length', '0.28cm'); |
| 230 | |
| 231 | break; |
| 232 | case Border::DASH_LARGEDASHDOTDOT: |
| 233 | $objWriter->writeAttribute('draw:distance', '0.105cm'); |
| 234 | $objWriter->writeAttribute('draw:dots1', '2'); |
| 235 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 236 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 237 | $objWriter->writeAttribute('draw:dots2-length', '0.28cm'); |
| 238 | |
| 239 | break; |
| 240 | case Border::DASH_SYSDASH: |
| 241 | $objWriter->writeAttribute('draw:distance', '0.035cm'); |
| 242 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 243 | $objWriter->writeAttribute('draw:dots2-length', '0.105cm'); |
| 244 | |
| 245 | break; |
| 246 | case Border::DASH_SYSDASHDOT: |
| 247 | $objWriter->writeAttribute('draw:distance', '0.035cm'); |
| 248 | $objWriter->writeAttribute('draw:dots1', '1'); |
| 249 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 250 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 251 | $objWriter->writeAttribute('draw:dots2-length', '0.105cm'); |
| 252 | |
| 253 | break; |
| 254 | case Border::DASH_SYSDASHDOTDOT: |
| 255 | $objWriter->writeAttribute('draw:distance', '0.035cm'); |
| 256 | $objWriter->writeAttribute('draw:dots1', '2'); |
| 257 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 258 | $objWriter->writeAttribute('draw:dots2', '1'); |
| 259 | $objWriter->writeAttribute('draw:dots2-length', '0.105cm'); |
| 260 | |
| 261 | break; |
| 262 | case Border::DASH_SYSDOT: |
| 263 | $objWriter->writeAttribute('draw:distance', '0.035cm'); |
| 264 | $objWriter->writeAttribute('draw:dots1', '1'); |
| 265 | $objWriter->writeAttribute('draw:dots1-length', '0.035cm'); |
| 266 | |
| 267 | break; |
| 268 | } |
| 269 | $objWriter->endElement(); |
| 270 | $this->arrayStrokeDash[] = $oBorder->getDashStyle(); |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * Write the default style information for a Table shape. |
| 277 | */ |
| 278 | protected function writeTableStyle(XMLWriter $objWriter, Table $shape): void |
| 279 | { |
| 280 | foreach ($shape->getRows() as $row) { |
| 281 | foreach ($row->getCells() as $cell) { |
| 282 | if (Fill::FILL_GRADIENT_LINEAR == $cell->getFill()->getFillType()) { |
| 283 | if (!in_array($cell->getFill()->getHashCode(), $this->arrayGradient)) { |
| 284 | $this->writeGradientFill($objWriter, $cell->getFill()); |
| 285 | } |
| 286 | } |
| 287 | } |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | /** |
| 292 | * Writes the style information for a group of shapes. |
| 293 | */ |
| 294 | protected function writeGroupStyle(XMLWriter $objWriter, Group $group): void |
| 295 | { |
| 296 | $shapes = $group->getShapeCollection(); |
| 297 | foreach ($shapes as $shape) { |
| 298 | if ($shape instanceof Table) { |
| 299 | $this->writeTableStyle($objWriter, $shape); |
| 300 | } elseif ($shape instanceof Group) { |
| 301 | $this->writeGroupStyle($objWriter, $shape); |
| 302 | } |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | /** |
| 307 | * Write the gradient style. |
| 308 | */ |
| 309 | protected function writeGradientFill(XMLWriter $objWriter, Fill $oFill): void |
| 310 | { |
| 311 | $objWriter->startElement('draw:gradient'); |
| 312 | $objWriter->writeAttribute('draw:name', 'gradient_' . $oFill->getHashCode()); |
| 313 | $objWriter->writeAttribute('draw:display-name', 'gradient_' . $oFill->getHashCode()); |
| 314 | $objWriter->writeAttribute('draw:style', 'linear'); |
| 315 | $objWriter->writeAttribute('draw:start-intensity', '100%'); |
| 316 | $objWriter->writeAttribute('draw:end-intensity', '100%'); |
| 317 | $objWriter->writeAttribute('draw:start-color', '#' . $oFill->getStartColor()->getRGB()); |
| 318 | $objWriter->writeAttribute('draw:end-color', '#' . $oFill->getEndColor()->getRGB()); |
| 319 | $objWriter->writeAttribute('draw:border', '0%'); |
| 320 | $objWriter->writeAttribute('draw:angle', $oFill->getRotation() - 90); |
| 321 | $objWriter->endElement(); |
| 322 | $this->arrayGradient[] = $oFill->getHashCode(); |
| 323 | } |
| 324 | |
| 325 | /** |
| 326 | * Write the background image style. |
| 327 | */ |
| 328 | protected function writeBackgroundStyle(XMLWriter $objWriter, Image $oBkgImage, int $numSlide): void |
| 329 | { |
| 330 | $objWriter->startElement('draw:fill-image'); |
| 331 | $objWriter->writeAttribute('draw:name', 'background_' . (string) $numSlide); |
| 332 | $objWriter->writeAttribute('xlink:href', 'Pictures/' . str_replace(' ', '_', $oBkgImage->getIndexedFilename((string) $numSlide))); |
| 333 | $objWriter->writeAttribute('xlink:type', 'simple'); |
| 334 | $objWriter->writeAttribute('xlink:show', 'embed'); |
| 335 | $objWriter->writeAttribute('xlink:actuate', 'onLoad'); |
| 336 | $objWriter->endElement(); |
| 337 | } |
| 338 | } |