Source for file Escher.php
Documentation is available at Escher.php
* Copyright (c) 2006 - 2011 PHPExcel
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @package PHPExcel_Writer_Excel5
* @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version 1.7.6, 2011-02-27
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer
* @package PHPExcel_Writer_Excel5
* @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
* The object we are writing
* The written binary data
* Shape offsets. Positions in binary stream where a new shape record begins
$this->_object = $object;
* Process the object to be written
case 'PHPExcel_Shared_Escher':
if ($dggContainer = $this->_object->getDggContainer()) {
$this->_data = $writer->close();
} else if ($dgContainer = $this->_object->getDgContainer()) {
$this->_data = $writer->close();
$this->_spOffsets = $writer->getSpOffsets();
case 'PHPExcel_Shared_Escher_DggContainer':
// this is a container record
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
, $this->_object->getSpIdMax() // maximum shape identifier increased by one
, $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one
, $this->_object->getCSpSaved()
, $this->_object->getCDgSaved() // count total number of drawings saved
// add file identifier clusters (one per drawing)
$IDCLs = $this->_object->getIDCLs();
foreach ($IDCLs as $dgId => $maxReducedSpId) {
$dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
$header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
$innerData .= $header . $dggData;
// write the bstoreContainer
if ($bstoreContainer = $this->_object->getBstoreContainer()) {
$innerData .= $writer->close();
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data = $header . $innerData;
case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer':
// this is a container record
if ($BSECollection = $this->_object->getBSECollection()) {
foreach ($BSECollection as $BSE) {
$innerData .= $writer->close();
$recInstance = count($this->_object->getBSECollection());
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data = $header . $innerData;
case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE':
// this is a semi-container record
// here we treat the inner data
if ($blip = $this->_object->getBlip()) {
$innerData .= $writer->close();
$btWin32 = $this->_object->getBlipType();
$btMacOS = $this->_object->getBlipType();
$data .= pack('CC', $btWin32, $btMacOS);
$rgbUid = pack('VVVV', 0,0,0,0); // todo
$data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
$recInstance = $this->_object->getBlipType();
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip':
// this is an atom record
switch ($this->_object->getParent()->getBlipType()) {
$rgbUid1 = pack('VVVV', 0,0,0,0); // todo
$innerData .= pack('C', $tag);
$innerData .= $this->_object->getData();
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data .= $innerData;
$rgbUid1 = pack('VVVV', 0,0,0,0); // todo
$innerData .= pack('C', $tag);
$innerData .= $this->_object->getData();
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data .= $innerData;
case 'PHPExcel_Shared_Escher_DgContainer':
// this is a container record
$recInstance = $this->_object->getDgId();
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
// number of shapes in this drawing (including group shape)
$countShapes = count($this->_object->getSpgrContainer()->getChildren());
$innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId());
//$innerData .= $header . pack('VV', 0, 0);
// write the spgrContainer
if ($spgrContainer = $this->_object->getSpgrContainer()) {
$innerData .= $writer->close();
// get the shape offsets relative to the spgrContainer record
$spOffsets = $writer->getSpOffsets();
// save the shape offsets relative to dgContainer
foreach ($spOffsets as & $spOffset) {
$spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
$this->_spOffsets = $spOffsets;
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data = $header . $innerData;
case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer':
// this is a container record
// initialize spape offsets
foreach ($this->_object->getChildren() as $spContainer) {
$spData = $writer->close();
// save the shape offsets (where new shape records begin)
$totalSize += strlen($spData);
$spOffsets[] = $totalSize;
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data = $header . $innerData;
$this->_spOffsets = $spOffsets;
case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer':
// write group shape record, if necessary?
if ($this->_object->getSpgr()) {
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$data .= $header . pack('VVVV', 0,0,0,0);
// write the shape record
$recInstance = $this->_object->getSpType(); // shape type
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00);
if ($this->_object->getOPTCollection()) {
$recInstance = count($this->_object->getOPTCollection());
foreach ($this->_object->getOPTCollection() as $property => $value) {
$optData .= pack('vV', $property, $value);
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$data .= $header . $optData;
if ($this->_object->getStartCoordinates()) {
$startOffsetX = $this->_object->getStartOffsetX();
$startOffsetY = $this->_object->getStartOffsetY();
$endOffsetX = $this->_object->getEndOffsetX();
$endOffsetY = $this->_object->getEndOffsetY();
$clientAnchorData = pack('vvvvvvvvv', 0x02,
$c1, $startOffsetX, $r1, $startOffsetY,
$c2, $endOffsetX, $r2, $endOffsetY);
$length = strlen($clientAnchorData);
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$data .= $header . $clientAnchorData;
// the client data, just empty for now
if (!$this->_object->getSpgr()) {
$length = strlen($clientDataData);
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$data .= $header . $clientDataData;
$recVerInstance = $recVer;
$recVerInstance |= $recInstance << 4;
$header = pack('vvV', $recVerInstance, $recType, $length);
$this->_data = $header . $data;
return $this->_spOffsets;
|