Completed
Pull Request — develop (#208)
by Franck
39:09 queued 30:26
created

Content   F

Complexity

Total Complexity 223

Size/Duplication

Total Lines 1269
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 36

Test Coverage

Coverage 92.44%

Importance

Changes 9
Bugs 0 Features 3
Metric Value
wmc 223
c 9
b 0
f 3
lcom 1
cbo 36
dl 0
loc 1269
ccs 831
cts 899
cp 0.9244
rs 0.5217

17 Methods

Rating   Name   Duplication   Size   Complexity  
A render() 0 5 1
A writeShapeLine() 0 15 1
B writeShapeChart() 0 25 1
F writeContent() 0 241 36
B writeShapePic() 0 42 4
D writeShapeTxt() 0 155 30
A writeShapeComment() 0 16 2
C writeShapeTable() 0 81 13
C writeShapeGroup() 0 28 8
B writeGroupStyle() 0 22 6
F writeTxtStyle() 0 104 27
A writeDrawingStyle() 0 19 2
B writeLineStyle() 0 28 3
F writeTableStyle() 0 101 17
A writeSlideNote() 0 18 4
F writeStyleSlide() 0 194 58
D writeStylePartShadow() 0 33 10

How to fix   Complexity   

Complex Class

Complex classes like Content often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Content, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PhpOffice\PhpPresentation\Writer\ODPresentation;
4
5
use PhpOffice\Common\Adapter\Zip\ZipInterface;
6
use PhpOffice\Common\Drawing as CommonDrawing;
7
use PhpOffice\Common\Text;
8
use PhpOffice\Common\XMLWriter;
9
use PhpOffice\PhpPresentation\Shape\Comment;
10
use PhpOffice\PhpPresentation\Slide;
11
use PhpOffice\PhpPresentation\Shape\AbstractDrawing;
12
use PhpOffice\PhpPresentation\Shape\Chart;
13
use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing;
14
use PhpOffice\PhpPresentation\Shape\Group;
15
use PhpOffice\PhpPresentation\Shape\Line;
16
use PhpOffice\PhpPresentation\Shape\MemoryDrawing;
17
use PhpOffice\PhpPresentation\Shape\RichText\BreakElement;
18
use PhpOffice\PhpPresentation\Shape\RichText\Run;
19
use PhpOffice\PhpPresentation\Shape\RichText\TextElement;
20
use PhpOffice\PhpPresentation\Shape\RichText;
21
use PhpOffice\PhpPresentation\Shape\Table;
22
use PhpOffice\PhpPresentation\Slide\Note;
23
use PhpOffice\PhpPresentation\Slide\Transition;
24
use PhpOffice\PhpPresentation\Style\Alignment;
25
use PhpOffice\PhpPresentation\Style\Border;
26
use PhpOffice\PhpPresentation\Style\Fill;
27
use PhpOffice\PhpPresentation\Style\Shadow;
28
use PhpOffice\PhpPresentation\Writer\ODPresentation;
29
30
class Content extends AbstractDecoratorWriter
31
{
32
    /**
33
     * Stores bullet styles for text shapes that include lists.
34
     *
35
     * @var []
36
     */
37
    protected $arrStyleBullet    = array();
38
39
    /**
40
     * Stores paragraph information for text shapes.
41
     *
42
     * @var array
43
     */
44
    protected $arrStyleParagraph = array();
45
46
    /**
47
     * Stores font styles for text shapes that include lists.
48
     *
49
     * @var Run[]
50
     */
51
    protected $arrStyleTextFont  = array();
52
53
    /**
54
     * Used to track the current shape ID.
55
     *
56
     * @var integer
57
     */
58
    protected $shapeId;
59
60
    /**
61
     * @return ZipInterface
62
     */
63 57
    public function render()
64
    {
65 57
        $this->getZip()->addFromString('content.xml', $this->writeContent());
66 57
        return $this->getZip();
67
    }
68
69
70
71
    /**
72
     * Write content file to XML format
73
     *
74
     * @return string        XML Output
75
     * @throws \Exception
76
     */
77 57
    public function writeContent()
78
    {
79
        // Create XML writer
80 57
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
81 57
        $objWriter->startDocument('1.0', 'UTF-8');
82
83
        // office:document-content
84 57
        $objWriter->startElement('office:document-content');
85 57
        $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
86 57
        $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
87 57
        $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
88 57
        $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
89 57
        $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
90 57
        $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
91 57
        $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
92 57
        $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
93 57
        $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
94 57
        $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
95 57
        $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
96 57
        $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
97 57
        $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
98 57
        $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
99 57
        $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
100 57
        $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
101 57
        $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
102 57
        $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
103 57
        $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
104 57
        $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
105 57
        $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
106 57
        $objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms');
107 57
        $objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
108 57
        $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
109 57
        $objWriter->writeAttribute('xmlns:smil', 'urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0');
110 57
        $objWriter->writeAttribute('xmlns:anim', 'urn:oasis:names:tc:opendocument:xmlns:animation:1.0');
111 57
        $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
112 57
        $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
113 57
        $objWriter->writeAttribute('xmlns:rdfa', 'http://docs.oasis-open.org/opendocument/meta/rdfa#');
114 57
        $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
115 57
        $objWriter->writeAttribute('xmlns:officeooo', 'http://openoffice.org/2009/office');
116 57
        $objWriter->writeAttribute('office:version', '1.2');
117
118
        // office:automatic-styles
119 57
        $objWriter->startElement('office:automatic-styles');
120
121 57
        $this->shapeId    = 0;
122 57
        $incSlide = 0;
123 57
        foreach ($this->getPresentation()->getAllSlides() as $pSlide) {
124
            // Slides
125 57
            $this->writeStyleSlide($objWriter, $pSlide, $incSlide);
126
127
            // Images
128 57
            $shapes = $pSlide->getShapeCollection();
129 57
            foreach ($shapes as $shape) {
130
                // Increment $this->shapeId
131 50
                ++$this->shapeId;
132
133
                // Check type
134 50
                if ($shape instanceof RichText) {
135 14
                    $this->writeTxtStyle($objWriter, $shape);
136 14
                }
137 50
                if ($shape instanceof AbstractDrawing) {
138 34
                    $this->writeDrawingStyle($objWriter, $shape);
139 34
                }
140 50
                if ($shape instanceof Line) {
141 1
                    $this->writeLineStyle($objWriter, $shape);
142 1
                }
143 50
                if ($shape instanceof Table) {
144 7
                    $this->writeTableStyle($objWriter, $shape);
145 7
                }
146 50
                if ($shape instanceof Group) {
147 1
                    $this->writeGroupStyle($objWriter, $shape);
148 1
                }
149 57
            }
150
151 57
            $incSlide++;
152 57
        }
153
        // Style : Bullet
154 57
        if (!empty($this->arrStyleBullet)) {
155 14
            foreach ($this->arrStyleBullet as $key => $item) {
156 14
                $oStyle   = $item['oStyle'];
157 14
                $arrLevel = explode(';', $item['level']);
158
                // style:style
159 14
                $objWriter->startElement('text:list-style');
160 14
                $objWriter->writeAttribute('style:name', 'L_' . $key);
161 14
                foreach ($arrLevel as $level) {
162 14
                    if ($level != '') {
163 14
                        $oAlign = $item['oAlign_' . $level];
164
                        // text:list-level-style-bullet
165 14
                        $objWriter->startElement('text:list-level-style-bullet');
166 14
                        $objWriter->writeAttribute('text:level', $level + 1);
167 14
                        $objWriter->writeAttribute('text:bullet-char', $oStyle->getBulletChar());
168
                        // style:list-level-properties
169 14
                        $objWriter->startElement('style:list-level-properties');
170 14
                        if ($oAlign->getIndent() < 0) {
171 1
                            $objWriter->writeAttribute('text:space-before', CommonDrawing::pixelsToCentimeters($oAlign->getMarginLeft() - (-1 * $oAlign->getIndent())) . 'cm');
172 1
                            $objWriter->writeAttribute('text:min-label-width', CommonDrawing::pixelsToCentimeters(-1 * $oAlign->getIndent()) . 'cm');
173 1
                        } else {
174 13
                            $objWriter->writeAttribute('text:space-before', (CommonDrawing::pixelsToCentimeters($oAlign->getMarginLeft() - $oAlign->getIndent())) . 'cm');
175 13
                            $objWriter->writeAttribute('text:min-label-width', CommonDrawing::pixelsToCentimeters($oAlign->getIndent()) . 'cm');
176
                        }
177
178 14
                        $objWriter->endElement();
179
                        // style:text-properties
180 14
                        $objWriter->startElement('style:text-properties');
181 14
                        $objWriter->writeAttribute('fo:font-family', $oStyle->getBulletFont());
182 14
                        $objWriter->writeAttribute('style:font-family-generic', 'swiss');
183 14
                        $objWriter->writeAttribute('style:use-window-font-color', 'true');
184 14
                        $objWriter->writeAttribute('fo:font-size', '100');
185 14
                        $objWriter->endElement();
186 14
                        $objWriter->endElement();
187 14
                    }
188 14
                }
189 14
                $objWriter->endElement();
190 14
            }
191 14
        }
192
        // Style : Paragraph
193 57
        if (!empty($this->arrStyleParagraph)) {
194 14
            foreach ($this->arrStyleParagraph as $key => $item) {
195
                // style:style
196 14
                $objWriter->startElement('style:style');
197 14
                $objWriter->writeAttribute('style:name', 'P_' . $key);
198 14
                $objWriter->writeAttribute('style:family', 'paragraph');
199
                // style:paragraph-properties
200 14
                $objWriter->startElement('style:paragraph-properties');
201 14
                switch ($item->getAlignment()->getHorizontal()) {
202 14
                    case Alignment::HORIZONTAL_LEFT:
203 14
                        $objWriter->writeAttribute('fo:text-align', 'left');
204 14
                        break;
205 1
                    case Alignment::HORIZONTAL_RIGHT:
206 1
                        $objWriter->writeAttribute('fo:text-align', 'right');
207 1
                        break;
208 1
                    case Alignment::HORIZONTAL_CENTER:
209 1
                        $objWriter->writeAttribute('fo:text-align', 'center');
210 1
                        break;
211 1
                    case Alignment::HORIZONTAL_JUSTIFY:
212 1
                        $objWriter->writeAttribute('fo:text-align', 'justify');
213 1
                        break;
214 1
                    case Alignment::HORIZONTAL_DISTRIBUTED:
215 1
                        $objWriter->writeAttribute('fo:text-align', 'justify');
216 1
                        break;
217 1
                    default:
218 1
                        $objWriter->writeAttribute('fo:text-align', 'left');
219 1
                        break;
220 14
                }
221 14
                $objWriter->endElement();
222 14
                $objWriter->endElement();
223 14
            }
224 14
        }
225
        // Style : Text : Font
226 57
        if (!empty($this->arrStyleTextFont)) {
227 10
            foreach ($this->arrStyleTextFont as $key => $item) {
228
                // style:style
229 10
                $objWriter->startElement('style:style');
230 10
                $objWriter->writeAttribute('style:name', 'T_' . $key);
231 10
                $objWriter->writeAttribute('style:family', 'text');
232
                // style:text-properties
233 10
                $objWriter->startElement('style:text-properties');
234 10
                $objWriter->writeAttribute('fo:color', '#' . $item->getFont()->getColor()->getRGB());
235 10
                $objWriter->writeAttribute('fo:font-family', $item->getFont()->getName());
236 10
                $objWriter->writeAttribute('fo:font-size', $item->getFont()->getSize() . 'pt');
237
                // @todo : fo:font-style
238 10
                if ($item->getFont()->isBold()) {
239 1
                    $objWriter->writeAttribute('fo:font-weight', 'bold');
240 1
                }
241 10
                $objWriter->writeAttribute('fo:language', ($item->getLanguage() ? $item->getLanguage() : 'en-US'));
242
243
                // @todo : style:text-underline-style
244 10
                $objWriter->endElement();
245 10
                $objWriter->endElement();
246 10
            }
247 10
        }
248 57
        $objWriter->endElement();
249
250
        //===============================================
251
        // Body
252
        //===============================================
253
        // office:body
254 57
        $objWriter->startElement('office:body');
255
        // office:presentation
256 57
        $objWriter->startElement('office:presentation');
257
258
        // Write slides
259 57
        $slideCount = $this->getPresentation()->getSlideCount();
260 57
        $this->shapeId    = 0;
261 57
        for ($i = 0; $i < $slideCount; ++$i) {
262 57
            $pSlide = $this->getPresentation()->getSlide($i);
263 57
            $objWriter->startElement('draw:page');
264 57
            $name = $pSlide->getName();
265 57
            if (!is_null($name)) {
266 1
                $objWriter->writeAttribute('draw:name', $name);
267 1
            }
268 57
            $objWriter->writeAttribute('draw:master-page-name', 'Standard');
269 57
            $objWriter->writeAttribute('draw:style-name', 'stylePage' . $i);
270
            // Images
271 57
            $shapes = $pSlide->getShapeCollection();
272 57
            foreach ($shapes as $shape) {
273
                // Increment $this->shapeId
274 50
                ++$this->shapeId;
275
276
                // Check type
277 50
                if ($shape instanceof RichText) {
278 14
                    $this->writeShapeTxt($objWriter, $shape);
279 50
                } elseif ($shape instanceof Table) {
280 7
                    $this->writeShapeTable($objWriter, $shape);
281 37
                } elseif ($shape instanceof Line) {
282 1
                    $this->writeShapeLine($objWriter, $shape);
283 31
                } elseif ($shape instanceof Chart) {
284 21
                    $this->writeShapeChart($objWriter, $shape);
285 31
                } elseif ($shape instanceof AbstractDrawing) {
286 8
                    $this->writeShapePic($objWriter, $shape);
287 11
                } elseif ($shape instanceof Group) {
288 1
                    $this->writeShapeGroup($objWriter, $shape);
289 3
                } elseif ($shape instanceof Comment) {
290 2
                    $this->writeShapeComment($objWriter, $shape);
291 2
                }
292 57
            }
293
            // Slide Note
294 57
            if ($pSlide->getNote() instanceof Note) {
295 57
                $this->writeSlideNote($objWriter, $pSlide->getNote());
296 57
            }
297
298 57
            $objWriter->endElement();
299 57
        }
300
301 57
        if ($this->getPresentation()->getPresentationProperties()->isLoopContinuouslyUntilEsc()) {
302
            $objWriter->startElement('presentation:settings');
303
            $objWriter->writeAttribute('presentation:endless', 'true');
304
            $objWriter->writeAttribute('presentation:pause', 'P0s');
305
            $objWriter->writeAttribute('presentation:mouse-visible', 'false');
306
            $objWriter->endElement();
307
        }
308
        // > office:presentation
309 57
        $objWriter->endElement();
310
        // > office:body
311 57
        $objWriter->endElement();
312
        // > office:document-content
313 57
        $objWriter->endElement();
314
315
        // Return
316 57
        return $objWriter->getData();
317
    }
318
319
    /**
320
     * Write picture
321
     *
322
     * @param \PhpOffice\Common\XMLWriter $objWriter
323
     * @param \PhpOffice\PhpPresentation\Shape\AbstractDrawing $shape
324
     */
325 9
    public function writeShapePic(XMLWriter $objWriter, AbstractDrawing $shape)
326
    {
327
        // draw:frame
328 9
        $objWriter->startElement('draw:frame');
329 9
        $objWriter->writeAttribute('draw:name', $shape->getName());
330 9
        $objWriter->writeAttribute('svg:width', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getWidth()), 3) . 'cm');
331 9
        $objWriter->writeAttribute('svg:height', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getHeight()), 3) . 'cm');
