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 | } |