Passed
Pull Request — master (#4142)
by Owen
16:30 queued 03:39
created

Drawing::writeVMLHeaderFooterImage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 3
dl 0
loc 32
ccs 21
cts 21
cp 1
crap 1
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
7
use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
8
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
9
use PhpOffice\PhpSpreadsheet\Spreadsheet;
10
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
11
use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
12
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
13
14
class Drawing extends WriterPart
15
{
16
    /**
17
     * Write drawings to XML format.
18
     *
19
     * @param bool $includeCharts Flag indicating if we should include drawing details for charts
20
     *
21
     * @return string XML Output
22
     */
23 114
    public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, bool $includeCharts = false): string
24
    {
25
        // Create XML writer
26 114
        $objWriter = null;
27 114
        if ($this->getParentWriter()->getUseDiskCaching()) {
28
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
29
        } else {
30 114
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
31
        }
32
33
        // XML header
34 114
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
35
36
        // xdr:wsDr
37 114
        $objWriter->startElement('xdr:wsDr');
38 114
        $objWriter->writeAttribute('xmlns:xdr', Namespaces::SPREADSHEET_DRAWING);
39 114
        $objWriter->writeAttribute('xmlns:a', Namespaces::DRAWINGML);
40
41
        // Loop through images and write drawings
42 114
        $i = 1;
43 114
        $iterator = $worksheet->getDrawingCollection()->getIterator();
44 114
        while ($iterator->valid()) {
45
            /** @var BaseDrawing $pDrawing */
46 50
            $pDrawing = $iterator->current();
47 50
            $pRelationId = $i;
48 50
            $hlinkClickId = $pDrawing->getHyperlink() === null ? null : ++$i;
49
50 50
            $this->writeDrawing($objWriter, $pDrawing, $pRelationId, $hlinkClickId);
51
52 50
            $iterator->next();
53 50
            ++$i;
54
        }
55
56 114
        if ($includeCharts) {
57 73
            $chartCount = $worksheet->getChartCount();
58
            // Loop through charts and write the chart position
59 73
            if ($chartCount > 0) {
60 73
                for ($c = 0; $c < $chartCount; ++$c) {
61 73
                    $chart = $worksheet->getChartByIndex((string) $c);
62 73
                    if ($chart !== false) {
63 73
                        $this->writeChart($objWriter, $chart, $c + $i);
64
                    }
65
                }
66
            }
67
        }
68
69
        // unparsed AlternateContent
70 114
        $unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
71 114
        if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'])) {
72 4
            foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
73 4
                $objWriter->writeRaw($drawingAlternateContent);
74
            }
75
        }
76
77 114
        $objWriter->endElement();
78
79
        // Return
80 114
        return $objWriter->getData();
81
    }
82
83
    /**
84
     * Write drawings to XML format.
85
     */
86 73
    public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $chart, int $relationId = -1): void
