home *** CD-ROM | disk | FTP | other *** search
-
- /*
- **
- ** $VER: dispatch.c 1.3 (9.11.97)
- ** acbm.datatype 1.3
- **
- ** Dispatch routine for a DataTypes class
- **
- ** Written 1996/97 by Roland 'Gizzy' Mainz
- ** Original example source from David N. Junod
- **
- */
-
- /* main includes */
- #include "classbase.h"
- #include "classdata.h"
-
- /* ansi includes */
- #include <limits.h>
-
- /*****************************************************************************/
-
- /* local prototypes */
- static LONG LoadACBM( struct ClassBase *, Object * );
- static BOOL CMAP2Object( struct ClassBase *, Object *, UBYTE *, ULONG );
- static LONG LoadABITBody( struct BitMap *, struct BitMapHeader *, BYTE *, ULONG );
-
- #ifndef NO_ENCODER
- static ULONG SaveIFFACBM( struct ClassBase *, Object *, struct dtWrite * );
-
- static struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
-
- static LONG PutIFFObjectInfo( struct ClassBase *, struct IFFHandle *, STRPTR, STRPTR, STRPTR, STRPTR, STRPTR );
- static LONG PutIFFString( struct ClassBase *, struct IFFHandle *, ULONG, STRPTR );
-
- static LONG PutILBMCMAP( struct ClassBase *, struct IFFHandle *, ULONG *, ULONG );
- static LONG PutACBMABIT( struct ClassBase *, struct IFFHandle *, struct BitMap *, struct BitMapHeader * );
- #endif /* NO_ENCODER */
-
-
-
- /*****************************************************************************/
-
- /* Create "acbm.datatype" BOOPSI class */
- struct IClass *initClass( struct ClassBase *cb )
- {
- struct IClass *cl;
-
- /* Create our class... */
- if( cl = MakeClass( ACBMDTCLASS, PICTUREDTCLASS, NULL, 0UL, 0UL ) )
- {
- #define DTSTACKSIZE (16384UL)
- cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)StackSwapDispatch; /* see stackswap.c */
- cl -> cl_Dispatcher . h_SubEntry = (HOOKFUNC)Dispatch; /* see stackswap.c */
- cl -> cl_Dispatcher . h_Data = (APTR)DTSTACKSIZE; /* see stackswap.c */
- cl -> cl_UserData = (ULONG)cb; /* class library base as expected by datatypes.library */
-
- /* ... then make it public */
- AddClass( cl );
- }
-
- return( cl );
- }
-
- /*****************************************************************************/
-
- /* IFF errors to DOS errors */
- static
- const
- LONG ifferr2doserr[] =
- {
- 0L, /* End of file (not an error). */
- 0L, /* End of context (not an error). */
- DTERROR_INVALID_DATA, /* No lexical scope. */
- ERROR_NO_FREE_STORE, /* Insufficient memory. */
- ERROR_SEEK_ERROR, /* Stream read error. */
- ERROR_SEEK_ERROR, /* Stream write error. */
- ERROR_SEEK_ERROR, /* Stream seek error. */
- DTERROR_INVALID_DATA, /* File is corrupt. */
- DTERROR_INVALID_DATA, /* IFF syntax error. */
- ERROR_OBJECT_WRONG_TYPE, /* Not an IFF file. */
- ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing. */
- 0xDEADDEAD /* Return to client. You should never see this ! */
- };
-
- /*****************************************************************************/
-
- /* class dispatcher */
- DISPATCHERFLAGS
- ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
- {
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- ULONG retval = 0UL;
-
- switch( msg -> MethodID )
- {
- /****** acbm.datatype/OM_NEW *************************************************
- *
- * NAME
- * OM_NEW -- Create a acbm.datatype object.
- *
- * FUNCTION
- * The OM_NEW method is used to create an instance of the acbm.datatype
- * class. This method is passed to the superclass first. After this,
- * acbm.datatype parses the description file and loads the colormap,
- * the bitmap and so on.
- *
- * ATTRIBUTES
- * The following attributes can be specified at creation time.
- *
- * DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
- * attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
- * If any other type was set in a given DTA_SourceType,
- * OM_NEW will be rejected.
- * Defaults to DTST_FILE.
- *
- * DTA_Handle -- For both supported DTST_FILE and DTST_CLIPBOARD, a
- * (struct IFFHandle *) is expected.
- * (DTST_FILE expects a IFF Stream handle because this is a IFF
- * type DataType (DTF_IFF)).
- * A DTST_RAM (create empty object) source type requires a NULL
- * handle.
- *
- * RESULT
- * If the object was created a pointer to the object is returned,
- * otherwise NULL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_NEW:
- {
- struct TagItem *ti;
-
- /* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
- if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
- {
- if( ((ti -> ti_Data) != DTST_FILE) &&
- ((ti -> ti_Data) != DTST_CLIPBOARD)
- #ifndef NO_ENCODER
- && ((ti -> ti_Data) != DTST_RAM)
- #endif /* !NO_ENCODER */
- )
- {
- SetIoErr( ERROR_OBJECT_WRONG_TYPE );
-
- break;
- }
- }
-
- /* This must not be a subclass of acbm.datatype
- * (not implemented yet)
- */
- if( o == (Object *)cl )
- {
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- LONG error;
-
- /* Load picture... */
- if( error = LoadACBM( cb, (Object *)retval ) )
- {
- /* Something went fatally wrong, dispose object */
- CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
- retval = 0UL;
- }
-
- SetIoErr( error );
- }
- }
- else
- {
- /* Subclasses of acbm.datatype are not implemented */
- SetIoErr( ERROR_NOT_IMPLEMENTED );
- }
- }
- break;
-
- case OM_UPDATE:
- {
- if( DoMethod( o, ICM_CHECKLOOP ) )
- {
- break;
- }
- }
- case OM_SET:
- {
- /* Pass the attributes to the picture class and force a refresh if we need it */
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- /* The following check statement isn't needed because OM_NEW does not allow subclasses of acbm.datatype,
- * therefore, we're always the top instance...
- */
- #ifdef COMMENTED_OUT
- /* Top instance ? */
- if( OCLASS( o ) == cl )
- #endif /* COMMENTED_OUT */
- {
- struct RastPort *rp;
-
- /* Get a pointer to the rastport */
- if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
- {
- struct gpRender gpr;
-
- /* Force a redraw */
- gpr . MethodID = GM_RENDER;
- gpr . gpr_GInfo = ((struct opSet *)msg) -> ops_GInfo;
- gpr . gpr_RPort = rp;
- gpr . gpr_Redraw = GREDRAW_UPDATE;
-
- DoMethodA( o, (Msg)(&gpr) );
-
- /* Release the temporary rastport */
- ReleaseGIRPort( rp );
-
- /* We did a refresh... */
- retval = 0UL;
- }
- }
- }
- }
- break;
-
- /****** acbm.datatype/DTM_WRITE **********************************************
- *
- * NAME
- * DTM_WRITE -- Save data
- *
- * FUNCTION
- * This method saves the object's contents to disk.
- *
- * If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
- * superclass, picture.datatype, which writes an IFF ILBM picture.
- *
- * If dtw_mode is DTWM_RAW, the object writes an IFF ACBM picture to
- * the filehandle given.
- * (If the class library was compiled with the NO_ENCODER switch
- * (not the default), result == 0 and resul2 == ERROR_NOT_IMPLEMENTED
- * are returned).
- *
- * TAGS
- * None defined.
- *
- * RESULT
- * Returns 0 for failure (IoErr() returns result2), non-zero
- * for success.
- *
- ******************************************************************************
- *
- */
- case DTM_WRITE:
- {
- struct dtWrite *dtw;
-
- dtw = (struct dtWrite *)msg;
-
- /* Local data format requested ? */
- if( (dtw -> dtw_Mode) == DTWM_RAW )
- {
- /* Enable the followng code if you don't have an encoder implemented... */
- #ifdef NO_ENCODER
- SetIoErr( ERROR_NOT_IMPLEMENTED );
- retval = 0UL;
- #else
- retval = SaveIFFACBM( cb, o, dtw );
- #endif /* NO_ENCODER */
- }
- else
- {
- /* Pass msg to superclass (which writes an IFF ILBM picture)... */
- retval = DoSuperMethodA( cl, o, msg );
- }
- }
- break;
-
- /* Let the superclass handle everything else */
- default:
- {
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
- }
-
- return( retval );
- }
-
-
- static
- LONG LoadACBM( struct ClassBase *cb, Object *o )
- {
- LONG error = 0L;
-
-
- APTR fh; /* IFF stream handle */
- ULONG sourcetype; /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
- struct BitMapHeader *bmh; /* obj's bitmapheader */
- ULONG modeid = 0UL; /* picture's view mode */
-
- /* Get file handle, handle type and BitMapHeader */
- if( GetDTAttrs( o, DTA_SourceType, (&sourcetype),
- DTA_Handle, (&fh),
- PDTA_BitMapHeader, (&bmh),
- TAG_DONE ) == 3UL )
- {
- struct IFFHandle *iff = NULL;
-
- switch( sourcetype )
- {
- case DTST_CLIPBOARD:
- case DTST_FILE:
- {
- /* This is an IFF DataType, datatypesclass provides an IFFHandle for us.
- * (See datatypesclass autdocs for details !)
- */
- iff = (struct IFFHandle *)fh;
- }
- break;
-
- #ifndef NO_ENCODER
- case DTST_RAM:
- {
- /* Do nothing... */
- }
- break;
- #endif /* !NO_ENCODER */
-
- default:
- {
- /* unsupported source type */
- error = ERROR_NOT_IMPLEMENTED;
- }
- break;
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- /* Any handle to proccess ? */
- if( iff )
- {
- struct BitMap *bm = NULL; /* resulting bitmap (e.g. PDTA_BitMap) */
-
- struct StoredProperty *bmhdprop = NULL, /* ACBM BMHD (struct BitMapHeader) */
- *camgprop = NULL, /* ACBM CAMG (amiga view mode id) */
- *cmapprop = NULL, /* ACBM CMAP (colormap) */
- *abitprop = NULL, /* ACBM ABIT (Amiga BITplanes */
- *annoprop = NULL, /* Generic IFF ANNO (annotation) chunk */
- *authprop = NULL, /* Generic IFF AUTH (author) chunk */
- *copyrightprop = NULL, /* Generic IFF (C) (copyright) chunk */
- *fverprop = NULL, /* Generic IFF FVER (version) chunk */
- *nameprop = NULL; /* Generic IFF NAME (name) chunk */
-
- #define NUM_PROPCHUNKS (9L)
- const
- LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
- {
- ID_ACBM, ID_BMHD,
- ID_ACBM, ID_CAMG,
- ID_ACBM, ID_CMAP,
- ID_ACBM, ID_ABIT,
- ID_ACBM, ID_ANNO,
- ID_ACBM, ID_AUTH,
- ID_ACBM, ID_Copyright,
- ID_ACBM, ID_FVER,
- ID_ACBM, ID_NAME
- };
-
- if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
- {
- /* Scan IFF stream until an error or an EOF occurs */
- for( ;; )
- {
- if( error = ParseIFF( iff, IFFPARSE_STEP ) )
- {
- /* EOF (End Of File) is no error here... */
- if( error == IFFERR_EOF )
- {
- error = 0L;
- break;
- }
-
- /* bmhd header loaded ? */
- if( bmhdprop == NULL )
- {
- if( bmhdprop = FindProp( iff, ID_ACBM, ID_BMHD ) )
- {
- *bmh = *((struct BitMapHeader *)(bmhdprop -> sp_Data));
-
- /* ABIT data __must__ not be compressed for IFF ACBM */
- if( (bmh -> bmh_Compression) != cmpNone )
- {
- error = DTERROR_INVALID_DATA;
- }
- }
- }
-
- /* camg loaded ? */
- if( camgprop == NULL )
- {
- if( camgprop = FindProp( iff, ID_ACBM, ID_CAMG ) )
- {
- modeid = *(ULONG *)(camgprop -> sp_Data);
- }
- }
-
- /* cmap loaded ? */
- if( cmapprop == NULL )
- {
- if( cmapprop = FindProp( iff, ID_ACBM, ID_CMAP ) )
- {
- if( !CMAP2Object( cb, o, (cmapprop -> sp_Data), (cmapprop -> sp_Size) ) )
- {
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* annotation loaded ? */
- if( annoprop == NULL )
- {
- /* IFF ANNO found ? */
- if( annoprop = FindProp( iff, ID_ACBM, ID_ANNO ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* autor loaded ? */
- if( authprop == NULL )
- {
- /* IFF AUTH found ? */
- if( authprop = FindProp( iff, ID_ACBM, ID_AUTH ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* copyright loaded ? */
- if( copyrightprop == NULL )
- {
- /* IFF (C) found ? */
- if( copyrightprop = FindProp( iff, ID_ACBM, ID_Copyright ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* file version loaded ? */
- if( fverprop == NULL )
- {
- /* IFF FVER found ? */
- if( fverprop = FindProp( iff, ID_ACBM, ID_FVER ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* name loaded ? */
- if( nameprop == NULL )
- {
- /* IFF NAME found ? */
- if( nameprop = FindProp( iff, ID_ACBM, ID_NAME ) )
- {
- STRPTR buff;
-
- /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
- if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
- {
- stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
-
- SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
-
- FreeVec( buff );
- }
- else
- {
- /* no temp. buffer */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
-
- /* abit loaded ? */
- if( abitprop == NULL )
- {
- if( abitprop = FindProp( iff, ID_ACBM, ID_ABIT ) )
- {
- if( bmhdprop )
- {
- if( bm = AllocBitMap( (ULONG)(bmh -> bmh_Width), (ULONG)(bmh -> bmh_Height), (ULONG)(bmh -> bmh_Depth), BMF_MINPLANES, NULL ) )
- {
- error = LoadABITBody( bm, bmh, (abitprop -> sp_Data), (abitprop -> sp_Size) );
- }
- else
- {
- /* Not bitmap (AllocBitMap failed) */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* No BMHD chunk before ABIT chunk */
- error = DTERROR_INVALID_DATA;
- }
- }
- }
-
- /* on error: leave for-loop */
- if( error )
- {
- if( error != IFFERR_EOC )
- {
- break;
- }
- }
- }
- }
- }
-
- /* bmh, cmap, abit and all other required information available ? */
- if( ((bmhdprop == NULL) || (cmapprop == NULL) || (abitprop == NULL) || (bm == NULL)) && (error == 0L) )
- {
- error = DTERROR_INVALID_DATA;
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- /* No name chunk ? */
- if( nameprop == NULL )
- {
- STRPTR name;
-
- GetDTAttrs( o, DTA_Name, (&name), TAG_DONE );
- SetDTAttrs( o, NULL, NULL, DTA_ObjName, name, TAG_DONE );
- }
-
- /* No mode id ? */
- if( modeid == 0UL )
- {
- /* BUG: Does currently not support SUPERHIRES modes */
- if( (bmh -> bmh_Width) >= 640UL )
- {
- if( (bmh -> bmh_Height) >= 400 )
- {
- modeid = HIRESLACE_KEY;
- }
- else
- {
- modeid = HIRES_KEY;
- }
- }
- else
- {
- if( (bmh -> bmh_Height) >= 400 )
- {
- modeid = LORESLACE_KEY;
- }
- else
- {
- modeid = LORES_KEY;
- }
- }
- }
-
- /* Set misc attributes */
- SetDTAttrs( o, NULL, NULL,
- PDTA_ModeID, modeid,
- PDTA_BitMap, bm,
- DTA_NominalHoriz, (bmh -> bmh_Width),
- DTA_NominalVert, (bmh -> bmh_Height),
- TAG_DONE );
-
- /* bm has been given to picture.datatype and will be freed there... */
- bm = NULL;
- }
-
- /* Free bitmap if it wasn't consumed by picture.datatype */
- if( bm )
- {
- FreeBitMap( bm );
- }
- }
- else
- {
- /* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
- if( sourcetype != DTST_RAM )
- {
- /* No handle ! */
- error = ERROR_REQUIRED_ARG_MISSING;
- }
- }
- }
- }
- else
- {
- /* can't get required attributes from superclass */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
-
- /* Error codes below 0 are related to the IFFParse.library functions */
- if( error < 0L )
- {
- /* convert IFFParse error to DOS error */
- error = ifferr2doserr[ (-error - 1) ];
- }
-
- return( error );
- }
-
-
- /* Put CMAP chunk into picture/animation object... */
- static
- BOOL CMAP2Object( struct ClassBase *cb, Object *o, UBYTE *rgb, ULONG rgbsize )
- {
- struct ColorRegister *acm;
- ULONG *acregs;
- ULONG nc;
-
- /* file has this many colors (e.g. each color has one byte per R,B,G-gun) */
- nc = rgbsize / 3UL;
-
- SetDTAttrs( o, NULL, NULL, PDTA_NumColors, nc, TAG_DONE );
-
- /* Get color context */
- if( GetDTAttrs( o,
- PDTA_ColorRegisters, (&acm),
- PDTA_CRegs, (&acregs),
- PDTA_NumColors, (&nc),
- TAG_DONE ) == 3UL )
- {
- /* All valid ? */
- if( acm && acregs && nc )
- {
- ULONG i;
-
- for( i = 0UL ; i < nc ; i++, acm++ )
- {
- acm -> red = *rgb++;
- acm -> green = *rgb++;
- acm -> blue = *rgb++;
-
- /* Replicate the color information.
- * This surrounds an OS bug which uses the low-order bytes of the 32-bit colors
- * instead of the high order ones
- */
- acregs[ ((i * 3) + 0) ] = ((ULONG)(acm -> red)) * 0x01010101UL;
- acregs[ ((i * 3) + 1) ] = ((ULONG)(acm -> green)) * 0x01010101UL;
- acregs[ ((i * 3) + 2) ] = ((ULONG)(acm -> blue)) * 0x01010101UL;
- }
-
- return( TRUE );
- }
- }
-
- return( FALSE );
- }
-
-
- /* Load IFF ACBM ABIT chunk into given bitmap */
- static
- LONG LoadABITBody( struct BitMap *bitmap, struct BitMapHeader *bmhd, BYTE *buffer, ULONG buffersize )
- {
- UBYTE srcPlaneCnt = bmhd -> bmh_Depth; /* Haven't counted for mask plane yet */
- WORD srcRowBytes = RowBytes( (bmhd -> bmh_Width) );
- WORD destRowBytes = bitmap -> BytesPerRow; /* used as a modulo only */
- LONG nRows = bmhd -> bmh_Height;
- LONG iPlane,
- iRow;
- BYTE *buf;
- BYTE *planes[ MaxSrcPlanes ]; /* array of ptrs to planes & mask */
-
- if( nRows > (bitmap -> Rows) )
- nRows = bitmap -> Rows;
-
- /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
- for( iPlane = 0 ; iPlane < (bitmap -> Depth) ; iPlane++ )
- {
- planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
- }
-
- for( ; iPlane < MaxSrcPlanes ; iPlane++ )
- {
- planes[ iPlane ] = NULL;
- }
-
- /* Copy any mask plane ptr into corresponding "planes" slot. */
- if( (bmhd -> bmh_Masking) == mskHasMask )
- {
- planes[ srcPlaneCnt ] = NULL; /* In case more dstPlanes than src. */
- srcPlaneCnt += 1; /* Include mask plane in count. */
- }
-
- /* Read the ABIT contents into client's bitmap. */
- buf = buffer;
-
- for( iPlane = 0 ; iPlane < srcPlaneCnt ; iPlane++ )
- {
- for( iRow = nRows ; iRow > 0 ; iRow-- )
- {
- memcpy( planes[ iPlane ], buf, (size_t)srcRowBytes );
- buf += srcRowBytes;
-
- planes[ iPlane ] += destRowBytes; /* Possibly skipping unused bytes */
- }
- }
-
- return( 0L );
- }
-
-
- #ifndef NO_ENCODER
- /* The IFF ACBM encoder */
- static
- ULONG SaveIFFACBM( struct ClassBase *cb, Object *o, struct dtWrite *dtw )
- {
- ULONG retval = 0UL;
- LONG error = 0L;
-
- /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
- if( dtw -> dtw_FileHandle )
- {
- struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
- STRPTR objname,
- objauthor,
- objannotation,
- objcopyright,
- objversion;
- struct BitMapHeader *bmh;
- ULONG modeid;
- ULONG *cregs;
- ULONG numcolors;
- struct BitMap *bm;
-
- /* Lock data that noone could change it...
- * We use here a shared lock because we don't chaange any object data below
- * Theoretically, this allows that multiple savers acts on the same object :-)
- */
- ObtainSemaphoreShared( (&(si -> si_Lock)) );
-
- if( GetDTAttrs( o, DTA_ObjName, (&objname),
- DTA_ObjAuthor, (&objauthor),
- DTA_ObjAnnotation, (&objannotation),
- DTA_ObjCopyright, (&objcopyright),
- DTA_ObjVersion, (&objversion),
- PDTA_BitMapHeader, (&bmh),
- PDTA_ModeID, (&modeid),
- PDTA_CRegs, (&cregs),
- PDTA_NumColors, (&numcolors),
- PDTA_BitMap, (&bm),
- TAG_DONE ) == 10UL )
- {
- if( bmh && cregs && numcolors && bm )
- {
- /* ABIT data __must__ not be compressed for IFF ACBM */
- if( (bmh -> bmh_Compression) == cmpNone )
- {
- /* Check if this is a standard amiga bitmap (we're accessing it directly below, and cannot
- * handle any other bitmap layout than the standart planar format)
- */
- if( GetBitMapAttr( bm, BMA_FLAGS ) & BMF_STANDARD )
- {
- struct IFFHandle *iff;
-
- /* Create IFF handle based in the given file handle */
- if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
- {
- if( !(error = OpenIFF( iff, IFFF_WRITE )) )
- {
- for( ;; ) /* not a loop, used as a jump table */
- {
- if( error = PushChunk( iff, ID_ACBM, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write BMHD (BitMapHeader) */
- {
- if( error = PushChunk( iff, 0UL, ID_BMHD, sizeof( struct BitMapHeader ) ) )
- break;
-
- if( (error = WriteChunkBytes( iff, (APTR)bmh, sizeof( struct BitMapHeader ) )) != sizeof( struct BitMapHeader ) )
- {
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write CMAP (global color map) */
- if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
- break;
-
- /* write misc info (name, author, annotation etc.) */
- if( error = PutIFFObjectInfo( cb, iff, objname, objauthor, objannotation, objcopyright, objversion ) )
- break;
-
- /* write CAMG (amiga view mode) (if available) */
- if( (modeid != 0UL) && (modeid != INVALID_ID) )
- {
- if( error = PushChunk( iff, 0UL, ID_CAMG, sizeof( ULONG ) ) )
- break;
-
- if( (error = WriteChunkBytes( iff, (APTR)(&modeid), sizeof( ULONG ) )) != sizeof( ULONG ) )
- {
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* Write ACBM ABIT */
- if( error = PutACBMABIT( cb, iff, bm, bmh ) )
- break;
-
- if( error = PopChunk( iff ) )
- break;
-
- break; /* end of jump table */
- }
-
- CloseIFF( iff );
- }
-
- /* No error == success */
- if( error == 0L )
- {
- retval = 1UL; /* success ! */
- }
-
- FreeIFF( iff );
- }
- else
- {
- /* Can't alloc iff handle */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* unknown bitmap layout (e.g. not a standard amiga bitmap) */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
- }
- else
- {
- /* IFF ACBM does not support compression */
- error = DTERROR_UNKNOWN_COMPRESSION;
- }
- }
- else
- {
- /* Some things are missing (e.g. no bitmap etc.)... */
- error = DTERROR_NOT_ENOUGH_DATA;
- }
- }
- else
- {
- /* Object does not support the attributes we need... */
- error = ERROR_OBJECT_WRONG_TYPE;
- }
-
- /* Release data */
- ReleaseSemaphore( (&(si -> si_Lock)) );
- }
-
- /* Error codes below 0 are related to the IFFParse.library functions */
- if( error < 0L )
- {
- /* convert IFFParse error to DOS error */
- error = ifferr2doserr[ (-error - 1) ];
- }
-
- /* Store Result2 */
- SetIoErr( error );
-
- return( retval );
- }
-
-
- /* Create IFF handle based on given file handle */
- static
- struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
- {
- struct IFFHandle *iff;
-
- if( iff = AllocIFF() )
- {
- iff -> iff_Stream = (ULONG)fh;
-
- InitIFFasDOS( iff );
- }
-
- return( iff );
- }
-
-
- /* Put IFF generic info chunks (NAME, AUTH, ANNO, (C), FVER etc. */
- static
- LONG PutIFFObjectInfo( struct ClassBase *cb, struct IFFHandle *iff, STRPTR objname, STRPTR objauthor, STRPTR objannotation, STRPTR objcopyright, STRPTR objversion )
- {
- LONG error;
-
- if( error = PutIFFString( cb, iff, ID_NAME, objname ) ) return( error );
- if( error = PutIFFString( cb, iff, ID_AUTH, objauthor ) ) return( error );
- if( error = PutIFFString( cb, iff, ID_ANNO, objannotation ) ) return( error );
- if( error = PutIFFString( cb, iff, ID_Copyright, objcopyright ) ) return( error );
- if( error = PutIFFString( cb, iff, ID_FVER, objversion ) ) return( error );
-
- return( 0L );
- }
-
-
- /* write an string into a chunk (like generic AUTH, ANNO etc. chunks) */
- static
- LONG PutIFFString( struct ClassBase *cb, struct IFFHandle *iff, ULONG id, STRPTR string )
- {
- LONG error = 0L;
-
- if( string )
- {
- ULONG len = (ULONG)(strlen( string ) + 1UL);
-
- if( error = PushChunk( iff, 0UL, id, len ) )
- return( error );
-
- if( (error = WriteChunkBytes( iff, (APTR)string, len )) != len )
- {
- return( error );
- }
-
- error = PopChunk( iff );
- }
-
- return( error );
- }
-
-
- /* write ILBM CMAP */
- static
- LONG PutILBMCMAP( struct ClassBase *cb, struct IFFHandle *iff, ULONG *cregs, ULONG numcolors )
- {
- long error;
- ULONG i;
- struct ColorRegister cm;
-
- #define SIZEOF_CMAPENTRY (3L)
- if( error = PushChunk( iff, 0UL, ID_CMAP, (numcolors * SIZEOF_CMAPENTRY) ) )
- return( error );
-
- for( i = 0UL ; i < numcolors ; i++ )
- {
- /* reduce colors from 32 bits to cmap's 8 bit-per-gun */
- cm . red = (UBYTE)(cregs[ ((i * 3) + 0) ] >> 24UL);
- cm . green = (UBYTE)(cregs[ ((i * 3) + 1) ] >> 24UL);
- cm . blue = (UBYTE)(cregs[ ((i * 3) + 2) ] >> 24UL);
-
- /* Write R, B, G bytes */
- if( (error = WriteChunkBytes( iff, (APTR)(&cm), SIZEOF_CMAPENTRY )) != SIZEOF_CMAPENTRY )
- {
- return( error );
- }
- }
-
- return( PopChunk( iff ) );
- }
-
- /*****************************************************************************/
-
- /* Write ACBM ABIT data */
- static
- LONG PutACBMABIT( struct ClassBase *cb, struct IFFHandle *iff, struct BitMap *bitmap, struct BitMapHeader *bmh )
- {
- LONG error;
- LONG rowBytes = bitmap -> BytesPerRow; /* for source modulo only */
- LONG FileRowBytes = RowBytes( (bmh -> bmh_Width) ); /* width to write in bytes */
- ULONG planeCnt = bmh -> bmh_Depth; /* number of bit planes including mask */
- ULONG iPlane,
- iRow;
- BYTE *planes[ 24 ]; /* array of ptrs to planes & mask */
-
- /* Copy the ptrs to bit & mask planes into local array "planes" */
- for( iPlane = 0 ; iPlane < planeCnt; iPlane++ )
- planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
-
- /* Write out a ABIT chunk header (size == number_of_planes * number_of_rows * bytes_per_row) */
- if( error = PushChunk( iff, 0L, ID_ABIT, (planeCnt * (bmh -> bmh_Height) * FileRowBytes) ) )
- return( error );
-
- /* Write out the ABIT contents */
- for( iPlane = 0 ; iPlane < planeCnt ; iPlane++ )
- {
- for( iRow = bmh -> bmh_Height ; iRow > 0 ; iRow-- )
- {
- /* Write next row.*/
- if( (error = WriteChunkBytes( iff, planes[ iPlane ], FileRowBytes )) != FileRowBytes )
- return( error );
-
- planes[ iPlane ] += rowBytes; /* Possibly skipping unused bytes */
- }
- }
-
- /* Finish the chunk */
- error = PopChunk( iff );
-
- return( error );
- }
-
- #endif /* NO_ENCODER */
-
-
-
-
-
-