332 9
        $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()), 3) . 'cm');
333 9
        $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()), 3) . 'cm');
334 9
        $objWriter->writeAttribute('draw:style-name', 'gr' . $this->shapeId);
335
        // draw:image
336 9
        $objWriter->startElement('draw:image');
337 9
        if ($shape instanceof ShapeDrawing) {
338 8
            $objWriter->writeAttribute('xlink:href', 'Pictures/' . md5($shape->getPath()) . '.' . $shape->getExtension());
339 9
        } elseif ($shape instanceof MemoryDrawing) {
340 1
            $objWriter->writeAttribute('xlink:href', 'Pictures/' . $shape->getIndexedFilename());
341 1
        }
342 9
        $objWriter->writeAttribute('xlink:type', 'simple');
343 9
        $objWriter->writeAttribute('xlink:show', 'embed');
344 9
        $objWriter->writeAttribute('xlink:actuate', 'onLoad');
345 9
        $objWriter->writeElement('text:p');
346 9
        $objWriter->endElement();
347
348 9
        if ($shape->hasHyperlink()) {
349
            // office:event-listeners
350 2
            $objWriter->startElement('office:event-listeners');
351
            // presentation:event-listener
352 2
            $objWriter->startElement('presentation:event-listener');
353 2
            $objWriter->writeAttribute('script:event-name', 'dom:click');
354 2
            $objWriter->writeAttribute('presentation:action', 'show');
355 2
            $objWriter->writeAttribute('xlink:href', $shape->getHyperlink()->getUrl());
356 2
            $objWriter->writeAttribute('xlink:type', 'simple');
357 2
            $objWriter->writeAttribute('xlink:show', 'embed');
358 2
            $objWriter->writeAttribute('xlink:actuate', 'onRequest');
359
            // > presentation:event-listener
360 2
            $objWriter->endElement();
361
            // > office:event-listeners
362 2
            $objWriter->endElement();
363 2
        }