87
    {
88 73
        $tl = $chart->getTopLeftPosition();
89 73
        $tlColRow = Coordinate::indexesFromString($tl['cell']);
90 73
        $br = $chart->getBottomRightPosition();
91
92 73
        $isTwoCellAnchor = $br['cell'] !== '';
93 73
        if ($isTwoCellAnchor) {
94 71
            $brColRow = Coordinate::indexesFromString($br['cell']);
95
96 71
            $objWriter->startElement('xdr:twoCellAnchor');
97
98 71
            $objWriter->startElement('xdr:from');
99 71
            $objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
100 71
            $objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
101 71
            $objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
102 71
            $objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
103 71
            $objWriter->endElement();
104 71
            $objWriter->startElement('xdr:to');
105 71
            $objWriter->writeElement('xdr:col', (string) ($brColRow[0] - 1));
106 71
            $objWriter->writeElement('xdr:colOff', self::stringEmu($br['xOffset']));
107 71
            $objWriter->writeElement('xdr:row', (string) ($brColRow[1] - 1));
108 71
            $objWriter->writeElement('xdr:rowOff', self::stringEmu($br['yOffset']));
109 71
            $objWriter->endElement();
110 3
        } elseif ($chart->getOneCellAnchor()) {
111 1
            $objWriter->startElement('xdr:oneCellAnchor');
112
113 1
            $objWriter->startElement('xdr:from');
114 1
            $objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
115 1
            $objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
116 1
            $objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
117 1
            $objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
118 1
            $objWriter->endElement();
119 1
            $objWriter->startElement('xdr:ext');
120 1
            $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
121 1
            $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
122 1
            $objWriter->endElement();
123
        } else {
124 2
            $objWriter->startElement('xdr:absoluteAnchor');
125 2
            $objWriter->startElement('xdr:pos');
126 2
            $objWriter->writeAttribute('x', '0');
127 2
            $objWriter->writeAttribute('y', '0');
128 2
            $objWriter->endElement();
129 2
            $objWriter->startElement('xdr:ext');
130 2
            $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
131 2
            $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
132 2
            $objWriter->endElement();
133
        }
134
135 73
        $objWriter->startElement('xdr:graphicFrame');
136 73
        $objWriter->writeAttribute('macro', '');
137 73
        $objWriter->startElement('xdr:nvGraphicFramePr');
138 73
        $objWriter->startElement('xdr:cNvPr');
139 73
        $objWriter->writeAttribute('name', 'Chart ' . $relationId);
140 73
        $objWriter->writeAttribute('id', (string) (1025 * $relationId));
141 73
        $objWriter->endElement();
142 73
        $objWriter->startElement('xdr:cNvGraphicFramePr');
143 73
        $objWriter->startElement('a:graphicFrameLocks');
144 73
        $objWriter->endElement();
145 73
        $objWriter->endElement();
146 73
        $objWriter->endElement();
147
148 73
        $objWriter->startElement('xdr:xfrm');
149 73
        $objWriter->startElement('a:off');
150 73
        $objWriter->writeAttribute('x', '0');
151 73
        $objWriter->writeAttribute('y', '0');
152 73
        $objWriter->endElement();
153 73
        $objWriter->startElement('a:ext');
154 73
        $objWriter->writeAttribute('cx', '0');
155 73
        $objWriter->writeAttribute('cy', '0');
156 73
        $objWriter->endElement();
157 73
        $objWriter->endElement();
158
159 73
        $objWriter->startElement('a:graphic');
160 73
        $objWriter->startElement('a:graphicData');
161 73
        $objWriter->writeAttribute('uri', Namespaces::CHART);
162 73
        $objWriter->startElement('c:chart');
163 73
        $objWriter->writeAttribute('xmlns:c', Namespaces::CHART);
164 73
        $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
165 73
        $objWriter->writeAttribute('r:id', 'rId' . $relationId);
166 73
        $objWriter->endElement();
167 73
        $objWriter->endElement();
168 73
        $objWriter->endElement();
169 73
        $objWriter->endElement();
170
171 73
        $objWriter->startElement('xdr:clientData');
172 73
        $objWriter->endElement();
173
174 73
        $objWriter->endElement();
175
    }
176
177
    /**
178
     * Write drawings to XML format.
179
     */
180 50
    public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, int $relationId = -1, ?int $hlinkClickId = null): void
181
    {
182 50
        if ($relationId >= 0) {
183 50
            $isTwoCellAnchor = $drawing->getCoordinates2() !== '';
184 50
            if ($isTwoCellAnchor) {
185
                // xdr:twoCellAnchor
186 30
                $objWriter->startElement('xdr:twoCellAnchor');
187 30
                if ($drawing->validEditAs()) {
188 25
                    $objWriter->writeAttribute('editAs', $drawing->getEditAs());
189
                }
190
                // Image location
191 30
                $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
192 30
                $aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2());
193
194
                // xdr:from
195 30
                $objWriter->startElement('xdr:from');
196 30
                $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
197 30
                $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
198 30
                $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
199 30
                $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
200 30
                $objWriter->endElement();
201
202
                // xdr:to
203 30
                $objWriter->startElement('xdr:to');
204 30
                $objWriter->writeElement('xdr:col', (string) ($aCoordinates2[0] - 1));
205 30
                $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX2()));
206 30
                $objWriter->writeElement('xdr:row', (string) ($aCoordinates2[1] - 1));
207 30
                $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY2()));
208 30
                $objWriter->endElement();
209
            } else {
210
                // xdr:oneCellAnchor
211 22
                $objWriter->startElement('xdr:oneCellAnchor');
212
                // Image location
213 22
                $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
214
215
                // xdr:from
216 22
                $objWriter->startElement('xdr:from');
217 22
                $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
218 22
                $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
219 22
                $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
220 22
                $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
221 22
                $objWriter->endElement();
222
223
                // xdr:ext
224 22
                $objWriter->startElement('xdr:ext');
225 22
                $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
226 22
                $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
227 22
                $objWriter->endElement();
228
            }
229
230
            // xdr:pic
231 50
            $objWriter->startElement('xdr:pic');
