For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

523 lines
18 KiB

  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2015 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 - 2015 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 - 2015 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. * Shape types.
  52. *
  53. * @var array
  54. */
  55. private $spTypes;
  56. /**
  57. * Constructor
  58. *
  59. * @param mixed
  60. */
  61. public function __construct($object)
  62. {
  63. $this->object = $object;
  64. }
  65. /**
  66. * Process the object to be written
  67. */
  68. public function close()
  69. {
  70. // initialize
  71. $this->data = '';
  72. switch (get_class($this->object)) {
  73. case 'PHPExcel_Shared_Escher':
  74. if ($dggContainer = $this->object->getDggContainer()) {
  75. $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer);
  76. $this->data = $writer->close();
  77. } elseif ($dgContainer = $this->object->getDgContainer()) {
  78. $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer);
  79. $this->data = $writer->close();
  80. $this->spOffsets = $writer->getSpOffsets();
  81. $this->spTypes = $writer->getSpTypes();
  82. }
  83. break;
  84. case 'PHPExcel_Shared_Escher_DggContainer':
  85. // this is a container record
  86. // initialize
  87. $innerData = '';
  88. // write the dgg
  89. $recVer = 0x0;
  90. $recInstance = 0x0000;
  91. $recType = 0xF006;
  92. $recVerInstance = $recVer;
  93. $recVerInstance |= $recInstance << 4;
  94. // dgg data
  95. $dggData =
  96. pack(
  97. 'VVVV',
  98. $this->object->getSpIdMax(), // maximum shape identifier increased by one
  99. $this->object->getCDgSaved() + 1, // number of file identifier clusters increased by one
  100. $this->object->getCSpSaved(),
  101. $this->object->getCDgSaved() // count total number of drawings saved
  102. );
  103. // add file identifier clusters (one per drawing)
  104. $IDCLs = $this->object->getIDCLs();
  105. foreach ($IDCLs as $dgId => $maxReducedSpId) {
  106. $dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
  107. }
  108. $header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
  109. $innerData .= $header . $dggData;
  110. // write the bstoreContainer
  111. if ($bstoreContainer = $this->object->getBstoreContainer()) {
  112. $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer);
  113. $innerData .= $writer->close();
  114. }
  115. // write the record
  116. $recVer = 0xF;
  117. $recInstance = 0x0000;
  118. $recType = 0xF000;
  119. $length = strlen($innerData);
  120. $recVerInstance = $recVer;
  121. $recVerInstance |= $recInstance << 4;
  122. $header = pack('vvV', $recVerInstance, $recType, $length);
  123. $this->data = $header . $innerData;
  124. break;
  125. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer':
  126. // this is a container record
  127. // initialize
  128. $innerData = '';
  129. // treat the inner data
  130. if ($BSECollection = $this->object->getBSECollection()) {
  131. foreach ($BSECollection as $BSE) {
  132. $writer = new PHPExcel_Writer_Excel5_Escher($BSE);
  133. $innerData .= $writer->close();
  134. }
  135. }
  136. // write the record
  137. $recVer = 0xF;
  138. $recInstance = count($this->object->getBSECollection());
  139. $recType = 0xF001;
  140. $length = strlen($innerData);
  141. $recVerInstance = $recVer;
  142. $recVerInstance |= $recInstance << 4;
  143. $header = pack('vvV', $recVerInstance, $recType, $length);
  144. $this->data = $header . $innerData;
  145. break;
  146. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE':
  147. // this is a semi-container record
  148. // initialize
  149. $innerData = '';
  150. // here we treat the inner data
  151. if ($blip = $this->object->getBlip()) {
  152. $writer = new PHPExcel_Writer_Excel5_Escher($blip);
  153. $innerData .= $writer->close();
  154. }
  155. // initialize
  156. $data = '';
  157. $btWin32 = $this->object->getBlipType();
  158. $btMacOS = $this->object->getBlipType();
  159. $data .= pack('CC', $btWin32, $btMacOS);
  160. $rgbUid = pack('VVVV', 0, 0, 0, 0); // todo
  161. $data .= $rgbUid;
  162. $tag = 0;
  163. $size = strlen($innerData);
  164. $cRef = 1;
  165. $foDelay = 0; //todo
  166. $unused1 = 0x0;
  167. $cbName = 0x0;
  168. $unused2 = 0x0;
  169. $unused3 = 0x0;
  170. $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
  171. $data .= $innerData;
  172. // write the record
  173. $recVer = 0x2;
  174. $recInstance = $this->object->getBlipType();
  175. $recType = 0xF007;
  176. $length = strlen($data);
  177. $recVerInstance = $recVer;
  178. $recVerInstance |= $recInstance << 4;
  179. $header = pack('vvV', $recVerInstance, $recType, $length);
  180. $this->data = $header;
  181. $this->data .= $data;
  182. break;
  183. case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip':
  184. // this is an atom record
  185. // write the record
  186. switch ($this->object->getParent()->getBlipType()) {
  187. case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG:
  188. // initialize
  189. $innerData = '';
  190. $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
  191. $innerData .= $rgbUid1;
  192. $tag = 0xFF; // todo
  193. $innerData .= pack('C', $tag);
  194. $innerData .= $this->object->getData();
  195. $recVer = 0x0;
  196. $recInstance = 0x46A;
  197. $recType = 0xF01D;
  198. $length = strlen($innerData);
  199. $recVerInstance = $recVer;
  200. $recVerInstance |= $recInstance << 4;
  201. $header = pack('vvV', $recVerInstance, $recType, $length);
  202. $this->data = $header;
  203. $this->data .= $innerData;
  204. break;
  205. case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG:
  206. // initialize
  207. $innerData = '';
  208. $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
  209. $innerData .= $rgbUid1;
  210. $tag = 0xFF; // todo
  211. $innerData .= pack('C', $tag);
  212. $innerData .= $this->object->getData();
  213. $recVer = 0x0;
  214. $recInstance = 0x6E0;
  215. $recType = 0xF01E;
  216. $length = strlen($innerData);
  217. $recVerInstance = $recVer;
  218. $recVerInstance |= $recInstance << 4;
  219. $header = pack('vvV', $recVerInstance, $recType, $length);
  220. $this->data = $header;
  221. $this->data .= $innerData;
  222. break;
  223. }
  224. break;
  225. case 'PHPExcel_Shared_Escher_DgContainer':
  226. // this is a container record
  227. // initialize
  228. $innerData = '';
  229. // write the dg
  230. $recVer = 0x0;
  231. $recInstance = $this->object->getDgId();
  232. $recType = 0xF008;
  233. $length = 8;
  234. $recVerInstance = $recVer;
  235. $recVerInstance |= $recInstance << 4;
  236. $header = pack('vvV', $recVerInstance, $recType, $length);
  237. // number of shapes in this drawing (including group shape)
  238. $countShapes = count($this->object->getSpgrContainer()->getChildren());
  239. $innerData .= $header . pack('VV', $countShapes, $this->object->getLastSpId());
  240. //$innerData .= $header . pack('VV', 0, 0);
  241. // write the spgrContainer
  242. if ($spgrContainer = $this->object->getSpgrContainer()) {
  243. $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer);
  244. $innerData .= $writer->close();
  245. // get the shape offsets relative to the spgrContainer record
  246. $spOffsets = $writer->getSpOffsets();
  247. $spTypes = $writer->getSpTypes();
  248. // save the shape offsets relative to dgContainer
  249. foreach ($spOffsets as & $spOffset) {
  250. $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
  251. }
  252. $this->spOffsets = $spOffsets;
  253. $this->spTypes = $spTypes;
  254. }
  255. // write the record
  256. $recVer = 0xF;
  257. $recInstance = 0x0000;
  258. $recType = 0xF002;
  259. $length = strlen($innerData);
  260. $recVerInstance = $recVer;
  261. $recVerInstance |= $recInstance << 4;
  262. $header = pack('vvV', $recVerInstance, $recType, $length);
  263. $this->data = $header . $innerData;
  264. break;
  265. case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer':
  266. // this is a container record
  267. // initialize
  268. $innerData = '';
  269. // initialize spape offsets
  270. $totalSize = 8;
  271. $spOffsets = array();
  272. $spTypes = array();
  273. // treat the inner data
  274. foreach ($this->object->getChildren() as $spContainer) {
  275. $writer = new PHPExcel_Writer_Excel5_Escher($spContainer);
  276. $spData = $writer->close();
  277. $innerData .= $spData;
  278. // save the shape offsets (where new shape records begin)
  279. $totalSize += strlen($spData);
  280. $spOffsets[] = $totalSize;
  281. $spTypes = array_merge($spTypes, $writer->getSpTypes());
  282. }
  283. // write the record
  284. $recVer = 0xF;
  285. $recInstance = 0x0000;
  286. $recType = 0xF003;
  287. $length = strlen($innerData);
  288. $recVerInstance = $recVer;
  289. $recVerInstance |= $recInstance << 4;
  290. $header = pack('vvV', $recVerInstance, $recType, $length);
  291. $this->data = $header . $innerData;
  292. $this->spOffsets = $spOffsets;
  293. $this->spTypes = $spTypes;
  294. break;
  295. case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer':
  296. // initialize
  297. $data = '';
  298. // build the data
  299. // write group shape record, if necessary?
  300. if ($this->object->getSpgr()) {
  301. $recVer = 0x1;
  302. $recInstance = 0x0000;
  303. $recType = 0xF009;
  304. $length = 0x00000010;
  305. $recVerInstance = $recVer;
  306. $recVerInstance |= $recInstance << 4;
  307. $header = pack('vvV', $recVerInstance, $recType, $length);
  308. $data .= $header . pack('VVVV', 0, 0, 0, 0);
  309. }
  310. $this->spTypes[] = ($this->object->getSpType());
  311. // write the shape record
  312. $recVer = 0x2;
  313. $recInstance = $this->object->getSpType(); // shape type
  314. $recType = 0xF00A;
  315. $length = 0x00000008;
  316. $recVerInstance = $recVer;
  317. $recVerInstance |= $recInstance << 4;
  318. $header = pack('vvV', $recVerInstance, $recType, $length);
  319. $data .= $header . pack('VV', $this->object->getSpId(), $this->object->getSpgr() ? 0x0005 : 0x0A00);
  320. // the options
  321. if ($this->object->getOPTCollection()) {
  322. $optData = '';
  323. $recVer = 0x3;
  324. $recInstance = count($this->object->getOPTCollection());
  325. $recType = 0xF00B;
  326. foreach ($this->object->getOPTCollection() as $property => $value) {
  327. $optData .= pack('vV', $property, $value);
  328. }
  329. $length = strlen($optData);
  330. $recVerInstance = $recVer;
  331. $recVerInstance |= $recInstance << 4;
  332. $header = pack('vvV', $recVerInstance, $recType, $length);
  333. $data .= $header . $optData;
  334. }
  335. // the client anchor
  336. if ($this->object->getStartCoordinates()) {
  337. $clientAnchorData = '';
  338. $recVer = 0x0;
  339. $recInstance = 0x0;
  340. $recType = 0xF010;
  341. // start coordinates
  342. list($column, $row) = PHPExcel_Cell::coordinateFromString($this->object->getStartCoordinates());
  343. $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1;
  344. $r1 = $row - 1;
  345. // start offsetX
  346. $startOffsetX = $this->object->getStartOffsetX();
  347. // start offsetY
  348. $startOffsetY = $this->object->getStartOffsetY();
  349. // end coordinates
  350. list($column, $row) = PHPExcel_Cell::coordinateFromString($this->object->getEndCoordinates());
  351. $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1;
  352. $r2 = $row - 1;
  353. // end offsetX
  354. $endOffsetX = $this->object->getEndOffsetX();
  355. // end offsetY
  356. $endOffsetY = $this->object->getEndOffsetY();
  357. $clientAnchorData = pack('vvvvvvvvv', $this->object->getSpFlag(), $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY);
  358. $length = strlen($clientAnchorData);
  359. $recVerInstance = $recVer;
  360. $recVerInstance |= $recInstance << 4;
  361. $header = pack('vvV', $recVerInstance, $recType, $length);
  362. $data .= $header . $clientAnchorData;
  363. }
  364. // the client data, just empty for now
  365. if (!$this->object->getSpgr()) {
  366. $clientDataData = '';
  367. $recVer = 0x0;
  368. $recInstance = 0x0;
  369. $recType = 0xF011;
  370. $length = strlen($clientDataData);
  371. $recVerInstance = $recVer;
  372. $recVerInstance |= $recInstance << 4;
  373. $header = pack('vvV', $recVerInstance, $recType, $length);
  374. $data .= $header . $clientDataData;
  375. }
  376. // write the record
  377. $recVer = 0xF;
  378. $recInstance = 0x0000;
  379. $recType = 0xF004;
  380. $length = strlen($data);
  381. $recVerInstance = $recVer;
  382. $recVerInstance |= $recInstance << 4;
  383. $header = pack('vvV', $recVerInstance, $recType, $length);
  384. $this->data = $header . $data;
  385. break;
  386. }
  387. return $this->data;
  388. }
  389. /**
  390. * Gets the shape offsets
  391. *
  392. * @return array
  393. */
  394. public function getSpOffsets()
  395. {
  396. return $this->spOffsets;
  397. }
  398. /**
  399. * Gets the shape types
  400. *
  401. * @return array
  402. */
  403. public function getSpTypes()
  404. {
  405. return $this->spTypes;
  406. }
  407. }