364
365 9
        $objWriter->endElement();
366 9
    }
367
368
    /**
369
     * Write text
370
     *
371
     * @param \PhpOffice\Common\XMLWriter $objWriter
372
     * @param \PhpOffice\PhpPresentation\Shape\RichText $shape
373
     */
374 15
    public function writeShapeTxt(XMLWriter $objWriter, RichText $shape)
375
    {
376
        // draw:frame
377 15
        $objWriter->startElement('draw:frame');
378 15
        $objWriter->writeAttribute('draw:style-name', 'gr' . $this->shapeId);
379 15
        $objWriter->writeAttribute('svg:width', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getWidth()), 3) . 'cm');
380 15
        $objWriter->writeAttribute('svg:height', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getHeight()), 3) . 'cm');
381 15
        $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()), 3) . 'cm');
382 15
        $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()), 3) . 'cm');
383
        // draw:text-box
384 15
        $objWriter->startElement('draw:text-box');
385
386 15
        $paragraphs             = $shape->getParagraphs();
387 15
        $paragraphId            = 0;
388 15
        $sCstShpLastBullet      = '';
389 15
        $iCstShpLastBulletLvl   = 0;
390 15
        $bCstShpHasBullet       = false;
391
392 15
        foreach ($paragraphs as $paragraph) {
393
            // Close the bullet list
394 15
            if ($sCstShpLastBullet != 'bullet' && $bCstShpHasBullet === true) {
395
                for ($iInc = $iCstShpLastBulletLvl; $iInc >= 0; $iInc--) {
396
                    // text:list-item
397
                    $objWriter->endElement();
398
                    // text:list
399
                    $objWriter->endElement();
400
                }
401
            }
402
            //===============================================
403
            // Paragraph
404
            //===============================================
405 15
            if ($paragraph->getBulletStyle()->getBulletType() == 'none') {
406 12
                ++$paragraphId;
407
                // text:p
408 12
                $objWriter->startElement('text:p');
409 12
                $objWriter->writeAttribute('text:style-name', 'P_' . $paragraph->getHashCode());
410
411
                // Loop trough rich text elements
412 12
                $richtexts  = $paragraph->getRichTextElements();
413 12
                $richtextId = 0;
414 12
                foreach ($richtexts as $richtext) {
415 6
                    ++$richtextId;
416 6
                    if ($richtext instanceof TextElement || $richtext instanceof Run) {
417
                        // text:span
418 6
                        $objWriter->startElement('text:span');
419 6
                        if ($richtext instanceof Run) {
420 6
                            $objWriter->writeAttribute('text:style-name', 'T_' . $richtext->getHashCode());
421 6
                        }
422 6
                        if ($richtext->hasHyperlink() === true && $richtext->getHyperlink()->getUrl() != '') {
423
                            // text:a
424 1
                            $objWriter->startElement('text:a');
425 1
                            $objWriter->writeAttribute('xlink:href', $richtext->getHyperlink()->getUrl());
426 1
                            $objWriter->text($richtext->getText());
427 1
                            $objWriter->endElement();
428 1
                        } else {
429 6
                            $objWriter->text($richtext->getText());
430
                        }
431 6
                        $objWriter->endElement();
432 6
                    } elseif ($richtext instanceof BreakElement) {
433
                        // text:span
434 1
                        $objWriter->startElement('text:span');
435
                        // text:line-break
436 1
                        $objWriter->startElement('text:line-break');
437 1
                        $objWriter->endElement();
438 1
                        $objWriter->endElement();
439 1
                    } else {
440
                        //echo '<pre>'.print_r($richtext, true).'</pre>';
441
                    }
442 12
                }
443 12
                $objWriter->endElement();
444
                //===============================================
445
                // Bullet list
446
                //===============================================
447 15
            } elseif ($paragraph->getBulletStyle()->getBulletType() == 'bullet') {
448 3
                $bCstShpHasBullet = true;
449
                // Open the bullet list
450 3
                if ($sCstShpLastBullet != 'bullet' || ($sCstShpLastBullet == $paragraph->getBulletStyle()->getBulletType() && $iCstShpLastBulletLvl < $paragraph->getAlignment()->getLevel())) {
451
                    // text:list
452 3
                    $objWriter->startElement('text:list');
453 3
                    $objWriter->writeAttribute('text:style-name', 'L_' . $paragraph->getBulletStyle()->getHashCode());
454 3
                }
455 3
                if ($sCstShpLastBullet == 'bullet') {
456 2
                    if ($iCstShpLastBulletLvl == $paragraph->getAlignment()->getLevel()) {
457
                        // text:list-item
458 2
                        $objWriter->endElement();
459 2
                    } elseif ($iCstShpLastBulletLvl > $paragraph->getAlignment()->getLevel()) {
460
                        // text:list-item
461 1
                        $objWriter->endElement();
462
                        // text:list
463 1
                        $objWriter->endElement();
464
                        // text:list-item
465 1
                        $objWriter->endElement();
466 1
                    }
467 2
                }
468
469
                // text:list-item
470 3
                $objWriter->startElement('text:list-item');
471 3
                ++$paragraphId;
472
                // text:p
473 3
                $objWriter->startElement('text:p');
474 3
                $objWriter->writeAttribute('text:style-name', 'P_' . $paragraph->getHashCode());
475
476
                // Loop trough rich text elements
477 3
                $richtexts  = $paragraph->getRichTextElements();
478 3
                $richtextId = 0;
479 3
                foreach ($richtexts as $richtext) {
480 3
                    ++$richtextId;
481 3
                    if ($richtext instanceof TextElement || $richtext instanceof Run) {
482
                        // text:span
483 3
                        $objWriter->startElement('text:span');
484 3
                        if ($richtext instanceof Run) {
485 3
                            $objWriter->writeAttribute('text:style-name', 'T_' . $richtext->getHashCode());
486 3
                        }
487 3
                        if ($richtext->hasHyperlink() === true && $richtext->getHyperlink()->getUrl() != '') {
488
                            // text:a
489 1
                            $objWriter->startElement('text:a');
490 1
                            $objWriter->writeAttribute('xlink:href', $richtext->getHyperlink()->getUrl());
491 1
                            $objWriter->text($richtext->getText());
492 1
                            $objWriter->endElement();
493 1
                        } else {
494 3
                            $objWriter->text($richtext->getText());
495
                        }
496 3
                        $objWriter->endElement();
497 3
                    } elseif ($richtext instanceof BreakElement) {
498
                        // text:span
499 1
                        $objWriter->startElement('text:span');
500
                        // text:line-break
501 1
                        $objWriter->startElement('text:line-break');
502 1
                        $objWriter->endElement();
503 1
                        $objWriter->endElement();
504 1
                    } else {
505
                        //echo '<pre>'.print_r($richtext, true).'</pre>';
506
                    }
507 3
                }
508 3
                $objWriter->endElement();
509 3
            }
510 15
            $sCstShpLastBullet      = $paragraph->getBulletStyle()->getBulletType();
511 15
            $iCstShpLastBulletLvl = $paragraph->getAlignment()->getLevel();
512 15
        }