232
233
            // xdr:nvPicPr
234 50
            $objWriter->startElement('xdr:nvPicPr');
235
236
            // xdr:cNvPr
237 50
            $objWriter->startElement('xdr:cNvPr');
238 50
            $objWriter->writeAttribute('id', (string) $relationId);
239 50
            $objWriter->writeAttribute('name', $drawing->getName());
240 50
            $objWriter->writeAttribute('descr', $drawing->getDescription());
241
242
            //a:hlinkClick
243 50
            $this->writeHyperLinkDrawing($objWriter, $hlinkClickId);
244
245 50
            $objWriter->endElement();
246
247
            // xdr:cNvPicPr
248 50
            $objWriter->startElement('xdr:cNvPicPr');
249
250
            // a:picLocks
251 50
            $objWriter->startElement('a:picLocks');
252 50
            $objWriter->writeAttribute('noChangeAspect', '1');
253 50
            $objWriter->endElement();
254
255 50
            $objWriter->endElement();
256
257 50
            $objWriter->endElement();
258
259
            // xdr:blipFill
260 50
            $objWriter->startElement('xdr:blipFill');
261
262
            // a:blip
263 50
            $objWriter->startElement('a:blip');
264 50
            $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
265 50
            $objWriter->writeAttribute('r:embed', 'rId' . $relationId);
266 50
            $temp = $drawing->getOpacity();
267 50
            if (is_int($temp) && $temp >= 0 && $temp <= 100000) {
268 4
                $objWriter->startElement('a:alphaModFix');
269 4
                $objWriter->writeAttribute('amt', "$temp");
270 4
                $objWriter->endElement(); // a:alphaModFix
271
            }
272 50
            $objWriter->endElement(); // a:blip
273
274 50
            $srcRect = $drawing->getSrcRect();
275 50
            if (!empty($srcRect)) {
276 2
                $objWriter->startElement('a:srcRect');
277 2
                foreach ($srcRect as $key => $value) {
278 2
                    $objWriter->writeAttribute($key, (string) $value);
279
                }
280 2
                $objWriter->endElement(); // a:srcRect
281 2
                $objWriter->startElement('a:stretch');
282 2
                $objWriter->endElement(); // a:stretch
283
            } else {
284
                // a:stretch
285 48
                $objWriter->startElement('a:stretch');
286 48
                $objWriter->writeElement('a:fillRect', null);
287 48
                $objWriter->endElement();
288
            }
289
290 50
            $objWriter->endElement();
291
292
            // xdr:spPr
293 50
            $objWriter->startElement('xdr:spPr');
294
295
            // a:xfrm
296 50
            $objWriter->startElement('a:xfrm');
297 50
            $objWriter->writeAttribute('rot', (string) SharedDrawing::degreesToAngle($drawing->getRotation()));
298 50
            self::writeAttributeIf($objWriter, $drawing->getFlipVertical(), 'flipV', '1');
299 50
            self::writeAttributeIf($objWriter, $drawing->getFlipHorizontal(), 'flipH', '1');
300 50
            if ($isTwoCellAnchor) {
301 30
                $objWriter->startElement('a:ext');
302 30
                $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
303 30
                $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
304 30
                $objWriter->endElement();
305
            }
306 50
            $objWriter->endElement();
307
308
            // a:prstGeom
309 50
            $objWriter->startElement('a:prstGeom');
310 50
            $objWriter->writeAttribute('prst', 'rect');
311
312
            // a:avLst
313 50
            $objWriter->writeElement('a:avLst', null);
314
315 50
            $objWriter->endElement();
316
317 50
            if ($drawing->getShadow()->getVisible()) {
318
                // a:effectLst
319 6
                $objWriter->startElement('a:effectLst');
320
321
                // a:outerShdw
322 6
                $objWriter->startElement('a:outerShdw');
323 6
                $objWriter->writeAttribute('blurRad', self::stringEmu($drawing->getShadow()->getBlurRadius()));
324 6
                $objWriter->writeAttribute('dist', self::stringEmu($drawing->getShadow()->getDistance()));
325 6
                $objWriter->writeAttribute('dir', (string) SharedDrawing::degreesToAngle($drawing->getShadow()->getDirection()));
326 6
                $objWriter->writeAttribute('algn', $drawing->getShadow()->getAlignment());
327 6
                $objWriter->writeAttribute('rotWithShape', '0');
328
329
                // a:srgbClr
330 6
                $objWriter->startElement('a:srgbClr');
331 6
                $objWriter->writeAttribute('val', $drawing->getShadow()->getColor()->getRGB());
332
333
                // a:alpha
334 6
                $objWriter->startElement('a:alpha');
335 6
                $objWriter->writeAttribute('val', (string) ($drawing->getShadow()->getAlpha() * 1000));
336 6
                $objWriter->endElement();
337
338 6
                $objWriter->endElement();
339
340 6
                $objWriter->endElement();
341
342 6
                $objWriter->endElement();
343
            }
