mirror of
https://github.com/Karaka-Management/Resources.git
synced 2026-01-11 13:28:40 +00:00
3473 lines
146 KiB
PHP
3473 lines
146 KiB
PHP
<?php
|
|
/**
|
|
* This file is part of PHPPresentation - A pure PHP library for reading and writing
|
|
* presentations documents.
|
|
*
|
|
* PHPPresentation is free software distributed under the terms of the GNU Lesser
|
|
* General Public License version 3 as published by the Free Software Foundation.
|
|
*
|
|
* For the full copyright and license information, please read the LICENSE
|
|
* file that was distributed with this source code. For the full list of
|
|
* contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors.
|
|
*
|
|
* @link https://github.com/PHPOffice/PHPPresentation
|
|
* @copyright 2009-2015 PHPPresentation contributors
|
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
|
*/
|
|
|
|
namespace PhpOffice\PhpPresentation\Reader;
|
|
|
|
use PhpOffice\Common\Microsoft\OLERead;
|
|
use PhpOffice\Common\Text;
|
|
use PhpOffice\PhpPresentation\PhpPresentation;
|
|
use PhpOffice\PhpPresentation\AbstractShape;
|
|
use PhpOffice\PhpPresentation\Shape;
|
|
use PhpOffice\PhpPresentation\Shape\Drawing;
|
|
use PhpOffice\PhpPresentation\Shape\Group;
|
|
use PhpOffice\PhpPresentation\Shape\Hyperlink;
|
|
use PhpOffice\PhpPresentation\Shape\Line;
|
|
use PhpOffice\PhpPresentation\Shape\RichText;
|
|
use PhpOffice\PhpPresentation\Style\Alignment;
|
|
use PhpOffice\PhpPresentation\Style\Color;
|
|
use PhpOffice\PhpPresentation\Style\Bullet;
|
|
|
|
/**
|
|
* Serialized format reader
|
|
*/
|
|
class PowerPoint97 implements ReaderInterface
|
|
{
|
|
const OFFICEARTBLIPEMF = 0xF01A;
|
|
const OFFICEARTBLIPWMF = 0xF01B;
|
|
const OFFICEARTBLIPPICT = 0xF01C;
|
|
const OFFICEARTBLIPJPG = 0xF01D;
|
|
const OFFICEARTBLIPPNG = 0xF01E;
|
|
const OFFICEARTBLIPDIB = 0xF01F;
|
|
const OFFICEARTBLIPTIFF = 0xF029;
|
|
const OFFICEARTBLIPJPEG = 0xF02A;
|
|
|
|
/**
|
|
* @link http://msdn.microsoft.com/en-us/library/dd945336(v=office.12).aspx
|
|
*/
|
|
const RT_ANIMATIONINFO = 0x1014;
|
|
const RT_ANIMATIONINFOATOM = 0x0FF1;
|
|
const RT_BINARYTAGDATABLOB = 0x138B;
|
|
const RT_BLIPCOLLECTION9 = 0x07F8;
|
|
const RT_BLIPENTITY9ATOM = 0x07F9;
|
|
const RT_BOOKMARKCOLLECTION = 0x07E3;
|
|
const RT_BOOKMARKENTITYATOM = 0x0FD0;
|
|
const RT_BOOKMARKSEEDATOM = 0x07E9;
|
|
const RT_BROADCASTDOCINFO9 = 0x177E;
|
|
const RT_BROADCASTDOCINFO9ATOM = 0x177F;
|
|
const RT_BUILDATOM = 0x2B03;
|
|
const RT_BUILDLIST = 0x2B02;
|
|
const RT_CHARTBUILD = 0x2B04;
|
|
const RT_CHARTBUILDATOM = 0x2B05;
|
|
const RT_COLORSCHEMEATOM = 0x07F0;
|
|
const RT_COMMENT10 = 0x2EE0;
|
|
const RT_COMMENT10ATOM = 0x2EE1;
|
|
const RT_COMMENTINDEX10 = 0x2EE4;
|
|
const RT_COMMENTINDEX10ATOM = 0x2EE5;
|
|
const RT_CRYPTSESSION10CONTAINER = 0x2F14;
|
|
const RT_CURRENTUSERATOM = 0x0FF6;
|
|
const RT_CSTRING = 0x0FBA;
|
|
const RT_DATETIMEMETACHARATOM = 0x0FF7;
|
|
const RT_DEFAULTRULERATOM = 0x0FAB;
|
|
const RT_DOCROUTINGSLIPATOM = 0x0406;
|
|
const RT_DIAGRAMBUILD = 0x2B06;
|
|
const RT_DIAGRAMBUILDATOM = 0x2B07;
|
|
const RT_DIFF10 = 0x2EED;
|
|
const RT_DIFF10ATOM = 0x2EEE;
|
|
const RT_DIFFTREE10 = 0x2EEC;
|
|
const RT_DOCTOOLBARSTATES10ATOM = 0x36B1;
|
|
const RT_DOCUMENT = 0x03E8;
|
|
const RT_DOCUMENTATOM = 0x03E9;
|
|
const RT_DRAWING = 0x040C;
|
|
const RT_DRAWINGGROUP = 0x040B;
|
|
const RT_ENDDOCUMENTATOM = 0x03EA;
|
|
const RT_EXTERNALAVIMOVIE = 0x1006;
|
|
const RT_EXTERNALCDAUDIO = 0x100E;
|
|
const RT_EXTERNALCDAUDIOATOM = 0x1012;
|
|
const RT_EXTERNALHYPERLINK = 0x0FD7;
|
|
const RT_EXTERNALHYPERLINK9 = 0x0FE4;
|
|
const RT_EXTERNALHYPERLINKATOM = 0x0FD3;
|
|
const RT_EXTERNALHYPERLINKFLAGSATOM = 0x1018;
|
|
const RT_EXTERNALMCIMOVIE = 0x1007;
|
|
const RT_EXTERNALMEDIAATOM = 0x1004;
|
|
const RT_EXTERNALMIDIAUDIO = 0x100D;
|
|
const RT_EXTERNALOBJECTLIST = 0x0409;
|
|
const RT_EXTERNALOBJECTLISTATOM = 0x040A;
|
|
const RT_EXTERNALOBJECTREFATOM = 0x0BC1;
|
|
const RT_EXTERNALOLECONTROL = 0x0FEE;
|
|
const RT_EXTERNALOLECONTROLATOM = 0x0FFB;
|
|
const RT_EXTERNALOLEEMBED = 0x0FCC;
|
|
const RT_EXTERNALOLEEMBEDATOM = 0x0FCD;
|
|
const RT_EXTERNALOLELINK = 0x0FCE;
|
|
const RT_EXTERNALOLELINKATOM = 0x0FD1;
|
|
const RT_EXTERNALOLEOBJECTATOM = 0x0FC3;
|
|
const RT_EXTERNALOLEOBJECTSTG = 0x1011;
|
|
const RT_EXTERNALVIDEO = 0x1005;
|
|
const RT_EXTERNALWAVAUDIOEMBEDDED = 0x100F;
|
|
const RT_EXTERNALWAVAUDIOEMBEDDEDATOM = 0x1013;
|
|
const RT_EXTERNALWAVAUDIOLINK = 0x1010;
|
|
const RT_ENVELOPEDATA9ATOM = 0x1785;
|
|
const RT_ENVELOPEFLAGS9ATOM = 0x1784;
|
|
const RT_ENVIRONMENT = 0x03F2;
|
|
const RT_FONTCOLLECTION = 0x07D5;
|
|
const RT_FONTCOLLECTION10 = 0x07D6;
|
|
const RT_FONTEMBEDDATABLOB = 0x0FB8;
|
|
const RT_FONTEMBEDFLAGS10ATOM = 0x32C8;
|
|
const RT_FILTERPRIVACYFLAGS10ATOM = 0x36B0;
|
|
const RT_FONTENTITYATOM = 0x0FB7;
|
|
const RT_FOOTERMETACHARATOM = 0x0FFA;
|
|
const RT_GENERICDATEMETACHARATOM = 0x0FF8;
|
|
const RT_GRIDSPACING10ATOM = 0x040D;
|
|
const RT_GUIDEATOM = 0x03FB;
|
|
const RT_HANDOUT = 0x0FC9;
|
|
const RT_HASHCODEATOM = 0x2B00;
|
|
const RT_HEADERSFOOTERS = 0x0FD9;
|
|
const RT_HEADERSFOOTERSATOM = 0x0FDA;
|
|
const RT_HEADERMETACHARATOM = 0x0FF9;
|
|
const RT_HTMLDOCINFO9ATOM = 0x177B;
|
|
const RT_HTMLPUBLISHINFOATOM = 0x177C;
|
|
const RT_HTMLPUBLISHINFO9 = 0x177D;
|
|
const RT_INTERACTIVEINFO = 0x0FF2;
|
|
const RT_INTERACTIVEINFOATOM = 0x0FF3;
|
|
const RT_KINSOKU = 0x0FC8;
|
|
const RT_KINSOKUATOM = 0x0FD2;
|
|
const RT_LEVELINFOATOM = 0x2B0A;
|
|
const RT_LINKEDSHAPE10ATOM = 0x2EE6;
|
|
const RT_LINKEDSLIDE10ATOM = 0x2EE7;
|
|
const RT_LIST = 0x07D0;
|
|
const RT_MAINMASTER = 0x03F8;
|
|
const RT_MASTERTEXTPROPATOM = 0x0FA2;
|
|
const RT_METAFILE = 0x0FC1;
|
|
const RT_NAMEDSHOW = 0x0411;
|
|
const RT_NAMEDSHOWS = 0x0410;
|
|
const RT_NAMEDSHOWSLIDESATOM = 0x0412;
|
|
const RT_NORMALVIEWSETINFO9 = 0x0414;
|
|
const RT_NORMALVIEWSETINFO9ATOM = 0x0415;
|
|
const RT_NOTES= 0x03F0;
|
|
const RT_NOTESATOM = 0x03F1;
|
|
const RT_NOTESTEXTVIEWINFO9 = 0x0413;
|
|
const RT_OUTLINETEXTPROPS9 = 0x0FAE;
|
|
const RT_OUTLINETEXTPROPS10 = 0x0FB3;
|
|
const RT_OUTLINETEXTPROPS11 = 0x0FB5;
|
|
const RT_OUTLINETEXTPROPSHEADER9ATOM = 0x0FAF;
|
|
const RT_OUTLINETEXTREFATOM = 0x0F9E;
|
|
const RT_OUTLINEVIEWINFO = 0x0407;
|
|
const RT_PERSISTDIRECTORYATOM = 0x1772;
|
|
const RT_PARABUILD = 0x2B08;
|
|
const RT_PARABUILDATOM = 0x2B09;
|
|
const RT_PHOTOALBUMINFO10ATOM = 0x36B2;
|
|
const RT_PLACEHOLDERATOM = 0x0BC3;
|
|
const RT_PRESENTATIONADVISORFLAGS9ATOM = 0x177A;
|
|
const RT_PRINTOPTIONSATOM = 0x1770;
|
|
const RT_PROGBINARYTAG = 0x138A;
|
|
const RT_PROGSTRINGTAG = 0x1389;
|
|
const RT_PROGTAGS = 0x1388;
|
|
const RT_RECOLORINFOATOM = 0x0FE7;
|
|
const RT_RTFDATETIMEMETACHARATOM = 0x1015;
|
|
const RT_ROUNDTRIPANIMATIONATOM12ATOM = 0x2B0B;
|
|
const RT_ROUNDTRIPANIMATIONHASHATOM12ATOM = 0x2B0D;
|
|
const RT_ROUNDTRIPCOLORMAPPING12ATOM = 0x040F;
|
|
const RT_ROUNDTRIPCOMPOSITEMASTERID12ATOM = 0x041D;
|
|
const RT_ROUNDTRIPCONTENTMASTERID12ATOM = 0x0422;
|
|
const RT_ROUNDTRIPCONTENTMASTERINFO12ATOM = 0x041E;
|
|
const RT_ROUNDTRIPCUSTOMTABLESTYLES12ATOM = 0x0428;
|
|
const RT_ROUNDTRIPDOCFLAGS12ATOM = 0x0425;
|
|
const RT_ROUNDTRIPHEADERFOOTERDEFAULTS12ATOM = 0x0424;
|
|
const RT_ROUNDTRIPHFPLACEHOLDER12ATOM = 0x0420;
|
|
const RT_ROUNDTRIPNEWPLACEHOLDERID12ATOM = 0x0BDD;
|
|
const RT_ROUNDTRIPNOTESMASTERTEXTSTYLES12ATOM = 0x0427;
|
|
const RT_ROUNDTRIPOARTTEXTSTYLES12ATOM = 0x0423;
|
|
const RT_ROUNDTRIPORIGINALMAINMASTERID12ATOM = 0x041C;
|
|
const RT_ROUNDTRIPSHAPECHECKSUMFORCL12ATOM = 0x0426;
|
|
const RT_ROUNDTRIPSHAPEID12ATOM = 0x041F;
|
|
const RT_ROUNDTRIPSLIDESYNCINFO12 = 0x3714;
|
|
const RT_ROUNDTRIPSLIDESYNCINFOATOM12 = 0x3715;
|
|
const RT_ROUNDTRIPTHEME12ATOM = 0x040E;
|
|
const RT_SHAPEATOM = 0x0BDB;
|
|
const RT_SHAPEFLAGS10ATOM = 0x0BDC;
|
|
const RT_SLIDE = 0x03EE;
|
|
const RT_SLIDEATOM = 0x03EF;
|
|
const RT_SLIDEFLAGS10ATOM = 0x2EEA;
|
|
const RT_SLIDELISTENTRY10ATOM = 0x2EF0;
|
|
const RT_SLIDELISTTABLE10 = 0x2EF1;
|
|
const RT_SLIDELISTWITHTEXT = 0x0FF0;
|
|
const RT_SLIDELISTTABLESIZE10ATOM = 0x2EEF;
|
|
const RT_SLIDENUMBERMETACHARATOM = 0x0FD8;
|
|
const RT_SLIDEPERSISTATOM = 0x03F3;
|
|
const RT_SLIDESHOWDOCINFOATOM = 0x0401;
|
|
const RT_SLIDESHOWSLIDEINFOATOM = 0x03F9;
|
|
const RT_SLIDETIME10ATOM = 0x2EEB;
|
|
const RT_SLIDEVIEWINFO = 0x03FA;
|
|
const RT_SLIDEVIEWINFOATOM = 0x03FE;
|
|
const RT_SMARTTAGSTORE11CONTAINER = 0x36B3;
|
|
const RT_SOUND = 0x07E6;
|
|
const RT_SOUNDCOLLECTION = 0x07E4;
|
|
const RT_SOUNDCOLLECTIONATOM = 0x07E5;
|
|
const RT_SOUNDDATABLOB = 0x07E7;
|
|
const RT_SORTERVIEWINFO = 0x0408;
|
|
const RT_STYLETEXTPROPATOM = 0x0FA1;
|
|
const RT_STYLETEXTPROP10ATOM = 0x0FB1;
|
|
const RT_STYLETEXTPROP11ATOM = 0x0FB6;
|
|
const RT_STYLETEXTPROP9ATOM = 0x0FAC;
|
|
const RT_SUMMARY = 0x0402;
|
|
const RT_TEXTBOOKMARKATOM = 0x0FA7;
|
|
const RT_TEXTBYTESATOM = 0x0FA8;
|
|
const RT_TEXTCHARFORMATEXCEPTIONATOM = 0x0FA4;
|
|
const RT_TEXTCHARSATOM = 0x0FA0;
|
|
const RT_TEXTDEFAULTS10ATOM = 0x0FB4;
|
|
const RT_TEXTDEFAULTS9ATOM = 0x0FB0;
|
|
const RT_TEXTHEADERATOM = 0x0F9F;
|
|
const RT_TEXTINTERACTIVEINFOATOM = 0x0FDF;
|
|
const RT_TEXTMASTERSTYLEATOM = 0x0FA3;
|
|
const RT_TEXTMASTERSTYLE10ATOM = 0x0FB2;
|
|
const RT_TEXTMASTERSTYLE9ATOM = 0x0FAD;
|
|
const RT_TEXTPARAGRAPHFORMATEXCEPTIONATOM = 0x0FA5;
|
|
const RT_TEXTRULERATOM = 0x0FA6;
|
|
const RT_TEXTSPECIALINFOATOM = 0x0FAA;
|
|
const RT_TEXTSPECIALINFODEFAULTATOM = 0x0FA9;
|
|
const RT_TIMEANIMATEBEHAVIOR = 0xF134;
|
|
const RT_TIMEANIMATEBEHAVIORCONTAINER = 0xF12B;
|
|
const RT_TIMEANIMATIONVALUE = 0xF143;
|
|
const RT_TIMEANIMATIONVALUELIST = 0xF13F;
|
|
const RT_TIMEBEHAVIOR = 0xF133;
|
|
const RT_TIMEBEHAVIORCONTAINER = 0xF12A;
|
|
const RT_TIMECOLORBEHAVIOR = 0xF135;
|
|
const RT_TIMECOLORBEHAVIORCONTAINER = 0xF12C;
|
|
const RT_TIMECLIENTVISUALELEMENT = 0xF13C;
|
|
const RT_TIMECOMMANDBEHAVIOR = 0xF13B;
|
|
const RT_TIMECOMMANDBEHAVIORCONTAINER = 0xF132;
|
|
const RT_TIMECONDITION = 0xF128;
|
|
const RT_TIMECONDITIONCONTAINER = 0xF125;
|
|
const RT_TIMEEFFECTBEHAVIOR = 0xF136;
|
|
const RT_TIMEEFFECTBEHAVIORCONTAINER = 0xF12D;
|
|
const RT_TIMEEXTTIMENODECONTAINER = 0xF144;
|
|
const RT_TIMEITERATEDATA = 0xF140;
|
|
const RT_TIMEMODIFIER = 0xF129;
|
|
const RT_TIMEMOTIONBEHAVIOR = 0xF137;
|
|
const RT_TIMEMOTIONBEHAVIORCONTAINER = 0xF12E;
|
|
const RT_TIMENODE = 0xF127;
|
|
const RT_TIMEPROPERTYLIST = 0xF13D;
|
|
const RT_TIMEROTATIONBEHAVIOR = 0xF138;
|
|
const RT_TIMEROTATIONBEHAVIORCONTAINER = 0xF12F;
|
|
const RT_TIMESCALEBEHAVIOR = 0xF139;
|
|
const RT_TIMESCALEBEHAVIORCONTAINER = 0xF130;
|
|
const RT_TIMESEQUENCEDATA = 0xF141;
|
|
const RT_TIMESETBEHAVIOR = 0xF13A;
|
|
const RT_TIMESETBEHAVIORCONTAINER = 0xF131;
|
|
const RT_TIMESUBEFFECTCONTAINER = 0xF145;
|
|
const RT_TIMEVARIANT = 0xF142;
|
|
const RT_TIMEVARIANTLIST = 0xF13E;
|
|
const RT_USEREDITATOM = 0x0FF5;
|
|
const RT_VBAINFO = 0x03FF;
|
|
const RT_VBAINFOATOM = 0x0400;
|
|
const RT_VIEWINFOATOM = 0x03FD;
|
|
const RT_VISUALPAGEATOM = 0x2B01;
|
|
const RT_VISUALSHAPEATOM = 0x2AFB;
|
|
|
|
/**
|
|
* @var http://msdn.microsoft.com/en-us/library/dd926394(v=office.12).aspx
|
|
*/
|
|
const SL_BIGOBJECT = 0x0000000F;
|
|
const SL_BLANK = 0x00000010;
|
|
const SL_COLUMNTWOROWS = 0x0000000A;
|
|
const SL_FOUROBJECTS = 0x0000000E;
|
|
const SL_MASTERTITLE = 0x00000002;
|
|
const SL_TITLEBODY = 0x00000001;
|
|
const SL_TITLEONLY = 0x00000007;
|
|
const SL_TITLESLIDE = 0x00000000;
|
|
const SL_TWOCOLUMNS = 0x00000008;
|
|
const SL_TWOCOLUMNSROW = 0x0000000D;
|
|
const SL_TWOROWS = 0x00000009;
|
|
const SL_TWOROWSCOLUMN = 0x0000000B;
|
|
const SL_VERTICALTITLEBODY = 0x00000011;
|
|
const SL_VERTICALTWOROWS = 0x00000012;
|
|
|
|
/**
|
|
* Array with Fonts
|
|
*/
|
|
private $arrayFonts = array();
|
|
/**
|
|
* Array with Hyperlinks
|
|
*/
|
|
private $arrayHyperlinks = array();
|
|
/**
|
|
* Array with Notes
|
|
*/
|
|
private $arrayNotes = array();
|
|
/**
|
|
* Array with Pictures
|
|
*/
|
|
private $arrayPictures = array();
|
|
/**
|
|
* Offset (in bytes) from the beginning of the PowerPoint Document Stream to the UserEditAtom record for the most recent user edit.
|
|
* @var int
|
|
*/
|
|
private $offsetToCurrentEdit;
|
|
/**
|
|
* A structure that specifies a compressed table of sequential persist object identifiers and stream offsets to associated persist objects.
|
|
* @var int[]
|
|
*/
|
|
private $rgPersistDirEntry;
|
|
/**
|
|
* Offset (in bytes) from the beginning of the PowerPoint Document Stream to the PersistDirectoryAtom record for this user edit
|
|
* @var int
|
|
*/
|
|
private $offsetPersistDirectory;
|
|
/**
|
|
* Output Object
|
|
* @var PhpPresentation
|
|
*/
|
|
private $oPhpPresentation;
|
|
/**
|
|
* Group Object
|
|
* @var Group
|
|
*/
|
|
private $oCurrentGroup;
|
|
/**
|
|
* @var boolean
|
|
*/
|
|
private $bFirstShapeGroup = false;
|
|
/**
|
|
* Stream "Powerpoint Document"
|
|
* @var string
|
|
*/
|
|
private $streamPowerpointDocument;
|
|
/**
|
|
* Stream "Current User"
|
|
* @var string
|
|
*/
|
|
private $streamCurrentUser;
|
|
/**
|
|
* Stream "Summary Information"
|
|
* @var string
|
|
*/
|
|
private $streamSummaryInformation;
|
|
/**
|
|
* Stream "Document Summary Information"
|
|
* @var string
|
|
*/
|
|
private $streamDocumentSummaryInformation;
|
|
/**
|
|
* Stream "Pictures"
|
|
* @var string
|
|
*/
|
|
private $streamPictures;
|
|
/**
|
|
* @var integer
|
|
*/
|
|
private $inMainType;
|
|
/**
|
|
* @var integer
|
|
*/
|
|
private $currentNote;
|
|
|
|
/**
|
|
* Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file?
|
|
*
|
|
* @param string $pFilename
|
|
* @throws \Exception
|
|
* @return boolean
|
|
*/
|
|
public function canRead($pFilename)
|
|
{
|
|
return $this->fileSupportsUnserializePhpPresentation($pFilename);
|
|
}
|
|
|
|
/**
|
|
* Does a file support UnserializePhpPresentation ?
|
|
*
|
|
* @param string $pFilename
|
|
* @throws \Exception
|
|
* @return boolean
|
|
*/
|
|
public function fileSupportsUnserializePhpPresentation($pFilename = '')
|
|
{
|
|
// Check if file exists
|
|
if (!file_exists($pFilename)) {
|
|
throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
|
}
|
|
|
|
try {
|
|
// Use ParseXL for the hard work.
|
|
$ole = new OLERead();
|
|
// get excel data
|
|
$ole->read($pFilename);
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads PhpPresentation Serialized file
|
|
*
|
|
* @param string $pFilename
|
|
* @return \PhpOffice\PhpPresentation\PhpPresentation
|
|
* @throws \Exception
|
|
*/
|
|
public function load($pFilename)
|
|
{
|
|
// Unserialize... First make sure the file supports it!
|
|
if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) {
|
|
throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\PowerPoint97: " . $pFilename . ".");
|
|
}
|
|
|
|
return $this->loadFile($pFilename);
|
|
}
|
|
|
|
/**
|
|
* Load PhpPresentation Serialized file
|
|
*
|
|
* @param string $pFilename
|
|
* @return \PhpOffice\PhpPresentation\PhpPresentation
|
|
* @throws \Exception
|
|
*/
|
|
private function loadFile($pFilename)
|
|
{
|
|
$this->oPhpPresentation = new PhpPresentation();
|
|
$this->oPhpPresentation->removeSlideByIndex();
|
|
|
|
// Read OLE Blocks
|
|
$this->loadOLE($pFilename);
|
|
// Read pictures in the Pictures Stream
|
|
$this->loadPicturesStream();
|
|
// Read information in the Current User Stream
|
|
$this->loadCurrentUserStream();
|
|
// Read information in the PowerPoint Document Stream
|
|
$this->loadPowerpointDocumentStream();
|
|
|
|
return $this->oPhpPresentation;
|
|
}
|
|
|
|
/**
|
|
* Read OLE Part
|
|
* @param string $pFilename
|
|
* @throws \Exception
|
|
*/
|
|
private function loadOLE($pFilename)
|
|
{
|
|
// OLE reader
|
|
$oOLE = new OLERead();
|
|
$oOLE->read($pFilename);
|
|
|
|
// PowerPoint Document Stream
|
|
$this->streamPowerpointDocument = $oOLE->getStream($oOLE->powerpointDocument);
|
|
|
|
// Current User Stream
|
|
$this->streamCurrentUser = $oOLE->getStream($oOLE->currentUser);
|
|
|
|
// Get summary information data
|
|
$this->streamSummaryInformation = $oOLE->getStream($oOLE->summaryInformation);
|
|
|
|
// Get additional document summary information data
|
|
$this->streamDocumentSummaryInformation = $oOLE->getStream($oOLE->docSummaryInfos);
|
|
|
|
// Get pictures data
|
|
$this->streamPictures = $oOLE->getStream($oOLE->pictures);
|
|
}
|
|
|
|
/**
|
|
* Stream Pictures
|
|
* @link http://msdn.microsoft.com/en-us/library/dd920746(v=office.12).aspx
|
|
*/
|
|
private function loadPicturesStream()
|
|
{
|
|
$stream = $this->streamPictures;
|
|
|
|
$pos = 0;
|
|
do {
|
|
$arrayRH = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
$readSuccess = false;
|
|
if ($arrayRH['recVer'] == 0x00 && ($arrayRH['recType'] == 0xF007 || ($arrayRH['recType'] >= 0xF018 && $arrayRH['recType'] <= 0xF117))) {
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950560(v=office.12).aspx
|
|
if ($arrayRH['recType'] == 0xF007) {
|
|
// OfficeArtFBSE
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($arrayRH['recType'] >= 0xF018 && $arrayRH['recType'] <= 0xF117) {
|
|
$arrayRecord = $this->readRecordOfficeArtBlip($stream, $pos - 8);
|
|
if ($arrayRecord['length'] > 0) {
|
|
$pos += $arrayRecord['length'];
|
|
$this->arrayPictures[] = $arrayRecord['picture'];
|
|
}
|
|
}
|
|
$readSuccess = true;
|
|
}
|
|
} while ($readSuccess === true);
|
|
}
|
|
|
|
/**
|
|
* Stream Current User
|
|
* @link http://msdn.microsoft.com/en-us/library/dd908567(v=office.12).aspx
|
|
*/
|
|
private function loadCurrentUserStream()
|
|
{
|
|
$pos = 0;
|
|
|
|
/**
|
|
* CurrentUserAtom : http://msdn.microsoft.com/en-us/library/dd948895(v=office.12).aspx
|
|
*/
|
|
// RecordHeader : http://msdn.microsoft.com/en-us/library/dd926377(v=office.12).aspx
|
|
$rHeader = $this->loadRecordHeader($this->streamCurrentUser, $pos);
|
|
$pos += 8;
|
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_CURRENTUSERATOM) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > RecordHeader).');
|
|
}
|
|
|
|
// Size
|
|
$size = self::getInt4d($this->streamCurrentUser, $pos);
|
|
$pos += 4;
|
|
if ($size != 0x00000014) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > Size).');
|
|
}
|
|
|
|
// headerToken
|
|
$headerToken = self::getInt4d($this->streamCurrentUser, $pos);
|
|
$pos += 4;
|
|
if ($headerToken == 0xF3D1C4DF && $headerToken != 0xE391C05F) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.') : Encrypted file');
|
|
}
|
|
|
|
// offsetToCurrentEdit
|
|
$this->offsetToCurrentEdit = self::getInt4d($this->streamCurrentUser, $pos);
|
|
$pos += 4;
|
|
|
|
// lenUserName
|
|
$lenUserName = self::getInt2d($this->streamCurrentUser, $pos);
|
|
$pos += 2;
|
|
if ($lenUserName > 255) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > lenUserName).');
|
|
}
|
|
|
|
// docFileVersion
|
|
$docFileVersion = self::getInt2d($this->streamCurrentUser, $pos);
|
|
$pos += 2;
|
|
if ($docFileVersion != 0x03F4) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > docFileVersion).');
|
|
}
|
|
|
|
// majorVersion
|
|
$majorVersion = self::getInt1d($this->streamCurrentUser, $pos);
|
|
$pos += 1;
|
|
if ($majorVersion != 0x03) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > majorVersion).');
|
|
}
|
|
|
|
// minorVersion
|
|
$minorVersion = self::getInt1d($this->streamCurrentUser, $pos);
|
|
$pos += 1;
|
|
if ($minorVersion != 0x00) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > minorVersion).');
|
|
}
|
|
|
|
// unused
|
|
$pos += 2;
|
|
|
|
// ansiUserName
|
|
$ansiUserName = '';
|
|
do {
|
|
$char = self::getInt1d($this->streamCurrentUser, $pos);
|
|
if (($char >= 0x00 && $char <= 0x1F) || ($char >= 0x7F && $char <= 0x9F)) {
|
|
$char = false;
|
|
} else {
|
|
$ansiUserName .= chr($char);
|
|
$pos += 1;
|
|
}
|
|
} while ($char !== false);
|
|
|
|
// relVersion
|
|
$relVersion = self::getInt4d($this->streamCurrentUser, $pos);
|
|
$pos += 4;
|
|
if ($relVersion != 0x00000008 && $relVersion != 0x00000009) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > relVersion).');
|
|
}
|
|
|
|
// unicodeUserName
|
|
$unicodeUserName = '';
|
|
for ($inc = 0; $inc < $lenUserName; $inc++) {
|
|
$char = self::getInt2d($this->streamCurrentUser, $pos);
|
|
if (($char >= 0x00 && $char <= 0x1F) || ($char >= 0x7F && $char <= 0x9F)) {
|
|
break;
|
|
}
|
|
$unicodeUserName .= chr($char);
|
|
$pos += 2;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stream Powerpoint Document
|
|
* @link http://msdn.microsoft.com/en-us/library/dd921564(v=office.12).aspx
|
|
*/
|
|
private function loadPowerpointDocumentStream()
|
|
{
|
|
$this->readRecordUserEditAtom($this->streamPowerpointDocument, $this->offsetToCurrentEdit);
|
|
|
|
$this->readRecordPersistDirectoryAtom($this->streamPowerpointDocument, $this->offsetPersistDirectory);
|
|
|
|
foreach ($this->rgPersistDirEntry as $offsetDir) {
|
|
$pos = $offsetDir;
|
|
|
|
$rh = $this->loadRecordHeader($this->streamPowerpointDocument, $pos);
|
|
$pos += 8;
|
|
$this->inMainType = $rh['recType'];
|
|
$this->currentNote = null;
|
|
switch ($rh['recType']) {
|
|
case self::RT_DOCUMENT:
|
|
$this->readRecordDocumentContainer($this->streamPowerpointDocument, $pos);
|
|
break;
|
|
case self::RT_NOTES:
|
|
$this->readRecordNotesContainer($this->streamPowerpointDocument, $pos);
|
|
break;
|
|
case self::RT_SLIDE:
|
|
$this->readRecordSlideContainer($this->streamPowerpointDocument, $pos);
|
|
break;
|
|
default:
|
|
// throw new \Exception('Feature not implemented : l.'.__LINE__.'('.dechex($rh['recType']).')');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read a record header
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
*/
|
|
private function loadRecordHeader($stream, $pos)
|
|
{
|
|
$rec = self::getInt2d($stream, $pos);
|
|
$recType = self::getInt2d($stream, $pos + 2);
|
|
$recLen = self::getInt4d($stream, $pos + 4);
|
|
return array(
|
|
'recVer' => ($rec >> 0) & bindec('1111'),
|
|
'recInstance' => ($rec >> 4) & bindec('111111111111'),
|
|
'recType' => $recType,
|
|
'recLen' => $recLen,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Read 8-bit unsigned integer
|
|
*
|
|
* @param string $data
|
|
* @param int $pos
|
|
* @return int
|
|
*/
|
|
public static function getInt1d($data, $pos)
|
|
{
|
|
return ord($data[$pos]);
|
|
}
|
|
|
|
/**
|
|
* Read 16-bit unsigned integer
|
|
*
|
|
* @param string $data
|
|
* @param int $pos
|
|
* @return int
|
|
*/
|
|
public static function getInt2d($data, $pos)
|
|
{
|
|
return ord($data[$pos]) | (ord($data[$pos+1]) << 8);
|
|
}
|
|
|
|
/**
|
|
* Read 32-bit signed integer
|
|
*
|
|
* @param string $data
|
|
* @param int $pos
|
|
* @return int
|
|
*/
|
|
public static function getInt4d($data, $pos)
|
|
{
|
|
// FIX: represent numbers correctly on 64-bit system
|
|
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
|
|
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
|
|
$or24 = ord($data[$pos + 3]);
|
|
|
|
$ord24 = ($or24 & 127) << 24;
|
|
if ($or24 >= 128) {
|
|
// negative number
|
|
$ord24 = -abs((256 - $or24) << 24);
|
|
}
|
|
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $ord24;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies the animation and sound information for a shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd772900(v=office.12).aspx
|
|
*/
|
|
private function readRecordAnimationInfoContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ANIMATIONINFO) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// animationAtom
|
|
// animationSound
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies information about the document.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @throws \Exception
|
|
* @link http://msdn.microsoft.com/en-us/library/dd947357(v=office.12).aspx
|
|
*/
|
|
private function readRecordDocumentContainer($stream, $pos)
|
|
{
|
|
$documentAtom = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
if ($documentAtom['recVer'] != 0x1 || $documentAtom['recInstance'] != 0x000 || $documentAtom['recType'] != self::RT_DOCUMENTATOM) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom).');
|
|
}
|
|
$pos += $documentAtom['recLen'];
|
|
|
|
$exObjList = $this->loadRecordHeader($stream, $pos);
|
|
if ($exObjList['recVer'] == 0xF && $exObjList['recInstance'] == 0x000 && $exObjList['recType'] == self::RT_EXTERNALOBJECTLIST) {
|
|
$pos += 8;
|
|
// exObjListAtom > rh
|
|
$exObjListAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($exObjListAtom['recVer'] != 0x0 || $exObjListAtom['recInstance'] != 0x000 || $exObjListAtom['recType'] != self::RT_EXTERNALOBJECTLISTATOM || $exObjListAtom['recLen'] != 0x00000004) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom > exObjList > exObjListAtom).');
|
|
}
|
|
$pos += 8;
|
|
// exObjListAtom > exObjIdSeed
|
|
$pos += 4;
|
|
// rgChildRec
|
|
$exObjList['recLen'] -= 12;
|
|
do {
|
|
$childRec = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
$exObjList['recLen'] -= 8;
|
|
switch ($childRec['recType']) {
|
|
case self::RT_EXTERNALHYPERLINK:
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd944995(v=office.12).aspx
|
|
// exHyperlinkAtom > rh
|
|
$exHyperlinkAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($exHyperlinkAtom['recVer'] != 0x0 || $exHyperlinkAtom['recInstance'] != 0x000 || $exHyperlinkAtom['recType'] != self::RT_EXTERNALHYPERLINKATOM || $exObjListAtom['recLen'] != 0x00000004) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom > exObjList > rgChildRec > RT_ExternalHyperlink).');
|
|
}
|
|
$pos += 8;
|
|
$exObjList['recLen'] -= 8;
|
|
// exHyperlinkAtom > exHyperlinkId
|
|
$exHyperlinkId = self::getInt4d($stream, $pos);
|
|
$pos += 4;
|
|
$exObjList['recLen'] -= 4;
|
|
|
|
$this->arrayHyperlinks[$exHyperlinkId] = array();
|
|
// friendlyNameAtom
|
|
$friendlyNameAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($friendlyNameAtom['recVer'] == 0x0 && $friendlyNameAtom['recInstance'] == 0x000 && $friendlyNameAtom['recType'] == self::RT_CSTRING && $friendlyNameAtom['recLen'] % 2 == 0) {
|
|
$pos += 8;
|
|
$exObjList['recLen'] -= 8;
|
|
$this->arrayHyperlinks[$exHyperlinkId]['text'] = '';
|
|
for ($inc = 0; $inc < ($friendlyNameAtom['recLen'] / 2); $inc++) {
|
|
$char = self::getInt2d($stream, $pos);
|
|
$pos += 2;
|
|
$exObjList['recLen'] -= 2;
|
|
$this->arrayHyperlinks[$exHyperlinkId]['text'] .= chr($char);
|
|
}
|
|
}
|
|
// targetAtom
|
|
$targetAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($targetAtom['recVer'] == 0x0 && $targetAtom['recInstance'] == 0x001 && $targetAtom['recType'] == self::RT_CSTRING && $targetAtom['recLen'] % 2 == 0) {
|
|
$pos += 8;
|
|
$exObjList['recLen'] -= 8;
|
|
$this->arrayHyperlinks[$exHyperlinkId]['url'] = '';
|
|
for ($inc = 0; $inc < ($targetAtom['recLen'] / 2); $inc++) {
|
|
$char = self::getInt2d($stream, $pos);
|
|
$pos += 2;
|
|
$exObjList['recLen'] -= 2;
|
|
$this->arrayHyperlinks[$exHyperlinkId]['url'] .= chr($char);
|
|
}
|
|
}
|
|
// locationAtom
|
|
$locationAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($locationAtom['recVer'] == 0x0 && $locationAtom['recInstance'] == 0x003 && $locationAtom['recType'] == self::RT_CSTRING && $locationAtom['recLen'] % 2 == 0) {
|
|
$pos += 8;
|
|
$exObjList['recLen'] -= 8;
|
|
$string = '';
|
|
for ($inc = 0; $inc < ($locationAtom['recLen'] / 2); $inc++) {
|
|
$char = self::getInt2d($stream, $pos);
|
|
$pos += 2;
|
|
$exObjList['recLen'] -= 2;
|
|
$string .= chr($char);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : '.dechex($childRec['recType'].')'));
|
|
}
|
|
} while ($exObjList['recLen'] > 0);
|
|
}
|
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd907813(v=office.12).aspx
|
|
$documentTextInfo = $this->loadRecordHeader($stream, $pos);
|
|
if ($documentTextInfo['recVer'] == 0xF && $documentTextInfo['recInstance'] == 0x000 && $documentTextInfo['recType'] == self::RT_ENVIRONMENT) {
|
|
$pos += 8;
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd952717(v=office.12).aspx
|
|
$kinsoku = $this->loadRecordHeader($stream, $pos);
|
|
if ($kinsoku['recVer'] == 0xF && $kinsoku['recInstance'] == 0x002 && $kinsoku['recType'] == self::RT_KINSOKU) {
|
|
$pos += 8;
|
|
$pos += $kinsoku['recLen'];
|
|
}
|
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948152(v=office.12).aspx
|
|
$fontCollection = $this->loadRecordHeader($stream, $pos);
|
|
if ($fontCollection['recVer'] == 0xF && $fontCollection['recInstance'] == 0x000 && $fontCollection['recType'] == self::RT_FONTCOLLECTION) {
|
|
$pos += 8;
|
|
do {
|
|
$fontEntityAtom = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
$fontCollection['recLen'] -= 8;
|
|
if ($fontEntityAtom['recVer'] != 0x0 || $fontEntityAtom['recInstance'] > 128 || $fontEntityAtom['recType'] != self::RT_FONTENTITYATOM) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > RT_Environment > RT_FontCollection > RT_FontEntityAtom).');
|
|
}
|
|
$string = '';
|
|
for ($inc = 0; $inc < 32; $inc++) {
|
|
$char = self::getInt2d($stream, $pos);
|
|
$pos += 2;
|
|
$fontCollection['recLen'] -= 2;
|
|
$string .= chr($char);
|
|
}
|
|
$this->arrayFonts[] = $string;
|
|
|
|
// lfCharSet (1 byte)
|
|
$pos += 1;
|
|
$fontCollection['recLen'] -= 1;
|
|
|
|
// fEmbedSubsetted (1 bit)
|
|
// unused (7 bits)
|
|
$pos += 1;
|
|
$fontCollection['recLen'] -= 1;
|
|
|
|
// rasterFontType (1 bit)
|
|
// deviceFontType (1 bit)
|
|
// truetypeFontType (1 bit)
|
|
// fNoFontSubstitution (1 bit)
|
|
// reserved (4 bits)
|
|
$pos += 1;
|
|
$fontCollection['recLen'] -= 1;
|
|
|
|
// lfPitchAndFamily (1 byte)
|
|
$pos += 1;
|
|
$fontCollection['recLen'] -= 1;
|
|
|
|
$fontEmbedData1 = $this->loadRecordHeader($stream, $pos);
|
|
if ($fontEmbedData1['recVer'] == 0x0 && $fontEmbedData1['recInstance'] >= 0x000 && $fontEmbedData1['recInstance'] <= 0x003 && $fontEmbedData1['recType'] == self::RT_FONTEMBEDDATABLOB) {
|
|
$pos += 8;
|
|
$fontCollection['recLen'] -= 8;
|
|
$pos += $fontEmbedData1['recLen'];
|
|
$fontCollection['recLen'] -= $fontEmbedData1['recLen'];
|
|
}
|
|
|
|
$fontEmbedData2 = $this->loadRecordHeader($stream, $pos);
|
|
if ($fontEmbedData2['recVer'] == 0x0 && $fontEmbedData2['recInstance'] >= 0x000 && $fontEmbedData2['recInstance'] <= 0x003 && $fontEmbedData2['recType'] == self::RT_FONTEMBEDDATABLOB) {
|
|
$pos += 8;
|
|
$fontCollection['recLen'] -= 8;
|
|
$pos += $fontEmbedData2['recLen'];
|
|
$fontCollection['recLen'] -= $fontEmbedData2['recLen'];
|
|
}
|
|
|
|
$fontEmbedData3 = $this->loadRecordHeader($stream, $pos);
|
|
if ($fontEmbedData3['recVer'] == 0x0 && $fontEmbedData3['recInstance'] >= 0x000 && $fontEmbedData3['recInstance'] <= 0x003 && $fontEmbedData3['recType'] == self::RT_FONTEMBEDDATABLOB) {
|
|
$pos += 8;
|
|
$fontCollection['recLen'] -= 8;
|
|
$pos += $fontEmbedData3['recLen'];
|
|
$fontCollection['recLen'] -= $fontEmbedData3['recLen'];
|
|
}
|
|
|
|
$fontEmbedData4 = $this->loadRecordHeader($stream, $pos);
|
|
if ($fontEmbedData4['recVer'] == 0x0 && $fontEmbedData4['recInstance'] >= 0x000 && $fontEmbedData4['recInstance'] <= 0x003 && $fontEmbedData4['recType'] == self::RT_FONTEMBEDDATABLOB) {
|
|
$pos += 8;
|
|
$fontCollection['recLen'] -= 8;
|
|
$pos += $fontEmbedData4['recLen'];
|
|
$fontCollection['recLen'] -= $fontEmbedData4['recLen'];
|
|
}
|
|
} while ($fontCollection['recLen'] > 0);
|
|
}
|
|
|
|
$textCFDefaultsAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($textCFDefaultsAtom['recVer'] == 0x0 && $textCFDefaultsAtom['recInstance'] == 0x000 && $textCFDefaultsAtom['recType'] == self::RT_TEXTCHARFORMATEXCEPTIONATOM) {
|
|
$pos += 8;
|
|
$pos += $textCFDefaultsAtom['recLen'];
|
|
}
|
|
|
|
$textPFDefaultsAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($textPFDefaultsAtom['recVer'] == 0x0 && $textPFDefaultsAtom['recInstance'] == 0x000 && $textPFDefaultsAtom['recType'] == self::RT_TEXTPARAGRAPHFORMATEXCEPTIONATOM) {
|
|
$pos += 8;
|
|
$pos += $textPFDefaultsAtom['recLen'];
|
|
}
|
|
|
|
$defaultRulerAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($defaultRulerAtom['recVer'] == 0x0 && $defaultRulerAtom['recInstance'] == 0x000 && $defaultRulerAtom['recType'] == self::RT_DEFAULTRULERATOM) {
|
|
$pos += 8;
|
|
$pos += $defaultRulerAtom['recLen'];
|
|
}
|
|
|
|
$textSIDefaultsAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($textSIDefaultsAtom['recVer'] == 0x0 && $textSIDefaultsAtom['recInstance'] == 0x000 && $textSIDefaultsAtom['recType'] == self::RT_TEXTSPECIALINFODEFAULTATOM) {
|
|
$pos += 8;
|
|
$pos += $textSIDefaultsAtom['recLen'];
|
|
}
|
|
|
|
$textMasterStyleAtom = $this->loadRecordHeader($stream, $pos);
|
|
if ($textMasterStyleAtom['recVer'] == 0x0 && $textMasterStyleAtom['recType'] == self::RT_TEXTMASTERSTYLEATOM) {
|
|
$pos += 8;
|
|
$pos += $textMasterStyleAtom['recLen'];
|
|
}
|
|
}
|
|
|
|
$soundCollection = $this->loadRecordHeader($stream, $pos);
|
|
if ($soundCollection['recVer'] == 0xF && $soundCollection['recInstance'] == 0x005 && $soundCollection['recType'] == self::RT_SOUNDCOLLECTION) {
|
|
$pos += 8;
|
|
$pos += $soundCollection['recLen'];
|
|
}
|
|
|
|
$drawingGroup = $this->loadRecordHeader($stream, $pos);
|
|
if ($drawingGroup['recVer'] == 0xF && $drawingGroup['recInstance'] == 0x000 && $drawingGroup['recType'] == self::RT_DRAWINGGROUP) {
|
|
$drawing = $this->readRecordDrawingGroupContainer($stream, $pos);
|
|
$pos += 8;
|
|
$pos += $drawing['length'];
|
|
}
|
|
|
|
$masterList = $this->loadRecordHeader($stream, $pos);
|
|
if ($masterList['recVer'] == 0xF && $masterList['recInstance'] == 0x001 && $masterList['recType'] == self::RT_SLIDELISTWITHTEXT) {
|
|
$pos += 8;
|
|
$pos += $masterList['recLen'];
|
|
}
|
|
|
|
$docInfoList = $this->loadRecordHeader($stream, $pos);
|
|
if ($docInfoList['recVer'] == 0xF && $docInfoList['recInstance'] == 0x000 && $docInfoList['recType'] == self::RT_LIST) {
|
|
$pos += 8;
|
|
$pos += $docInfoList['recLen'];
|
|
}
|
|
|
|
$slideHF = $this->loadRecordHeader($stream, $pos);
|
|
if ($slideHF['recVer'] == 0xF && $slideHF['recInstance'] == 0x003 && $slideHF['recType'] == self::RT_HEADERSFOOTERS) {
|
|
$pos += 8;
|
|
$pos += $slideHF['recLen'];
|
|
}
|
|
|
|
$notesHF = $this->loadRecordHeader($stream, $pos);
|
|
if ($notesHF['recVer'] == 0xF && $notesHF['recInstance'] == 0x004 && $notesHF['recType'] == self::RT_HEADERSFOOTERS) {
|
|
$pos += 8;
|
|
$pos += $notesHF['recLen'];
|
|
}
|
|
|
|
// SlideListWithTextContainer
|
|
$slideList = $this->loadRecordHeader($stream, $pos);
|
|
if ($slideList['recVer'] == 0xF && $slideList['recInstance'] == 0x000 && $slideList['recType'] == self::RT_SLIDELISTWITHTEXT) {
|
|
$pos += 8;
|
|
do {
|
|
// SlideListWithTextSubContainerOrAtom
|
|
$rhSlideList = $this->loadRecordHeader($stream, $pos);
|
|
if ($rhSlideList['recVer'] == 0x0 && $rhSlideList['recInstance'] == 0x000 && $rhSlideList['recType'] == self::RT_SLIDEPERSISTATOM && $rhSlideList['recLen'] == 0x00000014) {
|
|
$pos += 8;
|
|
$slideList['recLen'] -= 8;
|
|
// persistIdRef
|
|
$pos += 4;
|
|
$slideList['recLen'] -= 4;
|
|
// reserved1 - fShouldCollapse - fNonOutlineData - reserved2
|
|
$pos += 4;
|
|
$slideList['recLen'] -= 4;
|
|
// cTexts
|
|
$pos += 4;
|
|
$slideList['recLen'] -= 4;
|
|
// slideId
|
|
$slideId = self::getInt4d($stream, $pos);
|
|
if ($slideId == -2147483648) {
|
|
$slideId = 0;
|
|
}
|
|
if ($slideId > 0) {
|
|
$this->arrayNotes[$this->oPhpPresentation->getActiveSlideIndex()] = $slideId;
|
|
}
|
|
$pos += 4;
|
|
$slideList['recLen'] -= 4;
|
|
// reserved3
|
|
$pos += 4;
|
|
$slideList['recLen'] -= 4;
|
|
}
|
|
} while ($slideList['recLen'] > 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies information about a slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx
|
|
*/
|
|
private function readRecordDrawingContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_DRAWING) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
|
|
$officeArtDg = $this->readRecordOfficeArtDgContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $officeArtDg['length'];
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
private function readRecordDrawingGroupContainer($stream, $pos)
|
|
{
|
|
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_DRAWINGGROUP) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a reference to an external object.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910388(v=office.12).aspx
|
|
*/
|
|
private function readRecordExObjRefAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_EXTERNALOBJECTREFATOM && $data['recLen'] == 0x00000004) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a type of action to be performed.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd953300(v=office.12).aspx
|
|
*/
|
|
private function readRecordInteractiveInfoAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_INTERACTIVEINFOATOM && $data['recLen'] == 0x00000010) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// soundIdRef
|
|
$arrayReturn['length'] += 4;
|
|
// exHyperlinkIdRef
|
|
$arrayReturn['exHyperlinkIdRef'] = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
// action
|
|
$arrayReturn['length'] += 1;
|
|
// oleVerb
|
|
$arrayReturn['length'] += 1;
|
|
// jump
|
|
$arrayReturn['length'] += 1;
|
|
// fAnimated (1 bit)
|
|
// fStopSound (1 bit)
|
|
// fCustomShowReturn (1 bit)
|
|
// fVisited (1 bit)
|
|
// reserved (4 bits)
|
|
$arrayReturn['length'] += 1;
|
|
// hyperlinkType
|
|
$arrayReturn['length'] += 1;
|
|
// unused
|
|
$arrayReturn['length'] += 3;
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies the name of a macro, a file name, or a named show.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925121(v=office.12).aspx
|
|
*/
|
|
private function readRecordMacroNameAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x002 && $data['recType'] == self::RT_CSTRING && $data['recLen'] % 2 == 0) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies what actions to perform when interacting with an object by means of a mouse click.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd952348(v=office.12).aspx
|
|
*/
|
|
private function readRecordMouseClickInteractiveInfoContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_INTERACTIVEINFO) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// interactiveInfoAtom
|
|
$interactiveInfoAtom = $this->readRecordInteractiveInfoAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $interactiveInfoAtom['length'];
|
|
if ($interactiveInfoAtom['length'] > 0) {
|
|
$arrayReturn['exHyperlinkIdRef'] = $interactiveInfoAtom['exHyperlinkIdRef'];
|
|
}
|
|
// macroNameAtom
|
|
$macroNameAtom = $this->readRecordMacroNameAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $macroNameAtom['length'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies what actions to perform when interacting with an object by moving the mouse cursor over it.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925811(v=office.12).aspx
|
|
*/
|
|
private function readRecordMouseOverInteractiveInfoContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x001 && $data['recType'] == self::RT_INTERACTIVEINFO) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// interactiveInfoAtom
|
|
// macroNameAtom
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtBlip record specifies BLIP file data.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910081(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtBlip($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'picture' => null
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && ($data['recType'] >= 0xF018 && $data['recType'] <= 0xF117)) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
switch ($data['recType']) {
|
|
case self::OFFICEARTBLIPJPG:
|
|
case self::OFFICEARTBLIPPNG:
|
|
// rgbUid1
|
|
$arrayReturn['length'] += 16;
|
|
$data['recLen'] -= 16;
|
|
if ($data['recInstance'] == 0x6E1) {
|
|
// rgbUid2
|
|
$arrayReturn['length'] += 16;
|
|
$data['recLen'] -= 16;
|
|
}
|
|
// tag
|
|
$arrayReturn['length'] += 1;
|
|
$data['recLen'] -= 1;
|
|
// BLIPFileData
|
|
$arrayReturn['picture'] = substr($this->streamPictures, $pos + $arrayReturn['length'], $data['recLen']);
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
break;
|
|
default:
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : '.dechex($data['recType'].')'));
|
|
}
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtChildAnchor record specifies four signed integers that specify the anchor for the shape that contains this record.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922720(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtChildAnchor($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF00F && $data['recLen'] == 0x00000010) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['left'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$arrayReturn['top'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$arrayReturn['width'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']) - $arrayReturn['left'];
|
|
$arrayReturn['length'] += 4;
|
|
$arrayReturn['height'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']) - $arrayReturn['top'];
|
|
$arrayReturn['length'] += 4;
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies the location of a shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922797(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtClientAnchor($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF010 && ($data['recLen'] == 0x00000008 || $data['recLen'] == 0x00000010)) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
switch ($data['recLen']) {
|
|
case 0x00000008:
|
|
$arrayReturn['top'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['left'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['width'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6) - $arrayReturn['left'];
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['height'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6) - $arrayReturn['left'];
|
|
$arrayReturn['length'] += 2;
|
|
$pos += 8;
|
|
break;
|
|
case 0x00000010:
|
|
throw new \Exception('PowerPoint97 Reader : record OfficeArtClientAnchor (0x00000010)');
|
|
}
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies text related data for a shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910958(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtClientTextbox($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'text' => '',
|
|
'numParts' => 0,
|
|
'numTexts' => 0,
|
|
'hyperlink' => array(),
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
// recVer 0xF
|
|
// Doc : 0x0 https://msdn.microsoft.com/en-us/library/dd910958(v=office.12).aspx
|
|
// Sample : 0xF https://msdn.microsoft.com/en-us/library/dd953497(v=office.12).aspx
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF00D) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$strLen = 0;
|
|
do {
|
|
$rhChild = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']);
|
|
/**
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd947039(v=office.12).aspx
|
|
*/
|
|
// echo dechex($rhChild['recType']).'-'.$rhChild['recType'].EOL;
|
|
switch ($rhChild['recType']) {
|
|
case self::RT_INTERACTIVEINFO:
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948623(v=office.12).aspx
|
|
if ($rhChild['recInstance'] == 0x0000) {
|
|
$mouseClickInfo = $this->readRecordMouseClickInteractiveInfoContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $mouseClickInfo['length'];
|
|
$arrayReturn['hyperlink'][]['id'] = $mouseClickInfo['exHyperlinkIdRef'];
|
|
}
|
|
if ($rhChild['recInstance'] == 0x0001) {
|
|
$mouseOverInfo = $this->readRecordMouseOverInteractiveInfoContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $mouseOverInfo['length'];
|
|
}
|
|
break;
|
|
case self::RT_STYLETEXTPROPATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd950647(v=office.12).aspx
|
|
// rgTextPFRun
|
|
$strLenRT = $strLen + 1;
|
|
do {
|
|
$strucTextPFRun = $this->readStructureTextPFRun($stream, $pos + $arrayReturn['length'], $strLenRT);
|
|
$arrayReturn['numTexts']++;
|
|
$arrayReturn['text'.$arrayReturn['numTexts']] = $strucTextPFRun;
|
|
if (isset($strucTextPFRun['alignH'])) {
|
|
$arrayReturn['alignH'] = $strucTextPFRun['alignH'];
|
|
}
|
|
$strLenRT = $strucTextPFRun['strLenRT'];
|
|
$arrayReturn['length'] += $strucTextPFRun['length'];
|
|
} while ($strLenRT > 0);
|
|
// rgTextCFRun
|
|
$strLenRT = $strLen + 1;
|
|
do {
|
|
$strucTextCFRun = $this->readStructureTextCFRun($stream, $pos + $arrayReturn['length'], $strLenRT);
|
|
$arrayReturn['numParts']++;
|
|
$arrayReturn['part'.$arrayReturn['numParts']] = $strucTextCFRun;
|
|
$strLenRT = $strucTextCFRun['strLenRT'];
|
|
$arrayReturn['length'] += $strucTextCFRun['length'];
|
|
} while ($strLenRT > 0);
|
|
break;
|
|
case self::RT_TEXTBYTESATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : https://msdn.microsoft.com/en-us/library/dd947905(v=office.12).aspx
|
|
$strLen = (int)$rhChild['recLen'];
|
|
for ($inc = 0; $inc < $strLen; $inc++) {
|
|
$char = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
if ($char == 0x0B) {
|
|
$char = 0x20;
|
|
}
|
|
$arrayReturn['text'] .= Text::chr($char);
|
|
$arrayReturn['length'] += 1;
|
|
}
|
|
break;
|
|
case self::RT_TEXTCHARSATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd772921(v=office.12).aspx
|
|
$strLen = (int)($rhChild['recLen']/2);
|
|
for ($inc = 0; $inc < $strLen; $inc++) {
|
|
$char = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
if ($char == 0x0B) {
|
|
$char = 0x20;
|
|
}
|
|
$arrayReturn['text'] .= Text::chr($char);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
break;
|
|
case self::RT_TEXTHEADERATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd905272(v=office.12).aspx
|
|
// textType
|
|
$arrayReturn['length'] += 4;
|
|
break;
|
|
case self::RT_TEXTINTERACTIVEINFOATOM:
|
|
$arrayReturn['length'] += 8;
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947973(v=office.12).aspx
|
|
if ($rhChild['recInstance'] == 0x0000) {
|
|
//@todo : MouseClickTextInteractiveInfoAtom
|
|
$arrayReturn['hyperlink'][count($arrayReturn['hyperlink']) - 1]['start'] = self::getInt4d($stream, $pos + + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
|
|
$arrayReturn['hyperlink'][count($arrayReturn['hyperlink']) - 1]['end'] = self::getInt4d($stream, $pos + + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
}
|
|
if ($rhChild['recInstance'] == 0x0001) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
break;
|
|
case self::RT_TEXTSPECIALINFOATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd945296(v=office.12).aspx
|
|
$strLenRT = $strLen + 1;
|
|
do {
|
|
$structTextSIRun = $this->readStructureTextSIRun($stream, $pos + $arrayReturn['length'], $strLenRT);
|
|
$strLenRT = $structTextSIRun['strLenRT'];
|
|
$arrayReturn['length'] += $structTextSIRun['length'];
|
|
} while ($strLenRT > 0);
|
|
break;
|
|
case self::RT_TEXTRULERATOM:
|
|
$arrayReturn['length'] += 8;
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd953212(v=office.12).aspx
|
|
$structRuler = $this->readStructureTextRuler($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $structRuler['length'];
|
|
break;
|
|
case self::RT_SLIDENUMBERMETACHARATOM:
|
|
$datasRecord = $this->readRecordSlideNumberMCAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $datasRecord['length'];
|
|
break;
|
|
default:
|
|
$arrayReturn['length'] += 8;
|
|
$arrayReturn['length'] += $rhChild['recLen'];
|
|
// throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($rhChild['recType']).')');
|
|
}
|
|
} while (($data['recLen'] - $arrayReturn['length']) > 0);
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtSpContainer record specifies a shape container.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943794(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtSpContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'shape' => null,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF004) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// shapeGroup
|
|
$shapeGroup = $this->readRecordOfficeArtFSPGR($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shapeGroup['length'];
|
|
|
|
// shapeProp
|
|
$shapeProp = $this->readRecordOfficeArtFSP($stream, $pos + $arrayReturn['length']);
|
|
if ($shapeProp['length'] == 0) {
|
|
throw new \Exception('PowerPoint97 Reader : record OfficeArtFSP');
|
|
}
|
|
$arrayReturn['length'] += $shapeProp['length'];
|
|
|
|
if ($shapeProp['fDeleted'] == 0x1 && $shapeProp['fChild'] == 0x0) {
|
|
// deletedShape
|
|
$deletedShape = $this->readRecordOfficeArtFPSPL($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $deletedShape['length'];
|
|
}
|
|
|
|
// shapePrimaryOptions
|
|
$shpPrimaryOptions = $this->readRecordOfficeArtFOPT($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shpPrimaryOptions['length'];
|
|
|
|
// shapeSecondaryOptions1
|
|
$shpSecondaryOptions1 = $this->readRecordOfficeArtSecondaryFOPT($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shpSecondaryOptions1['length'];
|
|
|
|
// shapeTertiaryOptions1
|
|
$shpTertiaryOptions1 = $this->readRecordOfficeArtTertiaryFOPT($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shpTertiaryOptions1['length'];
|
|
|
|
// childAnchor
|
|
$childAnchor = $this->readRecordOfficeArtChildAnchor($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $childAnchor['length'];
|
|
|
|
// clientAnchor
|
|
$clientAnchor = $this->readRecordOfficeArtClientAnchor($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $clientAnchor['length'];
|
|
|
|
// clientData
|
|
$clientData = $this->readRecordOfficeArtClientData($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $clientData['length'];
|
|
|
|
// clientTextbox
|
|
$clientTextbox = $this->readRecordOfficeArtClientTextbox($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $clientTextbox['length'];
|
|
|
|
// shapeSecondaryOptions2
|
|
if ($shpSecondaryOptions1['length'] == 0) {
|
|
$shpSecondaryOptions2 = $this->readRecordOfficeArtSecondaryFOPT($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shpSecondaryOptions2['length'];
|
|
}
|
|
|
|
// shapeTertiaryOptions2
|
|
if ($shpTertiaryOptions1['length'] == 0) {
|
|
$shpTertiaryOptions2 = $this->readRecordOfficeArtTertiaryFOPT($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shpTertiaryOptions2['length'];
|
|
}
|
|
|
|
// Core : Shape
|
|
// Informations about group are not defined
|
|
$arrayDimensions = array();
|
|
$bIsGroup = false;
|
|
if (is_object($this->oCurrentGroup)) {
|
|
if (!$this->bFirstShapeGroup) {
|
|
if ($clientAnchor['length'] > 0) {
|
|
// $this->oCurrentGroup->setOffsetX($clientAnchor['left']);
|
|
// $this->oCurrentGroup->setOffsetY($clientAnchor['top']);
|
|
// $this->oCurrentGroup->setHeight($clientAnchor['height']);
|
|
// $this->oCurrentGroup->setWidth($clientAnchor['width']);
|
|
}
|
|
$bIsGroup = true;
|
|
$this->bFirstShapeGroup = true;
|
|
} else {
|
|
if ($childAnchor['length'] > 0) {
|
|
$arrayDimensions = $childAnchor;
|
|
}
|
|
}
|
|
} else {
|
|
if ($clientAnchor['length'] > 0) {
|
|
$arrayDimensions = $clientAnchor;
|
|
}
|
|
}
|
|
if (!$bIsGroup) {
|
|
// *** Shape ***
|
|
if (isset($shpPrimaryOptions['pib'])) {
|
|
// isDrawing
|
|
$drawingPib = $shpPrimaryOptions['pib'];
|
|
if (isset($this->arrayPictures[$drawingPib - 1])) {
|
|
$gdImage = imagecreatefromstring($this->arrayPictures[$drawingPib - 1]);
|
|
$arrayReturn['shape'] = new Drawing\Gd();
|
|
$arrayReturn['shape']->setImageResource($gdImage);
|
|
}
|
|
} elseif (isset($shpPrimaryOptions['line']) && $shpPrimaryOptions['line']) {
|
|
// isLine
|
|
$arrayReturn['shape'] = new Line(0, 0, 0, 0);
|
|
} elseif ($clientTextbox['length'] > 0) {
|
|
$arrayReturn['shape'] = new RichText();
|
|
if (isset($clientTextbox['alignH'])) {
|
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setHorizontal($clientTextbox['alignH']);
|
|
}
|
|
|
|
$start = 0;
|
|
$lastLevel = -1;
|
|
$lastMarginLeft = 0;
|
|
for ($inc = 1; $inc <= $clientTextbox['numParts']; $inc++) {
|
|
if ($clientTextbox['numParts'] == $clientTextbox['numTexts'] && isset($clientTextbox['text'.$inc])) {
|
|
if (isset($clientTextbox['text'.$inc]['bulletChar'])) {
|
|
$arrayReturn['shape']->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
|
|
$arrayReturn['shape']->getActiveParagraph()->getBulletStyle()->setBulletChar($clientTextbox['text'.$inc]['bulletChar']);
|
|
}
|
|
// Indent
|
|
$indent = 0;
|
|
if (isset($clientTextbox['text'.$inc]['indent'])) {
|
|
$indent = $clientTextbox['text'.$inc]['indent'];
|
|
}
|
|
if (isset($clientTextbox['text'.$inc]['leftMargin'])) {
|
|
if ($lastMarginLeft > $clientTextbox['text'.$inc]['leftMargin']) {
|
|
$lastLevel--;
|
|
}
|
|
if ($lastMarginLeft < $clientTextbox['text'.$inc]['leftMargin']) {
|
|
$lastLevel++;
|
|
}
|
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setLevel($lastLevel);
|
|
$lastMarginLeft = $clientTextbox['text'.$inc]['leftMargin'];
|
|
|
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setMarginLeft($clientTextbox['text'.$inc]['leftMargin']);
|
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setIndent($indent - $clientTextbox['text'.$inc]['leftMargin']);
|
|
}
|
|
}
|
|
// Texte
|
|
$sText = substr(isset($clientTextbox['text']) ? $clientTextbox['text'] : '', $start, $clientTextbox['part'.$inc]['partLength']);
|
|
$sHyperlinkURL = '';
|
|
if (empty($sText)) {
|
|
// Is there a hyperlink ?
|
|
if (isset($clientTextbox['hyperlink']) && is_array($clientTextbox['hyperlink']) && !empty($clientTextbox['hyperlink'])) {
|
|
foreach ($clientTextbox['hyperlink'] as $itmHyperlink) {
|
|
if ($itmHyperlink['start'] == $start && ($itmHyperlink['end'] - $itmHyperlink['start']) == $clientTextbox['part'.$inc]['partLength']) {
|
|
$sText = $this->arrayHyperlinks[$itmHyperlink['id']]['text'];
|
|
$sHyperlinkURL = $this->arrayHyperlinks[$itmHyperlink['id']]['url'];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// New paragraph
|
|
$bCreateParagraph = false;
|
|
if (strpos($sText, "\r") !== false) {
|
|
$bCreateParagraph = true;
|
|
$sText = str_replace("\r", '', $sText);
|
|
}
|
|
// TextRun
|
|
$txtRun = $arrayReturn['shape']->createTextRun($sText);
|
|
if (isset($clientTextbox['part'.$inc]['bold'])) {
|
|
$txtRun->getFont()->setBold($clientTextbox['part'.$inc]['bold']);
|
|
}
|
|
if (isset($clientTextbox['part'.$inc]['italic'])) {
|
|
$txtRun->getFont()->setItalic($clientTextbox['part'.$inc]['italic']);
|
|
}
|
|
if (isset($clientTextbox['part'.$inc]['underline'])) {
|
|
$txtRun->getFont()->setUnderline($clientTextbox['part'.$inc]['underline']);
|
|
}
|
|
if (isset($clientTextbox['part'.$inc]['fontName'])) {
|
|
$txtRun->getFont()->setName($clientTextbox['part'.$inc]['fontName']);
|
|
}
|
|
if (isset($clientTextbox['part'.$inc]['fontSize'])) {
|
|
$txtRun->getFont()->setSize($clientTextbox['part'.$inc]['fontSize']);
|
|
}
|
|
if (isset($clientTextbox['part'.$inc]['color'])) {
|
|
$txtRun->getFont()->setColor($clientTextbox['part'.$inc]['color']);
|
|
}
|
|
// Hyperlink
|
|
if (!empty($sHyperlinkURL)) {
|
|
$txtRun->setHyperlink(new Hyperlink($sHyperlinkURL));
|
|
}
|
|
|
|
$start += $clientTextbox['part'.$inc]['partLength'];
|
|
if ($bCreateParagraph) {
|
|
$arrayReturn['shape']->createParagraph();
|
|
}
|
|
}
|
|
}
|
|
|
|
// *** Properties ***
|
|
// Dimensions
|
|
if ($arrayReturn['shape'] instanceof AbstractShape) {
|
|
if (!empty($arrayDimensions)) {
|
|
$arrayReturn['shape']->setOffsetX($arrayDimensions['left']);
|
|
$arrayReturn['shape']->setOffsetY($arrayDimensions['top']);
|
|
$arrayReturn['shape']->setHeight($arrayDimensions['height']);
|
|
$arrayReturn['shape']->setWidth($arrayDimensions['width']);
|
|
}
|
|
// Rotation
|
|
if (isset($shpPrimaryOptions['rotation'])) {
|
|
$rotation = $shpPrimaryOptions['rotation'];
|
|
$arrayReturn['shape']->setRotation($rotation);
|
|
}
|
|
// Shadow
|
|
if (isset($shpPrimaryOptions['shadowOffsetX']) && isset($shpPrimaryOptions['shadowOffsetY'])) {
|
|
$shadowOffsetX = $shpPrimaryOptions['shadowOffsetX'];
|
|
$shadowOffsetY = $shpPrimaryOptions['shadowOffsetY'];
|
|
if ($shadowOffsetX != 0 && $shadowOffsetX != 0) {
|
|
$arrayReturn['shape']->getShadow()->setVisible(true);
|
|
if ($shadowOffsetX > 0 && $shadowOffsetX == $shadowOffsetY) {
|
|
$arrayReturn['shape']->getShadow()->setDistance($shadowOffsetX)->setDirection(45);
|
|
}
|
|
}
|
|
}
|
|
// Specific Line
|
|
if ($arrayReturn['shape'] instanceof Line) {
|
|
if (isset($shpPrimaryOptions['lineColor'])) {
|
|
$arrayReturn['shape']->getBorder()->getColor()->setARGB('FF'.$shpPrimaryOptions['lineColor']);
|
|
}
|
|
if (isset($shpPrimaryOptions['lineWidth'])) {
|
|
$arrayReturn['shape']->setHeight($shpPrimaryOptions['lineWidth']);
|
|
}
|
|
}
|
|
// Specific RichText
|
|
if ($arrayReturn['shape'] instanceof RichText) {
|
|
if (isset($shpPrimaryOptions['insetBottom'])) {
|
|
$arrayReturn['shape']->setInsetBottom($shpPrimaryOptions['insetBottom']);
|
|
}
|
|
if (isset($shpPrimaryOptions['insetLeft'])) {
|
|
$arrayReturn['shape']->setInsetLeft($shpPrimaryOptions['insetLeft']);
|
|
}
|
|
if (isset($shpPrimaryOptions['insetRight'])) {
|
|
$arrayReturn['shape']->setInsetRight($shpPrimaryOptions['insetRight']);
|
|
}
|
|
if (isset($shpPrimaryOptions['insetTop'])) {
|
|
$arrayReturn['shape']->setInsetTop($shpPrimaryOptions['insetTop']);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Rotation
|
|
if (isset($shpPrimaryOptions['rotation'])) {
|
|
$rotation = $shpPrimaryOptions['rotation'];
|
|
$this->oCurrentGroup->setRotation($rotation);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtSpgrContainer record specifies a container for groups of shapes.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @param boolean $bInGroup
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd910416(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtSpgrContainer($stream, $pos, $bInGroup = false)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF003) {
|
|
$arrayReturn['length'] += 8;
|
|
|
|
do {
|
|
$rhFileBlock = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']);
|
|
if (!($rhFileBlock['recVer'] == 0xF && $rhFileBlock['recInstance'] == 0x0000 && ($rhFileBlock['recType'] == 0xF003 || $rhFileBlock['recType'] == 0xF004))) {
|
|
throw new \Exception('PowerPoint97 Reader : readRecordOfficeArtSpgrContainer.');
|
|
}
|
|
|
|
switch ($rhFileBlock['recType']) {
|
|
case 0xF003:
|
|
// Core
|
|
$this->oCurrentGroup = $this->oPhpPresentation->getActiveSlide()->createGroup();
|
|
$this->bFirstShapeGroup = false;
|
|
// OfficeArtSpgrContainer
|
|
$fileBlock = $this->readRecordOfficeArtSpgrContainer($stream, $pos + $arrayReturn['length'], true);
|
|
$arrayReturn['length'] += $fileBlock['length'];
|
|
$data['recLen'] -= $fileBlock['length'];
|
|
break;
|
|
case 0xF004:
|
|
// Core
|
|
if (!$bInGroup) {
|
|
$this->oCurrentGroup = null;
|
|
}
|
|
// OfficeArtSpContainer
|
|
$fileBlock = $this->readRecordOfficeArtSpContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $fileBlock['length'];
|
|
$data['recLen'] -= $fileBlock['length'];
|
|
// Core
|
|
//@todo
|
|
if (!is_null($fileBlock['shape'])) {
|
|
switch ($this->inMainType) {
|
|
case self::RT_NOTES:
|
|
$arrayIdxSlide = array_flip($this->arrayNotes);
|
|
if ($this->currentNote > 0 && isset($arrayIdxSlide[$this->currentNote])) {
|
|
$oSlide = $this->oPhpPresentation->getSlide($arrayIdxSlide[$this->currentNote]);
|
|
if ($oSlide->getNote()->getShapeCollection()->count() == 0) {
|
|
$oSlide->getNote()->addShape($fileBlock['shape']);
|
|
}
|
|
}
|
|
break;
|
|
case self::RT_SLIDE:
|
|
if ($bInGroup) {
|
|
$this->oCurrentGroup->addShape($fileBlock['shape']);
|
|
} else {
|
|
$this->oPhpPresentation->getActiveSlide()->addShape($fileBlock['shape']);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
} while ($data['recLen'] > 0);
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtTertiaryFOPT record specifies a table of OfficeArtRGFOPTE records,.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd950206(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtTertiaryFOPT($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF122) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
|
|
$officeArtFOPTE = array();
|
|
for ($inc = 0; $inc < $data['recInstance']; $inc++) {
|
|
$opid = self::getInt2d($this->streamPowerpointDocument, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$optOp = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$officeArtFOPTE[] = array(
|
|
'opid' => ($opid >> 0) & bindec('11111111111111'),
|
|
'fBid' => ($opid >> 14) & bindec('1'),
|
|
'fComplex' => ($opid >> 15) & bindec('1'),
|
|
'op' => $optOp,
|
|
);
|
|
}
|
|
//@link : http://code.metager.de/source/xref/kde/calligra/filters/libmso/OPID
|
|
foreach ($officeArtFOPTE as $opt) {
|
|
switch ($opt['opid']) {
|
|
case 0x039F:
|
|
// Table properties
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd922773(v=office.12).aspx
|
|
break;
|
|
case 0x03A0:
|
|
// Table Row Properties
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd923419(v=office.12).aspx
|
|
if ($opt['fComplex'] == 0x1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
}
|
|
break;
|
|
case 0x03A9:
|
|
// GroupShape : metroBlob
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd943388(v=office.12).aspx
|
|
if ($opt['fComplex'] == 0x1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
}
|
|
break;
|
|
case 0x01FF:
|
|
// Line Style Boolean
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd951605(v=office.12).aspx
|
|
break;
|
|
default:
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($opt['opid']).')');
|
|
}
|
|
}
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtDgContainer record specifies the container for all the file records for the objects in a drawing.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd924455(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtDgContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF002) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// drawingData
|
|
$drawingData = $this->readRecordOfficeArtFDG($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $drawingData['length'];
|
|
// regroupItems
|
|
//@todo
|
|
// groupShape
|
|
$groupShape = $this->readRecordOfficeArtSpgrContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $groupShape['length'];
|
|
// shape
|
|
$shape = $this->readRecordOfficeArtSpContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $shape['length'];
|
|
// solvers1
|
|
//@todo
|
|
// deletedShapes
|
|
//@todo
|
|
// solvers1
|
|
//@todo
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtFDG record specifies the number of shapes, the drawing identifier, and the shape identifier of the last shape in a drawing.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd946757(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtFDG($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] <= 0xFFE && $data['recType'] == 0xF008 && $data['recLen'] == 0x00000008) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtFOPT record specifies a table of OfficeArtRGFOPTE records.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943404(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtFOPT($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF00B) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd906086(v=office.12).aspx
|
|
$officeArtFOPTE = array();
|
|
for ($inc = 0; $inc < $data['recInstance']; $inc++) {
|
|
$opid = self::getInt2d($this->streamPowerpointDocument, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$data['recLen'] -= 2;
|
|
$optOp = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$data['recLen'] -= 4;
|
|
$officeArtFOPTE[] = array(
|
|
'opid' => ($opid >> 0) & bindec('11111111111111'),
|
|
'fBid' => ($opid >> 14) & bindec('1'),
|
|
'fComplex' => ($opid >> 15) & bindec('1'),
|
|
'op' => $optOp,
|
|
);
|
|
}
|
|
//@link : http://code.metager.de/source/xref/kde/calligra/filters/libmso/OPID
|
|
foreach ($officeArtFOPTE as $opt) {
|
|
// echo $opt['opid'].'-0x'.dechex($opt['opid']).EOL;
|
|
switch ($opt['opid']) {
|
|
case 0x0004:
|
|
// Transform : rotation
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd949750(v=office.12).aspx
|
|
$arrayReturn['rotation'] = $opt['op'];
|
|
break;
|
|
case 0x007F:
|
|
// Transform : Protection Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909131(v=office.12).aspx
|
|
break;
|
|
case 0x0080:
|
|
// Text : ltxid
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947446(v=office.12).aspx
|
|
break;
|
|
case 0x0081:
|
|
// Text : dxTextLeft
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd953234(v=office.12).aspx
|
|
$arrayReturn['insetLeft'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x0082:
|
|
// Text : dyTextTop
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd925068(v=office.12).aspx
|
|
$arrayReturn['insetTop'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x0083:
|
|
// Text : dxTextRight
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd906782(v=office.12).aspx
|
|
$arrayReturn['insetRight'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x0084:
|
|
// Text : dyTextBottom
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd772858(v=office.12).aspx
|
|
$arrayReturn['insetBottom'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x0085:
|
|
// Text : WrapText
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd924770(v=office.12).aspx
|
|
break;
|
|
case 0x0087:
|
|
// Text : anchorText
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948575(v=office.12).aspx
|
|
break;
|
|
case 0x00BF:
|
|
// Text : Text Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950905(v=office.12).aspx
|
|
break;
|
|
case 0x0104:
|
|
// Blip : pib
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd772837(v=office.12).aspx
|
|
if ($opt['fComplex'] == 0) {
|
|
$arrayReturn['pib'] = $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
} else {
|
|
// pib Complex
|
|
}
|
|
break;
|
|
case 0x13F:
|
|
// Blip Boolean Properties
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd944215(v=office.12).aspx
|
|
break;
|
|
case 0x140:
|
|
// Geometry : geoLeft
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947489(v=office.12).aspx
|
|
// print_r('geoLeft : '.$opt['op'].EOL);
|
|
break;
|
|
case 0x141:
|
|
// Geometry : geoTop
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949459(v=office.12).aspx
|
|
// print_r('geoTop : '.$opt['op'].EOL);
|
|
break;
|
|
case 0x142:
|
|
// Geometry : geoRight
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947117(v=office.12).aspx
|
|
// print_r('geoRight : '.$opt['op'].EOL);
|
|
break;
|
|
case 0x143:
|
|
// Geometry : geoBottom
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948602(v=office.12).aspx
|
|
// print_r('geoBottom : '.$opt['op'].EOL);
|
|
break;
|
|
case 0x144:
|
|
// Geometry : shapePath
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd945249(v=office.12).aspx
|
|
$arrayReturn['line'] = true;
|
|
break;
|
|
case 0x145:
|
|
// Geometry : pVertices
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949814(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x146:
|
|
// Geometry : pSegmentInfo
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd905742(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x155:
|
|
// Geometry : pAdjustHandles
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd905890(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x156:
|
|
// Geometry : pGuides
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd910801(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x157:
|
|
// Geometry : pInscribe
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd904889(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x17F:
|
|
// Geometry Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd944968(v=office.12).aspx
|
|
break;
|
|
case 0x0180:
|
|
// Fill : fillType
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947909(v=office.12).aspx
|
|
break;
|
|
case 0x0181:
|
|
// Fill : fillColor
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd921332(v=office.12).aspx
|
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
// echo 'fillColor : '.$strColor.EOL;
|
|
break;
|
|
case 0x0183:
|
|
// Fill : fillBackColor
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950634(v=office.12).aspx
|
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
// echo 'fillBackColor : '.$strColor.EOL;
|
|
break;
|
|
case 0x0193:
|
|
// Fill : fillRectRight
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951294(v=office.12).aspx
|
|
// echo 'fillRectRight : '.\PhpOffice\Common\Drawing::emuToPixels($opt['op']).EOL;
|
|
break;
|
|
case 0x0194:
|
|
// Fill : fillRectBottom
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd910194(v=office.12).aspx
|
|
// echo 'fillRectBottom : '.\PhpOffice\Common\Drawing::emuToPixels($opt['op']).EOL;
|
|
break;
|
|
case 0x01BF:
|
|
// Fill : Fill Style Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909380(v=office.12).aspx
|
|
break;
|
|
case 0x01C0:
|
|
// Line Style : lineColor
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd920397(v=office.12).aspx
|
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0');
|
|
$arrayReturn['lineColor'] = $strColor;
|
|
break;
|
|
case 0x01C1:
|
|
// Line Style : lineOpacity
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd923433(v=office.12).aspx
|
|
// echo 'lineOpacity : '.dechex($opt['op']).EOL;
|
|
break;
|
|
case 0x01C2:
|
|
// Line Style : lineBackColor
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947669(v=office.12).aspx
|
|
break;
|
|
case 0x01CB:
|
|
// Line Style : lineWidth
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd926964(v=office.12).aspx
|
|
$arrayReturn['lineWidth'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x01D6:
|
|
// Line Style : lineJoinStyle
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909643(v=office.12).aspx
|
|
break;
|
|
case 0x01D7:
|
|
// Line Style : lineEndCapStyle
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd925071(v=office.12).aspx
|
|
break;
|
|
case 0x01FF:
|
|
// Line Style : Line Style Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951605(v=office.12).aspx
|
|
break;
|
|
case 0x0201:
|
|
// Shadow Style : shadowColor
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd923454(v=office.12).aspx
|
|
break;
|
|
case 0x0204:
|
|
// Shadow Style : shadowOpacity
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd920720(v=office.12).aspx
|
|
break;
|
|
case 0x0205:
|
|
// Shadow Style : shadowOffsetX
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd945280(v=office.12).aspx
|
|
$arrayReturn['shadowOffsetX'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x0206:
|
|
// Shadow Style : shadowOffsetY
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd907855(v=office.12).aspx
|
|
$arrayReturn['shadowOffsetY'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']);
|
|
break;
|
|
case 0x023F:
|
|
// Shadow Style : Shadow Style Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947887(v=office.12).aspx
|
|
break;
|
|
case 0x0304:
|
|
// Shape : bWMode
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947659(v=office.12).aspx
|
|
break;
|
|
case 0x033F:
|
|
// Shape Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951345(v=office.12).aspx
|
|
break;
|
|
case 0x0380:
|
|
// Group Shape Property Set : wzName
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950681(v=office.12).aspx
|
|
if ($opt['fComplex'] == 1) {
|
|
$arrayReturn['length'] += $opt['op'];
|
|
$data['recLen'] -= $opt['op'];
|
|
}
|
|
break;
|
|
case 0x03BF:
|
|
// Group Shape Property Set : Group Shape Boolean Properties
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949807(v=office.12).aspx
|
|
break;
|
|
default:
|
|
// throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($opt['opid']).')');
|
|
}
|
|
}
|
|
if ($data['recLen'] > 0) {
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtFPSPL record specifies the former hierarchical position of the containing object that is either a shape or a group of shapes.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd947479(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtFPSPL($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF11D && $data['recLen'] == 0x00000004) {
|
|
$arrayReturn['length'] += 8;
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtFSP record specifies an instance of a shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925898(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtFSP($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x2 && $data['recType'] == 0xF00A && $data['recLen'] == 0x00000008) {
|
|
$arrayReturn['length'] += 8;
|
|
// spid
|
|
$arrayReturn['length'] += 4;
|
|
// data
|
|
$data = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$arrayReturn['fGroup'] = ($data >> 0) & bindec('1');
|
|
$arrayReturn['fChild'] = ($data >> 1) & bindec('1');
|
|
$arrayReturn['fPatriarch'] = ($data >> 2) & bindec('1');
|
|
$arrayReturn['fDeleted'] = ($data >> 3) & bindec('1');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtFSPGR record specifies the coordinate system of the group shape that the anchors of the child shape are expressed in.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925381(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtFSPGR($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x1 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF009 && $data['recLen'] == 0x00000010) {
|
|
$arrayReturn['length'] += 8;
|
|
//$arrShapeGroup['xLeft'] = self::getInt4d($this->streamPowerpointDocument, $pos);
|
|
$arrayReturn['length'] += 4;
|
|
//$arrShapeGroup['yTop'] = self::getInt4d($this->streamPowerpointDocument, $pos);
|
|
$arrayReturn['length'] += 4;
|
|
//$arrShapeGroup['xRight'] = self::getInt4d($this->streamPowerpointDocument, $pos);
|
|
$arrayReturn['length'] += 4;
|
|
//$arrShapeGroup['yBottom'] = self::getInt4d($this->streamPowerpointDocument, $pos);
|
|
$arrayReturn['length'] += 4;
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* The OfficeArtSecondaryFOPT record specifies a table of OfficeArtRGFOPTE records.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd950259(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtSecondaryFOPT($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF121) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies information about a shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd950927(v=office.12).aspx
|
|
*/
|
|
private function readRecordOfficeArtClientData($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF011) {
|
|
$arrayReturn['length'] += 8;
|
|
// shapeFlagsAtom (9 bytes)
|
|
$dataShapeFlagsAtom = $this->readRecordShapeFlagsAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataShapeFlagsAtom['length'];
|
|
|
|
// shapeFlags10Atom (9 bytes)
|
|
$dataShapeFlags10Atom = $this->readRecordShapeFlags10Atom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataShapeFlags10Atom['length'];
|
|
|
|
// exObjRefAtom (12 bytes)
|
|
$dataExObjRefAtom = $this->readRecordExObjRefAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataExObjRefAtom['length'];
|
|
|
|
// animationInfo (variable)
|
|
$dataAnimationInfo = $this->readRecordAnimationInfoContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataAnimationInfo['length'];
|
|
|
|
// mouseClickInteractiveInfo (variable)
|
|
$mouseClickInfo = $this->readRecordMouseClickInteractiveInfoContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $mouseClickInfo['length'];
|
|
|
|
// mouseOverInteractiveInfo (variable)
|
|
$mouseOverInfo = $this->readRecordMouseOverInteractiveInfoContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $mouseOverInfo['length'];
|
|
|
|
// placeholderAtom (16 bytes)
|
|
$dataPlaceholderAtom = $this->readRecordPlaceholderAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataPlaceholderAtom['length'];
|
|
|
|
// recolorInfoAtom (variable)
|
|
$dataRecolorInfo = $this->readRecordRecolorInfoAtom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataRecolorInfo['length'];
|
|
|
|
// rgShapeClientRoundtripData (variable)
|
|
$array = array(
|
|
self::RT_PROGTAGS,
|
|
self::RT_ROUNDTRIPNEWPLACEHOLDERID12ATOM,
|
|
self::RT_ROUNDTRIPSHAPEID12ATOM,
|
|
self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM,
|
|
self::RT_ROUNDTRIPSHAPECHECKSUMFORCL12ATOM,
|
|
);
|
|
do {
|
|
$dataHeaderRG = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']);
|
|
if (in_array($dataHeaderRG['recType'], $array)) {
|
|
switch ($dataHeaderRG['recType']) {
|
|
case self::RT_PROGTAGS:
|
|
$dataRG = $this->readRecordShapeProgTagsContainer($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataRG['length'];
|
|
break;
|
|
case self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM:
|
|
$dataRG = $this->readRecordRoundTripHFPlaceholder12Atom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataRG['length'];
|
|
break;
|
|
case self::RT_ROUNDTRIPSHAPEID12ATOM:
|
|
$dataRG = $this->readRecordRoundTripShapeId12Atom($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += $dataRG['length'];
|
|
break;
|
|
default:
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($dataHeaderRG['recType']).')');
|
|
}
|
|
}
|
|
} while (in_array($dataHeaderRG['recType'], $array));
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a persist object directory. Each persist object identifier specified MUST be unique in that persist object directory.
|
|
* @link http://msdn.microsoft.com/en-us/library/dd952680(v=office.12).aspx
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @throws \Exception
|
|
*/
|
|
private function readRecordPersistDirectoryAtom($stream, $pos)
|
|
{
|
|
$rHeader = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_PERSISTDIRECTORYATOM) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : PersistDirectoryAtom > RecordHeader).');
|
|
}
|
|
// rgPersistDirEntry
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd947347(v=office.12).aspx
|
|
do {
|
|
$data = self::getInt4d($stream, $pos);
|
|
$pos += 4;
|
|
$rHeader['recLen'] -= 4;
|
|
//$persistId = ($data >> 0) & bindec('11111111111111111111');
|
|
$cPersist = ($data >> 20) & bindec('111111111111');
|
|
|
|
$rgPersistOffset = array();
|
|
for ($inc = 0; $inc < $cPersist; $inc++) {
|
|
$rgPersistOffset[] = self::getInt4d($stream, $pos);
|
|
$pos += 4;
|
|
$rHeader['recLen'] -= 4;
|
|
}
|
|
} while ($rHeader['recLen'] > 0);
|
|
$this->rgPersistDirEntry = $rgPersistOffset;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies information about the headers (1) and footers within a slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd904856(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordPerSlideHeadersFootersContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_HEADERSFOOTERS) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies whether a shape is a placeholder shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923930(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordPlaceholderAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PLACEHOLDERATOM && $data['recLen'] == 0x00000008) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a collection of re-color mappings for a metafile ([MS-WMF]).
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd904899(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordRecolorInfoAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_RECOLORINFOATOM) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies that a shape is a header or footerplaceholder shape.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910800(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordRoundTripHFPlaceholder12Atom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM && $data['recLen'] == 0x00000001) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a shape identifier.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd772926(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordRoundTripShapeId12Atom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPSHAPEID12ATOM && $data['recLen'] == 0x00000004) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies information about a slide that synchronizes to a slide in a slide library.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordRoundTripSlideSyncInfo12Container($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPSLIDESYNCINFO12) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies shape-level Boolean flags.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd908949(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordShapeFlags10Atom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SHAPEFLAGS10ATOM && $data['recLen'] == 0x00000001) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies shape-level Boolean flags.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925824(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordShapeFlagsAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SHAPEATOM && $data['recLen'] == 0x00000001) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies programmable tags with additional binary shape data.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd911033(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordShapeProgBinaryTagContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGBINARYTAG) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies programmable tags with additional shape data.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd911266(v=office.12).aspx
|
|
*/
|
|
private function readRecordShapeProgTagsContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGTAGS) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
|
|
$length = 0;
|
|
do {
|
|
$dataHeaderRG = $this->loadRecordHeader($stream, $pos + $arrayReturn['length'] + $length);
|
|
switch ($dataHeaderRG['recType']) {
|
|
case self::RT_PROGBINARYTAG:
|
|
$dataRG = $this->readRecordShapeProgBinaryTagContainer($stream, $pos + $arrayReturn['length'] + $length);
|
|
$length += $dataRG['length'];
|
|
break;
|
|
//case self::RT_PROGSTRINGTAG:
|
|
default:
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
} while ($length < $data['recLen']);
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies information about a slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx
|
|
*/
|
|
private function readRecordSlideAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x2 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDEATOM) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// slideAtom > geom
|
|
$arrayReturn['length'] += 4;
|
|
// slideAtom > rgPlaceholderTypes
|
|
$rgPlaceholderTypes = array();
|
|
for ($inc = 0; $inc < 8; $inc++) {
|
|
$rgPlaceholderTypes[] = self::getInt1d($this->streamPowerpointDocument, $pos);
|
|
$arrayReturn['length'] += 1;
|
|
}
|
|
|
|
// slideAtom > masterIdRef
|
|
$arrayReturn['length'] += 4;
|
|
// slideAtom > notesIdRef
|
|
$arrayReturn['length'] += 4;
|
|
// slideAtom > slideFlags
|
|
$arrayReturn['length'] += 2;
|
|
// slideAtom > unused;
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies a presentation slide or title master slide.
|
|
* @param string $stream
|
|
* @param int $pos
|
|
* @throws \Exception
|
|
* @link http://msdn.microsoft.com/en-us/library/dd946323(v=office.12).aspx
|
|
*/
|
|
private function readRecordSlideContainer($stream, $pos)
|
|
{
|
|
// Core
|
|
$this->oPhpPresentation->createSlide();
|
|
$this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1);
|
|
|
|
// *** slideAtom (32 bytes)
|
|
$slideAtom = $this->readRecordSlideAtom($stream, $pos);
|
|
if ($slideAtom['length'] == 0) {
|
|
throw new \Exception('PowerPoint97 Reader : record SlideAtom');
|
|
}
|
|
$pos += $slideAtom['length'];
|
|
|
|
// *** slideShowSlideInfoAtom (24 bytes)
|
|
$slideShowInfoAtom = $this->readRecordSlideShowSlideInfoAtom($stream, $pos);
|
|
$pos += $slideShowInfoAtom['length'];
|
|
|
|
// *** perSlideHFContainer (variable) : optional
|
|
$perSlideHFContainer = $this->readRecordPerSlideHeadersFootersContainer($stream, $pos);
|
|
$pos += $perSlideHFContainer['length'];
|
|
|
|
// *** rtSlideSyncInfo12 (variable) : optional
|
|
$rtSlideSyncInfo12 = $this->readRecordRoundTripSlideSyncInfo12Container($stream, $pos);
|
|
$pos += $rtSlideSyncInfo12['length'];
|
|
|
|
// *** drawing (variable)
|
|
$drawing = $this->readRecordDrawingContainer($stream, $pos);
|
|
$pos += $drawing['length'];
|
|
|
|
// *** slideSchemeColorSchemeAtom (40 bytes)
|
|
$slideSchemeColorAtom = $this->readRecordSlideSchemeColorSchemeAtom($stream, $pos);
|
|
if ($slideSchemeColorAtom['length'] == 0) {
|
|
throw new \Exception('PowerPoint97 Reader : record SlideSchemeColorSchemeAtom');
|
|
}
|
|
$pos += $slideSchemeColorAtom['length'];
|
|
|
|
// *** slideNameAtom (variable)
|
|
$slideNameAtom = $this->readRecordSlideNameAtom($stream, $pos);
|
|
$pos += $slideNameAtom['length'];
|
|
|
|
// *** slideProgTagsContainer (variable).
|
|
$slideProgTags = $this->readRecordSlideProgTagsContainer($stream, $pos);
|
|
$pos += $slideProgTags['length'];
|
|
|
|
// *** rgRoundTripSlide (variable)
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies the name of a slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd906297(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordSlideNameAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'slideName' => '',
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x003 && $data['recType'] == self::RT_CSTRING && $data['recLen'] % 2 == 0) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$strLen = ($data['recLen'] / 2);
|
|
for ($inc = 0; $inc < $strLen; $inc++) {
|
|
$char = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['slideName'] .= Text::chr($char);
|
|
}
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies a slide number metacharacter.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd945703(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordSlideNumberMCAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDENUMBERMETACHARATOM && $data['recLen'] == 0x00000004) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Datas
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies programmable tags with additional slide data.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd951946(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordSlideProgTagsContainer($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGTAGS) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A container record that specifies the color scheme used by a slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd949420(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordSlideSchemeColorSchemeAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x001 && $data['recType'] == self::RT_COLORSCHEMEATOM && $data['recLen'] == 0x00000020) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length
|
|
$rgSchemeColor = array();
|
|
for ($inc = 0; $inc <= 7; $inc++) {
|
|
$rgSchemeColor[] = array(
|
|
'red' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4),
|
|
'green' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4 + 1),
|
|
'blue' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4 + 2),
|
|
);
|
|
}
|
|
$arrayReturn['length'] += (8 * 4);
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* An atom record that specifies what transition effect to perform during a slide show, and how to advance to the next presentation slide.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943408(v=office.12).aspx
|
|
* @return array
|
|
*/
|
|
private function readRecordSlideShowSlideInfoAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDESHOWSLIDEINFOATOM && $data['recLen'] == 0x00000010) {
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// Length;
|
|
$arrayReturn['length'] += $data['recLen'];
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* UserEditAtom
|
|
* @link http://msdn.microsoft.com/en-us/library/dd945746(v=office.12).aspx
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @throws \Exception
|
|
*/
|
|
private function readRecordUserEditAtom($stream, $pos)
|
|
{
|
|
$rHeader = $this->loadRecordHeader($stream, $pos);
|
|
$pos += 8;
|
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_USEREDITATOM || ($rHeader['recLen'] != 0x0000001C && $rHeader['recLen'] != 0x00000020)) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > RecordHeader).');
|
|
}
|
|
|
|
// lastSlideIdRef
|
|
$pos += 4;
|
|
// version
|
|
$pos += 2;
|
|
|
|
// minorVersion
|
|
$minorVersion = self::getInt1d($stream, $pos);
|
|
$pos += 1;
|
|
if ($minorVersion != 0x00) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > minorVersion).');
|
|
}
|
|
|
|
// majorVersion
|
|
$majorVersion = self::getInt1d($stream, $pos);
|
|
$pos += 1;
|
|
if ($majorVersion != 0x03) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > majorVersion).');
|
|
}
|
|
|
|
// offsetLastEdit
|
|
$pos += 4;
|
|
// offsetPersistDirectory
|
|
$this->offsetPersistDirectory = self::getInt4d($stream, $pos);
|
|
$pos += 4;
|
|
|
|
// docPersistIdRef
|
|
$docPersistIdRef = self::getInt4d($stream, $pos);
|
|
$pos += 4;
|
|
if ($docPersistIdRef != 0x00000001) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > docPersistIdRef).');
|
|
}
|
|
|
|
// persistIdSeed
|
|
$pos += 4;
|
|
// lastView
|
|
$pos += 2;
|
|
// unused
|
|
$pos += 2;
|
|
}
|
|
|
|
/**
|
|
* A structure that specifies the character-level formatting of a run of text.
|
|
* @param string $stream
|
|
* @param int $pos
|
|
* @param int $strLenRT
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd945870(v=office.12).aspx
|
|
*/
|
|
private function readStructureTextCFRun($stream, $pos, $strLenRT)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'strLenRT' => $strLenRT,
|
|
);
|
|
|
|
// rgTextCFRun
|
|
$countRgTextCFRun = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['strLenRT'] -= $countRgTextCFRun;
|
|
$arrayReturn['length'] += 4;
|
|
$arrayReturn['partLength'] = $countRgTextCFRun;
|
|
|
|
$masks = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
|
|
$masksData = array();
|
|
$masksData['bold'] = ($masks >> 0) & bindec('1');
|
|
$masksData['italic'] = ($masks >> 1) & bindec('1');
|
|
$masksData['underline'] = ($masks >> 2) & bindec('1');
|
|
$masksData['unused1'] = ($masks >> 3) & bindec('1');
|
|
$masksData['shadow'] = ($masks >> 4) & bindec('1');
|
|
$masksData['fehint'] = ($masks >> 5) & bindec('1');
|
|
$masksData['unused2'] = ($masks >> 6) & bindec('1');
|
|
$masksData['kumi'] = ($masks >> 7) & bindec('1');
|
|
$masksData['unused3'] = ($masks >> 8) & bindec('1');
|
|
$masksData['emboss'] = ($masks >> 9) & bindec('1');
|
|
$masksData['fHasStyle'] = ($masks >> 10) & bindec('1111');
|
|
$masksData['unused4'] = ($masks >> 14) & bindec('11');
|
|
$masksData['typeface'] = ($masks >> 16) & bindec('1');
|
|
$masksData['size'] = ($masks >> 17) & bindec('1');
|
|
$masksData['color'] = ($masks >> 18) & bindec('1');
|
|
$masksData['position'] = ($masks >> 19) & bindec('1');
|
|
$masksData['pp10ext'] = ($masks >> 20) & bindec('1');
|
|
$masksData['oldEATypeface'] = ($masks >> 21) & bindec('1');
|
|
$masksData['ansiTypeface'] = ($masks >> 22) & bindec('1');
|
|
$masksData['symbolTypeface'] = ($masks >> 23) & bindec('1');
|
|
$masksData['newEATypeface'] = ($masks >> 24) & bindec('1');
|
|
$masksData['csTypeface'] = ($masks >> 25) & bindec('1');
|
|
$masksData['pp11ext'] = ($masks >> 26) & bindec('1');
|
|
if ($masksData['bold'] == 1 || $masksData['italic'] == 1 || $masksData['underline'] == 1 || $masksData['shadow'] == 1 || $masksData['fehint'] == 1 || $masksData['kumi'] == 1 || $masksData['emboss'] == 1 || $masksData['fHasStyle'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
|
|
$fontStyleFlags = array();
|
|
$fontStyleFlags['bold'] = ($data >> 0) & bindec('1');
|
|
$fontStyleFlags['italic'] = ($data >> 1) & bindec('1');
|
|
$fontStyleFlags['underline'] = ($data >> 2) & bindec('1');
|
|
$fontStyleFlags['unused1'] = ($data >> 3) & bindec('1');
|
|
$fontStyleFlags['shadow'] = ($data >> 4) & bindec('1');
|
|
$fontStyleFlags['fehint'] = ($data >> 5) & bindec('1');
|
|
$fontStyleFlags['unused2'] = ($data >> 6) & bindec('1');
|
|
$fontStyleFlags['kumi'] = ($data >> 7) & bindec('1');
|
|
$fontStyleFlags['unused3'] = ($data >> 8) & bindec('1');
|
|
$fontStyleFlags['emboss'] = ($data >> 9) & bindec('1');
|
|
$fontStyleFlags['pp9rt'] = ($data >> 10) & bindec('1111');
|
|
$fontStyleFlags['unused4'] = ($data >> 14) & bindec('11');
|
|
|
|
$arrayReturn['bold'] = ($fontStyleFlags['bold'] == 1) ? true : false;
|
|
$arrayReturn['italic'] = ($fontStyleFlags['italic'] == 1) ? true : false;
|
|
$arrayReturn['underline'] = ($fontStyleFlags['underline'] == 1) ? true : false;
|
|
}
|
|
if ($masksData['typeface'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['fontName'] = isset($this->arrayFonts[$data]) ? $this->arrayFonts[$data] : '';
|
|
}
|
|
if ($masksData['oldEATypeface'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['ansiTypeface'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['symbolTypeface'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['size'] == 1) {
|
|
$arrayReturn['fontSize'] = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['color'] == 1) {
|
|
$red = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$green = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$blue = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$index = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
|
|
if ($index == 0xFE) {
|
|
$strColor = str_pad(dechex($red), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex($green), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex($blue), 2, STR_PAD_LEFT, '0');
|
|
|
|
$arrayReturn['color'] = new Color('FF'.$strColor);
|
|
}
|
|
}
|
|
if ($masksData['position'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A structure that specifies the paragraph-level formatting of a run of text.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @param integer $strLenRT
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923535(v=office.12).aspx
|
|
*/
|
|
private function readStructureTextPFRun($stream, $pos, $strLenRT)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'strLenRT' => $strLenRT,
|
|
);
|
|
|
|
// rgTextPFRun
|
|
$countRgTextPFRun = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['strLenRT'] -= $countRgTextPFRun;
|
|
$arrayReturn['length'] += 4;
|
|
|
|
// indent
|
|
$arrayReturn['length'] += 2;
|
|
|
|
$masks = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
|
|
$masksData = array();
|
|
$masksData['hasBullet'] = ($masks >> 0) & bindec('1');
|
|
$masksData['bulletHasFont'] = ($masks >> 1) & bindec('1');
|
|
$masksData['bulletHasColor'] = ($masks >> 2) & bindec('1');
|
|
$masksData['bulletHasSize'] = ($masks >> 3) & bindec('1');
|
|
$masksData['bulletFont'] = ($masks >> 4) & bindec('1');
|
|
$masksData['bulletColor'] = ($masks >> 5) & bindec('1');
|
|
$masksData['bulletSize'] = ($masks >> 6) & bindec('1');
|
|
$masksData['bulletChar'] = ($masks >> 7) & bindec('1');
|
|
$masksData['leftMargin'] = ($masks >> 8) & bindec('1');
|
|
$masksData['unused'] = ($masks >> 9) & bindec('1');
|
|
$masksData['indent'] = ($masks >> 10) & bindec('1');
|
|
$masksData['align'] = ($masks >> 11) & bindec('1');
|
|
$masksData['lineSpacing'] = ($masks >> 12) & bindec('1');
|
|
$masksData['spaceBefore'] = ($masks >> 13) & bindec('1');
|
|
$masksData['spaceAfter'] = ($masks >> 14) & bindec('1');
|
|
$masksData['defaultTabSize'] = ($masks >> 15) & bindec('1');
|
|
$masksData['fontAlign'] = ($masks >> 16) & bindec('1');
|
|
$masksData['charWrap'] = ($masks >> 17) & bindec('1');
|
|
$masksData['wordWrap'] = ($masks >> 18) & bindec('1');
|
|
$masksData['overflow'] = ($masks >> 19) & bindec('1');
|
|
$masksData['tabStops'] = ($masks >> 20) & bindec('1');
|
|
$masksData['textDirection'] = ($masks >> 21) & bindec('1');
|
|
$masksData['reserved1'] = ($masks >> 22) & bindec('1');
|
|
$masksData['bulletBlip'] = ($masks >> 23) & bindec('1');
|
|
$masksData['bulletScheme'] = ($masks >> 24) & bindec('1');
|
|
$masksData['bulletHasScheme'] = ($masks >> 25) & bindec('1');
|
|
|
|
$bulletFlags = array();
|
|
if ($masksData['hasBullet'] == 1 || $masksData['bulletHasFont'] == 1 || $masksData['bulletHasColor'] == 1 || $masksData['bulletHasSize'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
|
|
$bulletFlags['fHasBullet'] = ($data >> 0) & bindec('1');
|
|
$bulletFlags['fBulletHasFont'] = ($data >> 1) & bindec('1');
|
|
$bulletFlags['fBulletHasColor'] = ($data >> 2) & bindec('1');
|
|
$bulletFlags['fBulletHasSize'] = ($data >> 3) & bindec('1');
|
|
}
|
|
if ($masksData['bulletChar'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['bulletChar'] = chr($data);
|
|
}
|
|
if ($masksData['bulletFont'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['bulletSize'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['bulletColor'] == 1) {
|
|
$red = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$green = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$blue = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
$index = self::getInt1d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 1;
|
|
|
|
if ($index == 0xFE) {
|
|
$strColor = str_pad(dechex($red), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex($green), 2, STR_PAD_LEFT, '0');
|
|
$strColor .= str_pad(dechex($blue), 2, STR_PAD_LEFT, '0');
|
|
}
|
|
}
|
|
if ($masksData['align'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
switch ($data) {
|
|
case 0x0000:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_LEFT;
|
|
break;
|
|
case 0x0001:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_CENTER;
|
|
break;
|
|
case 0x0002:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_RIGHT;
|
|
break;
|
|
case 0x0003:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_JUSTIFY;
|
|
break;
|
|
case 0x0004:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_DISTRIBUTED;
|
|
break;
|
|
case 0x0005:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_DISTRIBUTED;
|
|
break;
|
|
case 0x0006:
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_JUSTIFY;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ($masksData['lineSpacing'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['spaceBefore'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['spaceAfter'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['leftMargin'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['leftMargin'] = (int)round($data/6);
|
|
}
|
|
if ($masksData['indent'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayReturn['indent'] = (int)round($data/6);
|
|
}
|
|
if ($masksData['defaultTabSize'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['tabStops'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($masksData['fontAlign'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['charWrap'] == 1 || $masksData['wordWrap'] == 1 || $masksData['overflow'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['textDirection'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A structure that specifies language and spelling information for a run of text.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @param string $strLenRT
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd909603(v=office.12).aspx
|
|
*/
|
|
private function readStructureTextSIRun($stream, $pos, $strLenRT)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
'strLenRT' => $strLenRT,
|
|
);
|
|
|
|
$arrayReturn['strLenRT'] -= self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
|
|
$data = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
$masksData = array();
|
|
$masksData['spell'] = ($data >> 0) & bindec('1');
|
|
$masksData['lang'] = ($data >> 1) & bindec('1');
|
|
$masksData['altLang'] = ($data >> 2) & bindec('1');
|
|
$masksData['unused1'] = ($data >> 3) & bindec('1');
|
|
$masksData['unused2'] = ($data >> 4) & bindec('1');
|
|
$masksData['fPp10ext'] = ($data >> 5) & bindec('1');
|
|
$masksData['fBidi'] = ($data >> 6) & bindec('1');
|
|
$masksData['unused3'] = ($data >> 7) & bindec('1');
|
|
$masksData['reserved1'] = ($data >> 8) & bindec('1');
|
|
$masksData['smartTag'] = ($data >> 9) & bindec('1');
|
|
|
|
if ($masksData['spell'] == 1) {
|
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$masksSpell = array();
|
|
$masksSpell['error'] = ($data >> 0) & bindec('1');
|
|
$masksSpell['clean'] = ($data >> 1) & bindec('1');
|
|
$masksSpell['grammar'] = ($data >> 2) & bindec('1');
|
|
}
|
|
if ($masksData['lang'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['altLang'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fBidi'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($masksData['fPp10ext'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($masksData['smartTag'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* A structure that specifies tabbing, margins, and indentation for text.
|
|
* @param string $stream
|
|
* @param integer $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922749(v=office.12).aspx
|
|
*/
|
|
private function readStructureTextRuler($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 4;
|
|
|
|
$masksData = array();
|
|
$masksData['fDefaultTabSize'] = ($data >> 0) & bindec('1');
|
|
$masksData['fCLevels'] = ($data >> 1) & bindec('1');
|
|
$masksData['fTabStops'] = ($data >> 2) & bindec('1');
|
|
$masksData['fLeftMargin1'] = ($data >> 3) & bindec('1');
|
|
$masksData['fLeftMargin2'] = ($data >> 4) & bindec('1');
|
|
$masksData['fLeftMargin3'] = ($data >> 5) & bindec('1');
|
|
$masksData['fLeftMargin4'] = ($data >> 6) & bindec('1');
|
|
$masksData['fLeftMargin5'] = ($data >> 7) & bindec('1');
|
|
$masksData['fIndent1'] = ($data >> 8) & bindec('1');
|
|
$masksData['fIndent2'] = ($data >> 9) & bindec('1');
|
|
$masksData['fIndent3'] = ($data >> 10) & bindec('1');
|
|
$masksData['fIndent4'] = ($data >> 11) & bindec('1');
|
|
$masksData['fIndent5'] = ($data >> 12) & bindec('1');
|
|
|
|
if ($masksData['fCLevels'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($masksData['fDefaultTabSize'] == 1) {
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')');
|
|
}
|
|
if ($masksData['fTabStops'] == 1) {
|
|
$count = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayTabStops = array();
|
|
for ($inc = 0; $inc < $count; $inc++) {
|
|
$position = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$type = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
$arrayTabStops[] = array(
|
|
'position' => $position,
|
|
'type' => $type,
|
|
);
|
|
}
|
|
}
|
|
if ($masksData['fLeftMargin1'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fIndent1'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fLeftMargin2'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fIndent2'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fLeftMargin3'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fIndent3'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fLeftMargin4'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fIndent4'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fLeftMargin5'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
if ($masksData['fIndent5'] == 1) {
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']);
|
|
$arrayReturn['length'] += 2;
|
|
}
|
|
|
|
return $arrayReturn;
|
|
}
|
|
|
|
/**
|
|
* @param $stream
|
|
* @param int $pos
|
|
* @throws \Exception
|
|
*/
|
|
private function readRecordNotesContainer($stream, $pos)
|
|
{
|
|
// notesAtom
|
|
$notesAtom = $this->readRecordNotesAtom($stream, $pos);
|
|
$pos += $notesAtom['length'];
|
|
|
|
// drawing
|
|
$drawing = $this->readRecordDrawingContainer($stream, $pos);
|
|
$pos += $drawing['length'];
|
|
|
|
// slideSchemeColorSchemeAtom
|
|
// slideNameAtom
|
|
// slideProgTagsContainer
|
|
// rgNotesRoundTripAtom
|
|
}
|
|
|
|
/**
|
|
* @param $stream
|
|
* @param int $pos
|
|
* @return array
|
|
* @throws \Exception
|
|
*/
|
|
private function readRecordNotesAtom($stream, $pos)
|
|
{
|
|
$arrayReturn = array(
|
|
'length' => 0,
|
|
);
|
|
|
|
$data = $this->loadRecordHeader($stream, $pos);
|
|
if ($data['recVer'] != 0x1 || $data['recInstance'] != 0x000 || $data['recType'] != self::RT_NOTESATOM || $data['recLen'] != 0x00000008) {
|
|
throw new \Exception('File PowerPoint 97 in error (Location : NotesAtom > RecordHeader)');
|
|
}
|
|
// Record Header
|
|
$arrayReturn['length'] += 8;
|
|
// NotesAtom > slideIdRef
|
|
$notesIdRef = self::getInt4d($stream, $pos + $arrayReturn['length']);
|
|
if ($notesIdRef == -2147483648) {
|
|
$notesIdRef = 0;
|
|
}
|
|
$this->currentNote = $notesIdRef;
|
|
$arrayReturn['length'] += 4;
|
|
|
|
// NotesAtom > slideFlags
|
|
$arrayReturn['length'] += 2;
|
|
// NotesAtom > unused
|
|
$arrayReturn['length'] += 2;
|
|
|
|
return $arrayReturn;
|
|
}
|
|
}
|