2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Macintosh Utility Methods for MagickCore %
20 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % The directory methods are strongly based on similar methods written
37 % by Steve Summit, scs@eskimo.com. The Ghostscript launch code is strongly
38 % based on Dave Schooley's Mac Gnuplot and contributed by
39 % schindall@wave14i.nrl.navy.mil. Mac-centric improvements contributed by
40 % leonardr@digapp.com.
45 #if defined(macintosh)
51 #include <AppleEvents.h>
52 #include <AERegistry.h>
53 #include <AEObjects.h>
54 #include <AEPackObject.h>
55 #include <Processes.h>
56 #include <QuickDraw.h>
57 #include <QDOffscreen.h>
59 #include <ImageCompression.h>
60 #include <PictUtils.h>
63 #include <TextUtils.h>
64 #define ColorInfo KolorInfo
65 #include "MagickCore/studio.h"
66 #include "MagickCore/blob.h"
67 #include "MagickCore/client.h"
68 #include "MagickCore/exception.h"
69 #include "MagickCore/exception-private.h"
70 #include "MagickCore/image-private.h"
71 #include "MagickCore/list.h"
72 #include "MagickCore/magick.h"
73 #include "MagickCore/monitor.h"
74 #include "MagickCore/monitor-private.h"
75 #include "MagickCore/quantum.h"
76 #include "MagickCore/string_.h"
77 #include "MagickCore/utility.h"
78 #include "MagickCore/mac.h"
83 ImageDescriptionHandle
84 image_description = nil;
87 Forward declaractions.
90 SearchForFile(OSType,OSType,FSSpec *,short);
93 ArcMethod(GrafVerb,Rect *,short,short),
94 BitsMethod(BitMap *,Rect *,Rect *,short,RgnHandle),
95 FilenameToFSSpec(const char *filename,FSSpec *fsspec),
97 OvalMethod(GrafVerb,Rect *),
98 PolyMethod(GrafVerb,PolyHandle),
99 RRectMethod(GrafVerb,Rect *,short,short),
100 RectMethod(GrafVerb,Rect *),
101 RegionMethod(GrafVerb,RgnHandle),
102 StandardPixmap(PixMapPtr,Rect *,MatrixRecordPtr,short,RgnHandle,PixMapPtr,
104 TextMethod(short,Ptr,Point,Point);
109 #if defined(DISABLE_SIOUX)
110 static MACEventHookPtr
113 static MACErrorHookPtr
114 exception.hook = nil;
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 % B o t t l e n e c k T e s t %
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 % BottleneckTest() intercepts any compressed images.
130 % The format of the BottleneckTest method is:
132 % int BottleneckTest(const char *magick)
134 % A description of each parameter follows:
136 % o picture: Specifies a pointer to a PicHandle structure.
138 % o codec: the code type is returned in this CodecType pointer structure.
140 % o depth: the image depth is returned as an integer pointer.
142 % o colormap_id: the colormap ID is returned in this short pointer.
147 static pascal void ArcMethod(GrafVerb verb,Rect *r,short startAngle,
150 #pragma unused (verb,r,startAngle,arcAngle)
153 static pascal void BitsMethod(BitMap *bitPtr,Rect *source_rectangle,
154 Rect *dstRect,short mode,RgnHandle maskRgn)
156 #pragma unused (bitPtr,source_rectangle,dstRect,mode,maskRgn)
159 static pascal void LineMethod(Point newPt)
161 #pragma unused (newPt)
164 static pascal void OvalMethod(GrafVerb verb,Rect *r)
166 #pragma unused (verb,r)
169 static pascal void PolyMethod(GrafVerb verb,PolyHandle poly)
171 #pragma unused (verb,poly)
174 static pascal void RectMethod(GrafVerb verb,Rect *r)
176 #pragma unused (verb,r)
179 static pascal void RegionMethod(GrafVerb verb,RgnHandle rgn)
181 #pragma unused (verb,rgn)
184 static pascal void RRectMethod(GrafVerb verb,Rect *r,short ovalWidth,
187 #pragma unused (verb,r,ovalWidth,ovalHeight)
190 static pascal void StandardPixmap(PixMapPtr source,Rect *source_rectangle,
191 MatrixRecordPtr matrix,short mode,RgnHandle mask,PixMapPtr matte,
192 Rect *matte_rectangle,short flags)
194 #pragma unused (source_rectangle,matrix,mode,mask,matte,matte_rectangle,flags)
202 GetCompressedPixMapInfo(source,&image_description,&data,&size,nil,nil);
205 static pascal void TextMethod(short byteCount,Ptr textBuf,Point numer,
208 #pragma unused (byteCount,textBuf,numer,denom)
211 #if !defined(DISABLE_QUICKTIME)
212 static short BottleneckTest(PicHandle picture,CodecType *codec,int *depth,
227 status=Gestalt(gestaltQuickTime,&version);
230 ParamText("\pQuickTime not installed. Please install, then try again.",
236 Define our own bottlenecks to do nothing.
238 SetStdCProcs(&bottlenecks);
239 bottlenecks.textProc=NewQDTextUPP(&TextMethod);
240 bottlenecks.lineProc=NewQDLineUPP(&LineMethod);
241 bottlenecks.rectProc=NewQDRectUPP(&RectMethod);
242 bottlenecks.rRectProc=NewQDRRectUPP(&RRectMethod);
243 bottlenecks.ovalProc=NewQDOvalUPP(&OvalMethod);
244 bottlenecks.arcProc=NewQDArcUPP(&ArcMethod);
245 bottlenecks.polyProc=NewQDPolyUPP(&PolyMethod);
246 bottlenecks.rgnProc=NewQDRgnUPP(&RegionMethod);
247 bottlenecks.bitsProc=NewQDBitsUPP(&BitsMethod);
248 bottlenecks.newProc1=(UniversalProcPtr) NewStdPixUPP(&StandardPixmap);
250 Install our custom bottlenecks to intercept any compressed images.
252 (*(qd.thePort)).grafProcs=(QDProcs *) &bottlenecks;
253 DrawPicture(picture,&((**picture).picFrame));
254 PaintRect(&rectangle);
255 (*(qd.thePort)).grafProcs=0L;
257 Initialize our return values.
262 if (image_description != nil)
264 *codec=(**image_description).cType;
265 *depth=(**image_description).depth;
266 *colormap_id=(**image_description).clutID;
268 DisposeQDTextUPP(bottlenecks.textProc);
269 DisposeQDLineUPP(bottlenecks.lineProc);
270 DisposeQDRectUPP(bottlenecks.rectProc);
271 DisposeQDRRectUPP(bottlenecks.rRectProc);
272 DisposeQDOvalUPP(bottlenecks.ovalProc);
273 DisposeQDArcUPP(bottlenecks.arcProc);
274 DisposeQDPolyUPP(bottlenecks.polyProc);
275 DisposeQDRgnUPP(bottlenecks.rgnProc);
276 DisposeQDBitsUPP(bottlenecks.bitsProc);
277 DisposeStdPixUPP(bottlenecks.newProc1);
282 #if !defined(_MAGICKCORE_POSIX_SUPPORT_VERSION)
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294 % closedir() closes the named directory stream and frees the DIR structure.
296 % The format of the closedir method is:
300 % A description of each parameter follows:
302 % o entry: Specifies a pointer to a DIR structure.
306 MagickExport void closedir(DIR *entry)
308 if (image->debug != MagickFalse)
309 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
310 assert(entry != (DIR *) NULL);
311 RelinquishMagickMemory(entry);
316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 % Exit() exits the process.
328 % The format of the exit method is:
332 % A description of each parameter follows:
334 % o status: an integer value representing the status of the terminating
339 MagickExport int Exit(int status)
341 #if !defined(DISABLE_SIOUX)
342 (void) FormatLocaleFile(stdout,"Select File->Quit to exit.\n");
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 % F i l e n a m e T o F S S p e c %
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359 % FilenameToFSSpec() sets the file type of an image.
361 % The format of the FilenameToFSSpec method is:
363 % FilenameToFSSpec(filename,fsspec)
365 % A description of each parameter follows:
367 % o filename: Specifies the name of the file.
369 % o fsspec: A pointer to type FSSpec.
373 MagickExport void pascal FilenameToFSSpec(const char *filename,FSSpec *fsspec)
378 assert(filename != (char *) NULL);
379 c2pstrcpy(name,filename);
380 FSMakeFSSpec(0,0,name,fsspec);
384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388 % I s M a g i c k C o n f l i c t %
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 % MACIsMagickConflict() returns true if the image format conflicts with a
395 % logical drive (.e.g. X:).
397 % Contributed by Mark Gavin of Digital Applications, Inc.
399 % The format of the MACIsMagickConflict method is:
401 % status=MACIsMagickConflict(magick)
403 % A description of each parameter follows:
405 % o magick: Specifies the image format.
410 static OSErr HGetVInfo(short volume_index,StringPtr volume_name,short *volume,
411 size_t *free_bytes,size_t *total_bytes)
427 Use the File Manager to get the real vRefNum.
429 pb.volumeParam.ioVRefNum=0;
430 pb.volumeParam.ioNamePtr=volume_name;
431 pb.volumeParam.ioVolIndex=volume_index;
432 result=PBHGetVInfoSync(&pb);
435 *volume=pb.volumeParam.ioVRefNum;
436 blocksize=(size_t) pb.volumeParam.ioVAlBlkSiz;
437 allocation_blocks=(unsigned short) pb.volumeParam.ioVNmAlBlks;
438 free_blocks=(unsigned short) pb.volumeParam.ioVFrBlk;
439 *free_bytes=free_blocks*blocksize;
440 *total_bytes=allocation_blocks*blocksize;
444 MagickExport MagickBooleanType MACIsMagickConflict(const char *magick)
459 assert(magick != (char *) NULL);
460 if (image->debug != MagickFalse)
461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick);
462 (void) CopyMagickString((char *) volume_name,magick,MaxTextExtent);
463 c2pstr((char *) volume_name);
464 if (volume_name[volume_name[0]] != ':')
465 volume_name[++volume_name[0]]=':';
466 status=HGetVInfo(-1,volume_name,&volume,&free_bytes,&number_bytes);
467 return(status != 0 ? MagickFalse : MagickTrue);
471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475 + M A C E r r o r H a n d l e r %
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 % MACErrorHandler() displays an error reason and then terminates the program.
483 % The format of the MACErrorHandler method is:
485 % void MACErrorHandler(const ExceptionType error,const char *reason,
486 % const char *description)
488 % A description of each parameter follows:
490 % o exception: Specifies the numeric error category.
492 % o reason: Specifies the reason to display before terminating the
495 % o description: Specifies any description to the reason.
499 MagickExport void MACErrorHandler(const ExceptionType error,const char *reason,
500 const char *description)
503 buffer[3*MaxTextExtent];
505 if (reason == (char *) NULL)
507 if (description == (char *) NULL)
508 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
511 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
512 GetClientName(),reason,description);
513 #if defined(DISABLE_SIOUX)
514 if(exception.hook != (MACErrorHookPtr) NULL)
515 exception.hook(error,buffer);
518 MagickCoreTerminus();
523 MagickCoreTerminus();
528 #if defined(DISABLE_SIOUX)
530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 + M A C F a t a l E r r o r H a n d l e r %
538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540 % MACFatalErrorHandler() displays an error reason and then terminates the
543 % The format of the MACFatalErrorHandler method is:
545 % void MACFatalErrorHandler(const ExceptionType severity,
546 % const char *reason,const char *description)
548 % A description of each parameter follows:
550 % o severity: Specifies the numeric error category.
552 % o reason: Specifies the reason to display before terminating the
555 % o description: Specifies any description to the reason.
558 static void MACFatalErrorHandler(const ExceptionType severity,
559 const char *reason,const char *description)
562 buffer[3*MaxTextExtent];
564 if (reason == (char *) NULL)
566 if (description == (char *) NULL)
567 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
570 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
571 GetClientName(),reason,description);
572 if(exception.hook != (MACErrorHookPtr) NULL)
573 exception.hook(severity, buffer);
576 MagickCoreTerminus();
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587 % M a c G S E x e c u t e C o m m a n d %
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % MacGSExecuteCommand() executes the Ghostscript command.
597 static OSErr MacGSExecuteCommand(const char *command,ssize_t length)
603 reply = {typeNull, NULL};
606 event = {typeNull, NULL};
621 Send the Apple Event.
623 (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
624 (void) AECreateAppleEvent(id,'exec',&event_descriptor,-1,kAnyTransactionID,
626 (void) AEPutParamPtr(&event,keyDirectObject,typeChar,command,length);
627 (void) AESend(&event,&reply,kAEWaitReply+kAENeverInteract,kAENormalPriority,
628 kNoTimeOut,NULL,NULL);
630 Handle the reply and exit.
632 (void) AEGetParamPtr(&reply,keyDirectObject,typeInteger,&descriptor_type,
633 &error,sizeof(error),&actualSize);
634 (void) AEDisposeDesc(&event_descriptor);
635 (void) AEDisposeDesc(&event);
636 if (reply.descriptorType != NULL)
637 AEDisposeDesc(&reply);
638 return((OSErr) error);
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 % M a c G S L a u n c h A p p l i c a t i o n C o r e %
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % MacGSLaunchApplicationCore() launches the Ghostscript command.
656 static OSErr MacGSLaunchApplicationCore(ssize_t flags)
667 if (!SearchForFile('gsVR','APPL',&file_info,1))
669 launch_info.launchBlockID=extendedBlock;
670 launch_info.launchEPBLength=extendedBlockLen;
671 launch_info.launchFileFlags=0;
672 launch_info.launchControlFlags=launchContinue+launchNoFileFlags+flags;
673 launch_info.launchAppSpec=(&file_info);
674 launch_info.launchAppParameters=nil;
675 error=LaunchApplication(&launch_info);
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 % M a c G S L a u n c h A p p l i c a t i o n %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 % MacGSLaunchApplication() launches the Ghostscript command.
694 static OSErr MacGSLaunchApplication(void)
696 return(MacGSLaunchApplicationCore(launchDontSwitch));
700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 % M a c G S L a u n c h A p p l i c a t i o n T o F r o n t %
708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710 % MacGSLaunchApplicationToFront() moves the Ghostscript window to the front.
714 static OSErr MacGSLaunchApplicationToFront(void)
716 return(MacGSLaunchApplicationCore(0));
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 % M a c G S Q u i t A p p l i c a t i o n %
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730 % MacGSQuitApplication() quits the Ghostscript application.
734 static void MacGSQuitApplication(void)
740 reply = {typeNull, NULL};
743 event = {typeNull, NULL};
749 Send the Apple Event.
751 (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
752 (void) AECreateAppleEvent(typeAppleEvent,kAEQuitApplication,
753 &event_descriptor,-1,kAnyTransactionID,&event);
754 (void) AESend(&event,&reply,kAENoReply,kAENormalPriority,kNoTimeOut,NULL,
759 (void) AEDisposeDesc(&event_descriptor);
760 (void) AEDisposeDesc(&event);
761 if (reply.descriptorType != NULL)
762 AEDisposeDesc(&reply);
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 % M a c G S S e t W o r k i n g F o l d e r %
774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776 % MacGSSetWorkingFolder() set the Ghostscript working folder.
780 static OSErr MacGSSetWorkingFolder(char *directory)
783 application_descriptor,
794 folder_type = 'wfdr';
803 Send the Apple Event.
805 AECreateDesc(typeNull,NULL,0,&application_descriptor);
806 AECreateDesc(typeChar,directory,strlen(directory),&path_descriptor);
807 (void) AECreateDesc(typeType,&folder_type,sizeof(DescType),&type_descriptor);
808 CreateObjSpecifier(cProperty,&application_descriptor,formPropertyID,
809 &type_descriptor,0,&object);
810 (void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
811 (void) AECreateAppleEvent(kAECoreSuite,kAESetData,&event_descriptor,-1,
812 kAnyTransactionID,&event);
813 (void) AEPutParamDesc(&event,keyDirectObject,&object);
814 (void) AEPutParamDesc(&event,keyAEData,&path_descriptor);
815 error=AESend(&event,&reply,kAENoReply+kAENeverInteract,kAENormalPriority,
816 kNoTimeOut,NULL,NULL);
817 (void) AEDisposeDesc(&event);
818 (void) AEDisposeDesc(&event_descriptor);
819 (void) AEDisposeDesc(&object);
820 (void) AEDisposeDesc(&type_descriptor);
821 (void) AEDisposeDesc(&path_descriptor);
822 (void) AEDisposeDesc(&application_descriptor);
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 % M A C S e t E r r o r H o o k %
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 % MACSetErrorHook sets a callback function which is called if any error
838 % occurs within ImageMagick.
840 % The format of the MACSetErrorHook method is:
842 % int MACSetErrorHook(MACErrorHookPtr hook)
844 % A description of each parameter follows:
846 % o hook: This function pointer is the callback function.
850 MagickExport void MACSetErrorHook(MACErrorHookPtr hook)
853 We forget any previously set exception.hook.
859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 % M A C S e t E v e n t H o o k %
867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 % MACSetEventHook sets a callback function which is called every time
870 % ImageMagick likes to release the processor.
872 % The format of the MACSetEventHook method is:
874 % int MACSetEventHook(MACEventHookPtr hook)
876 % A description of each parameter follows:
878 % o hook: This function pointer is the callback function.
882 MagickExport void MACSetEventHook(MACEventHookPtr hook)
885 We forget any previously set event hook.
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895 % M A C S y s t e m C o m m a n d %
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % Method MACSystemCommand executes the specified command and waits until it
902 % terminates. The returned value is the exit status of the command.
904 % The format of the MACSystemCommand method is:
906 % int MACSystemCommand(MagickFalse,const char * command)
908 % A description of each parameter follows:
910 % o command: This string is the command to execute.
913 MagickExport int MACSystemCommand(const char * command)
916 We only know how to launch Ghostscript.
918 if (MacGSLaunchApplicationToFront())
920 return(MacGSExecuteCommand(command,strlen(command)));
924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928 % M A C W a r n i n g H a n d l e r %
932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 % MACWarningHandler() displays a warning reason.
936 % The format of the MACWarningHandler method is:
938 + void MACWarningHandler(const ExceptionType warning,const char *reason,
939 % const char *description)
941 % A description of each parameter follows:
943 % o warning: Specifies the numeric warning category.
945 % o reason: Specifies the reason to display before terminating the
948 % o description: Specifies any description to the reason.
952 MagickExport void MACWarningHandler(const ExceptionType warning,
953 const char *reason,const char *description)
958 if (reason == (char *) NULL)
960 if (description == (char *) NULL)
961 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
964 (void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
965 GetClientName(),reason,description);
966 #if defined(DISABLE_SIOUX)
967 if(exception.hook != (MACErrorHookPtr) NULL)
968 exception.hook(warning, buffer);
975 #if !defined(_MAGICKCORE_POSIX_SUPPORT_VERSION)
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 % opendir() opens the directory named by filename and associates a directory
990 % The format of the opendir method is:
992 % MagickExport DIR *opendir(char *path)
994 % A description of each parameter follows:
996 % o entry: Specifies a pointer to a DIR structure.
1000 MagickExport DIR *opendir(const char *path)
1013 search_info.hFileInfo.ioNamePtr=0;
1014 if ((path != (char *) NULL) || (*path != '\0'))
1015 if ((path[0] != '.') || (path[1] != '\0'))
1017 c2pstrcpy(pathname,path);
1018 search_info.hFileInfo.ioNamePtr=pathname;
1020 search_info.hFileInfo.ioCompletion=0;
1021 search_info.hFileInfo.ioVRefNum=0;
1022 search_info.hFileInfo.ioFDirIndex=0;
1023 search_info.hFileInfo.ioDirID=0;
1024 error=PBGetCatInfoSync(&search_info);
1028 return((DIR *) NULL);
1030 entry=(DIR *) AcquireMagickMemory(sizeof(DIR));
1031 if (entry == (DIR *) NULL)
1032 return((DIR *) NULL);
1033 entry->d_VRefNum=search_info.hFileInfo.ioVRefNum;
1034 entry->d_DirID=search_info.hFileInfo.ioDirID;
1041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045 % P r o c e s s P e n d i n g E v e n t s %
1049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1051 % ProcessPendingEvents() processes any pending events. This prevents
1052 % ImageMagick from monopolizing the processor.
1054 % The format of the ProcessPendingEvents method is:
1056 % ProcessPendingEvents(text)
1058 % A description of each parameter follows:
1060 % o text: A character string representing the current process.
1064 MagickExport void ProcessPendingEvents(const char *text)
1066 #if defined(DISABLE_SIOUX)
1067 if (event_hook != (MACEventHookPtr) NULL)
1071 *mark = (char *) NULL;
1076 while (WaitNextEvent(everyEvent,&event,0L,nil))
1077 SIOUXHandleOneEvent(&event);
1078 if (isatty(STDIN_FILENO) && (text != mark))
1086 #if !defined(_MAGICKCORE_POSIX_SUPPORT_VERSION)
1088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 % readdir() returns a pointer to a structure representing the directory entry
1099 % at the current position in the directory stream to which entry refers.
1101 % The format of the readdir
1103 % struct dirent *readdir(DIR *entry)
1105 % A description of each parameter follows:
1107 % o entry: Specifies a pointer to a DIR structure.
1111 MagickExport struct dirent *readdir(DIR *entry)
1119 static struct dirent
1122 static unsigned char
1123 pathname[MaxTextExtent];
1125 if (entry == (DIR *) NULL)
1126 return((struct dirent *) NULL);
1127 search_info.hFileInfo.ioCompletion=0;
1128 search_info.hFileInfo.ioNamePtr=pathname;
1129 search_info.hFileInfo.ioVRefNum=0;
1130 search_info.hFileInfo.ioFDirIndex=entry->d_index;
1131 search_info.hFileInfo.ioDirID=entry->d_DirID;
1132 error=PBGetCatInfoSync(&search_info);
1136 return((struct dirent *) NULL);
1139 p2cstrcpy(dir_entry.d_name,search_info.hFileInfo.ioNamePtr);
1140 dir_entry.d_namlen=strlen(dir_entry.d_name);
1146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1150 % R e a d P I C T I m a g e %
1154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 % ReadPICTImage() reads an Apple Macintosh QuickDraw/PICT image file using
1157 % MacOS QuickDraw methods and returns it. It allocates the memory necessary
1158 % for the new Image structure and returns a pointer to the new image.
1160 % This method was written and contributed by spd@daphne.cps.unizar.es
1161 % (feel free to copy and use it as you want. No warranty).
1163 % The format of the ReadPICTImage method is:
1165 % Image *ReadPICTImage(const ImageInfo *image_info,
1166 % ExceptionInfo *exception)
1168 % A description of each parameter follows:
1170 % o image: Method ReadPICTImage returns a pointer to the image after
1171 % reading. A null image is returned if there is a memory shortage or
1172 % if the image cannot be read.
1174 % o image_info: the image info..
1176 % o exception: return any errors or warnings in this structure.
1180 static inline size_t MagickMax(const size_t x,const size_t y)
1187 MagickExport Image *ReadPICTImage(const ImageInfo *image_info,
1188 ExceptionInfo *exception)
1190 #define PICTHeaderSize 512
1237 image=AcquireImage(image_info,exception);
1238 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1239 if (status == MagickFalse)
1241 picture_handle=(PicHandle) NewHandle(MagickMax(GetBlobSize(image)-
1242 PICTHeaderSize,PICTHeaderSize));
1243 if (picture_handle == nil)
1244 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1245 HLock((Handle) picture_handle);
1246 (void) ReadBlob(image,PICTHeaderSize,*(unsigned char **) picture_handle);
1247 status=ReadBlob(image,GetBlobSize(image)-PICTHeaderSize,*(unsigned char **)
1249 if (status == MagickFalse)
1251 DisposeHandle((Handle) picture_handle);
1252 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1254 GetGWorld(&port,&device);
1255 theErr=NewGWorld(&graphic_world,0,&(**picture_handle).picFrame,nil,nil,
1256 useTempMem | keepLocal);
1257 if ((theErr != noErr) && (graphic_world == nil))
1259 DisposeHandle((Handle) picture_handle);
1260 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1262 HUnlock((Handle) picture_handle);
1263 SetGWorld(graphic_world,nil);
1264 theErr=GetPictInfo(picture_handle,&picture_info,0,1,systemMethod,0);
1265 if (theErr != noErr)
1267 DisposeGWorld(graphic_world);
1268 DisposeHandle((Handle) picture_handle);
1269 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1271 #if defined(DISABLE_QUICKTIME)
1274 depth=picture_info.depth;
1276 BottleneckTest(picture_handle,&codec,&depth,&colormap_id);
1289 picture_info.theColorTable=GetCTable(colormap_id);
1295 depth=picture_info.depth;
1297 (void) GetPictInfo(picture_handle,&picture_info,returnColorTable,
1298 (short) (1 << picture_info.depth),systemMethod,0);
1302 image->resolution.x=(picture_info.hRes) >> 16;
1303 image->resolution.y=(picture_info.vRes) >> 16;
1304 image->units=PixelsPerInchResolution;
1305 image->columns=picture_info.sourceRect.right-picture_info.sourceRect.left;
1306 image->rows=picture_info.sourceRect.bottom-picture_info.sourceRect.top;
1307 if ((depth <= 8) && ((*(picture_info.theColorTable))->ctSize != 0))
1313 Colormapped PICT image.
1315 number_colors=(*(picture_info.theColorTable))->ctSize;
1316 if (!AcquireImageColormap(image,number_colors))
1318 if (picture_info.theColorTable != nil)
1319 DisposeHandle((Handle) picture_info.theColorTable);
1320 DisposeGWorld(graphic_world);
1321 DisposeHandle((Handle) picture_handle);
1322 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1324 for (x=0; x < image->colors; x++)
1326 image->colormap[x].red=
1327 (*(picture_info.theColorTable))->ctTable[x].rgb.red;
1328 image->colormap[x].green=
1329 (*(picture_info.theColorTable))->ctTable[x].rgb.green;
1330 image->colormap[x].blue=
1331 (*(picture_info.theColorTable))->ctTable[x].rgb.blue;
1334 SetRect(&rectangle,0,0,image->columns,image->rows);
1335 (void) UpdateGWorld(&graphic_world,depth,&rectangle,
1336 picture_info.theColorTable,nil,0);
1337 LockPixels(GetGWorldPixMap(graphic_world)); /*->portPixMap); */
1338 EraseRect(&rectangle);
1339 DrawPicture(picture_handle,&rectangle);
1340 if ((depth <= 8) && (colormap_id == -1))
1342 DisposeHandle((Handle) picture_info.theColorTable);
1343 picture_info.theColorTable=nil;
1345 DisposeHandle((Handle) picture_handle);
1347 Convert PICT pixels to pixel packets.
1349 for (y=0; y < image->rows; y++)
1357 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1358 if (q == (Quantum *) NULL)
1360 for (x=0; x < image->columns; x++)
1362 GetCPixel(x,y,&Pixel);
1363 SetPixelRed(image,ScaleCharToQuantum(Pixel.red & 0xff),q);
1364 SetPixelGreen(image,ScaleCharToQuantum(Pixel.green & 0xff),q);
1365 SetPixelBlue(image,ScaleCharToQuantum(Pixel.blue & 0xff),q);
1366 if (image->storage_class == PseudoClass)
1367 SetPixelIndex(image,Color2Index(&Pixel),q);
1368 q+=GetPixelChannels(image);
1370 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1372 proceed=SetImageProgress(image,LoadImageTag,y,image->rows);
1373 if (proceed == MagickFalse)
1376 UnlockPixels(GetGWorldPixMap(graphic_world));
1377 SetGWorld(port,device);
1378 if (picture_info.theColorTable != nil)
1379 DisposeHandle((Handle) picture_info.theColorTable);
1380 DisposeGWorld(graphic_world);
1381 (void) CloseBlob(image);
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1390 % S e a r c h F o r F i l e %
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 % SearchForFile() searches for a file.
1400 static Boolean SearchForFile(OSType creator_type,OSType file_type,FSSpec *file,
1426 buffer_size = 16384;
1428 serial_number.lowLongOfPSN=kCurrentProcess;
1429 serial_number.highLongOfPSN=0;
1430 application_info.processInfoLength=sizeof(ProcessInfoRec);
1431 application_info.processName=NULL;
1432 application_info.processAppSpec=(&application);
1433 GetProcessInformation(&serial_number,&application_info);
1434 buffer=NewPtr(buffer_size);
1435 if (buffer == (char *) NULL)
1437 parameter_info.csParam.ioCompletion=NULL;
1438 parameter_info.csParam.ioNamePtr=NULL;
1439 parameter_info.csParam.ioVRefNum=application.vRefNum;
1440 parameter_info.csParam.ioMatchPtr=file;
1441 parameter_info.csParam.ioReqMatchCount=count;
1442 parameter_info.csParam.ioSearchBits=fsSBFlFndrInfo;
1443 parameter_info.csParam.ioSearchInfo1=&search1_info;
1444 parameter_info.csParam.ioSearchInfo2=&search2_info;
1445 parameter_info.csParam.ioSearchTime=0;
1446 parameter_info.csParam.ioCatPosition.initialize=0;
1447 parameter_info.csParam.ioOptBuffer=buffer;
1448 parameter_info.csParam.ioOptBufSize=buffer_size;
1449 search1_info.hFileInfo.ioNamePtr=NULL;
1450 search1_info.hFileInfo.ioFlFndrInfo.fdType=file_type;
1451 search1_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
1452 search1_info.hFileInfo.ioFlAttrib=0;
1453 search1_info.hFileInfo.ioFlParID=0;
1454 search2_info=search1_info;
1455 search2_info.hFileInfo.ioFlAttrib=0x10;
1456 search2_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
1457 search2_info.hFileInfo.ioFlFndrInfo.fdType=(-1);
1458 search2_info.hFileInfo.ioFlFndrInfo.fdFlags=0;
1459 search2_info.hFileInfo.ioFlFndrInfo.fdLocation.h=0;
1460 search2_info.hFileInfo.ioFlFndrInfo.fdLocation.v=0;
1461 search2_info.hFileInfo.ioFlFndrInfo.fdFldr=0;
1462 search2_info.hFileInfo.ioFlParID=0;
1463 error=PBCatSearchSync((CSParamPtr) ¶meter_info);
1465 if (parameter_info.csParam.ioReqMatchCount ==
1466 parameter_info.csParam.ioActMatchCount)
1468 if (parameter_info.csParam.ioActMatchCount == 0)
1470 return(error == eofErr);
1473 #if !defined(_MAGICKCORE_POSIX_SUPPORT_VERSION)
1475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485 % seekdir() sets the position of the next readdir() operation on the directory
1488 % The format of the seekdir method is:
1490 % void seekdir(DIR *entry,ssize_t position)
1492 % A description of each parameter follows:
1494 % o entry: Specifies a pointer to a DIR structure.
1496 % o position: specifies the position associated with the directory
1502 MagickExport void seekdir(DIR *entry,ssize_t position)
1504 assert(entry != (DIR *) NULL);
1505 entry->d_index=position;
1510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514 % S e t A p p l i c a t i o n T y p e %
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1520 % SetApplicationType() sets the file type of an image.
1522 % The format of the SetApplicationType method is:
1524 % void SetApplicationType(const char *filename,const char *magick,
1525 % OSType application)
1527 % A description of each parameter follows:
1529 % o filename: Specifies the name of the file.
1531 % o filename: Specifies the file type.
1533 % o application: Specifies the type of the application.
1537 static inline size_t MagickMin(const size_t x,const size_t y)
1544 MagickExport void SetApplicationType(const char *filename,const char *magick,
1556 assert(filename != (char *) NULL);
1557 if (image->debug != MagickFalse)
1558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1559 assert(magick != (const char *) NULL);
1561 (void) CopyMagickString((char *) &filetype,magick,MagickMin(strlen(magick),
1563 if (LocaleCompare(magick,"JPG") == 0)
1564 (void) CopyMagickString((char *) &filetype,"JPEG",MaxTextExtent);
1565 c2pstrcpy(name,filename);
1566 FSMakeFSSpec(0,0,name,&file_specification);
1567 FSpCreate(&file_specification,application,filetype,smSystemScript);
1570 #if !defined(_MAGICKCORE_POSIX_SUPPORT_VERSION)
1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582 % Method telldir returns the current location associated with the
1583 % named directory stream.
1585 % The format of the telldir method is:
1587 % telldir(DIR *entry)
1589 % A description of each parameter follows:
1591 % o entry: Specifies a pointer to a DIR structure.
1595 MagickExport ssize_t telldir(DIR *entry)
1597 return(entry->d_index);