344 50
            $objWriter->endElement();
345
346 50
            $objWriter->endElement();
347
348
            // xdr:clientData
349 50
            $objWriter->writeElement('xdr:clientData', null);
350
351 50
            $objWriter->endElement();
352
        } else {
353
            throw new WriterException('Invalid parameters passed.');
354
        }
355
    }
356
357
    /**
358
     * Write VML header/footer images to XML format.
359
     *
360
     * @return string XML Output
361
     */
362 3
    public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): string
363
    {
364
        // Create XML writer
365 3
        $objWriter = null;
366 3
        if ($this->getParentWriter()->getUseDiskCaching()) {
367
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
368
        } else {
369 3
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
370
        }
371
372
        // XML header
373 3
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
374
375
        // Header/footer images
376 3
        $images = $worksheet->getHeaderFooter()->getImages();
377
378
        // xml
379 3
        $objWriter->startElement('xml');
380 3
        $objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML);
381 3
        $objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE);
382 3
        $objWriter->writeAttribute('xmlns:x', Namespaces::URN_EXCEL);
383
384
        // o:shapelayout
385 3
        $objWriter->startElement('o:shapelayout');
386 3
        $objWriter->writeAttribute('v:ext', 'edit');
387
388
        // o:idmap
389 3
        $objWriter->startElement('o:idmap');
390 3
        $objWriter->writeAttribute('v:ext', 'edit');
391 3
        $objWriter->writeAttribute('data', '1');
392 3
        $objWriter->endElement();
393
394 3
        $objWriter->endElement();
395
396
        // v:shapetype
397 3
        $objWriter->startElement('v:shapetype');
398 3
        $objWriter->writeAttribute('id', '_x0000_t75');
399 3
        $objWriter->writeAttribute('coordsize', '21600,21600');
400 3
        $objWriter->writeAttribute('o:spt', '75');
401 3
        $objWriter->writeAttribute('o:preferrelative', 't');
402 3
        $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
403 3
        $objWriter->writeAttribute('filled', 'f');
404 3
        $objWriter->writeAttribute('stroked', 'f');
405
406
        // v:stroke
407 3
        $objWriter->startElement('v:stroke');
408 3
        $objWriter->writeAttribute('joinstyle', 'miter');
409 3
        $objWriter->endElement();
410
411
        // v:formulas
412 3
        $objWriter->startElement('v:formulas');
413
414
        // v:f
415 3
        $objWriter->startElement('v:f');
416 3
        $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
417 3
        $objWriter->endElement();
418
419
        // v:f
420 3
        $objWriter->startElement('v:f');
421 3
        $objWriter->writeAttribute('eqn', 'sum @0 1 0');
422 3
        $objWriter->endElement();
423
424
        // v:f
425 3
        $objWriter->startElement('v:f');
426 3
        $objWriter->writeAttribute('eqn', 'sum 0 0 @1');
427 3
        $objWriter->endElement();
428
429
        // v:f
430 3
        $objWriter->startElement('v:f');
431 3
        $objWriter->writeAttribute('eqn', 'prod @2 1 2');
432 3
        $objWriter->endElement();
433
434
        // v:f
435 3
        $objWriter->startElement('v:f');
436 3
        $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
437 3
        $objWriter->endElement();
438
439
        // v:f
440 3
        $objWriter->startElement('v:f');
441 3
        $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
442 3
        $objWriter->endElement();
443
444
        // v:f
445 3
        $objWriter->startElement('v:f');
446 3
        $objWriter->writeAttribute('eqn', 'sum @0 0 1');
447 3
        $objWriter->endElement();
448
449
        // v:f
450 3
        $objWriter->startElement('v:f');
451 3
        $objWriter->writeAttribute('eqn', 'prod @6 1 2');
452 3
        $objWriter->endElement();
453
454
        // v:f
455 3
        $objWriter->startElement('v:f');
456 3
        $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
457 3
        $objWriter->endElement();
458
459
        // v:f
460 3
        $objWriter->startElement('v:f');
461 3
        $objWriter->writeAttribute('eqn', 'sum @8 21600 0');
