imagemagick/magick/mac.c

1607 lines
52 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M M AAA CCCC %
% MM MM A A C %
% M M M AAAAA C %
% M M A A C %
% M M A A CCCC %
% %
% %
% Macintosh Utility Methods for MagickCore %
% %
% Software Design %
% Cristy %
% September 1996 %
% %
% %
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The directory methods are strongly based on similar methods written
% by Steve Summit, scs@eskimo.com. The Ghostscript launch code is strongly
% based on Dave Schooley's Mac Gnuplot and contributed by
% schindall@wave14i.nrl.navy.mil. Mac-centric improvements contributed by
% leonardr@digapp.com.
%
%
*/
#if defined(macintosh)
/*
Include declarations.
*/
#define _X_H
#define _WIDGET_H
#include <AppleEvents.h>
#include <AERegistry.h>
#include <AEObjects.h>
#include <AEPackObject.h>
#include <Processes.h>
#include <QuickDraw.h>
#include <QDOffscreen.h>
#include <Palettes.h>
#include <ImageCompression.h>
#include <PictUtils.h>
#include <Files.h>
#include <Gestalt.h>
#include <TextUtils.h>
#define ColorInfo KolorInfo
#include "magick/studio.h"
#include "magick/blob.h"
#include "magick/client.h"
#include "magick/exception.h"
#include "magick/exception-private.h"
#include "magick/image-private.h"
#include "magick/list.h"
#include "magick/magick.h"
#include "magick/monitor.h"
#include "magick/monitor-private.h"
#include "magick/pixel-accessor.h"
#include "magick/quantum.h"
#include "magick/string_.h"
#include "magick/utility.h"
#include "magick/mac.h"
/*
Global declaractions.
*/
ImageDescriptionHandle
image_description = nil;
/*
Forward declaractions.
*/
static Boolean
SearchForFile(OSType,OSType,FSSpec *,short);
static pascal void
ArcMethod(GrafVerb,Rect *,short,short),
BitsMethod(BitMap *,Rect *,Rect *,short,RgnHandle),
FilenameToFSSpec(const char *filename,FSSpec *fsspec),
LineMethod(Point),
OvalMethod(GrafVerb,Rect *),
PolyMethod(GrafVerb,PolyHandle),
RRectMethod(GrafVerb,Rect *,short,short),
RectMethod(GrafVerb,Rect *),
RegionMethod(GrafVerb,RgnHandle),
StandardPixmap(PixMapPtr,Rect *,MatrixRecordPtr,short,RgnHandle,PixMapPtr,
Rect *,short),
TextMethod(short,Ptr,Point,Point);
/*
Static declarations
*/
#if defined(DISABLE_SIOUX)
static MACEventHookPtr
event_hook = nil;
static MACErrorHookPtr
exception.hook = nil;
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% B o t t l e n e c k T e s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BottleneckTest() intercepts any compressed images.
%
% The format of the BottleneckTest method is:
%
% int BottleneckTest(const char *magick)
%
% A description of each parameter follows:
%
% o picture: Specifies a pointer to a PicHandle structure.
%
% o codec: the code type is returned in this CodecType pointer structure.
%
% o depth: the image depth is returned as an integer pointer.
%
% o colormap_id: the colormap ID is returned in this short pointer.
%
%
*/
static pascal void ArcMethod(GrafVerb verb,Rect *r,short startAngle,
short arcAngle)
{
#pragma unused (verb,r,startAngle,arcAngle)
}
static pascal void BitsMethod(BitMap *bitPtr,Rect *source_rectangle,
Rect *dstRect,short mode,RgnHandle maskRgn)
{
#pragma unused (bitPtr,source_rectangle,dstRect,mode,maskRgn)
}
static pascal void LineMethod(Point newPt)
{
#pragma unused (newPt)
}
static pascal void OvalMethod(GrafVerb verb,Rect *r)
{
#pragma unused (verb,r)
}
static pascal void PolyMethod(GrafVerb verb,PolyHandle poly)
{
#pragma unused (verb,poly)
}
static pascal void RectMethod(GrafVerb verb,Rect *r)
{
#pragma unused (verb,r)
}
static pascal void RegionMethod(GrafVerb verb,RgnHandle rgn)
{
#pragma unused (verb,rgn)
}
static pascal void RRectMethod(GrafVerb verb,Rect *r,short ovalWidth,
short ovalHeight)
{
#pragma unused (verb,r,ovalWidth,ovalHeight)
}
static pascal void StandardPixmap(PixMapPtr source,Rect *source_rectangle,
MatrixRecordPtr matrix,short mode,RgnHandle mask,PixMapPtr matte,
Rect *matte_rectangle,short flags)
{
#pragma unused (source_rectangle,matrix,mode,mask,matte,matte_rectangle,flags)
Ptr
data;
ssize_t
size;
GetCompressedPixMapInfo(source,&image_description,&data,&size,nil,nil);
}
static pascal void TextMethod(short byteCount,Ptr textBuf,Point numer,
Point denom)
{
#pragma unused (byteCount,textBuf,numer,denom)
}
#if !defined(DISABLE_QUICKTIME)
static short BottleneckTest(PicHandle picture,CodecType *codec,int *depth,
short *colormap_id)
{
CQDProcs
bottlenecks;
int
status;
Rect
rectangle;
ssize_t
version;
status=Gestalt(gestaltQuickTime,&version);
if (status != noErr)
{
ParamText("\pQuickTime not installed. Please install, then try again.",
"\p","\p","\p");
Alert(128,nil);
return(-1);
}
/*
Define our own bottlenecks to do nothing.
*/
SetStdCProcs(&bottlenecks);
bottlenecks.textProc=NewQDTextUPP(&TextMethod);
bottlenecks.lineProc=NewQDLineUPP(&LineMethod);
bottlenecks.rectProc=NewQDRectUPP(&RectMethod);
bottlenecks.rRectProc=NewQDRRectUPP(&RRectMethod);
bottlenecks.ovalProc=NewQDOvalUPP(&OvalMethod);
bottlenecks.arcProc=NewQDArcUPP(&ArcMethod);
bottlenecks.polyProc=NewQDPolyUPP(&PolyMethod);
bottlenecks.rgnProc=NewQDRgnUPP(&RegionMethod);
bottlenecks.bitsProc=NewQDBitsUPP(&BitsMethod);
bottlenecks.newProc1=(UniversalProcPtr) NewStdPixUPP(&StandardPixmap);
/*
Install our custom bottlenecks to intercept any compressed images.
*/
(*(qd.thePort)).grafProcs=(QDProcs *) &bottlenecks;
DrawPicture(picture,&((**picture).picFrame));
PaintRect(&rectangle);
(*(qd.thePort)).grafProcs=0L;
/*
Initialize our return values.
*/
*codec='unkn';
*depth=0;
*colormap_id=(-1);
if (image_description != nil)
{
*codec=(**image_description).cType;
*depth=(**image_description).depth;
*colormap_id=(**image_description).clutID;
}
DisposeQDTextUPP(bottlenecks.textProc);
DisposeQDLineUPP(bottlenecks.lineProc);
DisposeQDRectUPP(bottlenecks.rectProc);
DisposeQDRRectUPP(bottlenecks.rRectProc);
DisposeQDOvalUPP(bottlenecks.ovalProc);
DisposeQDArcUPP(bottlenecks.arcProc);
DisposeQDPolyUPP(bottlenecks.polyProc);
DisposeQDRgnUPP(bottlenecks.rgnProc);
DisposeQDBitsUPP(bottlenecks.bitsProc);
DisposeStdPixUPP(bottlenecks.newProc1);
return(0);
}
#endif
#if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% c l o s e d i r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% closedir() closes the named directory stream and frees the DIR structure.
%
% The format of the closedir method is:
%
% closedir(entry)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
%
*/
MagickExport void closedir(DIR *entry)
{
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(entry != (DIR *) NULL);
RelinquishMagickMemory(entry);
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% E x i t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Exit() exits the process.
%
% The format of the exit method is:
%
% Exit(status)
%
% A description of each parameter follows:
%
% o status: an integer value representing the status of the terminating
% process.
%
%
*/
MagickExport int Exit(int status)
{
#if !defined(DISABLE_SIOUX)
(void) FormatLocaleFile(stdout,"Select File->Quit to exit.\n");
#endif
exit(status);
return(0);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% F i l e n a m e T o F S S p e c %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FilenameToFSSpec() sets the file type of an image.
%
% The format of the FilenameToFSSpec method is:
%
% FilenameToFSSpec(filename,fsspec)
%
% A description of each parameter follows:
%
% o filename: Specifies the name of the file.
%
% o fsspec: A pointer to type FSSpec.
%
%
*/
MagickExport void pascal FilenameToFSSpec(const char *filename,FSSpec *fsspec)
{
Str255
name;
assert(filename != (char *) NULL);
c2pstrcpy(name,filename);
FSMakeFSSpec(0,0,name,fsspec);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% I s M a g i c k C o n f l i c t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACIsMagickConflict() returns true if the image format conflicts with a
% logical drive (.e.g. X:).
%
% Contributed by Mark Gavin of Digital Applications, Inc.
%
% The format of the MACIsMagickConflict method is:
%
% status=MACIsMagickConflict(magick)
%
% A description of each parameter follows:
%
% o magick: Specifies the image format.
%
%
*/
static OSErr HGetVInfo(short volume_index,StringPtr volume_name,short *volume,
size_t *free_bytes,size_t *total_bytes)
{
HParamBlockRec
pb;
OSErr
result;
size_t
blocksize;
unsigned short
allocation_blocks,
free_blocks;
/*
Use the File Manager to get the real vRefNum.
*/
pb.volumeParam.ioVRefNum=0;
pb.volumeParam.ioNamePtr=volume_name;
pb.volumeParam.ioVolIndex=volume_index;
result=PBHGetVInfoSync(&pb);
if (result != noErr)
return(result);
*volume=pb.volumeParam.ioVRefNum;
blocksize=(size_t) pb.volumeParam.ioVAlBlkSiz;
allocation_blocks=(unsigned short) pb.volumeParam.ioVNmAlBlks;
free_blocks=(unsigned short) pb.volumeParam.ioVFrBlk;
*free_bytes=free_blocks*blocksize;
*total_bytes=allocation_blocks*blocksize;
return(result);
}
MagickExport MagickBooleanType MACIsMagickConflict(const char *magick)
{
size_t
free_bytes,
number_bytes;
OSErr
status;
short
volume;
Str255
volume_name;
assert(magick != (char *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick);
(void) CopyMagickString((char *) volume_name,magick,MaxTextExtent);
c2pstr((char *) volume_name);
if (volume_name[volume_name[0]] != ':')
volume_name[++volume_name[0]]=':';
status=HGetVInfo(-1,volume_name,&volume,&free_bytes,&number_bytes);
return(status != 0 ? MagickFalse : MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M A C E r r o r H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACErrorHandler() displays an error reason and then terminates the program.
%
% The format of the MACErrorHandler method is:
%
% void MACErrorHandler(const ExceptionType error,const char *reason,
% const char *description)
%
% A description of each parameter follows:
%
% o exception: Specifies the numeric error category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
%
*/
MagickExport void MACErrorHandler(const ExceptionType error,const char *reason,
const char *description)
{
char
buffer[3*MaxTextExtent];
if (reason == (char *) NULL)
return;
if (description == (char *) NULL)
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
reason);
else
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
GetClientName(),reason,description);
#if defined(DISABLE_SIOUX)
if(exception.hook != (MACErrorHookPtr) NULL)
exception.hook(error,buffer);
else
{
MagickCoreTerminus();
exit(error);
}
#else
puts(buffer);
MagickCoreTerminus();
exit(error);
#endif
}
#if defined(DISABLE_SIOUX)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ M A C F a t a l E r r o r H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACFatalErrorHandler() displays an error reason and then terminates the
% program.
%
% The format of the MACFatalErrorHandler method is:
%
% void MACFatalErrorHandler(const ExceptionType severity,
% const char *reason,const char *description)
%
% A description of each parameter follows:
%
% o severity: Specifies the numeric error category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
*/
static void MACFatalErrorHandler(const ExceptionType severity,
const char *reason,const char *description)
{
char
buffer[3*MaxTextExtent];
if (reason == (char *) NULL)
return;
if (description == (char *) NULL)
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
reason);
else
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
GetClientName(),reason,description);
if(exception.hook != (MACErrorHookPtr) NULL)
exception.hook(severity, buffer);
else
{
MagickCoreTerminus();
exit(severity);
}
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M a c G S E x e c u t e C o m m a n d %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSExecuteCommand() executes the Ghostscript command.
%
%
*/
static OSErr MacGSExecuteCommand(const char *command,ssize_t length)
{
AEAddressDesc
event_descriptor;
AEDesc
reply = {typeNull, NULL};
AppleEvent
event = {typeNull, NULL};
DescType
descriptor_type;
int
error;
OSType
id = 'gsVR';
Size
actualSize;
/*
Send the Apple Event.
*/
(void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
(void) AECreateAppleEvent(id,'exec',&event_descriptor,-1,kAnyTransactionID,
&event);
(void) AEPutParamPtr(&event,keyDirectObject,typeChar,command,length);
(void) AESend(&event,&reply,kAEWaitReply+kAENeverInteract,kAENormalPriority,
kNoTimeOut,NULL,NULL);
/*
Handle the reply and exit.
*/
(void) AEGetParamPtr(&reply,keyDirectObject,typeInteger,&descriptor_type,
&error,sizeof(error),&actualSize);
(void) AEDisposeDesc(&event_descriptor);
(void) AEDisposeDesc(&event);
if (reply.descriptorType != NULL)
AEDisposeDesc(&reply);
return((OSErr) error);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSLaunchApplicationCore() launches the Ghostscript command.
%
%
*/
static OSErr MacGSLaunchApplicationCore(ssize_t flags)
{
FSSpec
file_info;
LaunchParamBlockRec
launch_info;
OSErr
error;
if (!SearchForFile('gsVR','APPL',&file_info,1))
return(-43);
launch_info.launchBlockID=extendedBlock;
launch_info.launchEPBLength=extendedBlockLen;
launch_info.launchFileFlags=0;
launch_info.launchControlFlags=launchContinue+launchNoFileFlags+flags;
launch_info.launchAppSpec=(&file_info);
launch_info.launchAppParameters=nil;
error=LaunchApplication(&launch_info);
return(error);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M a c G S L a u n c h A p p l i c a t i o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSLaunchApplication() launches the Ghostscript command.
%
%
*/
static OSErr MacGSLaunchApplication(void)
{
return(MacGSLaunchApplicationCore(launchDontSwitch));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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 %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSLaunchApplicationToFront() moves the Ghostscript window to the front.
%
%
*/
static OSErr MacGSLaunchApplicationToFront(void)
{
return(MacGSLaunchApplicationCore(0));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M a c G S Q u i t A p p l i c a t i o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSQuitApplication() quits the Ghostscript application.
%
%
*/
static void MacGSQuitApplication(void)
{
AEAddressDesc
event_descriptor;
AEDesc
reply = {typeNull, NULL};
AppleEvent
event = {typeNull, NULL};
OSType
id = 'GPLT';
/*
Send the Apple Event.
*/
(void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
(void) AECreateAppleEvent(typeAppleEvent,kAEQuitApplication,
&event_descriptor,-1,kAnyTransactionID,&event);
(void) AESend(&event,&reply,kAENoReply,kAENormalPriority,kNoTimeOut,NULL,
NULL);
/*
Clean up and exit.
*/
(void) AEDisposeDesc(&event_descriptor);
(void) AEDisposeDesc(&event);
if (reply.descriptorType != NULL)
AEDisposeDesc(&reply);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M a c G S S e t W o r k i n g F o l d e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MacGSSetWorkingFolder() set the Ghostscript working folder.
%
%
*/
static OSErr MacGSSetWorkingFolder(char *directory)
{
AEDesc
application_descriptor,
event_descriptor,
object,
path_descriptor,
type_descriptor,
reply;
AppleEvent
event;
DescType
folder_type = 'wfdr';
OSErr
error;
OSType
id = 'GPLT';
/*
Send the Apple Event.
*/
AECreateDesc(typeNull,NULL,0,&application_descriptor);
AECreateDesc(typeChar,directory,strlen(directory),&path_descriptor);
(void) AECreateDesc(typeType,&folder_type,sizeof(DescType),&type_descriptor);
CreateObjSpecifier(cProperty,&application_descriptor,formPropertyID,
&type_descriptor,0,&object);
(void) AECreateDesc(typeApplSignature,&id,sizeof(id),&event_descriptor);
(void) AECreateAppleEvent(kAECoreSuite,kAESetData,&event_descriptor,-1,
kAnyTransactionID,&event);
(void) AEPutParamDesc(&event,keyDirectObject,&object);
(void) AEPutParamDesc(&event,keyAEData,&path_descriptor);
error=AESend(&event,&reply,kAENoReply+kAENeverInteract,kAENormalPriority,
kNoTimeOut,NULL,NULL);
(void) AEDisposeDesc(&event);
(void) AEDisposeDesc(&event_descriptor);
(void) AEDisposeDesc(&object);
(void) AEDisposeDesc(&type_descriptor);
(void) AEDisposeDesc(&path_descriptor);
(void) AEDisposeDesc(&application_descriptor);
return(error);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M A C S e t E r r o r H o o k %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACSetErrorHook sets a callback function which is called if any error
% occurs within ImageMagick.
%
% The format of the MACSetErrorHook method is:
%
% int MACSetErrorHook(MACErrorHookPtr hook)
%
% A description of each parameter follows:
%
% o hook: This function pointer is the callback function.
%
%
*/
MagickExport void MACSetErrorHook(MACErrorHookPtr hook)
{
/*
We forget any previously set exception.hook.
*/
exception.hook=hook;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M A C S e t E v e n t H o o k %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACSetEventHook sets a callback function which is called every time
% ImageMagick likes to release the processor.
%
% The format of the MACSetEventHook method is:
%
% int MACSetEventHook(MACEventHookPtr hook)
%
% A description of each parameter follows:
%
% o hook: This function pointer is the callback function.
%
%
*/
MagickExport void MACSetEventHook(MACEventHookPtr hook)
{
/*
We forget any previously set event hook.
*/
event_hook=hook;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M A C S y s t e m C o m m a n d %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method MACSystemCommand executes the specified command and waits until it
% terminates. The returned value is the exit status of the command.
%
% The format of the MACSystemCommand method is:
%
% int MACSystemCommand(MagickFalse,const char * command)
%
% A description of each parameter follows:
%
% o command: This string is the command to execute.
%
*/
MagickExport int MACSystemCommand(const char * command)
{
/*
We only know how to launch Ghostscript.
*/
if (MacGSLaunchApplicationToFront())
return(-1);
return(MacGSExecuteCommand(command,strlen(command)));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M A C W a r n i n g H a n d l e r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MACWarningHandler() displays a warning reason.
%
% The format of the MACWarningHandler method is:
%
+ void MACWarningHandler(const ExceptionType warning,const char *reason,
% const char *description)
%
% A description of each parameter follows:
%
% o warning: Specifies the numeric warning category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
%
*/
MagickExport void MACWarningHandler(const ExceptionType warning,
const char *reason,const char *description)
{
char
buffer[1664];
if (reason == (char *) NULL)
return;
if (description == (char *) NULL)
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s.\n",GetClientName(),
reason);
else
(void) FormatLocaleString(buffer,MaxTextExtent,"%s: %s (%s).\n",
GetClientName(),reason,description);
#if defined(DISABLE_SIOUX)
if(exception.hook != (MACErrorHookPtr) NULL)
exception.hook(warning, buffer);
#else
(void)warning;
puts(buffer);
#endif
}
#if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% o p e n d i r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% opendir() opens the directory named by filename and associates a directory
% stream with it.
%
% The format of the opendir method is:
%
% MagickExport DIR *opendir(char *path)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
%
*/
MagickExport DIR *opendir(const char *path)
{
Str255 pathname;
CInfoPBRec
search_info;
DIR
*entry;
int
error;
search_info.hFileInfo.ioNamePtr=0;
if ((path != (char *) NULL) || (*path != '\0'))
if ((path[0] != '.') || (path[1] != '\0'))
{
c2pstrcpy(pathname,path);
search_info.hFileInfo.ioNamePtr=pathname;
}
search_info.hFileInfo.ioCompletion=0;
search_info.hFileInfo.ioVRefNum=0;
search_info.hFileInfo.ioFDirIndex=0;
search_info.hFileInfo.ioDirID=0;
error=PBGetCatInfoSync(&search_info);
if (error != noErr)
{
errno=error;
return((DIR *) NULL);
}
entry=(DIR *) AcquireMagickMemory(sizeof(DIR));
if (entry == (DIR *) NULL)
return((DIR *) NULL);
entry->d_VRefNum=search_info.hFileInfo.ioVRefNum;
entry->d_DirID=search_info.hFileInfo.ioDirID;
entry->d_index=1;
return(entry);
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% P r o c e s s P e n d i n g E v e n t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ProcessPendingEvents() processes any pending events. This prevents
% ImageMagick from monopolizing the processor.
%
% The format of the ProcessPendingEvents method is:
%
% ProcessPendingEvents(text)
%
% A description of each parameter follows:
%
% o text: A character string representing the current process.
%
%
*/
MagickExport void ProcessPendingEvents(const char *text)
{
#if defined(DISABLE_SIOUX)
if (event_hook != (MACEventHookPtr) NULL)
event_hook(text);
#else
static const char
*mark = (char *) NULL;
EventRecord
event;
while (WaitNextEvent(everyEvent,&event,0L,nil))
SIOUXHandleOneEvent(&event);
if (isatty(STDIN_FILENO) && (text != mark))
{
(void) puts(text);
mark=text;
}
#endif
}
#if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% r e a d d i r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% readdir() returns a pointer to a structure representing the directory entry
% at the current position in the directory stream to which entry refers.
%
% The format of the readdir
%
% struct dirent *readdir(DIR *entry)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
%
*/
MagickExport struct dirent *readdir(DIR *entry)
{
CInfoPBRec
search_info;
int
error;
static struct dirent
dir_entry;
static unsigned char
pathname[MaxTextExtent];
if (entry == (DIR *) NULL)
return((struct dirent *) NULL);
search_info.hFileInfo.ioCompletion=0;
search_info.hFileInfo.ioNamePtr=pathname;
search_info.hFileInfo.ioVRefNum=0;
search_info.hFileInfo.ioFDirIndex=entry->d_index;
search_info.hFileInfo.ioDirID=entry->d_DirID;
error=PBGetCatInfoSync(&search_info);
if (error != noErr)
{
errno=error;
return((struct dirent *) NULL);
}
entry->d_index++;
p2cstrcpy(dir_entry.d_name,search_info.hFileInfo.ioNamePtr);
dir_entry.d_namlen=strlen(dir_entry.d_name);
return(&dir_entry);
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e a d P I C T I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadPICTImage() reads an Apple Macintosh QuickDraw/PICT image file using
% MacOS QuickDraw methods and returns it. It allocates the memory necessary
% for the new Image structure and returns a pointer to the new image.
%
% This method was written and contributed by spd@daphne.cps.unizar.es
% (feel free to copy and use it as you want. No warranty).
%
% The format of the ReadPICTImage method is:
%
% Image *ReadPICTImage(const ImageInfo *image_info,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: Method ReadPICTImage returns a pointer to the image after
% reading. A null image is returned if there is a memory shortage or
% if the image cannot be read.
%
% o image_info: the image info..
%
% o exception: return any errors or warnings in this structure.
%
*/
static inline size_t MagickMax(const size_t x,const size_t y)
{
if (x > y)
return(x);
return(y);
}
MagickExport Image *ReadPICTImage(const ImageInfo *image_info,
ExceptionInfo *exception)
{
#define PICTHeaderSize 512
CodecType
codec;
GDHandle
device;
GWorldPtr
graphic_world,
port;
Image
*image;
int
depth,
status;
MagickBooleanType
proceed,
status;
PicHandle
picture_handle;
PictInfo
picture_info;
QDErr
theErr = noErr;
Rect
rectangle;
RGBColor
Pixel;
short
colormap_id;
ssize_t
y;
/*
Open image file.
*/
image=AcquireImage(image_info);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
return(NULL);
picture_handle=(PicHandle) NewHandle(MagickMax(GetBlobSize(image)-
PICTHeaderSize,PICTHeaderSize));
if (picture_handle == nil)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
HLock((Handle) picture_handle);
(void) ReadBlob(image,PICTHeaderSize,*(unsigned char **) picture_handle);
status=ReadBlob(image,GetBlobSize(image)-PICTHeaderSize,*(unsigned char **)
picture_handle);
if (status == MagickFalse)
{
DisposeHandle((Handle) picture_handle);
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
}
GetGWorld(&port,&device);
theErr=NewGWorld(&graphic_world,0,&(**picture_handle).picFrame,nil,nil,
useTempMem | keepLocal);
if ((theErr != noErr) && (graphic_world == nil))
{
DisposeHandle((Handle) picture_handle);
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
}
HUnlock((Handle) picture_handle);
SetGWorld(graphic_world,nil);
theErr=GetPictInfo(picture_handle,&picture_info,0,1,systemMethod,0);
if (theErr != noErr)
{
DisposeGWorld(graphic_world);
DisposeHandle((Handle) picture_handle);
ThrowReaderException(CorruptImageError,"UnableToReadImageData");
}
#if defined(DISABLE_QUICKTIME)
codec='unkn';
colormap_id=(-1);
depth=picture_info.depth;
#else
BottleneckTest(picture_handle,&codec,&depth,&colormap_id);
#endif
switch (codec)
{
case 'rpza':
case 'jpeg':
case 'rle ':
case 'raw ':
case 'smc ':
{
if (depth > 200)
{
depth-=32;
picture_info.theColorTable=GetCTable(colormap_id);
}
break;
}
default:
{
depth=picture_info.depth;
if (depth <= 8)
(void) GetPictInfo(picture_handle,&picture_info,returnColorTable,
(short) (1 << picture_info.depth),systemMethod,0);
break;
}
}
image->x_resolution=(picture_info.hRes) >> 16;
image->y_resolution=(picture_info.vRes) >> 16;
image->units=PixelsPerInchResolution;
image->columns=picture_info.sourceRect.right-picture_info.sourceRect.left;
image->rows=picture_info.sourceRect.bottom-picture_info.sourceRect.top;
if ((depth <= 8) && ((*(picture_info.theColorTable))->ctSize != 0))
{
size_t
number_colors;
/*
Colormapped PICT image.
*/
number_colors=(*(picture_info.theColorTable))->ctSize;
if (!AcquireImageColormap(image,number_colors))
{
if (picture_info.theColorTable != nil)
DisposeHandle((Handle) picture_info.theColorTable);
DisposeGWorld(graphic_world);
DisposeHandle((Handle) picture_handle);
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
}
for (x=0; x < image->colors; x++)
{
image->colormap[x].red=
(*(picture_info.theColorTable))->ctTable[x].rgb.red;
image->colormap[x].green=
(*(picture_info.theColorTable))->ctTable[x].rgb.green;
image->colormap[x].blue=
(*(picture_info.theColorTable))->ctTable[x].rgb.blue;
}
}
SetRect(&rectangle,0,0,image->columns,image->rows);
(void) UpdateGWorld(&graphic_world,depth,&rectangle,
picture_info.theColorTable,nil,0);
LockPixels(GetGWorldPixMap(graphic_world)); /*->portPixMap); */
EraseRect(&rectangle);
DrawPicture(picture_handle,&rectangle);
if ((depth <= 8) && (colormap_id == -1))
{
DisposeHandle((Handle) picture_info.theColorTable);
picture_info.theColorTable=nil;
}
DisposeHandle((Handle) picture_handle);
/*
Convert PICT pixels to pixel packets.
*/
for (y=0; y < image->rows; y++)
{
IndexPacket
*restrict indexes;
ssize_t
x;
PixelPacket
*restrict q;
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (PixelPacket *) NULL)
break;
indexes=GetAuthenticIndexQueue(image);
for (x=0; x < image->columns; x++)
{
GetCPixel(x,y,&Pixel);
SetPixelRed(q,ScaleCharToQuantum(Pixel.red & 0xff));
SetPixelGreen(q,ScaleCharToQuantum(Pixel.green & 0xff));
SetPixelBlue(q,ScaleCharToQuantum(Pixel.blue & 0xff));
if (image->storage_class == PseudoClass)
SetPixelIndex(indexes+x,Color2Index(&Pixel));
q++;
}
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
proceed=SetImageProgress(image,LoadImageTag,y,image->rows);
if (proceed == MagickFalse)
break;
}
UnlockPixels(GetGWorldPixMap(graphic_world));
SetGWorld(port,device);
if (picture_info.theColorTable != nil)
DisposeHandle((Handle) picture_info.theColorTable);
DisposeGWorld(graphic_world);
(void) CloseBlob(image);
return(image);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e a r c h F o r F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SearchForFile() searches for a file.
%
%
*/
static Boolean SearchForFile(OSType creator_type,OSType file_type,FSSpec *file,
short count)
{
char
*buffer;
CInfoPBRec
search1_info,
search2_info;
FSSpec
application;
HParamBlockRec
parameter_info;
OSErr
error;
ProcessInfoRec
application_info;
ProcessSerialNumber
serial_number;
ssize_t
buffer_size = MagickMinBufferExtent;
serial_number.lowLongOfPSN=kCurrentProcess;
serial_number.highLongOfPSN=0;
application_info.processInfoLength=sizeof(ProcessInfoRec);
application_info.processName=NULL;
application_info.processAppSpec=(&application);
GetProcessInformation(&serial_number,&application_info);
buffer=NewPtr(buffer_size);
if (buffer == (char *) NULL)
return(false);
parameter_info.csParam.ioCompletion=NULL;
parameter_info.csParam.ioNamePtr=NULL;
parameter_info.csParam.ioVRefNum=application.vRefNum;
parameter_info.csParam.ioMatchPtr=file;
parameter_info.csParam.ioReqMatchCount=count;
parameter_info.csParam.ioSearchBits=fsSBFlFndrInfo;
parameter_info.csParam.ioSearchInfo1=&search1_info;
parameter_info.csParam.ioSearchInfo2=&search2_info;
parameter_info.csParam.ioSearchTime=0;
parameter_info.csParam.ioCatPosition.initialize=0;
parameter_info.csParam.ioOptBuffer=buffer;
parameter_info.csParam.ioOptBufSize=buffer_size;
search1_info.hFileInfo.ioNamePtr=NULL;
search1_info.hFileInfo.ioFlFndrInfo.fdType=file_type;
search1_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
search1_info.hFileInfo.ioFlAttrib=0;
search1_info.hFileInfo.ioFlParID=0;
search2_info=search1_info;
search2_info.hFileInfo.ioFlAttrib=0x10;
search2_info.hFileInfo.ioFlFndrInfo.fdCreator=creator_type;
search2_info.hFileInfo.ioFlFndrInfo.fdType=(-1);
search2_info.hFileInfo.ioFlFndrInfo.fdFlags=0;
search2_info.hFileInfo.ioFlFndrInfo.fdLocation.h=0;
search2_info.hFileInfo.ioFlFndrInfo.fdLocation.v=0;
search2_info.hFileInfo.ioFlFndrInfo.fdFldr=0;
search2_info.hFileInfo.ioFlParID=0;
error=PBCatSearchSync((CSParamPtr) &parameter_info);
DisposePtr(buffer);
if (parameter_info.csParam.ioReqMatchCount ==
parameter_info.csParam.ioActMatchCount)
error=eofErr;
if (parameter_info.csParam.ioActMatchCount == 0)
error=0;
return(error == eofErr);
}
#if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% s e e k d i r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% seekdir() sets the position of the next readdir() operation on the directory
% stream.
%
% The format of the seekdir method is:
%
% void seekdir(DIR *entry,ssize_t position)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
% o position: specifies the position associated with the directory
% stream.
%
%
%
*/
MagickExport void seekdir(DIR *entry,ssize_t position)
{
assert(entry != (DIR *) NULL);
entry->d_index=position;
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S e t A p p l i c a t i o n T y p e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SetApplicationType() sets the file type of an image.
%
% The format of the SetApplicationType method is:
%
% void SetApplicationType(const char *filename,const char *magick,
% OSType application)
%
% A description of each parameter follows:
%
% o filename: Specifies the name of the file.
%
% o filename: Specifies the file type.
%
% o application: Specifies the type of the application.
%
*/
static inline size_t MagickMin(const size_t x,const size_t y)
{
if (x < y)
return(x);
return(y);
}
MagickExport void SetApplicationType(const char *filename,const char *magick,
OSType application)
{
FSSpec
file_specification;
OSType
filetype;
Str255
name;
assert(filename != (char *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
assert(magick != (const char *) NULL);
filetype=' ';
(void) CopyMagickString((char *) &filetype,magick,MagickMin(strlen(magick),
4));
if (LocaleCompare(magick,"JPG") == 0)
(void) CopyMagickString((char *) &filetype,"JPEG",MaxTextExtent);
c2pstrcpy(name,filename);
FSMakeFSSpec(0,0,name,&file_specification);
FSpCreate(&file_specification,application,filetype,smSystemScript);
}
#if !defined(MAGICKCORE_POSIX_SUPPORT_VERSION)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% t e l l d i r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Method telldir returns the current location associated with the
% named directory stream.
%
% The format of the telldir method is:
%
% telldir(DIR *entry)
%
% A description of each parameter follows:
%
% o entry: Specifies a pointer to a DIR structure.
%
%
*/
MagickExport ssize_t telldir(DIR *entry)
{
return(entry->d_index);
}
#endif
#endif