home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Bitmap / jpeg-6a / jmemod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-17  |  7.6 KB  |  320 lines  |  [TEXT/MPS ]

  1. /*========================================================================================
  2. //
  3. //    File:                jmemod.c
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Author:                Mark Lanett
  7. //
  8. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //    Macintosh OpenDoc implementation of the system-dependent portion of 
  11. //    the JPEG memory manager. jmemmac.c isn't suitable because
  12. //    the application heap is too small.
  13. //    
  14. //    6/5/96 mlanett Written
  15. //    
  16. //    Note: This uses "temporary" memory for all memory allocations. Backing
  17. //    store uses Macintosh file system routines and the boot volume's
  18. //    temporary directory. Based on jmemmac.c, but mostly rewritten.
  19. //======================================================================================*/
  20.  
  21. #define JPEG_INTERNALS
  22. #include "jinclude.h"
  23. #include "jpeglib.h"
  24. #include "jmemsys.h"
  25.  
  26. #include <LowMem.h>
  27. #include <Memory.h>
  28.  
  29. #include <Files.h>
  30. #include <Folders.h>
  31. #include <TextUtils.h>
  32.  
  33. static Boolean gHaveTemporaryZone = false;
  34. static THz gTemporaryZone;
  35.  
  36. /*#define DEBUG 1*/
  37.  
  38. #ifdef DEBUG
  39. long gAllocationTotal = 0;
  40. long gAllocationCount = 0;
  41. #endif
  42.  
  43. /*
  44.     Use temporary memory. Allocating locked blocks in that heap is kind
  45.     of rude, but the IJG code can't deal with handles, and decoding is
  46.     a short-term process anyway.
  47. */
  48.  
  49. GLOBAL(void *)
  50. jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
  51. {
  52.     void* memory;
  53.     
  54.     THz currentZone = LMGetTheZone();
  55.     SetZone (gTemporaryZone);
  56.     memory = NewPtr (sizeofobject);
  57.     SetZone (currentZone);
  58.     
  59. #ifdef DEBUG
  60.     if (memory) {
  61.         gAllocationTotal += sizeofobject;
  62.         gAllocationCount ++;
  63.     }
  64. #endif
  65.     
  66.     return memory;
  67. }
  68.  
  69. GLOBAL(void)
  70. jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
  71. {
  72.     /* Not sure if DisposePtr is zone-aware like DisposeHandle */
  73.     THz currentZone = LMGetTheZone();
  74.     SetZone (gTemporaryZone);
  75.     DisposePtr ((Ptr)object);
  76.     SetZone (currentZone);
  77.     
  78. #ifdef DEBUG
  79.     if (object) {
  80.         gAllocationTotal -= sizeofobject;
  81.         gAllocationCount --;
  82.     }
  83. #endif
  84. }
  85.  
  86. /*
  87.     "Large" and "small" are the same; just call the "small" routines.
  88.  */
  89.  
  90. GLOBAL(void FAR *)
  91. jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
  92. {
  93.     return jpeg_get_small (cinfo, sizeofobject);
  94. }
  95.  
  96. GLOBAL(void)
  97. jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
  98. {
  99.     jpeg_free_small (cinfo, object, sizeofobject);
  100. }
  101.  
  102. /*
  103.  * This routine computes the total memory space available for allocation.
  104.  */
  105.  
  106. GLOBAL(long)
  107. jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
  108.             long max_bytes_needed, long already_allocated)
  109. {
  110.     long limitAvailable = cinfo->mem->max_memory_to_use - already_allocated;
  111.     long slop, mem;
  112.     THz currentZone;
  113.     
  114.     /* We shouldn't have gone negative, but just in case... */
  115.     if (limitAvailable < 0)
  116.         limitAvailable = 0;
  117.     
  118.     /* Don't ask for more than what application has told us we may use */
  119.     if (max_bytes_needed > limitAvailable)
  120.         max_bytes_needed = limitAvailable;
  121.     
  122.     /* Find whether there's a big enough free block in the heap.
  123.     * CompactMem tries to create a contiguous block of the requested size,
  124.     * and then returns the size of the largest free block (which could be
  125.     * much more or much less than we asked for).
  126.     * We add some slop to ensure we don't use up all available memory.
  127.     */
  128.     slop = max_bytes_needed / 16 + 32768L;
  129.     currentZone = LMGetTheZone();
  130.     SetZone (gTemporaryZone);
  131.     mem = CompactMem (max_bytes_needed + slop) - slop;
  132.     SetZone (currentZone);
  133.     
  134.     /* Don't take more than the application says we can have */
  135.     if (mem > limitAvailable)
  136.         mem = limitAvailable;
  137.     
  138.     /* Don't go negative */
  139.     if (mem < 0)
  140.         mem = 0;
  141.     
  142.     return mem;
  143. }
  144.  
  145.  
  146. /*
  147.  * Backing store (temporary file) management.
  148.  * Backing store objects are only used when the value returned by
  149.  * jpeg_mem_available is less than the total space needed.  You can dispense
  150.  * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  151.  */
  152.  
  153. typedef struct MacFileStruct {
  154.     FSSpec     location;
  155.     short     refnum;
  156. } MacFileStruct;
  157.  
  158. METHODDEF(void)
  159. read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  160.             void FAR * buffer_address,
  161.             long file_offset, long byte_count)
  162. {
  163.     MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
  164.     long bytes;
  165.     OSErr result;
  166.     
  167.     result = SetFPos (mfs->refnum, fsFromStart, file_offset);
  168.     if (result != noErr)
  169.         ERREXIT(cinfo, JERR_TFILE_SEEK);
  170.     
  171.     bytes = byte_count;
  172.     result = FSRead (mfs->refnum, &bytes, buffer_address);
  173.     if (result != noErr || bytes != byte_count)
  174.         ERREXIT(cinfo, JERR_TFILE_READ);
  175. }
  176.  
  177.  
  178. METHODDEF(void)
  179. write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  180.              void FAR * buffer_address,
  181.              long file_offset, long byte_count)
  182. {
  183.     MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
  184.     long bytes;
  185.     OSErr result;
  186.     
  187.     result = SetFPos (mfs->refnum, fsFromStart, file_offset);
  188.     if (result != noErr)
  189.         ERREXIT(cinfo, JERR_TFILE_SEEK);
  190.     
  191.     bytes = byte_count;
  192.     result = FSWrite (mfs->refnum, &bytes, buffer_address);
  193.     if (result != noErr || bytes != byte_count)
  194.         ERREXIT(cinfo, JERR_TFILE_WRITE);
  195. }
  196.  
  197. METHODDEF(void)
  198. close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
  199. {
  200.     MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
  201.     
  202.     FSClose (mfs->refnum);
  203.     FSpDelete (&mfs->location);
  204.     
  205.     /* We don't need to free mfs; the JPEG memory manager handles that */
  206. }
  207.  
  208.  
  209. /*
  210.  * Initial opening of a backing-store object.
  211.  *
  212.  * This version uses tmpfile(), which constructs a suitable file name
  213.  * behind the scenes.  We don't have to use info->temp_name[] at all;
  214.  * indeed, we can't even find out the actual name of the temp file.
  215.  */
  216.  
  217. GLOBAL(void)
  218. jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
  219.              long total_bytes_needed)
  220. {
  221.     OSErr result;
  222.     short volume;
  223.     long directory;
  224.     Str31 name;
  225.     FSSpec location;
  226.     short refnum;
  227.     MacFileStruct* mfs;
  228.     
  229.     /*
  230.         Find the temporary items folder
  231.         Create a temporary file named, yes, TickCount!
  232.     */
  233.     
  234.     result = FindFolder (kOnSystemDisk, kTemporaryFolderType, true, &volume, &directory);
  235.     if (result != noErr)
  236.         goto failexit;
  237.     
  238.     NumToString (TickCount(), name);
  239.     
  240.     result = Create (name, volume, directory, '????');
  241.     if (result != noErr)
  242.         goto failexit;
  243.     
  244.     result = FSMakeFSSpec (volume, directory, name, &location);
  245.     if (result != noErr)
  246.         goto deleteandexit;
  247.     
  248.     /*
  249.         Open it and resize it.
  250.     */
  251.     
  252.     result = FSpOpenDF (&location, fsRdWrPerm, &refnum);
  253.     if (result != noErr)
  254.         goto deleteandexit;
  255.     
  256.     result = SetEOF (refnum, total_bytes_needed);
  257.     if (result != noErr)
  258.         goto closeandexit;
  259.     
  260.     /*
  261.         Use the "temp_file" field in the backing_store so we don't have to
  262.         change the headers. Ugly, yes.
  263.     */
  264.     
  265.     mfs = (*cinfo->mem->alloc_small) (cinfo, 0?JPOOL_IMAGE:JPOOL_PERMANENT, sizeof (MacFileStruct));
  266.     if (mfs == 0)
  267.         goto closeandexit;
  268.     
  269.     memcpy (&mfs->location, &location, sizeof(location));
  270.     mfs->refnum = refnum;
  271.     
  272.     info->temp_file = (FILE*) mfs;
  273.     
  274.     info->read_backing_store = read_backing_store;
  275.     info->write_backing_store = write_backing_store;
  276.     info->close_backing_store = close_backing_store;
  277.     
  278.     return;
  279.     
  280. closeandexit:
  281.     FSClose (refnum);
  282. deleteandexit:
  283.     FSpDelete (&location);
  284. failexit:
  285.     ERREXITS(cinfo, JERR_TFILE_CREATE, "");
  286. }
  287.  
  288.  
  289. /*
  290.     We will be using temporary memory for allocations, so determine
  291.     how much is available. We are unlikely to get all of it, however.
  292. */
  293.  
  294. GLOBAL(long)
  295. jpeg_mem_init (j_common_ptr cinfo)
  296. {
  297.     OSErr result;
  298.     Handle zero;
  299.     
  300.     if (!gHaveTemporaryZone) {
  301.         zero = TempNewHandle (0, &result);
  302.         if (result != noErr || zero == 0)
  303.             return 0;
  304.         gTemporaryZone = HandleZone (zero);
  305.         DisposeHandle (zero);
  306.         gHaveTemporaryZone = true;
  307.     }
  308.     
  309.     return TempFreeMem();
  310. }
  311.  
  312. GLOBAL(void)
  313. jpeg_mem_term (j_common_ptr cinfo)
  314. {
  315. #ifdef DEBUG
  316.     if (gAllocationTotal != 0 || gAllocationCount != 0)
  317.         DebugStr ("\pjpeg_mem_term - memory was leaked");
  318. #endif
  319. }
  320.