composer package updates
[openemr.git] / vendor / phpoffice / phpspreadsheet / src / PhpSpreadsheet / Writer / Xlsx / Drawing.php
blob533c7b3b9de80fa9f1cf64a6c992f1950759d447
1 <?php
3 namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
5 use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
7 use PhpOffice\PhpSpreadsheet\Spreadsheet;
8 use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
9 use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
10 use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
12 class Drawing extends WriterPart
14 /**
15 * Write drawings to XML format.
17 * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
18 * @param bool $includeCharts Flag indicating if we should include drawing details for charts
20 * @throws WriterException
22 * @return string XML Output
24 public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet, $includeCharts = false)
26 // Create XML writer
27 $objWriter = null;
28 if ($this->getParentWriter()->getUseDiskCaching()) {
29 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
30 } else {
31 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
34 // XML header
35 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
37 // xdr:wsDr
38 $objWriter->startElement('xdr:wsDr');
39 $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
40 $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
42 // Loop through images and write drawings
43 $i = 1;
44 $iterator = $pWorksheet->getDrawingCollection()->getIterator();
45 while ($iterator->valid()) {
46 $this->writeDrawing($objWriter, $iterator->current(), $i);
48 $iterator->next();
49 ++$i;
52 if ($includeCharts) {
53 $chartCount = $pWorksheet->getChartCount();
54 // Loop through charts and write the chart position
55 if ($chartCount > 0) {
56 for ($c = 0; $c < $chartCount; ++$c) {
57 $this->writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c + $i);
62 // unparsed AlternateContent
63 $unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
64 if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'])) {
65 foreach ($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
66 $objWriter->writeRaw($drawingAlternateContent);
70 $objWriter->endElement();
72 // Return
73 return $objWriter->getData();
76 /**
77 * Write drawings to XML format.
79 * @param XMLWriter $objWriter XML Writer
80 * @param \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart
81 * @param int $pRelationId
83 public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $pRelationId = -1)
85 $tl = $pChart->getTopLeftPosition();
86 $tl['colRow'] = Coordinate::coordinateFromString($tl['cell']);
87 $br = $pChart->getBottomRightPosition();
88 $br['colRow'] = Coordinate::coordinateFromString($br['cell']);
90 $objWriter->startElement('xdr:twoCellAnchor');
92 $objWriter->startElement('xdr:from');
93 $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($tl['colRow'][0]) - 1);
94 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
95 $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1);
96 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
97 $objWriter->endElement();
98 $objWriter->startElement('xdr:to');
99 $objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($br['colRow'][0]) - 1);
100 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
101 $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1);
102 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['yOffset']));
103 $objWriter->endElement();
105 $objWriter->startElement('xdr:graphicFrame');
106 $objWriter->writeAttribute('macro', '');
107 $objWriter->startElement('xdr:nvGraphicFramePr');
108 $objWriter->startElement('xdr:cNvPr');
109 $objWriter->writeAttribute('name', 'Chart ' . $pRelationId);
110 $objWriter->writeAttribute('id', 1025 * $pRelationId);
111 $objWriter->endElement();
112 $objWriter->startElement('xdr:cNvGraphicFramePr');
113 $objWriter->startElement('a:graphicFrameLocks');
114 $objWriter->endElement();
115 $objWriter->endElement();
116 $objWriter->endElement();
118 $objWriter->startElement('xdr:xfrm');
119 $objWriter->startElement('a:off');
120 $objWriter->writeAttribute('x', '0');
121 $objWriter->writeAttribute('y', '0');
122 $objWriter->endElement();
123 $objWriter->startElement('a:ext');
124 $objWriter->writeAttribute('cx', '0');
125 $objWriter->writeAttribute('cy', '0');
126 $objWriter->endElement();
127 $objWriter->endElement();
129 $objWriter->startElement('a:graphic');
130 $objWriter->startElement('a:graphicData');
131 $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
132 $objWriter->startElement('c:chart');
133 $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
134 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
135 $objWriter->writeAttribute('r:id', 'rId' . $pRelationId);
136 $objWriter->endElement();
137 $objWriter->endElement();
138 $objWriter->endElement();
139 $objWriter->endElement();
141 $objWriter->startElement('xdr:clientData');
142 $objWriter->endElement();
144 $objWriter->endElement();
148 * Write drawings to XML format.
150 * @param XMLWriter $objWriter XML Writer
151 * @param BaseDrawing $pDrawing
152 * @param int $pRelationId
154 * @throws WriterException
156 public function writeDrawing(XMLWriter $objWriter, BaseDrawing $pDrawing, $pRelationId = -1)
158 if ($pRelationId >= 0) {
159 // xdr:oneCellAnchor
160 $objWriter->startElement('xdr:oneCellAnchor');
161 // Image location
162 $aCoordinates = Coordinate::coordinateFromString($pDrawing->getCoordinates());
163 $aCoordinates[0] = Coordinate::columnIndexFromString($aCoordinates[0]);
165 // xdr:from
166 $objWriter->startElement('xdr:from');
167 $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
168 $objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetX()));
169 $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
170 $objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getOffsetY()));
171 $objWriter->endElement();
173 // xdr:ext
174 $objWriter->startElement('xdr:ext');
175 $objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getWidth()));
176 $objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getHeight()));
177 $objWriter->endElement();
179 // xdr:pic
180 $objWriter->startElement('xdr:pic');
182 // xdr:nvPicPr
183 $objWriter->startElement('xdr:nvPicPr');
185 // xdr:cNvPr
186 $objWriter->startElement('xdr:cNvPr');
187 $objWriter->writeAttribute('id', $pRelationId);
188 $objWriter->writeAttribute('name', $pDrawing->getName());
189 $objWriter->writeAttribute('descr', $pDrawing->getDescription());
190 $objWriter->endElement();
192 // xdr:cNvPicPr
193 $objWriter->startElement('xdr:cNvPicPr');
195 // a:picLocks
196 $objWriter->startElement('a:picLocks');
197 $objWriter->writeAttribute('noChangeAspect', '1');
198 $objWriter->endElement();
200 $objWriter->endElement();
202 $objWriter->endElement();
204 // xdr:blipFill
205 $objWriter->startElement('xdr:blipFill');
207 // a:blip
208 $objWriter->startElement('a:blip');
209 $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
210 $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId);
211 $objWriter->endElement();
213 // a:stretch
214 $objWriter->startElement('a:stretch');
215 $objWriter->writeElement('a:fillRect', null);
216 $objWriter->endElement();
218 $objWriter->endElement();
220 // xdr:spPr
221 $objWriter->startElement('xdr:spPr');
223 // a:xfrm
224 $objWriter->startElement('a:xfrm');
225 $objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getRotation()));
226 $objWriter->endElement();
228 // a:prstGeom
229 $objWriter->startElement('a:prstGeom');
230 $objWriter->writeAttribute('prst', 'rect');
232 // a:avLst
233 $objWriter->writeElement('a:avLst', null);
235 $objWriter->endElement();
237 if ($pDrawing->getShadow()->getVisible()) {
238 // a:effectLst
239 $objWriter->startElement('a:effectLst');
241 // a:outerShdw
242 $objWriter->startElement('a:outerShdw');
243 $objWriter->writeAttribute('blurRad', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius()));
244 $objWriter->writeAttribute('dist', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance()));
245 $objWriter->writeAttribute('dir', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($pDrawing->getShadow()->getDirection()));
246 $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment());
247 $objWriter->writeAttribute('rotWithShape', '0');
249 // a:srgbClr
250 $objWriter->startElement('a:srgbClr');
251 $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB());
253 // a:alpha
254 $objWriter->startElement('a:alpha');
255 $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000);
256 $objWriter->endElement();
258 $objWriter->endElement();
260 $objWriter->endElement();
262 $objWriter->endElement();
264 $objWriter->endElement();
266 $objWriter->endElement();
268 // xdr:clientData
269 $objWriter->writeElement('xdr:clientData', null);
271 $objWriter->endElement();
272 } else {
273 throw new WriterException('Invalid parameters passed.');
278 * Write VML header/footer images to XML format.
280 * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
282 * @throws WriterException
284 * @return string XML Output
286 public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
288 // Create XML writer
289 $objWriter = null;
290 if ($this->getParentWriter()->getUseDiskCaching()) {
291 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
292 } else {
293 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
296 // XML header
297 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
299 // Header/footer images
300 $images = $pWorksheet->getHeaderFooter()->getImages();
302 // xml
303 $objWriter->startElement('xml');
304 $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml');
305 $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
306 $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel');
308 // o:shapelayout
309 $objWriter->startElement('o:shapelayout');
310 $objWriter->writeAttribute('v:ext', 'edit');
312 // o:idmap
313 $objWriter->startElement('o:idmap');
314 $objWriter->writeAttribute('v:ext', 'edit');
315 $objWriter->writeAttribute('data', '1');
316 $objWriter->endElement();
318 $objWriter->endElement();
320 // v:shapetype
321 $objWriter->startElement('v:shapetype');
322 $objWriter->writeAttribute('id', '_x0000_t75');
323 $objWriter->writeAttribute('coordsize', '21600,21600');
324 $objWriter->writeAttribute('o:spt', '75');
325 $objWriter->writeAttribute('o:preferrelative', 't');
326 $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
327 $objWriter->writeAttribute('filled', 'f');
328 $objWriter->writeAttribute('stroked', 'f');
330 // v:stroke
331 $objWriter->startElement('v:stroke');
332 $objWriter->writeAttribute('joinstyle', 'miter');
333 $objWriter->endElement();
335 // v:formulas
336 $objWriter->startElement('v:formulas');
338 // v:f
339 $objWriter->startElement('v:f');
340 $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
341 $objWriter->endElement();
343 // v:f
344 $objWriter->startElement('v:f');
345 $objWriter->writeAttribute('eqn', 'sum @0 1 0');
346 $objWriter->endElement();
348 // v:f
349 $objWriter->startElement('v:f');
350 $objWriter->writeAttribute('eqn', 'sum 0 0 @1');
351 $objWriter->endElement();
353 // v:f
354 $objWriter->startElement('v:f');
355 $objWriter->writeAttribute('eqn', 'prod @2 1 2');
356 $objWriter->endElement();
358 // v:f
359 $objWriter->startElement('v:f');
360 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
361 $objWriter->endElement();
363 // v:f
364 $objWriter->startElement('v:f');
365 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
366 $objWriter->endElement();
368 // v:f
369 $objWriter->startElement('v:f');
370 $objWriter->writeAttribute('eqn', 'sum @0 0 1');
371 $objWriter->endElement();
373 // v:f
374 $objWriter->startElement('v:f');
375 $objWriter->writeAttribute('eqn', 'prod @6 1 2');
376 $objWriter->endElement();
378 // v:f
379 $objWriter->startElement('v:f');
380 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
381 $objWriter->endElement();
383 // v:f
384 $objWriter->startElement('v:f');
385 $objWriter->writeAttribute('eqn', 'sum @8 21600 0');
386 $objWriter->endElement();
388 // v:f
389 $objWriter->startElement('v:f');
390 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
391 $objWriter->endElement();
393 // v:f
394 $objWriter->startElement('v:f');
395 $objWriter->writeAttribute('eqn', 'sum @10 21600 0');
396 $objWriter->endElement();
398 $objWriter->endElement();
400 // v:path
401 $objWriter->startElement('v:path');
402 $objWriter->writeAttribute('o:extrusionok', 'f');
403 $objWriter->writeAttribute('gradientshapeok', 't');
404 $objWriter->writeAttribute('o:connecttype', 'rect');
405 $objWriter->endElement();
407 // o:lock
408 $objWriter->startElement('o:lock');
409 $objWriter->writeAttribute('v:ext', 'edit');
410 $objWriter->writeAttribute('aspectratio', 't');
411 $objWriter->endElement();
413 $objWriter->endElement();
415 // Loop through images
416 foreach ($images as $key => $value) {
417 $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
420 $objWriter->endElement();
422 // Return
423 return $objWriter->getData();
427 * Write VML comment to XML format.
429 * @param XMLWriter $objWriter XML Writer
430 * @param string $pReference Reference
431 * @param HeaderFooterDrawing $pImage Image
433 private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $pReference, HeaderFooterDrawing $pImage)
435 // Calculate object id
436 preg_match('{(\d+)}', md5($pReference), $m);
437 $id = 1500 + (substr($m[1], 0, 2) * 1);
439 // Calculate offset
440 $width = $pImage->getWidth();
441 $height = $pImage->getHeight();
442 $marginLeft = $pImage->getOffsetX();
443 $marginTop = $pImage->getOffsetY();
445 // v:shape
446 $objWriter->startElement('v:shape');
447 $objWriter->writeAttribute('id', $pReference);
448 $objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
449 $objWriter->writeAttribute('type', '#_x0000_t75');
450 $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
452 // v:imagedata
453 $objWriter->startElement('v:imagedata');
454 $objWriter->writeAttribute('o:relid', 'rId' . $pReference);
455 $objWriter->writeAttribute('o:title', $pImage->getName());
456 $objWriter->endElement();
458 // o:lock
459 $objWriter->startElement('o:lock');
460 $objWriter->writeAttribute('v:ext', 'edit');
461 $objWriter->writeAttribute('textRotation', 't');
462 $objWriter->endElement();
464 $objWriter->endElement();
468 * Get an array of all drawings.
470 * @param Spreadsheet $spreadsheet
472 * @return \PhpOffice\PhpSpreadsheet\Worksheet\Drawing[] All drawings in PhpSpreadsheet
474 public function allDrawings(Spreadsheet $spreadsheet)
476 // Get an array of all drawings
477 $aDrawings = [];
479 // Loop through PhpSpreadsheet
480 $sheetCount = $spreadsheet->getSheetCount();
481 for ($i = 0; $i < $sheetCount; ++$i) {
482 // Loop through images and add to array
483 $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
484 while ($iterator->valid()) {
485 $aDrawings[] = $iterator->current();
487 $iterator->next();
491 return $aDrawings;