Completed
Pull Request — develop (#178)
by
unknown
09:34
created

Content   F

Complexity

Total Complexity 219

Size/Duplication

Total Lines 1237
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 34

Test Coverage

Coverage 91.27%

Importance

Changes 6
Bugs 0 Features 2
Metric Value
wmc 219
c 6
b 0
f 2
lcom 1
cbo 34
dl 0
loc 1237
ccs 805
cts 882
cp 0.9127
rs 0.5217

15 Methods

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

How to fix   Complexity   

Complex Class

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

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

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

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