Completed
Pull Request — master (#413)
by
unknown
07:08
created

Content::writeStylePartFill()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

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