/*
** $Id: mybrush.c,v 1.3 1999/08/10 21:53:03 wiz Exp $
*/

/// Includes
#include <exec/types.h>                 // exec
#include <exec/memory.h>
#include <exec/libraries.h>
#include <graphics/gfx.h>               // graphics
#include <graphics/modeid.h>
#include <graphics/gfxbase.h>
#include <datatypes/datatypes.h>        // datatypes
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/datatypes.h>

#include "mybrush.h"
///

extern struct Library  *DataTypesBase;
extern struct GfxBase  *GfxBase;

void FreeImg( struct MyImage * );

/// LoadImage
struct MyImage *LoadImage( STRPTR File )
{
    struct MyImage *Img;
    BOOL            ok = FALSE;

    if( DataTypesBase && ( Img = AllocMem( sizeof( struct MyImage ), MEMF_CLEAR ))) {
        static ULONG tags[] = { DTA_GroupID, GID_PICTURE,
                                PDTA_Remap,  FALSE,
                                TAG_END };

        if( Img->Datatype = NewDTObjectA( File, ( struct TagItem * )tags )) {
            struct BitMap          *b;
            ULONG                   w, h;
            struct gpLayout         gpl;

            gpl.MethodID    = DTM_PROCLAYOUT;
            gpl.gpl_GInfo   = NULL;
            gpl.gpl_Initial = 1;

            DoDTMethodA( Img->Datatype, NULL, NULL, (Msg) &gpl );

            GetDTAttrs( Img->Datatype,
                        DTA_NominalVert,        &h,
                        DTA_NominalHoriz,       &w,
                        PDTA_BitMap,            &b,
                        PDTA_ColorRegisters,    &Img->CReg,
                        TAG_DONE );

            Img->Width       = w;
            Img->Height      = h;
            Img->Depth       = b->Depth;
            Img->ImageData   = (UWORD *)b->Planes[0];
            Img->BytesPerRow = b->BytesPerRow;

            for( w = 0; w < Img->Depth; w++ )
                Img->Planes[ w ] = b->Planes[ w ];

            ok = TRUE;
        }

        if(!( ok )) {
            FreeImg( Img );
            Img = NULL;
        }
    }

    return( Img );
}
///
/// FreeImg
void FreeImg( struct MyImage *Img )
{
    if( Img ) {

        if( Img->Datatype )
            DisposeDTObject( Img->Datatype );

        FreeMem( Img, sizeof( struct MyImage ));
    }
}
///

/// CreateBitMap
struct BitMap *CreateBitMap( ULONG width, ULONG height, ULONG depth, ULONG flags, struct BitMap *friend )
{
    struct BitMap *bm;

    if( GfxBase->LibNode.lib_Version >= 39 ) {
        bm = AllocBitMap( width, height, depth, flags | BMF_CLEAR, friend );
    } else {

        if( bm = AllocMem( sizeof( struct BitMap ), 0L )) {

            InitBitMap( bm, depth, width, height );

            if( bm->Planes[0] = (PLANEPTR) AllocVec( depth * RASSIZE( width, height ), MEMF_CHIP | MEMF_CLEAR )) {
                LONG i;

                for( i = 1; i < depth; i++ )
                    bm->Planes[ i ] = bm->Planes[ i - 1 ] + RASSIZE( width, height );

            } else {
                FreeMem( bm, sizeof( struct BitMap ));
                bm = NULL;
            }
        }
    }

    return( bm );
}
///
/// DeleteBitMap
void DeleteBitMap( struct BitMap *bm )
{
    if( bm ) {
        if( GfxBase->LibNode.lib_Version >= 39 ) {
            FreeBitMap( bm );
        } else {
            FreeVec( bm->Planes[0] );
            FreeMem( bm, sizeof( struct BitMap ));
        }
    }
}
///

/// LoadBrush
struct MyBrush *LoadBrush( STRPTR File )
{
    struct MyImage *Img;
    struct MyBrush *Brush = NULL;

    if( Img = LoadImage( File )) {

        if( Brush = AllocMem( sizeof( struct MyBrush ), MEMF_CLEAR )) {
            BOOL    err = TRUE;

            Brush->Width  = Img->Width;
            Brush->Height = Img->Height;

            if( Brush->BitMap = CreateBitMap( Brush->Width, Brush->Height, Img->Depth, BMF_DISPLAYABLE, NULL )) {
                ULONG   i, row;

                row = ( Brush->Width + 7 ) >> 3;

                for( i = 0; i < Img->Depth; i++ ) {
                    UBYTE  *from, *to;
                    ULONG   h;

                    from = Img->Planes[ i ];
                    to   = Brush->BitMap->Planes[ i ];

                    for( h = 0; h < Img->Height; h++ ) {

                        CopyMem( from, to, row );

                        from += Img->BytesPerRow;
                        to   += Brush->BitMap->BytesPerRow;
                    }
                }

                i = ( 1L << Img->Depth ) * 3;

                if( Brush->Colors = AllocVec( i * sizeof( ULONG ), MEMF_ANY )) {
                    UBYTE  *from;

                    if( from = Img->CReg ) {
                        ULONG   n, *to;

                        to = Brush->Colors;

                        for( n = 0; n < i; n++ ) {
                            UBYTE   c;

                            c = *from++;

                            *to++ = ( c << 24 ) | ( c << 16 ) | ( c << 8 ) | c;
                        }
                    }

                    err = FALSE;
                }
            }

            if( err ) {
                FreeMem( Brush, sizeof( struct MyBrush ));
                Brush = NULL;
            }
        }

        FreeImg( Img );
    }

    return( Brush );
}
///
/// FreeBrush
void FreeBrush( struct MyBrush *Brush )
{
    if( Brush ) {

        DeleteBitMap( Brush->BitMap );

        FreeVec( Brush->Colors );

        FreeMem( Brush, sizeof( struct MyBrush ));
    }
}
///

