jmemmac.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * jmemmac.c
  3. *
  4. * Copyright (C) 1992-1997, Thomas G. Lane.
  5. * This file is part of the Independent JPEG Group's software.
  6. * For conditions of distribution and use, see the accompanying README file.
  7. *
  8. * jmemmac.c provides an Apple Macintosh implementation of the system-
  9. * dependent portion of the JPEG memory manager.
  10. *
  11. * If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the
  12. * JPEG_INTERNALS part of jconfig.h.
  13. *
  14. * jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr
  15. * instead of malloc and free. It accurately determines the amount of
  16. * memory available by using CompactMem. Notice that if left to its
  17. * own devices, this code can chew up all available space in the
  18. * application's zone, with the exception of the rather small "slop"
  19. * factor computed in jpeg_mem_available(). The application can ensure
  20. * that more space is left over by reducing max_memory_to_use.
  21. *
  22. * Large images are swapped to disk using temporary files and System 7.0+'s
  23. * temporary folder functionality.
  24. *
  25. * Note that jmemmac.c depends on two features of MacOS that were first
  26. * introduced in System 7: FindFolder and the FSSpec-based calls.
  27. * If your application uses jmemmac.c and is run under System 6 or earlier,
  28. * and the jpeg library decides it needs a temporary file, it will abort,
  29. * printing error messages about requiring System 7. (If no temporary files
  30. * are created, it will run fine.)
  31. *
  32. * If you want to use jmemmac.c in an application that might be used with
  33. * System 6 or earlier, then you should remove dependencies on FindFolder
  34. * and the FSSpec calls. You will need to replace FindFolder with some
  35. * other mechanism for finding a place to put temporary files, and you
  36. * should replace the FSSpec calls with their HFS equivalents:
  37. *
  38. * FSpDelete -> HDelete
  39. * FSpGetFInfo -> HGetFInfo
  40. * FSpCreate -> HCreate
  41. * FSpOpenDF -> HOpen *** Note: not HOpenDF ***
  42. * FSMakeFSSpec -> (fill in spec by hand.)
  43. *
  44. * (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen,
  45. * which is on all HFS macs. HOpenDF is a System 7 addition which avoids the
  46. * ages-old problem of names starting with a period.)
  47. *
  48. * Contributed by Sam Bushell ([email protected]) and
  49. * Dan Gildor ([email protected]).
  50. */
  51. #if defined(__APPLE__)
  52. #define JPEG_INTERNALS
  53. #include "jinclude.h"
  54. #include "jpeglib.h"
  55. #include "jmemsys.h" /* import the system-dependent declarations */
  56. #ifndef USE_MAC_MEMMGR /* make sure user got configuration right */
  57. You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */
  58. #endif
  59. #include <Memory.h> /* we use the MacOS memory manager */
  60. #include <Files.h> /* we use the MacOS File stuff */
  61. #include <Folders.h> /* we use the MacOS HFS stuff */
  62. #include <Script.h> /* for smSystemScript */
  63. #include <Gestalt.h> /* we use Gestalt to test for specific functionality */
  64. #ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
  65. #define TEMP_FILE_NAME "JPG%03d.TMP"
  66. #endif
  67. static int next_file_num; /* to distinguish among several temp files */
  68. /*
  69. * Memory allocation and freeing are controlled by the MacOS library
  70. * routines NewPtr() and DisposePtr(), which allocate fixed-address
  71. * storage. Unfortunately, the IJG library isn't smart enough to cope
  72. * with relocatable storage.
  73. */
  74. GLOBAL(void *)
  75. jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
  76. {
  77. return (void *) NewPtr(sizeofobject);
  78. }
  79. GLOBAL(void)
  80. jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
  81. {
  82. DisposePtr((Ptr) object);
  83. }
  84. /*
  85. * "Large" objects are treated the same as "small" ones.
  86. * NB: we include FAR keywords in the routine declarations simply for
  87. * consistency with the rest of the IJG code; FAR should expand to empty
  88. * on rational architectures like the Mac.
  89. */
  90. GLOBAL(void FAR *)
  91. jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
  92. {
  93. return (void FAR *) NewPtr(sizeofobject);
  94. }
  95. GLOBAL(void)
  96. jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
  97. {
  98. DisposePtr((Ptr) object);
  99. }
  100. /*
  101. * This routine computes the total memory space available for allocation.
  102. */
  103. GLOBAL(long)
  104. jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
  105. long max_bytes_needed, long already_allocated)
  106. {
  107. long limit = cinfo->mem->max_memory_to_use - already_allocated;
  108. long slop, mem;
  109. /* Don't ask for more than what application has told us we may use */
  110. if (max_bytes_needed > limit && limit > 0)
  111. max_bytes_needed = limit;
  112. /* Find whether there's a big enough free block in the heap.
  113. * CompactMem tries to create a contiguous block of the requested size,
  114. * and then returns the size of the largest free block (which could be
  115. * much more or much less than we asked for).
  116. * We add some slop to ensure we don't use up all available memory.
  117. */
  118. slop = max_bytes_needed / 16 + 32768L;
  119. mem = CompactMem(max_bytes_needed + slop) - slop;
  120. if (mem < 0)
  121. mem = 0; /* sigh, couldn't even get the slop */
  122. /* Don't take more than the application says we can have */
  123. if (mem > limit && limit > 0)
  124. mem = limit;
  125. return mem;
  126. }
  127. /*
  128. * Backing store (temporary file) management.
  129. * Backing store objects are only used when the value returned by
  130. * jpeg_mem_available is less than the total space needed. You can dispense
  131. * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  132. */
  133. METHODDEF(void)
  134. read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  135. void FAR * buffer_address,
  136. long file_offset, long byte_count)
  137. {
  138. long bytes = byte_count;
  139. long retVal;
  140. if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
  141. ERREXIT(cinfo, JERR_TFILE_SEEK);
  142. retVal = FSRead ( info->temp_file, &bytes,
  143. (unsigned char *) buffer_address );
  144. if ( retVal != noErr || bytes != byte_count )
  145. ERREXIT(cinfo, JERR_TFILE_READ);
  146. }
  147. METHODDEF(void)
  148. write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  149. void FAR * buffer_address,
  150. long file_offset, long byte_count)
  151. {
  152. long bytes = byte_count;
  153. long retVal;
  154. if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
  155. ERREXIT(cinfo, JERR_TFILE_SEEK);
  156. retVal = FSWrite ( info->temp_file, &bytes,
  157. (unsigned char *) buffer_address );
  158. if ( retVal != noErr || bytes != byte_count )
  159. ERREXIT(cinfo, JERR_TFILE_WRITE);
  160. }
  161. METHODDEF(void)
  162. close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
  163. {
  164. FSClose ( info->temp_file );
  165. FSpDelete ( &(info->tempSpec) );
  166. }
  167. /*
  168. * Initial opening of a backing-store object.
  169. *
  170. * This version uses FindFolder to find the Temporary Items folder,
  171. * and puts the temporary file in there.
  172. */
  173. GLOBAL(void)
  174. jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  175. long total_bytes_needed)
  176. {
  177. short tmpRef, vRefNum;
  178. long dirID;
  179. FInfo finderInfo;
  180. FSSpec theSpec;
  181. Str255 fName;
  182. OSErr osErr;
  183. long gestaltResponse = 0;
  184. /* Check that FSSpec calls are available. */
  185. osErr = Gestalt( gestaltFSAttr, &gestaltResponse );
  186. if ( ( osErr != noErr )
  187. || !( gestaltResponse & (1<<gestaltHasFSSpecCalls) ) )
  188. ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required");
  189. /* TO DO: add a proper error message to jerror.h. */
  190. /* Check that FindFolder is available. */
  191. osErr = Gestalt( gestaltFindFolderAttr, &gestaltResponse );
  192. if ( ( osErr != noErr )
  193. || !( gestaltResponse & (1<<gestaltFindFolderPresent) ) )
  194. ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required.");
  195. /* TO DO: add a proper error message to jerror.h. */
  196. osErr = FindFolder ( kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
  197. &vRefNum, &dirID );
  198. if ( osErr != noErr )
  199. ERREXITS(cinfo, JERR_TFILE_CREATE, "- temporary items folder unavailable");
  200. /* TO DO: Try putting the temp files somewhere else. */
  201. /* Keep generating file names till we find one that's not in use */
  202. for (;;) {
  203. next_file_num++; /* advance counter */
  204. sprintf(info->temp_name, TEMP_FILE_NAME, next_file_num);
  205. strcpy ( (Ptr)fName+1, info->temp_name );
  206. *fName = strlen (info->temp_name);
  207. osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec );
  208. if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr )
  209. break;
  210. }
  211. osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript );
  212. if ( osErr != noErr )
  213. ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
  214. osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) );
  215. if ( osErr != noErr )
  216. ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
  217. info->tempSpec = theSpec;
  218. info->read_backing_store = read_backing_store;
  219. info->write_backing_store = write_backing_store;
  220. info->close_backing_store = close_backing_store;
  221. TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
  222. }
  223. /*
  224. * These routines take care of any system-dependent initialization and
  225. * cleanup required.
  226. */
  227. GLOBAL(long)
  228. jpeg_mem_init (j_common_ptr cinfo)
  229. {
  230. next_file_num = 0;
  231. /* max_memory_to_use will be initialized to FreeMem()'s result;
  232. * the calling application might later reduce it, for example
  233. * to leave room to invoke multiple JPEG objects.
  234. * Note that FreeMem returns the total number of free bytes;
  235. * it may not be possible to allocate a single block of this size.
  236. */
  237. return FreeMem();
  238. }
  239. GLOBAL(void)
  240. jpeg_mem_term (j_common_ptr cinfo)
  241. {
  242. /* no work */
  243. }
  244. #endif