513
514
        // Close the bullet list
515 15
        if ($sCstShpLastBullet == 'bullet' && $bCstShpHasBullet === true) {
516 3
            for ($iInc = $iCstShpLastBulletLvl; $iInc >= 0; $iInc--) {
517
                // text:list-item
518 3
                $objWriter->endElement();
519
                // text:list
520 3
                $objWriter->endElement();
521 3
            }
522 3
        }
523
524
        // > draw:text-box
525 15
        $objWriter->endElement();
526
        // > draw:frame
527 15
        $objWriter->endElement();
528 15
    }
529
    /**
530
     * Write Comment
531
     * @param XMLWriter $objWriter
532
     * @param Comment $oShape
533
     */
534 2
    public function writeShapeComment(XMLWriter $objWriter, Comment $oShape)
535
    {
536
        // officeooo:annotation
537 2
        $objWriter->startElement('officeooo:annotation');
538 2
        $objWriter->writeAttribute('svg:x', number_format(CommonDrawing::pixelsToCentimeters($oShape->getOffsetX()), 2, '.', '').'cm');
539 2
        $objWriter->writeAttribute('svg:y', number_format(CommonDrawing::pixelsToCentimeters($oShape->getOffsetY()), 2, '.', '').'cm');
540
541 2
        if ($oShape->getAuthor() instanceof Comment\Author) {
542 1
            $objWriter->writeElement('dc:creator', $oShape->getAuthor()->getName());
543 1
        }
544 2
        $objWriter->writeElement('dc:date', date('Y-m-d\TH:i:s', $oShape->getDate()));
545 2
        $objWriter->writeElement('text:p', $oShape->getText());
546
547
        // ## officeooo:annotation
548 2
        $objWriter->endElement();
549 2
    }
550
551
    /**
552
     * @param XMLWriter $objWriter
553
     * @param Line $shape
554
     */
555 1
    public function writeShapeLine(XMLWriter $objWriter, Line $shape)
556
    {
557
        // draw:line
558 1
        $objWriter->startElement('draw:line');
559 1
        $objWriter->writeAttribute('draw:style-name', 'gr' . $this->shapeId);
560 1
        $objWriter->writeAttribute('svg:x1', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()), 3) . 'cm');
561 1
        $objWriter->writeAttribute('svg:y1', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()), 3) . 'cm');
562 1
        $objWriter->writeAttribute('svg:x2', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()+$shape->getWidth()), 3) . 'cm');
563 1
        $objWriter->writeAttribute('svg:y2', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()+$shape->getHeight()), 3) . 'cm');
564
565
        // text:p
566 1
        $objWriter->writeElement('text:p');
567
568 1
        $objWriter->endElement();
569 1
    }
570
571
    /**
572
     * Write table Shape
573
     * @param XMLWriter $objWriter
574
     * @param Table $shape
575
     */
576 7
    public function writeShapeTable(XMLWriter $objWriter, Table $shape)
577
    {
578
        // draw:frame
579 7
        $objWriter->startElement('draw:frame');
580 7
        $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()), 3) . 'cm');
581 7
        $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()), 3) . 'cm');
582 7
        $objWriter->writeAttribute('svg:height', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getHeight()), 3) . 'cm');
583 7
        $objWriter->writeAttribute('svg:width', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getWidth()), 3) . 'cm');
584
585
        // table:table
586 7
        $objWriter->startElement('table:table');
587
588 7
        foreach ($shape->getRows() as $keyRow => $shapeRow) {
589
            // table:table-row
590 6
            $objWriter->startElement('table:table-row');
591 6
            $objWriter->writeAttribute('table:style-name', 'gr'.$this->shapeId.'r'.$keyRow);
592
            //@todo getFill
593
594 6
            $numColspan = 0;
595 6
            foreach ($shapeRow->getCells() as $keyCell => $shapeCell) {
596 6
                if ($numColspan == 0) {
597
                    // table:table-cell
598 6
                    $objWriter->startElement('table:table-cell');
599 6
                    $objWriter->writeAttribute('table:style-name', 'gr' . $this->shapeId.'r'.$keyRow.'c'.$keyCell);
600 6
                    if ($shapeCell->getColspan() > 1) {
601 1
                        $objWriter->writeAttribute('table:number-columns-spanned', $shapeCell->getColspan());
602 1
                        $numColspan = $shapeCell->getColspan() - 1;
603 1
                    }
604
605
                    // text:p
606 6
                    $objWriter->startElement('text:p');
607
608
                    // text:span
609 6
                    foreach ($shapeCell->getParagraphs() as $shapeParagraph) {
610 6
                        foreach ($shapeParagraph->getRichTextElements() as $shapeRichText) {
611 2
                            if ($shapeRichText instanceof TextElement || $shapeRichText instanceof Run) {
612
                                // text:span
613 2
                                $objWriter->startElement('text:span');
614 2
                                if ($shapeRichText instanceof Run) {
615 2
                                    $objWriter->writeAttribute('text:style-name', 'T_' . $shapeRichText->getHashCode());
616 2
                                }
617 2
                                if ($shapeRichText->hasHyperlink() === true && $shapeRichText->getHyperlink()->getUrl() != '') {
618
                                    // text:a
619 1
                                    $objWriter->startElement('text:a');
620 1
                                    $objWriter->writeAttribute('xlink:href', $shapeRichText->getHyperlink()->getUrl());
621 1
                                    $objWriter->text($shapeRichText->getText());
622 1
                                    $objWriter->endElement();
623 1
                                } else {
624 1
                                    $objWriter->text($shapeRichText->getText());
625
                                }
626 2
                                $objWriter->endElement();
627 2
                            } elseif ($shapeRichText instanceof BreakElement) {
628
                                // text:span
629 1
                                $objWriter->startElement('text:span');
630
                                // text:line-break
631 1
                                $objWriter->startElement('text:line-break');
632 1
                                $objWriter->endElement();
633 1
                                $objWriter->endElement();
634 1
                            }
635 6
                        }
636 6
                    }
637
638
                    // > text:p
639 6
                    $objWriter->endElement();
640
641
                    // > table:table-cell
642 6
                    $objWriter->endElement();
643 6
                } else {
644
                    // table:covered-table-cell
645 1
                    $objWriter->writeElement('table:covered-table-cell');
646 1
                    $numColspan--;
647
                }
648 6
            }
649
            // > table:table-row
650 6
            $objWriter->endElement();
651 7
        }
652
        // > table:table
653 7
        $objWriter->endElement();
654
        // > draw:frame
655 7
        $objWriter->endElement();
656 7
    }
657
658
    /**
659
     * Write table Chart
660
     * @param XMLWriter $objWriter
661
     * @param Chart $shape
662
     * @throws \Exception
663
     */
664 21
    public function writeShapeChart(XMLWriter $objWriter, Chart $shape)
665
    {
666 21
        $arrayChart = $this->getArrayChart();
667 21
        $arrayChart[$this->shapeId] = $shape;
668 21
        $this->setArrayChart($arrayChart);
669
670
        // draw:frame
671 21
        $objWriter->startElement('draw:frame');
672 21
        $objWriter->writeAttribute('draw:name', $shape->getTitle()->getText());
673 21
        $objWriter->writeAttribute('svg:x', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetX()), 3) . 'cm');
674 21
        $objWriter->writeAttribute('svg:y', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getOffsetY()), 3) . 'cm');
675 21
        $objWriter->writeAttribute('svg:height', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getHeight()), 3) . 'cm');
676 21
        $objWriter->writeAttribute('svg:width', Text::numberFormat(CommonDrawing::pixelsToCentimeters($shape->getWidth()), 3) . 'cm');
677
678
        // draw:object
679 21
        $objWriter->startElement('draw:object');
680 21
        $objWriter->writeAttribute('xlink:href', './Object '.$this->shapeId);
681 21
        $objWriter->writeAttribute('xlink:type', 'simple');
