PageRenderTime 81ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Classes/PHPExcel/Writer/Excel5/Escher.php

#
PHP | 512 lines | 280 code | 126 blank | 106 comment | 13 complexity | afbd81189e755570aed86a867398ddb2 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2012 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Writer_Excel5
  23. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. /**
  28. * PHPExcel_Shared_Escher_DggContainer_BstoreContainer
  29. *
  30. * @category PHPExcel
  31. * @package PHPExcel_Writer_Excel5
  32. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  33. */
  34. class PHPExcel_Writer_Excel5_Escher
  35. {
  36. /**
  37. * The object we are writing
  38. */
  39. private $_object;
  40. /**
  41. * The written binary data
  42. */
  43. private $_data;
  44. /**
  45. * Shape offsets. Positions in binary stream where a new shape record begins
  46. *
  47. * @var array
  48. */
  49. private $_spOffsets;
  50. /**
  51. * Constructor
  52. *
  53. * @param mixed
  54. */
  55. public function __construct($object)
  56. {
  57. $this->_object = $object;
  58. }
  59. /**
  60. * Process the object to be written
  61. */
  62. public function close()
  63. {
  64. // initialize
  65. $this->_data = '';
  66. switch (get_class($this->_object)) {
  67. case 'PHPExcel_Shared_Escher':
  68. if ($dggContainer = $this->_object->getDggContainer()) {
  69. $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer);
  70. $this->_data = $writer->close();
  71. } else if ($dgContainer = $this->_object->getDgContainer()) {
  72. $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer);
  73. $this->_data = $writer->close();
  74. $this->_spOffsets = $writer->getSpOffsets();
  75. }
  76. break;
  77. case 'PHPExcel_Shared_Escher_DggContainer':
  78. // this is a container record
  79. // initialize
  80. $innerData = '';
  81. // write the dgg
  82. $recVer = 0x0;
  83. $recInstance = 0x0000;
  84. $recType = 0xF006;
  85. $recVerInstance = $recVer;
  86. $recVerInstance |= $recInstance << 4;
  87. // dgg data
  88. $dggData =
  89. pack('VVVV'
  90. , $this->_object->getSpIdMax() // maximum shape identifier increased by one
  91. , $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one
  92. , $this->_object->getCSpSaved()
  93. , $this->_object->getCDgSaved() // count total number of drawings saved
  94. );
  95. // add file identifier clusters (one per drawing)
  96. $IDCLs = $this->_object->getIDCLs();
  97. foreach ($IDCLs as $dgId => $maxReducedSpId) {
  98. $dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
  99. }
  100. $header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
  101. $innerData .= $header . $dggData;
  102. // write the bstoreContainer
  103. if ($bstoreContainer = $this->_object->getBstoreContainer()) {
  104. $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer);
  105. $innerData .= $writer->close();
  106. }
  107. // write the record
  108. $recVer = 0xF;
  109. $recInstance = 0x0000;
  110. $recType = 0xF000;
  111. $length = strlen($innerData);
  112. $recVerInstance = $recVer;
  113. $recVerInstance |= $recInstance << 4;
  114. $header = pack('vvV', $recVerInstance, $recType, $length);
  115. $this->_data = $header . $innerData;
  116. break;
  117. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer':
  118. // this is a container record
  119. // initialize
  120. $innerData = '';
  121. // treat the inner data
  122. if ($BSECollection = $this->_object->getBSECollection()) {
  123. foreach ($BSECollection as $BSE) {
  124. $writer = new PHPExcel_Writer_Excel5_Escher($BSE);
  125. $innerData .= $writer->close();
  126. }
  127. }
  128. // write the record
  129. $recVer = 0xF;
  130. $recInstance = count($this->_object->getBSECollection());
  131. $recType = 0xF001;
  132. $length = strlen($innerData);
  133. $recVerInstance = $recVer;
  134. $recVerInstance |= $recInstance << 4;
  135. $header = pack('vvV', $recVerInstance, $recType, $length);
  136. $this->_data = $header . $innerData;
  137. break;
  138. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE':
  139. // this is a semi-container record
  140. // initialize
  141. $innerData = '';
  142. // here we treat the inner data
  143. if ($blip = $this->_object->getBlip()) {
  144. $writer = new PHPExcel_Writer_Excel5_Escher($blip);
  145. $innerData .= $writer->close();
  146. }
  147. // initialize
  148. $data = '';
  149. $btWin32 = $this->_object->getBlipType();
  150. $btMacOS = $this->_object->getBlipType();
  151. $data .= pack('CC', $btWin32, $btMacOS);
  152. $rgbUid = pack('VVVV', 0,0,0,0); // todo
  153. $data .= $rgbUid;
  154. $tag = 0;
  155. $size = strlen($innerData);
  156. $cRef = 1;
  157. $foDelay = 0; //todo
  158. $unused1 = 0x0;
  159. $cbName = 0x0;
  160. $unused2 = 0x0;
  161. $unused3 = 0x0;
  162. $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
  163. $data .= $innerData;
  164. // write the record
  165. $recVer = 0x2;
  166. $recInstance = $this->_object->getBlipType();
  167. $recType = 0xF007;
  168. $length = strlen($data);
  169. $recVerInstance = $recVer;
  170. $recVerInstance |= $recInstance << 4;
  171. $header = pack('vvV', $recVerInstance, $recType, $length);
  172. $this->_data = $header;
  173. $this->_data .= $data;
  174. break;
  175. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip':
  176. // this is an atom record
  177. // write the record
  178. switch ($this->_object->getParent()->getBlipType()) {
  179. case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG:
  180. // initialize
  181. $innerData = '';
  182. $rgbUid1 = pack('VVVV', 0,0,0,0); // todo
  183. $innerData .= $rgbUid1;
  184. $tag = 0xFF; // todo
  185. $innerData .= pack('C', $tag);
  186. $innerData .= $this->_object->getData();
  187. $recVer = 0x0;
  188. $recInstance = 0x46A;
  189. $recType = 0xF01D;
  190. $length = strlen($innerData);
  191. $recVerInstance = $recVer;
  192. $recVerInstance |= $recInstance << 4;
  193. $header = pack('vvV', $recVerInstance, $recType, $length);
  194. $this->_data = $header;
  195. $this->_data .= $innerData;
  196. break;
  197. case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG:
  198. // initialize
  199. $innerData = '';
  200. $rgbUid1 = pack('VVVV', 0,0,0,0); // todo
  201. $innerData .= $rgbUid1;
  202. $tag = 0xFF; // todo
  203. $innerData .= pack('C', $tag);
  204. $innerData .= $this->_object->getData();
  205. $recVer = 0x0;
  206. $recInstance = 0x6E0;
  207. $recType = 0xF01E;
  208. $length = strlen($innerData);
  209. $recVerInstance = $recVer;
  210. $recVerInstance |= $recInstance << 4;
  211. $header = pack('vvV', $recVerInstance, $recType, $length);
  212. $this->_data = $header;
  213. $this->_data .= $innerData;
  214. break;
  215. }
  216. break;
  217. case 'PHPExcel_Shared_Escher_DgContainer':
  218. // this is a container record
  219. // initialize
  220. $innerData = '';
  221. // write the dg
  222. $recVer = 0x0;
  223. $recInstance = $this->_object->getDgId();
  224. $recType = 0xF008;
  225. $length = 8;
  226. $recVerInstance = $recVer;
  227. $recVerInstance |= $recInstance << 4;
  228. $header = pack('vvV', $recVerInstance, $recType, $length);
  229. // number of shapes in this drawing (including group shape)
  230. $countShapes = count($this->_object->getSpgrContainer()->getChildren());
  231. $innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId());
  232. //$innerData .= $header . pack('VV', 0, 0);
  233. // write the spgrContainer
  234. if ($spgrContainer = $this->_object->getSpgrContainer()) {
  235. $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer);
  236. $innerData .= $writer->close();
  237. // get the shape offsets relative to the spgrContainer record
  238. $spOffsets = $writer->getSpOffsets();
  239. // save the shape offsets relative to dgContainer
  240. foreach ($spOffsets as & $spOffset) {
  241. $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
  242. }
  243. $this->_spOffsets = $spOffsets;
  244. }
  245. // write the record
  246. $recVer = 0xF;
  247. $recInstance = 0x0000;
  248. $recType = 0xF002;
  249. $length = strlen($innerData);
  250. $recVerInstance = $recVer;
  251. $recVerInstance |= $recInstance << 4;
  252. $header = pack('vvV', $recVerInstance, $recType, $length);
  253. $this->_data = $header . $innerData;
  254. break;
  255. case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer':
  256. // this is a container record
  257. // initialize
  258. $innerData = '';
  259. // initialize spape offsets
  260. $totalSize = 8;
  261. $spOffsets = array();
  262. // treat the inner data
  263. foreach ($this->_object->getChildren() as $spContainer) {
  264. $writer = new PHPExcel_Writer_Excel5_Escher($spContainer);
  265. $spData = $writer->close();
  266. $innerData .= $spData;
  267. // save the shape offsets (where new shape records begin)
  268. $totalSize += strlen($spData);
  269. $spOffsets[] = $totalSize;
  270. }
  271. // write the record
  272. $recVer = 0xF;
  273. $recInstance = 0x0000;
  274. $recType = 0xF003;
  275. $length = strlen($innerData);
  276. $recVerInstance = $recVer;
  277. $recVerInstance |= $recInstance << 4;
  278. $header = pack('vvV', $recVerInstance, $recType, $length);
  279. $this->_data = $header . $innerData;
  280. $this->_spOffsets = $spOffsets;
  281. break;
  282. case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer':
  283. // initialize
  284. $data = '';
  285. // build the data
  286. // write group shape record, if necessary?
  287. if ($this->_object->getSpgr()) {
  288. $recVer = 0x1;
  289. $recInstance = 0x0000;
  290. $recType = 0xF009;
  291. $length = 0x00000010;
  292. $recVerInstance = $recVer;
  293. $recVerInstance |= $recInstance << 4;
  294. $header = pack('vvV', $recVerInstance, $recType, $length);
  295. $data .= $header . pack('VVVV', 0,0,0,0);
  296. }
  297. // write the shape record
  298. $recVer = 0x2;
  299. $recInstance = $this->_object->getSpType(); // shape type
  300. $recType = 0xF00A;
  301. $length = 0x00000008;
  302. $recVerInstance = $recVer;
  303. $recVerInstance |= $recInstance << 4;
  304. $header = pack('vvV', $recVerInstance, $recType, $length);
  305. $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00);
  306. // the options
  307. if ($this->_object->getOPTCollection()) {
  308. $optData = '';
  309. $recVer = 0x3;
  310. $recInstance = count($this->_object->getOPTCollection());
  311. $recType = 0xF00B;
  312. foreach ($this->_object->getOPTCollection() as $property => $value) {
  313. $optData .= pack('vV', $property, $value);
  314. }
  315. $length = strlen($optData);
  316. $recVerInstance = $recVer;
  317. $recVerInstance |= $recInstance << 4;
  318. $header = pack('vvV', $recVerInstance, $recType, $length);
  319. $data .= $header . $optData;
  320. }
  321. // the client anchor
  322. if ($this->_object->getStartCoordinates()) {
  323. $clientAnchorData = '';
  324. $recVer = 0x0;
  325. $recInstance = 0x0;
  326. $recType = 0xF010;
  327. // start coordinates
  328. list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getStartCoordinates());
  329. $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1;
  330. $r1 = $row - 1;
  331. // start offsetX
  332. $startOffsetX = $this->_object->getStartOffsetX();
  333. // start offsetY
  334. $startOffsetY = $this->_object->getStartOffsetY();
  335. // end coordinates
  336. list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getEndCoordinates());
  337. $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1;
  338. $r2 = $row - 1;
  339. // end offsetX
  340. $endOffsetX = $this->_object->getEndOffsetX();
  341. // end offsetY
  342. $endOffsetY = $this->_object->getEndOffsetY();
  343. $clientAnchorData = pack('vvvvvvvvv', 0x02,
  344. $c1, $startOffsetX, $r1, $startOffsetY,
  345. $c2, $endOffsetX, $r2, $endOffsetY);
  346. $length = strlen($clientAnchorData);
  347. $recVerInstance = $recVer;
  348. $recVerInstance |= $recInstance << 4;
  349. $header = pack('vvV', $recVerInstance, $recType, $length);
  350. $data .= $header . $clientAnchorData;
  351. }
  352. // the client data, just empty for now
  353. if (!$this->_object->getSpgr()) {
  354. $clientDataData = '';
  355. $recVer = 0x0;
  356. $recInstance = 0x0;
  357. $recType = 0xF011;
  358. $length = strlen($clientDataData);
  359. $recVerInstance = $recVer;
  360. $recVerInstance |= $recInstance << 4;
  361. $header = pack('vvV', $recVerInstance, $recType, $length);
  362. $data .= $header . $clientDataData;
  363. }
  364. // write the record
  365. $recVer = 0xF;
  366. $recInstance = 0x0000;
  367. $recType = 0xF004;
  368. $length = strlen($data);
  369. $recVerInstance = $recVer;
  370. $recVerInstance |= $recInstance << 4;
  371. $header = pack('vvV', $recVerInstance, $recType, $length);
  372. $this->_data = $header . $data;
  373. break;
  374. }
  375. return $this->_data;
  376. }
  377. /**
  378. * Gets the shape offsets
  379. *
  380. * @return array
  381. */
  382. public function getSpOffsets()
  383. {
  384. return $this->_spOffsets;
  385. }
  386. }