462 3
        $objWriter->endElement();
463
464
        // v:f
465 3
        $objWriter->startElement('v:f');
466 3
        $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
467 3
        $objWriter->endElement();
468
469
        // v:f
470 3
        $objWriter->startElement('v:f');
471 3
        $objWriter->writeAttribute('eqn', 'sum @10 21600 0');
472 3
        $objWriter->endElement();
473
474 3
        $objWriter->endElement();
475
476
        // v:path
477 3
        $objWriter->startElement('v:path');
478 3
        $objWriter->writeAttribute('o:extrusionok', 'f');
479 3
        $objWriter->writeAttribute('gradientshapeok', 't');
480 3
        $objWriter->writeAttribute('o:connecttype', 'rect');
481 3
        $objWriter->endElement();
482
483
        // o:lock
484 3
        $objWriter->startElement('o:lock');
485 3
        $objWriter->writeAttribute('v:ext', 'edit');
486 3
        $objWriter->writeAttribute('aspectratio', 't');
487 3
        $objWriter->endElement();
488
489 3
        $objWriter->endElement();
490
491
        // Loop through images
492 3
        foreach ($images as $key => $value) {
493 3
            $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
494
        }
495
496 3
        $objWriter->endElement();
497
498
        // Return
499 3
        return $objWriter->getData();
500
    }
501
502
    /**
503
     * Write VML comment to XML format.
504
     *
505
     * @param string $reference Reference
506
     */
507 3
    private function writeVMLHeaderFooterImage(XMLWriter $objWriter, string $reference, HeaderFooterDrawing $image): void
508
    {
509
        // Calculate object id
510 3
        preg_match('{(\d+)}', md5($reference), $m);
511 3
        $id = 1500 + ((int) substr($m[1], 0, 2) * 1);
512
513
        // Calculate offset
514 3
        $width = $image->getWidth();
515 3
        $height = $image->getHeight();
516 3
        $marginLeft = $image->getOffsetX();
517 3
        $marginTop = $image->getOffsetY();
518
519
        // v:shape
520 3
        $objWriter->startElement('v:shape');
521 3
        $objWriter->writeAttribute('id', $reference);
522 3
        $objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
523 3
        $objWriter->writeAttribute('type', '#_x0000_t75');
524 3
        $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
525
526
        // v:imagedata
527 3
        $objWriter->startElement('v:imagedata');
528 3
        $objWriter->writeAttribute('o:relid', 'rId' . $reference);
529 3
        $objWriter->writeAttribute('o:title', $image->getName());
530 3
        $objWriter->endElement();
531
532
        // o:lock
533 3
        $objWriter->startElement('o:lock');
534 3
        $objWriter->writeAttribute('v:ext', 'edit');
535 3
        $objWriter->writeAttribute('textRotation', 't');
536 3
        $objWriter->endElement();
537
538 3
        $objWriter->endElement();
539
    }
540
541
    /**
542
     * Get an array of all drawings.
543
     *
544
     * @return BaseDrawing[] All drawings in PhpSpreadsheet
545
     */
546 350
    public function allDrawings(Spreadsheet $spreadsheet): array
547
    {
548
        // Get an array of all drawings
549 350
        $aDrawings = [];
550
551
        // Loop through PhpSpreadsheet
552 350
        $sheetCount = $spreadsheet->getSheetCount();
553 350
        for ($i = 0; $i < $sheetCount; ++$i) {
554
            // Loop through images and add to array
555 350
            $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
556 350
            while ($iterator->valid()) {
557 50
                $aDrawings[] = $iterator->current();
558
559 50
                $iterator->next();
560
            }
561
        }
562
563 350
        return $aDrawings;
564
    }
565
566 50
    private function writeHyperLinkDrawing(XMLWriter $objWriter, ?int $hlinkClickId): void
567
    {
568 50
        if ($hlinkClickId === null) {
569 48
            return;
570
        }
571
572 2
        $objWriter->startElement('a:hlinkClick');
573 2
        $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
574 2
        $objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
575 2
        $objWriter->endElement();
576
    }
577
578 112
    private static function stringEmu(int $pixelValue): string
579
    {
580 112
        return (string) SharedDrawing::pixelsToEMU($pixelValue);
581
    }
582
583 50
    private static function writeAttributeIf(XMLWriter $objWriter, ?bool $condition, string $attr, string $val): void
584
    {
585 50
        if ($condition) {
586 1
            $objWriter->writeAttribute($attr, $val);
587
        }
588
    }
589
}
590