home *** CD-ROM | disk | FTP | other *** search
- /*========================================================================================
- //
- // File: jmemod.c
- // Release Version: $ ODF 2 $
- //
- // Author: Mark Lanett
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- // Macintosh OpenDoc implementation of the system-dependent portion of
- // the JPEG memory manager. jmemmac.c isn't suitable because
- // the application heap is too small.
- //
- // 6/5/96 mlanett Written
- //
- // Note: This uses "temporary" memory for all memory allocations. Backing
- // store uses Macintosh file system routines and the boot volume's
- // temporary directory. Based on jmemmac.c, but mostly rewritten.
- //======================================================================================*/
-
- #define JPEG_INTERNALS
- #include "jinclude.h"
- #include "jpeglib.h"
- #include "jmemsys.h"
-
- #include <LowMem.h>
- #include <Memory.h>
-
- #include <Files.h>
- #include <Folders.h>
- #include <TextUtils.h>
-
- static Boolean gHaveTemporaryZone = false;
- static THz gTemporaryZone;
-
- /*#define DEBUG 1*/
-
- #ifdef DEBUG
- long gAllocationTotal = 0;
- long gAllocationCount = 0;
- #endif
-
- /*
- Use temporary memory. Allocating locked blocks in that heap is kind
- of rude, but the IJG code can't deal with handles, and decoding is
- a short-term process anyway.
- */
-
- GLOBAL(void *)
- jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
- {
- void* memory;
-
- THz currentZone = LMGetTheZone();
- SetZone (gTemporaryZone);
- memory = NewPtr (sizeofobject);
- SetZone (currentZone);
-
- #ifdef DEBUG
- if (memory) {
- gAllocationTotal += sizeofobject;
- gAllocationCount ++;
- }
- #endif
-
- return memory;
- }
-
- GLOBAL(void)
- jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
- {
- /* Not sure if DisposePtr is zone-aware like DisposeHandle */
- THz currentZone = LMGetTheZone();
- SetZone (gTemporaryZone);
- DisposePtr ((Ptr)object);
- SetZone (currentZone);
-
- #ifdef DEBUG
- if (object) {
- gAllocationTotal -= sizeofobject;
- gAllocationCount --;
- }
- #endif
- }
-
- /*
- "Large" and "small" are the same; just call the "small" routines.
- */
-
- GLOBAL(void FAR *)
- jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
- {
- return jpeg_get_small (cinfo, sizeofobject);
- }
-
- GLOBAL(void)
- jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
- {
- jpeg_free_small (cinfo, object, sizeofobject);
- }
-
- /*
- * This routine computes the total memory space available for allocation.
- */
-
- GLOBAL(long)
- jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
- long max_bytes_needed, long already_allocated)
- {
- long limitAvailable = cinfo->mem->max_memory_to_use - already_allocated;
- long slop, mem;
- THz currentZone;
-
- /* We shouldn't have gone negative, but just in case... */
- if (limitAvailable < 0)
- limitAvailable = 0;
-
- /* Don't ask for more than what application has told us we may use */
- if (max_bytes_needed > limitAvailable)
- max_bytes_needed = limitAvailable;
-
- /* Find whether there's a big enough free block in the heap.
- * CompactMem tries to create a contiguous block of the requested size,
- * and then returns the size of the largest free block (which could be
- * much more or much less than we asked for).
- * We add some slop to ensure we don't use up all available memory.
- */
- slop = max_bytes_needed / 16 + 32768L;
- currentZone = LMGetTheZone();
- SetZone (gTemporaryZone);
- mem = CompactMem (max_bytes_needed + slop) - slop;
- SetZone (currentZone);
-
- /* Don't take more than the application says we can have */
- if (mem > limitAvailable)
- mem = limitAvailable;
-
- /* Don't go negative */
- if (mem < 0)
- mem = 0;
-
- return mem;
- }
-
-
- /*
- * Backing store (temporary file) management.
- * Backing store objects are only used when the value returned by
- * jpeg_mem_available is less than the total space needed. You can dispense
- * with these routines if you have plenty of virtual memory; see jmemnobs.c.
- */
-
- typedef struct MacFileStruct {
- FSSpec location;
- short refnum;
- } MacFileStruct;
-
- METHODDEF(void)
- read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
- void FAR * buffer_address,
- long file_offset, long byte_count)
- {
- MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
- long bytes;
- OSErr result;
-
- result = SetFPos (mfs->refnum, fsFromStart, file_offset);
- if (result != noErr)
- ERREXIT(cinfo, JERR_TFILE_SEEK);
-
- bytes = byte_count;
- result = FSRead (mfs->refnum, &bytes, buffer_address);
- if (result != noErr || bytes != byte_count)
- ERREXIT(cinfo, JERR_TFILE_READ);
- }
-
-
- METHODDEF(void)
- write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
- void FAR * buffer_address,
- long file_offset, long byte_count)
- {
- MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
- long bytes;
- OSErr result;
-
- result = SetFPos (mfs->refnum, fsFromStart, file_offset);
- if (result != noErr)
- ERREXIT(cinfo, JERR_TFILE_SEEK);
-
- bytes = byte_count;
- result = FSWrite (mfs->refnum, &bytes, buffer_address);
- if (result != noErr || bytes != byte_count)
- ERREXIT(cinfo, JERR_TFILE_WRITE);
- }
-
- METHODDEF(void)
- close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
- {
- MacFileStruct* mfs = (MacFileStruct*) info->temp_file;
-
- FSClose (mfs->refnum);
- FSpDelete (&mfs->location);
-
- /* We don't need to free mfs; the JPEG memory manager handles that */
- }
-
-
- /*
- * Initial opening of a backing-store object.
- *
- * This version uses tmpfile(), which constructs a suitable file name
- * behind the scenes. We don't have to use info->temp_name[] at all;
- * indeed, we can't even find out the actual name of the temp file.
- */
-
- GLOBAL(void)
- jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
- long total_bytes_needed)
- {
- OSErr result;
- short volume;
- long directory;
- Str31 name;
- FSSpec location;
- short refnum;
- MacFileStruct* mfs;
-
- /*
- Find the temporary items folder
- Create a temporary file named, yes, TickCount!
- */
-
- result = FindFolder (kOnSystemDisk, kTemporaryFolderType, true, &volume, &directory);
- if (result != noErr)
- goto failexit;
-
- NumToString (TickCount(), name);
-
- result = Create (name, volume, directory, '????');
- if (result != noErr)
- goto failexit;
-
- result = FSMakeFSSpec (volume, directory, name, &location);
- if (result != noErr)
- goto deleteandexit;
-
- /*
- Open it and resize it.
- */
-
- result = FSpOpenDF (&location, fsRdWrPerm, &refnum);
- if (result != noErr)
- goto deleteandexit;
-
- result = SetEOF (refnum, total_bytes_needed);
- if (result != noErr)
- goto closeandexit;
-
- /*
- Use the "temp_file" field in the backing_store so we don't have to
- change the headers. Ugly, yes.
- */
-
- mfs = (*cinfo->mem->alloc_small) (cinfo, 0?JPOOL_IMAGE:JPOOL_PERMANENT, sizeof (MacFileStruct));
- if (mfs == 0)
- goto closeandexit;
-
- memcpy (&mfs->location, &location, sizeof(location));
- mfs->refnum = refnum;
-
- info->temp_file = (FILE*) mfs;
-
- info->read_backing_store = read_backing_store;
- info->write_backing_store = write_backing_store;
- info->close_backing_store = close_backing_store;
-
- return;
-
- closeandexit:
- FSClose (refnum);
- deleteandexit:
- FSpDelete (&location);
- failexit:
- ERREXITS(cinfo, JERR_TFILE_CREATE, "");
- }
-
-
- /*
- We will be using temporary memory for allocations, so determine
- how much is available. We are unlikely to get all of it, however.
- */
-
- GLOBAL(long)
- jpeg_mem_init (j_common_ptr cinfo)
- {
- OSErr result;
- Handle zero;
-
- if (!gHaveTemporaryZone) {
- zero = TempNewHandle (0, &result);
- if (result != noErr || zero == 0)
- return 0;
- gTemporaryZone = HandleZone (zero);
- DisposeHandle (zero);
- gHaveTemporaryZone = true;
- }
-
- return TempFreeMem();
- }
-
- GLOBAL(void)
- jpeg_mem_term (j_common_ptr cinfo)
- {
- #ifdef DEBUG
- if (gAllocationTotal != 0 || gAllocationCount != 0)
- DebugStr ("\pjpeg_mem_term - memory was leaked");
- #endif
- }
-