682 21
        $objWriter->writeAttribute('xlink:show', 'embed');
683
684
        // > draw:object
685 21
        $objWriter->endElement();
686
        // > draw:frame
687 21
        $objWriter->endElement();
688 21
    }
689
690
    /**
691
     * Writes a group of shapes
692
     *
693
     * @param XMLWriter $objWriter
694
     * @param Group $group
695
     */
696 1
    public function writeShapeGroup(XMLWriter $objWriter, Group $group)
697
    {
698
        // draw:g
699 1
        $objWriter->startElement('draw:g');
700
701 1
        $shapes = $group->getShapeCollection();
702 1
        foreach ($shapes as $shape) {
703
            // Increment $this->shapeId
704 1
            ++$this->shapeId;
705
706
            // Check type
707 1
            if ($shape instanceof RichText) {
708
                $this->writeShapeTxt($objWriter, $shape);
709 1
            } elseif ($shape instanceof Table) {
710
                $this->writeShapeTable($objWriter, $shape);
711 1
            } elseif ($shape instanceof Line) {
712
                $this->writeShapeLine($objWriter, $shape);
713 1
            } elseif ($shape instanceof Chart) {
714
                $this->writeShapeChart($objWriter, $shape);
715 1
            } elseif ($shape instanceof AbstractDrawing) {
716 1
                $this->writeShapePic($objWriter, $shape);
717 1
            } elseif ($shape instanceof Group) {
718
                $this->writeShapeGroup($objWriter, $shape);
719
            }
720 1
        }
721
722 1
        $objWriter->endElement(); // draw:g
723 1
    }
724
725
    /**
726
     * Writes the style information for a group of shapes
727
     *
728
     * @param XMLWriter $objWriter
729
     * @param Group $group
730
     */
731 1
    public function writeGroupStyle(XMLWriter $objWriter, Group $group)
732
    {
733 1
        $shapes = $group->getShapeCollection();
734 1
        foreach ($shapes as $shape) {
735
            // Increment $this->shapeId
736 1
            ++$this->shapeId;
737
738
            // Check type
739 1
            if ($shape instanceof RichText) {
740
                $this->writeTxtStyle($objWriter, $shape);
741
            }
742 1
            if ($shape instanceof AbstractDrawing) {
743 1
                $this->writeDrawingStyle($objWriter, $shape);
744 1
            }
745 1
            if ($shape instanceof Line) {
746
                $this->writeLineStyle($objWriter, $shape);
747
            }
748 1
            if ($shape instanceof Table) {
749
                $this->writeTableStyle($objWriter, $shape);
750
            }
751 1
        }
752 1
    }
753
754
    /**
755
     * Write the default style information for a RichText shape
756
     *
757
     * @param \PhpOffice\Common\XMLWriter $objWriter
758
     * @param \PhpOffice\PhpPresentation\Shape\RichText $shape
759
     */
760 14
    public function writeTxtStyle(XMLWriter $objWriter, RichText $shape)
761
    {
762
        // style:style
763 14
        $objWriter->startElement('style:style');
764 14
        $objWriter->writeAttribute('style:name', 'gr' . $this->shapeId);
765 14
        $objWriter->writeAttribute('style:family', 'graphic');
766 14
        $objWriter->writeAttribute('style:parent-style-name', 'standard');
767
        // style:graphic-properties
768 14
        $objWriter->startElement('style:graphic-properties');
769 14
        if ($shape->getShadow()->isVisible()) {
770 1
            $this->writeStylePartShadow($objWriter, $shape->getShadow());
771 1
        }
772 14
        if (is_bool($shape->hasAutoShrinkVertical())) {
773 1
            $objWriter->writeAttribute('draw:auto-grow-height', var_export($shape->hasAutoShrinkVertical(), true));
774 1
        }
775 14
        if (is_bool($shape->hasAutoShrinkHorizontal())) {
776 1
            $objWriter->writeAttribute('draw:auto-grow-width', var_export($shape->hasAutoShrinkHorizontal(), true));
777 1
        }
778
        // Fill
779 14
        switch ($shape->getFill()->getFillType()) {
780 14
            case Fill::FILL_GRADIENT_LINEAR:
781 14
            case Fill::FILL_GRADIENT_PATH:
782 1
                $objWriter->writeAttribute('draw:fill', 'gradient');
783 1
                $objWriter->writeAttribute('draw:fill-gradient-name', 'gradient_'.$shape->getFill()->getHashCode());
784 1
                break;
785 13
            case Fill::FILL_SOLID:
786 1
                $objWriter->writeAttribute('draw:fill', 'solid');
787 1
                $objWriter->writeAttribute('draw:fill-color', '#'.$shape->getFill()->getStartColor()->getRGB());
788 1
                break;
789 12
            case Fill::FILL_NONE:
790 12
            default:
791 12
                $objWriter->writeAttribute('draw:fill', 'none');
792 12
                $objWriter->writeAttribute('draw:fill-color', '#'.$shape->getFill()->getStartColor()->getRGB());
793 12
                break;
794 14
        }
795
        // Border
796 14
        if ($shape->getBorder()->getLineStyle() == Border::LINE_NONE) {
797 13
            $objWriter->writeAttribute('draw:stroke', 'none');
798 13
        } else {
799 2
            $objWriter->writeAttribute('svg:stroke-color', '#'.$shape->getBorder()->getColor()->getRGB());
800 2
            $objWriter->writeAttribute('svg:stroke-width', number_format(CommonDrawing::pointsToCentimeters($shape->getBorder()->getLineWidth()), 3, '.', '').'cm');
801 2
            switch ($shape->getBorder()->getDashStyle()) {
802 2
                case Border::DASH_SOLID:
803 1
                    $objWriter->writeAttribute('draw:stroke', 'solid');
804 1
                    break;
805 2
                case Border::DASH_DASH:
806 2
                case Border::DASH_DASHDOT:
807 2
                case Border::DASH_DOT:
808 2
                case Border::DASH_LARGEDASH:
809 2
                case Border::DASH_LARGEDASHDOT:
810 2
                case Border::DASH_LARGEDASHDOTDOT:
811 2
                case Border::DASH_SYSDASH:
812 2
                case Border::DASH_SYSDASHDOT:
813 2
                case Border::DASH_SYSDASHDOTDOT:
814 2
                case Border::DASH_SYSDOT:
815 2
                    $objWriter->writeAttribute('draw:stroke', 'dash');
816 2
                    $objWriter->writeAttribute('draw:stroke-dash', 'strokeDash_'.$shape->getBorder()->getDashStyle());
817 2
                    break;
818
                default:
819
                    $objWriter->writeAttribute('draw:stroke', 'none');
820
                    break;
821 2
            }
822
        }
823
824 14
        $objWriter->writeAttribute('fo:wrap-option', 'wrap');
825
        // > style:graphic-properties
826 14
        $objWriter->endElement();
827
        // > style:style
828 14
        $objWriter->endElement();
829
830 14
        $paragraphs  = $shape->getParagraphs();
831 14
        $paragraphId = 0;
832 14
        foreach ($paragraphs as $paragraph) {
833 14
            ++$paragraphId;
834
835
            // Style des paragraphes
836 14
            if (!isset($this->arrStyleParagraph[$paragraph->getHashCode()])) {
837 14
                $this->arrStyleParagraph[$paragraph->getHashCode()] = $paragraph;
838 14
            }
839
840
            // Style des listes
841 14
            if (!isset($this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()])) {
842 14
                $this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()]['oStyle'] = $paragraph->getBulletStyle();
843 14
                $this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()]['level']  = '';
844 14
            }
845 14
            if (strpos($this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()]['level'], ';' . $paragraph->getAlignment()->getLevel()) === false) {
846 14
                $this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()]['level'] .= ';' . $paragraph->getAlignment()->getLevel();
847 14
                $this->arrStyleBullet[$paragraph->getBulletStyle()->getHashCode()]['oAlign_' . $paragraph->getAlignment()->getLevel()] = $paragraph->getAlignment();
848 14
            }
849
850 14
            $richtexts  = $paragraph->getRichTextElements();
851 14
            $richtextId = 0;
