1 // =================================================================================================
2 // ADOBE SYSTEMS INCORPORATED
3 // Copyright 2002-2007 Adobe Systems Incorporated
4 // All Rights Reserved
5 //
6 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
7 // of the Adobe license agreement accompanying it.
8 // =================================================================================================
9
10 #include <limits.h>
11
12 #include "XMPScanner.hpp"
13
14 #include "Scanner_Handler.hpp"
15 #include "PostScript_Handler.hpp"
16
17 using namespace std;
18
19 // =================================================================================================
20 /// \file PostScript_Handler.cpp
21 /// \brief File format handler for PostScript and EPS files.
22 ///
23 /// This header ...
24 ///
25 // =================================================================================================
26
27 static const char * kPSFileTag = "%!PS-Adobe-";
28 static const size_t kPSFileTagLen = strlen ( kPSFileTag );
29
30 // =================================================================================================
31 // PostScript_MetaHandlerCTor
32 // ==========================
33
PostScript_MetaHandlerCTor(XMPFiles * parent)34 XMPFileHandler * PostScript_MetaHandlerCTor ( XMPFiles * parent )
35 {
36 XMPFileHandler * newHandler = new PostScript_MetaHandler ( parent );
37
38 return newHandler;
39
40 } // PostScript_MetaHandlerCTor
41
42 // =================================================================================================
43 // PostScript_CheckFormat
44 // ======================
45
PostScript_CheckFormat(XMP_FileFormat format,XMP_StringPtr filePath,LFA_FileRef fileRef,XMPFiles * parent)46 bool PostScript_CheckFormat ( XMP_FileFormat format,
47 XMP_StringPtr filePath,
48 LFA_FileRef fileRef,
49 XMPFiles * parent )
50 {
51 IgnoreParam(filePath); IgnoreParam(parent);
52 XMP_Assert ( (format == kXMP_EPSFile) || (format == kXMP_PostScriptFile) );
53
54 IOBuffer ioBuf;
55
56 XMP_Int64 psOffset;
57 size_t psLength;
58 long temp1, temp2;
59
60 // Check for the binary EPSF preview header.
61
62 LFA_Seek ( fileRef, 0, SEEK_SET );
63 if ( ! CheckFileSpace ( fileRef, &ioBuf, 4 ) ) return false;
64 temp1 = GetUns32BE ( ioBuf.ptr );
65
66 if ( temp1 == (long)0xC5D0D3C6 ) {
67
68 if ( ! CheckFileSpace ( fileRef, &ioBuf, 30 ) ) return false;
69
70 psOffset = GetUns32LE ( ioBuf.ptr+4 ); // PostScript offset.
71 psLength = GetUns32LE ( ioBuf.ptr+8 ); // PostScript length.
72
73 bool ok;
74 LFA_Seek ( fileRef, psOffset, SEEK_SET, &ok );
75 if ( ! ok ) return false; // Don't throw for a failure.
76
77 ioBuf.ptr = ioBuf.limit; // Make sure RefillBuffer does a simple read.
78 RefillBuffer ( fileRef, &ioBuf );
79 if ( (ioBuf.len < kIOBufferSize) && (ioBuf.len < psLength) ) return false; // Not enough PostScript.
80
81 }
82
83 // Check the start of the PostScript DSC header comment.
84
85 if ( ! CheckFileSpace ( fileRef, &ioBuf, (kPSFileTagLen + 3 + 1) ) ) return false;
86 if ( ! CheckBytes ( ioBuf.ptr, Uns8Ptr(kPSFileTag), kPSFileTagLen ) ) return false;
87 ioBuf.ptr += kPSFileTagLen;
88
89 // Check the PostScript DSC major version number.
90
91 temp1 = LONG_MIN; // Will safely overflow if there are digits, remain negative if there aren't.
92 while ( (ioBuf.ptr < ioBuf.limit) && ('0' <= *ioBuf.ptr) && (*ioBuf.ptr <= '9') ) {
93 temp1 = (temp1 * 10) + (*ioBuf.ptr - '0');
94 if ( temp1 < 0 ) return false; // Overflow.
95 ioBuf.ptr += 1;
96 }
97 // if ( temp1 < 0 ) break; *** Covered by 3.0 check.
98 if ( temp1 < 3 ) return false; // The version must be at least 3.0.
99
100 if ( ! CheckFileSpace ( fileRef, &ioBuf, 3 ) ) return false;
101 if ( *ioBuf.ptr != '.' ) return false; // No minor number.
102 ioBuf.ptr += 1;
103
104 // Check the PostScript DSC minor version number.
105
106 temp2 = LONG_MIN; // Will safely overflow if there are digits, remain negative if there aren't.
107 while ( (ioBuf.ptr < ioBuf.limit) && ('0' <= *ioBuf.ptr) && (*ioBuf.ptr <= '9') ) {
108 temp2 = (temp2 * 10) + (*ioBuf.ptr - '0');
109 if ( temp2 < 0 ) return false; // Overflow.
110 ioBuf.ptr += 1;
111 }
112 if ( temp2 < 0 ) return false; // No digits or overflow.
113 // Note that we don't care about the actual minor version number.
114
115 if ( format == kXMP_PostScriptFile ) {
116
117 // Almost done for plain PostScript, check for whitespace.
118
119 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return false;
120 if ( (*ioBuf.ptr != ' ') && (*ioBuf.ptr != kLF) && (*ioBuf.ptr != kCR) ) return false;
121 ioBuf.ptr += 1;
122
123 } else {
124
125 // Check for the EPSF keyword on the header comment.
126
127 if ( ! CheckFileSpace ( fileRef, &ioBuf, 6+3+1 ) ) return false;
128 if ( ! CheckBytes ( ioBuf.ptr, Uns8Ptr(" EPSF-"), 6 ) ) return false;
129 ioBuf.ptr += 6;
130
131 // Check the EPS major version number.
132
133 temp1 = LONG_MIN; // Will safely overflow if there are digits, remain negative if there aren't.
134 while ( (ioBuf.ptr < ioBuf.limit) && ('0' <= *ioBuf.ptr) && (*ioBuf.ptr <= '9') ) {
135 temp1 = (temp1 * 10) + (*ioBuf.ptr - '0');
136 if ( temp1 < 0 ) return false; // Overflow.
137 ioBuf.ptr += 1;
138 }
139 // if ( temp1 < 0 ) break; *** Covered by 3.0 check.
140 if ( temp1 < 3 ) return false; // The version must be at least 3.0.
141
142 if ( ! CheckFileSpace ( fileRef, &ioBuf, 3 ) ) return false;
143 if ( *ioBuf.ptr != '.' ) return false; // No minor number.
144 ioBuf.ptr += 1;
145
146 // Check the EPS minor version number.
147
148 temp2 = LONG_MIN; // Will safely overflow if there are digits, remain negative if there aren't.
149 while ( (ioBuf.ptr < ioBuf.limit) && ('0' <= *ioBuf.ptr) && (*ioBuf.ptr <= '9') ) {
150 temp2 = (temp2 * 10) + (*ioBuf.ptr - '0');
151 if ( temp2 < 0 ) return false; // Overflow.
152 ioBuf.ptr += 1;
153 }
154 if ( temp2 < 0 ) return false; // No digits or overflow.
155 // Note that we don't care about the actual minor version number.
156
157 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return false;
158 if ( (*ioBuf.ptr != kLF) && (*ioBuf.ptr != kCR) ) return false;
159 ioBuf.ptr += 1;
160
161 }
162
163 return true;
164
165 } // PostScript_CheckFormat
166
167 // =================================================================================================
168 // PostScript_MetaHandler::PostScript_MetaHandler
169 // ==============================================
170
PostScript_MetaHandler(XMPFiles * _parent)171 PostScript_MetaHandler::PostScript_MetaHandler ( XMPFiles * _parent )
172 {
173 this->parent = _parent;
174 this->handlerFlags = kPostScript_HandlerFlags;
175 this->stdCharForm = kXMP_Char8Bit;
176 this->psHint = kPSHint_NoMarker;
177
178 } // PostScript_MetaHandler::PostScript_MetaHandler
179
180 // =================================================================================================
181 // PostScript_MetaHandler::~PostScript_MetaHandler
182 // ===============================================
183
~PostScript_MetaHandler()184 PostScript_MetaHandler::~PostScript_MetaHandler()
185 {
186 // ! Inherit the base cleanup.
187
188 } // PostScript_MetaHandler::~PostScript_MetaHandler
189
190 // =================================================================================================
191 // PostScript_MetaHandler::FindPostScriptHint
192 // ==========================================
193 //
194 // Search for "%ADO_ContainsXMP:" at the beginning of a line, it must be before "%%EndComments". If
195 // the XMP marker is found, look for the MainFirst/MainLast/NoMain options.
196
197 static const char * kPSContainsXMPString = "%ADO_ContainsXMP:";
198 static const size_t kPSContainsXMPLength = strlen ( kPSContainsXMPString );
199
200 static const char * kPSEndCommentString = "%%EndComments"; // ! Assumed shorter than kPSContainsXMPString.
201 static const size_t kPSEndCommentLength = strlen ( kPSEndCommentString );
202
FindPostScriptHint()203 int PostScript_MetaHandler::FindPostScriptHint()
204 {
205 bool found = false;
206 IOBuffer ioBuf;
207 XMP_Uns8 ch;
208
209 LFA_FileRef fileRef = this->parent->fileRef;
210
211 XMP_AbortProc abortProc = this->parent->abortProc;
212 void * abortArg = this->parent->abortArg;
213 const bool checkAbort = (abortProc != 0);
214
215 // Check for the binary EPSF preview header.
216
217 LFA_Seek ( fileRef, 0, SEEK_SET );
218 if ( ! CheckFileSpace ( fileRef, &ioBuf, 4 ) ) return false;
219 long temp1 = GetUns32BE ( ioBuf.ptr );
220
221 if ( temp1 == (long)0xC5D0D3C6 ) {
222
223 if ( ! CheckFileSpace ( fileRef, &ioBuf, 30 ) ) return false;
224
225 size_t psOffset = GetUns32LE ( ioBuf.ptr+4 ); // PostScript offset.
226 size_t psLength = GetUns32LE ( ioBuf.ptr+8 ); // PostScript length.
227
228 bool ok;
229 LFA_Seek ( fileRef, psOffset, SEEK_SET, &ok );
230 if ( ! ok ) return false; // Don't throw for a failure.
231
232 ioBuf.ptr = ioBuf.limit; // Force the next check to refill the buffer.
233
234 }
235
236 // Look for the ContainsXMP comment.
237
238 while ( true ) {
239
240 if ( checkAbort && abortProc(abortArg) ) {
241 XMP_Throw ( "PostScript_MetaHandler::FindPostScriptHint - User abort", kXMPErr_UserAbort );
242 }
243
244 if ( ! CheckFileSpace ( fileRef, &ioBuf, kPSContainsXMPLength ) ) return kPSHint_NoMarker;
245
246 if ( CheckBytes ( ioBuf.ptr, Uns8Ptr(kPSEndCommentString), kPSEndCommentLength ) ) {
247
248 // Found "%%EndComments", don't look any further.
249 return kPSHint_NoMarker;
250
251 } else if ( ! CheckBytes ( ioBuf.ptr, Uns8Ptr(kPSContainsXMPString), kPSContainsXMPLength ) ) {
252
253 // Not "%%EndComments" or "%ADO_ContainsXMP:", skip past the end of this line.
254 do {
255 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return kPSHint_NoMarker;
256 ch = *ioBuf.ptr;
257 ++ioBuf.ptr;
258 } while ( ! IsNewline ( ch ) );
259
260 } else {
261
262 // Found "%ADO_ContainsXMP:", look for the main packet location option.
263
264 ioBuf.ptr += kPSContainsXMPLength;
265 int xmpHint = kPSHint_NoMain; // ! From here on, a failure means "no main", not "no marker".
266 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return kPSHint_NoMain;
267 if ( ! IsSpaceOrTab ( *ioBuf.ptr ) ) return kPSHint_NoMain;
268
269 while ( true ) {
270
271 while ( true ) { // Skip leading spaces and tabs.
272 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return kPSHint_NoMain;
273 if ( ! IsSpaceOrTab ( *ioBuf.ptr ) ) break;
274 ++ioBuf.ptr;
275 }
276 if ( IsNewline ( *ioBuf.ptr ) ) return kPSHint_NoMain; // Reached the end of the ContainsXMP comment.
277
278 if ( ! CheckFileSpace ( fileRef, &ioBuf, 6 ) ) return kPSHint_NoMain;
279
280 if ( CheckBytes ( ioBuf.ptr, Uns8Ptr("NoMain"), 6 ) ) {
281
282 ioBuf.ptr += 6;
283 xmpHint = kPSHint_NoMain;
284 break;
285
286 } else if ( CheckBytes ( ioBuf.ptr, Uns8Ptr("MainFi"), 6 ) ) {
287
288 ioBuf.ptr += 6;
289 if ( ! CheckFileSpace ( fileRef, &ioBuf, 3 ) ) return kPSHint_NoMain;
290 if ( CheckBytes ( ioBuf.ptr, Uns8Ptr("rst"), 3 ) ) {
291 ioBuf.ptr += 3;
292 xmpHint = kPSHint_MainFirst;
293 }
294 break;
295
296 } else if ( CheckBytes ( ioBuf.ptr, Uns8Ptr("MainLa"), 6 ) ) {
297
298 ioBuf.ptr += 6;
299 if ( ! CheckFileSpace ( fileRef, &ioBuf, 2 ) ) return kPSHint_NoMain;
300 if ( CheckBytes ( ioBuf.ptr, Uns8Ptr("st"), 2 ) ) {
301 ioBuf.ptr += 2;
302 xmpHint = kPSHint_MainLast;
303 }
304 break;
305
306 } else {
307
308 while ( true ) { // Skip until whitespace.
309 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return kPSHint_NoMain;
310 if ( IsWhitespace ( *ioBuf.ptr ) ) break;
311 ++ioBuf.ptr;
312 }
313
314 }
315
316 } // Look for the main packet location option.
317
318 // Make sure we found exactly a known option.
319 if ( ! CheckFileSpace ( fileRef, &ioBuf, 1 ) ) return kPSHint_NoMain;
320 if ( ! IsWhitespace ( *ioBuf.ptr ) ) return kPSHint_NoMain;
321 return xmpHint;
322
323 } // Found "%ADO_ContainsXMP:".
324
325 } // Outer marker loop.
326
327 return kPSHint_NoMarker; // Should never reach here.
328
329 } // PostScript_MetaHandler::FindPostScriptHint
330
331
332 // =================================================================================================
333 // PostScript_MetaHandler::FindFirstPacket
334 // =======================================
335 //
336 // Run the packet scanner until we find a valid packet. The first one is the main. For simplicity,
337 // the state of all snips is checked after each buffer is read. In theory only the last of the
338 // previous snips might change from partial to valid, but then we would have to special case the
339 // first pass when there is no previous set of snips. Since we have to get a full report to look at
340 // the last snip anyway, it costs virtually nothing extra to recheck all of the snips.
341
FindFirstPacket()342 bool PostScript_MetaHandler::FindFirstPacket()
343 {
344 int snipCount;
345 bool found = false;
346 size_t bufPos, bufLen;
347
348 LFA_FileRef fileRef = this->parent->fileRef;
349 XMP_Int64 fileLen = LFA_Measure ( fileRef );
350 XMP_PacketInfo & packetInfo = this->packetInfo;
351
352 XMPScanner scanner ( fileLen );
353 XMPScanner::SnipInfoVector snips;
354
355 enum { kBufferSize = 64*1024 };
356 XMP_Uns8 buffer [kBufferSize];
357
358 XMP_AbortProc abortProc = this->parent->abortProc;
359 void * abortArg = this->parent->abortArg;
360 const bool checkAbort = (abortProc != 0);
361
362 bufPos = 0;
363 bufLen = 0;
364
365 LFA_Seek ( fileRef, 0, SEEK_SET ); // Seek back to the beginning of the file.
366
367 while ( true ) {
368
369 if ( checkAbort && abortProc(abortArg) ) {
370 XMP_Throw ( "PostScript_MetaHandler::FindFirstPacket - User abort", kXMPErr_UserAbort );
371 }
372
373 bufPos += bufLen;
374 bufLen = LFA_Read ( fileRef, buffer, kBufferSize );
375 if ( bufLen == 0 ) return false; // Must be at EoF, no packets found.
376
377 scanner.Scan ( buffer, bufPos, bufLen );
378 snipCount = scanner.GetSnipCount();
379 scanner.Report ( snips );
380
381 for ( int i = 0; i < snipCount; ++i ) {
382 if ( snips[i].fState == XMPScanner::eValidPacketSnip ) {
383 if ( snips[i].fLength > 0x7FFFFFFF ) XMP_Throw ( "PostScript_MetaHandler::FindFirstPacket: Oversize packet", kXMPErr_BadXMP );
384 packetInfo.offset = snips[i].fOffset;
385 packetInfo.length = (XMP_Int32)snips[i].fLength;
386 packetInfo.charForm = snips[i].fCharForm;
387 packetInfo.writeable = (snips[i].fAccess == 'w');
388 return true;
389 }
390 }
391
392 }
393
394 return false;
395
396 } // FindFirstPacket
397
398
399 // =================================================================================================
400 // PostScript_MetaHandler::FindLastPacket
401 // ======================================
402 //
403 // Run the packet scanner backwards until we find the start of a packet, or a valid packet. If we
404 // found a packet start, resume forward scanning to see if it is a valid packet. For simplicity, all
405 // of the snips are checked on each pass, for much the same reasons as in FindFirstPacket.
406
407 #if 1
408
409 // *** Doing this right (as described above) requires out of order scanning support which isn't
410 // *** implemented yet. For now we scan the whole file and pick the last valid packet.
411
FindLastPacket()412 bool PostScript_MetaHandler::FindLastPacket()
413 {
414 int pkt;
415 size_t bufPos, bufLen;
416
417 LFA_FileRef fileRef = this->parent->fileRef;
418 XMP_Int64 fileLen = LFA_Measure ( fileRef );
419 XMP_PacketInfo & packetInfo = this->packetInfo;
420
421 // ------------------------------------------------------
422 // Scan the entire file to find all of the valid packets.
423
424 XMPScanner scanner ( fileLen );
425
426 enum { kBufferSize = 64*1024 };
427 XMP_Uns8 buffer [kBufferSize];
428
429 XMP_AbortProc abortProc = this->parent->abortProc;
430 void * abortArg = this->parent->abortArg;
431 const bool checkAbort = (abortProc != 0);
432
433 LFA_Seek ( fileRef, 0, SEEK_SET ); // Seek back to the beginning of the file.
434
435 for ( bufPos = 0; bufPos < (size_t)fileLen; bufPos += bufLen ) {
436 if ( checkAbort && abortProc(abortArg) ) {
437 XMP_Throw ( "PostScript_MetaHandler::FindLastPacket - User abort", kXMPErr_UserAbort );
438 }
439 bufLen = LFA_Read ( fileRef, buffer, kBufferSize );
440 if ( bufLen == 0 ) XMP_Throw ( "PostScript_MetaHandler::FindLastPacket: Read failure", kXMPErr_ExternalFailure );
441 scanner.Scan ( buffer, bufPos, bufLen );
442 }
443
444 // -------------------------------
445 // Pick the last the valid packet.
446
447 long snipCount = scanner.GetSnipCount();
448
449 XMPScanner::SnipInfoVector snips ( snipCount );
450 scanner.Report ( snips );
451
452 for ( pkt = snipCount-1; pkt >= 0; --pkt ) {
453 if ( snips[pkt].fState == XMPScanner::eValidPacketSnip ) break;
454 }
455
456 if ( pkt >= 0 ) {
457 if ( snips[pkt].fLength > 0x7FFFFFFF ) XMP_Throw ( "PostScript_MetaHandler::FindLastPacket: Oversize packet", kXMPErr_BadXMP );
458 packetInfo.offset = snips[pkt].fOffset;
459 packetInfo.length = (XMP_Int32)snips[pkt].fLength;
460 packetInfo.charForm = snips[pkt].fCharForm;
461 packetInfo.writeable = (snips[pkt].fAccess == 'w');
462 return true;
463 }
464
465 return false;
466
467 } // PostScript_MetaHandler::FindLastPacket
468
469 #else
470
FindLastPacket()471 bool PostScript_MetaHandler::FindLastPacket()
472 {
473 int err, snipCount;
474 bool found = false;
475 XMP_Int64 backPos, backLen;
476 size_t ioCount;
477
478 LFA_FileRef fileRef = this->parent->fileRef;
479 XMP_Int64 fileLen = LFA_Measure ( fileRef );
480 XMP_PacketInfo & packetInfo = this->packetInfo;
481
482 XMPScanner scanner ( fileLen );
483 XMPScanner::SnipInfoVector snips;
484
485 enum { kBufferSize = 64*1024 };
486 XMP_Uns8 buffer [kBufferSize];
487
488 XMP_AbortProc abortProc = this->parent->abortProc;
489 void * abortArg = this->parent->abortArg;
490 const bool checkAbort = (abortProc != 0);
491
492 backPos = fileLen;
493 backLen = 0;
494
495 while ( true ) {
496
497 if ( checkAbort && abortProc(abortArg) ) {
498 XMP_Throw ( "PostScript_MetaHandler::FindLastPacket - User abort", kXMPErr_UserAbort );
499 }
500
501 backLen = kBufferSize;
502 if ( backPos < kBufferSize ) backLen = backPos;
503 if ( backLen == 0 ) return false; // Must be at BoF, no packets found.
504
505 backPos -= backLen;
506 LFA_Seek ( fileRef, backPos, SEEK_SET ); // Seek back to the start of the next buffer.
507
508 #error "ioCount is 32 bits, backLen is 64"
509 ioCount = LFA_Read ( fileRef, buffer, backLen );
510 if ( ioCount != backLen ) XMP_Throw ( "PostScript_MetaHandler::FindLastPacket: Read failure", kXMPErr_ExternalFailure );
511
512 scanner.Scan ( buffer, backPos, backLen );
513 snipCount = scanner.GetSnipCount();
514 scanner.Report ( snips );
515
516 for ( int i = snipCount-1; i >= 0; --i ) {
517
518 if ( snips[i].fState == XMPScanner::eValidPacketSnip ) {
519
520 return VerifyMainPacket ( fileRef, snips[i].fOffset, snips[i].fLength, format, beLenient, mainInfo );
521
522 } else if ( snips[i].fState == XMPScanner::ePartialPacketSnip ) {
523
524 // This part is a tad tricky. We have a partial packet, so we need to scan
525 // forward from its ending to see if it is a valid packet. Snips won't recombine,
526 // the partial snip will change state. Be careful with the I/O to not clobber the
527 // backward scan positions, so that it can be resumed if necessary.
528
529 size_t fwdPos = snips[i].fOffset + snips[i].fLength;
530 LFA_Seek ( fileRef, fwdPos, SEEK_SET ); // Seek to the end of the partial snip.
531
532 while ( (fwdPos < fileLen) && (snips[i].fState == XMPScanner::ePartialPacketSnip) ) {
533 ioCount = LFA_Read ( fileRef, buffer, kBufferSize );
534 if ( ioCount == 0 ) XMP_Throw ( "PostScript_MetaHandler::FindLastPacket: Read failure", kXMPErr_ExternalFailure );
535 scanner.Scan ( buffer, fwdPos, ioCount );
536 scanner.Report ( snips );
537 fwdPos += ioCount;
538 }
539
540 if ( snips[i].fState == XMPScanner::eValidPacketSnip ) {
541 if ( snips[i].fLength > 0x7FFFFFFF ) XMP_Throw ( "PostScript_MetaHandler::FindLastPacket: Oversize packet", kXMPErr_BadXMP );
542 packetInfo.offset = snips[i].fOffset;
543 packetInfo.length = (XMP_Int32)snips[i].fLength;
544 packetInfo.charForm = snips[i].fCharForm;
545 packetInfo.writeable = (snips[i].fAccess == 'w');
546 return true;
547 }
548
549 }
550
551 } // Backwards snip loop.
552
553 } // Backwards read loop.
554
555 return false; // Should never get here.
556
557 } // PostScript_MetaHandler::FindLastPacket
558
559 #endif
560
561 // =================================================================================================
562 // PostScript_MetaHandler::CacheFileData
563 // =====================================
564
CacheFileData()565 void PostScript_MetaHandler::CacheFileData()
566 {
567 this->containsXMP = false;
568 this->psHint = FindPostScriptHint();
569
570 if ( this->psHint == kPSHint_MainFirst ) {
571 this->containsXMP = FindFirstPacket();
572 } else if ( this->psHint == kPSHint_MainLast ) {
573 this->containsXMP = FindLastPacket();
574 }
575
576 if ( this->containsXMP ) ReadXMPPacket ( this );
577
578 } // PostScript_MetaHandler::CacheFileData
579
580 // =================================================================================================
581