|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* This file is part of PHPPresentation - A pure PHP library for reading and writing |
|
4
|
|
|
* presentations documents. |
|
5
|
|
|
* |
|
6
|
|
|
* PHPPresentation is free software distributed under the terms of the GNU Lesser |
|
7
|
|
|
* General Public License version 3 as published by the Free Software Foundation. |
|
8
|
|
|
* |
|
9
|
|
|
* For the full copyright and license information, please read the LICENSE |
|
10
|
|
|
* file that was distributed with this source code. For the full list of |
|
11
|
|
|
* contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors. |
|
12
|
|
|
* |
|
13
|
|
|
* @link https://github.com/PHPOffice/PHPPresentation |
|
14
|
|
|
* @copyright 2009-2015 PHPPresentation contributors |
|
15
|
|
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|
16
|
|
|
*/ |
|
17
|
|
|
|
|
18
|
|
|
namespace PhpOffice\PhpPresentation\Reader; |
|
19
|
|
|
|
|
20
|
|
|
use PhpOffice\Common\Microsoft\OLERead; |
|
21
|
|
|
use PhpOffice\Common\Text; |
|
22
|
|
|
use PhpOffice\PhpPresentation\PhpPresentation; |
|
23
|
|
|
use PhpOffice\PhpPresentation\AbstractShape; |
|
24
|
|
|
use PhpOffice\PhpPresentation\Shape; |
|
25
|
|
|
use PhpOffice\PhpPresentation\Shape\Drawing; |
|
26
|
|
|
use PhpOffice\PhpPresentation\Shape\Group; |
|
27
|
|
|
use PhpOffice\PhpPresentation\Shape\Hyperlink; |
|
28
|
|
|
use PhpOffice\PhpPresentation\Shape\Line; |
|
29
|
|
|
use PhpOffice\PhpPresentation\Shape\RichText; |
|
30
|
|
|
use PhpOffice\PhpPresentation\Style\Alignment; |
|
31
|
|
|
use PhpOffice\PhpPresentation\Style\Color; |
|
32
|
|
|
use PhpOffice\PhpPresentation\Style\Bullet; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Serialized format reader |
|
36
|
|
|
*/ |
|
37
|
|
|
class PowerPoint97 implements ReaderInterface |
|
38
|
|
|
{ |
|
39
|
|
|
const OFFICEARTBLIPEMF = 0xF01A; |
|
40
|
|
|
const OFFICEARTBLIPWMF = 0xF01B; |
|
41
|
|
|
const OFFICEARTBLIPPICT = 0xF01C; |
|
42
|
|
|
const OFFICEARTBLIPJPG = 0xF01D; |
|
43
|
|
|
const OFFICEARTBLIPPNG = 0xF01E; |
|
44
|
|
|
const OFFICEARTBLIPDIB = 0xF01F; |
|
45
|
|
|
const OFFICEARTBLIPTIFF = 0xF029; |
|
46
|
|
|
const OFFICEARTBLIPJPEG = 0xF02A; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd945336(v=office.12).aspx |
|
50
|
|
|
*/ |
|
51
|
|
|
const RT_ANIMATIONINFO = 0x1014; |
|
52
|
|
|
const RT_ANIMATIONINFOATOM = 0x0FF1; |
|
53
|
|
|
const RT_BINARYTAGDATABLOB = 0x138B; |
|
54
|
|
|
const RT_BLIPCOLLECTION9 = 0x07F8; |
|
55
|
|
|
const RT_BLIPENTITY9ATOM = 0x07F9; |
|
56
|
|
|
const RT_BOOKMARKCOLLECTION = 0x07E3; |
|
57
|
|
|
const RT_BOOKMARKENTITYATOM = 0x0FD0; |
|
58
|
|
|
const RT_BOOKMARKSEEDATOM = 0x07E9; |
|
59
|
|
|
const RT_BROADCASTDOCINFO9 = 0x177E; |
|
60
|
|
|
const RT_BROADCASTDOCINFO9ATOM = 0x177F; |
|
61
|
|
|
const RT_BUILDATOM = 0x2B03; |
|
62
|
|
|
const RT_BUILDLIST = 0x2B02; |
|
63
|
|
|
const RT_CHARTBUILD = 0x2B04; |
|
64
|
|
|
const RT_CHARTBUILDATOM = 0x2B05; |
|
65
|
|
|
const RT_COLORSCHEMEATOM = 0x07F0; |
|
66
|
|
|
const RT_COMMENT10 = 0x2EE0; |
|
67
|
|
|
const RT_COMMENT10ATOM = 0x2EE1; |
|
68
|
|
|
const RT_COMMENTINDEX10 = 0x2EE4; |
|
69
|
|
|
const RT_COMMENTINDEX10ATOM = 0x2EE5; |
|
70
|
|
|
const RT_CRYPTSESSION10CONTAINER = 0x2F14; |
|
71
|
|
|
const RT_CURRENTUSERATOM = 0x0FF6; |
|
72
|
|
|
const RT_CSTRING = 0x0FBA; |
|
73
|
|
|
const RT_DATETIMEMETACHARATOM = 0x0FF7; |
|
74
|
|
|
const RT_DEFAULTRULERATOM = 0x0FAB; |
|
75
|
|
|
const RT_DOCROUTINGSLIPATOM = 0x0406; |
|
76
|
|
|
const RT_DIAGRAMBUILD = 0x2B06; |
|
77
|
|
|
const RT_DIAGRAMBUILDATOM = 0x2B07; |
|
78
|
|
|
const RT_DIFF10 = 0x2EED; |
|
79
|
|
|
const RT_DIFF10ATOM = 0x2EEE; |
|
80
|
|
|
const RT_DIFFTREE10 = 0x2EEC; |
|
81
|
|
|
const RT_DOCTOOLBARSTATES10ATOM = 0x36B1; |
|
82
|
|
|
const RT_DOCUMENT = 0x03E8; |
|
83
|
|
|
const RT_DOCUMENTATOM = 0x03E9; |
|
84
|
|
|
const RT_DRAWING = 0x040C; |
|
85
|
|
|
const RT_DRAWINGGROUP = 0x040B; |
|
86
|
|
|
const RT_ENDDOCUMENTATOM = 0x03EA; |
|
87
|
|
|
const RT_EXTERNALAVIMOVIE = 0x1006; |
|
88
|
|
|
const RT_EXTERNALCDAUDIO = 0x100E; |
|
89
|
|
|
const RT_EXTERNALCDAUDIOATOM = 0x1012; |
|
90
|
|
|
const RT_EXTERNALHYPERLINK = 0x0FD7; |
|
91
|
|
|
const RT_EXTERNALHYPERLINK9 = 0x0FE4; |
|
92
|
|
|
const RT_EXTERNALHYPERLINKATOM = 0x0FD3; |
|
93
|
|
|
const RT_EXTERNALHYPERLINKFLAGSATOM = 0x1018; |
|
94
|
|
|
const RT_EXTERNALMCIMOVIE = 0x1007; |
|
95
|
|
|
const RT_EXTERNALMEDIAATOM = 0x1004; |
|
96
|
|
|
const RT_EXTERNALMIDIAUDIO = 0x100D; |
|
97
|
|
|
const RT_EXTERNALOBJECTLIST = 0x0409; |
|
98
|
|
|
const RT_EXTERNALOBJECTLISTATOM = 0x040A; |
|
99
|
|
|
const RT_EXTERNALOBJECTREFATOM = 0x0BC1; |
|
100
|
|
|
const RT_EXTERNALOLECONTROL = 0x0FEE; |
|
101
|
|
|
const RT_EXTERNALOLECONTROLATOM = 0x0FFB; |
|
102
|
|
|
const RT_EXTERNALOLEEMBED = 0x0FCC; |
|
103
|
|
|
const RT_EXTERNALOLEEMBEDATOM = 0x0FCD; |
|
104
|
|
|
const RT_EXTERNALOLELINK = 0x0FCE; |
|
105
|
|
|
const RT_EXTERNALOLELINKATOM = 0x0FD1; |
|
106
|
|
|
const RT_EXTERNALOLEOBJECTATOM = 0x0FC3; |
|
107
|
|
|
const RT_EXTERNALOLEOBJECTSTG = 0x1011; |
|
108
|
|
|
const RT_EXTERNALVIDEO = 0x1005; |
|
109
|
|
|
const RT_EXTERNALWAVAUDIOEMBEDDED = 0x100F; |
|
110
|
|
|
const RT_EXTERNALWAVAUDIOEMBEDDEDATOM = 0x1013; |
|
111
|
|
|
const RT_EXTERNALWAVAUDIOLINK = 0x1010; |
|
112
|
|
|
const RT_ENVELOPEDATA9ATOM = 0x1785; |
|
113
|
|
|
const RT_ENVELOPEFLAGS9ATOM = 0x1784; |
|
114
|
|
|
const RT_ENVIRONMENT = 0x03F2; |
|
115
|
|
|
const RT_FONTCOLLECTION = 0x07D5; |
|
116
|
|
|
const RT_FONTCOLLECTION10 = 0x07D6; |
|
117
|
|
|
const RT_FONTEMBEDDATABLOB = 0x0FB8; |
|
118
|
|
|
const RT_FONTEMBEDFLAGS10ATOM = 0x32C8; |
|
119
|
|
|
const RT_FILTERPRIVACYFLAGS10ATOM = 0x36B0; |
|
120
|
|
|
const RT_FONTENTITYATOM = 0x0FB7; |
|
121
|
|
|
const RT_FOOTERMETACHARATOM = 0x0FFA; |
|
122
|
|
|
const RT_GENERICDATEMETACHARATOM = 0x0FF8; |
|
123
|
|
|
const RT_GRIDSPACING10ATOM = 0x040D; |
|
124
|
|
|
const RT_GUIDEATOM = 0x03FB; |
|
125
|
|
|
const RT_HANDOUT = 0x0FC9; |
|
126
|
|
|
const RT_HASHCODEATOM = 0x2B00; |
|
127
|
|
|
const RT_HEADERSFOOTERS = 0x0FD9; |
|
128
|
|
|
const RT_HEADERSFOOTERSATOM = 0x0FDA; |
|
129
|
|
|
const RT_HEADERMETACHARATOM = 0x0FF9; |
|
130
|
|
|
const RT_HTMLDOCINFO9ATOM = 0x177B; |
|
131
|
|
|
const RT_HTMLPUBLISHINFOATOM = 0x177C; |
|
132
|
|
|
const RT_HTMLPUBLISHINFO9 = 0x177D; |
|
133
|
|
|
const RT_INTERACTIVEINFO = 0x0FF2; |
|
134
|
|
|
const RT_INTERACTIVEINFOATOM = 0x0FF3; |
|
135
|
|
|
const RT_KINSOKU = 0x0FC8; |
|
136
|
|
|
const RT_KINSOKUATOM = 0x0FD2; |
|
137
|
|
|
const RT_LEVELINFOATOM = 0x2B0A; |
|
138
|
|
|
const RT_LINKEDSHAPE10ATOM = 0x2EE6; |
|
139
|
|
|
const RT_LINKEDSLIDE10ATOM = 0x2EE7; |
|
140
|
|
|
const RT_LIST = 0x07D0; |
|
141
|
|
|
const RT_MAINMASTER = 0x03F8; |
|
142
|
|
|
const RT_MASTERTEXTPROPATOM = 0x0FA2; |
|
143
|
|
|
const RT_METAFILE = 0x0FC1; |
|
144
|
|
|
const RT_NAMEDSHOW = 0x0411; |
|
145
|
|
|
const RT_NAMEDSHOWS = 0x0410; |
|
146
|
|
|
const RT_NAMEDSHOWSLIDESATOM = 0x0412; |
|
147
|
|
|
const RT_NORMALVIEWSETINFO9 = 0x0414; |
|
148
|
|
|
const RT_NORMALVIEWSETINFO9ATOM = 0x0415; |
|
149
|
|
|
const RT_NOTES= 0x03F0; |
|
150
|
|
|
const RT_NOTESATOM = 0x03F1; |
|
151
|
|
|
const RT_NOTESTEXTVIEWINFO9 = 0x0413; |
|
152
|
|
|
const RT_OUTLINETEXTPROPS9 = 0x0FAE; |
|
153
|
|
|
const RT_OUTLINETEXTPROPS10 = 0x0FB3; |
|
154
|
|
|
const RT_OUTLINETEXTPROPS11 = 0x0FB5; |
|
155
|
|
|
const RT_OUTLINETEXTPROPSHEADER9ATOM = 0x0FAF; |
|
156
|
|
|
const RT_OUTLINETEXTREFATOM = 0x0F9E; |
|
157
|
|
|
const RT_OUTLINEVIEWINFO = 0x0407; |
|
158
|
|
|
const RT_PERSISTDIRECTORYATOM = 0x1772; |
|
159
|
|
|
const RT_PARABUILD = 0x2B08; |
|
160
|
|
|
const RT_PARABUILDATOM = 0x2B09; |
|
161
|
|
|
const RT_PHOTOALBUMINFO10ATOM = 0x36B2; |
|
162
|
|
|
const RT_PLACEHOLDERATOM = 0x0BC3; |
|
163
|
|
|
const RT_PRESENTATIONADVISORFLAGS9ATOM = 0x177A; |
|
164
|
|
|
const RT_PRINTOPTIONSATOM = 0x1770; |
|
165
|
|
|
const RT_PROGBINARYTAG = 0x138A; |
|
166
|
|
|
const RT_PROGSTRINGTAG = 0x1389; |
|
167
|
|
|
const RT_PROGTAGS = 0x1388; |
|
168
|
|
|
const RT_RECOLORINFOATOM = 0x0FE7; |
|
169
|
|
|
const RT_RTFDATETIMEMETACHARATOM = 0x1015; |
|
170
|
|
|
const RT_ROUNDTRIPANIMATIONATOM12ATOM = 0x2B0B; |
|
171
|
|
|
const RT_ROUNDTRIPANIMATIONHASHATOM12ATOM = 0x2B0D; |
|
172
|
|
|
const RT_ROUNDTRIPCOLORMAPPING12ATOM = 0x040F; |
|
173
|
|
|
const RT_ROUNDTRIPCOMPOSITEMASTERID12ATOM = 0x041D; |
|
174
|
|
|
const RT_ROUNDTRIPCONTENTMASTERID12ATOM = 0x0422; |
|
175
|
|
|
const RT_ROUNDTRIPCONTENTMASTERINFO12ATOM = 0x041E; |
|
176
|
|
|
const RT_ROUNDTRIPCUSTOMTABLESTYLES12ATOM = 0x0428; |
|
177
|
|
|
const RT_ROUNDTRIPDOCFLAGS12ATOM = 0x0425; |
|
178
|
|
|
const RT_ROUNDTRIPHEADERFOOTERDEFAULTS12ATOM = 0x0424; |
|
179
|
|
|
const RT_ROUNDTRIPHFPLACEHOLDER12ATOM = 0x0420; |
|
180
|
|
|
const RT_ROUNDTRIPNEWPLACEHOLDERID12ATOM = 0x0BDD; |
|
181
|
|
|
const RT_ROUNDTRIPNOTESMASTERTEXTSTYLES12ATOM = 0x0427; |
|
182
|
|
|
const RT_ROUNDTRIPOARTTEXTSTYLES12ATOM = 0x0423; |
|
183
|
|
|
const RT_ROUNDTRIPORIGINALMAINMASTERID12ATOM = 0x041C; |
|
184
|
|
|
const RT_ROUNDTRIPSHAPECHECKSUMFORCL12ATOM = 0x0426; |
|
185
|
|
|
const RT_ROUNDTRIPSHAPEID12ATOM = 0x041F; |
|
186
|
|
|
const RT_ROUNDTRIPSLIDESYNCINFO12 = 0x3714; |
|
187
|
|
|
const RT_ROUNDTRIPSLIDESYNCINFOATOM12 = 0x3715; |
|
188
|
|
|
const RT_ROUNDTRIPTHEME12ATOM = 0x040E; |
|
189
|
|
|
const RT_SHAPEATOM = 0x0BDB; |
|
190
|
|
|
const RT_SHAPEFLAGS10ATOM = 0x0BDC; |
|
191
|
|
|
const RT_SLIDE = 0x03EE; |
|
192
|
|
|
const RT_SLIDEATOM = 0x03EF; |
|
193
|
|
|
const RT_SLIDEFLAGS10ATOM = 0x2EEA; |
|
194
|
|
|
const RT_SLIDELISTENTRY10ATOM = 0x2EF0; |
|
195
|
|
|
const RT_SLIDELISTTABLE10 = 0x2EF1; |
|
196
|
|
|
const RT_SLIDELISTWITHTEXT = 0x0FF0; |
|
197
|
|
|
const RT_SLIDELISTTABLESIZE10ATOM = 0x2EEF; |
|
198
|
|
|
const RT_SLIDENUMBERMETACHARATOM = 0x0FD8; |
|
199
|
|
|
const RT_SLIDEPERSISTATOM = 0x03F3; |
|
200
|
|
|
const RT_SLIDESHOWDOCINFOATOM = 0x0401; |
|
201
|
|
|
const RT_SLIDESHOWSLIDEINFOATOM = 0x03F9; |
|
202
|
|
|
const RT_SLIDETIME10ATOM = 0x2EEB; |
|
203
|
|
|
const RT_SLIDEVIEWINFO = 0x03FA; |
|
204
|
|
|
const RT_SLIDEVIEWINFOATOM = 0x03FE; |
|
205
|
|
|
const RT_SMARTTAGSTORE11CONTAINER = 0x36B3; |
|
206
|
|
|
const RT_SOUND = 0x07E6; |
|
207
|
|
|
const RT_SOUNDCOLLECTION = 0x07E4; |
|
208
|
|
|
const RT_SOUNDCOLLECTIONATOM = 0x07E5; |
|
209
|
|
|
const RT_SOUNDDATABLOB = 0x07E7; |
|
210
|
|
|
const RT_SORTERVIEWINFO = 0x0408; |
|
211
|
|
|
const RT_STYLETEXTPROPATOM = 0x0FA1; |
|
212
|
|
|
const RT_STYLETEXTPROP10ATOM = 0x0FB1; |
|
213
|
|
|
const RT_STYLETEXTPROP11ATOM = 0x0FB6; |
|
214
|
|
|
const RT_STYLETEXTPROP9ATOM = 0x0FAC; |
|
215
|
|
|
const RT_SUMMARY = 0x0402; |
|
216
|
|
|
const RT_TEXTBOOKMARKATOM = 0x0FA7; |
|
217
|
|
|
const RT_TEXTBYTESATOM = 0x0FA8; |
|
218
|
|
|
const RT_TEXTCHARFORMATEXCEPTIONATOM = 0x0FA4; |
|
219
|
|
|
const RT_TEXTCHARSATOM = 0x0FA0; |
|
220
|
|
|
const RT_TEXTDEFAULTS10ATOM = 0x0FB4; |
|
221
|
|
|
const RT_TEXTDEFAULTS9ATOM = 0x0FB0; |
|
222
|
|
|
const RT_TEXTHEADERATOM = 0x0F9F; |
|
223
|
|
|
const RT_TEXTINTERACTIVEINFOATOM = 0x0FDF; |
|
224
|
|
|
const RT_TEXTMASTERSTYLEATOM = 0x0FA3; |
|
225
|
|
|
const RT_TEXTMASTERSTYLE10ATOM = 0x0FB2; |
|
226
|
|
|
const RT_TEXTMASTERSTYLE9ATOM = 0x0FAD; |
|
227
|
|
|
const RT_TEXTPARAGRAPHFORMATEXCEPTIONATOM = 0x0FA5; |
|
228
|
|
|
const RT_TEXTRULERATOM = 0x0FA6; |
|
229
|
|
|
const RT_TEXTSPECIALINFOATOM = 0x0FAA; |
|
230
|
|
|
const RT_TEXTSPECIALINFODEFAULTATOM = 0x0FA9; |
|
231
|
|
|
const RT_TIMEANIMATEBEHAVIOR = 0xF134; |
|
232
|
|
|
const RT_TIMEANIMATEBEHAVIORCONTAINER = 0xF12B; |
|
233
|
|
|
const RT_TIMEANIMATIONVALUE = 0xF143; |
|
234
|
|
|
const RT_TIMEANIMATIONVALUELIST = 0xF13F; |
|
235
|
|
|
const RT_TIMEBEHAVIOR = 0xF133; |
|
236
|
|
|
const RT_TIMEBEHAVIORCONTAINER = 0xF12A; |
|
237
|
|
|
const RT_TIMECOLORBEHAVIOR = 0xF135; |
|
238
|
|
|
const RT_TIMECOLORBEHAVIORCONTAINER = 0xF12C; |
|
239
|
|
|
const RT_TIMECLIENTVISUALELEMENT = 0xF13C; |
|
240
|
|
|
const RT_TIMECOMMANDBEHAVIOR = 0xF13B; |
|
241
|
|
|
const RT_TIMECOMMANDBEHAVIORCONTAINER = 0xF132; |
|
242
|
|
|
const RT_TIMECONDITION = 0xF128; |
|
243
|
|
|
const RT_TIMECONDITIONCONTAINER = 0xF125; |
|
244
|
|
|
const RT_TIMEEFFECTBEHAVIOR = 0xF136; |
|
245
|
|
|
const RT_TIMEEFFECTBEHAVIORCONTAINER = 0xF12D; |
|
246
|
|
|
const RT_TIMEEXTTIMENODECONTAINER = 0xF144; |
|
247
|
|
|
const RT_TIMEITERATEDATA = 0xF140; |
|
248
|
|
|
const RT_TIMEMODIFIER = 0xF129; |
|
249
|
|
|
const RT_TIMEMOTIONBEHAVIOR = 0xF137; |
|
250
|
|
|
const RT_TIMEMOTIONBEHAVIORCONTAINER = 0xF12E; |
|
251
|
|
|
const RT_TIMENODE = 0xF127; |
|
252
|
|
|
const RT_TIMEPROPERTYLIST = 0xF13D; |
|
253
|
|
|
const RT_TIMEROTATIONBEHAVIOR = 0xF138; |
|
254
|
|
|
const RT_TIMEROTATIONBEHAVIORCONTAINER = 0xF12F; |
|
255
|
|
|
const RT_TIMESCALEBEHAVIOR = 0xF139; |
|
256
|
|
|
const RT_TIMESCALEBEHAVIORCONTAINER = 0xF130; |
|
257
|
|
|
const RT_TIMESEQUENCEDATA = 0xF141; |
|
258
|
|
|
const RT_TIMESETBEHAVIOR = 0xF13A; |
|
259
|
|
|
const RT_TIMESETBEHAVIORCONTAINER = 0xF131; |
|
260
|
|
|
const RT_TIMESUBEFFECTCONTAINER = 0xF145; |
|
261
|
|
|
const RT_TIMEVARIANT = 0xF142; |
|
262
|
|
|
const RT_TIMEVARIANTLIST = 0xF13E; |
|
263
|
|
|
const RT_USEREDITATOM = 0x0FF5; |
|
264
|
|
|
const RT_VBAINFO = 0x03FF; |
|
265
|
|
|
const RT_VBAINFOATOM = 0x0400; |
|
266
|
|
|
const RT_VIEWINFOATOM = 0x03FD; |
|
267
|
|
|
const RT_VISUALPAGEATOM = 0x2B01; |
|
268
|
|
|
const RT_VISUALSHAPEATOM = 0x2AFB; |
|
269
|
|
|
|
|
270
|
|
|
/** |
|
271
|
|
|
* @var http://msdn.microsoft.com/en-us/library/dd926394(v=office.12).aspx |
|
272
|
|
|
*/ |
|
273
|
|
|
const SL_BIGOBJECT = 0x0000000F; |
|
274
|
|
|
const SL_BLANK = 0x00000010; |
|
275
|
|
|
const SL_COLUMNTWOROWS = 0x0000000A; |
|
276
|
|
|
const SL_FOUROBJECTS = 0x0000000E; |
|
277
|
|
|
const SL_MASTERTITLE = 0x00000002; |
|
278
|
|
|
const SL_TITLEBODY = 0x00000001; |
|
279
|
|
|
const SL_TITLEONLY = 0x00000007; |
|
280
|
|
|
const SL_TITLESLIDE = 0x00000000; |
|
281
|
|
|
const SL_TWOCOLUMNS = 0x00000008; |
|
282
|
|
|
const SL_TWOCOLUMNSROW = 0x0000000D; |
|
283
|
|
|
const SL_TWOROWS = 0x00000009; |
|
284
|
|
|
const SL_TWOROWSCOLUMN = 0x0000000B; |
|
285
|
|
|
const SL_VERTICALTITLEBODY = 0x00000011; |
|
286
|
|
|
const SL_VERTICALTWOROWS = 0x00000012; |
|
287
|
|
|
|
|
288
|
|
|
/** |
|
289
|
|
|
* Array with Fonts |
|
290
|
|
|
*/ |
|
291
|
|
|
private $arrayFonts = array(); |
|
292
|
|
|
/** |
|
293
|
|
|
* Array with Hyperlinks |
|
294
|
|
|
*/ |
|
295
|
|
|
private $arrayHyperlinks = array(); |
|
296
|
|
|
/** |
|
297
|
|
|
* Array with Notes |
|
298
|
|
|
*/ |
|
299
|
|
|
private $arrayNotes = array(); |
|
300
|
|
|
/** |
|
301
|
|
|
* Array with Pictures |
|
302
|
|
|
*/ |
|
303
|
|
|
private $arrayPictures = array(); |
|
304
|
|
|
/** |
|
305
|
|
|
* Offset (in bytes) from the beginning of the PowerPoint Document Stream to the UserEditAtom record for the most recent user edit. |
|
306
|
|
|
* @var int |
|
307
|
|
|
*/ |
|
308
|
|
|
private $offsetToCurrentEdit; |
|
309
|
|
|
/** |
|
310
|
|
|
* A structure that specifies a compressed table of sequential persist object identifiers and stream offsets to associated persist objects. |
|
311
|
|
|
* @var int[] |
|
312
|
|
|
*/ |
|
313
|
|
|
private $rgPersistDirEntry; |
|
314
|
|
|
/** |
|
315
|
|
|
* Offset (in bytes) from the beginning of the PowerPoint Document Stream to the PersistDirectoryAtom record for this user edit |
|
316
|
|
|
* @var int |
|
317
|
|
|
*/ |
|
318
|
|
|
private $offsetPersistDirectory; |
|
319
|
|
|
/** |
|
320
|
|
|
* Output Object |
|
321
|
|
|
* @var PhpPresentation |
|
322
|
|
|
*/ |
|
323
|
|
|
private $oPhpPresentation; |
|
324
|
|
|
/** |
|
325
|
|
|
* Group Object |
|
326
|
|
|
* @var Group |
|
327
|
|
|
*/ |
|
328
|
|
|
private $oCurrentGroup; |
|
329
|
|
|
/** |
|
330
|
|
|
* @var boolean |
|
331
|
|
|
*/ |
|
332
|
|
|
private $bFirstShapeGroup = false; |
|
333
|
|
|
/** |
|
334
|
|
|
* Stream "Powerpoint Document" |
|
335
|
|
|
* @var string |
|
336
|
|
|
*/ |
|
337
|
|
|
private $streamPowerpointDocument; |
|
338
|
|
|
/** |
|
339
|
|
|
* Stream "Current User" |
|
340
|
|
|
* @var string |
|
341
|
|
|
*/ |
|
342
|
|
|
private $streamCurrentUser; |
|
343
|
|
|
/** |
|
344
|
|
|
* Stream "Summary Information" |
|
345
|
|
|
* @var string |
|
346
|
|
|
*/ |
|
347
|
|
|
private $streamSummaryInformation; |
|
348
|
|
|
/** |
|
349
|
|
|
* Stream "Document Summary Information" |
|
350
|
|
|
* @var string |
|
351
|
|
|
*/ |
|
352
|
|
|
private $streamDocumentSummaryInformation; |
|
353
|
|
|
/** |
|
354
|
|
|
* Stream "Pictures" |
|
355
|
|
|
* @var string |
|
356
|
|
|
*/ |
|
357
|
|
|
private $streamPictures; |
|
358
|
|
|
/** |
|
359
|
|
|
* @var integer |
|
360
|
|
|
*/ |
|
361
|
|
|
private $inMainType; |
|
362
|
|
|
/** |
|
363
|
|
|
* @var integer |
|
364
|
|
|
*/ |
|
365
|
|
|
private $currentNote; |
|
366
|
|
|
|
|
367
|
|
|
/** |
|
368
|
|
|
* Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file? |
|
369
|
|
|
* |
|
370
|
|
|
* @param string $pFilename |
|
371
|
|
|
* @throws \Exception |
|
372
|
|
|
* @return boolean |
|
373
|
|
|
*/ |
|
374
|
3 |
|
public function canRead($pFilename) |
|
375
|
|
|
{ |
|
376
|
3 |
|
return $this->fileSupportsUnserializePhpPresentation($pFilename); |
|
377
|
|
|
} |
|
378
|
|
|
|
|
379
|
|
|
/** |
|
380
|
|
|
* Does a file support UnserializePhpPresentation ? |
|
381
|
|
|
* |
|
382
|
|
|
* @param string $pFilename |
|
383
|
|
|
* @throws \Exception |
|
384
|
|
|
* @return boolean |
|
385
|
|
|
*/ |
|
386
|
9 |
|
public function fileSupportsUnserializePhpPresentation($pFilename = '') |
|
387
|
|
|
{ |
|
388
|
|
|
// Check if file exists |
|
389
|
9 |
|
if (!file_exists($pFilename)) { |
|
390
|
2 |
|
throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist."); |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
try { |
|
394
|
|
|
// Use ParseXL for the hard work. |
|
395
|
7 |
|
$ole = new OLERead(); |
|
396
|
|
|
// get excel data |
|
397
|
7 |
|
$ole->read($pFilename); |
|
398
|
4 |
|
return true; |
|
399
|
3 |
|
} catch (\Exception $e) { |
|
400
|
3 |
|
return false; |
|
401
|
|
|
} |
|
402
|
|
|
} |
|
403
|
|
|
|
|
404
|
|
|
/** |
|
405
|
|
|
* Loads PhpPresentation Serialized file |
|
406
|
|
|
* |
|
407
|
|
|
* @param string $pFilename |
|
408
|
|
|
* @return \PhpOffice\PhpPresentation\PhpPresentation |
|
409
|
|
|
* @throws \Exception |
|
410
|
|
|
*/ |
|
411
|
5 |
|
public function load($pFilename) |
|
412
|
|
|
{ |
|
413
|
|
|
// Unserialize... First make sure the file supports it! |
|
414
|
5 |
|
if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) { |
|
415
|
1 |
|
throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\PowerPoint97: " . $pFilename . "."); |
|
416
|
|
|
} |
|
417
|
|
|
|
|
418
|
3 |
|
return $this->loadFile($pFilename); |
|
419
|
|
|
} |
|
420
|
|
|
|
|
421
|
|
|
/** |
|
422
|
|
|
* Load PhpPresentation Serialized file |
|
423
|
|
|
* |
|
424
|
|
|
* @param string $pFilename |
|
425
|
|
|
* @return \PhpOffice\PhpPresentation\PhpPresentation |
|
426
|
|
|
* @throws \Exception |
|
427
|
|
|
*/ |
|
428
|
3 |
|
private function loadFile($pFilename) |
|
429
|
|
|
{ |
|
430
|
3 |
|
$this->oPhpPresentation = new PhpPresentation(); |
|
431
|
3 |
|
$this->oPhpPresentation->removeSlideByIndex(); |
|
432
|
|
|
|
|
433
|
|
|
// Read OLE Blocks |
|
434
|
3 |
|
$this->loadOLE($pFilename); |
|
435
|
|
|
// Read pictures in the Pictures Stream |
|
436
|
3 |
|
$this->loadPicturesStream(); |
|
437
|
|
|
// Read information in the Current User Stream |
|
438
|
3 |
|
$this->loadCurrentUserStream(); |
|
439
|
|
|
// Read information in the PowerPoint Document Stream |
|
440
|
3 |
|
$this->loadPowerpointDocumentStream(); |
|
441
|
|
|
|
|
442
|
3 |
|
return $this->oPhpPresentation; |
|
443
|
|
|
} |
|
444
|
|
|
|
|
445
|
|
|
/** |
|
446
|
|
|
* Read OLE Part |
|
447
|
|
|
* @param string $pFilename |
|
448
|
|
|
* @throws \Exception |
|
449
|
|
|
*/ |
|
450
|
3 |
|
private function loadOLE($pFilename) |
|
451
|
|
|
{ |
|
452
|
|
|
// OLE reader |
|
453
|
3 |
|
$oOLE = new OLERead(); |
|
454
|
3 |
|
$oOLE->read($pFilename); |
|
455
|
|
|
|
|
456
|
|
|
// PowerPoint Document Stream |
|
457
|
3 |
|
$this->streamPowerpointDocument = $oOLE->getStream($oOLE->powerpointDocument); |
|
458
|
|
|
|
|
459
|
|
|
// Current User Stream |
|
460
|
3 |
|
$this->streamCurrentUser = $oOLE->getStream($oOLE->currentUser); |
|
461
|
|
|
|
|
462
|
|
|
// Get summary information data |
|
463
|
3 |
|
$this->streamSummaryInformation = $oOLE->getStream($oOLE->summaryInformation); |
|
464
|
|
|
|
|
465
|
|
|
// Get additional document summary information data |
|
466
|
3 |
|
$this->streamDocumentSummaryInformation = $oOLE->getStream($oOLE->docSummaryInfos); |
|
467
|
|
|
|
|
468
|
|
|
// Get pictures data |
|
469
|
3 |
|
$this->streamPictures = $oOLE->getStream($oOLE->pictures); |
|
470
|
3 |
|
} |
|
471
|
|
|
|
|
472
|
|
|
/** |
|
473
|
|
|
* Stream Pictures |
|
474
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd920746(v=office.12).aspx |
|
475
|
|
|
*/ |
|
476
|
3 |
|
private function loadPicturesStream() |
|
477
|
|
|
{ |
|
478
|
3 |
|
$stream = $this->streamPictures; |
|
479
|
|
|
|
|
480
|
3 |
|
$pos = 0; |
|
481
|
|
|
do { |
|
482
|
3 |
|
$arrayRH = $this->loadRecordHeader($stream, $pos); |
|
483
|
3 |
|
$pos += 8; |
|
484
|
3 |
|
$readSuccess = false; |
|
485
|
3 |
|
if ($arrayRH['recVer'] == 0x00 && ($arrayRH['recType'] == 0xF007 || ($arrayRH['recType'] >= 0xF018 && $arrayRH['recType'] <= 0xF117))) { |
|
486
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950560(v=office.12).aspx |
|
487
|
3 |
|
if ($arrayRH['recType'] == 0xF007) { |
|
488
|
|
|
// OfficeArtFBSE |
|
489
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
490
|
|
|
} |
|
491
|
3 |
|
if ($arrayRH['recType'] >= 0xF018 && $arrayRH['recType'] <= 0xF117) { |
|
492
|
3 |
|
$arrayRecord = $this->readRecordOfficeArtBlip($stream, $pos - 8); |
|
493
|
3 |
|
if ($arrayRecord['length'] > 0) { |
|
494
|
3 |
|
$pos += $arrayRecord['length']; |
|
495
|
3 |
|
$this->arrayPictures[] = $arrayRecord['picture']; |
|
496
|
|
|
} |
|
497
|
|
|
} |
|
498
|
3 |
|
$readSuccess = true; |
|
499
|
|
|
} |
|
500
|
3 |
|
} while ($readSuccess === true); |
|
501
|
3 |
|
} |
|
502
|
|
|
|
|
503
|
|
|
/** |
|
504
|
|
|
* Stream Current User |
|
505
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd908567(v=office.12).aspx |
|
506
|
|
|
*/ |
|
507
|
3 |
|
private function loadCurrentUserStream() |
|
508
|
|
|
{ |
|
509
|
3 |
|
$pos = 0; |
|
510
|
|
|
|
|
511
|
|
|
/** |
|
512
|
|
|
* CurrentUserAtom : http://msdn.microsoft.com/en-us/library/dd948895(v=office.12).aspx |
|
513
|
|
|
*/ |
|
514
|
|
|
// RecordHeader : http://msdn.microsoft.com/en-us/library/dd926377(v=office.12).aspx |
|
515
|
3 |
|
$rHeader = $this->loadRecordHeader($this->streamCurrentUser, $pos); |
|
516
|
3 |
|
$pos += 8; |
|
517
|
3 |
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_CURRENTUSERATOM) { |
|
518
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > RecordHeader).'); |
|
519
|
|
|
} |
|
520
|
|
|
|
|
521
|
|
|
// Size |
|
522
|
3 |
|
$size = self::getInt4d($this->streamCurrentUser, $pos); |
|
523
|
3 |
|
$pos += 4; |
|
524
|
3 |
|
if ($size != 0x00000014) { |
|
525
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > Size).'); |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
// headerToken |
|
529
|
3 |
|
$headerToken = self::getInt4d($this->streamCurrentUser, $pos); |
|
530
|
3 |
|
$pos += 4; |
|
531
|
3 |
|
if ($headerToken == 0xF3D1C4DF && $headerToken != 0xE391C05F) { |
|
532
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.') : Encrypted file'); |
|
533
|
|
|
} |
|
534
|
|
|
|
|
535
|
|
|
// offsetToCurrentEdit |
|
536
|
3 |
|
$this->offsetToCurrentEdit = self::getInt4d($this->streamCurrentUser, $pos); |
|
537
|
3 |
|
$pos += 4; |
|
538
|
|
|
|
|
539
|
|
|
// lenUserName |
|
540
|
3 |
|
$lenUserName = self::getInt2d($this->streamCurrentUser, $pos); |
|
541
|
3 |
|
$pos += 2; |
|
542
|
3 |
|
if ($lenUserName > 255) { |
|
543
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > lenUserName).'); |
|
544
|
|
|
} |
|
545
|
|
|
|
|
546
|
|
|
// docFileVersion |
|
547
|
3 |
|
$docFileVersion = self::getInt2d($this->streamCurrentUser, $pos); |
|
548
|
3 |
|
$pos += 2; |
|
549
|
3 |
|
if ($docFileVersion != 0x03F4) { |
|
550
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > docFileVersion).'); |
|
551
|
|
|
} |
|
552
|
|
|
|
|
553
|
|
|
// majorVersion |
|
554
|
3 |
|
$majorVersion = self::getInt1d($this->streamCurrentUser, $pos); |
|
555
|
3 |
|
$pos += 1; |
|
556
|
3 |
|
if ($majorVersion != 0x03) { |
|
557
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > majorVersion).'); |
|
558
|
|
|
} |
|
559
|
|
|
|
|
560
|
|
|
// minorVersion |
|
561
|
3 |
|
$minorVersion = self::getInt1d($this->streamCurrentUser, $pos); |
|
562
|
3 |
|
$pos += 1; |
|
563
|
3 |
|
if ($minorVersion != 0x00) { |
|
564
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > minorVersion).'); |
|
565
|
|
|
} |
|
566
|
|
|
|
|
567
|
|
|
// unused |
|
568
|
3 |
|
$pos += 2; |
|
569
|
|
|
|
|
570
|
|
|
// ansiUserName |
|
571
|
3 |
|
$ansiUserName = ''; |
|
572
|
|
|
do { |
|
573
|
3 |
|
$char = self::getInt1d($this->streamCurrentUser, $pos); |
|
574
|
3 |
|
if (($char >= 0x00 && $char <= 0x1F) || ($char >= 0x7F && $char <= 0x9F)) { |
|
575
|
3 |
|
$char = false; |
|
576
|
|
|
} else { |
|
577
|
3 |
|
$ansiUserName .= chr($char); |
|
578
|
3 |
|
$pos += 1; |
|
579
|
|
|
} |
|
580
|
3 |
|
} while ($char !== false); |
|
581
|
|
|
|
|
582
|
|
|
// relVersion |
|
583
|
3 |
|
$relVersion = self::getInt4d($this->streamCurrentUser, $pos); |
|
584
|
3 |
|
$pos += 4; |
|
585
|
3 |
|
if ($relVersion != 0x00000008 && $relVersion != 0x00000009) { |
|
586
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : CurrentUserAtom > relVersion).'); |
|
587
|
|
|
} |
|
588
|
|
|
|
|
589
|
|
|
// unicodeUserName |
|
590
|
3 |
|
$unicodeUserName = ''; |
|
591
|
3 |
|
for ($inc = 0; $inc < $lenUserName; $inc++) { |
|
592
|
3 |
|
$char = self::getInt2d($this->streamCurrentUser, $pos); |
|
593
|
3 |
|
if (($char >= 0x00 && $char <= 0x1F) || ($char >= 0x7F && $char <= 0x9F)) { |
|
594
|
3 |
|
break; |
|
595
|
|
|
} |
|
596
|
|
|
$unicodeUserName .= chr($char); |
|
597
|
|
|
$pos += 2; |
|
598
|
|
|
} |
|
599
|
3 |
|
} |
|
600
|
|
|
|
|
601
|
|
|
/** |
|
602
|
|
|
* Stream Powerpoint Document |
|
603
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd921564(v=office.12).aspx |
|
604
|
|
|
*/ |
|
605
|
3 |
|
private function loadPowerpointDocumentStream() |
|
606
|
|
|
{ |
|
607
|
3 |
|
$this->readRecordUserEditAtom($this->streamPowerpointDocument, $this->offsetToCurrentEdit); |
|
608
|
|
|
|
|
609
|
3 |
|
$this->readRecordPersistDirectoryAtom($this->streamPowerpointDocument, $this->offsetPersistDirectory); |
|
610
|
|
|
|
|
611
|
3 |
|
foreach ($this->rgPersistDirEntry as $offsetDir) { |
|
612
|
3 |
|
$pos = $offsetDir; |
|
613
|
|
|
|
|
614
|
3 |
|
$rh = $this->loadRecordHeader($this->streamPowerpointDocument, $pos); |
|
615
|
3 |
|
$pos += 8; |
|
616
|
3 |
|
$this->inMainType = $rh['recType']; |
|
617
|
3 |
|
$this->currentNote = null; |
|
618
|
3 |
|
switch ($rh['recType']) { |
|
619
|
3 |
|
case self::RT_DOCUMENT: |
|
620
|
3 |
|
$this->readRecordDocumentContainer($this->streamPowerpointDocument, $pos); |
|
621
|
3 |
|
break; |
|
622
|
3 |
|
case self::RT_NOTES: |
|
623
|
3 |
|
$this->readRecordNotesContainer($this->streamPowerpointDocument, $pos); |
|
624
|
3 |
|
break; |
|
625
|
3 |
|
case self::RT_SLIDE: |
|
626
|
3 |
|
$this->readRecordSlideContainer($this->streamPowerpointDocument, $pos); |
|
627
|
3 |
|
break; |
|
628
|
3 |
|
case self::RT_MAINMASTER: |
|
629
|
3 |
|
break; |
|
630
|
|
|
default: |
|
631
|
|
|
throw new \Exception('Feature not implemented : l.' . __LINE__ . '(' . dechex($rh['recType']) . ')'); |
|
632
|
3 |
|
break; |
|
|
|
|
|
|
633
|
|
|
} |
|
634
|
|
|
} |
|
635
|
3 |
|
} |
|
636
|
|
|
|
|
637
|
|
|
/** |
|
638
|
|
|
* Read a record header |
|
639
|
|
|
* @param string $stream |
|
640
|
|
|
* @param integer $pos |
|
641
|
|
|
* @return array |
|
642
|
|
|
*/ |
|
643
|
3 |
|
private function loadRecordHeader($stream, $pos) |
|
644
|
|
|
{ |
|
645
|
3 |
|
$rec = self::getInt2d($stream, $pos); |
|
646
|
3 |
|
$recType = self::getInt2d($stream, $pos + 2); |
|
647
|
3 |
|
$recLen = self::getInt4d($stream, $pos + 4); |
|
648
|
|
|
return array( |
|
649
|
3 |
|
'recVer' => ($rec >> 0) & bindec('1111'), |
|
650
|
3 |
|
'recInstance' => ($rec >> 4) & bindec('111111111111'), |
|
651
|
3 |
|
'recType' => $recType, |
|
652
|
3 |
|
'recLen' => $recLen, |
|
653
|
|
|
); |
|
654
|
|
|
} |
|
655
|
|
|
|
|
656
|
|
|
/** |
|
657
|
|
|
* Read 8-bit unsigned integer |
|
658
|
|
|
* |
|
659
|
|
|
* @param string $data |
|
660
|
|
|
* @param int $pos |
|
661
|
|
|
* @return int |
|
662
|
|
|
*/ |
|
663
|
3 |
|
public static function getInt1d($data, $pos) |
|
664
|
|
|
{ |
|
665
|
3 |
|
return ord($data[$pos]); |
|
666
|
|
|
} |
|
667
|
|
|
|
|
668
|
|
|
/** |
|
669
|
|
|
* Read 16-bit unsigned integer |
|
670
|
|
|
* |
|
671
|
|
|
* @param string $data |
|
672
|
|
|
* @param int $pos |
|
673
|
|
|
* @return int |
|
674
|
|
|
*/ |
|
675
|
3 |
|
public static function getInt2d($data, $pos) |
|
676
|
|
|
{ |
|
677
|
3 |
|
return ord($data[$pos]) | (ord($data[$pos+1]) << 8); |
|
678
|
|
|
} |
|
679
|
|
|
|
|
680
|
|
|
/** |
|
681
|
|
|
* Read 32-bit signed integer |
|
682
|
|
|
* |
|
683
|
|
|
* @param string $data |
|
684
|
|
|
* @param int $pos |
|
685
|
|
|
* @return int |
|
686
|
|
|
*/ |
|
687
|
3 |
|
public static function getInt4d($data, $pos) |
|
688
|
|
|
{ |
|
689
|
|
|
// FIX: represent numbers correctly on 64-bit system |
|
690
|
|
|
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 |
|
691
|
|
|
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems |
|
692
|
3 |
|
$or24 = ord($data[$pos + 3]); |
|
693
|
|
|
|
|
694
|
3 |
|
$ord24 = ($or24 & 127) << 24; |
|
695
|
3 |
|
if ($or24 >= 128) { |
|
696
|
|
|
// negative number |
|
697
|
3 |
|
$ord24 = -abs((256 - $or24) << 24); |
|
698
|
|
|
} |
|
699
|
3 |
|
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $ord24; |
|
700
|
|
|
} |
|
701
|
|
|
|
|
702
|
|
|
/** |
|
703
|
|
|
* A container record that specifies the animation and sound information for a shape. |
|
704
|
|
|
* @param string $stream |
|
705
|
|
|
* @param integer $pos |
|
706
|
|
|
* @return array |
|
707
|
|
|
* @throws \Exception |
|
708
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd772900(v=office.12).aspx |
|
709
|
|
|
*/ |
|
710
|
3 |
|
private function readRecordAnimationInfoContainer($stream, $pos) |
|
711
|
|
|
{ |
|
712
|
|
|
$arrayReturn = array( |
|
713
|
3 |
|
'length' => 0, |
|
714
|
|
|
); |
|
715
|
|
|
|
|
716
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
717
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ANIMATIONINFO) { |
|
718
|
|
|
// Record Header |
|
719
|
|
|
$arrayReturn['length'] += 8; |
|
720
|
|
|
// animationAtom |
|
721
|
|
|
// animationSound |
|
722
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
723
|
|
|
} |
|
724
|
|
|
|
|
725
|
3 |
|
return $arrayReturn; |
|
726
|
|
|
} |
|
727
|
|
|
|
|
728
|
|
|
/** |
|
729
|
|
|
* A container record that specifies information about the document. |
|
730
|
|
|
* @param string $stream |
|
731
|
|
|
* @param integer $pos |
|
732
|
|
|
* @throws \Exception |
|
733
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd947357(v=office.12).aspx |
|
734
|
|
|
*/ |
|
735
|
3 |
|
private function readRecordDocumentContainer($stream, $pos) |
|
736
|
|
|
{ |
|
737
|
3 |
|
$documentAtom = $this->loadRecordHeader($stream, $pos); |
|
738
|
3 |
|
$pos += 8; |
|
739
|
3 |
|
if ($documentAtom['recVer'] != 0x1 || $documentAtom['recInstance'] != 0x000 || $documentAtom['recType'] != self::RT_DOCUMENTATOM) { |
|
740
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom).'); |
|
741
|
|
|
} |
|
742
|
3 |
|
$pos += $documentAtom['recLen']; |
|
743
|
|
|
|
|
744
|
3 |
|
$exObjList = $this->loadRecordHeader($stream, $pos); |
|
745
|
3 |
|
if ($exObjList['recVer'] == 0xF && $exObjList['recInstance'] == 0x000 && $exObjList['recType'] == self::RT_EXTERNALOBJECTLIST) { |
|
746
|
1 |
|
$pos += 8; |
|
747
|
|
|
// exObjListAtom > rh |
|
748
|
1 |
|
$exObjListAtom = $this->loadRecordHeader($stream, $pos); |
|
749
|
1 |
|
if ($exObjListAtom['recVer'] != 0x0 || $exObjListAtom['recInstance'] != 0x000 || $exObjListAtom['recType'] != self::RT_EXTERNALOBJECTLISTATOM || $exObjListAtom['recLen'] != 0x00000004) { |
|
750
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom > exObjList > exObjListAtom).'); |
|
751
|
|
|
} |
|
752
|
1 |
|
$pos += 8; |
|
753
|
|
|
// exObjListAtom > exObjIdSeed |
|
754
|
1 |
|
$pos += 4; |
|
755
|
|
|
// rgChildRec |
|
756
|
1 |
|
$exObjList['recLen'] -= 12; |
|
757
|
|
|
do { |
|
758
|
1 |
|
$childRec = $this->loadRecordHeader($stream, $pos); |
|
759
|
1 |
|
$pos += 8; |
|
760
|
1 |
|
$exObjList['recLen'] -= 8; |
|
761
|
1 |
|
switch ($childRec['recType']) { |
|
762
|
1 |
|
case self::RT_EXTERNALHYPERLINK: |
|
763
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd944995(v=office.12).aspx |
|
764
|
|
|
// exHyperlinkAtom > rh |
|
765
|
1 |
|
$exHyperlinkAtom = $this->loadRecordHeader($stream, $pos); |
|
766
|
1 |
|
if ($exHyperlinkAtom['recVer'] != 0x0 || $exHyperlinkAtom['recInstance'] != 0x000 || $exHyperlinkAtom['recType'] != self::RT_EXTERNALHYPERLINKATOM || $exObjListAtom['recLen'] != 0x00000004) { |
|
767
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > DocumentAtom > exObjList > rgChildRec > RT_ExternalHyperlink).'); |
|
768
|
|
|
} |
|
769
|
1 |
|
$pos += 8; |
|
770
|
1 |
|
$exObjList['recLen'] -= 8; |
|
771
|
|
|
// exHyperlinkAtom > exHyperlinkId |
|
772
|
1 |
|
$exHyperlinkId = self::getInt4d($stream, $pos); |
|
773
|
1 |
|
$pos += 4; |
|
774
|
1 |
|
$exObjList['recLen'] -= 4; |
|
775
|
|
|
|
|
776
|
1 |
|
$this->arrayHyperlinks[$exHyperlinkId] = array(); |
|
777
|
|
|
// friendlyNameAtom |
|
778
|
1 |
|
$friendlyNameAtom = $this->loadRecordHeader($stream, $pos); |
|
779
|
1 |
|
if ($friendlyNameAtom['recVer'] == 0x0 && $friendlyNameAtom['recInstance'] == 0x000 && $friendlyNameAtom['recType'] == self::RT_CSTRING && $friendlyNameAtom['recLen'] % 2 == 0) { |
|
780
|
1 |
|
$pos += 8; |
|
781
|
1 |
|
$exObjList['recLen'] -= 8; |
|
782
|
1 |
|
$this->arrayHyperlinks[$exHyperlinkId]['text'] = ''; |
|
783
|
1 |
|
for ($inc = 0; $inc < ($friendlyNameAtom['recLen'] / 2); $inc++) { |
|
784
|
1 |
|
$char = self::getInt2d($stream, $pos); |
|
785
|
1 |
|
$pos += 2; |
|
786
|
1 |
|
$exObjList['recLen'] -= 2; |
|
787
|
1 |
|
$this->arrayHyperlinks[$exHyperlinkId]['text'] .= chr($char); |
|
788
|
|
|
} |
|
789
|
|
|
} |
|
790
|
|
|
// targetAtom |
|
791
|
1 |
|
$targetAtom = $this->loadRecordHeader($stream, $pos); |
|
792
|
1 |
|
if ($targetAtom['recVer'] == 0x0 && $targetAtom['recInstance'] == 0x001 && $targetAtom['recType'] == self::RT_CSTRING && $targetAtom['recLen'] % 2 == 0) { |
|
793
|
1 |
|
$pos += 8; |
|
794
|
1 |
|
$exObjList['recLen'] -= 8; |
|
795
|
1 |
|
$this->arrayHyperlinks[$exHyperlinkId]['url'] = ''; |
|
796
|
1 |
|
for ($inc = 0; $inc < ($targetAtom['recLen'] / 2); $inc++) { |
|
797
|
1 |
|
$char = self::getInt2d($stream, $pos); |
|
798
|
1 |
|
$pos += 2; |
|
799
|
1 |
|
$exObjList['recLen'] -= 2; |
|
800
|
1 |
|
$this->arrayHyperlinks[$exHyperlinkId]['url'] .= chr($char); |
|
801
|
|
|
} |
|
802
|
|
|
} |
|
803
|
|
|
// locationAtom |
|
804
|
1 |
|
$locationAtom = $this->loadRecordHeader($stream, $pos); |
|
805
|
1 |
|
if ($locationAtom['recVer'] == 0x0 && $locationAtom['recInstance'] == 0x003 && $locationAtom['recType'] == self::RT_CSTRING && $locationAtom['recLen'] % 2 == 0) { |
|
806
|
|
|
$pos += 8; |
|
807
|
|
|
$exObjList['recLen'] -= 8; |
|
808
|
|
|
$string = ''; |
|
809
|
|
|
for ($inc = 0; $inc < ($locationAtom['recLen'] / 2); $inc++) { |
|
810
|
|
|
$char = self::getInt2d($stream, $pos); |
|
811
|
|
|
$pos += 2; |
|
812
|
|
|
$exObjList['recLen'] -= 2; |
|
813
|
|
|
$string .= chr($char); |
|
814
|
|
|
} |
|
815
|
|
|
} |
|
816
|
1 |
|
break; |
|
817
|
|
|
default: |
|
818
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : '.dechex($childRec['recType'].')')); |
|
819
|
|
|
} |
|
820
|
1 |
|
} while ($exObjList['recLen'] > 0); |
|
821
|
|
|
} |
|
822
|
|
|
|
|
823
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd907813(v=office.12).aspx |
|
824
|
3 |
|
$documentTextInfo = $this->loadRecordHeader($stream, $pos); |
|
825
|
3 |
|
if ($documentTextInfo['recVer'] == 0xF && $documentTextInfo['recInstance'] == 0x000 && $documentTextInfo['recType'] == self::RT_ENVIRONMENT) { |
|
826
|
3 |
|
$pos += 8; |
|
827
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd952717(v=office.12).aspx |
|
828
|
3 |
|
$kinsoku = $this->loadRecordHeader($stream, $pos); |
|
829
|
3 |
|
if ($kinsoku['recVer'] == 0xF && $kinsoku['recInstance'] == 0x002 && $kinsoku['recType'] == self::RT_KINSOKU) { |
|
830
|
3 |
|
$pos += 8; |
|
831
|
3 |
|
$pos += $kinsoku['recLen']; |
|
832
|
|
|
} |
|
833
|
|
|
|
|
834
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948152(v=office.12).aspx |
|
835
|
3 |
|
$fontCollection = $this->loadRecordHeader($stream, $pos); |
|
836
|
3 |
|
if ($fontCollection['recVer'] == 0xF && $fontCollection['recInstance'] == 0x000 && $fontCollection['recType'] == self::RT_FONTCOLLECTION) { |
|
837
|
3 |
|
$pos += 8; |
|
838
|
|
|
do { |
|
839
|
3 |
|
$fontEntityAtom = $this->loadRecordHeader($stream, $pos); |
|
840
|
3 |
|
$pos += 8; |
|
841
|
3 |
|
$fontCollection['recLen'] -= 8; |
|
842
|
3 |
|
if ($fontEntityAtom['recVer'] != 0x0 || $fontEntityAtom['recInstance'] > 128 || $fontEntityAtom['recType'] != self::RT_FONTENTITYATOM) { |
|
843
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : RTDocument > RT_Environment > RT_FontCollection > RT_FontEntityAtom).'); |
|
844
|
|
|
} |
|
845
|
3 |
|
$string = ''; |
|
846
|
3 |
|
for ($inc = 0; $inc < 32; $inc++) { |
|
847
|
3 |
|
$char = self::getInt2d($stream, $pos); |
|
848
|
3 |
|
$pos += 2; |
|
849
|
3 |
|
$fontCollection['recLen'] -= 2; |
|
850
|
3 |
|
$string .= chr($char); |
|
851
|
|
|
} |
|
852
|
3 |
|
$this->arrayFonts[] = $string; |
|
853
|
|
|
|
|
854
|
|
|
// lfCharSet (1 byte) |
|
855
|
3 |
|
$pos += 1; |
|
856
|
3 |
|
$fontCollection['recLen'] -= 1; |
|
857
|
|
|
|
|
858
|
|
|
// fEmbedSubsetted (1 bit) |
|
859
|
|
|
// unused (7 bits) |
|
860
|
3 |
|
$pos += 1; |
|
861
|
3 |
|
$fontCollection['recLen'] -= 1; |
|
862
|
|
|
|
|
863
|
|
|
// rasterFontType (1 bit) |
|
864
|
|
|
// deviceFontType (1 bit) |
|
865
|
|
|
// truetypeFontType (1 bit) |
|
866
|
|
|
// fNoFontSubstitution (1 bit) |
|
867
|
|
|
// reserved (4 bits) |
|
868
|
3 |
|
$pos += 1; |
|
869
|
3 |
|
$fontCollection['recLen'] -= 1; |
|
870
|
|
|
|
|
871
|
|
|
// lfPitchAndFamily (1 byte) |
|
872
|
3 |
|
$pos += 1; |
|
873
|
3 |
|
$fontCollection['recLen'] -= 1; |
|
874
|
|
|
|
|
875
|
3 |
|
$fontEmbedData1 = $this->loadRecordHeader($stream, $pos); |
|
876
|
3 |
|
if ($fontEmbedData1['recVer'] == 0x0 && $fontEmbedData1['recInstance'] >= 0x000 && $fontEmbedData1['recInstance'] <= 0x003 && $fontEmbedData1['recType'] == self::RT_FONTEMBEDDATABLOB) { |
|
877
|
|
|
$pos += 8; |
|
878
|
|
|
$fontCollection['recLen'] -= 8; |
|
879
|
|
|
$pos += $fontEmbedData1['recLen']; |
|
880
|
|
|
$fontCollection['recLen'] -= $fontEmbedData1['recLen']; |
|
881
|
|
|
} |
|
882
|
|
|
|
|
883
|
3 |
|
$fontEmbedData2 = $this->loadRecordHeader($stream, $pos); |
|
884
|
3 |
|
if ($fontEmbedData2['recVer'] == 0x0 && $fontEmbedData2['recInstance'] >= 0x000 && $fontEmbedData2['recInstance'] <= 0x003 && $fontEmbedData2['recType'] == self::RT_FONTEMBEDDATABLOB) { |
|
885
|
|
|
$pos += 8; |
|
886
|
|
|
$fontCollection['recLen'] -= 8; |
|
887
|
|
|
$pos += $fontEmbedData2['recLen']; |
|
888
|
|
|
$fontCollection['recLen'] -= $fontEmbedData2['recLen']; |
|
889
|
|
|
} |
|
890
|
|
|
|
|
891
|
3 |
|
$fontEmbedData3 = $this->loadRecordHeader($stream, $pos); |
|
892
|
3 |
|
if ($fontEmbedData3['recVer'] == 0x0 && $fontEmbedData3['recInstance'] >= 0x000 && $fontEmbedData3['recInstance'] <= 0x003 && $fontEmbedData3['recType'] == self::RT_FONTEMBEDDATABLOB) { |
|
893
|
|
|
$pos += 8; |
|
894
|
|
|
$fontCollection['recLen'] -= 8; |
|
895
|
|
|
$pos += $fontEmbedData3['recLen']; |
|
896
|
|
|
$fontCollection['recLen'] -= $fontEmbedData3['recLen']; |
|
897
|
|
|
} |
|
898
|
|
|
|
|
899
|
3 |
|
$fontEmbedData4 = $this->loadRecordHeader($stream, $pos); |
|
900
|
3 |
|
if ($fontEmbedData4['recVer'] == 0x0 && $fontEmbedData4['recInstance'] >= 0x000 && $fontEmbedData4['recInstance'] <= 0x003 && $fontEmbedData4['recType'] == self::RT_FONTEMBEDDATABLOB) { |
|
901
|
|
|
$pos += 8; |
|
902
|
|
|
$fontCollection['recLen'] -= 8; |
|
903
|
|
|
$pos += $fontEmbedData4['recLen']; |
|
904
|
|
|
$fontCollection['recLen'] -= $fontEmbedData4['recLen']; |
|
905
|
|
|
} |
|
906
|
3 |
|
} while ($fontCollection['recLen'] > 0); |
|
907
|
|
|
} |
|
908
|
|
|
|
|
909
|
3 |
|
$textCFDefaultsAtom = $this->loadRecordHeader($stream, $pos); |
|
910
|
3 |
|
if ($textCFDefaultsAtom['recVer'] == 0x0 && $textCFDefaultsAtom['recInstance'] == 0x000 && $textCFDefaultsAtom['recType'] == self::RT_TEXTCHARFORMATEXCEPTIONATOM) { |
|
911
|
3 |
|
$pos += 8; |
|
912
|
3 |
|
$pos += $textCFDefaultsAtom['recLen']; |
|
913
|
|
|
} |
|
914
|
|
|
|
|
915
|
3 |
|
$textPFDefaultsAtom = $this->loadRecordHeader($stream, $pos); |
|
916
|
3 |
|
if ($textPFDefaultsAtom['recVer'] == 0x0 && $textPFDefaultsAtom['recInstance'] == 0x000 && $textPFDefaultsAtom['recType'] == self::RT_TEXTPARAGRAPHFORMATEXCEPTIONATOM) { |
|
917
|
|
|
$pos += 8; |
|
918
|
|
|
$pos += $textPFDefaultsAtom['recLen']; |
|
919
|
|
|
} |
|
920
|
|
|
|
|
921
|
3 |
|
$defaultRulerAtom = $this->loadRecordHeader($stream, $pos); |
|
922
|
3 |
|
if ($defaultRulerAtom['recVer'] == 0x0 && $defaultRulerAtom['recInstance'] == 0x000 && $defaultRulerAtom['recType'] == self::RT_DEFAULTRULERATOM) { |
|
923
|
|
|
$pos += 8; |
|
924
|
|
|
$pos += $defaultRulerAtom['recLen']; |
|
925
|
|
|
} |
|
926
|
|
|
|
|
927
|
3 |
|
$textSIDefaultsAtom = $this->loadRecordHeader($stream, $pos); |
|
928
|
3 |
|
if ($textSIDefaultsAtom['recVer'] == 0x0 && $textSIDefaultsAtom['recInstance'] == 0x000 && $textSIDefaultsAtom['recType'] == self::RT_TEXTSPECIALINFODEFAULTATOM) { |
|
929
|
3 |
|
$pos += 8; |
|
930
|
3 |
|
$pos += $textSIDefaultsAtom['recLen']; |
|
931
|
|
|
} |
|
932
|
|
|
|
|
933
|
3 |
|
$textMasterStyleAtom = $this->loadRecordHeader($stream, $pos); |
|
934
|
3 |
|
if ($textMasterStyleAtom['recVer'] == 0x0 && $textMasterStyleAtom['recType'] == self::RT_TEXTMASTERSTYLEATOM) { |
|
935
|
3 |
|
$pos += 8; |
|
936
|
3 |
|
$pos += $textMasterStyleAtom['recLen']; |
|
937
|
|
|
} |
|
938
|
|
|
} |
|
939
|
|
|
|
|
940
|
3 |
|
$soundCollection = $this->loadRecordHeader($stream, $pos); |
|
941
|
3 |
|
if ($soundCollection['recVer'] == 0xF && $soundCollection['recInstance'] == 0x005 && $soundCollection['recType'] == self::RT_SOUNDCOLLECTION) { |
|
942
|
|
|
$pos += 8; |
|
943
|
|
|
$pos += $soundCollection['recLen']; |
|
944
|
|
|
} |
|
945
|
|
|
|
|
946
|
3 |
|
$drawingGroup = $this->loadRecordHeader($stream, $pos); |
|
947
|
3 |
|
if ($drawingGroup['recVer'] == 0xF && $drawingGroup['recInstance'] == 0x000 && $drawingGroup['recType'] == self::RT_DRAWINGGROUP) { |
|
948
|
3 |
|
$drawing = $this->readRecordDrawingGroupContainer($stream, $pos); |
|
949
|
3 |
|
$pos += 8; |
|
950
|
3 |
|
$pos += $drawing['length']; |
|
951
|
|
|
} |
|
952
|
|
|
|
|
953
|
3 |
|
$masterList = $this->loadRecordHeader($stream, $pos); |
|
954
|
3 |
|
if ($masterList['recVer'] == 0xF && $masterList['recInstance'] == 0x001 && $masterList['recType'] == self::RT_SLIDELISTWITHTEXT) { |
|
955
|
|
|
$pos += 8; |
|
956
|
|
|
$pos += $masterList['recLen']; |
|
957
|
|
|
} |
|
958
|
|
|
|
|
959
|
3 |
|
$docInfoList = $this->loadRecordHeader($stream, $pos); |
|
960
|
3 |
|
if ($docInfoList['recVer'] == 0xF && $docInfoList['recInstance'] == 0x000 && $docInfoList['recType'] == self::RT_LIST) { |
|
961
|
|
|
$pos += 8; |
|
962
|
|
|
$pos += $docInfoList['recLen']; |
|
963
|
|
|
} |
|
964
|
|
|
|
|
965
|
3 |
|
$slideHF = $this->loadRecordHeader($stream, $pos); |
|
966
|
3 |
|
if ($slideHF['recVer'] == 0xF && $slideHF['recInstance'] == 0x003 && $slideHF['recType'] == self::RT_HEADERSFOOTERS) { |
|
967
|
|
|
$pos += 8; |
|
968
|
|
|
$pos += $slideHF['recLen']; |
|
969
|
|
|
} |
|
970
|
|
|
|
|
971
|
3 |
|
$notesHF = $this->loadRecordHeader($stream, $pos); |
|
972
|
3 |
|
if ($notesHF['recVer'] == 0xF && $notesHF['recInstance'] == 0x004 && $notesHF['recType'] == self::RT_HEADERSFOOTERS) { |
|
973
|
|
|
$pos += 8; |
|
974
|
|
|
$pos += $notesHF['recLen']; |
|
975
|
|
|
} |
|
976
|
|
|
|
|
977
|
|
|
// SlideListWithTextContainer |
|
978
|
3 |
|
$slideList = $this->loadRecordHeader($stream, $pos); |
|
979
|
3 |
|
if ($slideList['recVer'] == 0xF && $slideList['recInstance'] == 0x000 && $slideList['recType'] == self::RT_SLIDELISTWITHTEXT) { |
|
980
|
|
|
$pos += 8; |
|
981
|
|
|
do { |
|
982
|
|
|
// SlideListWithTextSubContainerOrAtom |
|
983
|
|
|
$rhSlideList = $this->loadRecordHeader($stream, $pos); |
|
984
|
|
|
if ($rhSlideList['recVer'] == 0x0 && $rhSlideList['recInstance'] == 0x000 && $rhSlideList['recType'] == self::RT_SLIDEPERSISTATOM && $rhSlideList['recLen'] == 0x00000014) { |
|
985
|
|
|
$pos += 8; |
|
986
|
|
|
$slideList['recLen'] -= 8; |
|
987
|
|
|
// persistIdRef |
|
988
|
|
|
$pos += 4; |
|
989
|
|
|
$slideList['recLen'] -= 4; |
|
990
|
|
|
// reserved1 - fShouldCollapse - fNonOutlineData - reserved2 |
|
991
|
|
|
$pos += 4; |
|
992
|
|
|
$slideList['recLen'] -= 4; |
|
993
|
|
|
// cTexts |
|
994
|
|
|
$pos += 4; |
|
995
|
|
|
$slideList['recLen'] -= 4; |
|
996
|
|
|
// slideId |
|
997
|
|
|
$slideId = self::getInt4d($stream, $pos); |
|
998
|
|
|
if ($slideId == -2147483648) { |
|
999
|
|
|
$slideId = 0; |
|
1000
|
|
|
} |
|
1001
|
|
|
if ($slideId > 0) { |
|
1002
|
|
|
$this->arrayNotes[$this->oPhpPresentation->getActiveSlideIndex()] = $slideId; |
|
1003
|
|
|
} |
|
1004
|
|
|
$pos += 4; |
|
1005
|
|
|
$slideList['recLen'] -= 4; |
|
1006
|
|
|
// reserved3 |
|
1007
|
|
|
$pos += 4; |
|
1008
|
|
|
$slideList['recLen'] -= 4; |
|
1009
|
|
|
} |
|
1010
|
|
|
} while ($slideList['recLen'] > 0); |
|
1011
|
|
|
} |
|
1012
|
3 |
|
} |
|
1013
|
|
|
|
|
1014
|
|
|
/** |
|
1015
|
|
|
* An atom record that specifies information about a slide. |
|
1016
|
|
|
* @param string $stream |
|
1017
|
|
|
* @param integer $pos |
|
1018
|
|
|
* @return array |
|
1019
|
|
|
* @throws \Exception |
|
1020
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx |
|
1021
|
|
|
*/ |
|
1022
|
3 |
|
private function readRecordDrawingContainer($stream, $pos) |
|
1023
|
|
|
{ |
|
1024
|
|
|
$arrayReturn = array( |
|
1025
|
3 |
|
'length' => 0, |
|
1026
|
|
|
); |
|
1027
|
|
|
|
|
1028
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1029
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_DRAWING) { |
|
1030
|
|
|
// Record Header |
|
1031
|
3 |
|
$arrayReturn['length'] += 8; |
|
1032
|
|
|
|
|
1033
|
3 |
|
$officeArtDg = $this->readRecordOfficeArtDgContainer($stream, $pos + $arrayReturn['length']); |
|
1034
|
3 |
|
$arrayReturn['length'] += $officeArtDg['length']; |
|
1035
|
|
|
} |
|
1036
|
3 |
|
return $arrayReturn; |
|
1037
|
|
|
} |
|
1038
|
|
|
|
|
1039
|
3 |
|
private function readRecordDrawingGroupContainer($stream, $pos) |
|
|
|
|
|
|
1040
|
|
|
{ |
|
1041
|
|
|
|
|
1042
|
|
|
$arrayReturn = array( |
|
1043
|
3 |
|
'length' => 0, |
|
1044
|
|
|
); |
|
1045
|
|
|
|
|
1046
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1047
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_DRAWINGGROUP) { |
|
1048
|
|
|
// Record Header |
|
1049
|
3 |
|
$arrayReturn['length'] += 8; |
|
1050
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
1051
|
|
|
} |
|
1052
|
3 |
|
return $arrayReturn; |
|
1053
|
|
|
} |
|
1054
|
|
|
|
|
1055
|
|
|
/** |
|
1056
|
|
|
* An atom record that specifies a reference to an external object. |
|
1057
|
|
|
* @param string $stream |
|
1058
|
|
|
* @param integer $pos |
|
1059
|
|
|
* @return array |
|
1060
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910388(v=office.12).aspx |
|
1061
|
|
|
*/ |
|
1062
|
3 |
|
private function readRecordExObjRefAtom($stream, $pos) |
|
1063
|
|
|
{ |
|
1064
|
|
|
$arrayReturn = array( |
|
1065
|
3 |
|
'length' => 0, |
|
1066
|
|
|
); |
|
1067
|
|
|
|
|
1068
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1069
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_EXTERNALOBJECTREFATOM && $data['recLen'] == 0x00000004) { |
|
1070
|
|
|
// Record Header |
|
1071
|
|
|
$arrayReturn['length'] += 8; |
|
1072
|
|
|
// Datas |
|
1073
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
1074
|
|
|
} |
|
1075
|
|
|
|
|
1076
|
3 |
|
return $arrayReturn; |
|
1077
|
|
|
} |
|
1078
|
|
|
|
|
1079
|
|
|
/** |
|
1080
|
|
|
* An atom record that specifies a type of action to be performed. |
|
1081
|
|
|
* @param string $stream |
|
1082
|
|
|
* @param integer $pos |
|
1083
|
|
|
* @return array |
|
1084
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd953300(v=office.12).aspx |
|
1085
|
|
|
*/ |
|
1086
|
1 |
|
private function readRecordInteractiveInfoAtom($stream, $pos) |
|
1087
|
|
|
{ |
|
1088
|
|
|
$arrayReturn = array( |
|
1089
|
1 |
|
'length' => 0, |
|
1090
|
|
|
); |
|
1091
|
|
|
|
|
1092
|
1 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1093
|
1 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_INTERACTIVEINFOATOM && $data['recLen'] == 0x00000010) { |
|
1094
|
|
|
// Record Header |
|
1095
|
1 |
|
$arrayReturn['length'] += 8; |
|
1096
|
|
|
// soundIdRef |
|
1097
|
1 |
|
$arrayReturn['length'] += 4; |
|
1098
|
|
|
// exHyperlinkIdRef |
|
1099
|
1 |
|
$arrayReturn['exHyperlinkIdRef'] = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
1100
|
1 |
|
$arrayReturn['length'] += 4; |
|
1101
|
|
|
// action |
|
1102
|
1 |
|
$arrayReturn['length'] += 1; |
|
1103
|
|
|
// oleVerb |
|
1104
|
1 |
|
$arrayReturn['length'] += 1; |
|
1105
|
|
|
// jump |
|
1106
|
1 |
|
$arrayReturn['length'] += 1; |
|
1107
|
|
|
// fAnimated (1 bit) |
|
1108
|
|
|
// fStopSound (1 bit) |
|
1109
|
|
|
// fCustomShowReturn (1 bit) |
|
1110
|
|
|
// fVisited (1 bit) |
|
1111
|
|
|
// reserved (4 bits) |
|
1112
|
1 |
|
$arrayReturn['length'] += 1; |
|
1113
|
|
|
// hyperlinkType |
|
1114
|
1 |
|
$arrayReturn['length'] += 1; |
|
1115
|
|
|
// unused |
|
1116
|
1 |
|
$arrayReturn['length'] += 3; |
|
1117
|
|
|
} |
|
1118
|
|
|
|
|
1119
|
1 |
|
return $arrayReturn; |
|
1120
|
|
|
} |
|
1121
|
|
|
|
|
1122
|
|
|
/** |
|
1123
|
|
|
* An atom record that specifies the name of a macro, a file name, or a named show. |
|
1124
|
|
|
* @param string $stream |
|
1125
|
|
|
* @param integer $pos |
|
1126
|
|
|
* @return array |
|
1127
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925121(v=office.12).aspx |
|
1128
|
|
|
*/ |
|
1129
|
1 |
|
private function readRecordMacroNameAtom($stream, $pos) |
|
1130
|
|
|
{ |
|
1131
|
|
|
$arrayReturn = array( |
|
1132
|
1 |
|
'length' => 0, |
|
1133
|
|
|
); |
|
1134
|
|
|
|
|
1135
|
1 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1136
|
1 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x002 && $data['recType'] == self::RT_CSTRING && $data['recLen'] % 2 == 0) { |
|
1137
|
|
|
// Record Header |
|
1138
|
|
|
$arrayReturn['length'] += 8; |
|
1139
|
|
|
// Datas |
|
1140
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
1141
|
|
|
} |
|
1142
|
|
|
|
|
1143
|
1 |
|
return $arrayReturn; |
|
1144
|
|
|
} |
|
1145
|
|
|
|
|
1146
|
|
|
/** |
|
1147
|
|
|
* A container record that specifies what actions to perform when interacting with an object by means of a mouse click. |
|
1148
|
|
|
* @param string $stream |
|
1149
|
|
|
* @param integer $pos |
|
1150
|
|
|
* @return array |
|
1151
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd952348(v=office.12).aspx |
|
1152
|
|
|
*/ |
|
1153
|
3 |
|
private function readRecordMouseClickInteractiveInfoContainer($stream, $pos) |
|
1154
|
|
|
{ |
|
1155
|
|
|
$arrayReturn = array( |
|
1156
|
3 |
|
'length' => 0, |
|
1157
|
|
|
); |
|
1158
|
|
|
|
|
1159
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1160
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_INTERACTIVEINFO) { |
|
1161
|
|
|
// Record Header |
|
1162
|
1 |
|
$arrayReturn['length'] += 8; |
|
1163
|
|
|
// interactiveInfoAtom |
|
1164
|
1 |
|
$interactiveInfoAtom = $this->readRecordInteractiveInfoAtom($stream, $pos + $arrayReturn['length']); |
|
1165
|
1 |
|
$arrayReturn['length'] += $interactiveInfoAtom['length']; |
|
1166
|
1 |
|
if ($interactiveInfoAtom['length'] > 0) { |
|
1167
|
1 |
|
$arrayReturn['exHyperlinkIdRef'] = $interactiveInfoAtom['exHyperlinkIdRef']; |
|
1168
|
|
|
} |
|
1169
|
|
|
// macroNameAtom |
|
1170
|
1 |
|
$macroNameAtom = $this->readRecordMacroNameAtom($stream, $pos + $arrayReturn['length']); |
|
1171
|
1 |
|
$arrayReturn['length'] += $macroNameAtom['length']; |
|
1172
|
|
|
} |
|
1173
|
|
|
|
|
1174
|
3 |
|
return $arrayReturn; |
|
1175
|
|
|
} |
|
1176
|
|
|
|
|
1177
|
|
|
/** |
|
1178
|
|
|
* A container record that specifies what actions to perform when interacting with an object by moving the mouse cursor over it. |
|
1179
|
|
|
* @param string $stream |
|
1180
|
|
|
* @param integer $pos |
|
1181
|
|
|
* @return array |
|
1182
|
|
|
* @throws \Exception |
|
1183
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925811(v=office.12).aspx |
|
1184
|
|
|
*/ |
|
1185
|
3 |
|
private function readRecordMouseOverInteractiveInfoContainer($stream, $pos) |
|
1186
|
|
|
{ |
|
1187
|
|
|
$arrayReturn = array( |
|
1188
|
3 |
|
'length' => 0, |
|
1189
|
|
|
); |
|
1190
|
|
|
|
|
1191
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1192
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x001 && $data['recType'] == self::RT_INTERACTIVEINFO) { |
|
1193
|
|
|
// Record Header |
|
1194
|
|
|
$arrayReturn['length'] += 8; |
|
1195
|
|
|
// interactiveInfoAtom |
|
1196
|
|
|
// macroNameAtom |
|
1197
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
1198
|
|
|
} |
|
1199
|
|
|
|
|
1200
|
3 |
|
return $arrayReturn; |
|
1201
|
|
|
} |
|
1202
|
|
|
|
|
1203
|
|
|
/** |
|
1204
|
|
|
* The OfficeArtBlip record specifies BLIP file data. |
|
1205
|
|
|
* @param string $stream |
|
1206
|
|
|
* @param integer $pos |
|
1207
|
|
|
* @return array |
|
1208
|
|
|
* @throws \Exception |
|
1209
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910081(v=office.12).aspx |
|
1210
|
|
|
*/ |
|
1211
|
3 |
|
private function readRecordOfficeArtBlip($stream, $pos) |
|
1212
|
|
|
{ |
|
1213
|
|
|
$arrayReturn = array( |
|
1214
|
3 |
|
'length' => 0, |
|
1215
|
|
|
'picture' => null |
|
1216
|
|
|
); |
|
1217
|
|
|
|
|
1218
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1219
|
3 |
|
if ($data['recVer'] == 0x0 && ($data['recType'] >= 0xF018 && $data['recType'] <= 0xF117)) { |
|
1220
|
|
|
// Record Header |
|
1221
|
3 |
|
$arrayReturn['length'] += 8; |
|
1222
|
|
|
// Datas |
|
1223
|
3 |
|
switch ($data['recType']) { |
|
1224
|
3 |
|
case self::OFFICEARTBLIPJPG: |
|
1225
|
2 |
|
case self::OFFICEARTBLIPPNG: |
|
1226
|
|
|
// rgbUid1 |
|
1227
|
3 |
|
$arrayReturn['length'] += 16; |
|
1228
|
3 |
|
$data['recLen'] -= 16; |
|
1229
|
3 |
|
if ($data['recInstance'] == 0x6E1) { |
|
1230
|
|
|
// rgbUid2 |
|
1231
|
|
|
$arrayReturn['length'] += 16; |
|
1232
|
|
|
$data['recLen'] -= 16; |
|
1233
|
|
|
} |
|
1234
|
|
|
// tag |
|
1235
|
3 |
|
$arrayReturn['length'] += 1; |
|
1236
|
3 |
|
$data['recLen'] -= 1; |
|
1237
|
|
|
// BLIPFileData |
|
1238
|
3 |
|
$arrayReturn['picture'] = substr($this->streamPictures, $pos + $arrayReturn['length'], $data['recLen']); |
|
1239
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
1240
|
3 |
|
break; |
|
1241
|
|
|
default: |
|
1242
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : '.dechex($data['recType'].')')); |
|
1243
|
|
|
} |
|
1244
|
|
|
} |
|
1245
|
|
|
|
|
1246
|
3 |
|
return $arrayReturn; |
|
1247
|
|
|
} |
|
1248
|
|
|
|
|
1249
|
|
|
/** |
|
1250
|
|
|
* The OfficeArtChildAnchor record specifies four signed integers that specify the anchor for the shape that contains this record. |
|
1251
|
|
|
* @param string $stream |
|
1252
|
|
|
* @param integer $pos |
|
1253
|
|
|
* @return array |
|
1254
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922720(v=office.12).aspx |
|
1255
|
|
|
*/ |
|
1256
|
3 |
|
private function readRecordOfficeArtChildAnchor($stream, $pos) |
|
1257
|
|
|
{ |
|
1258
|
|
|
$arrayReturn = array( |
|
1259
|
3 |
|
'length' => 0 |
|
1260
|
|
|
); |
|
1261
|
|
|
|
|
1262
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1263
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF00F && $data['recLen'] == 0x00000010) { |
|
1264
|
|
|
// Record Header |
|
1265
|
|
|
$arrayReturn['length'] += 8; |
|
1266
|
|
|
// Datas |
|
1267
|
|
|
$arrayReturn['left'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
1268
|
|
|
$arrayReturn['length'] += 4; |
|
1269
|
|
|
$arrayReturn['top'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
1270
|
|
|
$arrayReturn['length'] += 4; |
|
1271
|
|
|
$arrayReturn['width'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']) - $arrayReturn['left']; |
|
1272
|
|
|
$arrayReturn['length'] += 4; |
|
1273
|
|
|
$arrayReturn['height'] = (int) self::getInt4d($stream, $pos + $arrayReturn['length']) - $arrayReturn['top']; |
|
1274
|
|
|
$arrayReturn['length'] += 4; |
|
1275
|
|
|
} |
|
1276
|
|
|
|
|
1277
|
3 |
|
return $arrayReturn; |
|
1278
|
|
|
} |
|
1279
|
|
|
|
|
1280
|
|
|
/** |
|
1281
|
|
|
* An atom record that specifies the location of a shape. |
|
1282
|
|
|
* @param string $stream |
|
1283
|
|
|
* @param integer $pos |
|
1284
|
|
|
* @return array |
|
1285
|
|
|
* @throws \Exception |
|
1286
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922797(v=office.12).aspx |
|
1287
|
|
|
*/ |
|
1288
|
3 |
|
private function readRecordOfficeArtClientAnchor($stream, $pos) |
|
1289
|
|
|
{ |
|
1290
|
|
|
$arrayReturn = array( |
|
1291
|
3 |
|
'length' => 0 |
|
1292
|
|
|
); |
|
1293
|
|
|
|
|
1294
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1295
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF010 && ($data['recLen'] == 0x00000008 || $data['recLen'] == 0x00000010)) { |
|
1296
|
|
|
// Record Header |
|
1297
|
3 |
|
$arrayReturn['length'] += 8; |
|
1298
|
|
|
// Datas |
|
1299
|
3 |
|
switch ($data['recLen']) { |
|
1300
|
3 |
|
case 0x00000008: |
|
1301
|
3 |
|
$arrayReturn['top'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6); |
|
1302
|
3 |
|
$arrayReturn['length'] += 2; |
|
1303
|
3 |
|
$arrayReturn['left'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6); |
|
1304
|
3 |
|
$arrayReturn['length'] += 2; |
|
1305
|
3 |
|
$arrayReturn['width'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6) - $arrayReturn['left']; |
|
1306
|
3 |
|
$arrayReturn['length'] += 2; |
|
1307
|
3 |
|
$arrayReturn['height'] = (int) (self::getInt2d($stream, $pos + $arrayReturn['length']) / 6) - $arrayReturn['left']; |
|
1308
|
3 |
|
$arrayReturn['length'] += 2; |
|
1309
|
3 |
|
$pos += 8; |
|
1310
|
3 |
|
break; |
|
1311
|
|
|
case 0x00000010: |
|
1312
|
|
|
throw new \Exception('PowerPoint97 Reader : record OfficeArtClientAnchor (0x00000010)'); |
|
1313
|
|
|
} |
|
1314
|
|
|
} |
|
1315
|
|
|
|
|
1316
|
3 |
|
return $arrayReturn; |
|
1317
|
|
|
} |
|
1318
|
|
|
|
|
1319
|
|
|
/** |
|
1320
|
|
|
* A container record that specifies text related data for a shape. |
|
1321
|
|
|
* @param string $stream |
|
1322
|
|
|
* @param integer $pos |
|
1323
|
|
|
* @return array |
|
1324
|
|
|
* @throws \Exception |
|
1325
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910958(v=office.12).aspx |
|
1326
|
|
|
*/ |
|
1327
|
3 |
|
private function readRecordOfficeArtClientTextbox($stream, $pos) |
|
1328
|
|
|
{ |
|
1329
|
|
|
$arrayReturn = array( |
|
1330
|
3 |
|
'length' => 0, |
|
1331
|
|
|
'text' => '', |
|
1332
|
|
|
'numParts' => 0, |
|
1333
|
|
|
'numTexts' => 0, |
|
1334
|
|
|
'hyperlink' => array(), |
|
1335
|
|
|
); |
|
1336
|
|
|
|
|
1337
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1338
|
|
|
// recVer 0xF |
|
1339
|
|
|
// Doc : 0x0 https://msdn.microsoft.com/en-us/library/dd910958(v=office.12).aspx |
|
1340
|
|
|
// Sample : 0xF https://msdn.microsoft.com/en-us/library/dd953497(v=office.12).aspx |
|
1341
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF00D) { |
|
1342
|
|
|
// Record Header |
|
1343
|
3 |
|
$arrayReturn['length'] += 8; |
|
1344
|
|
|
// Datas |
|
1345
|
3 |
|
$strLen = 0; |
|
1346
|
|
|
do { |
|
1347
|
3 |
|
$rhChild = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']); |
|
1348
|
|
|
/** |
|
1349
|
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd947039(v=office.12).aspx |
|
1350
|
|
|
*/ |
|
1351
|
|
|
// echo dechex($rhChild['recType']).'-'.$rhChild['recType'].EOL; |
|
1352
|
3 |
|
switch ($rhChild['recType']) { |
|
1353
|
3 |
|
case self::RT_INTERACTIVEINFO: |
|
1354
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948623(v=office.12).aspx |
|
1355
|
1 |
|
if ($rhChild['recInstance'] == 0x0000) { |
|
1356
|
1 |
|
$mouseClickInfo = $this->readRecordMouseClickInteractiveInfoContainer($stream, $pos + $arrayReturn['length']); |
|
1357
|
1 |
|
$arrayReturn['length'] += $mouseClickInfo['length']; |
|
1358
|
1 |
|
$arrayReturn['hyperlink'][]['id'] = $mouseClickInfo['exHyperlinkIdRef']; |
|
1359
|
|
|
} |
|
1360
|
1 |
|
if ($rhChild['recInstance'] == 0x0001) { |
|
1361
|
|
|
$mouseOverInfo = $this->readRecordMouseOverInteractiveInfoContainer($stream, $pos + $arrayReturn['length']); |
|
1362
|
|
|
$arrayReturn['length'] += $mouseOverInfo['length']; |
|
1363
|
|
|
} |
|
1364
|
1 |
|
break; |
|
1365
|
3 |
|
case self::RT_STYLETEXTPROPATOM: |
|
1366
|
3 |
|
$arrayReturn['length'] += 8; |
|
1367
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd950647(v=office.12).aspx |
|
1368
|
|
|
// rgTextPFRun |
|
1369
|
3 |
|
$strLenRT = $strLen + 1; |
|
1370
|
|
|
do { |
|
1371
|
3 |
|
$strucTextPFRun = $this->readStructureTextPFRun($stream, $pos + $arrayReturn['length'], $strLenRT); |
|
1372
|
3 |
|
$arrayReturn['numTexts']++; |
|
1373
|
3 |
|
$arrayReturn['text'.$arrayReturn['numTexts']] = $strucTextPFRun; |
|
1374
|
3 |
|
if (isset($strucTextPFRun['alignH'])) { |
|
1375
|
3 |
|
$arrayReturn['alignH'] = $strucTextPFRun['alignH']; |
|
1376
|
|
|
} |
|
1377
|
3 |
|
$strLenRT = $strucTextPFRun['strLenRT']; |
|
1378
|
3 |
|
$arrayReturn['length'] += $strucTextPFRun['length']; |
|
1379
|
3 |
|
} while ($strLenRT > 0); |
|
1380
|
|
|
// rgTextCFRun |
|
1381
|
3 |
|
$strLenRT = $strLen + 1; |
|
1382
|
|
|
do { |
|
1383
|
3 |
|
$strucTextCFRun = $this->readStructureTextCFRun($stream, $pos + $arrayReturn['length'], $strLenRT); |
|
1384
|
3 |
|
$arrayReturn['numParts']++; |
|
1385
|
3 |
|
$arrayReturn['part'.$arrayReturn['numParts']] = $strucTextCFRun; |
|
1386
|
3 |
|
$strLenRT = $strucTextCFRun['strLenRT']; |
|
1387
|
3 |
|
$arrayReturn['length'] += $strucTextCFRun['length']; |
|
1388
|
3 |
|
} while ($strLenRT > 0); |
|
1389
|
3 |
|
break; |
|
1390
|
3 |
|
case self::RT_TEXTBYTESATOM: |
|
1391
|
|
|
$arrayReturn['length'] += 8; |
|
1392
|
|
|
// @link : https://msdn.microsoft.com/en-us/library/dd947905(v=office.12).aspx |
|
1393
|
|
|
$strLen = (int)$rhChild['recLen']; |
|
1394
|
|
|
for ($inc = 0; $inc < $strLen; $inc++) { |
|
1395
|
|
|
$char = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
1396
|
|
|
if ($char == 0x0B) { |
|
1397
|
|
|
$char = 0x20; |
|
1398
|
|
|
} |
|
1399
|
|
|
$arrayReturn['text'] .= Text::chr($char); |
|
1400
|
|
|
$arrayReturn['length'] += 1; |
|
1401
|
|
|
} |
|
1402
|
|
|
break; |
|
1403
|
3 |
|
case self::RT_TEXTCHARSATOM: |
|
1404
|
3 |
|
$arrayReturn['length'] += 8; |
|
1405
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd772921(v=office.12).aspx |
|
1406
|
3 |
|
$strLen = (int)($rhChild['recLen']/2); |
|
1407
|
3 |
|
for ($inc = 0; $inc < $strLen; $inc++) { |
|
1408
|
3 |
|
$char = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
1409
|
3 |
|
if ($char == 0x0B) { |
|
1410
|
1 |
|
$char = 0x20; |
|
1411
|
|
|
} |
|
1412
|
3 |
|
$arrayReturn['text'] .= Text::chr($char); |
|
1413
|
3 |
|
$arrayReturn['length'] += 2; |
|
1414
|
|
|
} |
|
1415
|
3 |
|
break; |
|
1416
|
3 |
|
case self::RT_TEXTHEADERATOM: |
|
1417
|
3 |
|
$arrayReturn['length'] += 8; |
|
1418
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd905272(v=office.12).aspx |
|
1419
|
|
|
// textType |
|
1420
|
3 |
|
$arrayReturn['length'] += 4; |
|
1421
|
3 |
|
break; |
|
1422
|
3 |
|
case self::RT_TEXTINTERACTIVEINFOATOM: |
|
1423
|
1 |
|
$arrayReturn['length'] += 8; |
|
1424
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947973(v=office.12).aspx |
|
1425
|
1 |
|
if ($rhChild['recInstance'] == 0x0000) { |
|
1426
|
|
|
//@todo : MouseClickTextInteractiveInfoAtom |
|
1427
|
1 |
|
$arrayReturn['hyperlink'][count($arrayReturn['hyperlink']) - 1]['start'] = self::getInt4d($stream, $pos + + $arrayReturn['length']); |
|
1428
|
1 |
|
$arrayReturn['length'] += 4; |
|
1429
|
|
|
|
|
1430
|
1 |
|
$arrayReturn['hyperlink'][count($arrayReturn['hyperlink']) - 1]['end'] = self::getInt4d($stream, $pos + + $arrayReturn['length']); |
|
1431
|
1 |
|
$arrayReturn['length'] += 4; |
|
1432
|
|
|
} |
|
1433
|
1 |
|
if ($rhChild['recInstance'] == 0x0001) { |
|
1434
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
1435
|
|
|
} |
|
1436
|
1 |
|
break; |
|
1437
|
3 |
|
case self::RT_TEXTSPECIALINFOATOM: |
|
1438
|
3 |
|
$arrayReturn['length'] += 8; |
|
1439
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd945296(v=office.12).aspx |
|
1440
|
3 |
|
$strLenRT = $strLen + 1; |
|
1441
|
|
|
do { |
|
1442
|
3 |
|
$structTextSIRun = $this->readStructureTextSIRun($stream, $pos + $arrayReturn['length'], $strLenRT); |
|
1443
|
3 |
|
$strLenRT = $structTextSIRun['strLenRT']; |
|
1444
|
3 |
|
$arrayReturn['length'] += $structTextSIRun['length']; |
|
1445
|
3 |
|
} while ($strLenRT > 0); |
|
1446
|
3 |
|
break; |
|
1447
|
3 |
|
case self::RT_TEXTRULERATOM: |
|
1448
|
3 |
|
$arrayReturn['length'] += 8; |
|
1449
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd953212(v=office.12).aspx |
|
1450
|
3 |
|
$structRuler = $this->readStructureTextRuler($stream, $pos + $arrayReturn['length']); |
|
1451
|
3 |
|
$arrayReturn['length'] += $structRuler['length']; |
|
1452
|
3 |
|
break; |
|
1453
|
3 |
|
case self::RT_SLIDENUMBERMETACHARATOM: |
|
1454
|
3 |
|
$datasRecord = $this->readRecordSlideNumberMCAtom($stream, $pos + $arrayReturn['length']); |
|
1455
|
3 |
|
$arrayReturn['length'] += $datasRecord['length']; |
|
1456
|
3 |
|
break; |
|
1457
|
|
|
default: |
|
1458
|
3 |
|
$arrayReturn['length'] += 8; |
|
1459
|
3 |
|
$arrayReturn['length'] += $rhChild['recLen']; |
|
1460
|
|
|
// throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($rhChild['recType']).')'); |
|
1461
|
|
|
} |
|
1462
|
3 |
|
} while (($data['recLen'] - $arrayReturn['length']) > 0); |
|
1463
|
|
|
} |
|
1464
|
3 |
|
return $arrayReturn; |
|
1465
|
|
|
} |
|
1466
|
|
|
|
|
1467
|
|
|
/** |
|
1468
|
|
|
* The OfficeArtSpContainer record specifies a shape container. |
|
1469
|
|
|
* @param string $stream |
|
1470
|
|
|
* @param integer $pos |
|
1471
|
|
|
* @return array |
|
1472
|
|
|
* @throws \Exception |
|
1473
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943794(v=office.12).aspx |
|
1474
|
|
|
*/ |
|
1475
|
3 |
|
private function readRecordOfficeArtSpContainer($stream, $pos) |
|
1476
|
|
|
{ |
|
1477
|
|
|
$arrayReturn = array( |
|
1478
|
3 |
|
'length' => 0, |
|
1479
|
|
|
'shape' => null, |
|
1480
|
|
|
); |
|
1481
|
|
|
|
|
1482
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1483
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF004) { |
|
1484
|
|
|
// Record Header |
|
1485
|
3 |
|
$arrayReturn['length'] += 8; |
|
1486
|
|
|
// shapeGroup |
|
1487
|
3 |
|
$shapeGroup = $this->readRecordOfficeArtFSPGR($stream, $pos + $arrayReturn['length']); |
|
1488
|
3 |
|
$arrayReturn['length'] += $shapeGroup['length']; |
|
1489
|
|
|
|
|
1490
|
|
|
// shapeProp |
|
1491
|
3 |
|
$shapeProp = $this->readRecordOfficeArtFSP($stream, $pos + $arrayReturn['length']); |
|
1492
|
3 |
|
if ($shapeProp['length'] == 0) { |
|
1493
|
|
|
throw new \Exception('PowerPoint97 Reader : record OfficeArtFSP'); |
|
1494
|
|
|
} |
|
1495
|
3 |
|
$arrayReturn['length'] += $shapeProp['length']; |
|
1496
|
|
|
|
|
1497
|
3 |
|
if ($shapeProp['fDeleted'] == 0x1 && $shapeProp['fChild'] == 0x0) { |
|
1498
|
|
|
// deletedShape |
|
1499
|
|
|
$deletedShape = $this->readRecordOfficeArtFPSPL($stream, $pos + $arrayReturn['length']); |
|
1500
|
|
|
$arrayReturn['length'] += $deletedShape['length']; |
|
1501
|
|
|
} |
|
1502
|
|
|
|
|
1503
|
|
|
// shapePrimaryOptions |
|
1504
|
3 |
|
$shpPrimaryOptions = $this->readRecordOfficeArtFOPT($stream, $pos + $arrayReturn['length']); |
|
1505
|
3 |
|
$arrayReturn['length'] += $shpPrimaryOptions['length']; |
|
1506
|
|
|
|
|
1507
|
|
|
// shapeSecondaryOptions1 |
|
1508
|
3 |
|
$shpSecondaryOptions1 = $this->readRecordOfficeArtSecondaryFOPT($stream, $pos + $arrayReturn['length']); |
|
1509
|
3 |
|
$arrayReturn['length'] += $shpSecondaryOptions1['length']; |
|
1510
|
|
|
|
|
1511
|
|
|
// shapeTertiaryOptions1 |
|
1512
|
3 |
|
$shpTertiaryOptions1 = $this->readRecordOfficeArtTertiaryFOPT($stream, $pos + $arrayReturn['length']); |
|
1513
|
3 |
|
$arrayReturn['length'] += $shpTertiaryOptions1['length']; |
|
1514
|
|
|
|
|
1515
|
|
|
// childAnchor |
|
1516
|
3 |
|
$childAnchor = $this->readRecordOfficeArtChildAnchor($stream, $pos + $arrayReturn['length']); |
|
1517
|
3 |
|
$arrayReturn['length'] += $childAnchor['length']; |
|
1518
|
|
|
|
|
1519
|
|
|
// clientAnchor |
|
1520
|
3 |
|
$clientAnchor = $this->readRecordOfficeArtClientAnchor($stream, $pos + $arrayReturn['length']); |
|
1521
|
3 |
|
$arrayReturn['length'] += $clientAnchor['length']; |
|
1522
|
|
|
|
|
1523
|
|
|
// clientData |
|
1524
|
3 |
|
$clientData = $this->readRecordOfficeArtClientData($stream, $pos + $arrayReturn['length']); |
|
1525
|
3 |
|
$arrayReturn['length'] += $clientData['length']; |
|
1526
|
|
|
|
|
1527
|
|
|
// clientTextbox |
|
1528
|
3 |
|
$clientTextbox = $this->readRecordOfficeArtClientTextbox($stream, $pos + $arrayReturn['length']); |
|
1529
|
3 |
|
$arrayReturn['length'] += $clientTextbox['length']; |
|
1530
|
|
|
|
|
1531
|
|
|
// shapeSecondaryOptions2 |
|
1532
|
3 |
|
if ($shpSecondaryOptions1['length'] == 0) { |
|
1533
|
3 |
|
$shpSecondaryOptions2 = $this->readRecordOfficeArtSecondaryFOPT($stream, $pos + $arrayReturn['length']); |
|
1534
|
3 |
|
$arrayReturn['length'] += $shpSecondaryOptions2['length']; |
|
1535
|
|
|
} |
|
1536
|
|
|
|
|
1537
|
|
|
// shapeTertiaryOptions2 |
|
1538
|
3 |
|
if ($shpTertiaryOptions1['length'] == 0) { |
|
1539
|
3 |
|
$shpTertiaryOptions2 = $this->readRecordOfficeArtTertiaryFOPT($stream, $pos + $arrayReturn['length']); |
|
1540
|
3 |
|
$arrayReturn['length'] += $shpTertiaryOptions2['length']; |
|
1541
|
|
|
} |
|
1542
|
|
|
|
|
1543
|
|
|
// Core : Shape |
|
1544
|
|
|
// Informations about group are not defined |
|
1545
|
3 |
|
$arrayDimensions = array(); |
|
1546
|
3 |
|
$bIsGroup = false; |
|
1547
|
3 |
|
if (is_object($this->oCurrentGroup)) { |
|
1548
|
|
|
if (!$this->bFirstShapeGroup) { |
|
1549
|
|
|
if ($clientAnchor['length'] > 0) { |
|
1550
|
|
|
// $this->oCurrentGroup->setOffsetX($clientAnchor['left']); |
|
1551
|
|
|
// $this->oCurrentGroup->setOffsetY($clientAnchor['top']); |
|
1552
|
|
|
// $this->oCurrentGroup->setHeight($clientAnchor['height']); |
|
1553
|
|
|
// $this->oCurrentGroup->setWidth($clientAnchor['width']); |
|
1554
|
|
|
} |
|
1555
|
|
|
$bIsGroup = true; |
|
1556
|
|
|
$this->bFirstShapeGroup = true; |
|
1557
|
|
|
} else { |
|
1558
|
|
|
if ($childAnchor['length'] > 0) { |
|
1559
|
|
|
$arrayDimensions = $childAnchor; |
|
1560
|
|
|
} |
|
1561
|
|
|
} |
|
1562
|
|
|
} else { |
|
1563
|
3 |
|
if ($clientAnchor['length'] > 0) { |
|
1564
|
3 |
|
$arrayDimensions = $clientAnchor; |
|
1565
|
|
|
} |
|
1566
|
|
|
} |
|
1567
|
3 |
|
if (!$bIsGroup) { |
|
1568
|
|
|
// *** Shape *** |
|
1569
|
3 |
|
if (isset($shpPrimaryOptions['pib'])) { |
|
1570
|
|
|
// isDrawing |
|
1571
|
3 |
|
$drawingPib = $shpPrimaryOptions['pib']; |
|
1572
|
3 |
|
if (isset($this->arrayPictures[$drawingPib - 1])) { |
|
1573
|
3 |
|
$gdImage = imagecreatefromstring($this->arrayPictures[$drawingPib - 1]); |
|
1574
|
3 |
|
$arrayReturn['shape'] = new Drawing\Gd(); |
|
1575
|
3 |
|
$arrayReturn['shape']->setImageResource($gdImage); |
|
1576
|
|
|
} |
|
1577
|
3 |
|
} elseif (isset($shpPrimaryOptions['line']) && $shpPrimaryOptions['line']) { |
|
1578
|
|
|
// isLine |
|
1579
|
1 |
|
$arrayReturn['shape'] = new Line(0, 0, 0, 0); |
|
1580
|
3 |
|
} elseif ($clientTextbox['length'] > 0) { |
|
1581
|
3 |
|
$arrayReturn['shape'] = new RichText(); |
|
1582
|
3 |
|
if (isset($clientTextbox['alignH'])) { |
|
1583
|
3 |
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setHorizontal($clientTextbox['alignH']); |
|
1584
|
|
|
} |
|
1585
|
|
|
|
|
1586
|
3 |
|
$start = 0; |
|
1587
|
3 |
|
$lastLevel = -1; |
|
1588
|
3 |
|
$lastMarginLeft = 0; |
|
1589
|
3 |
|
for ($inc = 1; $inc <= $clientTextbox['numParts']; $inc++) { |
|
1590
|
3 |
|
if ($clientTextbox['numParts'] == $clientTextbox['numTexts'] && isset($clientTextbox['text'.$inc])) { |
|
1591
|
3 |
|
if (isset($clientTextbox['text'.$inc]['bulletChar'])) { |
|
1592
|
1 |
|
$arrayReturn['shape']->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET); |
|
1593
|
1 |
|
$arrayReturn['shape']->getActiveParagraph()->getBulletStyle()->setBulletChar($clientTextbox['text'.$inc]['bulletChar']); |
|
1594
|
|
|
} |
|
1595
|
|
|
// Indent |
|
1596
|
3 |
|
$indent = 0; |
|
1597
|
3 |
|
if (isset($clientTextbox['text'.$inc]['indent'])) { |
|
1598
|
1 |
|
$indent = $clientTextbox['text'.$inc]['indent']; |
|
1599
|
|
|
} |
|
1600
|
3 |
|
if (isset($clientTextbox['text'.$inc]['leftMargin'])) { |
|
1601
|
1 |
|
if ($lastMarginLeft > $clientTextbox['text'.$inc]['leftMargin']) { |
|
1602
|
1 |
|
$lastLevel--; |
|
1603
|
|
|
} |
|
1604
|
1 |
|
if ($lastMarginLeft < $clientTextbox['text'.$inc]['leftMargin']) { |
|
1605
|
1 |
|
$lastLevel++; |
|
1606
|
|
|
} |
|
1607
|
1 |
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setLevel($lastLevel); |
|
1608
|
1 |
|
$lastMarginLeft = $clientTextbox['text'.$inc]['leftMargin']; |
|
1609
|
|
|
|
|
1610
|
1 |
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setMarginLeft($clientTextbox['text'.$inc]['leftMargin']); |
|
1611
|
1 |
|
$arrayReturn['shape']->getActiveParagraph()->getAlignment()->setIndent($indent - $clientTextbox['text'.$inc]['leftMargin']); |
|
1612
|
|
|
} |
|
1613
|
|
|
} |
|
1614
|
|
|
// Texte |
|
1615
|
3 |
|
$sText = substr(isset($clientTextbox['text']) ? $clientTextbox['text'] : '', $start, $clientTextbox['part'.$inc]['partLength']); |
|
1616
|
3 |
|
$sHyperlinkURL = ''; |
|
1617
|
3 |
|
if (empty($sText)) { |
|
1618
|
|
|
// Is there a hyperlink ? |
|
1619
|
1 |
|
if (isset($clientTextbox['hyperlink']) && is_array($clientTextbox['hyperlink']) && !empty($clientTextbox['hyperlink'])) { |
|
1620
|
1 |
|
foreach ($clientTextbox['hyperlink'] as $itmHyperlink) { |
|
1621
|
1 |
|
if ($itmHyperlink['start'] == $start && ($itmHyperlink['end'] - $itmHyperlink['start']) == $clientTextbox['part'.$inc]['partLength']) { |
|
1622
|
1 |
|
$sText = $this->arrayHyperlinks[$itmHyperlink['id']]['text']; |
|
1623
|
1 |
|
$sHyperlinkURL = $this->arrayHyperlinks[$itmHyperlink['id']]['url']; |
|
1624
|
1 |
|
break; |
|
1625
|
|
|
} |
|
1626
|
|
|
} |
|
1627
|
|
|
} |
|
1628
|
|
|
} |
|
1629
|
|
|
// New paragraph |
|
1630
|
3 |
|
$bCreateParagraph = false; |
|
1631
|
3 |
|
if (strpos($sText, "\r") !== false) { |
|
1632
|
1 |
|
$bCreateParagraph = true; |
|
1633
|
1 |
|
$sText = str_replace("\r", '', $sText); |
|
1634
|
|
|
} |
|
1635
|
|
|
// TextRun |
|
1636
|
3 |
|
$txtRun = $arrayReturn['shape']->createTextRun($sText); |
|
1637
|
3 |
|
if (isset($clientTextbox['part'.$inc]['bold'])) { |
|
1638
|
2 |
|
$txtRun->getFont()->setBold($clientTextbox['part'.$inc]['bold']); |
|
1639
|
|
|
} |
|
1640
|
3 |
|
if (isset($clientTextbox['part'.$inc]['italic'])) { |
|
1641
|
2 |
|
$txtRun->getFont()->setItalic($clientTextbox['part'.$inc]['italic']); |
|
1642
|
|
|
} |
|
1643
|
3 |
|
if (isset($clientTextbox['part'.$inc]['underline'])) { |
|
1644
|
2 |
|
$txtRun->getFont()->setUnderline($clientTextbox['part'.$inc]['underline']); |
|
1645
|
|
|
} |
|
1646
|
3 |
|
if (isset($clientTextbox['part'.$inc]['fontName'])) { |
|
1647
|
3 |
|
$txtRun->getFont()->setName($clientTextbox['part'.$inc]['fontName']); |
|
1648
|
|
|
} |
|
1649
|
3 |
|
if (isset($clientTextbox['part'.$inc]['fontSize'])) { |
|
1650
|
3 |
|
$txtRun->getFont()->setSize($clientTextbox['part'.$inc]['fontSize']); |
|
1651
|
|
|
} |
|
1652
|
3 |
|
if (isset($clientTextbox['part'.$inc]['color'])) { |
|
1653
|
3 |
|
$txtRun->getFont()->setColor($clientTextbox['part'.$inc]['color']); |
|
1654
|
|
|
} |
|
1655
|
|
|
// Hyperlink |
|
1656
|
3 |
|
if (!empty($sHyperlinkURL)) { |
|
1657
|
1 |
|
$txtRun->setHyperlink(new Hyperlink($sHyperlinkURL)); |
|
1658
|
|
|
} |
|
1659
|
|
|
|
|
1660
|
3 |
|
$start += $clientTextbox['part'.$inc]['partLength']; |
|
1661
|
3 |
|
if ($bCreateParagraph) { |
|
1662
|
1 |
|
$arrayReturn['shape']->createParagraph(); |
|
1663
|
|
|
} |
|
1664
|
|
|
} |
|
1665
|
|
|
} |
|
1666
|
|
|
|
|
1667
|
|
|
// *** Properties *** |
|
1668
|
|
|
// Dimensions |
|
1669
|
3 |
|
if ($arrayReturn['shape'] instanceof AbstractShape) { |
|
1670
|
3 |
|
if (!empty($arrayDimensions)) { |
|
1671
|
3 |
|
$arrayReturn['shape']->setOffsetX($arrayDimensions['left']); |
|
1672
|
3 |
|
$arrayReturn['shape']->setOffsetY($arrayDimensions['top']); |
|
1673
|
3 |
|
$arrayReturn['shape']->setHeight($arrayDimensions['height']); |
|
1674
|
3 |
|
$arrayReturn['shape']->setWidth($arrayDimensions['width']); |
|
1675
|
|
|
} |
|
1676
|
|
|
// Rotation |
|
1677
|
3 |
|
if (isset($shpPrimaryOptions['rotation'])) { |
|
1678
|
|
|
$rotation = $shpPrimaryOptions['rotation']; |
|
1679
|
|
|
$arrayReturn['shape']->setRotation($rotation); |
|
1680
|
|
|
} |
|
1681
|
|
|
// Shadow |
|
1682
|
3 |
|
if (isset($shpPrimaryOptions['shadowOffsetX']) && isset($shpPrimaryOptions['shadowOffsetY'])) { |
|
1683
|
2 |
|
$shadowOffsetX = $shpPrimaryOptions['shadowOffsetX']; |
|
1684
|
2 |
|
$shadowOffsetY = $shpPrimaryOptions['shadowOffsetY']; |
|
1685
|
2 |
|
if ($shadowOffsetX != 0 && $shadowOffsetX != 0) { |
|
1686
|
2 |
|
$arrayReturn['shape']->getShadow()->setVisible(true); |
|
1687
|
2 |
|
if ($shadowOffsetX > 0 && $shadowOffsetX == $shadowOffsetY) { |
|
1688
|
2 |
|
$arrayReturn['shape']->getShadow()->setDistance($shadowOffsetX)->setDirection(45); |
|
1689
|
|
|
} |
|
1690
|
|
|
} |
|
1691
|
|
|
} |
|
1692
|
|
|
// Specific Line |
|
1693
|
3 |
|
if ($arrayReturn['shape'] instanceof Line) { |
|
1694
|
1 |
|
if (isset($shpPrimaryOptions['lineColor'])) { |
|
1695
|
1 |
|
$arrayReturn['shape']->getBorder()->getColor()->setARGB('FF'.$shpPrimaryOptions['lineColor']); |
|
1696
|
|
|
} |
|
1697
|
1 |
|
if (isset($shpPrimaryOptions['lineWidth'])) { |
|
1698
|
1 |
|
$arrayReturn['shape']->setHeight($shpPrimaryOptions['lineWidth']); |
|
1699
|
|
|
} |
|
1700
|
|
|
} |
|
1701
|
|
|
// Specific RichText |
|
1702
|
3 |
|
if ($arrayReturn['shape'] instanceof RichText) { |
|
1703
|
3 |
|
if (isset($shpPrimaryOptions['insetBottom'])) { |
|
1704
|
3 |
|
$arrayReturn['shape']->setInsetBottom($shpPrimaryOptions['insetBottom']); |
|
1705
|
|
|
} |
|
1706
|
3 |
|
if (isset($shpPrimaryOptions['insetLeft'])) { |
|
1707
|
3 |
|
$arrayReturn['shape']->setInsetLeft($shpPrimaryOptions['insetLeft']); |
|
1708
|
|
|
} |
|
1709
|
3 |
|
if (isset($shpPrimaryOptions['insetRight'])) { |
|
1710
|
3 |
|
$arrayReturn['shape']->setInsetRight($shpPrimaryOptions['insetRight']); |
|
1711
|
|
|
} |
|
1712
|
3 |
|
if (isset($shpPrimaryOptions['insetTop'])) { |
|
1713
|
3 |
|
$arrayReturn['shape']->setInsetTop($shpPrimaryOptions['insetTop']); |
|
1714
|
|
|
} |
|
1715
|
|
|
} |
|
1716
|
|
|
} |
|
1717
|
|
|
} else { |
|
1718
|
|
|
// Rotation |
|
1719
|
|
|
if (isset($shpPrimaryOptions['rotation'])) { |
|
1720
|
|
|
$rotation = $shpPrimaryOptions['rotation']; |
|
1721
|
|
|
$this->oCurrentGroup->setRotation($rotation); |
|
1722
|
|
|
} |
|
1723
|
|
|
} |
|
1724
|
|
|
} |
|
1725
|
|
|
|
|
1726
|
3 |
|
return $arrayReturn; |
|
1727
|
|
|
} |
|
1728
|
|
|
|
|
1729
|
|
|
/** |
|
1730
|
|
|
* The OfficeArtSpgrContainer record specifies a container for groups of shapes. |
|
1731
|
|
|
* @param string $stream |
|
1732
|
|
|
* @param integer $pos |
|
1733
|
|
|
* @param boolean $bInGroup |
|
1734
|
|
|
* @return array |
|
1735
|
|
|
* @throws \Exception |
|
1736
|
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd910416(v=office.12).aspx |
|
1737
|
|
|
*/ |
|
1738
|
3 |
|
private function readRecordOfficeArtSpgrContainer($stream, $pos, $bInGroup = false) |
|
1739
|
|
|
{ |
|
1740
|
|
|
$arrayReturn = array( |
|
1741
|
3 |
|
'length' => 0, |
|
1742
|
|
|
); |
|
1743
|
|
|
|
|
1744
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1745
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF003) { |
|
1746
|
3 |
|
$arrayReturn['length'] += 8; |
|
1747
|
|
|
|
|
1748
|
|
|
do { |
|
1749
|
3 |
|
$rhFileBlock = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']); |
|
1750
|
3 |
|
if (!($rhFileBlock['recVer'] == 0xF && $rhFileBlock['recInstance'] == 0x0000 && ($rhFileBlock['recType'] == 0xF003 || $rhFileBlock['recType'] == 0xF004))) { |
|
1751
|
|
|
throw new \Exception('PowerPoint97 Reader : readRecordOfficeArtSpgrContainer.'); |
|
1752
|
|
|
} |
|
1753
|
|
|
|
|
1754
|
3 |
|
switch ($rhFileBlock['recType']) { |
|
1755
|
3 |
|
case 0xF003: |
|
1756
|
|
|
// Core |
|
1757
|
|
|
$this->oCurrentGroup = $this->oPhpPresentation->getActiveSlide()->createGroup(); |
|
1758
|
|
|
$this->bFirstShapeGroup = false; |
|
1759
|
|
|
// OfficeArtSpgrContainer |
|
1760
|
|
|
$fileBlock = $this->readRecordOfficeArtSpgrContainer($stream, $pos + $arrayReturn['length'], true); |
|
1761
|
|
|
$arrayReturn['length'] += $fileBlock['length']; |
|
1762
|
|
|
$data['recLen'] -= $fileBlock['length']; |
|
1763
|
|
|
break; |
|
1764
|
3 |
|
case 0xF004: |
|
1765
|
|
|
// Core |
|
1766
|
3 |
|
if (!$bInGroup) { |
|
1767
|
3 |
|
$this->oCurrentGroup = null; |
|
1768
|
|
|
} |
|
1769
|
|
|
// OfficeArtSpContainer |
|
1770
|
3 |
|
$fileBlock = $this->readRecordOfficeArtSpContainer($stream, $pos + $arrayReturn['length']); |
|
1771
|
3 |
|
$arrayReturn['length'] += $fileBlock['length']; |
|
1772
|
3 |
|
$data['recLen'] -= $fileBlock['length']; |
|
1773
|
|
|
// Core |
|
1774
|
|
|
//@todo |
|
1775
|
3 |
|
if (!is_null($fileBlock['shape'])) { |
|
1776
|
3 |
|
switch ($this->inMainType) { |
|
1777
|
3 |
|
case self::RT_NOTES: |
|
1778
|
3 |
|
$arrayIdxSlide = array_flip($this->arrayNotes); |
|
1779
|
3 |
|
if ($this->currentNote > 0 && isset($arrayIdxSlide[$this->currentNote])) { |
|
1780
|
|
|
$oSlide = $this->oPhpPresentation->getSlide($arrayIdxSlide[$this->currentNote]); |
|
1781
|
|
|
if ($oSlide->getNote()->getShapeCollection()->count() == 0) { |
|
1782
|
|
|
$oSlide->getNote()->addShape($fileBlock['shape']); |
|
1783
|
|
|
} |
|
1784
|
|
|
} |
|
1785
|
3 |
|
break; |
|
1786
|
3 |
|
case self::RT_SLIDE: |
|
1787
|
3 |
|
if ($bInGroup) { |
|
1788
|
|
|
$this->oCurrentGroup->addShape($fileBlock['shape']); |
|
1789
|
|
|
} else { |
|
1790
|
3 |
|
$this->oPhpPresentation->getActiveSlide()->addShape($fileBlock['shape']); |
|
1791
|
|
|
} |
|
1792
|
3 |
|
break; |
|
1793
|
|
|
} |
|
1794
|
|
|
} |
|
1795
|
3 |
|
break; |
|
1796
|
|
|
} |
|
1797
|
3 |
|
} while ($data['recLen'] > 0); |
|
1798
|
|
|
} |
|
1799
|
3 |
|
return $arrayReturn; |
|
1800
|
|
|
} |
|
1801
|
|
|
|
|
1802
|
|
|
/** |
|
1803
|
|
|
* The OfficeArtTertiaryFOPT record specifies a table of OfficeArtRGFOPTE records,. |
|
1804
|
|
|
* @param string $stream |
|
1805
|
|
|
* @param integer $pos |
|
1806
|
|
|
* @return array |
|
1807
|
|
|
* @throws \Exception |
|
1808
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd950206(v=office.12).aspx |
|
1809
|
|
|
*/ |
|
1810
|
3 |
|
private function readRecordOfficeArtTertiaryFOPT($stream, $pos) |
|
1811
|
|
|
{ |
|
1812
|
|
|
$arrayReturn = array( |
|
1813
|
3 |
|
'length' => 0, |
|
1814
|
|
|
); |
|
1815
|
|
|
|
|
1816
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1817
|
3 |
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF122) { |
|
1818
|
|
|
// Record Header |
|
1819
|
|
|
$arrayReturn['length'] += 8; |
|
1820
|
|
|
|
|
1821
|
|
|
$officeArtFOPTE = array(); |
|
1822
|
|
|
for ($inc = 0; $inc < $data['recInstance']; $inc++) { |
|
1823
|
|
|
$opid = self::getInt2d($this->streamPowerpointDocument, $pos + $arrayReturn['length']); |
|
1824
|
|
|
$arrayReturn['length'] += 2; |
|
1825
|
|
|
$optOp = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']); |
|
1826
|
|
|
$arrayReturn['length'] += 4; |
|
1827
|
|
|
$officeArtFOPTE[] = array( |
|
1828
|
|
|
'opid' => ($opid >> 0) & bindec('11111111111111'), |
|
1829
|
|
|
'fBid' => ($opid >> 14) & bindec('1'), |
|
1830
|
|
|
'fComplex' => ($opid >> 15) & bindec('1'), |
|
1831
|
|
|
'op' => $optOp, |
|
1832
|
|
|
); |
|
1833
|
|
|
} |
|
1834
|
|
|
//@link : http://code.metager.de/source/xref/kde/calligra/filters/libmso/OPID |
|
1835
|
|
|
foreach ($officeArtFOPTE as $opt) { |
|
1836
|
|
|
switch ($opt['opid']) { |
|
1837
|
|
|
case 0x039F: |
|
1838
|
|
|
// Table properties |
|
1839
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd922773(v=office.12).aspx |
|
1840
|
|
|
break; |
|
1841
|
|
|
case 0x03A0: |
|
1842
|
|
|
// Table Row Properties |
|
1843
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd923419(v=office.12).aspx |
|
1844
|
|
|
if ($opt['fComplex'] == 0x1) { |
|
1845
|
|
|
$arrayReturn['length'] += $opt['op']; |
|
1846
|
|
|
} |
|
1847
|
|
|
break; |
|
1848
|
|
|
case 0x03A9: |
|
1849
|
|
|
// GroupShape : metroBlob |
|
1850
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd943388(v=office.12).aspx |
|
1851
|
|
|
if ($opt['fComplex'] == 0x1) { |
|
1852
|
|
|
$arrayReturn['length'] += $opt['op']; |
|
1853
|
|
|
} |
|
1854
|
|
|
break; |
|
1855
|
|
|
case 0x01FF: |
|
1856
|
|
|
// Line Style Boolean |
|
1857
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd951605(v=office.12).aspx |
|
1858
|
|
|
break; |
|
1859
|
|
|
default: |
|
1860
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($opt['opid']).')'); |
|
1861
|
|
|
} |
|
1862
|
|
|
} |
|
1863
|
|
|
} |
|
1864
|
3 |
|
return $arrayReturn; |
|
1865
|
|
|
} |
|
1866
|
|
|
|
|
1867
|
|
|
/** |
|
1868
|
|
|
* The OfficeArtDgContainer record specifies the container for all the file records for the objects in a drawing. |
|
1869
|
|
|
* @param string $stream |
|
1870
|
|
|
* @param integer $pos |
|
1871
|
|
|
* @return array |
|
1872
|
|
|
* @throws \Exception |
|
1873
|
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd924455(v=office.12).aspx |
|
1874
|
|
|
*/ |
|
1875
|
3 |
|
private function readRecordOfficeArtDgContainer($stream, $pos) |
|
1876
|
|
|
{ |
|
1877
|
|
|
$arrayReturn = array( |
|
1878
|
3 |
|
'length' => 0, |
|
1879
|
|
|
); |
|
1880
|
|
|
|
|
1881
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1882
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF002) { |
|
1883
|
|
|
// Record Header |
|
1884
|
3 |
|
$arrayReturn['length'] += 8; |
|
1885
|
|
|
// drawingData |
|
1886
|
3 |
|
$drawingData = $this->readRecordOfficeArtFDG($stream, $pos + $arrayReturn['length']); |
|
1887
|
3 |
|
$arrayReturn['length'] += $drawingData['length']; |
|
1888
|
|
|
// regroupItems |
|
1889
|
|
|
//@todo |
|
1890
|
|
|
// groupShape |
|
1891
|
3 |
|
$groupShape = $this->readRecordOfficeArtSpgrContainer($stream, $pos + $arrayReturn['length']); |
|
1892
|
3 |
|
$arrayReturn['length'] += $groupShape['length']; |
|
1893
|
|
|
// shape |
|
1894
|
3 |
|
$shape = $this->readRecordOfficeArtSpContainer($stream, $pos + $arrayReturn['length']); |
|
1895
|
3 |
|
$arrayReturn['length'] += $shape['length']; |
|
1896
|
|
|
// solvers1 |
|
1897
|
|
|
//@todo |
|
1898
|
|
|
// deletedShapes |
|
1899
|
|
|
//@todo |
|
1900
|
|
|
// solvers1 |
|
1901
|
|
|
//@todo |
|
1902
|
|
|
} |
|
1903
|
|
|
|
|
1904
|
3 |
|
return $arrayReturn; |
|
1905
|
|
|
} |
|
1906
|
|
|
|
|
1907
|
|
|
/** |
|
1908
|
|
|
* The OfficeArtFDG record specifies the number of shapes, the drawing identifier, and the shape identifier of the last shape in a drawing. |
|
1909
|
|
|
* @param string $stream |
|
1910
|
|
|
* @param integer $pos |
|
1911
|
|
|
* @return array |
|
1912
|
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd946757(v=office.12).aspx |
|
1913
|
|
|
*/ |
|
1914
|
3 |
|
private function readRecordOfficeArtFDG($stream, $pos) |
|
1915
|
|
|
{ |
|
1916
|
|
|
$arrayReturn = array( |
|
1917
|
3 |
|
'length' => 0, |
|
1918
|
|
|
); |
|
1919
|
|
|
|
|
1920
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1921
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] <= 0xFFE && $data['recType'] == 0xF008 && $data['recLen'] == 0x00000008) { |
|
1922
|
|
|
// Record Header |
|
1923
|
3 |
|
$arrayReturn['length'] += 8; |
|
1924
|
|
|
// Length |
|
1925
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
1926
|
|
|
} |
|
1927
|
|
|
|
|
1928
|
3 |
|
return $arrayReturn; |
|
1929
|
|
|
} |
|
1930
|
|
|
|
|
1931
|
|
|
/** |
|
1932
|
|
|
* The OfficeArtFOPT record specifies a table of OfficeArtRGFOPTE records. |
|
1933
|
|
|
* @param string $stream |
|
1934
|
|
|
* @param integer $pos |
|
1935
|
|
|
* @return array |
|
1936
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943404(v=office.12).aspx |
|
1937
|
|
|
*/ |
|
1938
|
3 |
|
private function readRecordOfficeArtFOPT($stream, $pos) |
|
1939
|
|
|
{ |
|
1940
|
|
|
$arrayReturn = array( |
|
1941
|
3 |
|
'length' => 0, |
|
1942
|
|
|
); |
|
1943
|
|
|
|
|
1944
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
1945
|
3 |
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF00B) { |
|
1946
|
|
|
// Record Header |
|
1947
|
3 |
|
$arrayReturn['length'] += 8; |
|
1948
|
|
|
|
|
1949
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd906086(v=office.12).aspx |
|
1950
|
3 |
|
$officeArtFOPTE = array(); |
|
1951
|
3 |
|
for ($inc = 0; $inc < $data['recInstance']; $inc++) { |
|
1952
|
3 |
|
$opid = self::getInt2d($this->streamPowerpointDocument, $pos + $arrayReturn['length']); |
|
1953
|
3 |
|
$arrayReturn['length'] += 2; |
|
1954
|
3 |
|
$data['recLen'] -= 2; |
|
1955
|
3 |
|
$optOp = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']); |
|
1956
|
3 |
|
$arrayReturn['length'] += 4; |
|
1957
|
3 |
|
$data['recLen'] -= 4; |
|
1958
|
3 |
|
$officeArtFOPTE[] = array( |
|
1959
|
3 |
|
'opid' => ($opid >> 0) & bindec('11111111111111'), |
|
1960
|
3 |
|
'fBid' => ($opid >> 14) & bindec('1'), |
|
1961
|
3 |
|
'fComplex' => ($opid >> 15) & bindec('1'), |
|
1962
|
3 |
|
'op' => $optOp, |
|
1963
|
|
|
); |
|
1964
|
|
|
} |
|
1965
|
|
|
//@link : http://code.metager.de/source/xref/kde/calligra/filters/libmso/OPID |
|
1966
|
3 |
|
foreach ($officeArtFOPTE as $opt) { |
|
1967
|
|
|
// echo $opt['opid'].'-0x'.dechex($opt['opid']).EOL; |
|
1968
|
3 |
|
switch ($opt['opid']) { |
|
1969
|
3 |
|
case 0x0004: |
|
1970
|
|
|
// Transform : rotation |
|
1971
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd949750(v=office.12).aspx |
|
1972
|
|
|
$arrayReturn['rotation'] = $opt['op']; |
|
1973
|
|
|
break; |
|
1974
|
3 |
|
case 0x007F: |
|
1975
|
|
|
// Transform : Protection Boolean Properties |
|
1976
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909131(v=office.12).aspx |
|
1977
|
3 |
|
break; |
|
1978
|
3 |
|
case 0x0080: |
|
1979
|
|
|
// Text : ltxid |
|
1980
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947446(v=office.12).aspx |
|
1981
|
3 |
|
break; |
|
1982
|
3 |
|
case 0x0081: |
|
1983
|
|
|
// Text : dxTextLeft |
|
1984
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd953234(v=office.12).aspx |
|
1985
|
3 |
|
$arrayReturn['insetLeft'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
1986
|
3 |
|
break; |
|
1987
|
3 |
|
case 0x0082: |
|
1988
|
|
|
// Text : dyTextTop |
|
1989
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd925068(v=office.12).aspx |
|
1990
|
3 |
|
$arrayReturn['insetTop'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
1991
|
3 |
|
break; |
|
1992
|
3 |
|
case 0x0083: |
|
1993
|
|
|
// Text : dxTextRight |
|
1994
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd906782(v=office.12).aspx |
|
1995
|
3 |
|
$arrayReturn['insetRight'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
1996
|
3 |
|
break; |
|
1997
|
3 |
|
case 0x0084: |
|
1998
|
|
|
// Text : dyTextBottom |
|
1999
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd772858(v=office.12).aspx |
|
2000
|
3 |
|
$arrayReturn['insetBottom'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
2001
|
3 |
|
break; |
|
2002
|
3 |
|
case 0x0085: |
|
2003
|
|
|
// Text : WrapText |
|
2004
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd924770(v=office.12).aspx |
|
2005
|
3 |
|
break; |
|
2006
|
3 |
|
case 0x0087: |
|
2007
|
|
|
// Text : anchorText |
|
2008
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948575(v=office.12).aspx |
|
2009
|
3 |
|
break; |
|
2010
|
3 |
|
case 0x00BF: |
|
2011
|
|
|
// Text : Text Boolean Properties |
|
2012
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950905(v=office.12).aspx |
|
2013
|
3 |
|
break; |
|
2014
|
3 |
|
case 0x0104: |
|
2015
|
|
|
// Blip : pib |
|
2016
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd772837(v=office.12).aspx |
|
2017
|
3 |
|
if ($opt['fComplex'] == 0) { |
|
2018
|
3 |
|
$arrayReturn['pib'] = $opt['op']; |
|
2019
|
3 |
|
$data['recLen'] -= $opt['op']; |
|
2020
|
|
|
} else { |
|
2021
|
|
|
// pib Complex |
|
2022
|
|
|
} |
|
2023
|
3 |
|
break; |
|
2024
|
3 |
|
case 0x0105: |
|
2025
|
|
|
// Blip : pibName - specifies the comment, file name, or URL, as specified by the pibFlags property, for this BLIP. |
|
2026
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd945885(v=office.12).aspx |
|
2027
|
|
|
break; |
|
2028
|
3 |
|
case 0x013F: |
|
2029
|
|
|
// Blip Boolean Properties |
|
2030
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd944215(v=office.12).aspx |
|
2031
|
|
|
break; |
|
2032
|
3 |
|
case 0x0140: |
|
2033
|
|
|
// Geometry : geoLeft |
|
2034
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947489(v=office.12).aspx |
|
2035
|
|
|
// print_r('geoLeft : '.$opt['op'].EOL); |
|
2036
|
2 |
|
break; |
|
2037
|
3 |
|
case 0x0141: |
|
2038
|
|
|
// Geometry : geoTop |
|
2039
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949459(v=office.12).aspx |
|
2040
|
|
|
// print_r('geoTop : '.$opt['op'].EOL); |
|
2041
|
2 |
|
break; |
|
2042
|
3 |
|
case 0x0142: |
|
2043
|
|
|
// Geometry : geoRight |
|
2044
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947117(v=office.12).aspx |
|
2045
|
|
|
// print_r('geoRight : '.$opt['op'].EOL); |
|
2046
|
2 |
|
break; |
|
2047
|
3 |
|
case 0x0143: |
|
2048
|
|
|
// Geometry : geoBottom |
|
2049
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd948602(v=office.12).aspx |
|
2050
|
|
|
// print_r('geoBottom : '.$opt['op'].EOL); |
|
2051
|
2 |
|
break; |
|
2052
|
3 |
|
case 0x0144: |
|
2053
|
|
|
// Geometry : shapePath |
|
2054
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd945249(v=office.12).aspx |
|
2055
|
1 |
|
$arrayReturn['line'] = true; |
|
2056
|
1 |
|
break; |
|
2057
|
3 |
|
case 0x0145: |
|
2058
|
|
|
// Geometry : pVertices |
|
2059
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949814(v=office.12).aspx |
|
2060
|
2 |
|
if ($opt['fComplex'] == 1) { |
|
2061
|
2 |
|
$arrayReturn['length'] += $opt['op']; |
|
2062
|
2 |
|
$data['recLen'] -= $opt['op']; |
|
2063
|
|
|
} |
|
2064
|
2 |
|
break; |
|
2065
|
3 |
|
case 0x0146: |
|
2066
|
|
|
// Geometry : pSegmentInfo |
|
2067
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd905742(v=office.12).aspx |
|
2068
|
2 |
|
if ($opt['fComplex'] == 1) { |
|
2069
|
2 |
|
$arrayReturn['length'] += $opt['op']; |
|
2070
|
2 |
|
$data['recLen'] -= $opt['op']; |
|
2071
|
|
|
} |
|
2072
|
2 |
|
break; |
|
2073
|
3 |
|
case 0x0155: |
|
2074
|
|
|
// Geometry : pAdjustHandles |
|
2075
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd905890(v=office.12).aspx |
|
2076
|
2 |
|
if ($opt['fComplex'] == 1) { |
|
2077
|
2 |
|
$arrayReturn['length'] += $opt['op']; |
|
2078
|
2 |
|
$data['recLen'] -= $opt['op']; |
|
2079
|
|
|
} |
|
2080
|
2 |
|
break; |
|
2081
|
3 |
|
case 0x0156: |
|
2082
|
|
|
// Geometry : pGuides |
|
2083
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd910801(v=office.12).aspx |
|
2084
|
2 |
|
if ($opt['fComplex'] == 1) { |
|
2085
|
2 |
|
$arrayReturn['length'] += $opt['op']; |
|
2086
|
2 |
|
$data['recLen'] -= $opt['op']; |
|
2087
|
|
|
} |
|
2088
|
2 |
|
break; |
|
2089
|
3 |
|
case 0x0157: |
|
2090
|
|
|
// Geometry : pInscribe |
|
2091
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd904889(v=office.12).aspx |
|
2092
|
2 |
|
if ($opt['fComplex'] == 1) { |
|
2093
|
2 |
|
$arrayReturn['length'] += $opt['op']; |
|
2094
|
2 |
|
$data['recLen'] -= $opt['op']; |
|
2095
|
|
|
} |
|
2096
|
2 |
|
break; |
|
2097
|
3 |
|
case 0x017F: |
|
2098
|
|
|
// Geometry Boolean Properties |
|
2099
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd944968(v=office.12).aspx |
|
2100
|
1 |
|
break; |
|
2101
|
3 |
|
case 0x0180: |
|
2102
|
|
|
// Fill : fillType |
|
2103
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947909(v=office.12).aspx |
|
2104
|
3 |
|
break; |
|
2105
|
3 |
|
case 0x0181: |
|
2106
|
|
|
// Fill : fillColor |
|
2107
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd921332(v=office.12).aspx |
|
2108
|
3 |
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2109
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2110
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2111
|
|
|
// echo 'fillColor : '.$strColor.EOL; |
|
2112
|
3 |
|
break; |
|
2113
|
3 |
|
case 0x0183: |
|
2114
|
|
|
// Fill : fillBackColor |
|
2115
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950634(v=office.12).aspx |
|
2116
|
3 |
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2117
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2118
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2119
|
|
|
// echo 'fillBackColor : '.$strColor.EOL; |
|
2120
|
3 |
|
break; |
|
2121
|
3 |
|
case 0x0193: |
|
2122
|
|
|
// Fill : fillRectRight |
|
2123
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951294(v=office.12).aspx |
|
2124
|
|
|
// echo 'fillRectRight : '.\PhpOffice\Common\Drawing::emuToPixels($opt['op']).EOL; |
|
2125
|
3 |
|
break; |
|
2126
|
3 |
|
case 0x0194: |
|
2127
|
|
|
// Fill : fillRectBottom |
|
2128
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd910194(v=office.12).aspx |
|
2129
|
|
|
// echo 'fillRectBottom : '.\PhpOffice\Common\Drawing::emuToPixels($opt['op']).EOL; |
|
2130
|
3 |
|
break; |
|
2131
|
3 |
|
case 0x01BF: |
|
2132
|
|
|
// Fill : Fill Style Boolean Properties |
|
2133
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909380(v=office.12).aspx |
|
2134
|
3 |
|
break; |
|
2135
|
3 |
|
case 0x01C0: |
|
2136
|
|
|
// Line Style : lineColor |
|
2137
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd920397(v=office.12).aspx |
|
2138
|
3 |
|
$strColor = str_pad(dechex(($opt['op'] >> 0) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2139
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 8) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2140
|
3 |
|
$strColor .= str_pad(dechex(($opt['op'] >> 16) & bindec('11111111')), 2, STR_PAD_LEFT, '0'); |
|
2141
|
3 |
|
$arrayReturn['lineColor'] = $strColor; |
|
2142
|
3 |
|
break; |
|
2143
|
3 |
|
case 0x01C1: |
|
2144
|
|
|
// Line Style : lineOpacity |
|
2145
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd923433(v=office.12).aspx |
|
2146
|
|
|
// echo 'lineOpacity : '.dechex($opt['op']).EOL; |
|
2147
|
3 |
|
break; |
|
2148
|
3 |
|
case 0x01C2: |
|
2149
|
|
|
// Line Style : lineBackColor |
|
2150
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947669(v=office.12).aspx |
|
2151
|
3 |
|
break; |
|
2152
|
3 |
|
case 0x01CB: |
|
2153
|
|
|
// Line Style : lineWidth |
|
2154
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd926964(v=office.12).aspx |
|
2155
|
1 |
|
$arrayReturn['lineWidth'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
2156
|
1 |
|
break; |
|
2157
|
3 |
|
case 0x01D6: |
|
2158
|
|
|
// Line Style : lineJoinStyle |
|
2159
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd909643(v=office.12).aspx |
|
2160
|
3 |
|
break; |
|
2161
|
3 |
|
case 0x01D7: |
|
2162
|
|
|
// Line Style : lineEndCapStyle |
|
2163
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd925071(v=office.12).aspx |
|
2164
|
3 |
|
break; |
|
2165
|
3 |
|
case 0x01FF: |
|
2166
|
|
|
// Line Style : Line Style Boolean Properties |
|
2167
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951605(v=office.12).aspx |
|
2168
|
3 |
|
break; |
|
2169
|
3 |
|
case 0x0201: |
|
2170
|
|
|
// Shadow Style : shadowColor |
|
2171
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd923454(v=office.12).aspx |
|
2172
|
3 |
|
break; |
|
2173
|
3 |
|
case 0x0204: |
|
2174
|
|
|
// Shadow Style : shadowOpacity |
|
2175
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd920720(v=office.12).aspx |
|
2176
|
2 |
|
break; |
|
2177
|
3 |
|
case 0x0205: |
|
2178
|
|
|
// Shadow Style : shadowOffsetX |
|
2179
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd945280(v=office.12).aspx |
|
2180
|
2 |
|
$arrayReturn['shadowOffsetX'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
2181
|
2 |
|
break; |
|
2182
|
3 |
|
case 0x0206: |
|
2183
|
|
|
// Shadow Style : shadowOffsetY |
|
2184
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd907855(v=office.12).aspx |
|
2185
|
2 |
|
$arrayReturn['shadowOffsetY'] = \PhpOffice\Common\Drawing::emuToPixels($opt['op']); |
|
2186
|
2 |
|
break; |
|
2187
|
3 |
|
case 0x0210: |
|
2188
|
|
|
// Shadow Style : shadowOriginX |
|
2189
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd921662(v=office.12).aspx |
|
2190
|
|
|
break; |
|
2191
|
3 |
|
case 0x0211: |
|
2192
|
|
|
// Shadow Style : shadowOriginY |
|
2193
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd945853(v=office.12).aspx |
|
2194
|
|
|
break; |
|
2195
|
3 |
|
case 0x023F: |
|
2196
|
|
|
// Shadow Style : Shadow Style Boolean Properties |
|
2197
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947887(v=office.12).aspx |
|
2198
|
3 |
|
break; |
|
2199
|
3 |
|
case 0x0304: |
|
2200
|
|
|
// Shape : bWMode |
|
2201
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd947659(v=office.12).aspx |
|
2202
|
3 |
|
break; |
|
2203
|
3 |
|
case 0x033F: |
|
2204
|
|
|
// Shape Boolean Properties |
|
2205
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd951345(v=office.12).aspx |
|
2206
|
3 |
|
break; |
|
2207
|
|
|
case 0x0380: |
|
2208
|
|
|
// Group Shape Property Set : wzName |
|
2209
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd950681(v=office.12).aspx |
|
2210
|
|
|
if ($opt['fComplex'] == 1) { |
|
2211
|
|
|
$arrayReturn['length'] += $opt['op']; |
|
2212
|
|
|
$data['recLen'] -= $opt['op']; |
|
2213
|
|
|
} |
|
2214
|
|
|
break; |
|
2215
|
|
|
case 0x0381: |
|
2216
|
|
|
// Group Shape Property Set : wzDescription |
|
2217
|
|
|
//@link : https://msdn.microsoft.com/en-us/library/dd945733(v=office.12).aspx |
|
2218
|
|
|
if ($opt['fComplex'] == 1) { |
|
2219
|
|
|
$arrayReturn['length'] += $opt['op']; |
|
2220
|
|
|
$data['recLen'] -= $opt['op']; |
|
2221
|
|
|
} |
|
2222
|
|
|
break; |
|
2223
|
|
|
case 0x03BF: |
|
2224
|
|
|
// Group Shape Property Set : Group Shape Boolean Properties |
|
2225
|
|
|
//@link : http://msdn.microsoft.com/en-us/library/dd949807(v=office.12).aspx |
|
2226
|
|
|
break; |
|
2227
|
|
|
default: |
|
2228
|
3 |
|
throw new \Exception('Feature not implemented (l.' . __LINE__ . ' : 0x' . dechex($opt['opid']) . ')'); |
|
2229
|
|
|
} |
|
2230
|
|
|
} |
|
2231
|
3 |
|
if ($data['recLen'] > 0) { |
|
2232
|
2 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2233
|
|
|
} |
|
2234
|
|
|
} |
|
2235
|
|
|
|
|
2236
|
3 |
|
return $arrayReturn; |
|
2237
|
|
|
} |
|
2238
|
|
|
|
|
2239
|
|
|
/** |
|
2240
|
|
|
* The OfficeArtFPSPL record specifies the former hierarchical position of the containing object that is either a shape or a group of shapes. |
|
2241
|
|
|
* @param string $stream |
|
2242
|
|
|
* @param integer $pos |
|
2243
|
|
|
* @return array |
|
2244
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd947479(v=office.12).aspx |
|
2245
|
|
|
*/ |
|
2246
|
|
|
private function readRecordOfficeArtFPSPL($stream, $pos) |
|
2247
|
|
|
{ |
|
2248
|
|
|
$arrayReturn = array( |
|
2249
|
|
|
'length' => 0, |
|
2250
|
|
|
); |
|
2251
|
|
|
|
|
2252
|
|
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2253
|
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF11D && $data['recLen'] == 0x00000004) { |
|
2254
|
|
|
$arrayReturn['length'] += 8; |
|
2255
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2256
|
|
|
} |
|
2257
|
|
|
|
|
2258
|
|
|
return $arrayReturn; |
|
2259
|
|
|
} |
|
2260
|
|
|
|
|
2261
|
|
|
/** |
|
2262
|
|
|
* The OfficeArtFSP record specifies an instance of a shape. |
|
2263
|
|
|
* @param string $stream |
|
2264
|
|
|
* @param integer $pos |
|
2265
|
|
|
* @return array |
|
2266
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925898(v=office.12).aspx |
|
2267
|
|
|
*/ |
|
2268
|
3 |
|
private function readRecordOfficeArtFSP($stream, $pos) |
|
2269
|
|
|
{ |
|
2270
|
|
|
$arrayReturn = array( |
|
2271
|
3 |
|
'length' => 0, |
|
2272
|
|
|
); |
|
2273
|
|
|
|
|
2274
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2275
|
3 |
|
if ($data['recVer'] == 0x2 && $data['recType'] == 0xF00A && $data['recLen'] == 0x00000008) { |
|
2276
|
3 |
|
$arrayReturn['length'] += 8; |
|
2277
|
|
|
// spid |
|
2278
|
3 |
|
$arrayReturn['length'] += 4; |
|
2279
|
|
|
// data |
|
2280
|
3 |
|
$data = self::getInt4d($this->streamPowerpointDocument, $pos + $arrayReturn['length']); |
|
2281
|
3 |
|
$arrayReturn['length'] += 4; |
|
2282
|
3 |
|
$arrayReturn['fGroup'] = ($data >> 0) & bindec('1'); |
|
2283
|
3 |
|
$arrayReturn['fChild'] = ($data >> 1) & bindec('1'); |
|
2284
|
3 |
|
$arrayReturn['fPatriarch'] = ($data >> 2) & bindec('1'); |
|
2285
|
3 |
|
$arrayReturn['fDeleted'] = ($data >> 3) & bindec('1'); |
|
2286
|
|
|
} |
|
2287
|
|
|
|
|
2288
|
3 |
|
return $arrayReturn; |
|
2289
|
|
|
} |
|
2290
|
|
|
|
|
2291
|
|
|
/** |
|
2292
|
|
|
* The OfficeArtFSPGR record specifies the coordinate system of the group shape that the anchors of the child shape are expressed in. |
|
2293
|
|
|
* @param string $stream |
|
2294
|
|
|
* @param integer $pos |
|
2295
|
|
|
* @return array |
|
2296
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925381(v=office.12).aspx |
|
2297
|
|
|
*/ |
|
2298
|
3 |
|
private function readRecordOfficeArtFSPGR($stream, $pos) |
|
2299
|
|
|
{ |
|
2300
|
|
|
$arrayReturn = array( |
|
2301
|
3 |
|
'length' => 0, |
|
2302
|
|
|
); |
|
2303
|
|
|
|
|
2304
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2305
|
3 |
|
if ($data['recVer'] == 0x1 && $data['recInstance'] == 0x000 && $data['recType'] == 0xF009 && $data['recLen'] == 0x00000010) { |
|
2306
|
3 |
|
$arrayReturn['length'] += 8; |
|
2307
|
|
|
//$arrShapeGroup['xLeft'] = self::getInt4d($this->streamPowerpointDocument, $pos); |
|
2308
|
3 |
|
$arrayReturn['length'] += 4; |
|
2309
|
|
|
//$arrShapeGroup['yTop'] = self::getInt4d($this->streamPowerpointDocument, $pos); |
|
2310
|
3 |
|
$arrayReturn['length'] += 4; |
|
2311
|
|
|
//$arrShapeGroup['xRight'] = self::getInt4d($this->streamPowerpointDocument, $pos); |
|
2312
|
3 |
|
$arrayReturn['length'] += 4; |
|
2313
|
|
|
//$arrShapeGroup['yBottom'] = self::getInt4d($this->streamPowerpointDocument, $pos); |
|
2314
|
3 |
|
$arrayReturn['length'] += 4; |
|
2315
|
|
|
} |
|
2316
|
|
|
|
|
2317
|
3 |
|
return $arrayReturn; |
|
2318
|
|
|
} |
|
2319
|
|
|
|
|
2320
|
|
|
/** |
|
2321
|
|
|
* The OfficeArtSecondaryFOPT record specifies a table of OfficeArtRGFOPTE records. |
|
2322
|
|
|
* @param string $stream |
|
2323
|
|
|
* @param integer $pos |
|
2324
|
|
|
* @return array |
|
2325
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd950259(v=office.12).aspx |
|
2326
|
|
|
*/ |
|
2327
|
3 |
|
private function readRecordOfficeArtSecondaryFOPT($stream, $pos) |
|
2328
|
|
|
{ |
|
2329
|
|
|
$arrayReturn = array( |
|
2330
|
3 |
|
'length' => 0, |
|
2331
|
|
|
); |
|
2332
|
|
|
|
|
2333
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2334
|
3 |
|
if ($data['recVer'] == 0x3 && $data['recType'] == 0xF121) { |
|
2335
|
|
|
// Record Header |
|
2336
|
|
|
$arrayReturn['length'] += 8; |
|
2337
|
|
|
// Length |
|
2338
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2339
|
|
|
} |
|
2340
|
3 |
|
return $arrayReturn; |
|
2341
|
|
|
} |
|
2342
|
|
|
|
|
2343
|
|
|
/** |
|
2344
|
|
|
* A container record that specifies information about a shape. |
|
2345
|
|
|
* @param string $stream |
|
2346
|
|
|
* @param integer $pos |
|
2347
|
|
|
* @return array |
|
2348
|
|
|
* @throws \Exception |
|
2349
|
|
|
* @link : https://msdn.microsoft.com/en-us/library/dd950927(v=office.12).aspx |
|
2350
|
|
|
*/ |
|
2351
|
3 |
|
private function readRecordOfficeArtClientData($stream, $pos) |
|
2352
|
|
|
{ |
|
2353
|
|
|
$arrayReturn = array( |
|
2354
|
3 |
|
'length' => 0, |
|
2355
|
|
|
); |
|
2356
|
|
|
|
|
2357
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2358
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == 0xF011) { |
|
2359
|
3 |
|
$arrayReturn['length'] += 8; |
|
2360
|
|
|
// shapeFlagsAtom (9 bytes) |
|
2361
|
3 |
|
$dataShapeFlagsAtom = $this->readRecordShapeFlagsAtom($stream, $pos + $arrayReturn['length']); |
|
2362
|
3 |
|
$arrayReturn['length'] += $dataShapeFlagsAtom['length']; |
|
2363
|
|
|
|
|
2364
|
|
|
// shapeFlags10Atom (9 bytes) |
|
2365
|
3 |
|
$dataShapeFlags10Atom = $this->readRecordShapeFlags10Atom($stream, $pos + $arrayReturn['length']); |
|
2366
|
3 |
|
$arrayReturn['length'] += $dataShapeFlags10Atom['length']; |
|
2367
|
|
|
|
|
2368
|
|
|
// exObjRefAtom (12 bytes) |
|
2369
|
3 |
|
$dataExObjRefAtom = $this->readRecordExObjRefAtom($stream, $pos + $arrayReturn['length']); |
|
2370
|
3 |
|
$arrayReturn['length'] += $dataExObjRefAtom['length']; |
|
2371
|
|
|
|
|
2372
|
|
|
// animationInfo (variable) |
|
2373
|
3 |
|
$dataAnimationInfo = $this->readRecordAnimationInfoContainer($stream, $pos + $arrayReturn['length']); |
|
2374
|
3 |
|
$arrayReturn['length'] += $dataAnimationInfo['length']; |
|
2375
|
|
|
|
|
2376
|
|
|
// mouseClickInteractiveInfo (variable) |
|
2377
|
3 |
|
$mouseClickInfo = $this->readRecordMouseClickInteractiveInfoContainer($stream, $pos + $arrayReturn['length']); |
|
2378
|
3 |
|
$arrayReturn['length'] += $mouseClickInfo['length']; |
|
2379
|
|
|
|
|
2380
|
|
|
// mouseOverInteractiveInfo (variable) |
|
2381
|
3 |
|
$mouseOverInfo = $this->readRecordMouseOverInteractiveInfoContainer($stream, $pos + $arrayReturn['length']); |
|
2382
|
3 |
|
$arrayReturn['length'] += $mouseOverInfo['length']; |
|
2383
|
|
|
|
|
2384
|
|
|
// placeholderAtom (16 bytes) |
|
2385
|
3 |
|
$dataPlaceholderAtom = $this->readRecordPlaceholderAtom($stream, $pos + $arrayReturn['length']); |
|
2386
|
3 |
|
$arrayReturn['length'] += $dataPlaceholderAtom['length']; |
|
2387
|
|
|
|
|
2388
|
|
|
// recolorInfoAtom (variable) |
|
2389
|
3 |
|
$dataRecolorInfo = $this->readRecordRecolorInfoAtom($stream, $pos + $arrayReturn['length']); |
|
2390
|
3 |
|
$arrayReturn['length'] += $dataRecolorInfo['length']; |
|
2391
|
|
|
|
|
2392
|
|
|
// rgShapeClientRoundtripData (variable) |
|
2393
|
|
|
$array = array( |
|
2394
|
3 |
|
self::RT_PROGTAGS, |
|
2395
|
3 |
|
self::RT_ROUNDTRIPNEWPLACEHOLDERID12ATOM, |
|
2396
|
3 |
|
self::RT_ROUNDTRIPSHAPEID12ATOM, |
|
2397
|
3 |
|
self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM, |
|
2398
|
3 |
|
self::RT_ROUNDTRIPSHAPECHECKSUMFORCL12ATOM, |
|
2399
|
|
|
); |
|
2400
|
|
|
do { |
|
2401
|
3 |
|
$dataHeaderRG = $this->loadRecordHeader($stream, $pos + $arrayReturn['length']); |
|
2402
|
3 |
|
if (in_array($dataHeaderRG['recType'], $array)) { |
|
2403
|
|
|
switch ($dataHeaderRG['recType']) { |
|
2404
|
|
|
case self::RT_PROGTAGS: |
|
2405
|
|
|
$dataRG = $this->readRecordShapeProgTagsContainer($stream, $pos + $arrayReturn['length']); |
|
2406
|
|
|
$arrayReturn['length'] += $dataRG['length']; |
|
2407
|
|
|
break; |
|
2408
|
|
|
case self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM: |
|
2409
|
|
|
$dataRG = $this->readRecordRoundTripHFPlaceholder12Atom($stream, $pos + $arrayReturn['length']); |
|
2410
|
|
|
$arrayReturn['length'] += $dataRG['length']; |
|
2411
|
|
|
break; |
|
2412
|
|
|
case self::RT_ROUNDTRIPSHAPEID12ATOM: |
|
2413
|
|
|
$dataRG = $this->readRecordRoundTripShapeId12Atom($stream, $pos + $arrayReturn['length']); |
|
2414
|
|
|
$arrayReturn['length'] += $dataRG['length']; |
|
2415
|
|
|
break; |
|
2416
|
|
|
default: |
|
2417
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.' : 0x'.dechex($dataHeaderRG['recType']).')'); |
|
2418
|
|
|
} |
|
2419
|
|
|
} |
|
2420
|
3 |
|
} while (in_array($dataHeaderRG['recType'], $array)); |
|
2421
|
|
|
} |
|
2422
|
|
|
|
|
2423
|
3 |
|
return $arrayReturn; |
|
2424
|
|
|
} |
|
2425
|
|
|
|
|
2426
|
|
|
/** |
|
2427
|
|
|
* An atom record that specifies a persist object directory. Each persist object identifier specified MUST be unique in that persist object directory. |
|
2428
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd952680(v=office.12).aspx |
|
2429
|
|
|
* @param string $stream |
|
2430
|
|
|
* @param integer $pos |
|
2431
|
|
|
* @throws \Exception |
|
2432
|
|
|
*/ |
|
2433
|
3 |
|
private function readRecordPersistDirectoryAtom($stream, $pos) |
|
2434
|
|
|
{ |
|
2435
|
3 |
|
$rHeader = $this->loadRecordHeader($stream, $pos); |
|
2436
|
3 |
|
$pos += 8; |
|
2437
|
3 |
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_PERSISTDIRECTORYATOM) { |
|
2438
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : PersistDirectoryAtom > RecordHeader).'); |
|
2439
|
|
|
} |
|
2440
|
|
|
// rgPersistDirEntry |
|
2441
|
|
|
// @link : http://msdn.microsoft.com/en-us/library/dd947347(v=office.12).aspx |
|
2442
|
|
|
do { |
|
2443
|
3 |
|
$data = self::getInt4d($stream, $pos); |
|
2444
|
3 |
|
$pos += 4; |
|
2445
|
3 |
|
$rHeader['recLen'] -= 4; |
|
2446
|
|
|
//$persistId = ($data >> 0) & bindec('11111111111111111111'); |
|
2447
|
3 |
|
$cPersist = ($data >> 20) & bindec('111111111111'); |
|
2448
|
|
|
|
|
2449
|
3 |
|
$rgPersistOffset = array(); |
|
2450
|
3 |
|
for ($inc = 0; $inc < $cPersist; $inc++) { |
|
2451
|
3 |
|
$rgPersistOffset[] = self::getInt4d($stream, $pos); |
|
2452
|
3 |
|
$pos += 4; |
|
2453
|
3 |
|
$rHeader['recLen'] -= 4; |
|
2454
|
|
|
} |
|
2455
|
3 |
|
} while ($rHeader['recLen'] > 0); |
|
2456
|
3 |
|
$this->rgPersistDirEntry = $rgPersistOffset; |
|
2457
|
3 |
|
} |
|
2458
|
|
|
|
|
2459
|
|
|
/** |
|
2460
|
|
|
* A container record that specifies information about the headers (1) and footers within a slide. |
|
2461
|
|
|
* @param string $stream |
|
2462
|
|
|
* @param integer $pos |
|
2463
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd904856(v=office.12).aspx |
|
2464
|
|
|
* @return array |
|
2465
|
|
|
*/ |
|
2466
|
3 |
|
private function readRecordPerSlideHeadersFootersContainer($stream, $pos) |
|
2467
|
|
|
{ |
|
2468
|
|
|
$arrayReturn = array( |
|
2469
|
3 |
|
'length' => 0, |
|
2470
|
|
|
); |
|
2471
|
|
|
|
|
2472
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2473
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_HEADERSFOOTERS) { |
|
2474
|
|
|
// Record Header |
|
2475
|
3 |
|
$arrayReturn['length'] += 8; |
|
2476
|
|
|
// Length |
|
2477
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2478
|
|
|
} |
|
2479
|
|
|
|
|
2480
|
3 |
|
return $arrayReturn; |
|
2481
|
|
|
} |
|
2482
|
|
|
|
|
2483
|
|
|
/** |
|
2484
|
|
|
* An atom record that specifies whether a shape is a placeholder shape. |
|
2485
|
|
|
* @param string $stream |
|
2486
|
|
|
* @param integer $pos |
|
2487
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923930(v=office.12).aspx |
|
2488
|
|
|
* @return array |
|
2489
|
|
|
*/ |
|
2490
|
3 |
|
private function readRecordPlaceholderAtom($stream, $pos) |
|
2491
|
|
|
{ |
|
2492
|
|
|
$arrayReturn = array( |
|
2493
|
3 |
|
'length' => 0, |
|
2494
|
|
|
); |
|
2495
|
|
|
|
|
2496
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2497
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PLACEHOLDERATOM && $data['recLen'] == 0x00000008) { |
|
2498
|
|
|
// Record Header |
|
2499
|
3 |
|
$arrayReturn['length'] += 8; |
|
2500
|
|
|
// Datas |
|
2501
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2502
|
|
|
} |
|
2503
|
|
|
|
|
2504
|
3 |
|
return $arrayReturn; |
|
2505
|
|
|
} |
|
2506
|
|
|
|
|
2507
|
|
|
/** |
|
2508
|
|
|
* An atom record that specifies a collection of re-color mappings for a metafile ([MS-WMF]). |
|
2509
|
|
|
* @param string $stream |
|
2510
|
|
|
* @param integer $pos |
|
2511
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd904899(v=office.12).aspx |
|
2512
|
|
|
* @return array |
|
2513
|
|
|
*/ |
|
2514
|
3 |
|
private function readRecordRecolorInfoAtom($stream, $pos) |
|
2515
|
|
|
{ |
|
2516
|
|
|
$arrayReturn = array( |
|
2517
|
3 |
|
'length' => 0, |
|
2518
|
|
|
); |
|
2519
|
|
|
|
|
2520
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2521
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_RECOLORINFOATOM) { |
|
2522
|
|
|
// Record Header |
|
2523
|
|
|
$arrayReturn['length'] += 8; |
|
2524
|
|
|
// Datas |
|
2525
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2526
|
|
|
} |
|
2527
|
|
|
|
|
2528
|
3 |
|
return $arrayReturn; |
|
2529
|
|
|
} |
|
2530
|
|
|
|
|
2531
|
|
|
/** |
|
2532
|
|
|
* An atom record that specifies that a shape is a header or footerplaceholder shape. |
|
2533
|
|
|
* @param string $stream |
|
2534
|
|
|
* @param integer $pos |
|
2535
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd910800(v=office.12).aspx |
|
2536
|
|
|
* @return array |
|
2537
|
|
|
*/ |
|
2538
|
|
|
private function readRecordRoundTripHFPlaceholder12Atom($stream, $pos) |
|
2539
|
|
|
{ |
|
2540
|
|
|
$arrayReturn = array( |
|
2541
|
|
|
'length' => 0, |
|
2542
|
|
|
); |
|
2543
|
|
|
|
|
2544
|
|
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2545
|
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPHFPLACEHOLDER12ATOM && $data['recLen'] == 0x00000001) { |
|
2546
|
|
|
// Record Header |
|
2547
|
|
|
$arrayReturn['length'] += 8; |
|
2548
|
|
|
// Datas |
|
2549
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2550
|
|
|
} |
|
2551
|
|
|
|
|
2552
|
|
|
return $arrayReturn; |
|
2553
|
|
|
} |
|
2554
|
|
|
|
|
2555
|
|
|
/** |
|
2556
|
|
|
* An atom record that specifies a shape identifier. |
|
2557
|
|
|
* @param string $stream |
|
2558
|
|
|
* @param integer $pos |
|
2559
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd772926(v=office.12).aspx |
|
2560
|
|
|
* @return array |
|
2561
|
|
|
*/ |
|
2562
|
|
|
private function readRecordRoundTripShapeId12Atom($stream, $pos) |
|
2563
|
|
|
{ |
|
2564
|
|
|
$arrayReturn = array( |
|
2565
|
|
|
'length' => 0, |
|
2566
|
|
|
); |
|
2567
|
|
|
|
|
2568
|
|
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2569
|
|
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPSHAPEID12ATOM && $data['recLen'] == 0x00000004) { |
|
2570
|
|
|
// Record Header |
|
2571
|
|
|
$arrayReturn['length'] += 8; |
|
2572
|
|
|
// Length |
|
2573
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2574
|
|
|
} |
|
2575
|
|
|
|
|
2576
|
|
|
return $arrayReturn; |
|
2577
|
|
|
} |
|
2578
|
|
|
|
|
2579
|
|
|
/** |
|
2580
|
|
|
* A container record that specifies information about a slide that synchronizes to a slide in a slide library. |
|
2581
|
|
|
* @param string $stream |
|
2582
|
|
|
* @param integer $pos |
|
2583
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx |
|
2584
|
|
|
* @return array |
|
2585
|
|
|
*/ |
|
2586
|
3 |
|
private function readRecordRoundTripSlideSyncInfo12Container($stream, $pos) |
|
2587
|
|
|
{ |
|
2588
|
|
|
$arrayReturn = array( |
|
2589
|
3 |
|
'length' => 0, |
|
2590
|
|
|
); |
|
2591
|
|
|
|
|
2592
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2593
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_ROUNDTRIPSLIDESYNCINFO12) { |
|
2594
|
|
|
// Record Header |
|
2595
|
|
|
$arrayReturn['length'] += 8; |
|
2596
|
|
|
// Length |
|
2597
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2598
|
|
|
} |
|
2599
|
|
|
|
|
2600
|
3 |
|
return $arrayReturn; |
|
2601
|
|
|
} |
|
2602
|
|
|
|
|
2603
|
|
|
/** |
|
2604
|
|
|
* An atom record that specifies shape-level Boolean flags. |
|
2605
|
|
|
* @param string $stream |
|
2606
|
|
|
* @param integer $pos |
|
2607
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd908949(v=office.12).aspx |
|
2608
|
|
|
* @return array |
|
2609
|
|
|
*/ |
|
2610
|
3 |
|
private function readRecordShapeFlags10Atom($stream, $pos) |
|
2611
|
|
|
{ |
|
2612
|
|
|
$arrayReturn = array( |
|
2613
|
3 |
|
'length' => 0, |
|
2614
|
|
|
); |
|
2615
|
|
|
|
|
2616
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2617
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SHAPEFLAGS10ATOM && $data['recLen'] == 0x00000001) { |
|
2618
|
|
|
// Record Header |
|
2619
|
|
|
$arrayReturn['length'] += 8; |
|
2620
|
|
|
// Datas |
|
2621
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2622
|
|
|
} |
|
2623
|
|
|
|
|
2624
|
3 |
|
return $arrayReturn; |
|
2625
|
|
|
} |
|
2626
|
|
|
|
|
2627
|
|
|
/** |
|
2628
|
|
|
* An atom record that specifies shape-level Boolean flags. |
|
2629
|
|
|
* @param string $stream |
|
2630
|
|
|
* @param integer $pos |
|
2631
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd925824(v=office.12).aspx |
|
2632
|
|
|
* @return array |
|
2633
|
|
|
*/ |
|
2634
|
3 |
|
private function readRecordShapeFlagsAtom($stream, $pos) |
|
2635
|
|
|
{ |
|
2636
|
|
|
$arrayReturn = array( |
|
2637
|
3 |
|
'length' => 0, |
|
2638
|
|
|
); |
|
2639
|
|
|
|
|
2640
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2641
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SHAPEATOM && $data['recLen'] == 0x00000001) { |
|
2642
|
|
|
// Record Header |
|
2643
|
|
|
$arrayReturn['length'] += 8; |
|
2644
|
|
|
// Datas |
|
2645
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2646
|
|
|
} |
|
2647
|
|
|
|
|
2648
|
3 |
|
return $arrayReturn; |
|
2649
|
|
|
} |
|
2650
|
|
|
|
|
2651
|
|
|
/** |
|
2652
|
|
|
* A container record that specifies programmable tags with additional binary shape data. |
|
2653
|
|
|
* @param string $stream |
|
2654
|
|
|
* @param integer $pos |
|
2655
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd911033(v=office.12).aspx |
|
2656
|
|
|
* @return array |
|
2657
|
|
|
*/ |
|
2658
|
|
|
private function readRecordShapeProgBinaryTagContainer($stream, $pos) |
|
2659
|
|
|
{ |
|
2660
|
|
|
$arrayReturn = array( |
|
2661
|
|
|
'length' => 0, |
|
2662
|
|
|
); |
|
2663
|
|
|
|
|
2664
|
|
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2665
|
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGBINARYTAG) { |
|
2666
|
|
|
// Record Header |
|
2667
|
|
|
$arrayReturn['length'] += 8; |
|
2668
|
|
|
// Datas |
|
2669
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2670
|
|
|
} |
|
2671
|
|
|
|
|
2672
|
|
|
return $arrayReturn; |
|
2673
|
|
|
} |
|
2674
|
|
|
|
|
2675
|
|
|
/** |
|
2676
|
|
|
* A container record that specifies programmable tags with additional shape data. |
|
2677
|
|
|
* @param string $stream |
|
2678
|
|
|
* @param integer $pos |
|
2679
|
|
|
* @return array |
|
2680
|
|
|
* @throws \Exception |
|
2681
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd911266(v=office.12).aspx |
|
2682
|
|
|
*/ |
|
2683
|
|
|
private function readRecordShapeProgTagsContainer($stream, $pos) |
|
2684
|
|
|
{ |
|
2685
|
|
|
$arrayReturn = array( |
|
2686
|
|
|
'length' => 0, |
|
2687
|
|
|
); |
|
2688
|
|
|
|
|
2689
|
|
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2690
|
|
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGTAGS) { |
|
2691
|
|
|
// Record Header |
|
2692
|
|
|
$arrayReturn['length'] += 8; |
|
2693
|
|
|
|
|
2694
|
|
|
$length = 0; |
|
2695
|
|
|
do { |
|
2696
|
|
|
$dataHeaderRG = $this->loadRecordHeader($stream, $pos + $arrayReturn['length'] + $length); |
|
2697
|
|
|
switch ($dataHeaderRG['recType']) { |
|
2698
|
|
|
case self::RT_PROGBINARYTAG: |
|
2699
|
|
|
$dataRG = $this->readRecordShapeProgBinaryTagContainer($stream, $pos + $arrayReturn['length'] + $length); |
|
2700
|
|
|
$length += $dataRG['length']; |
|
2701
|
|
|
break; |
|
2702
|
|
|
//case self::RT_PROGSTRINGTAG: |
|
2703
|
|
|
default: |
|
2704
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
2705
|
|
|
} |
|
2706
|
|
|
} while ($length < $data['recLen']); |
|
2707
|
|
|
// Datas |
|
2708
|
|
|
$arrayReturn['length'] += $data['recLen']; |
|
2709
|
|
|
} |
|
2710
|
|
|
|
|
2711
|
|
|
return $arrayReturn; |
|
2712
|
|
|
} |
|
2713
|
|
|
|
|
2714
|
|
|
/** |
|
2715
|
|
|
* An atom record that specifies information about a slide. |
|
2716
|
|
|
* @param string $stream |
|
2717
|
|
|
* @param integer $pos |
|
2718
|
|
|
* @return array |
|
2719
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923801(v=office.12).aspx |
|
2720
|
|
|
*/ |
|
2721
|
3 |
|
private function readRecordSlideAtom($stream, $pos) |
|
2722
|
|
|
{ |
|
2723
|
|
|
$arrayReturn = array( |
|
2724
|
3 |
|
'length' => 0, |
|
2725
|
|
|
); |
|
2726
|
|
|
|
|
2727
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2728
|
3 |
|
if ($data['recVer'] == 0x2 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDEATOM) { |
|
2729
|
|
|
// Record Header |
|
2730
|
3 |
|
$arrayReturn['length'] += 8; |
|
2731
|
|
|
// slideAtom > geom |
|
2732
|
3 |
|
$arrayReturn['length'] += 4; |
|
2733
|
|
|
// slideAtom > rgPlaceholderTypes |
|
2734
|
3 |
|
$rgPlaceholderTypes = array(); |
|
2735
|
3 |
|
for ($inc = 0; $inc < 8; $inc++) { |
|
2736
|
3 |
|
$rgPlaceholderTypes[] = self::getInt1d($this->streamPowerpointDocument, $pos); |
|
2737
|
3 |
|
$arrayReturn['length'] += 1; |
|
2738
|
|
|
} |
|
2739
|
|
|
|
|
2740
|
|
|
// slideAtom > masterIdRef |
|
2741
|
3 |
|
$arrayReturn['length'] += 4; |
|
2742
|
|
|
// slideAtom > notesIdRef |
|
2743
|
3 |
|
$arrayReturn['length'] += 4; |
|
2744
|
|
|
// slideAtom > slideFlags |
|
2745
|
3 |
|
$arrayReturn['length'] += 2; |
|
2746
|
|
|
// slideAtom > unused; |
|
2747
|
3 |
|
$arrayReturn['length'] += 2; |
|
2748
|
|
|
} |
|
2749
|
|
|
|
|
2750
|
3 |
|
return $arrayReturn; |
|
2751
|
|
|
} |
|
2752
|
|
|
|
|
2753
|
|
|
/** |
|
2754
|
|
|
* A container record that specifies a presentation slide or title master slide. |
|
2755
|
|
|
* @param string $stream |
|
2756
|
|
|
* @param int $pos |
|
2757
|
|
|
* @throws \Exception |
|
2758
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd946323(v=office.12).aspx |
|
2759
|
|
|
*/ |
|
2760
|
3 |
|
private function readRecordSlideContainer($stream, $pos) |
|
2761
|
|
|
{ |
|
2762
|
|
|
// Core |
|
2763
|
3 |
|
$this->oPhpPresentation->createSlide(); |
|
2764
|
3 |
|
$this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1); |
|
2765
|
|
|
|
|
2766
|
|
|
// *** slideAtom (32 bytes) |
|
2767
|
3 |
|
$slideAtom = $this->readRecordSlideAtom($stream, $pos); |
|
2768
|
3 |
|
if ($slideAtom['length'] == 0) { |
|
2769
|
|
|
throw new \Exception('PowerPoint97 Reader : record SlideAtom'); |
|
2770
|
|
|
} |
|
2771
|
3 |
|
$pos += $slideAtom['length']; |
|
2772
|
|
|
|
|
2773
|
|
|
// *** slideShowSlideInfoAtom (24 bytes) |
|
2774
|
3 |
|
$slideShowInfoAtom = $this->readRecordSlideShowSlideInfoAtom($stream, $pos); |
|
2775
|
3 |
|
$pos += $slideShowInfoAtom['length']; |
|
2776
|
|
|
|
|
2777
|
|
|
// *** perSlideHFContainer (variable) : optional |
|
2778
|
3 |
|
$perSlideHFContainer = $this->readRecordPerSlideHeadersFootersContainer($stream, $pos); |
|
2779
|
3 |
|
$pos += $perSlideHFContainer['length']; |
|
2780
|
|
|
|
|
2781
|
|
|
// *** rtSlideSyncInfo12 (variable) : optional |
|
2782
|
3 |
|
$rtSlideSyncInfo12 = $this->readRecordRoundTripSlideSyncInfo12Container($stream, $pos); |
|
2783
|
3 |
|
$pos += $rtSlideSyncInfo12['length']; |
|
2784
|
|
|
|
|
2785
|
|
|
// *** drawing (variable) |
|
2786
|
3 |
|
$drawing = $this->readRecordDrawingContainer($stream, $pos); |
|
2787
|
3 |
|
$pos += $drawing['length']; |
|
2788
|
|
|
|
|
2789
|
|
|
// *** slideSchemeColorSchemeAtom (40 bytes) |
|
2790
|
3 |
|
$slideSchemeColorAtom = $this->readRecordSlideSchemeColorSchemeAtom($stream, $pos); |
|
2791
|
3 |
|
if ($slideSchemeColorAtom['length'] == 0) { |
|
2792
|
|
|
throw new \Exception('PowerPoint97 Reader : record SlideSchemeColorSchemeAtom'); |
|
2793
|
|
|
} |
|
2794
|
3 |
|
$pos += $slideSchemeColorAtom['length']; |
|
2795
|
|
|
|
|
2796
|
|
|
// *** slideNameAtom (variable) |
|
2797
|
3 |
|
$slideNameAtom = $this->readRecordSlideNameAtom($stream, $pos); |
|
2798
|
3 |
|
$pos += $slideNameAtom['length']; |
|
2799
|
|
|
|
|
2800
|
|
|
// *** slideProgTagsContainer (variable). |
|
2801
|
3 |
|
$slideProgTags = $this->readRecordSlideProgTagsContainer($stream, $pos); |
|
2802
|
3 |
|
$pos += $slideProgTags['length']; |
|
2803
|
|
|
|
|
2804
|
|
|
// *** rgRoundTripSlide (variable) |
|
2805
|
3 |
|
} |
|
2806
|
|
|
|
|
2807
|
|
|
/** |
|
2808
|
|
|
* An atom record that specifies the name of a slide. |
|
2809
|
|
|
* @param string $stream |
|
2810
|
|
|
* @param integer $pos |
|
2811
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd906297(v=office.12).aspx |
|
2812
|
|
|
* @return array |
|
2813
|
|
|
*/ |
|
2814
|
3 |
|
private function readRecordSlideNameAtom($stream, $pos) |
|
2815
|
|
|
{ |
|
2816
|
|
|
$arrayReturn = array( |
|
2817
|
3 |
|
'length' => 0, |
|
2818
|
|
|
'slideName' => '', |
|
2819
|
|
|
); |
|
2820
|
|
|
|
|
2821
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2822
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x003 && $data['recType'] == self::RT_CSTRING && $data['recLen'] % 2 == 0) { |
|
2823
|
|
|
// Record Header |
|
2824
|
|
|
$arrayReturn['length'] += 8; |
|
2825
|
|
|
// Length |
|
2826
|
|
|
$strLen = ($data['recLen'] / 2); |
|
2827
|
|
|
for ($inc = 0; $inc < $strLen; $inc++) { |
|
2828
|
|
|
$char = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
2829
|
|
|
$arrayReturn['length'] += 2; |
|
2830
|
|
|
$arrayReturn['slideName'] .= Text::chr($char); |
|
2831
|
|
|
} |
|
2832
|
|
|
} |
|
2833
|
|
|
|
|
2834
|
3 |
|
return $arrayReturn; |
|
2835
|
|
|
} |
|
2836
|
|
|
|
|
2837
|
|
|
/** |
|
2838
|
|
|
* An atom record that specifies a slide number metacharacter. |
|
2839
|
|
|
* @param string $stream |
|
2840
|
|
|
* @param integer $pos |
|
2841
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd945703(v=office.12).aspx |
|
2842
|
|
|
* @return array |
|
2843
|
|
|
*/ |
|
2844
|
3 |
|
private function readRecordSlideNumberMCAtom($stream, $pos) |
|
2845
|
|
|
{ |
|
2846
|
|
|
$arrayReturn = array( |
|
2847
|
3 |
|
'length' => 0, |
|
2848
|
|
|
); |
|
2849
|
|
|
|
|
2850
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2851
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDENUMBERMETACHARATOM && $data['recLen'] == 0x00000004) { |
|
2852
|
|
|
// Record Header |
|
2853
|
3 |
|
$arrayReturn['length'] += 8; |
|
2854
|
|
|
// Datas |
|
2855
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2856
|
|
|
} |
|
2857
|
|
|
|
|
2858
|
3 |
|
return $arrayReturn; |
|
2859
|
|
|
} |
|
2860
|
|
|
|
|
2861
|
|
|
/** |
|
2862
|
|
|
* A container record that specifies programmable tags with additional slide data. |
|
2863
|
|
|
* @param string $stream |
|
2864
|
|
|
* @param integer $pos |
|
2865
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd951946(v=office.12).aspx |
|
2866
|
|
|
* @return array |
|
2867
|
|
|
*/ |
|
2868
|
3 |
|
private function readRecordSlideProgTagsContainer($stream, $pos) |
|
2869
|
|
|
{ |
|
2870
|
|
|
$arrayReturn = array( |
|
2871
|
3 |
|
'length' => 0, |
|
2872
|
|
|
); |
|
2873
|
|
|
|
|
2874
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2875
|
3 |
|
if ($data['recVer'] == 0xF && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_PROGTAGS) { |
|
2876
|
|
|
// Record Header |
|
2877
|
3 |
|
$arrayReturn['length'] += 8; |
|
2878
|
|
|
// Length |
|
2879
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2880
|
|
|
} |
|
2881
|
|
|
|
|
2882
|
3 |
|
return $arrayReturn; |
|
2883
|
|
|
} |
|
2884
|
|
|
|
|
2885
|
|
|
/** |
|
2886
|
|
|
* A container record that specifies the color scheme used by a slide. |
|
2887
|
|
|
* @param string $stream |
|
2888
|
|
|
* @param integer $pos |
|
2889
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd949420(v=office.12).aspx |
|
2890
|
|
|
* @return array |
|
2891
|
|
|
*/ |
|
2892
|
3 |
|
private function readRecordSlideSchemeColorSchemeAtom($stream, $pos) |
|
2893
|
|
|
{ |
|
2894
|
|
|
$arrayReturn = array( |
|
2895
|
3 |
|
'length' => 0, |
|
2896
|
|
|
); |
|
2897
|
|
|
|
|
2898
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2899
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x001 && $data['recType'] == self::RT_COLORSCHEMEATOM && $data['recLen'] == 0x00000020) { |
|
2900
|
|
|
// Record Header |
|
2901
|
3 |
|
$arrayReturn['length'] += 8; |
|
2902
|
|
|
// Length |
|
2903
|
3 |
|
$rgSchemeColor = array(); |
|
2904
|
3 |
|
for ($inc = 0; $inc <= 7; $inc++) { |
|
2905
|
3 |
|
$rgSchemeColor[] = array( |
|
2906
|
3 |
|
'red' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4), |
|
2907
|
3 |
|
'green' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4 + 1), |
|
2908
|
3 |
|
'blue' => self::getInt1d($stream, $pos + $arrayReturn['length'] + $inc * 4 + 2), |
|
2909
|
|
|
); |
|
2910
|
|
|
} |
|
2911
|
3 |
|
$arrayReturn['length'] += (8 * 4); |
|
2912
|
|
|
} |
|
2913
|
|
|
|
|
2914
|
3 |
|
return $arrayReturn; |
|
2915
|
|
|
} |
|
2916
|
|
|
|
|
2917
|
|
|
/** |
|
2918
|
|
|
* An atom record that specifies what transition effect to perform during a slide show, and how to advance to the next presentation slide. |
|
2919
|
|
|
* @param string $stream |
|
2920
|
|
|
* @param integer $pos |
|
2921
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd943408(v=office.12).aspx |
|
2922
|
|
|
* @return array |
|
2923
|
|
|
*/ |
|
2924
|
3 |
|
private function readRecordSlideShowSlideInfoAtom($stream, $pos) |
|
2925
|
|
|
{ |
|
2926
|
|
|
$arrayReturn = array( |
|
2927
|
3 |
|
'length' => 0, |
|
2928
|
|
|
); |
|
2929
|
|
|
|
|
2930
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
2931
|
3 |
|
if ($data['recVer'] == 0x0 && $data['recInstance'] == 0x000 && $data['recType'] == self::RT_SLIDESHOWSLIDEINFOATOM && $data['recLen'] == 0x00000010) { |
|
2932
|
|
|
// Record Header |
|
2933
|
3 |
|
$arrayReturn['length'] += 8; |
|
2934
|
|
|
// Length; |
|
2935
|
3 |
|
$arrayReturn['length'] += $data['recLen']; |
|
2936
|
|
|
} |
|
2937
|
|
|
|
|
2938
|
3 |
|
return $arrayReturn; |
|
2939
|
|
|
} |
|
2940
|
|
|
|
|
2941
|
|
|
/** |
|
2942
|
|
|
* UserEditAtom |
|
2943
|
|
|
* @link http://msdn.microsoft.com/en-us/library/dd945746(v=office.12).aspx |
|
2944
|
|
|
* @param string $stream |
|
2945
|
|
|
* @param integer $pos |
|
2946
|
|
|
* @throws \Exception |
|
2947
|
|
|
*/ |
|
2948
|
3 |
|
private function readRecordUserEditAtom($stream, $pos) |
|
2949
|
|
|
{ |
|
2950
|
3 |
|
$rHeader = $this->loadRecordHeader($stream, $pos); |
|
2951
|
3 |
|
$pos += 8; |
|
2952
|
3 |
|
if ($rHeader['recVer'] != 0x0 || $rHeader['recInstance'] != 0x000 || $rHeader['recType'] != self::RT_USEREDITATOM || ($rHeader['recLen'] != 0x0000001C && $rHeader['recLen'] != 0x00000020)) { |
|
2953
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > RecordHeader).'); |
|
2954
|
|
|
} |
|
2955
|
|
|
|
|
2956
|
|
|
// lastSlideIdRef |
|
2957
|
3 |
|
$pos += 4; |
|
2958
|
|
|
// version |
|
2959
|
3 |
|
$pos += 2; |
|
2960
|
|
|
|
|
2961
|
|
|
// minorVersion |
|
2962
|
3 |
|
$minorVersion = self::getInt1d($stream, $pos); |
|
2963
|
3 |
|
$pos += 1; |
|
2964
|
3 |
|
if ($minorVersion != 0x00) { |
|
2965
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > minorVersion).'); |
|
2966
|
|
|
} |
|
2967
|
|
|
|
|
2968
|
|
|
// majorVersion |
|
2969
|
3 |
|
$majorVersion = self::getInt1d($stream, $pos); |
|
2970
|
3 |
|
$pos += 1; |
|
2971
|
3 |
|
if ($majorVersion != 0x03) { |
|
2972
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > majorVersion).'); |
|
2973
|
|
|
} |
|
2974
|
|
|
|
|
2975
|
|
|
// offsetLastEdit |
|
2976
|
3 |
|
$pos += 4; |
|
2977
|
|
|
// offsetPersistDirectory |
|
2978
|
3 |
|
$this->offsetPersistDirectory = self::getInt4d($stream, $pos); |
|
2979
|
3 |
|
$pos += 4; |
|
2980
|
|
|
|
|
2981
|
|
|
// docPersistIdRef |
|
2982
|
3 |
|
$docPersistIdRef = self::getInt4d($stream, $pos); |
|
2983
|
3 |
|
$pos += 4; |
|
2984
|
3 |
|
if ($docPersistIdRef != 0x00000001) { |
|
2985
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : UserEditAtom > docPersistIdRef).'); |
|
2986
|
|
|
} |
|
2987
|
|
|
|
|
2988
|
|
|
// persistIdSeed |
|
2989
|
3 |
|
$pos += 4; |
|
2990
|
|
|
// lastView |
|
2991
|
3 |
|
$pos += 2; |
|
2992
|
|
|
// unused |
|
2993
|
3 |
|
$pos += 2; |
|
2994
|
3 |
|
} |
|
2995
|
|
|
|
|
2996
|
|
|
/** |
|
2997
|
|
|
* A structure that specifies the character-level formatting of a run of text. |
|
2998
|
|
|
* @param string $stream |
|
2999
|
|
|
* @param int $pos |
|
3000
|
|
|
* @param int $strLenRT |
|
3001
|
|
|
* @return array |
|
3002
|
|
|
* @throws \Exception |
|
3003
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd945870(v=office.12).aspx |
|
3004
|
|
|
*/ |
|
3005
|
3 |
|
private function readStructureTextCFRun($stream, $pos, $strLenRT) |
|
3006
|
|
|
{ |
|
3007
|
|
|
$arrayReturn = array( |
|
3008
|
3 |
|
'length' => 0, |
|
3009
|
3 |
|
'strLenRT' => $strLenRT, |
|
3010
|
|
|
); |
|
3011
|
|
|
|
|
3012
|
|
|
// rgTextCFRun |
|
3013
|
3 |
|
$countRgTextCFRun = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3014
|
3 |
|
$arrayReturn['strLenRT'] -= $countRgTextCFRun; |
|
3015
|
3 |
|
$arrayReturn['length'] += 4; |
|
3016
|
3 |
|
$arrayReturn['partLength'] = $countRgTextCFRun; |
|
3017
|
|
|
|
|
3018
|
3 |
|
$masks = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3019
|
3 |
|
$arrayReturn['length'] += 4; |
|
3020
|
|
|
|
|
3021
|
3 |
|
$masksData = array(); |
|
3022
|
3 |
|
$masksData['bold'] = ($masks >> 0) & bindec('1'); |
|
3023
|
3 |
|
$masksData['italic'] = ($masks >> 1) & bindec('1'); |
|
3024
|
3 |
|
$masksData['underline'] = ($masks >> 2) & bindec('1'); |
|
3025
|
3 |
|
$masksData['unused1'] = ($masks >> 3) & bindec('1'); |
|
3026
|
3 |
|
$masksData['shadow'] = ($masks >> 4) & bindec('1'); |
|
3027
|
3 |
|
$masksData['fehint'] = ($masks >> 5) & bindec('1'); |
|
3028
|
3 |
|
$masksData['unused2'] = ($masks >> 6) & bindec('1'); |
|
3029
|
3 |
|
$masksData['kumi'] = ($masks >> 7) & bindec('1'); |
|
3030
|
3 |
|
$masksData['unused3'] = ($masks >> 8) & bindec('1'); |
|
3031
|
3 |
|
$masksData['emboss'] = ($masks >> 9) & bindec('1'); |
|
3032
|
3 |
|
$masksData['fHasStyle'] = ($masks >> 10) & bindec('1111'); |
|
3033
|
3 |
|
$masksData['unused4'] = ($masks >> 14) & bindec('11'); |
|
3034
|
3 |
|
$masksData['typeface'] = ($masks >> 16) & bindec('1'); |
|
3035
|
3 |
|
$masksData['size'] = ($masks >> 17) & bindec('1'); |
|
3036
|
3 |
|
$masksData['color'] = ($masks >> 18) & bindec('1'); |
|
3037
|
3 |
|
$masksData['position'] = ($masks >> 19) & bindec('1'); |
|
3038
|
3 |
|
$masksData['pp10ext'] = ($masks >> 20) & bindec('1'); |
|
3039
|
3 |
|
$masksData['oldEATypeface'] = ($masks >> 21) & bindec('1'); |
|
3040
|
3 |
|
$masksData['ansiTypeface'] = ($masks >> 22) & bindec('1'); |
|
3041
|
3 |
|
$masksData['symbolTypeface'] = ($masks >> 23) & bindec('1'); |
|
3042
|
3 |
|
$masksData['newEATypeface'] = ($masks >> 24) & bindec('1'); |
|
3043
|
3 |
|
$masksData['csTypeface'] = ($masks >> 25) & bindec('1'); |
|
3044
|
3 |
|
$masksData['pp11ext'] = ($masks >> 26) & bindec('1'); |
|
3045
|
3 |
|
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) { |
|
3046
|
2 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3047
|
2 |
|
$arrayReturn['length'] += 2; |
|
3048
|
|
|
|
|
3049
|
2 |
|
$fontStyleFlags = array(); |
|
3050
|
2 |
|
$fontStyleFlags['bold'] = ($data >> 0) & bindec('1'); |
|
3051
|
2 |
|
$fontStyleFlags['italic'] = ($data >> 1) & bindec('1'); |
|
3052
|
2 |
|
$fontStyleFlags['underline'] = ($data >> 2) & bindec('1'); |
|
3053
|
2 |
|
$fontStyleFlags['unused1'] = ($data >> 3) & bindec('1'); |
|
3054
|
2 |
|
$fontStyleFlags['shadow'] = ($data >> 4) & bindec('1'); |
|
3055
|
2 |
|
$fontStyleFlags['fehint'] = ($data >> 5) & bindec('1'); |
|
3056
|
2 |
|
$fontStyleFlags['unused2'] = ($data >> 6) & bindec('1'); |
|
3057
|
2 |
|
$fontStyleFlags['kumi'] = ($data >> 7) & bindec('1'); |
|
3058
|
2 |
|
$fontStyleFlags['unused3'] = ($data >> 8) & bindec('1'); |
|
3059
|
2 |
|
$fontStyleFlags['emboss'] = ($data >> 9) & bindec('1'); |
|
3060
|
2 |
|
$fontStyleFlags['pp9rt'] = ($data >> 10) & bindec('1111'); |
|
3061
|
2 |
|
$fontStyleFlags['unused4'] = ($data >> 14) & bindec('11'); |
|
3062
|
|
|
|
|
3063
|
2 |
|
$arrayReturn['bold'] = ($fontStyleFlags['bold'] == 1) ? true : false; |
|
3064
|
2 |
|
$arrayReturn['italic'] = ($fontStyleFlags['italic'] == 1) ? true : false; |
|
3065
|
2 |
|
$arrayReturn['underline'] = ($fontStyleFlags['underline'] == 1) ? true : false; |
|
3066
|
|
|
} |
|
3067
|
3 |
|
if ($masksData['typeface'] == 1) { |
|
3068
|
3 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3069
|
3 |
|
$arrayReturn['length'] += 2; |
|
3070
|
3 |
|
$arrayReturn['fontName'] = isset($this->arrayFonts[$data]) ? $this->arrayFonts[$data] : ''; |
|
3071
|
|
|
} |
|
3072
|
3 |
|
if ($masksData['oldEATypeface'] == 1) { |
|
3073
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3074
|
3 |
|
$arrayReturn['length'] += 2; |
|
3075
|
|
|
} |
|
3076
|
3 |
|
if ($masksData['ansiTypeface'] == 1) { |
|
3077
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3078
|
|
|
$arrayReturn['length'] += 2; |
|
3079
|
|
|
} |
|
3080
|
3 |
|
if ($masksData['symbolTypeface'] == 1) { |
|
3081
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3082
|
|
|
$arrayReturn['length'] += 2; |
|
3083
|
|
|
} |
|
3084
|
3 |
|
if ($masksData['size'] == 1) { |
|
3085
|
3 |
|
$arrayReturn['fontSize'] = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3086
|
3 |
|
$arrayReturn['length'] += 2; |
|
3087
|
|
|
} |
|
3088
|
3 |
|
if ($masksData['color'] == 1) { |
|
3089
|
3 |
|
$red = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3090
|
3 |
|
$arrayReturn['length'] += 1; |
|
3091
|
3 |
|
$green = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3092
|
3 |
|
$arrayReturn['length'] += 1; |
|
3093
|
3 |
|
$blue = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3094
|
3 |
|
$arrayReturn['length'] += 1; |
|
3095
|
3 |
|
$index = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3096
|
3 |
|
$arrayReturn['length'] += 1; |
|
3097
|
|
|
|
|
3098
|
3 |
|
if ($index == 0xFE) { |
|
3099
|
3 |
|
$strColor = str_pad(dechex($red), 2, STR_PAD_LEFT, '0'); |
|
3100
|
3 |
|
$strColor .= str_pad(dechex($green), 2, STR_PAD_LEFT, '0'); |
|
3101
|
3 |
|
$strColor .= str_pad(dechex($blue), 2, STR_PAD_LEFT, '0'); |
|
3102
|
|
|
|
|
3103
|
3 |
|
$arrayReturn['color'] = new Color('FF'.$strColor); |
|
3104
|
|
|
} |
|
3105
|
|
|
} |
|
3106
|
3 |
|
if ($masksData['position'] == 1) { |
|
3107
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3108
|
|
|
} |
|
3109
|
|
|
|
|
3110
|
3 |
|
return $arrayReturn; |
|
3111
|
|
|
} |
|
3112
|
|
|
|
|
3113
|
|
|
/** |
|
3114
|
|
|
* A structure that specifies the paragraph-level formatting of a run of text. |
|
3115
|
|
|
* @param string $stream |
|
3116
|
|
|
* @param integer $pos |
|
3117
|
|
|
* @param integer $strLenRT |
|
3118
|
|
|
* @return array |
|
3119
|
|
|
* @throws \Exception |
|
3120
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd923535(v=office.12).aspx |
|
3121
|
|
|
*/ |
|
3122
|
3 |
|
private function readStructureTextPFRun($stream, $pos, $strLenRT) |
|
3123
|
|
|
{ |
|
3124
|
|
|
$arrayReturn = array( |
|
3125
|
3 |
|
'length' => 0, |
|
3126
|
3 |
|
'strLenRT' => $strLenRT, |
|
3127
|
|
|
); |
|
3128
|
|
|
|
|
3129
|
|
|
// rgTextPFRun |
|
3130
|
3 |
|
$countRgTextPFRun = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3131
|
3 |
|
$arrayReturn['strLenRT'] -= $countRgTextPFRun; |
|
3132
|
3 |
|
$arrayReturn['length'] += 4; |
|
3133
|
|
|
|
|
3134
|
|
|
// indent |
|
3135
|
3 |
|
$arrayReturn['length'] += 2; |
|
3136
|
|
|
|
|
3137
|
3 |
|
$masks = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3138
|
3 |
|
$arrayReturn['length'] += 4; |
|
3139
|
|
|
|
|
3140
|
3 |
|
$masksData = array(); |
|
3141
|
3 |
|
$masksData['hasBullet'] = ($masks >> 0) & bindec('1'); |
|
3142
|
3 |
|
$masksData['bulletHasFont'] = ($masks >> 1) & bindec('1'); |
|
3143
|
3 |
|
$masksData['bulletHasColor'] = ($masks >> 2) & bindec('1'); |
|
3144
|
3 |
|
$masksData['bulletHasSize'] = ($masks >> 3) & bindec('1'); |
|
3145
|
3 |
|
$masksData['bulletFont'] = ($masks >> 4) & bindec('1'); |
|
3146
|
3 |
|
$masksData['bulletColor'] = ($masks >> 5) & bindec('1'); |
|
3147
|
3 |
|
$masksData['bulletSize'] = ($masks >> 6) & bindec('1'); |
|
3148
|
3 |
|
$masksData['bulletChar'] = ($masks >> 7) & bindec('1'); |
|
3149
|
3 |
|
$masksData['leftMargin'] = ($masks >> 8) & bindec('1'); |
|
3150
|
3 |
|
$masksData['unused'] = ($masks >> 9) & bindec('1'); |
|
3151
|
3 |
|
$masksData['indent'] = ($masks >> 10) & bindec('1'); |
|
3152
|
3 |
|
$masksData['align'] = ($masks >> 11) & bindec('1'); |
|
3153
|
3 |
|
$masksData['lineSpacing'] = ($masks >> 12) & bindec('1'); |
|
3154
|
3 |
|
$masksData['spaceBefore'] = ($masks >> 13) & bindec('1'); |
|
3155
|
3 |
|
$masksData['spaceAfter'] = ($masks >> 14) & bindec('1'); |
|
3156
|
3 |
|
$masksData['defaultTabSize'] = ($masks >> 15) & bindec('1'); |
|
3157
|
3 |
|
$masksData['fontAlign'] = ($masks >> 16) & bindec('1'); |
|
3158
|
3 |
|
$masksData['charWrap'] = ($masks >> 17) & bindec('1'); |
|
3159
|
3 |
|
$masksData['wordWrap'] = ($masks >> 18) & bindec('1'); |
|
3160
|
3 |
|
$masksData['overflow'] = ($masks >> 19) & bindec('1'); |
|
3161
|
3 |
|
$masksData['tabStops'] = ($masks >> 20) & bindec('1'); |
|
3162
|
3 |
|
$masksData['textDirection'] = ($masks >> 21) & bindec('1'); |
|
3163
|
3 |
|
$masksData['reserved1'] = ($masks >> 22) & bindec('1'); |
|
3164
|
3 |
|
$masksData['bulletBlip'] = ($masks >> 23) & bindec('1'); |
|
3165
|
3 |
|
$masksData['bulletScheme'] = ($masks >> 24) & bindec('1'); |
|
3166
|
3 |
|
$masksData['bulletHasScheme'] = ($masks >> 25) & bindec('1'); |
|
3167
|
|
|
|
|
3168
|
3 |
|
$bulletFlags = array(); |
|
3169
|
3 |
|
if ($masksData['hasBullet'] == 1 || $masksData['bulletHasFont'] == 1 || $masksData['bulletHasColor'] == 1 || $masksData['bulletHasSize'] == 1) { |
|
3170
|
3 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3171
|
3 |
|
$arrayReturn['length'] += 2; |
|
3172
|
|
|
|
|
3173
|
3 |
|
$bulletFlags['fHasBullet'] = ($data >> 0) & bindec('1'); |
|
3174
|
3 |
|
$bulletFlags['fBulletHasFont'] = ($data >> 1) & bindec('1'); |
|
3175
|
3 |
|
$bulletFlags['fBulletHasColor'] = ($data >> 2) & bindec('1'); |
|
3176
|
3 |
|
$bulletFlags['fBulletHasSize'] = ($data >> 3) & bindec('1'); |
|
3177
|
|
|
} |
|
3178
|
3 |
|
if ($masksData['bulletChar'] == 1) { |
|
3179
|
1 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3180
|
1 |
|
$arrayReturn['length'] += 2; |
|
3181
|
1 |
|
$arrayReturn['bulletChar'] = chr($data); |
|
3182
|
|
|
} |
|
3183
|
3 |
|
if ($masksData['bulletFont'] == 1) { |
|
3184
|
|
|
// $data = self::getInt2d($stream, $pos); |
|
3185
|
1 |
|
$arrayReturn['length'] += 2; |
|
3186
|
|
|
} |
|
3187
|
3 |
|
if ($masksData['bulletSize'] == 1) { |
|
3188
|
|
|
// $data = self::getInt2d($stream, $pos); |
|
3189
|
1 |
|
$arrayReturn['length'] += 2; |
|
3190
|
|
|
} |
|
3191
|
3 |
|
if ($masksData['bulletColor'] == 1) { |
|
3192
|
1 |
|
$red = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3193
|
1 |
|
$arrayReturn['length'] += 1; |
|
3194
|
1 |
|
$green = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3195
|
1 |
|
$arrayReturn['length'] += 1; |
|
3196
|
1 |
|
$blue = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3197
|
1 |
|
$arrayReturn['length'] += 1; |
|
3198
|
1 |
|
$index = self::getInt1d($stream, $pos + $arrayReturn['length']); |
|
3199
|
1 |
|
$arrayReturn['length'] += 1; |
|
3200
|
|
|
|
|
3201
|
1 |
|
if ($index == 0xFE) { |
|
3202
|
1 |
|
$strColor = str_pad(dechex($red), 2, STR_PAD_LEFT, '0'); |
|
3203
|
1 |
|
$strColor .= str_pad(dechex($green), 2, STR_PAD_LEFT, '0'); |
|
3204
|
1 |
|
$strColor .= str_pad(dechex($blue), 2, STR_PAD_LEFT, '0'); |
|
3205
|
|
|
} |
|
3206
|
|
|
} |
|
3207
|
3 |
|
if ($masksData['align'] == 1) { |
|
3208
|
3 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3209
|
3 |
|
$arrayReturn['length'] += 2; |
|
3210
|
|
|
switch ($data) { |
|
3211
|
3 |
|
case 0x0000: |
|
3212
|
1 |
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_LEFT; |
|
3213
|
1 |
|
break; |
|
3214
|
3 |
|
case 0x0001: |
|
3215
|
1 |
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_CENTER; |
|
3216
|
1 |
|
break; |
|
3217
|
3 |
|
case 0x0002: |
|
3218
|
3 |
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_RIGHT; |
|
3219
|
3 |
|
break; |
|
3220
|
|
|
case 0x0003: |
|
3221
|
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_JUSTIFY; |
|
3222
|
|
|
break; |
|
3223
|
|
|
case 0x0004: |
|
3224
|
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_DISTRIBUTED; |
|
3225
|
|
|
break; |
|
3226
|
|
|
case 0x0005: |
|
3227
|
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_DISTRIBUTED; |
|
3228
|
|
|
break; |
|
3229
|
|
|
case 0x0006: |
|
3230
|
|
|
$arrayReturn['alignH'] = Alignment::HORIZONTAL_JUSTIFY; |
|
3231
|
|
|
break; |
|
3232
|
|
|
default: |
|
3233
|
|
|
break; |
|
3234
|
|
|
} |
|
3235
|
|
|
} |
|
3236
|
3 |
|
if ($masksData['lineSpacing'] == 1) { |
|
3237
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3238
|
3 |
|
$arrayReturn['length'] += 2; |
|
3239
|
|
|
} |
|
3240
|
3 |
|
if ($masksData['spaceBefore'] == 1) { |
|
3241
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3242
|
2 |
|
$arrayReturn['length'] += 2; |
|
3243
|
|
|
} |
|
3244
|
3 |
|
if ($masksData['spaceAfter'] == 1) { |
|
3245
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3246
|
2 |
|
$arrayReturn['length'] += 2; |
|
3247
|
|
|
} |
|
3248
|
3 |
|
if ($masksData['leftMargin'] == 1) { |
|
3249
|
1 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3250
|
1 |
|
$arrayReturn['length'] += 2; |
|
3251
|
1 |
|
$arrayReturn['leftMargin'] = (int)round($data/6); |
|
3252
|
|
|
} |
|
3253
|
3 |
|
if ($masksData['indent'] == 1) { |
|
3254
|
1 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3255
|
1 |
|
$arrayReturn['length'] += 2; |
|
3256
|
1 |
|
$arrayReturn['indent'] = (int)round($data/6); |
|
3257
|
|
|
} |
|
3258
|
3 |
|
if ($masksData['defaultTabSize'] == 1) { |
|
3259
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3260
|
|
|
$arrayReturn['length'] += 2; |
|
3261
|
|
|
} |
|
3262
|
3 |
|
if ($masksData['tabStops'] == 1) { |
|
3263
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3264
|
|
|
} |
|
3265
|
3 |
|
if ($masksData['fontAlign'] == 1) { |
|
3266
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3267
|
|
|
$arrayReturn['length'] += 2; |
|
3268
|
|
|
} |
|
3269
|
3 |
|
if ($masksData['charWrap'] == 1 || $masksData['wordWrap'] == 1 || $masksData['overflow'] == 1) { |
|
3270
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3271
|
3 |
|
$arrayReturn['length'] += 2; |
|
3272
|
|
|
} |
|
3273
|
3 |
|
if ($masksData['textDirection'] == 1) { |
|
3274
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3275
|
|
|
} |
|
3276
|
|
|
|
|
3277
|
3 |
|
return $arrayReturn; |
|
3278
|
|
|
} |
|
3279
|
|
|
|
|
3280
|
|
|
/** |
|
3281
|
|
|
* A structure that specifies language and spelling information for a run of text. |
|
3282
|
|
|
* @param string $stream |
|
3283
|
|
|
* @param integer $pos |
|
3284
|
|
|
* @param string $strLenRT |
|
3285
|
|
|
* @return array |
|
3286
|
|
|
* @throws \Exception |
|
3287
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd909603(v=office.12).aspx |
|
3288
|
|
|
*/ |
|
3289
|
3 |
|
private function readStructureTextSIRun($stream, $pos, $strLenRT) |
|
3290
|
|
|
{ |
|
3291
|
|
|
$arrayReturn = array( |
|
3292
|
3 |
|
'length' => 0, |
|
3293
|
3 |
|
'strLenRT' => $strLenRT, |
|
3294
|
|
|
); |
|
3295
|
|
|
|
|
3296
|
3 |
|
$arrayReturn['strLenRT'] -= self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3297
|
3 |
|
$arrayReturn['length'] += 4; |
|
3298
|
|
|
|
|
3299
|
3 |
|
$data = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3300
|
3 |
|
$arrayReturn['length'] += 4; |
|
3301
|
3 |
|
$masksData = array(); |
|
3302
|
3 |
|
$masksData['spell'] = ($data >> 0) & bindec('1'); |
|
3303
|
3 |
|
$masksData['lang'] = ($data >> 1) & bindec('1'); |
|
3304
|
3 |
|
$masksData['altLang'] = ($data >> 2) & bindec('1'); |
|
3305
|
3 |
|
$masksData['unused1'] = ($data >> 3) & bindec('1'); |
|
3306
|
3 |
|
$masksData['unused2'] = ($data >> 4) & bindec('1'); |
|
3307
|
3 |
|
$masksData['fPp10ext'] = ($data >> 5) & bindec('1'); |
|
3308
|
3 |
|
$masksData['fBidi'] = ($data >> 6) & bindec('1'); |
|
3309
|
3 |
|
$masksData['unused3'] = ($data >> 7) & bindec('1'); |
|
3310
|
3 |
|
$masksData['reserved1'] = ($data >> 8) & bindec('1'); |
|
3311
|
3 |
|
$masksData['smartTag'] = ($data >> 9) & bindec('1'); |
|
3312
|
|
|
|
|
3313
|
3 |
|
if ($masksData['spell'] == 1) { |
|
3314
|
3 |
|
$data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3315
|
3 |
|
$arrayReturn['length'] += 2; |
|
3316
|
3 |
|
$masksSpell = array(); |
|
3317
|
3 |
|
$masksSpell['error'] = ($data >> 0) & bindec('1'); |
|
3318
|
3 |
|
$masksSpell['clean'] = ($data >> 1) & bindec('1'); |
|
3319
|
3 |
|
$masksSpell['grammar'] = ($data >> 2) & bindec('1'); |
|
3320
|
|
|
} |
|
3321
|
3 |
|
if ($masksData['lang'] == 1) { |
|
3322
|
|
|
// $data = self::getInt2d($stream, $pos); |
|
3323
|
3 |
|
$arrayReturn['length'] += 2; |
|
3324
|
|
|
} |
|
3325
|
3 |
|
if ($masksData['altLang'] == 1) { |
|
3326
|
|
|
// $data = self::getInt2d($stream, $pos); |
|
3327
|
3 |
|
$arrayReturn['length'] += 2; |
|
3328
|
|
|
} |
|
3329
|
3 |
|
if ($masksData['fBidi'] == 1) { |
|
3330
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3331
|
|
|
} |
|
3332
|
3 |
|
if ($masksData['fPp10ext'] == 1) { |
|
3333
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3334
|
|
|
} |
|
3335
|
3 |
|
if ($masksData['smartTag'] == 1) { |
|
3336
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3337
|
|
|
} |
|
3338
|
|
|
|
|
3339
|
3 |
|
return $arrayReturn; |
|
3340
|
|
|
} |
|
3341
|
|
|
|
|
3342
|
|
|
/** |
|
3343
|
|
|
* A structure that specifies tabbing, margins, and indentation for text. |
|
3344
|
|
|
* @param string $stream |
|
3345
|
|
|
* @param integer $pos |
|
3346
|
|
|
* @return array |
|
3347
|
|
|
* @throws \Exception |
|
3348
|
|
|
* @link https://msdn.microsoft.com/en-us/library/dd922749(v=office.12).aspx |
|
3349
|
|
|
*/ |
|
3350
|
3 |
|
private function readStructureTextRuler($stream, $pos) |
|
3351
|
|
|
{ |
|
3352
|
|
|
$arrayReturn = array( |
|
3353
|
3 |
|
'length' => 0, |
|
3354
|
|
|
); |
|
3355
|
|
|
|
|
3356
|
3 |
|
$data = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3357
|
3 |
|
$arrayReturn['length'] += 4; |
|
3358
|
|
|
|
|
3359
|
3 |
|
$masksData = array(); |
|
3360
|
3 |
|
$masksData['fDefaultTabSize'] = ($data >> 0) & bindec('1'); |
|
3361
|
3 |
|
$masksData['fCLevels'] = ($data >> 1) & bindec('1'); |
|
3362
|
3 |
|
$masksData['fTabStops'] = ($data >> 2) & bindec('1'); |
|
3363
|
3 |
|
$masksData['fLeftMargin1'] = ($data >> 3) & bindec('1'); |
|
3364
|
3 |
|
$masksData['fLeftMargin2'] = ($data >> 4) & bindec('1'); |
|
3365
|
3 |
|
$masksData['fLeftMargin3'] = ($data >> 5) & bindec('1'); |
|
3366
|
3 |
|
$masksData['fLeftMargin4'] = ($data >> 6) & bindec('1'); |
|
3367
|
3 |
|
$masksData['fLeftMargin5'] = ($data >> 7) & bindec('1'); |
|
3368
|
3 |
|
$masksData['fIndent1'] = ($data >> 8) & bindec('1'); |
|
3369
|
3 |
|
$masksData['fIndent2'] = ($data >> 9) & bindec('1'); |
|
3370
|
3 |
|
$masksData['fIndent3'] = ($data >> 10) & bindec('1'); |
|
3371
|
3 |
|
$masksData['fIndent4'] = ($data >> 11) & bindec('1'); |
|
3372
|
3 |
|
$masksData['fIndent5'] = ($data >> 12) & bindec('1'); |
|
3373
|
|
|
|
|
3374
|
3 |
|
if ($masksData['fCLevels'] == 1) { |
|
3375
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3376
|
|
|
} |
|
3377
|
3 |
|
if ($masksData['fDefaultTabSize'] == 1) { |
|
3378
|
|
|
throw new \Exception('Feature not implemented (l.'.__LINE__.')'); |
|
3379
|
|
|
} |
|
3380
|
3 |
|
if ($masksData['fTabStops'] == 1) { |
|
3381
|
3 |
|
$count = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3382
|
3 |
|
$arrayReturn['length'] += 2; |
|
3383
|
3 |
|
$arrayTabStops = array(); |
|
3384
|
3 |
|
for ($inc = 0; $inc < $count; $inc++) { |
|
3385
|
3 |
|
$position = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3386
|
3 |
|
$arrayReturn['length'] += 2; |
|
3387
|
3 |
|
$type = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3388
|
3 |
|
$arrayReturn['length'] += 2; |
|
3389
|
3 |
|
$arrayTabStops[] = array( |
|
3390
|
3 |
|
'position' => $position, |
|
3391
|
3 |
|
'type' => $type, |
|
3392
|
|
|
); |
|
3393
|
|
|
} |
|
3394
|
|
|
} |
|
3395
|
3 |
|
if ($masksData['fLeftMargin1'] == 1) { |
|
3396
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3397
|
1 |
|
$arrayReturn['length'] += 2; |
|
3398
|
|
|
} |
|
3399
|
3 |
|
if ($masksData['fIndent1'] == 1) { |
|
3400
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3401
|
1 |
|
$arrayReturn['length'] += 2; |
|
3402
|
|
|
} |
|
3403
|
3 |
|
if ($masksData['fLeftMargin2'] == 1) { |
|
3404
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3405
|
1 |
|
$arrayReturn['length'] += 2; |
|
3406
|
|
|
} |
|
3407
|
3 |
|
if ($masksData['fIndent2'] == 1) { |
|
3408
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3409
|
1 |
|
$arrayReturn['length'] += 2; |
|
3410
|
|
|
} |
|
3411
|
3 |
|
if ($masksData['fLeftMargin3'] == 1) { |
|
3412
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3413
|
|
|
$arrayReturn['length'] += 2; |
|
3414
|
|
|
} |
|
3415
|
3 |
|
if ($masksData['fIndent3'] == 1) { |
|
3416
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3417
|
|
|
$arrayReturn['length'] += 2; |
|
3418
|
|
|
} |
|
3419
|
3 |
|
if ($masksData['fLeftMargin4'] == 1) { |
|
3420
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3421
|
|
|
$arrayReturn['length'] += 2; |
|
3422
|
|
|
} |
|
3423
|
3 |
|
if ($masksData['fIndent4'] == 1) { |
|
3424
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3425
|
|
|
$arrayReturn['length'] += 2; |
|
3426
|
|
|
} |
|
3427
|
3 |
|
if ($masksData['fLeftMargin5'] == 1) { |
|
3428
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3429
|
|
|
$arrayReturn['length'] += 2; |
|
3430
|
|
|
} |
|
3431
|
3 |
|
if ($masksData['fIndent5'] == 1) { |
|
3432
|
|
|
// $data = self::getInt2d($stream, $pos + $arrayReturn['length']); |
|
3433
|
|
|
$arrayReturn['length'] += 2; |
|
3434
|
|
|
} |
|
3435
|
|
|
|
|
3436
|
3 |
|
return $arrayReturn; |
|
3437
|
|
|
} |
|
3438
|
|
|
|
|
3439
|
|
|
/** |
|
3440
|
|
|
* @param $stream |
|
3441
|
|
|
* @param int $pos |
|
3442
|
|
|
* @throws \Exception |
|
3443
|
|
|
*/ |
|
3444
|
3 |
|
private function readRecordNotesContainer($stream, $pos) |
|
3445
|
|
|
{ |
|
3446
|
|
|
// notesAtom |
|
3447
|
3 |
|
$notesAtom = $this->readRecordNotesAtom($stream, $pos); |
|
3448
|
3 |
|
$pos += $notesAtom['length']; |
|
3449
|
|
|
|
|
3450
|
|
|
// drawing |
|
3451
|
3 |
|
$drawing = $this->readRecordDrawingContainer($stream, $pos); |
|
3452
|
3 |
|
$pos += $drawing['length']; |
|
3453
|
|
|
|
|
3454
|
|
|
// slideSchemeColorSchemeAtom |
|
3455
|
|
|
// slideNameAtom |
|
3456
|
|
|
// slideProgTagsContainer |
|
3457
|
|
|
// rgNotesRoundTripAtom |
|
3458
|
3 |
|
} |
|
3459
|
|
|
|
|
3460
|
|
|
/** |
|
3461
|
|
|
* @param $stream |
|
3462
|
|
|
* @param int $pos |
|
3463
|
|
|
* @return array |
|
3464
|
|
|
* @throws \Exception |
|
3465
|
|
|
*/ |
|
3466
|
3 |
|
private function readRecordNotesAtom($stream, $pos) |
|
3467
|
|
|
{ |
|
3468
|
|
|
$arrayReturn = array( |
|
3469
|
3 |
|
'length' => 0, |
|
3470
|
|
|
); |
|
3471
|
|
|
|
|
3472
|
3 |
|
$data = $this->loadRecordHeader($stream, $pos); |
|
3473
|
3 |
|
if ($data['recVer'] != 0x1 || $data['recInstance'] != 0x000 || $data['recType'] != self::RT_NOTESATOM || $data['recLen'] != 0x00000008) { |
|
3474
|
|
|
throw new \Exception('File PowerPoint 97 in error (Location : NotesAtom > RecordHeader)'); |
|
3475
|
|
|
} |
|
3476
|
|
|
// Record Header |
|
3477
|
3 |
|
$arrayReturn['length'] += 8; |
|
3478
|
|
|
// NotesAtom > slideIdRef |
|
3479
|
3 |
|
$notesIdRef = self::getInt4d($stream, $pos + $arrayReturn['length']); |
|
3480
|
3 |
|
if ($notesIdRef == -2147483648) { |
|
3481
|
|
|
$notesIdRef = 0; |
|
3482
|
|
|
} |
|
3483
|
3 |
|
$this->currentNote = $notesIdRef; |
|
3484
|
3 |
|
$arrayReturn['length'] += 4; |
|
3485
|
|
|
|
|
3486
|
|
|
// NotesAtom > slideFlags |
|
3487
|
3 |
|
$arrayReturn['length'] += 2; |
|
3488
|
|
|
// NotesAtom > unused |
|
3489
|
3 |
|
$arrayReturn['length'] += 2; |
|
3490
|
|
|
|
|
3491
|
3 |
|
return $arrayReturn; |
|
3492
|
|
|
} |
|
3493
|
|
|
} |
|
3494
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.