PHPExcel_Reader_Excel5
[ class tree: PHPExcel_Reader_Excel5 ] [ index: PHPExcel_Reader_Excel5 ] [ all elements ]

Source for file Escher.php

Documentation is available at Escher.php

  1. <?php
  2. /**
  3.  * PHPExcel
  4.  *
  5.  * Copyright (c) 2006 - 2009 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_Reader_Excel5
  23.  * @copyright  Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  24.  * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  25.  * @version    1.7.0, 2009-08-10
  26.  */
  27.  
  28. /** PHPExcel root directory */
  29. if (!defined('PHPEXCEL_ROOT')) {
  30.     /**
  31.      * @ignore
  32.      */
  33.     define('PHPEXCEL_ROOT'dirname(__FILE__'/../../../');
  34. }
  35.  
  36. /** PHPExcel_Cell */
  37. require_once PHPEXCEL_ROOT 'PHPExcel/Cell.php';
  38.  
  39. /** PHPExcel_Shared_Escher_DggContainer */
  40. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DggContainer.php';
  41.  
  42. /** PHPExcel_Shared_Escher_DggContainer_BstoreContainer */
  43. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php';
  44.  
  45. /** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE */
  46. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php';
  47.  
  48. /** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip */
  49. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php';
  50.  
  51. /** PHPExcel_Shared_Escher_DgContainer */
  52. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DgContainer.php';
  53.  
  54. /** PHPExcel_Shared_Escher_DgContainer_SpgrContainer */
  55. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php';
  56.  
  57. /** PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer */
  58. require_once PHPEXCEL_ROOT 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php';
  59.  
  60. /**
  61.  * PHPExcel_Reader_Excel5_Escher
  62.  *
  63.  * @category   PHPExcel
  64.  * @package    PHPExcel_Reader_Excel5
  65.  * @copyright  Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  66.  */
  67. {
  68.     const DGGCONTAINER        0xF000;
  69.     const BSTORECONTAINER    0xF001;
  70.     const DGCONTAINER        0xF002;
  71.     const SPGRCONTAINER        0xF003;
  72.     const SPCONTAINER        0xF004;
  73.     const DGG                0xF006;
  74.     const BSE                0xF007;
  75.     const DG                0xF008;
  76.     const SPGR                0xF009;
  77.     const SP                0xF00A;
  78.     const OPT                0xF00B;
  79.     const CLIENTTEXTBOX        0xF00D;
  80.     const CLIENTANCHOR        0xF010;
  81.     const CLIENTDATA        0xF011;
  82.     const BLIPJPEG            0xF01D;
  83.     const BLIPPNG            0xF01E;
  84.     const SPLITMENUCOLORS    0xF11E;
  85.     const TERTIARYOPT        0xF122;
  86.  
  87.     /**
  88.      * Escher stream data (binary)
  89.      *
  90.      * @var string 
  91.      */
  92.     private $_data;
  93.  
  94.     /**
  95.      * Size in bytes of the Escher stream data
  96.      *
  97.      * @var int 
  98.      */
  99.     private $_dataSize;
  100.  
  101.     /**
  102.      * Current position of stream pointer in Escher stream data
  103.      *
  104.      * @var int 
  105.      */
  106.     private $_pos;
  107.  
  108.     /**
  109.      * The object to be returned by the reader. Modified during load.
  110.      *
  111.      * @var mixed 
  112.      */
  113.     private $_object;
  114.  
  115.     /**
  116.      * Create a new PHPExcel_Reader_Excel5_Escher instance
  117.      *
  118.      * @param mixed $object 
  119.      */
  120.     public function __construct($object)
  121.     {
  122.         $this->_object = $object;
  123.     }
  124.     
  125.     /**
  126.      * Load Escher stream data. May be a partial Escher stream.
  127.      *
  128.      * @param string $data 
  129.      */
  130.     public function load($data)
  131.     {
  132.         $this->_data = $data;
  133.  
  134.         // total byte size of Excel data (workbook global substream + sheet substreams)
  135.         $this->_dataSize = strlen($this->_data);
  136.  
  137.         $this->_pos = 0;
  138.         
  139.         // Parse Escher stream
  140.         while ($this->_pos < $this->_dataSize{
  141.             
  142.             
  143.             // offset: 2; size: 2: Record Type
  144.             $fbt $this->_GetInt2d($this->_data$this->_pos + 2);
  145.             
  146.             switch ($fbt{
  147.                 case self::DGGCONTAINER:    $this->_readDggContainer();        break;
  148.                 case self::DGG:                $this->_readDgg();                break;
  149.                 case self::BSTORECONTAINER:    $this->_readBstoreContainer();    break;
  150.                 case self::BSE:                $this->_readBSE();                break;
  151.                 case self::BLIPJPEG:        $this->_readBlipJPEG();            break;
  152.                 case self::BLIPPNG:            $this->_readBlipPNG();            break;
  153.                 case self::OPT:                $this->_readOPT();                break;
  154.                 case self::TERTIARYOPT:        $this->_readTertiaryOPT();        break;
  155.                 case self::SPLITMENUCOLORS:    $this->_readSplitMenuColors();    break;
  156.                 case self::DGCONTAINER:        $this->_readDgContainer();        break;
  157.                 case self::DG:                $this->_readDg();                break;
  158.                 case self::SPGRCONTAINER:    $this->_readSpgrContainer();    break;
  159.                 case self::SPCONTAINER:        $this->_readSpContainer();        break;
  160.                 case self::SPGR:            $this->_readSpgr();                break;
  161.                 case self::SP:                $this->_readSp();                break;
  162.                 case self::CLIENTTEXTBOX:    $this->_readClientTextbox();    break;
  163.                 case self::CLIENTANCHOR:    $this->_readClientAnchor();        break;
  164.                 case self::CLIENTDATA:        $this->_readClientData();        break;
  165.                 default:                    $this->_readDefault();            break;
  166.             }
  167.         }
  168.         
  169.         return $this->_object;
  170.     }
  171.  
  172.     /**
  173.      * Read a generic record
  174.      */
  175.     private function _readDefault()
  176.     {
  177.         // offset 0; size: 2; recVer and recInstance
  178.         $verInstance $this->_GetInt2d($this->_data$this->_pos);
  179.         
  180.         // offset: 2; size: 2: Record Type
  181.         $fbt $this->_GetInt2d($this->_data$this->_pos + 2);
  182.  
  183.         // bit: 0-3; mask: 0x000F; recVer
  184.         $recVer (0x000F $verInstance>> 0;
  185.         
  186.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  187.         $recordData substr($this->_data$this->_pos + 8$length);
  188.         
  189.         // move stream pointer to next record
  190.         $this->_pos += $length;
  191.     }
  192.  
  193.     /**
  194.      * Read DggContainer record (Drawing Group Container)
  195.      */
  196.     private function _readDggContainer()
  197.     {
  198.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  199.         $recordData substr($this->_data$this->_pos + 8$length);
  200.  
  201.         // move stream pointer to next record
  202.         $this->_pos += $length;
  203.  
  204.         // record is a container, read contents
  205.         $dggContainer new PHPExcel_Shared_Escher_DggContainer();
  206.         $this->_object->setDggContainer($dggContainer);
  207.         $reader new PHPExcel_Reader_Excel5_Escher($dggContainer);
  208.         $reader->load($recordData);
  209.     }
  210.  
  211.     /**
  212.      * Read Dgg record (Drawing Group)
  213.      */
  214.     private function _readDgg()
  215.     {
  216.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  217.         $recordData substr($this->_data$this->_pos + 8$length);
  218.         
  219.         // move stream pointer to next record
  220.         $this->_pos += $length;
  221.     }
  222.  
  223.     /**
  224.      * Read BstoreContainer record (Blip Store Container)
  225.      */
  226.     private function _readBstoreContainer()
  227.     {
  228.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  229.         $recordData substr($this->_data$this->_pos + 8$length);
  230.  
  231.         // move stream pointer to next record
  232.         $this->_pos += $length;
  233.  
  234.         // record is a container, read contents
  235.         $bstoreContainer new PHPExcel_Shared_Escher_DggContainer_BstoreContainer();
  236.         $this->_object->setBstoreContainer($bstoreContainer);
  237.         $reader new PHPExcel_Reader_Excel5_Escher($bstoreContainer);
  238.         $reader->load($recordData);
  239.     }
  240.  
  241.     /**
  242.      * Read BSE record
  243.      */
  244.     private function _readBSE()
  245.     {
  246.         // offset: 0; size: 2; recVer and recInstance
  247.         
  248.         // bit: 4-15; mask: 0xFFF0; recInstance
  249.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  250.  
  251.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  252.         $recordData substr($this->_data$this->_pos + 8$length);
  253.         
  254.         // move stream pointer to next record
  255.         $this->_pos += $length;
  256.         
  257.         // add BSE to BstoreContainer
  258.         $this->_object->addBSE($BSE);
  259.  
  260.         $BSE->setBLIPType($recInstance);
  261.         
  262.         // offset: 0; size: 1; btWin32 (MSOBLIPTYPE)
  263.         $btWin32 ord($recordData[0]);
  264.  
  265.         // offset: 1; size: 1; btWin32 (MSOBLIPTYPE)
  266.         $btMacOS ord($recordData[1]);
  267.  
  268.         // offset: 2; size: 16; MD4 digest
  269.         $rgbUid substr($recordData216);
  270.  
  271.         // offset: 18; size: 2; tag
  272.         $tag $this->_GetInt2d($recordData18);
  273.  
  274.         // offset: 20; size: 4; size of BLIP in bytes
  275.         $size $this->_GetInt4d($recordData20);
  276.  
  277.         // offset: 24; size: 4; number of references to this BLIP
  278.         $cRef $this->_GetInt4d($recordData24);
  279.  
  280.         // offset: 28; size: 4; MSOFO file offset
  281.         $foDelay $this->_GetInt4d($recordData28);
  282.  
  283.         // offset: 32; size: 1; unused1
  284.         $unused1 ord($recordData{32});
  285.  
  286.         // offset: 33; size: 1; size of nameData in bytes (including null terminator)
  287.         $cbName ord($recordData{33});
  288.  
  289.         // offset: 34; size: 1; unused2
  290.         $unused2 ord($recordData{34});
  291.  
  292.         // offset: 35; size: 1; unused3
  293.         $unused3 ord($recordData{35});
  294.  
  295.         // offset: 36; size: $cbName; nameData
  296.         $nameData substr($recordData36$cbName);
  297.  
  298.         // offset: 36 + $cbName, size: var; the BLIP data
  299.         $blipData substr($recordData36 $cbName);
  300.  
  301.         // record is a container, read contents
  302.         $reader new PHPExcel_Reader_Excel5_Escher($BSE);
  303.         $reader->load($blipData);
  304.     }
  305.  
  306.     /**
  307.      * Read BlipJPEG record. Holds raw JPEG image data
  308.      */
  309.     private function _readBlipJPEG()
  310.     {
  311.         // offset: 0; size: 2; recVer and recInstance
  312.         
  313.         // bit: 4-15; mask: 0xFFF0; recInstance
  314.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  315.  
  316.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  317.         $recordData substr($this->_data$this->_pos + 8$length);
  318.         
  319.         // move stream pointer to next record
  320.         $this->_pos += $length;
  321.         
  322.         $pos 0;
  323.         
  324.         // offset: 0; size: 16; rgbUid1 (MD4 digest of)
  325.         $rgbUid1 substr($recordData016);
  326.         $pos += 16;
  327.         
  328.         // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
  329.         if (in_array($recInstancearray(0x046B0x06E3))) {
  330.             $rgbUid2 substr($recordData1616);
  331.             $pos += 16;
  332.         }
  333.         
  334.         // offset: var; size: 1; tag
  335.         $tag ord($recordData{$pos});
  336.         $pos += 1;
  337.         
  338.         // offset: var; size: var; the raw image data
  339.         $data substr($recordData$pos);
  340.         
  341.         $blip->setData($data);
  342.         
  343.         $this->_object->setBlip($blip);
  344.     }
  345.  
  346.     /**
  347.      * Read BlipPNG record. Holds raw PNG image data
  348.      */
  349.     private function _readBlipPNG()
  350.     {
  351.         // offset: 0; size: 2; recVer and recInstance
  352.         
  353.         // bit: 4-15; mask: 0xFFF0; recInstance
  354.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  355.  
  356.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  357.         $recordData substr($this->_data$this->_pos + 8$length);
  358.         
  359.         // move stream pointer to next record
  360.         $this->_pos += $length;
  361.         
  362.         $pos 0;
  363.         
  364.         // offset: 0; size: 16; rgbUid1 (MD4 digest of)
  365.         $rgbUid1 substr($recordData016);
  366.         $pos += 16;
  367.         
  368.         // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
  369.         if ($recInstance == 0x06E1{
  370.             $rgbUid2 substr($recordData1616);
  371.             $pos += 16;
  372.         }
  373.         
  374.         // offset: var; size: 1; tag
  375.         $tag ord($recordData{$pos});
  376.         $pos += 1;
  377.         
  378.         // offset: var; size: var; the raw image data
  379.         $data substr($recordData$pos);
  380.         
  381.         $blip->setData($data);
  382.         
  383.         $this->_object->setBlip($blip);
  384.     }
  385.  
  386.     /**
  387.      * Read OPT record. This record may occur within DggContainer record or SpContainer
  388.      */
  389.     private function _readOPT()
  390.     {
  391.         // offset: 0; size: 2; recVer and recInstance
  392.         
  393.         // bit: 4-15; mask: 0xFFF0; recInstance
  394.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  395.  
  396.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  397.         $recordData substr($this->_data$this->_pos + 8$length);
  398.         
  399.         // move stream pointer to next record
  400.         $this->_pos += $length;
  401.  
  402.         $this->_readOfficeArtRGFOPTE($recordData$recInstance);
  403.     }
  404.  
  405.     /**
  406.      * Read TertiaryOPT record
  407.      */
  408.     private function _readTertiaryOPT()
  409.     {
  410.         // offset: 0; size: 2; recVer and recInstance
  411.         
  412.         // bit: 4-15; mask: 0xFFF0; recInstance
  413.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  414.  
  415.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  416.         $recordData substr($this->_data$this->_pos + 8$length);
  417.  
  418.         // move stream pointer to next record
  419.         $this->_pos += $length;
  420.     }
  421.  
  422.     /**
  423.      * Read SplitMenuColors record
  424.      */
  425.     private function _readSplitMenuColors()
  426.     {
  427.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  428.         $recordData substr($this->_data$this->_pos + 8$length);
  429.  
  430.         // move stream pointer to next record
  431.         $this->_pos += $length;
  432.     }
  433.  
  434.     /**
  435.      * Read DgContainer record (Drawing Container)
  436.      */
  437.     private function _readDgContainer()
  438.     {
  439.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  440.         $recordData substr($this->_data$this->_pos + 8$length);
  441.  
  442.         // move stream pointer to next record
  443.         $this->_pos += $length;
  444.  
  445.         // record is a container, read contents
  446.         $dgContainer new PHPExcel_Shared_Escher_DgContainer();
  447.         $this->_object->setDgContainer($dgContainer);
  448.         $reader new PHPExcel_Reader_Excel5_Escher($dgContainer);
  449.         $escher $reader->load($recordData);
  450.     }
  451.  
  452.     /**
  453.      * Read Dg record (Drawing)
  454.      */
  455.     private function _readDg()
  456.     {
  457.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  458.         $recordData substr($this->_data$this->_pos + 8$length);
  459.  
  460.         // move stream pointer to next record
  461.         $this->_pos += $length;
  462.     }
  463.  
  464.     /**
  465.      * Read SpgrContainer record (Shape Group Container)
  466.      */
  467.     private function _readSpgrContainer()
  468.     {
  469.         // context is either context DgContainer or SpgrContainer
  470.  
  471.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  472.         $recordData substr($this->_data$this->_pos + 8$length);
  473.  
  474.         // move stream pointer to next record
  475.         $this->_pos += $length;
  476.  
  477.         // record is a container, read contents
  478.         $spgrContainer new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
  479.  
  480.         if ($this->_object instanceof PHPExcel_Shared_Escher_DgContainer{
  481.             // DgContainer
  482.             $this->_object->setSpgrContainer($spgrContainer);
  483.         else {
  484.             // SpgrContainer
  485.             $this->_object->addChild($spgrContainer);
  486.         }
  487.  
  488.         $reader new PHPExcel_Reader_Excel5_Escher($spgrContainer);
  489.         $escher $reader->load($recordData);
  490.     }
  491.  
  492.     /**
  493.      * Read SpContainer record (Shape Container)
  494.      */
  495.     private function _readSpContainer()
  496.     {
  497.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  498.         $recordData substr($this->_data$this->_pos + 8$length);
  499.  
  500.         // add spContainer to spgrContainer
  501.         $spContainer new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
  502.         $this->_object->addChild($spContainer);
  503.  
  504.         // move stream pointer to next record
  505.         $this->_pos += $length;
  506.  
  507.         // record is a container, read contents
  508.         $reader new PHPExcel_Reader_Excel5_Escher($spContainer);
  509.         $escher $reader->load($recordData);
  510.     }
  511.  
  512.     /**
  513.      * Read Spgr record (Shape Group)
  514.      */
  515.     private function _readSpgr()
  516.     {
  517.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  518.         $recordData substr($this->_data$this->_pos + 8$length);
  519.  
  520.         // move stream pointer to next record
  521.         $this->_pos += $length;
  522.     }
  523.  
  524.     /**
  525.      * Read Sp record (Shape)
  526.      */
  527.     private function _readSp()
  528.     {
  529.         // offset: 0; size: 2; recVer and recInstance
  530.  
  531.         // bit: 4-15; mask: 0xFFF0; recInstance
  532.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  533.  
  534.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  535.         $recordData substr($this->_data$this->_pos + 8$length);
  536.  
  537.         // move stream pointer to next record
  538.         $this->_pos += $length;
  539.     }
  540.  
  541.     /**
  542.      * Read ClientTextbox record
  543.      */
  544.     private function _readClientTextbox()
  545.     {
  546.         // offset: 0; size: 2; recVer and recInstance
  547.  
  548.         // bit: 4-15; mask: 0xFFF0; recInstance
  549.         $recInstance (0xFFF0 $this->_GetInt2d($this->_data$this->_pos)) >> 4;
  550.  
  551.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  552.         $recordData substr($this->_data$this->_pos + 8$length);
  553.  
  554.         // move stream pointer to next record
  555.         $this->_pos += $length;
  556.     }
  557.  
  558.     /**
  559.      * Read ClientAnchor record. This record holds information about where the shape is anchored in worksheet
  560.      */
  561.     private function _readClientAnchor()
  562.     {
  563.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  564.         $recordData substr($this->_data$this->_pos + 8$length);
  565.         
  566.         // move stream pointer to next record
  567.         $this->_pos += $length;
  568.         
  569.         // offset: 2; size: 2; upper-left corner column index (0-based)
  570.         $c1 $this->_GetInt2d($recordData2);
  571.  
  572.         // offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width
  573.         $startOffsetX $this->_GetInt2d($recordData4);
  574.  
  575.         // offset: 6; size: 2; upper-left corner row index (0-based)
  576.         $r1 $this->_GetInt2d($recordData6);
  577.  
  578.         // offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height
  579.         $startOffsetY $this->_GetInt2d($recordData8);
  580.  
  581.         // offset: 10; size: 2; bottom-right corner column index (0-based)
  582.         $c2 $this->_GetInt2d($recordData10);
  583.  
  584.         // offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width
  585.         $endOffsetX $this->_GetInt2d($recordData12);
  586.  
  587.         // offset: 14; size: 2; bottom-right corner row index (0-based)
  588.         $r2 $this->_GetInt2d($recordData14);
  589.  
  590.         // offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height
  591.         $endOffsetY $this->_GetInt2d($recordData16);
  592.  
  593.         // set the start coordinates
  594.         $this->_object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1($r1 1));
  595.  
  596.         // set the start offsetX
  597.         $this->_object->setStartOffsetX($startOffsetX);
  598.  
  599.         // set the start offsetY
  600.         $this->_object->setStartOffsetY($startOffsetY);
  601.  
  602.         // set the end coordinates
  603.         $this->_object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2($r2 1));
  604.  
  605.         // set the end offsetX
  606.         $this->_object->setEndOffsetX($endOffsetX);
  607.  
  608.         // set the end offsetY
  609.         $this->_object->setEndOffsetY($endOffsetY);
  610.     }
  611.  
  612.     /**
  613.      * Read ClientData record
  614.      */
  615.     private function _readClientData()
  616.     {
  617.         $length $this->_GetInt4d($this->_data$this->_pos + 4);
  618.         $recordData substr($this->_data$this->_pos + 8$length);
  619.  
  620.         // move stream pointer to next record
  621.         $this->_pos += $length;
  622.     }
  623.  
  624.     /**
  625.      * Read OfficeArtRGFOPTE table of property-value pairs
  626.      *
  627.      * @param string $data Binary data
  628.      * @param int $n Number of properties
  629.      */
  630.     private function _readOfficeArtRGFOPTE($data$n{
  631.  
  632.         $splicedComplexData substr($data$n);
  633.  
  634.         // loop through property-value pairs
  635.         for ($i 0$i $n++$i{
  636.             // read 6 bytes at a time
  637.             $fopte substr($data$i6);
  638.  
  639.             // offset: 0; size: 2; opid
  640.             $opid $this->_GetInt2d($fopte0);
  641.  
  642.             // bit: 0-13; mask: 0x3FFF; opid.opid
  643.             $opidOpid (0x3FFF $opid>> 0;
  644.  
  645.             // bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier
  646.             $opidFBid (0x4000 $opid>> 14;
  647.  
  648.             // bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data
  649.             $opidFComplex (0x8000 $opid>> 15;
  650.  
  651.             // offset: 2; size: 4; the value for this property
  652.             $op $this->_GetInt4d($fopte2);
  653.  
  654.             if ($opidFComplex{
  655.                 $complexData substr($splicedComplexData0$op);
  656.                 $splicedComplexData substr($splicedComplexData$op);
  657.  
  658.                 // we store string value with complex data
  659.                 $value $complexData;
  660.             else {
  661.                 // we store integer value
  662.                 $value $op;
  663.             }
  664.  
  665.             $this->_object->setOPT($opidOpid$value);
  666.         }
  667.     }
  668.  
  669.     /**
  670.      * Read 16-bit unsigned integer
  671.      *
  672.      * @param string $data 
  673.      * @param int $pos 
  674.      * @return int 
  675.      */
  676.     private function _GetInt2d($data$pos)
  677.     {
  678.         return ord($data[$pos](ord($data[$pos 1]<< 8);
  679.     }
  680.  
  681.     /**
  682.      * Read 32-bit signed integer
  683.      *
  684.      * @param string $data 
  685.      * @param int $pos 
  686.      * @return int 
  687.      */
  688.     private function _GetInt4d($data$pos)
  689.     {
  690.         //return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) |
  691.         //    (ord($data[$pos + 2]) << 16) | (ord($data[$pos + 3]) << 24);
  692.  
  693.         // FIX: represent numbers correctly on 64-bit system
  694.         // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
  695.         $_or_24 ord($data[$pos 3]);
  696.         if ($_or_24 >= 128{
  697.             // negative number
  698.             $_ord_24 = -abs((256 $_or_24<< 24);
  699.         else {
  700.             $_ord_24 ($_or_24 127<< 24;
  701.         }
  702.         return ord($data[$pos](ord($data[$pos 1]<< 8(ord($data[$pos 2]<< 16$_ord_24;
  703.     }
  704.  
  705. }

Documentation generated on Mon, 10 Aug 2009 08:03:30 +0200 by phpDocumentor 1.4.1