Completed
Pull Request — develop (#209)
by Franck
07:06
created

Content::writeLineStyle()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3

Importance

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