852 14
            foreach ($richtexts as $richtext) {
853 8
                ++$richtextId;
854
                // Not a line break
855 8
                if ($richtext instanceof Run) {
856
                    // Style des font text
857 8
                    if (!isset($this->arrStyleTextFont[$richtext->getHashCode()])) {
858 8
                        $this->arrStyleTextFont[$richtext->getHashCode()] = $richtext;
859 8
                    }
860 8
                }
861 14
            }
862 14
        }
863 14
    }
864
865
    /**
866
     * Write the default style information for an AbstractDrawing
867
     *
868
     * @param \PhpOffice\Common\XMLWriter $objWriter
869
     * @param \PhpOffice\PhpPresentation\Shape\AbstractDrawing $shape
870
     */
871 35
    public function writeDrawingStyle(XMLWriter $objWriter, AbstractDrawing $shape)
872
    {
873
        // style:style
874 35
        $objWriter->startElement('style:style');
875 35
        $objWriter->writeAttribute('style:name', 'gr' . $this->shapeId);
876 35
        $objWriter->writeAttribute('style:family', 'graphic');
877 35
        $objWriter->writeAttribute('style:parent-style-name', 'standard');
878
879
        // style:graphic-properties
880 35
        $objWriter->startElement('style:graphic-properties');
881 35
        $objWriter->writeAttribute('draw:stroke', 'none');
882 35
        $objWriter->writeAttribute('draw:fill', 'none');
883 35
        if ($shape->getShadow()->isVisible()) {
884
            $this->writeStylePartShadow($objWriter, $shape->getShadow());
885
        }
886 35
        $objWriter->endElement();
887
888 35
        $objWriter->endElement();
889 35
    }
890
891
    /**
892
     * Write the default style information for a Line shape.
893
     *
894
     * @param XMLWriter $objWriter
895
     * @param Line $shape
896
     */
897 1
    public function writeLineStyle(XMLWriter $objWriter, Line $shape)
898
    {
899
        // style:style
900 1
        $objWriter->startElement('style:style');
901 1
        $objWriter->writeAttribute('style:name', 'gr' . $this->shapeId);
902 1
        $objWriter->writeAttribute('style:family', 'graphic');
903 1
        $objWriter->writeAttribute('style:parent-style-name', 'standard');
904
905
        // style:graphic-properties
906 1
        $objWriter->startElement('style:graphic-properties');
907 1
        $objWriter->writeAttribute('draw:fill', 'none');
908 1
        switch ($shape->getBorder()->getLineStyle()) {
909 1
            case Border::LINE_NONE:
910
                $objWriter->writeAttribute('draw:stroke', 'none');
911
                break;
912 1
            case Border::LINE_SINGLE:
913 1
                $objWriter->writeAttribute('draw:stroke', 'solid');
914 1
                break;
915
            default:
916
                $objWriter->writeAttribute('draw:stroke', 'none');
917
                break;
918 1
        }
919 1
        $objWriter->writeAttribute('svg:stroke-color', '#'.$shape->getBorder()->getColor()->getRGB());
920 1
        $objWriter->writeAttribute('svg:stroke-width', Text::numberFormat(CommonDrawing::pixelsToCentimeters((CommonDrawing::pointsToPixels($shape->getBorder()->getLineWidth()))), 3).'cm');
921 1
        $objWriter->endElement();
922
923 1
        $objWriter->endElement();
924 1
    }
925
926
    /**
927
     * Write the default style information for a Table shape
928
     *
929
     * @param XMLWriter $objWriter
930
     * @param Table $shape
931
     */
932 7
    public function writeTableStyle(XMLWriter $objWriter, Table $shape)
933
    {
934 7
        foreach ($shape->getRows() as $keyRow => $shapeRow) {
935
            // style:style
936 6
            $objWriter->startElement('style:style');
937 6
            $objWriter->writeAttribute('style:name', 'gr' . $this->shapeId.'r'.$keyRow);
938 6
            $objWriter->writeAttribute('style:family', 'table-row');
939
940
            // style:table-row-properties
941 6
            $objWriter->startElement('style:table-row-properties');
942 6
            $objWriter->writeAttribute('style:row-height', Text::numberFormat(CommonDrawing::pixelsToCentimeters(CommonDrawing::pointsToPixels($shapeRow->getHeight())), 3).'cm');
943 6
            $objWriter->endElement();
944
945 6
            $objWriter->endElement();
946
947 6
            foreach ($shapeRow->getCells() as $keyCell => $shapeCell) {
948
                // style:style
949 6
                $objWriter->startElement('style:style');
950 6
                $objWriter->writeAttribute('style:name', 'gr' . $this->shapeId.'r'.$keyRow.'c'.$keyCell);
951 6
                $objWriter->writeAttribute('style:family', 'table-cell');
952
953
                // style:graphic-properties
954 6
                $objWriter->startElement('style:graphic-properties');
955 6
                if ($shapeCell->getFill()->getFillType() == Fill::FILL_SOLID) {
956 1
                    $objWriter->writeAttribute('draw:fill', 'solid');
957 1
                    $objWriter->writeAttribute('draw:fill-color', '#'.$shapeCell->getFill()->getStartColor()->getRGB());
958 1
                }
959 6
                if ($shapeCell->getFill()->getFillType() == Fill::FILL_GRADIENT_LINEAR) {
960 1
                    $objWriter->writeAttribute('draw:fill', 'gradient');
961 1
                    $objWriter->writeAttribute('draw:fill-gradient-name', 'gradient_'.$shapeCell->getFill()->getHashCode());
962 1
                }
963 6
                $objWriter->endElement();
964
                // <style:graphic-properties
965
966
                // style:paragraph-properties
967 6
                $objWriter->startElement('style:paragraph-properties');
968 6
                if ($shapeCell->getBorders()->getBottom()->getHashCode() == $shapeCell->getBorders()->getTop()->getHashCode()
969 6
                    && $shapeCell->getBorders()->getBottom()->getHashCode() == $shapeCell->getBorders()->getLeft()->getHashCode()
970 6
                    && $shapeCell->getBorders()->getBottom()->getHashCode() == $shapeCell->getBorders()->getRight()->getHashCode()) {
971 6
                    $lineStyle = 'none';
972 6
                    $lineWidth = Text::numberFormat($shapeCell->getBorders()->getBottom()->getLineWidth() / 1.75, 2);
973 6
                    $lineColor = $shapeCell->getBorders()->getBottom()->getColor()->getRGB();
974 6
                    switch ($shapeCell->getBorders()->getBottom()->getLineStyle()) {
975 6
                        case Border::LINE_SINGLE:
976 6
                            $lineStyle = 'solid';
977 6
                    }
978 6
                    $objWriter->writeAttribute('fo:border', $lineWidth.'pt '.$lineStyle.' #'.$lineColor);
979 6
                } else {
980
                    $lineStyle = 'none';
981
                    $lineWidth = Text::numberFormat($shapeCell->getBorders()->getBottom()->getLineWidth() / 1.75, 2);
982
                    $lineColor = $shapeCell->getBorders()->getBottom()->getColor()->getRGB();
983
                    switch ($shapeCell->getBorders()->getBottom()->getLineStyle()) {
984
                        case Border::LINE_SINGLE:
985
                            $lineStyle = 'solid';
986
                    }
987
                    $objWriter->writeAttribute('fo:border-bottom', $lineWidth.'pt '.$lineStyle.' #'.$lineColor);
988
                    // TOP
989
                    $lineStyle = 'none';
990
                    $lineWidth = Text::numberFormat($shapeCell->getBorders()->getTop()->getLineWidth() / 1.75, 2);
991
                    $lineColor = $shapeCell->getBorders()->getTop()->getColor()->getRGB();
992
                    switch ($shapeCell->getBorders()->getTop()->getLineStyle()) {
993
                        case Border::LINE_SINGLE:
994
                            $lineStyle = 'solid';
995
                    }
996
                    $objWriter->writeAttribute('fo:border-top', $lineWidth.'pt '.$lineStyle.' #'.$lineColor);
997
                    // RIGHT
998
                    $lineStyle = 'none';
999
                    $lineWidth = Text::numberFormat($shapeCell->getBorders()->getRight()->getLineWidth() / 1.75, 2);
1000
                    $lineColor = $shapeCell->getBorders()->getRight()->getColor()->getRGB();
1001
                    switch ($shapeCell->getBorders()->getRight()->getLineStyle()) {
1002
                        case Border::LINE_SINGLE:
1003
                            $lineStyle = 'solid';
1004
                    }
1005
                    $objWriter->writeAttribute('fo:border-right', $lineWidth.'pt '.$lineStyle.' #'.$lineColor);
1006
                    // LEFT
1007
                    $lineStyle = 'none';
1008
                    $lineWidth = Text::numberFormat($shapeCell->getBorders()->getLeft()->getLineWidth() / 1.75, 2);
1009
                    $lineColor = $shapeCell->getBorders()->getLeft()->getColor()->getRGB();
1010
                    switch ($shapeCell->getBorders()->getLeft()->getLineStyle()) {
1011
                        case Border::LINE_SINGLE:
1012
                            $lineStyle = 'solid';
1013
                    }
1014
                    $objWriter->writeAttribute('fo:border-left', $lineWidth.'pt '.$lineStyle.' #'.$lineColor);
1015
                }
1016 6
                $objWriter->endElement();
1017
1018 6
                $objWriter->endElement();
1019
1020 6
                foreach ($shapeCell->getParagraphs() as $shapeParagraph) {
1021 6
                    foreach ($shapeParagraph->getRichTextElements() as $shapeRichText) {
1022 2
                        if ($shapeRichText instanceof Run) {
1023
                            // Style des font text
1024 2
                            if (!isset($this->arrStyleTextFont[$shapeRichText->getHashCode()])) {
1025 2
                                $this->arrStyleTextFont[$shapeRichText->getHashCode()] = $shapeRichText;
1026 2
                            }
1027 2
                        }
1028 6
                    }
1029 6
                }
1030 6
            }
1031 7
        }
1032 7
    }
