jmemmac.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. #define JPEG_INTERNALS
  52. #include "jinclude.h"
  53. #include "jpeglib.h"
  54. #include "jmemsys.h" /* import the system-dependent declarations */
  55. #ifndef USE_MAC_MEMMGR /* make sure user got configuration right */
  56. You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */
  57. #endif
  58. #include <Memory.h> /* we use the MacOS memory manager */
  59. #include <Files.h> /* we use the MacOS File stuff */
  60. #include <Folders.h> /* we use the MacOS HFS stuff */
  61. #include <Script.h> /* for smSystemScript */
  62. #include <Gestalt.h> /* we use Gestalt to test for specific functionality */
  63. #ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
  64. #define TEMP_FILE_NAME "JPG%03d.TMP"
  65. #endif
  66. static int next_file_num; /* to distinguish among several temp files */
  67. /*
  68. * Memory allocation and freeing are controlled by the MacOS library
  69. * routines NewPtr() and DisposePtr(), which allocate fixed-address
  70. * storage. Unfortunately, the IJG library isn't smart enough to cope
  71. * with relocatable storage.
  72. */
  73. GLOBAL(void *)
  74. jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
  75. {
  76. return (void *) NewPtr(sizeofobject);
  77. }
  78. GLOBAL(void)
  79. jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
  80. {
  81. DisposePtr((Ptr) object);
  82. }
  83. /*
  84. * "Large" objects are treated the same as "small" ones.
  85. * NB: we include FAR keywords in the routine declarations simply for
  86. * consistency with the rest of the IJG code; FAR should expand to empty
  87. * on rational architectures like the Mac.
  88. */
  89. GLOBAL(void FAR *)
  90. jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
  91. {
  92. return (void FAR *) NewPtr(sizeofobject);
  93. }
  94. GLOBAL(void)
  95. jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
  96. {
  97. DisposePtr((Ptr) object);
  98. }
  99. /*
  100. * This routine computes the total memory space available for allocation.
  101. */
  102. GLOBAL(long)
  103. jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
  104. long max_bytes_needed, long already_allocated)
  105. {
  106. long limit = cinfo->mem->max_memory_to_use - already_allocated;
  107. long slop, mem;
  108. /* Don't ask for more than what application has told us we may use */
  109. if (max_bytes_needed > limit && limit > 0)
  110. max_bytes_needed = limit;
  111. /* Find whether there's a big enough free block in the heap.
  112. * CompactMem tries to create a contiguous block of the requested size,
  113. * and then returns the size of the largest free block (which could be
  114. * much more or much less than we asked for).
  115. * We add some slop to ensure we don't use up all available memory.
  116. */
  117. slop = max_bytes_needed / 16 + 32768L;
  118. mem = CompactMem(max_bytes_needed + slop) - slop;
  119. if (mem < 0)
  120. mem = 0; /* sigh, couldn't even get the slop */
  121. /* Don't take more than the application says we can have */
  122. if (mem > limit && limit > 0)
  123. mem = limit;
  124. return mem;
  125. }
  126. /*
  127. * Backing store (temporary file) management.
  128. * Backing store objects are only used when the value returned by
  129. * jpeg_mem_available is less than the total space needed. You can dispense
  130. * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  131. */
  132. METHODDEF(void)
  133. read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  134. void FAR * buffer_address,
  135. long file_offset, long byte_count)
  136. {
  137. long bytes = byte_count;
  138. long retVal;
  139. if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
  140. ERREXIT(cinfo, JERR_TFILE_SEEK);
  141. retVal = FSRead ( info->temp_file, &bytes,
  142. (unsigned char *) buffer_address );
  143. if ( retVal != noErr || bytes != byte_count )
  144. ERREXIT(cinfo, JERR_TFILE_READ);
  145. }
  146. METHODDEF(void)
  147. write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  148. void FAR * buffer_address,
  149. long file_offset, long byte_count)
  150. {
  151. long bytes = byte_count;
  152. long retVal;
  153. if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
  154. ERREXIT(cinfo, JERR_TFILE_SEEK);
  155. retVal = FSWrite ( info->temp_file, &bytes,
  156. (unsigned char *) buffer_address );
  157. if ( retVal != noErr || bytes != byte_count )
  158. ERREXIT(cinfo, JERR_TFILE_WRITE);
  159. }
  160. METHODDEF(void)
  161. close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
  162. {
  163. FSClose ( info->temp_file );
  164. FSpDelete ( &(info->tempSpec) );
  165. }
  166. /*
  167. * Initial opening of a backing-store object.
  168. *
  169. * This version uses FindFolder to find the Temporary Items folder,
  170. * and puts the temporary file in there.
  171. */
  172. GLOBAL(void)
  173. jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  174. long total_bytes_needed)
  175. {
  176. short tmpRef, vRefNum;
  177. long dirID;
  178. FInfo finderInfo;
  179. FSSpec theSpec;
  180. Str255 fName;
  181. OSErr osErr;
  182. long gestaltResponse = 0;
  183. /* Check that FSSpec calls are available. */
  184. osErr = Gestalt( gestaltFSAttr, &gestaltResponse );
  185. if ( ( osErr != noErr )
  186. || !( gestaltResponse & (1<<gestaltHasFSSpecCalls) ) )
  187. ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required");
  188. /* TO DO: add a proper error message to jerror.h. */
  189. /* Check that FindFolder is available. */
  190. osErr = Gestalt( gestaltFindFolderAttr, &gestaltResponse );
  191. if ( ( osErr != noErr )
  192. || !( gestaltResponse & (1<<gestaltFindFolderPresent) ) )
  193. ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required.");
  194. /* TO DO: add a proper error message to jerror.h. */
  195. osErr = FindFolder ( kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
  196. &vRefNum, &dirID );
  197. if ( osErr != noErr )
  198. ERREXITS(cinfo, JERR_TFILE_CREATE, "- temporary items folder unavailable");
  199. /* TO DO: Try putting the temp files somewhere else. */
  200. /* Keep generating file names till we find one that's not in use */
  201. for (;;) {
  202. next_file_num++; /* advance counter */
  203. sprintf(info->temp_name, TEMP_FILE_NAME, next_file_num);
  204. strcpy ( (Ptr)fName+1, info->temp_name );
  205. *fName = strlen (info->temp_name);
  206. osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec );
  207. if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr )
  208. break;
  209. }
  210. osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript );
  211. if ( osErr != noErr )
  212. ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
  213. osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) );
  214. if ( osErr != noErr )
  215. ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
  216. info->tempSpec = theSpec;
  217. info->read_backing_store = read_backing_store;
  218. info->write_backing_store = write_backing_store;
  219. info->close_backing_store = close_backing_store;
  220. TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
  221. }
  222. /*
  223. * These routines take care of any system-dependent initialization and
  224. * cleanup required.
  225. */
  226. GLOBAL(long)
  227. jpeg_mem_init (j_common_ptr cinfo)
  228. {
  229. next_file_num = 0;
  230. /* max_memory_to_use will be initialized to FreeMem()'s result;
  231. * the calling application might later reduce it, for example
  232. * to leave room to invoke multiple JPEG objects.
  233. * Note that FreeMem returns the total number of free bytes;
  234. * it may not be possible to allocate a single block of this size.
  235. */
  236. return FreeMem();
  237. }
  238. GLOBAL(void)
  239. jpeg_mem_term (j_common_ptr cinfo)
  240. {
  241. /* no work */
  242. }