Aros/Developer/Docs/Libraries/DataTypes
Introduction
editThe datatypes.library was introduced to decode file formats (#?.png #?.jpg etc.) easily using different classes which can be installed as they are needed.
First you should learn about BOOPSI (Amiga OOP object oriented system). Once understand, it's makes it easier to understand datatypes, MUI, etc
The descriptors in devs/datatypes contain the information how to identify a file type. Usually the file is opened only once by datatypes.library and a small buffer is used for comparisons which contains the first few bytes of the file (64 bytes IIRC).
dt descriptor is related to the struct DataTypeHeader dth_Name, dth_BaseName, etc.
Most datatype descriptors are held very simple, for example "compare the first 12 bytes with the pattern FORM????ILBM". The comparison is done by datatypes.library, there is no foreign code involved.
Only very few descriptors actually contain code. In this code everything can be done, though. For example, the code can close and reopen the file and read it entirely if needed. But this should not be done because identification needs to be very fast.
Dtdesc tool (and accompanied documentation) createdtdesc package is aimed at creating (picture) datatypes (as a whole, including makefiles). dtdescr is aimed at (only) viewing and creating the descriptor.
Once the file type is identified and the application wants to load the file, the class library from classes/datatypes is called. This library contains the code to decode the file contents and to make it available to datatypes.library.
Datatypes consist of a few libraries that exposes a couple of methods to load and save pictures of a certain type. Internally there is a 'common' storage method of the pixels that is used by the picture datatype, and so each 'library' that can handle its own type is able to 'convert' this common storage method into a specific format or load to this specific format.
The datatypes system itself exposes methods for the developer/user that allows for easy loading and saving by just calling some functions.
The only problem with AmigaOS implementation of datatypes is that they aren't really bidirectional. You can generally only save in IFF but AROS aspires to bring the original idea back
The ideal implementation would allow each datatype superclass (picture.datatype, sound.datatype etc.) to provide a list of all currently known sub-classes that support encoding. You'd then be able to pick one and encode data for that datatype and write it out to disk in that format.
Wanderer (AROS WB replacement) does not utilise the datatype subsystem directly "except" for loading window background imagery. The datatype system cannot deal with progressive loading and streaming yet.
How to Use
editcreate a Datatype Object, use the NewDTObject function ...
gd->gd_DisplayObject = NewDTObject ((IPTR)gd->gd_Unit, DTA_SourceType, DTST_CLIPBOARD, GA_Immediate, TRUE, GA_RelVerify, TRUE, DTA_TextAttr, (ULONG) & gd->gd_TextAttr, TAG_DONE))
The parameters of this functions uses Tags as defined in datatypes/datatypesclasses.h and intuition/gadgetclass.h
gf->gd_Unit = the Clipboard unit number DTST_Clipboard = the Clipboard is the data source GA_Immediate = Should the object be active when displayed GA_RelVerify = Verify that the pointer is over the object when it is selected gd_->gd_TextAttr = Pointer to text font attributes
Once a datatype object is no longer required, it is disposed of and memory released: e.g.
DisposeDTObject (gd->gd_DisplayObject);
To get attributes from a datatype object, you can use the GetDTAttrs function e.g.
GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);
and examining the results from the dtn structure you can retrieve:
dtn->dtn_Header->dth_Name = Descriptive name of the datatype dtn->dtn_Header->dth_GroupID = The group the datatype belongs to
The function GetDTString returns a localised Datatypes string of the id given. This string could be syst, text, docu, soun, inst, musi, pict, anim or movi (see datatypes.h). e.g.
GetDTString (dtn->dtn_Header->dth_GroupID)
opening a file and know the base class it is, you just need:
Object *dto; if(dto = NewDTObject(filename, DTA_GroupID, GID_TEXT, TAG_DONE)) DisposeDTObvject(dto);
The DTA_GroupID tag ensure that the file is of that type. Otherwise you'll get problems later when you try to read data.
You'll need to use GetDTAttrs or call some methods before DisposeDTObject, if you want to do anything useful.
If you merely want to find out what filetype a file is, you need something like:
struct DataTypeHeader *dth = NULL; struct DataType *dtn; if (dtn = ObtainDataTypeA (DTST_FILE, (APTR)lock, NULL)) { dth = dtn->dtn_Header; printf("Group: %sn",dth->dth_GroupID); printf("BaseName: %sn",dth->dth_BaseName); ReleaseDataType(dtn); }
You can then open the file and handle it as per the base type dth_GroupID
what you usually do is, to create an object (initial state), get/set some attributes (attribute change) and then do layout or extract a type.
in that case there many programs that call remap but doesn't have a gpinfo structure.
is there some info what remap have on initial state ?
AROS dt set it to true.
pd->Remap = TRUE;
when a program has no gpinfo with screen, then remap should be set to false. Maybe AmigaOS AOS does that somewhere.
same can happen on AROS dt too, maybe on AOS dt bitmap (state change and get/set); however it is not clearly defined in which way state changes may affect attributes (screen, colors) or what happens in case some attributes have not been set prior triggering the state change; it's not even exactly clear which states are possible
Your application can find out when a refresh is appropriate by using the Boopsi ICATarget attribute with the ICTargetIDCMP value. This causes the datatype (gadget) to send an IDCMP_IDCMPUpdate IntuiMessage to the window port on certain status changes. That message carries a pointer to one or more attributes and if DTA_Sync is in that list with a value of 1 then the datatype object is ready for refresh.
You get one of these on attaching the datatype object to your window, and also a stream of them when the window is resized.
In order to create a jpeg datatype object (jpeg subclass of picture class)
DTImage = NewDTObject(NULL, DTA_SourceType, DTST_RAM, DTA_BaseName, "jpeg", PDTA_DestMode, PMODE_V43, TAG_DONE);
Text
editAROS/workbench/classes/datatypes/text/ V44.5 of the text.datatype replacement sebauer@t-online.de (Sebastian Bauer)
Most OS outside AROS prefer XML but others like doc, docx, ood, rtf, etc
Originally, FTXT was used by the the clipboard for cut/copy function on AmigaOS, current apps use only use raw ASCII data. IFF FTXT is supposed to be Formatted TeXT, but there's very little formatting apparently supported, and this impacts what can be put on the clipboard too (copying a table with all the formatting intact is not easy).
#include <graphics/text.h> #include <graphics/rastport.h> #include <intuition/gadgetclass.h> #include <intuition/cghooks.h> #include <intuition/classusr.h> #ifndef LNF_MARKED #define LNF_MARKED (1<<15) #endif struct Text_Data { LONG left, top; /* Offsets of the gadget */ LONG width, height; /* Dimensions of the gadget */ LONG fillpen, filltextpen; /* pens for marking */ #ifndef COMPILE_DATATYPE struct Screen *screen; /* Screen on which the gadget lies */ struct DrawInfo *drinfo; /* Resulting from screen */ struct RastPort *rp; APTR line_pool; #else LONG update_type; LONG update_arg; LONG mouse_pressed; LONG redraw; #endif STRPTR title; UBYTE *buffer_allocated; ULONG buffer_allocated_len; struct List line_list; /* double linked list of the lines */ char *word_delim; LONG word_wrap; struct TextFont *font; struct TextAttr attr; LONG horiz_visible; LONG vert_visible; LONG vert_top; LONG horiz_top; LONG horiz_unit; LONG vert_unit; LONG vert_diff; /* For optimized Scrolling */ LONG use_vert_diff; LONG horiz_diff; LONG use_horiz_diff; LONG mark_x1; LONG mark_x2; LONG mark_y1; LONG mark_y2; struct Line *mark_line1; struct Line *mark_line2; LONG pressed; LONG copy_text; /* if mb is released, copy the text into the clipboard */ LONG doubleclick; /* 1 if doubleclicked, 2 if trippleclicked */ LONG lastsecs; /* For Doubleclick check */ LONG lastmics; struct TextExtent te; struct RastPort font_rp; char search_buffer[128]; struct Process *search_proc; /* the search requester process */ struct GadgetInfo search_ginfo; /* for the search process */ int search_line; int search_pos; /* x position */ int search_case; #ifdef MORPHOS_AG_EXTENSION LONG links; struct Line *marked_line; struct Line *selected_line; struct Line *last_marked_line; LONG shinepen, shadowpen; BOOL link_pressed; Object *obj; UBYTE word[128]; /* double clicked word */ struct GadgetInfo *ginfo; #endif }; #ifdef __cplusplus extern "C" { #endif APTR Text_Create(void); VOID Text_SetFrameBox( APTR mem, struct Screen *scr, struct RastPort *rp, LONG left, LONG top, LONG width, LONG height); VOID Text_Load(APTR mem, STRPTR); VOID Text_ChangeDimension( APTR mem, LONG left, LONG top, LONG width, LONG height); VOID Text_Redraw( APTR mem ); VOID Text_Free(APTR mem); ULONG Text_PageHeight( APTR mem ); ULONG Text_PageWidth( APTR mem ); ULONG Text_VisibleHeight( APTR mem ); ULONG Text_VisibleTop( APTR mem ); ULONG Text_VisibleHoriz( APTR mem ); VOID Text_SetVisibleTop( APTR mem, ULONG newy ); VOID Text_SetVisibleLeft( APTR mem, ULONG newx ); VOID Text_HandleMouse( APTR mem, LONG x, LONG y, LONG code, ULONG secs, ULONG mics); VOID Text_Print( APTR mem ); #ifdef __cplusplus } #endif
Picture
editAROS/workbench/classes/datatypes/picture/
/* Copyright (C) 1995-2020, The AROS Development Team. All rights reserved. */ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #include <datatypes/pictureclass.h> #include <graphics/gfx.h> struct Picture_Data { /* * public entries, accessible with SET/GET */ ULONG Precision; ULONG ModeID; struct BitMapHeader bmhd; struct BitMap *SrcBM; /* PDTA_BitMap and PDTA_ClassBM */ ULONG SrcColRegs[256 * 3]; /* PDTA_CRegs */ struct BitMap *DestBM; UBYTE *MaskPlane; ULONG DestColRegs[256 * 3]; /* PDTA_GRegs */ struct Screen *DestScreen; struct ColorRegister ColMap[256]; UBYTE ColTable[256]; UWORD NumColors; UWORD NumPictures; UWORD WhichPicture; UWORD NumAlloc; UBYTE SparseTable[256]; UWORD NumSparse; Point Grab; UWORD MaxDitherPens; UWORD DitherQuality; UWORD ScaleQuality; BOOL FreeSource; BOOL Remap; BOOL UseFriendBM; BOOL DestMode; BOOL DelayRead; BOOL DelayedRead; /* * private entries */ UBYTE *SrcBuffer; ULONG SrcWidth; ULONG SrcWidthBytes; ULONG SrcHeight; LONG SrcPixelFormat; UWORD SrcPixelBytes; UWORD SrcDepth; ULONG DestWidth; ULONG DestHeight; ULONG ColTableXRGB[256]; UWORD DestDepth; BOOL TrueColorSrc; BOOL TrueColorDest; BOOL Layouted; BOOL UseAsImage; BOOL KeepSrcBM; BOOL NoDelay; BOOL Scale; ULONG XScale; ULONG YScale; LONG ClickX; LONG ClickY; struct Screen *RemapScreen; };
The following items must be implemented: library-framework 100% done dispatcher-function 100% done methods: OM_NEW OK OM_DISPOSE OK OM_UPDATE part of OM_SET OM_SET OK, see below OM_GET OK, see below GM_RENDER OK GM_LAYOUT uses DTM_ASYNCLAYOUT GM_GOACTIVE superclass GM_HANDLEINPUT superclass GM_HITTEST superclass DTM_PROCLAYOUT uses DTM_ASYNCLAYOUT DTM_ASYNCLAYOUT OK, improvements in speed and quality possible DTM_FRAMEBOX superclass DTM_SELECT ? DTM_CLEARSELECTED ? DTM_COPY missing DTM_PRINT missing DTM_WRITE missing PDTM_WRITEPIXELARRAY OK PDTM_READPIXELARRAY mostly done PDTM_SCALE in progress The following attributes must be supported: OBP_Precision (I) OK DTA_Methods (G) OK PDTA_ModeID (ISG) OK, but not used internally PDTA_BitMapHeader (G) OK PDTA_BitMap (ISG) OK PDTA_DestBitMap (G) OK, with limitations PDTA_ClassBitMap (ISG) OK, can't be used in parallel with PDTA_BitMap PDTA_Screen (ISG) OK, alternate mapping dest ? (additional Get) PDTA_ColorRegisters (G) OK, but not used internally PDTA_CRegs (G) OK PDTA_GRegs (G) OK PDTA_ColorTable (G) OK ? private PDTA_ColorTable2 (G) OK ? private PDTA_NumColors (ISG) OK PDTA_NumAlloc (G) OK PDTA_Allocated (G) not implemented, obsolete (wasn't clearly defined) PDTA_SparseTable (I) OK PDTA_NumSparse (I) OK PDTA_Grab (ISG) OK ? PDTA_FreeSourceBitMap (ISG) OK (additional Get) PDTA_Remap (I) OK, set get ? PDTA_UseFriendBitMap (ISG) OK, but not used internally PDTA_SourceMode (ISG) OK, but ignored internally PDTA_DestMode (ISG) OK, but ignored internally PDTA_MaxDitherPens (ISG) OK ? PDTA_DitherQuality (ISG) OK ? PDTA_AllocatedPens (G) OK ? PDTA_ScaleQuality (ISG) OK, but not used internally PDTA_DelayRead (I) OK ? PDTA_DelayedRead (SG) OK ? (Set only by subclass)
Sound
editAROS/workbench/classes/datatypes/sound.datatype based on Stephan Rupprechts sounddt 41 from Aminet
only have two sound datatypes for AROS those being Wave Datatype & 8SVX Datatype. The 8SVX datatype first looked at OM_NEW & Read8SVX. But the Read Function doesn't test for DTST_RAM & an empty filehandle
8bit sound only with 16bit 32bit still needed
#ifndef DATATYPES_SOUNDCLASS_H #include <datatypes/soundclass.h> #endif #include <intuition/classes.h> #include <exec/execbase.h> /****************************************************************************/ struct ClassBase { /* std library stuff */ struct Library LibNode; UWORD pad_word; #ifndef __AROS__ BPTR LibSegment; struct ExecBase *cb_SysBase; #endif struct SignalSemaphore cb_LibLock; /* library bases */ #if !defined(__MAXON__) && !defined(__AROS__) struct Library *cb_IntuitionBase; struct Library *cb_GfxBase; struct Library *cb_DOSBase; struct Library *cb_UtilityBase; struct Library *cb_DataTypesBase; struct Library *cb_IFFParseBase; struct Library *cb_TapeDeckBase; #endif Class *cb_Class; ULONG *cb_Methods; /* prefs */ BOOL cb_AIFF; BOOL cb_AHI; ULONG cb_AHIModeID; ULONG cb_AHIMixFrequency; UWORD cb_NomWidth; UWORD cb_NomHeight; ULONG cb_WfCol[3]; ULONG cb_BgCol[3]; BOOL cb_Compress; BOOL cb_ForceAHIMode; ULONG cb_BufferSize; UWORD cb_Volume; BOOL cb_ControlPanel; BOOL cb_NoGTSlider; }; /****************************************************************************/ struct InstanceData { struct ClassBase *ClassBase; struct SignalSemaphore Lock; /* v39 tags */ struct VoiceHeader VoiceHeader; BYTE *Sample; ULONG SampleLength; UWORD Frequency; UWORD Volume; UWORD Cycles; /* v40 tags */ UWORD Continuous; struct Task *SignalTask; BYTE SignalBit; /* v41 tags */ UBYTE SampleType; ULONG Panning; /* v44 tags */ struct timeval ReplayPeriod; BOOL LeftSample; // SDTA_Sample is SDTA_LeftSample? UWORD pad_word2; BYTE *RightSample; BOOL SyncSampleChange; BOOL FreeSampleData; /* additional tags */ BOOL Immediate; BOOL Repeat; BOOL DelayedImmed; /* offset */ ULONG StartSample; ULONG EndSample; /* private data */ struct Process *PlayerProc; struct MsgPort *PlayerPort; /* for STM_STOP (doubleclick) */ struct timeval LastClick; /* DTM_SELECT */ WORD MinX; WORD MaxX; BOOL MarkMode; /* controlpanel */ WORD pad_word; WORD TapeDeckHeight; BOOL ControlPanel; struct Gadget *TapeDeckGadget; struct Gadget *VolumeSlider; struct Gadget *ActiveMember; struct Screen *Screen; // DTM_DRAW struct DrawInfo *DrawInfo; // DTM_DRAW struct Window *Window; struct Requester *Requester; struct Gadget *Gadget; struct ColorMap *ColorMap; // Needed to release allocated pens, GInfo of DTM_REMOVEDTOBJECT == NULL WORD WaveformPen; // Drawing pens WORD BackgroundPen; BOOL ForceRefresh; // bugfix (?) for gmv }; /****************************************************************************/ struct ObjectMsg { struct Message Message; ULONG Command; APTR Data; // ULONG ErrorCode; }; enum { COMMAND_INIT, COMMAND_EXIT, COMMAND_PLAY, COMMAND_STOP, COMMAND_PAUSE, COMMAND_PERVOL, COMMAND_NEXT_BUFFER }; /****************************************************************************/
Animation
edit/* Copyright � 2015-2020, The AROS Development Team. All rights reserved. $Id$ */ #include <graphics/gfx.h> #include <datatypes/pictureclass.h> #include <datatypes/animationclass.h> #include <datatypes/animationclassext.h> #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /* api flags */ #define ANIMDF_CONTROLPANEL (1 << 0) #define ANIMDF_IMMEDIATE (1 << 1) #define ANIMDF_REPEAT (1 << 2) #define ANIMDF_REMAP (1 << 3) #define ANIMDF_ADJUSTPALETTE (1 << 4) #define ANIMDF_ADAPTFPS (1 << 5) #define ANIMDF_FRAMESKIP (1 << 6) #define ANIMDF_SMARTSKIP (1 << 7) /* special flags used by rendering/layout code */ #define ANIMDF_LAYOUT (1 << 29) #define ANIMDF_REMAPPEDPENS (1 << 30) #define ANIMDF_SHOWPANEL (1 << 31) #define ANIMPLAYER_TICKFREQ ((struct RealTimeBase *)RealTimeBase)->rtb_Reserved1 struct ProcessPrivate; struct Animation_Data; struct AnimFrame; BOOL ProcEnabled(struct ProcessPrivate *, volatile ULONG *, ULONG); void cacheFrame(struct Animation_Data *, struct AnimFrame *); void freeFrame(struct Animation_Data *, struct AnimFrame *); struct AnimColor_Data { struct SignalSemaphore acd_PenLock; struct ColorMap *acd_ColorMap; struct ColorRegister *acd_ColorRegs; ULONG *acd_CRegs; ULONG *acd_GRegs; UWORD acd_NumColors; UWORD acd_NumAlloc; UBYTE *acd_ColorTable[2]; UBYTE *acd_Allocated; /* pens we have actually allocated */ ULONG acd_PenPrecison; /* precision to use allocating pens */ }; struct AnimFrame_Data { struct SignalSemaphore afd_AnimFramesLock; struct List afd_AnimFrames; UWORD afd_Frames; /* # of frames */ UWORD afd_FrameCurrent; /* # of current frame */ UWORD afd_FramesStep; /* how much to skip back/fwd */ }; struct AnimTimer_Data { UWORD atd_FramesPerSec; /* Playback rate */ UWORD atd_TicksPerFrame; /* realtime.libraries tick frequency / ad_FramesPerSec */ UWORD atd_Tick; }; /* our nodes used to play the anim! */ struct AnimFrame { struct Node af_Node; #define af_CacheBM af_Node.ln_Name ULONG af_Flags; struct adtNewFormatFrame af_Frame; }; #define AFFLAGB_READY 0 #define AFFLAGF_READY (1 << 0) /* for sanity, we embed the frame number in the ln_type/ln_pri fields */ static inline UWORD GetNODEID(struct AnimFrame *node) { UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type; return *id_ptr; } static inline void SetNODEID(struct AnimFrame *node, UWORD id) { UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type; *id_ptr = id; } struct Animation_Data { ULONG ad_Flags; /* object control flags */ char *ad_BaseName; struct Window *ad_Window; struct AnimFrame_Data ad_FrameData; struct AnimTimer_Data ad_TimerData; struct BitMap *ad_FrameBM; /* currently displayed frame */ struct BitMap *ad_CacheBM; /* .. */ struct AnimFrame *ad_KeyFrame; /* animations key (first) frame */ UWORD ad_VertTop; /* Y offset of visible rectangle */ UWORD ad_VertTotal; UWORD ad_VertVis; UWORD ad_HorizTop; /* X offset of visible rectangle */ UWORD ad_HorizTotal; UWORD ad_HorizVis; UWORD ad_RenderLeft; UWORD ad_RenderTop; UWORD ad_RenderWidth; UWORD ad_RenderHeight; IPTR ad_ModeID; struct BitMapHeader ad_BitMapHeader; /* objects embedded bitmap header */ struct AnimColor_Data ad_ColorData; IPTR ad_ProcStack; struct ProcessPrivate *ad_ProcessData; struct Process *ad_BufferProc; /* buffering process */ struct Process *ad_PlayerProc; /* playback process */ struct Player *ad_Player; struct Hook ad_PlayerHook; struct Gadget *ad_Tapedeck; ULONG ad_BufferTime; /* (prefs) how many seconds to buffer */ ULONG ad_BufferStep; /* (prefs) no of frames to try to load in one go */ UBYTE ad_PlayerSourceLastState; }; struct ProcessPrivate { Object *pp_Object; struct Animation_Data *pp_Data; char *pp_PlayBackName; char *pp_BufferingName; volatile ULONG pp_PlayerFlags; volatile ULONG pp_BufferFlags; ULONG pp_BufferFrames; /* no of frames to buffer in total */ ULONG pp_BufferLevel; /* no of frames buffered */ IPTR pp_BufferSpecific; /* specific frame to load */ struct AnimFrame *pp_BufferFirst; /* starting point to load from */ struct AnimFrame *pp_PlaybackFrame; ULONG pp_BufferSigMask; BYTE pp_BufferEnable; BYTE pp_BufferDisable; BYTE pp_BufferFill; BYTE pp_BufferPurge; ULONG pp_PlaybackSigMask; BYTE pp_PlaybackEnable; BYTE pp_PlaybackDisable; BYTE pp_PlaybackTick; /* signal frames needs to change */ BYTE pp_PlaybackSync; /* signal position changed */ }; #define PRIVPROCF_ENABLED (1 << 0) #define PRIVPROCF_RUNNING (1 << 1) #define PRIVPROCF_ACTIVE (1 << 2) #define PRIVPROCF_BUSY (1 << 3) #define TAG_PRIVATE (ADTA_Dummy + 100) #define PRIVATE_INITPLAYER (TAG_PRIVATE - 1) #define PRIVATE_ALLOCCOLORTABLES (TAG_PRIVATE - 2) #define PRIVATE_MAPFRAMEPENS (TAG_PRIVATE - 3) #define PRIVATE_FREECOLORTABLES (TAG_PRIVATE - 4) #define PRIVATE_FREEPENS (TAG_PRIVATE - 5) #define PRIVATE_ALLOCBUFFER (TAG_PRIVATE - 6) #define PRIVATE_RENDERFRAME (TAG_PRIVATE - 7) #define PRIVATE_REMAPFRAME (TAG_PRIVATE - 8) struct privAllocColorTables { STACKED ULONG MethodID; STACKED ULONG NumColors; }; struct privMapFramePens { STACKED ULONG MethodID; STACKED struct AnimFrame *Frame; }; struct privAllocBuffer { STACKED ULONG MethodID; STACKED struct BitMap *Friend; STACKED UBYTE Depth; }; struct privRenderFrame { STACKED ULONG MethodID; STACKED struct AnimFrame *Frame; STACKED struct BitMap *Target; }; #if DEBUG > 0 #define DFRAMES(...) bug(__VA_ARGS__); #else #define DFRAMES(...) #endif
Creating New Datatypes
editText
editOther text sub-classes are
The original specs provided some support for FTXT, an IFF “data section” or “FORM type”
Text is stored in one or more “CHRS” chunks inside an FTXT. Each CHRS contains a stream of 8-bit text compatible with ANSI/ISO standard
- C0 terminal control characters in the range NUL (hex 00) through hex 1F. Only LF (hex 0A) and ESC (hex 1B) are significant. ESC begins a control sequence. LF is the line terminator, CR (hex 0D) is not recognized as terminator.
- G0 gui graphic characters in the range hex 20 through hex 7F. SP (hex 20) is the space character. DEL (hex 7F) is the delete character which is not used. The rest are the standard ASCII printable characters “!” (hex 21) through “~” (hex 7E).
- C1 extended control characters in the range hex 80 through hex 9F. The control sequence starting with CSI (hex 9B) is used for FTXT formatting. All other control sequences and C1 control characters are unused.
- G1 is the group of extended graphic characters in the range NBSP (hex A0) through “y” (hex FF).
optional “FONS” holds a FontSpecifier as below. It assigns a font to a numbered register so it can be referenced by number within other CHRS chunks. CHRS text uses font 1 until another font is chosen. If font 1 hasn’t been specified, the selected system font is used as font 1. The SGR sequence has parameters 10-19 to select from ten pre-defined fonts meaning only ten FONS chunks would be meaningful within an IFF FTXT file
If application programmers ever start using formatted text as per the FTXT specification, other programmers can no longer assume the clipboard to only include plain text data. Therefore, they'll need to implement proper control-code stripping (again, as per the FTXT specification) in their clipboard handling routines
typedef struct { UBYTE id; /* 0 through 9 is a font id number referenced by an SGR control sequence selective parameter of 10 through 19. Other values are reserved for future standardization. */ UBYTE pad1; /* reserved for future use; store 0 here */ UBYTE proportional; /* proportional font-- 0=unknown, 1=no, 2=yes */ UBYTE serif; /* serif font-- 0 = unknown, 1 = no, 2 = yes */ char name[]; /* A NUL-terminated string naming the preferred font. */ } FontSpecifier;
Picture
editOther datatypes for image files that can store multiple images such as INFO, ICO, ICNS, etc. added "WhichPicture" & "GetNumPictures" PDTA Methods to the AROS picture datatype. We can display multiple images using picture datatypes!
It would be easy to add a function to Count Image Directories (IFD's) for GetNumPictures.
TIFF Datatype can count directories using PDTA_GetNumPictures and it can set a directory current using PDTA_WhichPicture. So now it can display Multiple Images.
/*
Copyright © 1995-2005, The AROS Development Team. All rights reserved.
$Id: bmpclass.c 30902 2009-03-14 13:38:20Z mazze $
*/
/**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <cybergraphx/cybergraphics.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>
#include <aros/symbolsets.h>
#include "debug.h"
#include "methods.h"
/* Open superclass */
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);
/**************************************************************************************************/
#define FILEBUFSIZE 65536
#define MAXCOLORS 256
typedef struct {
struct IFFHandle *filehandle;
UBYTE *filebuf;
UBYTE *filebufpos;
long filebufbytes;
long filebufsize;
UBYTE *linebuf;
UBYTE *linebufpos;
long linebufbytes;
long linebufsize;
APTR codecvars;
} BmpHandleType;
typedef struct
{
WORD bfType; // 0 ASCII "BM"
ULONG bfSize; // 2 Size in bytes of the file
WORD bfReserved1; // 6 Zero
WORD bfReserved2; // 8 Zero
ULONG bfOffBits; // 10 Byte offset in files where image begins
} FileBitMapHeader __attribute__((packed)); // 14
typedef struct
{
ULONG biSize; // 0 Size of this header, 40 bytes
LONG biWidth; // 4 Image width in pixels
LONG biHeight; // 8 Image height in pixels
WORD biPlanes; // 12 Number of image planes, must be 1
WORD biBitCount; // 14 Bits per pixel, 1, 4, 8, 24, or 32
ULONG biCompression; // 16 Compression type, below
ULONG biSizeImage; // 20 Size in bytes of compressed image, or zero
LONG biXPelsPerMeter; // 24 Horizontal resolution, in pixels/meter
LONG biYPelsPerMeter; // 28 Vertical resolution, in pixels/meter
ULONG biClrUsed; // 32 Number of colors used, below
ULONG biClrImportant; // 36 Number of "important" colors
} BitmapInfoHeader __attribute__((packed)); // 40
/* "BM" backwards, due to LE byte order */
#define BITMAP_ID "MB"
/**************************************************************************************************/
static void BMP_Exit(BmpHandleType *bmphandle, LONG errorcode)
{
D(if (errorcode) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode));
if (bmphandle->filebuf)
{
FreeMem(bmphandle->filebuf, bmphandle->filebufsize);
}
if (bmphandle->linebuf)
{
FreeMem(bmphandle->linebuf, bmphandle->linebufsize);
}
if (bmphandle->codecvars)
{
FreeVec(bmphandle->codecvars);
}
SetIoErr(errorcode);
}
/**************************************************************************************************/
/* buffered file access, useful for RLE */
BOOL SaveBMP_EmptyBuf(BmpHandleType *bmphandle, long minbytes)
{
long bytes, bytestowrite;
bytestowrite = bmphandle->filebufsize - (bmphandle->filebufbytes + minbytes);
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes, (long)bytestowrite));
bytes = Write(bmphandle->filehandle, bmphandle->filebuf, bytestowrite);
if ( bytes < bytestowrite )
{
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes));
return FALSE;
}
bmphandle->filebufpos = bmphandle->filebuf;
bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
return TRUE;
}
/* buffered file access, useful for RLE */
BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
{
long i, bytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
if ( bmphandle->filebufbytes >= 0 )
return TRUE;
bytes = bmphandle->filebufbytes + minbytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
if (bytes > 0)
{
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
for (i=0; i<bytes; i++) /* copy existing bytes to start of buffer */
bmphandle->filebuf[i] = bmphandle->filebufpos[i];
}
bmphandle->filebufpos = bmphandle->filebuf;
bytes = Read(bmphandle->filehandle, bmphandle->filebuf + bytes, bmphandle->filebufsize - bytes);
if (bytes < 0 ) bytes = 0;
bmphandle->filebufbytes += bytes;
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
//D(bug("bmp.datatype/LoadBMP_FillBuf() --- >minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
if (bmphandle->filebufbytes >= 0)
return TRUE;
return FALSE;
}
static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
struct ColorRegister *colormap, ULONG *colregs)
{
unsigned int i, j;
if (numcolors && numcolors <= MAXCOLORS)
{
j = 0;
for (i = 0; i < numcolors; i++)
{
if ( (bmphandle->filebufbytes -= 4) < 0 && !LoadBMP_FillBuf(bmphandle, 4) )
{
D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
return FALSE;
}
/* BGR0 format for MS Win files, BGR format for OS/2 files */
colormap[i].blue = *(bmphandle->filebufpos)++;
colormap[i].green = *(bmphandle->filebufpos)++;
colormap[i].red = *(bmphandle->filebufpos)++;
bmphandle->filebufpos++;
colregs[j++] = ((ULONG)colormap[i].red)<<24;
colregs[j++] = ((ULONG)colormap[i].green)<<24;
colregs[j++] = ((ULONG)colormap[i].blue)<<24;
// D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
}
D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors));
}
return TRUE;
}
/**************************************************************************************************/
static BOOL LoadBMP(struct IClass *cl, Object *o)
{
BmpHandleType *bmphandle;
UBYTE *filebuf;
IPTR sourcetype;
ULONG bfSize, bfOffBits;
ULONG biSize, biWidth, biHeight, biCompression;
ULONG biClrUsed, biClrImportant;
UWORD biPlanes, biBitCount;
ULONG alignwidth, alignbytes, pixelfmt;
long x, y;
int cont, byte;
struct BitMapHeader *bmhd;
struct ColorRegister *colormap;
ULONG *colorregs;
STRPTR name;
D(bug("bmp.datatype/LoadBMP()\n"));
if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
bmphandle->filebuf = NULL;
bmphandle->linebuf = NULL;
bmphandle->codecvars = NULL;
if( GetDTAttrs(o, DTA_SourceType , (IPTR)&sourcetype ,
DTA_Handle , (IPTR)&(bmphandle->filehandle),
PDTA_BitMapHeader , (IPTR)&bmhd,
TAG_DONE) != 3 )
{
BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
if ( sourcetype == DTST_RAM && bmphandle->filehandle == NULL && bmhd )
{
D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
if ( sourcetype != DTST_FILE || !bmphandle->filehandle || !bmhd )
{
D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
/* initialize buffered file reads */
bmphandle->filebufbytes = 0;
bmphandle->filebufsize = FILEBUFSIZE;
if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
/* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
if ( (bmphandle->filebufbytes -= 14) < 0 && !LoadBMP_FillBuf(bmphandle, 14) )
{
D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 14;
if( filebuf[0] != 'B' && filebuf[1] != 'M' )
{
D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
/* byte-wise access isn't elegant, but it is endianess-safe */
bfSize = (filebuf[5]<<24) | (filebuf[4]<<16) | (filebuf[3]<<8) | filebuf[2];
bfOffBits = (filebuf[13]<<24) | (filebuf[12]<<16) | (filebuf[11]<<8) | filebuf[10];
D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize, bfOffBits));
/* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
if ( (bmphandle->filebufbytes -= 40) < 0 && !LoadBMP_FillBuf(bmphandle, 40) )
{
D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 40;
/* get image size attributes */
biSize = (filebuf[3]<<24) | (filebuf[2]<<16) | (filebuf[1]<<8) | filebuf[0];
biWidth = (filebuf[7]<<24) | (filebuf[6]<<16) | (filebuf[5]<<8) | filebuf[4];
biHeight = (filebuf[11]<<24) | (filebuf[10]<<16) | (filebuf[9]<<8) | filebuf[8];
biPlanes = (filebuf[13]<<8) | filebuf[12];
biBitCount = (filebuf[15]<<8) | filebuf[14];
biCompression = (filebuf[19]<<24) | (filebuf[18]<<16) | (filebuf[17]<<8) | filebuf[16];
biClrUsed = (filebuf[35]<<24) | (filebuf[34]<<16) | (filebuf[33]<<8) | filebuf[32];
biClrImportant = (filebuf[39]<<24) | (filebuf[38]<<16) | (filebuf[37]<<8) | filebuf[36];
D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
biWidth, biHeight, (long)biBitCount, biClrUsed, biClrImportant, biCompression, biSize));
if (biSize != 40 || biPlanes != 1 || biCompression != 0)
{
D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
/* check color mode */
pixelfmt = PBPAFMT_LUT8;
switch (biBitCount)
{
case 1:
alignwidth = (biWidth + 31) & ~31UL;
alignbytes = alignwidth / 8;
break;
case 4:
alignwidth = (biWidth + 7) & ~7UL;
alignbytes = alignwidth / 2;
break;
case 8:
alignwidth = (biWidth + 3) & ~3UL;
alignbytes = alignwidth;
break;
case 24:
alignbytes = (biWidth + 3) & ~3UL;
alignwidth = alignbytes * 3;
pixelfmt = PBPAFMT_RGB;
break;
default:
D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
return FALSE;
}
D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));
/* set BitMapHeader with image size */
bmhd->bmh_Width = bmhd->bmh_PageWidth = biWidth;
bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
bmhd->bmh_Depth = biBitCount;
/* get empty colormap, then fill in colormap to use*/
if (biBitCount != 24)
{
if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
PDTA_CRegs, (IPTR)&colorregs,
TAG_DONE ) == 2) ||
!(colormap && colorregs) )
{
D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
{
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
}
/* skip offset */
bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
if ( bfOffBits < 0 ||
( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
{
D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
bmphandle->filebufpos += bfOffBits;
/* Pass attributes to picture.datatype */
GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
DTA_NominalHoriz, biWidth,
DTA_NominalVert , biHeight,
DTA_ObjName , (IPTR)name,
TAG_DONE);
/* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
bmphandle->linebufsize = bmphandle->linebufbytes = alignwidth;
if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
//D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
cont = 1;
for (y=biHeight-1; y>=0 && cont; y--)
{
int r, g, b;
bmphandle->linebufpos = bmphandle->linebuf;
if (biBitCount == 24)
{
if ( (bmphandle->filebufbytes -= alignwidth) < 0 && !LoadBMP_FillBuf(bmphandle, alignwidth) )
{
D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
//return FALSE;
cont = 0;
}
for (x=0; x<alignbytes; x++)
{
b = *(bmphandle->filebufpos)++;
g = *(bmphandle->filebufpos)++;
r = *(bmphandle->filebufpos)++;
*(bmphandle->linebufpos)++ = r;
*(bmphandle->linebufpos)++ = g;
*(bmphandle->linebufpos)++ = b;
}
}
else
{
for (x=0; x<alignbytes; x++)
{
if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
{
D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
//return FALSE;
cont = 0;
break;
}
byte = *(bmphandle->filebufpos)++;
switch (biBitCount)
{
case 1:
for (b=0; b<8; b++)
{
*(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
byte <<= 1;
}
break;
case 4:
*(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
*(bmphandle->linebufpos)++ = (byte & 0x0f);
break;
case 8:
*(bmphandle->linebufpos)++ = byte;
break;
case 24:
*(bmphandle->linebufpos)++ = byte;
break;
}
}
}
if
(
!DoSuperMethod(cl, o,
PDTM_WRITEPIXELARRAY, /* Method_ID */
(IPTR)bmphandle->linebuf, /* PixelData */
pixelfmt, /* PixelFormat */
alignwidth, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
y, /* Top edge */
biWidth, /* Width */
1 /* Height (here: one line) */
)
)
{
D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
}
//D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
/**************************************************************************************************/
static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
BmpHandleType *bmphandle;
UBYTE *filebuf;
unsigned int width, height, widthxheight, numplanes, numcolors;
struct BitMapHeader *bmhd;
struct BitMap *bm;
struct RastPort rp;
long *colorregs;
int i, j, ret;
D(bug("bmp.datatype/SaveBMP()\n"));
if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
bmphandle->filebuf = NULL;
bmphandle->linebuf = NULL;
bmphandle->codecvars = NULL;
/* A NULL file handle is a NOP */
if( !dtw->dtw_FileHandle )
{
D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
bmphandle->filehandle = dtw->dtw_FileHandle;
/* Get BitMap and color palette */
if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR)&bmhd,
PDTA_BitMap, (IPTR)&bm,
PDTA_CRegs, (IPTR)&colorregs,
PDTA_NumColors, (IPTR)&numcolors,
TAG_DONE ) != 4UL ||
!bmhd || !bm || !colorregs || !numcolors)
{
D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
#if 0
/* Check if this is a standard BitMap */
if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
{
D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
#endif
/* initialize buffered file reads */
bmphandle->filebufsize = FILEBUFSIZE;
bmphandle->filebufbytes = bmphandle->filebufsize;
if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
/* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
{
D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 13;
/* set screen descriptor attributes (from BitMapHeader) */
width = bmhd->bmh_PageWidth;
height = bmhd->bmh_PageHeight;
numplanes = bmhd->bmh_Depth - 1;
numcolors = 1 << (numplanes + 1);
D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
filebuf[6] = width & 0xff;
filebuf[7] = width >> 8;
filebuf[8] = height & 0xff;
filebuf[9] = height >> 8;
filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
filebuf[11] = 0; /* this is fillcolor */
filebuf[12] = 0; /* this is pixel aspect ratio, 0 means unused */
/* write screen colormap, we don't use an image colormap */
for (i = 0; i < numcolors*3; i += 3)
{
if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
*(bmphandle->filebufpos)++ = colorregs[i] >> 24;
*(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
*(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
}
/* write image header, image has same size as screen */
if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
filebuf = bmphandle->filebufpos; /* this makes things easier */
bmphandle->filebufpos += 10;
filebuf[0] = ','; /* header ID */
filebuf[1] = filebuf[2] = 0; /* no left edge */
filebuf[3] = filebuf[4] = 0; /* no top edge */
filebuf[5] = width & 0xff;
filebuf[6] = width >> 8;
filebuf[7] = height & 0xff;
filebuf[8] = height >> 8;
filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */
/* Now read the picture data from the bitplanes and write it to a chunky buffer */
/* For now, we use a full picture pixel buffer, not a single line */
widthxheight = width*height;
bmphandle->linebufsize = bmphandle->linebufbytes = widthxheight;
if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
InitRastPort(&rp);
rp.BitMap=bm;
for (j=0; j<height; j++)
{
for (i=0; i<width; i++)
{
ret = (UBYTE)ReadPixel(&rp, i, j); /* very slow, to be changed */
*(bmphandle->linebufpos)++ = ret;
}
}
bmphandle->linebufpos = bmphandle->linebuf;
/* write the chunky buffer to file, after encoding */
/* write end-of-BMP marker */
if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
{
BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
return FALSE;
}
*(bmphandle->filebufpos)++ = ';';
/* flush write buffer to file and exit */
SaveBMP_EmptyBuf(bmphandle, 0);
D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
BMP_Exit(bmphandle, 0);
return TRUE;
}
/**************************************************************************************************/
IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
{
Object *newobj;
D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
newobj = (Object *)DoSuperMethodA(cl, o, msg);
if (newobj)
{
if (!LoadBMP(cl, newobj))
{
CoerceMethod(cl, newobj, OM_DISPOSE);
newobj = NULL;
}
}
return (IPTR)newobj;
}
/**************************************************************************************************/
IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
{
D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
if( (dtw -> dtw_Mode) == DTWM_RAW )
{
/* Local data format requested */
return SaveBMP(cl, o, dtw );
}
else
{
/* Pass msg to superclass (which writes an IFF ILBM picture)... */
return DoSuperMethodA( cl, o, (Msg)dtw );
}
}
/*
Copyright © 1995-2001, The AROS Development Team. All rights reserved.
$Id: ppmclass.c 30902 2009-03-14 13:38:20Z mazze $
*/
/**********************************************************************/
#define DEBUGMETHODS 0
/**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>
#include <aros/symbolsets.h>
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);
#include "debug.h"
#include "methods.h"
/**************************************************************************************************/
IPTR PPM__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{
IPTR RetVal;
char *Title;
IPTR sourcetype;
BPTR FileHandle;
struct BitMapHeader *bmhd;
char LineBuffer[128];
long Width, Height, NumChars;
unsigned int i;
unsigned char *RGBBuffer;
D(bug("ppm.datatype/OM_NEW: Entering\n"));
D(bug("ppm.datatype/OM_NEW: cl: 0x%lx o: 0x%lx msg: 0x%lx\n", (unsigned long) cl, (unsigned long) o, (unsigned long) msg));
RetVal=DoSuperMethodA(cl, o, (Msg) msg);
if(!RetVal)
{
D(bug("ppm.datatype/OM_NEW: DoSuperMethod failed\n"));
return(0);
}
D(bug("ppm.datatype/OM_NEW: DoSuperMethod: 0x%lx\n", (unsigned long) RetVal));
if( GetDTAttrs((Object *) RetVal,
DTA_SourceType , (IPTR)&sourcetype ,
DTA_Handle , (IPTR)&FileHandle,
DTA_Name , (IPTR)&Title,
PDTA_BitMapHeader , (IPTR)&bmhd,
TAG_DONE) != 4 )
{
D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) error !\n"));
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_OBJECT_NOT_FOUND);
return FALSE;
}
D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) successful\n"));
if ( sourcetype == DTST_RAM && FileHandle == NULL )
{
D(bug("ppm.datatype/OM_NEW: Creating an empty object\n"));
return TRUE;
}
if ( sourcetype != DTST_FILE || !FileHandle || !bmhd )
{
D(bug("ppm.datatype/OM_NEW: Unsupported sourcetype mode\n"));
SetIoErr(ERROR_NOT_IMPLEMENTED);
return FALSE;
}
D(bug("ppm.datatype/OM_NEW: Title: %s\n", Title?Title:"[none]"));
Seek(FileHandle, 0, OFFSET_BEGINNING);
D(bug("ppm.datatype/OM_NEW: Seek successful\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 1 failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(!(LineBuffer[0]=='P' && LineBuffer[1]=='6'))
{
D(bug("ppm.datatype/OM_NEW: Not a P6 PPM\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: It's a P6 PPM\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 2 failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(LineBuffer[0]=='#')
{
D(bug("ppm.datatype/OM_NEW: Line 2 is a comment\n"));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 3 after comment failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
}
NumChars=StrToLong(LineBuffer, (LONG *)&Width);
if(!((NumChars>0) && (Width>0)))
{
D(bug("ppm.datatype/OM_NEW: StrToLong(Width) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Width: %ld\n", (long) Width));
D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));
NumChars=StrToLong(LineBuffer+NumChars, (LONG *)&Height);
if(!((NumChars>0) && (Height>0)))
{
D(bug("ppm.datatype/OM_NEW: StrToLong(Height) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Height: %ld\n", (long) Height));
D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));
if(!FGets(FileHandle, LineBuffer, 128))
{
D(bug("ppm.datatype/OM_NEW: FGets line 3 (4) failed\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
if(!(LineBuffer[0]=='2' && LineBuffer[1]=='5' && LineBuffer[2]=='5'))
{
D(bug("ppm.datatype/OM_NEW: Wrong depth\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: Header successful read\n"));
bmhd->bmh_Width = Width;
bmhd->bmh_Height = Height;
bmhd->bmh_PageWidth = bmhd->bmh_Width;
bmhd->bmh_PageHeight = bmhd->bmh_Height;
D(bug("ppm.datatype/OM_NEW: Using 24 bit colors\n"));
bmhd->bmh_Depth = 24;
/* Get a buffer for one line of RGB triples */
RGBBuffer=AllocVec(Width*3, MEMF_ANY | MEMF_CLEAR);
if(!RGBBuffer)
{
D(bug("ppm.datatype/OM_NEW: AllocVec(RGBBuffer) failed\n"));
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_NO_FREE_STORE);
return(0);
}
D(bug("ppm.datatype/OM_NEW: RGBBuffer successfully allocated\n"));
/* Flush filehandle, so that unbuffered Read() can be used after buffered FGets() */
Flush(FileHandle);
/* Copy picture line by line to picture.datatype using WRITEPIXELARRAY method */
for(i=0; i<Height; i++)
{
if(!(Read(FileHandle, RGBBuffer, (Width*3))==(Width*3)))
{
D(bug("ppm.datatype/OM_NEW: Read(RGBBuffer) failed, maybe file too short\n"));
FreeVec(RGBBuffer);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return(0);
}
if(!DoSuperMethod(cl, (Object *) RetVal,
PDTM_WRITEPIXELARRAY, /* Method_ID */
(IPTR) RGBBuffer, /* PixelData */
PBPAFMT_RGB, /* PixelFormat */
Width*3, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
i, /* Top edge */
Width, /* Width */
1)) /* Height (here: one line) */
{
D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY failed\n"));
FreeVec(RGBBuffer);
CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
return(0);
}
}
D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY of whole picture done\n"));
FreeVec(RGBBuffer);
SetDTAttrs((Object *) RetVal, NULL, NULL, DTA_ObjName, (IPTR) Title,
DTA_NominalHoriz, Width,
DTA_NominalVert, Height,
TAG_DONE);
D(bug("ppm.datatype/OM_NEW: Leaving. (24 bit mode)\n"));
return(RetVal);
} /* PPM_New() */
/**************************************************************************************************/
static BOOL PPM_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
BPTR filehandle;
unsigned int width, height, numplanes, y;
UBYTE *linebuf;
struct BitMapHeader *bmhd;
long *colorregs;
D(bug("ppm.datatype/PPM_Save()\n"));
/* A NULL file handle is a NOP */
if( !dtw->dtw_FileHandle )
{
D(bug("ppm.datatype/PPM_Save() --- empty Filehandle - just testing\n"));
return TRUE;
}
filehandle = dtw->dtw_FileHandle;
/* Get BitMapHeader and color palette */
if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR) &bmhd,
PDTA_CRegs, (IPTR) &colorregs,
TAG_DONE ) != 2UL ||
!bmhd || !colorregs )
{
D(bug("ppm.datatype/PPM_Save() --- missing attributes\n"));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
width = bmhd->bmh_Width;
height = bmhd->bmh_Height;
numplanes = bmhd->bmh_Depth;
if( numplanes != 24 )
{
D(bug("ppm.datatype/PPM_Save() --- color depth %d, can save only depths of 24\n", numplanes));
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
D(bug("ppm.datatype/PPM_Save() --- Picture size %d x %d (x %d bit)\n", width, height, numplanes));
/* Write header to file */
if( FPrintf( filehandle, "P6\n#Created by AROS ppm.datatype aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n%ld %ld\n255\n",
(long)width, (long)height ) == -1 )
{
D(bug("ppm.datatype/PPM_Save() --- writing header failed\n"));
return FALSE;
}
/* Now read the picture data line by line and write it to a chunky buffer */
if( !(linebuf = AllocVec(width*3, MEMF_ANY)) )
{
SetIoErr(ERROR_NO_FREE_STORE);
return FALSE;
}
D(bug("ppm.datatype/PPM_Save() --- copying picture with READPIXELARRAY\n"));
for (y=0; y<height; y++)
{
if(!DoSuperMethod(cl, o,
PDTM_READPIXELARRAY, /* Method_ID */
(IPTR)linebuf, /* PixelData */
PBPAFMT_RGB, /* PixelFormat */
width, /* PixelArrayMod (number of bytes per row) */
0, /* Left edge */
y, /* Top edge */
width, /* Width */
1)) /* Height */
{
D(bug("ppm.datatype/PPM_Save() --- READPIXELARRAY line %d failed !\n", y));
FreeVec(linebuf);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
return FALSE;
}
if( FWrite( filehandle, linebuf, width*3, 1 ) != 1 )
{
D(bug("ppm.datatype/PPM_Save() --- writing picture data line %d failed !\n", y));
FreeVec(linebuf);
return FALSE;
}
}
D(bug("ppm.datatype/PPM_Save() --- Normal Exit\n"));
FreeVec(linebuf);
SetIoErr(0);
return TRUE;
}
/**************************************************************************************************/
IPTR PPM__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{
if( (dtw -> dtw_Mode) == DTWM_RAW )
{
/* Local data format requested */
return PPM_Save(cl, o, dtw );
}
else
{
/* Pass msg to superclass (which writes an IFF ILBM picture)... */
return DoSuperMethodA( cl, o, (Msg)dtw );
}
}
/**************************************************************************************************/
#if DEBUGMETHODS
STATIC IPTR DT_NotifyMethod(struct IClass *cl, struct Gadget *g, struct opUpdate *msg)
{
return(DoSuperMethodA(cl, (Object *) g, (Msg) msg));
}
/**************************************************************************************************/
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
IPTR RetVal;
D(bug("ppm.datatype/OM_SET: Entering\n"));
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
return(RetVal);
}
/**************************************************************************************************/
STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{
IPTR RetVal;
D(bug("ppm.datatype/OM_GET: Entering\n"));
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
return(RetVal);
}
/**************************************************************************************************/
STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{
IPTR RetVal;
const char L[]="GM_LAYOUT";
const char P[]="DTM_PROCLAYOUT";
const char A[]="DTM_ASYNCLAYOUT";
const char U[]="Unknown Method";
char *MethodName;
RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);
D(bug("ppm.datatype/%s: RetVal 0x%lx\n", MethodName, (unsigned int) RetVal));
D(bug("ppm.datatype/%s: Leaving\n", MethodName));
return(RetVal);
}
#endif /* DEBUGMETHODS */
IPTR DTD__OM_NEW(Class *cl, Object *o, struct opSet *msg) { } /* DTD_OM_New() */ /**************************************************************************************************/ static BOOL DTD_Load(struct IClass *cl, Object *o) { } static BOOL DTD_Save(struct IClass *cl, Object *o, struct dtWrite *dtw ) { } IPTR DTD__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw) { } /**************************************************************************************************/ STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg) { } STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg) { } STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg) { }
Sound
editSound Datatype the Sound_Write function is the SuperMethod. Normally when a datatype has two methods: OM_NEW & DTM_WRITE. The first links the Load function of the datatype with Datatypes Library for getting new datatypes. The second links the Save function of the datatype or if DT Write Method is not DTWM_RAW then it is supposed to defer to the SuperMethod. In this case it would send the DTWM_IFF message to the Sound Datatype function Sound_Write
Should it be better to use DTMethod to decompress on a buffer and then use this uncompressed buffer ? For sound, get the data using the SDTA_Sample (or SDTA_LeftSample/SDTA_RightSample) attributes. You can retrieve sample data using SDTA_Sample tag but AmigaOS lacks support for SDTA_SampleType so you can get only 8-bit sample data there. AROS and MorphOS are more advanced there.
Any applications will query the methods supported by your class. Make sure that if you choose to implement support for the OM_GET/DTA_Methods tag the methods you return should also include the methods supported by your superclass. Otherwise, the user will be unable to use functions such as "Copy" or "Print".
NAME sound.datatype -- root data type for sounds. FUNCTION The sound.datatype is the super-class for any sound related classes. METHODS OM_NEW -- Create a new sound object. OM_GET -- Obtain the value of an attribute. OM_SET -- Set the values of multiple attributes. OM_UPDATE -- Update the values of multiple attributes. OM_DISPOSE -- Dispose of a sound object. GM_LAYOUT -- Layout the object and notify the application of the title and size. GM_HITTEST -- Determine if the object has been hit with the mouse. GM_GOACTIVE -- Tell the object to go active. On SELECTDOWN, the sound will start playing. GM_HANDLEINPUT -- Handle input. Currently input (other than SELECTDOWN) doesn't affect the sound. GM_RENDER -- Cause the graphic to render. Currently the graphic for the sound is just a static icon. DTM_TRIGGER -- Cause an event to occur. Currently the only trigger event is STM_PLAY, which will cause the sound to start playing. NOTE: Subclasses which support streaming data access may support more than just the STM_PLAY event. DTM_COPY -- Copy the entire sound to the clipboard as 8SVX. NOTE: Up to and including V40 sound.datatype never stored a valid VoiceHeader with the file. This was fixed in V44. Subclasses which support streaming data access may not support this method. DTM_WRITE -- Write the entire sound to a file as 8SVX. NOTE: Up to and including V40 sound.datatype never stored a valid VoiceHeader with the file. This was fixed in V44. Subclasses which support streaming data access may not support this method. TAGS SDTA_VoiceHeader (struct VoiceHeader *) -- Set and get the base information for the sound. VoiceHeader is defined in <datatypes/soundclass.h>. NOTE: Up to and including V40 sound.datatype never returned a valid VoiceHeader for OM_GET and the VoiceHeader data was ignored in the OM_NEW/OM_SET cases. This was fixed in V44. Applicability is (ISG). SDTA_Sample (BYTE *) -- Set and get the sound data. Starting with V40 the sample data does not need to be in CHIP memory. Starting with V44 the sample data does not need to start on a WORD-aligned address. Setting SDTA_Sample to NULL will stop sound replay if sound.datatype was started playing with a non-NULL SDTA_Sample parameter. The SDTA_Sample parameter selects mono playback on any sound channel that is currently available. NOTE: For streaming sound playback, SDTA_LeftSample, SDTA_RightSample, and SDTA_Sample will all be NULL (V44). Applicability is (ISG). SDTA_SampleLength (ULONG) -- Length of the sound data in bytes. Starting with V44 the sample data does not need to be an even number of bytes. Setting SDTA_SampleLength to 0 will stop sound replay. Applicability is (ISG). SDTA_Period (UWORD) -- Set and get the period of the sound (in timing intervals per sample). This attribute can be used to affect a playing sound. Please note that the Amiga audio hardware does not reliably support playback periods shorter than 124; sound.datatype will limit the period to valid intervals (V44). Default for this tag is 394. Applicability is (ISG). SDTA_Volume (UWORD) -- Set and get the volume of the sound. This attribute can be used to affect a playing sound. Valid range is from 0 to 64. Default for this tag is 64. Applicability is (ISG). SDTA_Cycles (UWORD) -- Set and get the number of cycles the sound will be played. Default for this tag is 1. Applicability is (ISG). The following tags are new for V40. SDTA_SignalTask (struct Task *) -- Task to signal when the is complete, or if SDTA_Continuous is TRUE, when the next buffer is needed. Default for this tag is NULL. Applicability is (IS). SDTA_SignalBit (ULONG) -- Signal mask to use with SDTA_SignalTask or 0 to disable. NOTE: Due to a bug in sound.datatype V40 SDTA_SignalBit was actually implemented as a signal mask as opposed to a bit number. The documentation now reflects this. If you intend to use a signal bit number instead of the mask, use the new V44 tag SDTA_SignalBitNumber below. Default for this tag is 0. Applicability is (IS). SDTA_Continuous (BOOL) -- Used to indicate that the sound datatype will be fed a continuous stream of data. Default for this tag is FALSE. Applicability is (I). The following tags are new for V44. SDTA_SignalBitMask (ULONG) -- Signal mask to use with SDTA_SignalTask or 0 to disable. This tag is an alias for SDTA_SignalBit. Default for this tag is 0. Applicability is (IS). SDTA_SignalBitNumber (BYTE) -- Signal bit to use with SDTA_SignalTask or -1 to disable. Default for this tag is -1. Applicability is (IS). SDTA_SamplesPerSec (UWORD) -- Set and get the replay frequency of a sound (in Hz). This attribute can be used to affect a playing sound. Unlike the SDTA_Period tag, which serves the same purpose, this tag automatically takes the system clock value into account. Please note that the Amiga audio hardware does not reliably support playback rates beyond 28,000 samples per second; sound.datatype will limit the replay frequency to valid intervals. Applicability is (ISG). SDTA_ReplayPeriod (struct timeval *) -- Get the replay period, i.e. the time it takes for the complete sound to be played. If the sample size has not been set yet, the timeval tv_sec and tv_micro members will be set to 0. If the sample is to be played continuously, both timeval members will be set to 0xFFFFFFFF. Applicability is (G). SDTA_Pan (BYTE) -- Set the stereo panning; this must be set to a number in the range of -64..64. A value of -64 will pan the sound to the left channel, silencing the right channel; a value of 64 will pan the sound to the right channel and silence the left channel. To center playback, use a panning value of 0. The panning value only takes effect if a stereo sound is being played. Default for this tag is 0. Applicability is (IS). SDTA_FreeSampleData (BOOL) -- This tag controls whether sound.datatype will call FreeVec() on the sample data attached to an object. If the SDTA_Continuous attribute was set to TRUE, sound.datatype will never free any data attached to an object. It is safe to attach the same sample to more than one channel as sound.datatype will make sure that no sample data is freed twice. Default for this tag is FALSE. Applicability is (IS). SDTA_LeftSample (BYTE *) -- Set and get the left channel sound data. The sample data does not need to be in CHIP memory and does not need to start on a WORD-aligned address. Setting SDTA_LeftSample to NULL will stop sound replay if sound.datatype was started playing with a non-NULL SDTA_LeftSample parameter. The SDTA_LeftSample parameter alone selects mono playback on any left sound channel that is currently available. Used together with the SDTA_RightSample parameter, stereo playback on any available stereo channels is selected. The SDTA_LeftSample parameter takes precedence over the the SDTA_Sample parameter. NOTE: For streaming sound playback, SDTA_LeftSample, SDTA_RightSample, and SDTA_Sample will all be NULL (V44). Applicability is (ISG). SDTA_RightSample (BYTE *) -- Set and get the right channel sound data . The sample data does not need to be in CHIP memory and does not need to start on a WORD-aligned address. Setting SDTA_RightSample to NULL will stop sound replay if sound.datatype was started playing with a non-NULL SDTA_RightSample parameter. The SDTA_RightSample parameter alone selects mono playback on any right sound channel that is currently available. Used together with the SDTA_LeftSample parameter, stereo playback on any available stereo channels is selected. The SDTA_RightSample parameter takes precedence over the the SDTA_Sample parameter. NOTE: For streaming sound playback, SDTA_LeftSample, SDTA_RightSample, and SDTA_Sample will all be NULL (V44). Applicability is (ISG). SDTA_SyncSampleChange (BOOL) -- If SDTA_Continuous was set to TRUE, sound.datatype will expect a continuous stream of data to be played. By specifying "SDTA_SyncSampleChange,TRUE" you request that new sound data will be played only if the old data has been played completely (otherwise, playback would restart immediately with the new sound). If playback is currently in progress, the Task to change the sample data will be made to wait until playback of the old sound has finished. Default for this tag is FALSE. Applicability is (IS). DTA_Immediate (BOOL) -- Select and query whether playback should start immediately after the object has passed the layout process. Default for this tag is FALSE. Applicability is (ISG). DTA_Repeat (BOOL) -- Select and query whether playback should loop indefinitely, regardless of the current SDTA_Cycles settings. Default for this tag is FALSE. Applicability is (ISG). NOTES You cannot switch between mono and stereo playback on the fly while the sound is still playing. First, stop the sound, then change the SDTA_Sample/SDTA_LeftSample/SDTA_LeftSample attributes. The sound.datatype implementation has been cleaned up for V44 to allow for streaming subclasses to be written. Such subclasses will always return NULL when their SDTA_LeftSample, SDTA_RightSample and SDTA_Sample attributes are queried. However, they will never return 0 for the SDTA_SampleLength and SDTA_SamplesPerSec attributes since these can be used to calculate the length of the entire sample. Streaming subclasses will respond to the DTM_TRIGGER method, to start, stop playback, etc. but may not support any other methods which rely upon the entire sample to reside in memory.
Hypertext
editAmigaOS users experimented with this to provide HTML, pictures, animations and audio combined
AROS has nothing like this so far
How to compile datatypes
editBuild dtdesc tool, this is what you need. The source is located in tools/dtdesc. This tool is used in order to make a datatype descriptor from .dtd file. Class library is built in a usual way, using a usual crosscompiler.
A package so that it will be easy to build datatypes independently of the whole build system. Compiled createdtdesc and examinedtdesc for native AROS. One other tool that is needed is genmodule.
What is needed is a READ/WRITEPIXELARRAY interface, that replaces the former SET PDTA_BitMap and GET PDTA_DestBtMap interface. If a Bitmap was SET (legacy interface), it gets converted to LUT8 format during layout. A destination BitMap is only created, if this is set by Prefs or an applications requests it by GET PDTA_DestBitMap.
RENDER Method chooses one of these functions for displaying
- cgfx/WritePixelArray: Truecolor pic -> Truecolor screen
- cgfx/WriteLUTPixelArray: Colormapped pic -> Truecolor screen
- graphics/WriteChunkyPixels: Colormapped pic -> Colormapped chunky screen
- graphics/BltBitMapRastPort: Colormapped pic -> Colormapped planar screen
Truecolor pic -> Colormapped screen is handled during layout, with a fixed colormap and some simple but fast dithering algorithm (one dimensional error propagation). Floyd-Steinberg dithering algorithm could be used for slightly better results (two dimensional error propagation). Much better results could be obtained by a calculated colormap (e.g. median cut algorithm), but this is much slower.
Colormapped data is always stored in LUT8 format, or BitMap format for legacy. Truecolor data is always stored in ARGB format. This isn't memory effective, but makes things more simple and faster. Some optimization could be done here.
Created a template for new graphic datatypes here.
AmigaGuide
editNAME amigaguide.datatype -- data type for AmigaGuide databases. FUNCTION The amigaguide.datatype is the DataTypes class for AmigaGuide databases. METHODS OM_NEW -- Create a new AmigaGuide object. OM_GET -- Obtain the value of an attribute. OM_SET -- Set the values of multiple attributes. OM_UPDATE -- Update the values of multiple attributes. OM_DISPOSE -- Dispose of an AmigaGuide object. GM_LAYOUT -- Layout the object and notify the application of the title and size. GM_HITTEST -- Determine if the object has been hit with the mouse. GM_GOACTIVE -- Tell the object to go active. GM_HANDLEINPUT -- Handle input. GM_RENDER -- Cause the AmigaGuide database to render. DTM_GOTO -- Cause the AmigaGuide database to load and display document. DTM_TRIGGER -- Trigger an event. STM_COMMAND - Invoke an AmigaGuide command. STM_CONTENTS - Display the table of contents. STM_INDEX - Display the index. STM_HELP - Display the help file. STM_RETRACE - Retrace. STM_BROWSE_PREV - Go to the previous sequential document. STM_BROWSE_NEXT - Go to the next sequential document. DTM_PROCLAYOUT -- Layout (remap) the AmigaGuide database on the application's process. DTM_FRAMEBOX -- Obtain the display environment that the AmigaGuide database requires. DTM_SELECT -- Select an area in the AmigaGuide database. DTM_CLEARSELECTED -- Deselect the selected area of the AmigaGuide database. DTM_COPY -- Copy the selected area of the text to the clipboard as FTXT. If no area is selected, then the entire text is copied. DTM_PRINT -- Print the selected area of the text. If no area is selected, then the entire text is printed. DTM_WRITE -- Write the selected area of the text to a file. If no area is selected, then the entire text is saved. TAGS DTA_TriggerMethods -- List of the trigger methods supported. Applicability is (G). DTA_Methods -- List of the methods supported. Applicability is (G). DTA_TextAttr (struct TextAttr *) -- Text attribute to use for the AmigaGuide database. Applicability is (ISG). DTA_Name (STRPTR) -- Name of the AmigaGuide database. Applicability is (I). DTA_Handle (BPTR) -- File handle for the AmigaGuide database. Applicability is (I). DTA_NodeName (STRPTR) -- Document to display. Applicability is (I). TDTA_WordDelim (STRPTR) -- Characters used to deliminate words. Applicability is (IS). Defaults to "t *-,<>()[];"". AGA_HelpGroup (ULONG) -- Help group that the AmigaGuide object belongs in. Applicability is (I). AGA_Secure (BOOL) -- This tag allows you control whether AmigaGuide will execute the commands "ONOPEN", "ONCLOSE", "LINK RX", "LINK RXS" and "LINK SYSTEM". These commands present a potential security hole if, for example, AmigaGuide documents are displayed in an e-mail reader program. To disabled them, set the AGA_Secure tag to TRUE; in this case AmigaGuide will still recognize the commands but will not execute them. Applicability is (ISG). Defaults to FALSE. (V41) COMMANDS Commands must start in the very first column of a line, and can be the only thing on the line. If a line begins with an @ sign, then it is interpreted as a command. The following commands can be used in the global section of a database. @$VER: <AmigaDOS version string> Specify the version of the database. This command must always be in upper-case. @(C) <copyright> Specify the copyright notice for the database. @AUTHOR <name> Specify the author of the database. @DATABASE <name> Must be the very first line of an AmigaGuide document. @DNODE <name> Indicates the start of a dynamic node. The AmigaGuide system uses the callback hooks to obtain the document from a document provider. This is obsolete, do not use. @FONT <name> <size> Specify the font to use for the database. @HEIGHT <chars> How high, in characters, the largest document is. @HELP <name/node> Specify the name of the help node, which will be accessed by the Help button. Can be a node in an external database. @INDEX <name/node> Specify the name of the index node, which will be accessed by the Index button. Can be a node in an external database. @MACRO <name> <commands> This is used to construct a macro. A macro can be used the same way as an attribute command, and can only consist of other attribute commands or macros. The macro list is searched before the attribute command list is searched. This is new for V40. @macro icom "@{i}$1 @{ui}" ... This is an @{icom "example"} of macro. @MASTER <path> Complete path of the source document used to define this AmigaGuide database. @NODE <name> <title> Indicate the start of a node (page/article/section). The first node, or main node, must be named MAIN. MAIN must be the master table of contents for the database. @ONCLOSE <rxcommand> This is used to specify an ARexx macro file to execute when the database is closed. The return value of the script has no effect on the database. New for V40. @ONOPEN <rxcommand> This is used to specify an ARexx macro file to execute when the database is opened. If the script returns an error, then the database will not be opened. New for V40. @REM <remark> @REMARK <remark> This is used to place remarks in the database. These remarks are not displayed to the user. @SMARTWRAP This is used to indicate that the text of the database is to wordwrapped using a more intelligent algorithm than @WORDWRAP. A paragraph doesn't need to be restricted to one physical line, but paragraphs must be separated by two line feeds. New for V40. @TAB <num> Number of spaces in a tab. Defaults to 8. New for V40. @WIDTH <chars> How wide, in characters, the largest document is. @WORDWRAP Turn on wordwrapping for the whole database. A paragraph must be restrained to one physical line. The following commands can be used within nodes of a database. \ A backslash is the escape character. A backslash in front of the @ sign is used to escape it. The backslash has no effect as an escape character inside commands such as @ONOPEN or @{".." LINK ..}; in cases like these it is treated as a regular character. Please note that AmigaGuide V35 does not treat the backslash character as an escape character. @ENDNODE <name> Indicate the end of a node. Must start at the beginning of a line. @FONT <name> <size> Specify the font to use for the node. @HELP <name/node> Specify the name of the help node, which will be accessed by the Help button. Can be a node in an external database. @INDEX <name/node> Specify the name of the index node, which will be accessed by the Index button. Can be a node in an external database. @KEYWORDS <keywords> Keywords of the node. Someday when searching is reimplemented, there will be a keyword search. @NEXT <node name> Node to display when the user selects "Browse >" @ONCLOSE <rxcommand> This is used to specify an ARexx macro file to execute when the node is closed. The return value of the script has no effect on the node. New for V40. @ONOPEN <rxcommand> This is used to specify an ARexx macro file to execute when the node is opened. If the script returns an error, then the node will not be opened. New for V40. @PREV <node name> Node to display when the user selects "< Browse" @SMARTWRAP This is used to indicate that the text of the node is to wordwrapped using a more intelligent algorithm than @WORDWRAP. A paragraph doesn't need to be restricted to one physical line, but paragraphs must be separated by two line feeds. New for V40. @TAB <num> Number of spaces in a tab. Defaults to 8. New for V40. @TITLE <title> Title to display in the title bar of the window during the display of this node. Must start at the beginning of a line. @TOC <node name> Name of the node that contains the table of contents for this node. Defaults to MAIN. This is the node that is displayed when the user presses the "Contents" button. @WORDWRAP Turn on wordwrapping for the node. A paragraph must be restrained to one physical line. @{<label> <command>} Indicate a textual link point. Can be anywhere in a line. Starting with 3.0, AmigaGuide can can link to graphics, sounds, animations and other DataTypes. ATTRIBUTES Following is a list of attributes that can be applied to the text of a node. @{AMIGAGUIDE} Displays the word AmigaGuide in bold followed by the ® symbol. New for V40. @{APEN} Use to change the foreground color to a specific pen number. New for V40. @{B} Turn bold on. @{BG <color>} Used to change the background text color. Color can be: Text Shine Shadow Fill FillText Background Highlight @{BODY} Indicate that the following text is the body of the document. Word wrap will be turned back on if it is the default. New for V40. @{BPEN} Use to change the background color to a specific pen number. New for V40. @{CLEARTABS} Restore the default tab stops. New for V40. @{CODE} Indicate that the following text is not to be word-wrapped. New for V40. @{FG <color>} Used to change the foreground color. The same colors can be used as in the FG command. @{I} Turn italic on. @{JCENTER} Turn on centering. New for V40. @{JLEFT} Turn on left justification. New for V40. @{JRIGHT} Turn on right justification. New for V40. @{LINDENT} Set the number of spaces to indent the body of a paragraph. New for V40. @{LINE} Force a line feed without starting a new paragraph. New for V40. @{PAR} Used to indicate the end of a paragraph. This is the same as two sequential LF's in the source file. New for V40. @{PARD} Restore the default settings for a paragraph. Text pen to 1, background to 0, normal font, and no indentation. New for V40. @{PARI} Set the number of spaces to indent the first line of a paragraph relative to the normal paragraph indentation. The value may be a negative number. New for V40. @{PLAIN} Used to turn off all @{B}, @{I}, and @{U} commands. New for V40. @{SETTABS <n> ... <n>} This is used to establish tab stops. New for V40. @{TAB} The same as character 9 in the source file. New for V40. @{U} Turn underline on. @{UB} Turn bold off. @{UI} Turn italic off. @{UU} Turn underline off. AREXX COMMANDS AmigaGuide supports the following ARexx commands. BEEP DisplayBeep(). CLOSE Close the current database. GETNODECOUNT Returns the number of nodes in the database using the RESULT variable. New for V40. LINK Go to the named node. NEXT Go to the next physical node in the database. Same as pressing the "Browse >" button. New for V40. PREVIOUS Go to the previous physical node in the database. Same as pressing the "Browse <" button. New for V40. PRINT Print the current node. Doesn't return until complete. New for V40. QUIT Close the current database. RETRACE Go to the previous node in the database. Same as pressing the "Retrace" button. New for V40.
Streaming
editThe datatype system cannot deal with progressive loading and streaming yet.
References
edit- V30 Amiga OS 2
- V40 Amiga OS 3
- V44 Amiga OS 3.5+
Commodore and Electronics Arts developed the IFF (Interchangable File Format) to cover pictures (ILBM), sound (8SVX) and text (FTXT) etc. So for AmigaOS 3.0 introduced the Datatype library which can decode file formats easily using different classes which can be installed as they are needed.
Include the following headers to use datatypes:
#include <proto/datatypes.h> #include <datatypes/datatypes.h>
To use datatypes, you need to open the datatypes library along with the other libraries in your program:
DataTypesBase = OpenLibrary ("datatypes.library", 39)
To create a Datatype Object, use the NewDTObject function as below:
Object o = NewDTObject(APTR name, Tag1[, tag2, tag3, ... ] ) Object o = NewDTObjectA(APTR name, struct TagItem *attrs)
The type of source that Datatypes can use include Clipboard (DTST_CLIPBOARD), a file (DTST_FILE), RAM (DTST_RAM, DTST_MEMORY), or a hotlink (DTST_HOTLINK).
The group of objects you can use for Datatypes include:
GID_SYSTEM = System file, directory, program, library, device etc. GID_TEXT = Text file. GID_DOCUMENT = Formatted text with graphics etc. GID_SOUND = Sounds. GID_INSTRUMENT = Musical instruments. GID_MUSIC = A musical score. GID_PICTURE = A still picture. GID_ANIMATION = An animated picture GID_MOVIE = Animation with audio track.
Example, read a object from the clipboard:
gd->gd_DisplayObject = NewDTObject ((APTR)gd->gd_Unit, DTA_SourceType, DTST_CLIPBOARD, GA_Immediate, TRUE, GA_RelVerify, TRUE, DTA_TextAttr, (ULONG) & gd->gd_TextAttr, TAG_DONE))
The parameters of this functions uses Tags as defined in datatypes/datatypesclasses.h and intuition/gadgetclass.h
gf->gd_Unit = the Clipboard unit number DTST_Clipboard = the Clipboard is the data source GA_Immediate = Should the object be active when displayed GA_RelVerify = Verify that the pointer is over the object when it is selected gd_->gd_TextAttr = Pointer to text font attributes
This example read a file to be displayed from 'pathname' and it is of type picture (ILBM, JPEG, GIF, PNG etc):
picDT = NewDTObject(pathname, DTA_SourceType, DTST_File, DTA_GroupID, GID_PICTURE, GA__Left, 10, GA_Top, 10, TAG_END); picDT = Object databastype created. pathname = String containing path of the file to load. DTST_FILE = Source is a file. GID_Picture = Group of objects file must be long to i.e. Pictures.
Once we have a datatype loaded with NewDTObject, the program should create a window and then the datatype object can be added to window or a requester, simply with single command:
LONG realposition = AddDTObject( struct Window *win, struct Requester *req, Object *obj, LONG pos);
Parameters:
win = Pointer to Window object (if not a Requester). req = Pointer to an optional Requester object (if not a window) obj = The Datatype object created with NewDTObject function. pos = Position in gadget list. Use -1 to add it to end of the list.
realpos = AddDTObject(win, NULL, pictDT, -1);
Once a datatype object is no longer required, it is removed from the window and disposed and memory released
position = RemoveDTObject(window, object);
void DisposeDTObject(Object *o)
RemoveDTObject(win, gd->gd_DisplayObject);
DisposeDTObject (gd->gd_DisplayObject);
To get attributes from a datatype object, you can use the the GetDTAttrs function
GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);
and examing the results from the dtn structure you can retreive:
dtn->dtn_Header->dth_Name = Descriptive name of the datatype. dtn->dtn_Header->dth_GroupID = The group the datatype belongs to
The function GetDTString returns a localised Datatypes string of the id given. This string could be syst, text, docu, soun, inst, musi, pict, anim or movi (see datatypes.h).
GetDTString (dtn->dtn_Header->dth_GroupID)
Other functions available for datatypes: ObtainDataType(), ReleaseDataType(), SetDTAttrs(), RefreshDRObject(), DoAsyncLayout(), DoDTMethod(), GetDTMethods(), DTMethods(), PrintDTObject().
datatypes
Index AddDTObject() CopyDTMethods() CopyDTTriggerMethods() DisposeDTObject() DoAsyncLayout() DoDTDomainA() DoDTMethodA() DrawDTObjectA() FindMethod() FindToolNodeA() FindTriggerMethod() FreeDTMethods() GetDTAttrsA() GetDTMethods() GetDTString() GetDTTriggerMethodDataFlags() GetDTTriggerMethods() LaunchToolA() LockDataType() NewDTObjectA() ObtainDataTypeA() ObtainDTDrawInfoA() PrintDTObjectA() RefreshDTObjectA() ReleaseDataType() ReleaseDTDrawInfo() RemoveDTObject() SaveDTObjectA() SetDTAttrsA() StartDragSelect()
AddDTObject()
LONG AddDTObject(
struct Window * win, struct Requester * req, Object * obj, LONG pos );
Function
Add an object to the window 'win' or requester 'req' at the position in the gadget list specified by the 'pos' argument.
Inputs
win -- window the object should be added to; may be NULL in which case
nothing is done
req -- requester the object should be added to obj -- the object to add; may be NULL in which case nothing is done pos -- the position of the object in the list
Result
The position where the object was added (may be different from what you asked for).
Notes
The object will receice a GM_LAYOUT message with the gpl_Initial field set to 1 when the object is added.
See also RemoveDTObject() intuition.library/AddGList()
CopyDTMethods()
ULONG * CopyDTMethods(
ULONG * methods, ULONG * include, ULONG * exclude );
Function
Copy and modify an array of methods. This is used by subclass implementors who want to add supported methods to an existing class.
Inputs
methods -- array of methods; may be NULL include -- array of methods to include terminated with ~0UL; may be NULL method -- array of methods to exclude terminated with ~0UL; may be NULL.
Result
The new array of methods or NULL if something went wrong (like out of memory).
See also
FindMethod() CopyDTTriggerMethods() FreeDTMethods()
CopyDTTriggerMethods()
struct DTMethod * CopyDTTriggerMethods(
struct DTMethod * methods, struct DTMethod * include, struct DTMethod * exclude );
Function
Copy and modify an array of DTMethod:s. This is used by subclass implementors who want to add supported methods to an existing class.
Inputs
methods -- array of methods; may be NULL include -- array of methods to include terminated with ~0UL; may be NULL method -- array of methods to exclude terminated with ~0UL; may be NULL
the dtm_Command and dtm_Method fields may have the options described in the FindTriggerMethod to filter out the given entries
Result
The new array of methods or NULL if something went wrong (like out of memory).
Notes
dtm_Label and dtm_Command must be valid as long as the object exists as they are not copied.
A subclass that implment DTM_TRIGGER must send unknown trigger
methods to its superclass.
See also
FindTriggerMethod() CopyDTMethods() FreeDTMethods()
DisposeDTObject()
void DisposeDTObject(
Object * o );
Function
Dispose a data type object obtained by NewDTObjectA().
Inputs
o -- The data type object to dispose of; may be NULL.
See also
NewDTObjectA() DoAsyncLayout() Synopsis
ULONG DoAsyncLayout(
Object * object, struct gpLayout * gpl );
Function
Perform an object's DTM_ASYNCLAYOUT method -- doing it asynchronously off loads the input.device. The method should exit when a SIGBREAK_CTRL_C is received; this signal means that the data is obsolete and the method will be called again.
Inputs
object -- pointer to data type object gpl -- gpLayout message pointer
DoDTDomainA() Synopsis
ULONG DoDTDomainA(
Object * o, struct Window * win, struct Requester * req, struct RastPort * rport, ULONG which, struct IBox * domain, struct TagItem * attrs );
ULONG DoDTDomain(
Object * o, struct Window * win, struct Requester * req, struct RastPort * rport, ULONG which, struct IBox * domain, TAG tag, ... );
Function
Obtain the maximum/minimum/nominal domains of a data type object.
Inputs
o -- data type object in question win -- window that the object is attached to req -- requester the object is attached to rport -- rastport; used for domain calculations which -- the domain to obtain (GDOMAIN_, see <intuition/gadgetclass.h> domain -- the result will be put here attrs -- additional attributes (subclass specific)
Result
The return value of GM_DOMAIN or 0 if an error occurred. The 'domain' IBox will be filled with the requested values as a side effect.
Notes
This function requires an object to perform the GM_DOMAIN method. To achieve similar results without an object, you must use CoerceMethodA() manually.
See also intuition/gadgetclass.h
DoDTMethodA()
IPTR DoDTMethodA(
Object * o, struct Window * win, struct Requester * req, Msg msg );
IPTR DoDTMethod(
Object * o, struct Window * win, struct Requester * req, TAG tag, ... );
Function
Perform a specific datatypes methodl.
Inputs
o -- pointer to data type object win -- window the object is attached to req -- requester the object is attached to msg -- the message to send to the object
Result
The value returned by the specified method.
See also
intuition.library/DoGadgetMethodA()
DrawDTObjectA()
LONG DrawDTObjectA(
struct RastPort * rp, Object * o, LONG x, LONG y, LONG w, LONG h, LONG th, LONG tv, struct TagItem * attrs );
LONG DrawDTObject(
struct RastPort * rp, Object * o, LONG x, LONG y, LONG w, LONG h, LONG th, LONG tv, TAG tag, ... );
Function
Draw a data type object into a RastPort. You must have successfully called ObtainDTDrawInfoA before calling this function; it invokes the object's DTM_DRAW method.
Inputs
rp -- pointer to the RastPort to draw the object into o -- pointer to the data type object to draw x -- left edge of drawing area y -- top edge of drawing area w -- width of drawing area h -- height of drawing area th -- horizontal top in units tv -- vertical top in units attrs -- additional attributes
Tags
ADTA_Frame for animationclass objects (selects the frame that should be drawn.
Result
TRUE if rendering went OK, FALSE if failure.
Notes
The RastPort in question must support clipping, i.e. have a valid layer structure attached to it; if not, some datatypes can't draw and FALSE will be returned.
See also ObtainDataTypeA()
FindMethod()
ULONG * FindMethod(
ULONG * methods, ULONG searchmethodid );
Function
Search for a specific method in a array of methods.
Inputs
methods -- array of methods; may be NULL searchmethodid -- method to search for
Result
Pointer to method table entry or NULL if the method wasn't found.
See also
GetDTMethods() CopyDTMethods()
FindToolNodeA()
struct ToolNode * FindToolNodeA(
struct List * toollist, struct TagItem * attrs );
struct ToolNode * FindToolNode(
struct List * toollist, TAG tag, ... );
Function
Search for a specific tool in a list of given tool nodes.
Inputs
toollist -- a list or a struct ToolNode * (which will be skipped) to
search in; may be NULL.
attrs -- search tags; if NULL, the result of the function will
simply be the following node.
Tags
TOOLA_Program -- name of the program to search for
TOOLA_Which -- one of the TW_#? types
TOOLA_LaunchType -- launch mode: TF_SHELL, TF_WORKBENCH or TF_RX
Result
A pointer to a ToolNode describing the search result (NULL for failure).
Notes
The entries in dt->dtn_ToolList are valid as long as a lock is kept on the data type 'dt' (ObtainDataTypeA() or LockDataType()).
See also LaunchToolA()
FindTriggerMethod()
struct DTMethod * FindTriggerMethod(
struct DTMethod * methods, STRPTR command, ULONG method );
Function
Search for a specific trigger method in a array of trigger methods (check if either 'command' or 'method' matches).
Inputs
methods -- array of trigger methods; may be NULL command -- name of trigger method (may be NULL; if so, 'command'
is not matched against)
method -- id of trigger method to search for (may be ~0; if so, don't
match against 'method'.
Result
Pointer to trigger method table entry (struct DTMethod *) or NULL if the method wasn't found.
See also GetDTTriggerMethods() CopyDTTriggerMethods()
FreeDTMethods()
VOID FreeDTMethods(
APTR methods );
Function
Free array obtained from CopyDTMethods() or CopyDTTriggerMethods().
Inputs
methods -- array of methods; may be NULL
See also
CopyDTMethods() CopyDTTriggerMethods() GetDTAttrsA() Synopsis
ULONG GetDTAttrsA(
Object * o, struct TagItem * attrs );
ULONG GetDTAttrs(
Object * o, TAG tag, ... );
Function
Get the attributes of a specific data type object.
Inputs
o -- pointer to a data type object; may be NULL attrs -- the attributes to get terminated with TAG_DONE; each Tag's
data element should contain the address of the respective storage element; may be NULL
<base attribs>
DTA_DataType (#1) DTA_ObjName DTA_ObjAuthor DTA_ObjAnnotation DTA_ObjCopyright DTA_ObjVersion DTA_ObjectID
Result
The number of attributes obtained.
Notes
(#1) - On AROS, the "DataType" an object returns may be a clone of
the real entry, so that the subclass can override subformat information.
See also SetDTAttrsA() intuition.library/GetAttr()
GetDTMethods()
ULONG * GetDTMethods(
Object * object );
Function
Get a list of the methods an object supports.
Inputs
object -- pointer to a data type object
Result
Pointer to a ULONG array which is terminated ~0; the array is only valid until the object is disposed of.
See also GetDTTriggerMethods()
GetDTString()
CONST_STRPTR GetDTString(
ULONG id );
Function
Get a pointer to a localized datatypes string.
Inputs
id -- ID of the string to get
Result
Pointer to a NULL terminated string.
GetDTTriggerMethodDataFlags()
ULONG GetDTTriggerMethodDataFlags(
ULONG method );
Function
Get the kind of data that may be attached to the stt_Data field in the dtTrigger method body. The data type can be specified by or:ing the method id (within the STMF_METHOD_MASK value) with one of the STMD_ identifiers.
STMD_VOID -- stt_Data must be NULL STMD_ULONG -- stt_Data contains an unsigned value STMD_STRPTR -- stt_Data is a pointer to a string STMD_TAGLIST -- stt_Data points to an array of struct TagItem terminated
with TAG_DONE
The trigger methods below STM_USER are explicitly handled as described in <datatypes/datatypesclass.h>.
Inputs
method -- dtt_Method ID from struct DTMethod
Result
One of the STMD_ identifiers defined in <datatypes/datatypesclass.h>
See also CopyDTTriggerMethods() FindTriggerMethod()
GetDTTriggerMethods()
struct DTMethod * GetDTTriggerMethods(
Object * object );
Function
Get a list of the trigger methods an object supports.
Inputs
object -- pointer to a data type object
Result
A pointer to a STM_DONE terminated DTMethod list. This list in only valid until the object is disposed of.
Example
To call the specific method, do the following:
DoMethod(object, DTM_TRIGGER, myMethod);
Notes
Some trigger methods requires an argument (calling these with a NULL argument is wrong). Use GetDTTriggerMethodDataFlags() to obtain the type of the requested argument.
See also GetDTMethods()
LaunchToolA()
ULONG LaunchToolA(
struct Tool * tool, STRPTR project, struct TagItem * attrs );
ULONG LaunchTool(
struct Tool * tool, STRPTR project, TAG tag, ... );
Function
Launch an application with a particular project.
Inputs
tool -- tool to use (may be NULL in which case this function
returns 0)
project -- name of the project to execute or NULL attrs -- additional attributes
Tags
NP_Priority (BYTE) -- priority of the launched tool (default is the
priority of the currect process except for Workbench applications where the default priority is 0 if not overridden by the TOOLPRI tooltype).
NP_Synchronous (BOOL) -- don't return until launched application process
finishes (defaults to FALSE).
Result
Zero for failure, non-zero otherwise.
See also NewDTObjectA()
LockDataType()
VOID LockDataType(
struct DataType * dt );
Function
Lock a DataType structure obtained from ObtainDataTypeA() or a data type object (DTA_DataType).
Inputs
dt -- DataType structure; may be NULL
Notes
Calls to LockDataType() and ObtainDataTypeA() must have a corresponding ReleaseDataType() call or else problems will arise.
See also ObtainDataTypeA() ReleaseDataType()
NewDTObjectA()
Object * NewDTObjectA(
APTR name, struct TagItem * attrs );
Object * NewDTObject(
APTR name, TAG tag, ... );
Function
Create a data type object from a BOOPSI class.
Inputs
name -- name of the data source; generally an existing file name attrs -- pointer to a TagList specifying additional arguments
Tags
DTA_SourceType -- The type of source data (defaults to DTST_FILE).
If the source is the clipboard the name field contains the numeric clipboard unit.
DTA_Handle -- Can be used instead of the 'name' field. If the
source is DTST_FILE, ths must be a valid FileHandle; must be a valid IFFHandle if source is DTST_CLIPBOARD.
DTA_DataType -- The class of the data. Data is a pointer to a valid
DataType; only used when creating a new object that doens't have any source data.
DTA_GroupID -- If the object isn't of this type, fail with an IoErr()
of ERROR_OBJECT_WRONG_TYPE.
GA_Left GA_RelRight GA_Top GA_RelBottom GA_Width GA_RelWidth GA_Height GA_RelHeight -- Specify the position of the object relative to the
window.
GA_ID -- ID of the object.
GA_UserData -- Application specific data for the object.
GA_Previous -- Previous object / gadget in the list.
Result
A BOOPSI object. This may be used in different contexts such as a gadget or image. NULL indicates failure -- in that case IoErr() gives more information:
ERROR_REQUIRED_ARG_MISSING -- A required attribute wasn't specified.
ERROR_BAD_NUMBER -- The group ID specified was invalid.
ERROR_OBJECT_WRONG_TYPE -- Object data type doesn't match DTA_GroupID.
Notes
This function invokes the method OM_NEW for the specified class.
The object should (eventually) be freed by DisposeDTObject() when no longer needed.
See also AddDTObject() DisposeDTObject() RemoveDTObject() intuition.library/NewObjectA()
ObtainDataTypeA()
struct DataType * ObtainDataTypeA(
ULONG type, APTR handle, struct TagItem * attrs );
struct DataType * ObtainDataType(
ULONG type, APTR handle, TAG tag, ... );
Function
Examine the data pointed to by 'handle'.
Inputs
type -- specifies the stream-type of 'handle', using one of the following types;
DTST_FILE - 'handle' is a BPTR lock DTST_CLIPBOARD - 'handle' is a struct IFFHandle * DTST_RAM - (v45) 'handle' is a STRPTR datatype-name
handle -- handle to return a datatype for. attrs -- additional attributes.
DTA_GroupID - (v45) (ULONG) the group (GID_#?) to match. 0 is used as a wildcard value.
DTA_DataType - (v45) (struct DataType *) starts/continues search from the specified DataType. NULL has the same effect as not using DTA_DataType.
Result
A pointer to a DataType or NULL if failure. IoErr() gives more information in the latter case:
ERROR_NO_FREE_STORE -- Not enough memory available ERROR_OBJECT_NOT_FOUND -- Unable to open the data type object ERROR_NOT_IMPLEMENTED -- Unknown handle type
See also ReleaseDataType()
ObtainDTDrawInfoA()
APTR ObtainDTDrawInfoA(
Object * o, struct TagItem * attrs );
APTR ObtainDTDrawInfo(
Object * o, TAG tag, ... );
Function
Prepare a data type object for drawing into a RastPort; this function will send the DTM_OBTAINDRAWINFO method the object using an opSet message.
Inputs
o -- pointer to the data type object to obtain the drawinfo for;
may be NULL in which case nothing is done
attrs -- additional attributes
Tags
None defined so far.
Result
A private handle that must be passed to ReleaseDTDrawInfo when the application is done drawing the object, or NULL if failure.
See also DrawDTObjectA() ReleaseDTDrawInfo()
PrintDTObjectA()
ULONG PrintDTObjectA(
Object * object, struct Window * window, struct Requester * requester, struct dtPrint * msg );
ULONG PrintDTObject(
Object * object, struct Window * window, struct Requester * requester, TAG tag, ... );
Function
Perform an object's DTM_PRINT method in an asynchronous manner.
Inputs
object -- pointer to the data type object window -- pointer to the window the object has been added to requester -- pointer to the requester the object has been added to
Result
TRUE on success, FALSE otherwise.
Notes
When an application has called PrintDTObjectA() it must not touch the printerIO union until a IDCMP_IDCMPUPDATE is received which contains the DTA_PrinterStatus tag.
To abort a print, send the DTM_ABORTPRINT method to the object.
This will signal the print process with a SIGBREAK_CTRL_C.
RefreshDTObjectA()
void RefreshDTObjectA(
Object * object, struct Window * window, struct Requester * req, struct TagItem * attrs );
void RefreshDTObject(
Object * object, struct Window * window, struct Requester * req, TAG tag, ... );
Function
Refresh a specified object sending the GM_RENDER message to the object.
Inputs
object -- pointer to the data type object to refresh; may be NULL window -- pointer to the window; may be NULL req -- must be NULL attrs -- additional attributes (currently none defined)
See also AddDTObject() RemoveDTObject() intuition.library/RefreshGList()
ReleaseDataType()
VOID ReleaseDataType(
struct DataType * dt );
Function
Release a DataType structure aquired by ObtainDataTypeA().
Inputs
dt -- DataType structure as returned by ObtainDataTypeA(); NULL is
a valid input.
See also
ObtainDataTypeA() ReleaseDTDrawInfo() Synopsis
VOID ReleaseDTDrawInfo(
Object * o, APTR handle );
Function
Release the handle obtained from ObtainDTDrawInfoA(); invokes the object's DTM_RELEASEDRAWINFO method sending the dtReleaseDrawInfo message.
Inputs
o -- pointer to the data type object the drawinfo of which to
release; may be NULL
handle -- handle got from ObtainDTDrawInfoA()
Result
A private handle that must be passed to ReleaseDTDrawInfo when the application is done drawing the object, or NULL if failure.
See also DrawDTObjectA() ObtainDTDrawInfoA()
RemoveDTObject()
LONG RemoveDTObject(
struct Window * window, Object * object );
Function
Remove an object from the specified window's object list; this will wait until the AsyncLayout process is ready. The object will receive a message of type DTM_REMOVEDTOBJECT as a sign of it having been removed.
Inputs
window -- pointer to the window in question object -- pointer to the object to remove
Result
The position of the object in the list before it was removed; if the object wasn't found -1 is returned.
See also AddDTObject() intuition.library/RemoveGList()
SaveDTObjectA()
ULONG SaveDTObjectA(
Object * o, struct Window * win, struct Requester * req, STRPTR file, ULONG mode, BOOL saveicon, struct TagItem * attrs );
ULONG SaveDTObject(
Object * o, struct Window * win, struct Requester * req, STRPTR file, ULONG mode, BOOL saveicon, TAG tag, ... );
Function
Save the contents of an object to a file using DTM_WRITE.
Inputs
o -- data type object to write to a file win -- window the object is attached to req -- requester the object is attached to file -- name of the file to save the object to mode -- save mode (RAW, IFF etc.), one of the DTWM_ identifiers saveicon -- should an icon be saved together with the file attrs -- additional attributes (these are subclass specific)
Result
The return value of DTM_WRITE.
Notes
If DTM_WRITE returns 0, the file will be deleted.
SetDTAttrsA()
ULONG SetDTAttrsA(
Object * o, struct Window * win, struct Requester * req, struct TagItem * attrs );
ULONG SetDTAttrs(
Object * o, struct Window * win, struct Requester * req, TAG tag, ... );
Function
Set the attributes of a data type object.
Inputs
o -- pointer to the data type object the attributes of which to set win -- window that the object has been added to attrs -- attributes to set (terminated with TAG_DONE)
tags are specified in <datatypes/datatypesclass.h>
See also GetDTAttrsA() intuition.library/SetGadgetAttrsA() datatypes/datatypesclass.h
StartDragSelect()
ULONG StartDragSelect(
Object * o );
Function
Start drag-selection by the user; the drag selection will only start if the object in question supports DTM_SELECT, is in a window or requester and no layout-process is working on the object.
Inputs
o -- data type object in question; may be NULL
Result
TRUE if all went OK, FALSE otherwise. If FALSE, IoErr() gives further information:
ERROR_ACTION_NOT_KNOWN -- the object doesn't support DTM_SELECT ERROR_OBJECT_IN_USE -- the object is currently occupied
Picture.class 41.00
editOM_DISPOSE function DT_DisposeMethod OM_GET function DT_GetMethod OM_NEW function DT_NewMethod OM_SET alias OM_UPDATE or function DT_SetMethod GM_GOACTIVE function DT_GoActiveMethod GM_HANDLEINPUT function DT_HandleInputMethod GM_LAYOUT function DT_Layout GM_RENDER function DT_Render DTM_ASYNCLAYOUT function DT_AsyncLayout DTM_DRAW function DT_Draw DTM_FRAMEBOX function DT_FrameBox DTM_OBTAINDRAWINFO function DT_ObtainDrawInfo DTM_PROCLAYOUT function DT_ProcLayout DTM_RELEASEDRAWINFO function DT_ReleaseDrawInfo PDTM_READPIXELARRAY function PDT_ReadPixelArray PDTM_SCALE function PDT_Scale PDTM_WRITEPIXELARRAY function PDT_WritePixelArray
sound.class 41.11
editOM_DISPOSE function Sound_DISPOSE OM_GET function Sound_GET OM_NEW function Sound_NEW OM_SET function Sound_SET OM_UPDATE function Sound_UPDATE GM_DOMAIN function Sound_DOMAIN GM_GOINACTIVE function Sound_GOINACTIVE GM_HANDLEINPUT function Sound_HANDLEINPUT alias GM_GOACTIVE GM_HITTEST function Sound_HITTEST alias GM_HELPTEST GM_LAYOUT function Sound_LAYOUT alias DTM_PROCLAYOUT GM_RENDER function Sound_RENDER DTM_CLEARSELECTED function Sound_CLEARSELECTED DTM_WRITE function Sound_WRITE alias DTM_COPY DTM_DRAW function Sound_DRAW DTM_OBTAINDRAWINFO function Sound_OBTAINDRAWINFO DTM_RELEASEDRAWINFO function Sound_RELEASEDRAWINFO DTM_REMOVEDTOBJECT function Sound_REMOVEDTOBJECT DTM_SELECT function Sound_SELECT DTM_TRIGGER function Sound_TRIGGER
animation.class
editImplement the animation.datatype (including boopsi control gadget). Must also provide a child datatype (ie avi, mpeg, divx or any other usable format) and a basic application to demonstrate functionality animation.datatype -- root data type for animations. The animation.datatype is the super-class for any animation related classes.
This class creates the controls, scaling, remapping and synchronization.
LONG DrawDTObjectA( struct RastPort * rp, Object * o, LONG x, LONG y, LONG w, LONG h, LONG th, LONG tv, struct TagItem * attrs ); LONG DrawDTObject( struct RastPort * rp, Object * o, LONG x, LONG y, LONG w, LONG h, LONG th, LONG tv, TAG tag, ... );
Draw a data type object into a RastPort. You must have successfully called ObtainDTDrawInfoA before calling this function; it invokes the object's DTM_DRAW method.
rp -- pointer to the RastPort to draw the object into o -- pointer to the data type object to draw x -- left edge of drawing area y -- top edge of drawing area w -- width of drawing area h -- height of drawing area th -- horizontal top in units tv -- vertical top in units attrs -- additional attributes
ADTA_Frame Tag for animationclass objects (selects the frame that should be drawn.
TRUE if rendering went OK, FALSE if failure. The RastPort in question must support clipping, i.e. have a valid layer structure attached to it; if not, some datatypes can't draw and FALSE will be returned.
/* Copyright � 2015-2020, The AROS Development Team. All rights reserved. $Id$ */ #include <graphics/gfx.h> #include <datatypes/pictureclass.h> #include <datatypes/animationclass.h> #include <datatypes/animationclassext.h> #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /* api flags */ #define ANIMDF_CONTROLPANEL (1 << 0) #define ANIMDF_IMMEDIATE (1 << 1) #define ANIMDF_REPEAT (1 << 2) #define ANIMDF_REMAP (1 << 3) #define ANIMDF_ADJUSTPALETTE (1 << 4) #define ANIMDF_ADAPTFPS (1 << 5) #define ANIMDF_FRAMESKIP (1 << 6) #define ANIMDF_SMARTSKIP (1 << 7) /* special flags used by rendering/layout code */ #define ANIMDF_LAYOUT (1 << 29) #define ANIMDF_REMAPPEDPENS (1 << 30) #define ANIMDF_SHOWPANEL (1 << 31) #define ANIMPLAYER_TICKFREQ ((struct RealTimeBase *)RealTimeBase)->rtb_Reserved1 struct ProcessPrivate; struct Animation_Data; struct AnimFrame; BOOL ProcEnabled(struct ProcessPrivate *, volatile ULONG *, ULONG); void cacheFrame(struct Animation_Data *, struct AnimFrame *); void freeFrame(struct Animation_Data *, struct AnimFrame *); struct AnimColor_Data { struct SignalSemaphore acd_PenLock; struct ColorMap *acd_ColorMap; struct ColorRegister *acd_ColorRegs; ULONG *acd_CRegs; ULONG *acd_GRegs; UWORD acd_NumColors; UWORD acd_NumAlloc; UBYTE *acd_ColorTable[2]; UBYTE *acd_Allocated; /* pens we have actually allocated */ ULONG acd_PenPrecison; /* precision to use allocating pens */ }; struct AnimFrame_Data { struct SignalSemaphore afd_AnimFramesLock; struct List afd_AnimFrames; UWORD afd_Frames; /* # of frames */ UWORD afd_FrameCurrent; /* # of current frame */ UWORD afd_FramesStep; /* how much to skip back/fwd */ }; struct AnimTimer_Data { UWORD atd_FramesPerSec; /* Playback rate */ UWORD atd_TicksPerFrame; /* realtime.libraries tick frequency / ad_FramesPerSec */ UWORD atd_Tick; }; /* our nodes used to play the anim! */ struct AnimFrame { struct Node af_Node; #define af_CacheBM af_Node.ln_Name ULONG af_Flags; struct adtNewFormatFrame af_Frame; }; #define AFFLAGB_READY 0 #define AFFLAGF_READY (1 << 0) /* for sanity, we embed the frame number in the ln_type/ln_pri fields */ static inline UWORD GetNODEID(struct AnimFrame *node) { UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type; return *id_ptr; } static inline void SetNODEID(struct AnimFrame *node, UWORD id) { UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type; *id_ptr = id; } struct Animation_Data { ULONG ad_Flags; /* object control flags */ char *ad_BaseName; struct Window *ad_Window; struct AnimFrame_Data ad_FrameData; struct AnimTimer_Data ad_TimerData; struct BitMap *ad_FrameBM; /* currently displayed frame */ struct BitMap *ad_CacheBM; /* .. */ struct AnimFrame *ad_KeyFrame; /* animations key (first) frame */ UWORD ad_VertTop; /* Y offset of visible rectangle */ UWORD ad_VertTotal; UWORD ad_VertVis; UWORD ad_HorizTop; /* X offset of visible rectangle */ UWORD ad_HorizTotal; UWORD ad_HorizVis; UWORD ad_RenderLeft; UWORD ad_RenderTop; UWORD ad_RenderWidth; UWORD ad_RenderHeight; IPTR ad_ModeID; struct BitMapHeader ad_BitMapHeader; /* objects embedded bitmap header */ struct AnimColor_Data ad_ColorData; IPTR ad_ProcStack; struct ProcessPrivate *ad_ProcessData; struct Process *ad_BufferProc; /* buffering process */ struct Process *ad_PlayerProc; /* playback process */ struct Player *ad_Player; struct Hook ad_PlayerHook; struct Gadget *ad_Tapedeck; ULONG ad_BufferTime; /* (prefs) how many seconds to buffer */ ULONG ad_BufferStep; /* (prefs) no of frames to try to load in one go */ UBYTE ad_PlayerSourceLastState; }; struct ProcessPrivate { Object *pp_Object; struct Animation_Data *pp_Data; char *pp_PlayBackName; char *pp_BufferingName; volatile ULONG pp_PlayerFlags; volatile ULONG pp_BufferFlags; ULONG pp_BufferFrames; /* no of frames to buffer in total */ ULONG pp_BufferLevel; /* no of frames buffered */ IPTR pp_BufferSpecific; /* specific frame to load */ struct AnimFrame *pp_BufferFirst; /* starting point to load from */ struct AnimFrame *pp_PlaybackFrame; ULONG pp_BufferSigMask; BYTE pp_BufferEnable; BYTE pp_BufferDisable; BYTE pp_BufferFill; BYTE pp_BufferPurge; ULONG pp_PlaybackSigMask; BYTE pp_PlaybackEnable; BYTE pp_PlaybackDisable; BYTE pp_PlaybackTick; /* signal frames needs to change */ BYTE pp_PlaybackSync; /* signal position changed */ }; #define PRIVPROCF_ENABLED (1 << 0) #define PRIVPROCF_RUNNING (1 << 1) #define PRIVPROCF_ACTIVE (1 << 2) #define PRIVPROCF_BUSY (1 << 3) #define TAG_PRIVATE (ADTA_Dummy + 100) #define PRIVATE_INITPLAYER (TAG_PRIVATE - 1) #define PRIVATE_ALLOCCOLORTABLES (TAG_PRIVATE - 2) #define PRIVATE_MAPFRAMEPENS (TAG_PRIVATE - 3) #define PRIVATE_FREECOLORTABLES (TAG_PRIVATE - 4) #define PRIVATE_FREEPENS (TAG_PRIVATE - 5) #define PRIVATE_ALLOCBUFFER (TAG_PRIVATE - 6) #define PRIVATE_RENDERFRAME (TAG_PRIVATE - 7) #define PRIVATE_REMAPFRAME (TAG_PRIVATE - 8) struct privAllocColorTables { STACKED ULONG MethodID; STACKED ULONG NumColors; }; struct privMapFramePens { STACKED ULONG MethodID; STACKED struct AnimFrame *Frame; }; struct privAllocBuffer { STACKED ULONG MethodID; STACKED struct BitMap *Friend; STACKED UBYTE Depth; }; struct privRenderFrame { STACKED ULONG MethodID; STACKED struct AnimFrame *Frame; STACKED struct BitMap *Target; }; #if DEBUG > 0 #define DFRAMES(...) bug(__VA_ARGS__); #else #define DFRAMES(...) #endif
/* Copyright � 2016-2020, The AROS Development Team. All rights reserved. $Id$ */ #ifndef DEBUG # define DEBUG 0 #endif #include <aros/debug.h> #include <clib/alib_protos.h> #include <proto/exec.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/utility.h> #include "animationclass.h" /* * converts/remaps a frame to a bitmap suitable for display.. */ void cacheFrame(struct Animation_Data *animd, struct AnimFrame *frame) { struct privRenderFrame rendFrameMsg; DFRAMES("[animation.datatype/CACHE]: %s()\n", __func__) if (frame->af_Frame.alf_CMap) { DFRAMES("[animation.datatype/CACHE]: %s: CMap @ 0x%p\n", __func__, frame->af_Frame.alf_CMap) rendFrameMsg.MethodID = PRIVATE_MAPFRAMEPENS; rendFrameMsg.Frame = frame; DoMethodA(animd->ad_ProcessData->pp_Object, (Msg)&rendFrameMsg); } rendFrameMsg.MethodID = PRIVATE_RENDERFRAME; rendFrameMsg.Frame = frame; if ((rendFrameMsg.Target = (struct BitMap *)frame->af_CacheBM) == NULL) { frame->af_CacheBM = (char *)AllocBitMap(animd->ad_BitMapHeader.bmh_Width, animd->ad_BitMapHeader.bmh_Height, 24, BMF_CLEAR, animd->ad_CacheBM); rendFrameMsg.Target = (struct BitMap *)frame->af_CacheBM; frame->af_Flags = 0; DFRAMES("[animation.datatype/CACHE]: %s: allocated frame cache bm @ 0x%p (friend @ 0x%p)\n", __func__, frame->af_CacheBM, animd->ad_CacheBM) } DoMethodA(animd->ad_ProcessData->pp_Object, (Msg)&rendFrameMsg); } void freeFrame(struct Animation_Data *animd, struct AnimFrame *frame) { DFRAMES("[animation.datatype/CACHE]: %s()\n", __func__) if (frame->af_CacheBM) { FreeBitMap((struct BitMap *)frame->af_CacheBM); frame->af_CacheBM = NULL; } }
/* Copyright � 2015-2020, The AROS Development Team. All rights reserved. $Id$ */ #ifndef DEBUG # define DEBUG 0 #endif #include <aros/debug.h> #include <clib/alib_protos.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/utility.h> #include <proto/realtime.h> #include <proto/layers.h> #include <proto/datatypes.h> #include <intuition/gadgetclass.h> #include <libraries/realtime.h> #include <gadgets/tapedeck.h> #include "animationclass.h" AROS_UFH3(ULONG, playerHookFunc, AROS_UFHA(struct Hook *, hook, A0), AROS_UFHA(struct Player *, obj, A2), AROS_UFHA(struct pmTime *, msg, A1)) { AROS_USERFUNC_INIT struct Animation_Data *animd = (struct Animation_Data *)hook->h_Data; IPTR buffSigs = 0, playbacksigs = 0; #if (0) // only enable if you like spam. bug("[animation.datatype]: %s(%08x)\n", __func__, msg->pmt_Method); #endif switch (msg->pmt_Method) { case PM_TICK: animd->ad_TimerData.atd_Tick++; if (animd->ad_TimerData.atd_Tick >= animd->ad_TimerData.atd_TicksPerFrame) { animd->ad_TimerData.atd_Tick = 0; // increment the frame counter if we are supposed to... if (!(animd->ad_ProcessData->pp_PlayerFlags & PRIVPROCF_BUSY) || (animd->ad_Flags & ANIMDF_FRAMESKIP)) { animd->ad_FrameData.afd_FrameCurrent++; if (animd->ad_FrameData.afd_FrameCurrent >= animd->ad_FrameData.afd_Frames) { if (animd->ad_Flags & ANIMDF_REPEAT) animd->ad_FrameData.afd_FrameCurrent = 1; else animd->ad_FrameData.afd_FrameCurrent = animd->ad_FrameData.afd_Frames - 1; } } if (animd->ad_ProcessData->pp_PlaybackTick != -1) playbacksigs |= (1 << animd->ad_ProcessData->pp_PlaybackTick); } if (animd->ad_TimerData.atd_Tick == 0) { // flush unused buffers... if (animd->ad_ProcessData->pp_BufferPurge != -1) buffSigs |= (1 << animd->ad_ProcessData->pp_BufferPurge); } break; case PM_SHUTTLE: D(bug("[animation.datatype] %s: PM_SHUTTLE\n", __func__);) animd->ad_FrameData.afd_FrameCurrent = msg->pmt_Time/animd->ad_TimerData.atd_TicksPerFrame; animd->ad_TimerData.atd_Tick = 0; if (animd->ad_ProcessData->pp_PlaybackSync != -1) playbacksigs |= (1 << animd->ad_ProcessData->pp_PlaybackSync); break; case PM_STATE: break; } if (buffSigs && (animd->ad_BufferProc)) Signal((struct Task *)animd->ad_BufferProc, buffSigs); if (playbacksigs && (animd->ad_PlayerProc)) Signal((struct Task *)animd->ad_PlayerProc, playbacksigs); return 0; AROS_USERFUNC_EXIT } void FreePlaybackSignals(struct ProcessPrivate *priv) { D(bug("[animation.datatype/PLAY]: %s()\n", __func__);) if (priv->pp_PlaybackTick != -1) FreeSignal(priv->pp_PlaybackTick); if (priv->pp_PlaybackEnable != -1) FreeSignal(priv->pp_PlaybackEnable); if (priv->pp_PlaybackDisable != -1) FreeSignal(priv->pp_PlaybackDisable); } BOOL AllocPlaybackSignals(struct ProcessPrivate *priv) { if ((priv->pp_PlaybackEnable = AllocSignal(-1)) != -1) { D(bug("[animation.datatype/PLAY]: %s: allocated enable signal (%x)\n", __func__, priv->pp_PlaybackEnable);) if ((priv->pp_PlaybackDisable = AllocSignal(-1)) != -1) { D(bug("[animation.datatype/PLAY]: %s: allocated disable signal (%x)\n", __func__, priv->pp_PlaybackDisable);) if ((priv->pp_PlaybackTick = AllocSignal(-1)) != -1) { D(bug("[animation.datatype/PLAY]: %s: allocated tick signal (%x)\n", __func__, priv->pp_PlaybackTick);) if ((priv->pp_PlaybackSync = AllocSignal(-1)) != -1) { D(bug("[animation.datatype/PLAY]: %s: allocated sync signal (%x)\n", __func__, priv->pp_PlaybackSync);) priv->pp_PlaybackSigMask = (1 << priv->pp_PlaybackEnable) | (1 << priv->pp_PlaybackDisable) | (1 << priv->pp_PlaybackTick) | (1 << priv->pp_PlaybackSync); D(bug("[animation.datatype/PLAY]: %s: signal mask (%x)\n", __func__, priv->pp_PlaybackSigMask);) return TRUE; } } } } return FALSE; } struct AnimFrame *NextFrame(struct ProcessPrivate *priv, struct AnimFrame *frameCurrent, UWORD *frame) { struct AnimFrame *frameFound = NULL, *frameFirst = NULL, *framePrev = NULL; UWORD frameID = 0; DFRAMES("[animation.datatype/PLAY]: %s(0x%p, %d)\n", __func__, frameCurrent, *frame) ObtainSemaphoreShared(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock); if ((!frameCurrent) || (*frame < GetNODEID(frameCurrent))) frameCurrent = frameFound = (struct AnimFrame *)&priv->pp_Data->ad_FrameData.afd_AnimFrames; else frameFound = frameCurrent; while ((frameFound->af_Node.ln_Succ) && (frameFound->af_Node.ln_Succ->ln_Succ)) { frameFound = (struct AnimFrame *)frameFound->af_Node.ln_Succ; DFRAMES("[animation.datatype/PLAY] %s: frame #%d @ 0x%p\n", __func__, GetNODEID(frameFound), frameFound) if (!frameFirst) frameFirst = frameFound; if (GetNODEID(frameFound) >= *frame) { break; } framePrev = frameFound; } if (!(frameFound) || (frameCurrent == frameFound) || (frameFound == (struct AnimFrame *)&priv->pp_Data->ad_FrameData.afd_AnimFrames) || (GetNODEID(frameFound) > *frame)) { frameFound = NULL; if (!(priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP)) { if ((frameFirst) && (GetNODEID(frameFirst) == (GetNODEID(frameCurrent) + 1))) frameFound = frameFirst; } else if ((framePrev) && (GetNODEID(framePrev) > 0)) frameFound = framePrev; if (!(frameFound) && (frameCurrent) && (GetNODEID(frameCurrent) < priv->pp_Data->ad_FrameData.afd_Frames)) frameFound = frameCurrent; } if (frameFound) { frameID = GetNODEID(frameFound); if (frameFound != frameCurrent) priv->pp_PlaybackFrame = frameFound; else frameFound = NULL; } *frame = frameID; DFRAMES("[animation.datatype/PLAY] %s: found #%d @ 0x%p\n", __func__, *frame, frameFound) ReleaseSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock); return frameFound; } BOOL GetFrameCacheBitmap(struct BitMap **frameBM, struct AnimFrame *frame) { if (frame->af_Flags & AFFLAGF_READY) { *frameBM = (struct BitMap *)frame->af_CacheBM; return TRUE; } return FALSE; } AROS_UFH3(void, playerProc, AROS_UFHA(STRPTR, argPtr, A0), AROS_UFHA(ULONG, argSize, D0), AROS_UFHA(struct ExecBase *, SysBase, A6)) { AROS_USERFUNC_INIT struct ProcessPrivate *priv = FindTask(NULL)->tc_UserData; struct AnimFrame *curFrame = NULL; struct gpRender gprMsg; struct TagItem attrtags[] = { { TAG_IGNORE, 0}, { TAG_IGNORE, 0}, { TAG_DONE, 0} }; UWORD frame = 0; ULONG signal, buffsigs; D(bug("[animation.datatype/PLAY]: %s()\n", __func__);) if (priv) { D( bug("[animation.datatype/PLAY] %s: private data @ 0x%p\n", __func__, priv); bug("[animation.datatype/PLAY] %s: dt obj @ 0x%p, instance data @ 0x%p\n", __func__, priv->pp_Object, priv->pp_Data); ) priv->pp_PlaybackFrame = NULL; priv->pp_PlayerFlags |= PRIVPROCF_RUNNING; if (AllocPlaybackSignals(priv)) { D(bug("[animation.datatype/PLAY]: %s: entering main loop ...\n", __func__);) while (TRUE) { priv->pp_PlayerFlags &= ~PRIVPROCF_ACTIVE; signal = priv->pp_PlaybackSigMask | SIGBREAKF_CTRL_C; signal = Wait(signal); D(bug("[animation.datatype/PLAY]: %s: signalled (%08x)\n", __func__, signal);) if (signal & SIGBREAKF_CTRL_C) break; priv->pp_PlayerFlags |= PRIVPROCF_ACTIVE; if (signal & (1 << priv->pp_PlaybackEnable)) priv->pp_PlayerFlags |= PRIVPROCF_ENABLED; else if (signal & (1 << priv->pp_PlaybackDisable)) priv->pp_PlayerFlags &= ~PRIVPROCF_ENABLED; if ((priv->pp_PlayerFlags & PRIVPROCF_ENABLED) && ((signal & ((1 << priv->pp_PlaybackTick)|(1 << priv->pp_PlaybackSync))) != 0)) { priv->pp_PlayerFlags |= PRIVPROCF_BUSY; frame = priv->pp_Data->ad_FrameData.afd_FrameCurrent; buffsigs = 0; DFRAMES("[animation.datatype/PLAY] %s: Frame #%d\n", __func__, frame) curFrame = NextFrame(priv, priv->pp_PlaybackFrame, &frame); if ((priv->pp_BufferFrames > priv->pp_BufferLevel) && (priv->pp_BufferLevel < priv->pp_Data->ad_FrameData.afd_Frames)) { buffsigs |= (1 << priv->pp_BufferFill); } if (!(curFrame)) { ObtainSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock); if ((signal & (1 << priv->pp_PlaybackSync)) || (priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP)) { priv->pp_BufferSpecific = frame; } if ((priv->pp_PlaybackFrame) && ((GetNODEID(priv->pp_PlaybackFrame) < frame) || (!(priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP) && (GetNODEID(priv->pp_PlaybackFrame) < (priv->pp_Data->ad_FrameData.afd_Frames - 1))))) { priv->pp_BufferFirst = priv->pp_PlaybackFrame; } else if (priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP) priv->pp_BufferFirst = NULL; ReleaseSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock); buffsigs |= ((1 << priv->pp_BufferPurge) | (1 << priv->pp_BufferFill)); } if ((buffsigs) && (priv->pp_Data->ad_BufferProc)) { Signal((struct Task *)priv->pp_Data->ad_BufferProc, buffsigs); if (buffsigs & (1 << priv->pp_BufferPurge)) SetTaskPri((struct Task *)priv->pp_Data->ad_PlayerProc, -2); } // frame has changed ... render it .. if ((curFrame) && GetFrameCacheBitmap(&priv->pp_Data->ad_FrameBM, curFrame)) { D( bug("[animation.datatype/PLAY]: %s: Rendering Frame #%d\n", __func__, GetNODEID(curFrame)); bug("[animation.datatype/PLAY]: %s: BitMap @ 0x%p\n", __func__, priv->pp_Data->ad_FrameBM); ) priv->pp_PlayerFlags &= ~PRIVPROCF_BUSY; if ((priv->pp_Data->ad_Window) && !(priv->pp_Data->ad_Flags & ANIMDF_LAYOUT)) { if (priv->pp_Data->ad_Tapedeck) { // update the tapedeck gadget.. attrtags[0].ti_Tag = TDECK_CurrentFrame; attrtags[0].ti_Data = GetNODEID(curFrame); attrtags[1].ti_Tag = TAG_IGNORE; SetAttrsA((Object *)priv->pp_Data->ad_Tapedeck, attrtags); } // tell the top level gadget to redraw... gprMsg.MethodID = GM_RENDER; gprMsg.gpr_RPort = priv->pp_Data->ad_Window->RPort; gprMsg.gpr_GInfo = NULL; gprMsg.gpr_Redraw = GREDRAW_UPDATE; DoGadgetMethodA((struct Gadget *)priv->pp_Object, priv->pp_Data->ad_Window, NULL, (Msg)&gprMsg); } } } } FreePlaybackSignals(priv); } priv->pp_PlayerFlags &= ~PRIVPROCF_RUNNING; priv->pp_Data->ad_PlayerProc = NULL; } D(bug("[animation.datatype/PLAY]: %s: exiting ...\n", __func__);) return; AROS_USERFUNC_EXIT }
// // animationclass.h // Const ANIMATIONDTCLASS : PChar = 'animation.datatype'; //* Tags */ ADTA_Dummy = (DTA_Dummy + 600); ADTA_ModeID = PDTA_ModeID; ADTA_KeyFrame = PDTA_BitMap; ADTA_ColorRegisters = PDTA_ColorRegisters; ADTA_CRegs = PDTA_CRegs; ADTA_GRegs = PDTA_GRegs; ADTA_ColorTable = PDTA_ColorTable; ADTA_ColorTable2 = PDTA_ColorTable2; ADTA_Allocated = PDTA_Allocated; ADTA_NumColors = PDTA_NumColors; ADTA_NumAlloc = PDTA_NumAlloc; ADTA_Remap = PDTA_Remap; ADTA_Screen = PDTA_Screen; ADTA_Width = (ADTA_Dummy + 1); ADTA_Height = (ADTA_Dummy + 2); ADTA_Depth = (ADTA_Dummy + 3); ADTA_Frames = (ADTA_Dummy + 4); ADTA_Frame = (ADTA_Dummy + 5); ADTA_FramesPerSecond = (ADTA_Dummy + 6); ADTA_FrameIncrement = (ADTA_Dummy + 7); ADTA_Sample = SDTA_Sample; ADTA_SampleLength = SDTA_SampleLength; ADTA_Period = SDTA_Period; ADTA_Volume = SDTA_Volume; ADTA_Cycles = SDTA_Cycles; //* New in V44 */ // NOTE: nowhere in MorpOS SDK are SDTA_xxx constants below defined. // i fixed it above. ADTA_PreloadFrameCount= (ADTA_Dummy + 8); { (V44) } ADTA_LeftSample = SDTA_LeftSample; { (V44) } ADTA_RightSample = SDTA_RightSample; { (V44) } ADTA_SamplesPerSec = SDTA_SamplesPerSec; { (V44) } //* IFF ANIM chunks */ ID_ANIM = ord('A') shl 24 + ord('N') shl 16 + ord('I') shl 8 + ord('M'); // 1095649613; ID_ANHD = ord('A') shl 24 + ord('N') shl 16 + ord('H') shl 8 + ord('D'); // 1095649348; ID_DLTA = ord('D') shl 24 + ord('L') shl 16 + ord('T') shl 8 + ord('A'); // 1145852993; Type PAnimHeader = ^TAnimHeader; TAnimHeader = record ah_Operation : UBYTE; ah_Mask : UBYTE; ah_Height : UWORD; ah_Width : UWORD; ah_Left : SWORD; ah_Top : SWORD; ah_AbsTime : ULONG; ah_RelTime : ULONG; ah_Interleave : UBYTE; ah_Pad0 : UBYTE; ah_Flags : ULONG; ah_Pad : packed array[0..16-1] of UBYTE; end; const //* Methods */ ADTM_Dummy = ($700); ADTM_LOADFRAME = ($701); ADTM_UNLOADFRAME = ($702); ADTM_START = ($703); ADTM_PAUSE = ($704); ADTM_STOP = ($705); ADTM_LOCATE = ($706); //* New on V44 */ ADTM_LOADNEWFORMATFRAME = ($707); ADTM_UNLOADNEWFORMATFRAME = ($708); Type PadtFrame = ^TadtFrame; TadtFrame = record MethodID : ULONG; alf_TimeStamp : ULONG; alf_Frame : ULONG; alf_Duration : ULONG; alf_BitMap : PBitMap; alf_CMap : PColorMap; alf_Sample : PSBYTE; alf_SampleLength: ULONG; alf_Period : ULONG; alf_UserData : APTR; end; PadtNewFormatFrame = ^TadtNewFormatFrame; TadtNewFormatFrame = record MethodID : ULONG; alf_TimeStamp : ULONG; alf_Frame : ULONG; alf_Duration : ULONG; alf_BitMap : PBitMap; alf_CMap : PColorMap; alf_Sample : PSBYTE; alf_SampleLength : ULONG; alf_Period : ULONG; alf_UserData : APTR; alf_Size : ULONG; alf_LeftSample : PSBYTE; alf_RightSample : PSBYTE; alf_SamplesPerSec : ULONG; end; PadtStart = ^tadtStart; TadtStart = record MethodID : ULONG; asa_Frame : ULONG; end;
Examples
edit#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/datatypes.h>
#include <datatypes/pictureclass.h>
int main (void)
{
struct RDArgs *rdargs;
struct {
char *file;
char *pubscreen;
} args = {0};
int rc = RETURN_FAIL;
struct Screen *scr;
Object *dto;
struct BitMapHeader *bmhd;
struct BitMap *bm;
WORD winw,winh;
struct Window *win;
struct IntuiMessage *imsg;
BOOL cont;
rdargs = ReadArgs ("FILE/A,PUBSCREEN/K",(LONG *)&args,NULL);
if (!rdargs)
{
PrintFault (IoErr(),NULL);
return (RETURN_FAIL);
}
if (scr = LockPubScreen (args.pubscreen))
{
if (dto = NewDTObject (args.file,DTA_GroupID,GID_PICTURE,PDTA_Remap,TRUE,PDTA_Screen,scr,TAG_END))
{
DoDTMethod (dto,NULL,NULL,DTM_PROCLAYOUT,NULL,TRUE);
GetDTAttrs (dto,(ULONG) PDTA_BitMapHeader,&bmhd,(ULONG) PDTA_BitMap,&bm,TAG_END);
if (bm && bmhd)
{
winw = bmhd->bmh_Width + scr->WBorLeft + scr->WBorRight;
winh = bmhd->bmh_Height + scr->WBorTop + scr->RastPort.TxHeight + 1 + scr->WBorBottom;
if (win = OpenWindowTags (NULL,
WA_Left, (scr->Width - winw) / 2,
WA_Top, (scr->Height - winh) / 2,
WA_Width, winw,
WA_Height, winh,
WA_Title, args.file,
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY,
TAG_END))
{
rc = RETURN_OK;
BltBitMapRastPort (bm,0,0,win->RPort,win->BorderLeft,win->BorderTop,win->GZZWidth,win->GZZHeight,0xc0);
cont = TRUE;
do {
if (Wait ((1L << win->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
cont = FALSE;
while (imsg = (struct IntuiMessage *) GetMsg (win->UserPort))
{
switch (imsg->Class)
{
case IDCMP_VANILLAKEY:
if (imsg->Code == 0x1b) /* Esc */
cont = FALSE;
break;
case IDCMP_CLOSEWINDOW:
cont = FALSE;
break;
}
ReplyMsg ((struct Message *) imsg);
}
}
while (cont);
CloseWindow (win);
}
}
else
Printf ("image cannot be rendered into the named pubscreen\n");
DisposeDTObject (dto);
}
else
{
Printf (GetDTString (IoErr()),args.file);
Printf ("\n");
}
UnlockPubScreen (NULL,scr);
}
else
Printf ("cannot lock pubscreen\n");
return (rc);
}
that's code of diskobjpngio.c.read
icon->iconPNG.handle = PNG_LoadImageMEM(icon->iconPNG.filebuffer, filesize, chunknames, chunkpointer, TRUE);
if (!icon->iconPNG.handle)
{
FreeIconPNG(&icon->dobj, IconBase);
return FALSE;
}
{
LONG width, height;
PNG_GetImageInfo(icon->iconPNG.handle, &width, &height, NULL, NULL);
icon->iconPNG.width = width;
icon->iconPNG.height = height;
icon->iconPNG.transparency = 0xffffffff;
PNG_GetImageData(icon->iconPNG.handle, (APTR *)&icon->iconPNG.img1, NULL);
dt2thumb application
edit#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <utility/utility.h>
#include <proto/arossupport.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/cybergraphics.h>
#include <proto/datatypes.h>
#include <proto/icon.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <datatypes/pictureclass.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CTRL_C (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
#define isDir(fib) ((fib)->fib_DirEntryType >= 0)
#define ARG_TEMPLATE "FILE/A,ALL/S,QUIET/S,W=WIDTH/N,H=HEIGHT/N,F=FORCEASPECT/S,M=METHOD,DEFTOOL"
enum
{
ARG_FILE = 0,
ARG_ALL,
ARG_QUIET,
ARG_WIDTH,
ARG_HEIGHT,
ARG_FORCEASPECT,
ARG_METHOD,
ARG_DEFTOOL,
NOOFARGS
};
/* Maximum file path length */
#define MAX_PATH_LEN 2048
const TEXT version[] = "$VER: dt2thumb 1.1 (10.12.2010)\n";
static char cmdname[] = "dt2thumb";
typedef struct rgbImage
{
UWORD Width;
UWORD Height;
UBYTE *Data;
}
RGBImage;
int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL readpic_by_datatype(RGBImage *pic, char *file_name);
BOOL savepic_by_datatype(RGBImage *pic, char *file_name);
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2);
int main(void)
{
struct RDArgs *rda = NULL;
struct AnchorPath *ap = NULL;
int retval = RETURN_OK;
STRPTR files = "#?";
BOOL all = FALSE;
BOOL quiet = FALSE;
ULONG destwidth = 128;
ULONG destheight = 128;
BOOL keepaspect = TRUE;
STRPTR method = NULL;
STRPTR deftool = NULL;
IPTR args[NOOFARGS] = { (IPTR)files, all, quiet, (IPTR)&destwidth, (IPTR)&destheight, !keepaspect ,(IPTR)method ,(IPTR)deftool};
ap = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN, MEMF_ANY | MEMF_CLEAR);
if (ap != NULL)
{
ap->ap_Strlen = MAX_PATH_LEN;
rda = ReadArgs(ARG_TEMPLATE, args, NULL);
if (rda != NULL)
{
/* Convert arguments into (less complex) variables */
if (args[ARG_FILE]) files = (STRPTR)args[ARG_FILE];
if (args[ARG_ALL]) all = TRUE;
if (args[ARG_QUIET]) quiet = TRUE;
if (args[ARG_WIDTH]) destwidth = (ULONG)*((IPTR *)args[ARG_WIDTH]);
if (args[ARG_HEIGHT]) destheight = (ULONG)*((IPTR *)args[ARG_HEIGHT]);
if (args[ARG_FORCEASPECT]) keepaspect = FALSE;
if (args[ARG_METHOD]) method = (STRPTR)args[ARG_METHOD];
if (args[ARG_DEFTOOL]) deftool = (STRPTR)args[ARG_DEFTOOL];
if (!all &&IsDosEntryA(files, LDF_VOLUMES | LDF_DEVICES))
{
Printf("Can't create thumb for %s - ", files);
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
PrintFault(IoErr(), NULL);
retval = RETURN_FAIL;
}
else
retval = doThumbs(ap, files, all, quiet, destwidth, destheight, keepaspect, deftool, method);
FreeArgs(rda);
}
else
{
PrintFault(IoErr(), cmdname);
retval = RETURN_FAIL;
}
if (ap!=NULL) FreeVec(ap);
}
else
{
retval = RETURN_FAIL;
}
return retval;
} /* main */
int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
LONG match;
int retval = RETURN_OK;
LONG indent = 0;
int i; /* Loop variable */
BOOL error;
for (match = MatchFirst(files, ap);
match == 0 && retval == RETURN_OK;// && !CTRL_C;
match = MatchNext(ap))
{
if (isDir(&ap->ap_Info))
{
if (ap->ap_Flags & APF_DIDDIR)
{
indent--;
ap->ap_Flags &= ~APF_DIDDIR; /* Should not be necessary */
continue;
}
else if (all)
{
ap->ap_Flags |= APF_DODIR;
indent++;
}
}
error = CreateThumb(ap->ap_Buf, destwidth, destheight, keepaspect, deftool, method);
if (!quiet)
{
/* Fix indentation level */
for (i = 0; i < indent; i++)
{
PutStr(" ");
}
if (!isDir(&ap->ap_Info))
{
PutStr(" ");
}
PutStr(ap->ap_Info.fib_FileName);
if (isDir(&ap->ap_Info))
{
PutStr(" (dir)");
}
if (error)
{
PutStr(" ..Not a known picture file\n");
}
else
{
PutStr(" ..Thumbnail created\n");
}
}
}
MatchEnd(ap);
return retval;
}
STRPTR get_ext(char *filename)
{
static char extension[32];
int position=strlen((char *)filename)-1;
strcpy(extension,"");
while(position > -1 && filename[position] != '.') position--;
if (position > -1)
{
strncpy(extension,&filename[position+1],32);
}
return extension;
}
BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
RGBImage *in_pic = NULL, *out_pic = NULL;
char outfile[MAX_PATH_LEN];
BOOL retval = TRUE;
// do not create thumb for info files
if (strnicmp(get_ext(infile),"info",4)==0) return retval;
sprintf(outfile,"%s.info",infile);
if (in_pic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
in_pic->Data = NULL;
if (readpic_by_datatype(in_pic, infile))
{
if (keepaspect)
{
int arw = in_pic->Width / destwidth;
int arh = in_pic->Height / destheight;
if (arw > arh) destheight = in_pic->Height / arw;
else if (arh > arw) destwidth = in_pic->Width / arh;
}
if (method != NULL)
{
if (strnicmp(method,"BI",2)==0)
out_pic = resizeBilinear(in_pic, destwidth, destheight);
else if (strnicmp(method,"AV",2)==0)
out_pic = resizeAverage(in_pic, destwidth, destheight);
else
out_pic = resizeNearest(in_pic, destwidth, destheight);
}
else
out_pic = resizeNearest(in_pic, destwidth, destheight);
if (out_pic)
{
if (savepic_by_datatype(out_pic, outfile))
{
// Write default tool
struct DiskObject *icon = GetIconTags
(
infile, ICONGETA_FailIfUnavailable, FALSE, TAG_DONE
);
if (icon != NULL)
{
STRPTR oldDefaultTool = icon->do_DefaultTool;
if (deftool)
icon->do_DefaultTool = deftool;
else
{
static STRPTR tool = "multiview";
icon->do_DefaultTool = tool;
}
if (!PutIconTags(infile, icon, TAG_DONE))
{
Printf("ERROR: Failed to write icon.\n");
}
icon->do_DefaultTool = oldDefaultTool;
FreeDiskObject(icon);
retval = FALSE;
}
else
{
Printf("ERROR: Failed to open icon for file\n");
retval = TRUE;;
}
}
}
}
if (in_pic)
{
if (in_pic->Data) FreeVec(in_pic->Data);
FreeVec(in_pic);
}
if (out_pic)
{
if (out_pic->Data) FreeVec(out_pic->Data);
FreeVec(out_pic);
}
}
return retval;
}
BOOL readpic_by_datatype(RGBImage *pic, char *file_name)
{
Object *DTImage = NULL;
struct BitMapHeader *bmh;
struct pdtBlitPixelArray bpa;
DTImage = NewDTObject( file_name,
(DTA_SourceType), DTST_FILE,
(DTA_GroupID), GID_PICTURE,
(PDTA_Remap), FALSE,
(OBP_Precision), PRECISION_EXACT,
TAG_DONE);
if (DTImage)
{
if (GetDTAttrs( DTImage,
PDTA_BitMapHeader, (ULONG)&bmh,
TAG_END ) == 1)
{
/* Picture struct and buffer mem allocation */
pic->Data = (UBYTE *)AllocVec(bmh->bmh_Width * bmh->bmh_Height * 4, MEMF_ANY);
if (pic->Data)
{
bpa.MethodID = PDTM_READPIXELARRAY;
bpa.pbpa_PixelData = (APTR)pic->Data;
bpa.pbpa_PixelFormat = PBPAFMT_ARGB;
bpa.pbpa_PixelArrayMod = bmh->bmh_Width * 4;
bpa.pbpa_Left = 0;
bpa.pbpa_Top = 0;
bpa.pbpa_Width = bmh->bmh_Width;
bpa.pbpa_Height = bmh->bmh_Height;
DoMethodA( DTImage, (Msg)&bpa );
pic->Width = bmh->bmh_Width;
pic->Height = bmh->bmh_Height;
DisposeDTObject( DTImage );
return TRUE;
}
}
DisposeDTObject( DTImage );
}
return FALSE;
}
/**
* Nearest Neighbor resizing algorithm
* In case of thumbnail generation the loss of quality
* should be minimal vs the bilinear algorithm
*/
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
ULONG x2,y2,i,j;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
outpic->Data = NULL;
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
for (i=0;i<h2;i++)
{
y2 = ((i*y_ratio)>>16) ;
for (j=0;j<w2;j++)
{
x2 = ((j*x_ratio)>>16) ;
temp[(i*w2)+j] = pixels[(y2*pic->Width)+x2] ;
}
}
}
}
return outpic;
}
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)
/**
* Averaging resizing algorithm
*
*
*/
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG xpixels = min(256,max((ULONG)(pic->Width/w2),1));
ULONG ypixels = min(256,max((ULONG)(pic->Height/h2),1));
ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
ULONG r,g,b,a,index;
ULONG x2,y2,i,j,x,y;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
outpic->Data = NULL;
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
for (i=0;i<h2;i++)
{
y2 = ((i*y_ratio)>>16) ;
for (j=0;j<w2;j++)
{
x2 = ((j*x_ratio)>>16) ;
r = 0;
g = 0;
b = 0;
a = 0;
for (y=0;y<ypixels;y++)
for (x=0;x<xpixels;x++)
{
index = ((y2+y)*pic->Width+(x2+x));
b += (pixels[index]&0xff);
g += ((pixels[index]>>8)&0xff);
r += ((pixels[index]>>16)&0xff);
a += ((pixels[index]>>24)&0xff);
}
r /= (ypixels*xpixels);
g /= (ypixels*xpixels);
b /= (ypixels*xpixels);
a /= (ypixels*xpixels);
temp[(i*w2)+j] = ((((ULONG)a)<<24) & 0xff000000) |
((((ULONG)r)<<16) & 0x00ff0000) |
((((ULONG)g)<<8) & 0x0000ff00) |
((ULONG)b) ;
}
}
}
}
return outpic;
}
/**
* Bilinear resize ARGB image.
* pixels is an array of size w * h.
* Target dimension is w2 * h2.
* w2 * h2 cannot be zero.
*/
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2)
{
ULONG *temp = NULL;
RGBImage *outpic = NULL;
ULONG *pixels = (ULONG *)pic->Data;
ULONG a, b, c, d, x, y, index ;
float x_ratio = ((float)(pic->Width-1))/w2 ;
float y_ratio = ((float)(pic->Height-1))/h2 ;
float x_diff, y_diff, blue, red, green, alpha ;
ULONG offset = 0 ;
int i,j;
if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
{
if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
{
outpic->Width = w2;
outpic->Height = h2;
temp = (ULONG *)outpic->Data;
if ((pic->Width==w2) && (pic->Height=h2))
{
CopyMem(pixels, temp, pic->Width * pic->Height * 4);
return outpic;
}
for (i=0;i<h2;i++)
{
for (j=0;j<w2;j++)
{
x = (ULONG)(x_ratio * j) ;
y = (ULONG)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = (y*pic->Width+x) ;
a = pixels[index] ;
b = pixels[index+1] ;
c = pixels[index+pic->Width] ;
d = pixels[index+pic->Width+1] ;
// blue element
// Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
blue = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) +
(c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff);
// green element
// Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
green = ((a>>8)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>8)&0xff)*(x_diff)*(1-y_diff) +
((c>>8)&0xff)*(y_diff)*(1-x_diff) + ((d>>8)&0xff)*(x_diff*y_diff);
// red element
// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
red = ((a>>16)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>16)&0xff)*(x_diff)*(1-y_diff) +
((c>>16)&0xff)*(y_diff)*(1-x_diff) + ((d>>16)&0xff)*(x_diff*y_diff);
// alpha element
// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
alpha = ((a>>24)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>24)&0xff)*(x_diff)*(1-y_diff) +
((c>>24)&0xff)*(y_diff)*(1-x_diff) + ((d>>24)&0xff)*(x_diff*y_diff);
temp[offset++] = ((((ULONG)alpha)<<24) & 0xff000000) |
((((ULONG)red) <<16) & 0x00ff0000) |
((((ULONG)green)<<8) & 0x0000ff00) |
((ULONG)blue) ;
}
}
}
}
return outpic ;
}
BOOL savepic_by_datatype(RGBImage *pic, char *file_name)
{
Object *DTImage = NULL;
struct BitMapHeader *bmhd;
struct dtWrite dtw;
struct pdtBlitPixelArray dtb;
FILE *file = NULL;
BOOL retval = FALSE;
DTImage = NewDTObject( (APTR)NULL,
DTA_SourceType, DTST_RAM,
DTA_BaseName, (IPTR)"png",
PDTA_DestMode, PMODE_V43,
TAG_DONE);
if (!DTImage) return(FALSE);
if (GetDTAttrs(DTImage,PDTA_BitMapHeader,(IPTR)&bmhd,TAG_DONE))
{
dtb.MethodID = PDTM_WRITEPIXELARRAY;
dtb.pbpa_PixelData = pic->Data;
dtb.pbpa_PixelFormat = PBPAFMT_ARGB;
dtb.pbpa_PixelArrayMod = pic->Width*4;
dtb.pbpa_Left = 0;
dtb.pbpa_Top = 0;
dtb.pbpa_Width = pic->Width;
dtb.pbpa_Height = pic->Height;
bmhd->bmh_Width = pic->Width;
bmhd->bmh_Height = pic->Height;
bmhd->bmh_Depth = 24;
bmhd->bmh_PageWidth = 320;
bmhd->bmh_PageHeight = 240;
DoMethodA(DTImage, (Msg) &dtb);
//write datatype object to file
if (file = Open (file_name,MODE_NEWFILE))
{
dtw.MethodID = DTM_WRITE;
dtw.dtw_GInfo = NULL;
dtw.dtw_FileHandle = file;
dtw.dtw_Mode = DTWM_RAW;
dtw.dtw_AttrList = NULL;
if (DoMethodA(DTImage, (Msg) &dtw)) retval = TRUE;
}
}
if (file) Close (file);
if (DTImage) DisposeDTObject(DTImage);
return retval;
}
sound function
editvoid do_sound()
{
soundnow = "sounds/bingobongo.aiff";
cout << "do sound!"<<endl;
int frq, vol, pan, state;
if (soundobject)DisposeDTObject(soundobject);
if ((soundobject = NewDTObject(soundnow,
DTA_SourceType, DTST_FILE,
DTA_GroupID, GID_SOUND,
DTA_Repeat, TRUE,
SDTA_SignalTask, (ULONG) FindTask(NULL),
SDTA_SignalBit, (ULONG) SIGBREAKF_CTRL_C,
TAG_DONE)))
{
DoDTMethod(soundobject, NULL, NULL, DTM_TRIGGER, NULL, STM_PLAY, NULL);
}
else
{
cout << "can't create sound"<<endl;
}
}
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
struct Picture_Data *pd;
const struct TagItem *tl = msg->ops_AttrList;
struct TagItem *ti;
IPTR RetVal;
struct RastPort *rp;
pd=(struct Picture_Data *) INST_DATA(cl, g);
RetVal=0;
while((ti=NextTagItem(&tl)))
{
switch (ti->ti_Tag)
{
case DTA_VisibleHoriz:
case DTA_VisibleVert:
RetVal = 1;
break;
case PDTA_ModeID:
pd->ModeID = (ULONG) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_ModeID: 0x%lx\n",(long)pd->ModeID));
break;
case PDTA_ClassBitMap:
pd->KeepSrcBM = TRUE;
DGS(bug("picture.datatype/OM_GET: Tag PDTA_ClassBitMap: Handled as PDTA_BitMap\n"));
case PDTA_BitMap:
pd->SrcBM = (struct BitMap *) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_BitMap: 0x%lx\n",(long)pd->SrcBM));
break;
case PDTA_Screen:
pd->DestScreen = (struct Screen *) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_Screen: 0x%lx\n",(long)pd->DestScreen));
break;
case PDTA_NumColors:
pd->NumColors = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_NumColors:%ld\n", (long)pd->NumColors));
break;
case PDTA_Grab:
{
Point *ThePoint;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_Grab\n"));
ThePoint = (Point *) ti->ti_Data;
if(!ThePoint)
{
break;
}
pd->Grab.x = ThePoint->x;
pd->Grab.y = ThePoint->y;
break;
}
case PDTA_SourceMode:
DGS(bug("picture.datatype/OM_SET: Tag PDTA_SourceMode (ignored): %ld\n", (long)ti->ti_Data));
break;
case PDTA_DestMode:
pd->DestMode = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DestMode: %ld\n",(long)pd->DestMode));
break;
case PDTA_FreeSourceBitMap:
pd->FreeSource = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_FreeSourceBitMap:%ld\n", (long)pd->FreeSource));
break;
case PDTA_UseFriendBitMap:
pd->UseFriendBM = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_UseFriendBitMap:%ld\n", (long)pd->UseFriendBM));
break;
case PDTA_MaxDitherPens:
pd->MaxDitherPens = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_MaxDitherPens:%ld\n", (long)pd->MaxDitherPens));
break;
case PDTA_DitherQuality:
pd->DitherQuality = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DitherQuality:%ld\n", (long)pd->DitherQuality));
break;
case PDTA_ScaleQuality:
pd->ScaleQuality = (UWORD) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_ScaleQuality:%ld\n", (long)pd->ScaleQuality));
break;
case PDTA_Remap:
pd->Remap = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag ID PDTA_Remap: %ld\n",(long)pd->Remap));
break;
#ifdef __AROS__
case PDTA_DelayedRead:
pd->DelayedRead = (BOOL) ti->ti_Data;
DGS(bug("picture.datatype/OM_SET: Tag PDTA_DelayedRead:
%ld\n", (long)pd->DelayedRead));
break;
#endif
#ifdef MYDEBUG
default:
{
register int i;
int Known;
Known=FALSE;
for(i=0; i<NumAttribs; i++)
{
if(ti->ti_Tag==KnownAttribs[i])
{
Known=TRUE;
DGS(bug("picture.datatype/OM_SET: Tag %s: 0x%lx (%ld)\n",AttribNames[i], (long)ti->ti_Data, (long)ti->ti_Data));
}
}
if(!Known)
{
DGS(bug("picture.datatype/OM_SET: Tag ID 0x%lx: 0x%lx\n",(long)ti->ti_Tag, (long)ti->ti_Data));
}
}
#endif /* MYDEBUG */
}
}
#if 0
if(msg->ops_GInfo)
{
DoMethod((Object *) g, GM_LAYOUT, msg->ops_GInfo, TRUE);
}
#endif
/* Do not call the SuperMethod if you come from OM_NEW! */
if(!(msg->MethodID == OM_NEW))
{
RetVal += (IPTR) DoSuperMethodA(cl, (Object *) g, (Msg) msg);
}
if(msg->ops_GInfo)
{
#if 1
if (RetVal)
#else
if(OCLASS((Object *) g) == cl)
#endif
{
rp=ObtainGIRPort(msg->ops_GInfo);
if(rp)
{
DoMethod((Object *) g, GM_RENDER, (IPTR) msg->ops_GInfo,(IPTR) rp, GREDRAW_UPDATE);
ReleaseGIRPort (rp);
}
}
#if 0 /* stegerg: ?? */
if(msg->MethodID == OM_UPDATE)
{
DoMethod((Object *) g, OM_NOTIFY, msg->ops_AttrList,
msg->ops_GInfo, 0);
}
#endif
}
return(RetVal);
}
---------------------------------------------------
STATIC IPTR DT_Render(struct IClass *cl, struct Gadget *g, struct gpRender *msg)
{
struct Picture_Data *pd;
struct DTSpecialInfo *si;
struct IBox *domain;
IPTR TopVert, TopHoriz;
long SrcX, SrcY, DestX, DestY, SizeX, SizeY;
pd = (struct Picture_Data *) INST_DATA(cl, g);
si = (struct DTSpecialInfo *) g->SpecialInfo;
if(!pd->Layouted)
{
D(bug("picture.datatype/GM_RENDER: No layout done yet !\n"));
return FALSE;
}
if(si->si_Flags & DTSIF_LAYOUT)
{
D(bug("picture.datatype/GM_RENDER: In layout process !\n"));
return FALSE;
}
if(!(GetDTAttrs((Object *) g, DTA_Domain, (IPTR) &domain,
DTA_TopHoriz, (IPTR) &TopHoriz,
DTA_TopVert, (IPTR) &TopVert,
TAG_DONE) == 3))
{
D(bug("picture.datatype/GM_RENDER: Couldn't get dimensions\n"));
return FALSE;
}
ObtainSemaphore(&(si->si_Lock));
D(bug("picture.datatype/GM_RENDER: Domain: left %ld top %ld width %ld height %ld\n", domain->Left, domain->Top, domain->Width, domain->Height));
D(bug("picture.datatype/GM_RENDER: TopHoriz %ld TopVert %ld Width %ld Height %ld\n", (long)TopHoriz, (long)TopVert, (long)pd->DestWidth, (long)pd->DestHeight));
if( pd->DestBM )
{
SrcX = MIN( TopHoriz, pd->DestWidth );
SrcY = MIN( TopVert, pd->DestHeight );
DestX = domain->Left;
DestY = domain->Top;
SizeX = MIN( pd->DestWidth - SrcX, domain->Width );
SizeY = MIN( pd->DestHeight - SrcY, domain->Height );
D(bug("picture.datatype/GM_RENDER: SizeX/Y %ld/%ld\n SrcX/Y %ld/%ld DestX/Y %ld/%ld\n",
SizeX, SizeY, SrcX, SrcY, DestX, DestY));
render_on_rastport(pd, g, SrcX, SrcY, msg->gpr_RPort, DestX, DestY, SizeX, SizeY);
}
else /* if(pd->DestBuffer) || if(pd->DestBM) */
{
D(bug("picture.datatype/GM_RENDER: No destination picture present !\n"));
return FALSE;
}
ReleaseSemaphore(&(si->si_Lock));
return TRUE;
}
assume you are trying to manipulate images? Load images using datatypes but read image data to ARGB array using ReadPixelArray methods and dispose source object. For images, to get the raw data use PDTM_READPIXELARRAY (that's the uncompressed data).