1033
1034
    /**
1035
     * Write the slide note
1036
     * @param XMLWriter $objWriter
1037
     * @param \PhpOffice\PhpPresentation\Slide\Note $note
1038
     */
1039 57
    public function writeSlideNote(XMLWriter $objWriter, Note $note)
1040
    {
1041 57
        $shapesNote = $note->getShapeCollection();
1042 57
        if (count($shapesNote) > 0) {
1043 1
            $objWriter->startElement('presentation:notes');
1044
1045 1
            foreach ($shapesNote as $shape) {
1046
                // Increment $this->shapeId
1047 1
                ++$this->shapeId;
1048
1049 1
                if ($shape instanceof RichText) {
1050 1
                    $this->writeShapeTxt($objWriter, $shape);
1051 1
                }
1052 1
            }
1053
1054 1
            $objWriter->endElement();
1055 1
        }
1056 57
    }
1057
1058
    /**
1059
     * Write style of a slide
1060
     * @param XMLWriter $objWriter
1061
     * @param Slide $slide
1062
     * @param int $incPage
1063
     */
1064 57
    public function writeStyleSlide(XMLWriter $objWriter, Slide $slide, $incPage)
1065
    {
1066
        // style:style
1067 57
        $objWriter->startElement('style:style');
1068 57
        $objWriter->writeAttribute('style:family', 'drawing-page');
1069 57
        $objWriter->writeAttribute('style:name', 'stylePage'.$incPage);
1070
        // style:style/style:drawing-page-properties
1071 57
        $objWriter->startElement('style:drawing-page-properties');
1072 57
        if (!is_null($oTransition = $slide->getTransition())) {
1073 1
            $objWriter->writeAttribute('presentation:duration', 'PT'.number_format($oTransition->getAdvanceTimeTrigger() / 1000, 6, '.', '').'S');
1074 1
            if ($oTransition->hasManualTrigger()) {
1075 1
                $objWriter->writeAttribute('presentation:transition-type', 'manual');
1076 1
            } elseif ($oTransition->hasTimeTrigger()) {
1077 1
                $objWriter->writeAttribute('presentation:transition-type', 'automatic');
1078 1
            }
1079 1
            switch ($oTransition->getSpeed()) {
1080 1
                case Transition::SPEED_FAST:
1081 1
                    $objWriter->writeAttribute('presentation:transition-speed', 'fast');
1082 1
                    break;
1083 1
                case Transition::SPEED_MEDIUM:
1084 1
                    $objWriter->writeAttribute('presentation:transition-speed', 'medium');
1085 1
                    break;
1086 1
                case Transition::SPEED_SLOW:
1087 1
                    $objWriter->writeAttribute('presentation:transition-speed', 'slow');
1088 1
                    break;
1089 1
            }
1090
1091
            /**
1092
             * http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#property-presentation_transition-style
1093
             */
1094 1
            switch ($oTransition->getTransitionType()) {
1095 1
                case Transition::TRANSITION_BLINDS_HORIZONTAL:
1096 1
                    $objWriter->writeAttribute('presentation:transition-style', 'horizontal-stripes');
1097 1
                    break;
1098 1
                case Transition::TRANSITION_BLINDS_VERTICAL:
1099 1
                    $objWriter->writeAttribute('presentation:transition-style', 'vertical-stripes');
1100 1
                    break;
1101 1
                case Transition::TRANSITION_CHECKER_HORIZONTAL:
1102 1
                    $objWriter->writeAttribute('presentation:transition-style', 'horizontal-checkerboard');
1103 1
                    break;
1104 1
                case Transition::TRANSITION_CHECKER_VERTICAL:
1105 1
                    $objWriter->writeAttribute('presentation:transition-style', 'vertical-checkerboard');
1106 1
                    break;
1107 1
                case Transition::TRANSITION_CIRCLE_HORIZONTAL:
1108 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1109 1
                    break;
1110 1
                case Transition::TRANSITION_CIRCLE_VERTICAL:
1111 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1112 1
                    break;
1113 1
                case Transition::TRANSITION_COMB_HORIZONTAL:
1114 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1115 1
                    break;
1116 1
                case Transition::TRANSITION_COMB_VERTICAL:
1117 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1118 1
                    break;
1119 1
                case Transition::TRANSITION_COVER_DOWN:
1120 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-bottom');
1121 1
                    break;
1122 1
                case Transition::TRANSITION_COVER_LEFT:
1123 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-left');
1124 1
                    break;
1125 1
                case Transition::TRANSITION_COVER_LEFT_DOWN:
1126 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-lowerleft');
1127 1
                    break;
1128 1
                case Transition::TRANSITION_COVER_LEFT_UP:
1129 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-upperleft');
1130 1
                    break;
1131 1
                case Transition::TRANSITION_COVER_RIGHT:
1132 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-right');
1133 1
                    break;
1134 1
                case Transition::TRANSITION_COVER_RIGHT_DOWN:
1135 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-lowerright');
1136 1
                    break;
1137 1
                case Transition::TRANSITION_COVER_RIGHT_UP:
1138 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-upperright');
1139 1
                    break;
1140 1
                case Transition::TRANSITION_COVER_UP:
1141 1
                    $objWriter->writeAttribute('presentation:transition-style', 'uncover-to-top');
1142 1
                    break;
1143 1
                case Transition::TRANSITION_CUT:
1144 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1145 1
                    break;
1146 1
                case Transition::TRANSITION_DIAMOND:
1147 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1148 1
                    break;
1149 1
                case Transition::TRANSITION_DISSOLVE:
1150 1
                    $objWriter->writeAttribute('presentation:transition-style', 'dissolve');
1151 1
                    break;
1152 1
                case Transition::TRANSITION_FADE:
1153 1
                    $objWriter->writeAttribute('presentation:transition-style', 'fade-from-center');
1154 1
                    break;
1155 1
                case Transition::TRANSITION_NEWSFLASH:
1156 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1157 1
                    break;
1158 1
                case Transition::TRANSITION_PLUS:
1159 1
                    $objWriter->writeAttribute('presentation:transition-style', 'close');
1160 1
                    break;
1161 1
                case Transition::TRANSITION_PULL_DOWN:
1162 1
                    $objWriter->writeAttribute('presentation:transition-style', 'stretch-from-bottom');
1163 1
                    break;
1164 1
                case Transition::TRANSITION_PULL_LEFT:
1165 1
                    $objWriter->writeAttribute('presentation:transition-style', 'stretch-from-left');
1166 1
                    break;
1167 1
                case Transition::TRANSITION_PULL_RIGHT:
1168 1
                    $objWriter->writeAttribute('presentation:transition-style', 'stretch-from-right');
1169 1
                    break;
1170 1
                case Transition::TRANSITION_PULL_UP:
1171 1
                    $objWriter->writeAttribute('presentation:transition-style', 'stretch-from-top');
1172 1
                    break;
1173 1
                case Transition::TRANSITION_PUSH_DOWN:
1174 1
                    $objWriter->writeAttribute('presentation:transition-style', 'roll-from-bottom');
1175 1
                    break;
1176 1
                case Transition::TRANSITION_PUSH_LEFT:
1177 1
                    $objWriter->writeAttribute('presentation:transition-style', 'roll-from-left');
1178 1
                    break;
1179 1
                case Transition::TRANSITION_PUSH_RIGHT:
1180 1
                    $objWriter->writeAttribute('presentation:transition-style', 'roll-from-right');
1181 1
                    break;
1182 1
                case Transition::TRANSITION_PUSH_UP:
1183 1
                    $objWriter->writeAttribute('presentation:transition-style', 'roll-from-top');
1184 1
                    break;
1185 1
                case Transition::TRANSITION_RANDOM:
1186 1
                    $objWriter->writeAttribute('presentation:transition-style', 'random');
1187 1
                    break;
1188 1
                case Transition::TRANSITION_RANDOMBAR_HORIZONTAL:
1189 1
                    $objWriter->writeAttribute('presentation:transition-style', 'horizontal-lines');
1190 1
                    break;
1191 1
                case Transition::TRANSITION_RANDOMBAR_VERTICAL:
1192 1
                    $objWriter->writeAttribute('presentation:transition-style', 'vertical-lines');
1193 1
                    break;
1194 1
                case Transition::TRANSITION_SPLIT_IN_HORIZONTAL:
1195 1
                    $objWriter->writeAttribute('presentation:transition-style', 'close-horizontal');
1196 1
                    break;
1197 1
                case Transition::TRANSITION_SPLIT_OUT_HORIZONTAL:
1198 1
                    $objWriter->writeAttribute('presentation:transition-style', 'open-horizontal');
1199 1
                    break;
1200 1
                case Transition::TRANSITION_SPLIT_IN_VERTICAL:
1201 1
                    $objWriter->writeAttribute('presentation:transition-style', 'close-vertical');
1202 1
                    break;
1203 1
                case Transition::TRANSITION_SPLIT_OUT_VERTICAL:
1204 1
                    $objWriter->writeAttribute('presentation:transition-style', 'open-vertical');
1205 1
                    break;
1206 1
                case Transition::TRANSITION_STRIPS_LEFT_DOWN:
1207 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1208 1
                    break;
1209 1
                case Transition::TRANSITION_STRIPS_LEFT_UP:
1210 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1211 1
                    break;
1212 1
                case Transition::TRANSITION_STRIPS_RIGHT_DOWN:
1213 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1214 1
                    break;
1215 1
                case Transition::TRANSITION_STRIPS_RIGHT_UP:
1216 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1217 1
                    break;
1218 1
                case Transition::TRANSITION_WEDGE:
1219 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1220 1
                    break;
1221 1
                case Transition::TRANSITION_WIPE_DOWN:
1222 1
                    $objWriter->writeAttribute('presentation:transition-style', 'fade-from-bottom');
1223 1
                    break;
1224 1
                case Transition::TRANSITION_WIPE_LEFT:
1225 1
                    $objWriter->writeAttribute('presentation:transition-style', 'fade-from-left');
1226 1
                    break;
1227 1
                case Transition::TRANSITION_WIPE_RIGHT:
1228 1
                    $objWriter->writeAttribute('presentation:transition-style', 'fade-from-right');
1229 1
                    break;
1230 1
                case Transition::TRANSITION_WIPE_UP:
1231 1
                    $objWriter->writeAttribute('presentation:transition-style', 'fade-from-top');
1232 1
                    break;
1233 1
                case Transition::TRANSITION_ZOOM_IN:
1234 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1235 1
                    break;
1236 1
                case Transition::TRANSITION_ZOOM_OUT:
1237 1
                    $objWriter->writeAttribute('presentation:transition-style', 'none');
1238 1
                    break;
1239 1
            }
1240 1
        }
1241 57
        $oBackground = $slide->getBackground();
1242 57
        if ($oBackground instanceof Slide\AbstractBackground) {
1243 1
            $objWriter->writeAttribute('presentation:background-visible', 'true');
1244 1
            if ($oBackground instanceof Slide\Background\Color) {
1245
                $objWriter->writeAttribute('draw:fill', 'solid');
1246
                $objWriter->writeAttribute('draw:fill-color', '#' . $oBackground->getColor()->getRGB());
1247
            }
1248 1
            if ($oBackground instanceof Slide\Background\Image) {
1249 1
                $objWriter->writeAttribute('draw:fill', 'bitmap');
1250 1
                $objWriter->writeAttribute('draw:fill-image-name', 'background_'.$incPage);
1251 1
                $objWriter->writeAttribute('style:repeat', 'stretch');
1252 1
            }
1253 1
        }
1254 57
        $objWriter->endElement();
1255
        // > style:style
1256 57
        $objWriter->endElement();
1257 57
    }
