Content::writeShapeTxt()   F
last analyzed

Complexity

Conditions 30
Paths 42

Size

Total Lines 153

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 88
CRAP Score 30.0323

Importance

Changes 0
Metric Value
dl 0
loc 153
ccs 88
cts 91
cp 0.967
rs 3.3333
c 0
b 0
f 0
cc 30
nc 42
nop 2
crap 30.0323

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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