Completed
Pull Request — develop (#390)
by Franck
07:28
created

Content::writeShapeLine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

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