1258
1259
1260
    /**
1261
     * @param XMLWriter $objWriter
1262
     * @param Shadow $oShadow
1263
     * @todo Improve for supporting any direction (https://sinepost.wordpress.com/2012/02/16/theyve-got-atan-you-want-atan2/)
1264
     */
1265 1
    protected function writeStylePartShadow(XMLWriter $objWriter, Shadow $oShadow)
1266
    {
1267 1
        $objWriter->writeAttribute('draw:shadow', 'visible');
1268 1
        $objWriter->writeAttribute('draw:shadow-color', '#' . $oShadow->getColor()->getRGB());
1269 1
        if ($oShadow->getDirection() == 0 || $oShadow->getDirection() == 360) {
1270 1
            $objWriter->writeAttribute('draw:shadow-offset-x', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1271 1
            $objWriter->writeAttribute('draw:shadow-offset-y', '0cm');
1272 1
        } elseif ($oShadow->getDirection() == 45) {
1273 1
            $objWriter->writeAttribute('draw:shadow-offset-x', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1274 1
            $objWriter->writeAttribute('draw:shadow-offset-y', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1275 1
        } elseif ($oShadow->getDirection() == 90) {
1276 1
            $objWriter->writeAttribute('draw:shadow-offset-x', '0cm');
1277 1
            $objWriter->writeAttribute('draw:shadow-offset-y', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1278 1
        } elseif ($oShadow->getDirection() == 135) {
1279 1
            $objWriter->writeAttribute('draw:shadow-offset-x', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1280 1
            $objWriter->writeAttribute('draw:shadow-offset-y', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1281 1
        } elseif ($oShadow->getDirection() == 180) {
1282 1
            $objWriter->writeAttribute('draw:shadow-offset-x', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1283 1
            $objWriter->writeAttribute('draw:shadow-offset-y', '0cm');
1284 1
        } elseif ($oShadow->getDirection() == 225) {
1285 1
            $objWriter->writeAttribute('draw:shadow-offset-x', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1286 1
            $objWriter->writeAttribute('draw:shadow-offset-y', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1287 1
        } elseif ($oShadow->getDirection() == 270) {
1288 1
            $objWriter->writeAttribute('draw:shadow-offset-x', '0cm');
1289 1
            $objWriter->writeAttribute('draw:shadow-offset-y', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1290 1
        } elseif ($oShadow->getDirection() == 315) {
1291 1
            $objWriter->writeAttribute('draw:shadow-offset-x', CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1292 1
            $objWriter->writeAttribute('draw:shadow-offset-y', '-' . CommonDrawing::pixelsToCentimeters($oShadow->getDistance()) . 'cm');
1293 1
        }
1294 1
        $objWriter->writeAttribute('draw:shadow-opacity', (100 - $oShadow->getAlpha()) . '%');
1295 1
        $objWriter->writeAttribute('style:mirror', 'none');
1296
1297 1
    }
1298
}
1299