Aros/開發者/文件/庫/資料型別
datatypes.library 的引入是為了使用不同的類輕鬆解碼檔案格式(#?.png #?.jpg 等),這些類可以根據需要安裝。
首先,您應該瞭解 BOOPSI(Amiga OOP 面向物件系統)。一旦理解了,就會更容易理解資料型別、MUI 等。
devs/datatypes 中的描述符包含如何識別檔案型別的資訊。通常,檔案只會被 datatypes.library 開啟一次,並且使用一個小緩衝區進行比較,該緩衝區包含檔案的前幾個位元組(IIRC 為 64 個位元組)。
dt 描述符與 struct DataTypeHeader dth_Name、dth_BaseName 等相關聯。
大多數資料型別描述符都非常簡單,例如“將前 12 個位元組與模式 FORM????ILBM 進行比較”。比較由 datatypes.library 完成,沒有涉及任何外部程式碼。
只有極少數描述符實際上包含程式碼。在程式碼中,任何事情都可以完成。例如,程式碼可以關閉並重新開啟檔案,並在需要時完全讀取它。但是,不應這樣做,因為識別需要非常快。
Dtdesc 工具(以及附帶的文件)createdtdesc 包旨在建立(圖片)資料型別(作為一個整體,包括 makefile)。dtdescr 旨在(僅)檢視和建立描述符。
一旦檔案型別被識別,並且應用程式想要載入檔案,就會呼叫 classes/datatypes 中的類庫。這個庫包含解碼檔案內容並將其提供給 datatypes.library 的程式碼。
資料型別包含一些庫,這些庫公開了一些方法來載入和儲存特定型別的圖片。在內部,存在圖片資料型別使用的畫素的“公共”儲存方法,因此每個可以處理自身型別的“庫”能夠將此公共儲存方法轉換為特定格式或載入到此特定格式。
資料型別系統本身公開了開發者/使用者可以使用的方法,這些方法可以透過簡單地呼叫一些函式來輕鬆地載入和儲存。
AmigaOS 實現資料型別唯一的缺陷是它們並不真正雙向。您通常只能以 IFF 格式儲存,但 AROS 渴望將原始思想帶回來。
理想的實現將允許每個資料型別超類(picture.datatype、sound.datatype 等)提供支援編碼的所有已知子類的列表。然後,您將能夠選擇一個併為該資料型別編碼資料,並將其以該格式寫入磁碟。
Wanderer(AROS WB 替代品)不直接使用資料型別子系統,"除了"載入視窗背景影像之外。資料型別系統還無法處理漸進載入和流式傳輸。
建立一個數據型別物件,使用 NewDTObject 函式...
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))
此函式的引數使用在 datatypes/datatypesclasses.h 和 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
一旦不再需要資料型別物件,它就會被處理掉,記憶體也會被釋放:例如。
DisposeDTObject (gd->gd_DisplayObject);
要從資料型別物件獲取屬性,您可以使用 GetDTAttrs 函式,例如。
GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);
並檢查 dtn 結構中的結果,您可以檢索
dtn->dtn_Header->dth_Name = Descriptive name of the datatype dtn->dtn_Header->dth_GroupID = The group the datatype belongs to
GetDTString 函式返回給定 id 的本地化資料型別字串。此字串可能是 syst、text、docu、soun、inst、musi、pict、anim 或 movi(參見 datatypes.h)。例如。
GetDTString (dtn->dtn_Header->dth_GroupID)
開啟一個檔案並知道它的基類,你只需要
Object *dto;
if(dto = NewDTObject(filename, DTA_GroupID, GID_TEXT, TAG_DONE))
DisposeDTObvject(dto);
DTA_GroupID 標籤確保檔案是該型別。否則,當您嘗試讀取資料時,您將遇到問題。
您需要在 DisposeDTObject 之前使用 GetDTAttrs 或呼叫一些方法,如果您想執行任何有用的操作。
如果您只是想找出檔案的型別,您需要類似於以下的內容。
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);
}
然後,您可以開啟檔案並根據基型別 dth_GroupID 處理它。
通常,您要做的是建立一個物件(初始狀態),獲取/設定一些屬性(屬性更改),然後進行佈局或提取型別。
在這種情況下,有許多程式呼叫重新對映,但沒有 gpinfo 結構。
重新對映在初始狀態下有哪些資訊嗎?
AROS dt 將其設定為 true。
pd->Remap = TRUE;
當程式沒有帶有螢幕的 gpinfo 時,重新對映應該設定為 false。也許 AmigaOS AOS 在某個地方做了這個操作。
AROS dt 上也會發生同樣的情況,也許在 AOS dt 點陣圖(狀態更改和獲取/設定)上;但是,在狀態更改可能會影響哪些屬性(螢幕、顏色)或在某些屬性未在觸發狀態更改之前設定的情況下會發生什麼,這一點尚未明確定義;甚至哪些狀態是可能的,這一點也不完全清楚。
您的應用程式可以使用帶有 ICTargetIDCMP 值的 Boopsi ICATarget 屬性來找出何時需要重新整理。這會導致資料型別(小部件)在某些狀態更改時向視窗埠傳送一個 IDCMP_IDCMPUpdate IntuiMessage。該訊息包含一個指向一個或多個屬性的指標,如果 DTA_Sync 在該列表中並且值為 1,則資料型別物件已準備好重新整理。
當您將資料型別物件附加到視窗時,您會收到其中一個,以及當視窗大小改變時會收到一系列的這些訊息。
為了建立一個 jpeg 資料型別物件(jpeg 是圖片類的子類)
DTImage = NewDTObject(NULL, DTA_SourceType, DTST_RAM, DTA_BaseName, "jpeg", PDTA_DestMode, PMODE_V43, TAG_DONE);
AROS/workbench/classes/datatypes/text/ V44.5 的 text.datatype 替代品 sebauer@t-online.de (Sebastian Bauer)
AROS 之外的多數作業系統更喜歡 XML,但其他作業系統喜歡 doc、docx、ood、rtf 等。
最初,FTXT 被 AmigaOS 的剪貼簿用於剪下/複製功能,當前的應用程式僅使用原始 ASCII 資料。IFF FTXT 應該代表格式化的文字,但顯然支援的格式很少,這也會影響到可以放在剪貼簿上的內容(複製一個包含所有格式的表格並不容易)。
#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
AROS/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)
AROS/workbench/classes/datatypes/sound.datatype 基於 Stephan Rupprechts 來自 Aminet 的 sounddt 41
AROS 只有兩種聲音資料型別,分別是 Wave 資料型別和 8SVX 資料型別。8SVX 資料型別首先檢視 OM_NEW 和 Read8SVX。但 Read 函式不會測試 DTST_RAM 和空檔案控制代碼。
只有 8 位聲音,仍然需要 16 位和 32 位聲音。
#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
};
/****************************************************************************/
/*
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
其他文字子類是
原始規範提供了一些對 FTXT 的支援,FTXT 是 IFF 的“資料部分”或“FORM 型別”。文字儲存在一個或多個 FTXT 內部的“CHRS”塊中。每個 CHRS 包含一個與 ANSI/ISO 標準相容的 8 位文字流
- 在 NUL(十六進位制 00)到十六進位制 1F 範圍內的 C0 終端控制字元。只有 LF(十六進位制 0A)和 ESC(十六進位制 1B)是重要的。ESC 啟動一個控制序列。LF 是行終止符,CR(十六進位制 0D)不被識別為終止符。
- 在十六進位制 20 到十六進位制 7F 範圍內的 G0 圖形字元。SP(十六進位制 20)是空格字元。DEL(十六進位制 7F)是刪除字元,不使用。其餘的是標準 ASCII 可列印字元“!”(十六進位制 21)到“~”(十六進位制 7E)。
- 在十六進位制 80 到十六進位制 9F 範圍內的 C1 擴充套件控制字元。以 CSI(十六進位制 9B)開頭的控制序列用於 FTXT 格式化。所有其他控制序列和 C1 控制字元均未使用。
- G1 是在 NBSP(十六進位制 A0)到“y”(十六進位制 FF)範圍內的擴充套件圖形字元組。
可選的“FONS”儲存一個 FontSpecifier,如下所示。它將字型分配給一個編號的暫存器,以便可以在其他 CHRS 塊中按編號引用它。CHRS 文字使用字型 1,直到選擇另一個字型。如果字型 1 未指定,則使用選定的系統字型作為字型 1。SGR 序列具有引數 10-19,用於從十個預定義字型中選擇,這意味著 IFF FTXT 檔案中只有十個 FONS 塊有意義。
如果應用程式程式設計師開始使用符合 FTXT 規範的格式化文字,其他程式設計師將不再假設剪貼簿只包含純文字資料。因此,他們需要在剪貼簿處理例程中實現適當的控制程式碼剝離(同樣,根據 FTXT 規範)。
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;
其他可以儲存多個影像的影像檔案資料型別,例如 INFO、ICO、ICNS 等,為 AROS 圖片資料型別添加了“WhichPicture”和“GetNumPictures”PDTA 方法。我們可以使用圖片資料型別顯示多個影像!
新增一個函式來計算影像目錄(IFD)以獲取 GetNumPictures 會很容易。
TIFF 資料型別可以使用 PDTA_GetNumPictures 計數目錄,並且可以使用 PDTA_WhichPicture 設定當前目錄。所以現在它可以顯示多個影像了。
/*
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_Write 函式是 SuperMethod。通常,當資料型別具有兩種方法時:OM_NEW 和 DTM_WRITE。第一個將資料型別的 Load 函式與 Datatypes 庫連結,用於獲取新的資料型別。第二個連結資料型別的 Save 函式,或者如果 DT Write 方法不是 DTWM_RAW,則它應該委託給 SuperMethod。在這種情況下,它將 DTWM_IFF 訊息傳送到聲音資料型別函式 Sound_Write。
是否最好使用 DTMethod 在緩衝區上解壓縮,然後使用此未壓縮的緩衝區?對於聲音,使用 SDTA_Sample(或 SDTA_LeftSample/SDTA_RightSample)屬性獲取資料。可以使用 SDTA_Sample 標籤檢索樣本資料,但 AmigaOS 不支援 SDTA_SampleType,因此您只能從那裡獲取 8 位樣本資料。AROS 和 MorphOS 在這裡更先進。
任何應用程式都會查詢您的類支援的方法。確保如果您選擇實現對 OM_GET/DTA_Methods 標籤的支援,您返回的方法也應該包含您的超類支援的方法。否則,使用者將無法使用“複製”或“列印”等函式。
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.
AmigaOS 使用者嘗試使用它來提供 HTML、圖片、動畫和音訊的組合。
到目前為止,AROS 還沒有任何類似的東西。
構建 dtdesc 工具,這是您需要的。原始碼位於 tools/dtdesc 中。該工具用於從 .dtd 檔案建立資料型別描述符。類庫以通常的方式構建,使用通常的交叉編譯器。
一個包,以便可以獨立於整個構建系統輕鬆構建資料型別。為原生 AROS 編譯了 createdtdesc 和 examinedtdesc。另一個需要的工具是 genmodule。
需要一個 READ/WRITEPIXELARRAY 介面,它取代了以前的 SET PDTA_BitMap 和 GET PDTA_DestBtMap 介面。如果一個位圖被 SET(舊介面),它會在佈局過程中被轉換為 LUT8 格式。僅當 Prefs 設定了它或應用程式透過 GET PDTA_DestBitMap 請求它時,才會建立目標點陣圖。
RENDER 方法選擇以下函式之一進行顯示
- cgfx/WritePixelArray:真彩色圖片 -> 真彩色螢幕
- cgfx/WriteLUTPixelArray:顏色對映圖片 -> 真彩色螢幕
- graphics/WriteChunkyPixels:顏色對映圖片 -> 顏色對映塊狀螢幕
- graphics/BltBitMapRastPort:顏色對映圖片 -> 顏色對映平面螢幕
真彩色圖片 -> 顏色對映螢幕在佈局過程中處理,使用固定的顏色對映和一些簡單的但快速的抖動演算法(一維誤差傳播)。Floyd-Steinberg 抖動演算法可用於獲得稍微好一些的結果(二維誤差傳播)。透過計算顏色對映(例如中值切割演算法)可以獲得更好的結果,但這要慢得多。
顏色對映資料始終儲存在 LUT8 格式中,或為舊版儲存在 BitMap 格式中。真彩色資料始終儲存在 ARGB 格式中。這在記憶體方面並不有效,但使事情更簡單、更快。這裡可以做一些最佳化。
為新的圖形資料型別建立了一個模板 這裡。
NAME
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.
資料型別系統還無法處理漸進載入和流。
- V30 Amiga OS 2
- V40 Amiga OS 3
- V44 Amiga OS 3.5+
Commodore 和 Electronic Arts 開發了 IFF(可互換檔案格式)來涵蓋圖片(ILBM)、聲音(8SVX)和文字(FTXT)等。因此,對於 AmigaOS 3.0 引入了資料型別庫,它可以使用不同的類輕鬆解碼檔案格式,這些類可以在需要時安裝。
包含以下標頭檔案以使用資料型別
#include <proto/datatypes.h> #include <datatypes/datatypes.h>
要使用資料型別,您需要在您的程式中開啟資料型別庫以及其他庫
DataTypesBase = OpenLibrary ("datatypes.library", 39)
要建立資料型別物件,請使用以下 NewDTObject 函式
Object o = NewDTObject(APTR name, Tag1[, tag2, tag3, ... ] ) Object o = NewDTObjectA(APTR name, struct TagItem *attrs)
資料型別可以使用的資料來源型別包括剪貼簿(DTST_CLIPBOARD)、檔案(DTST_FILE)、RAM(DTST_RAM、DTST_MEMORY)或熱連結(DTST_HOTLINK)。
您可以用於資料型別的一組物件包括
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.
例如,從剪貼簿讀取物件
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))
此函式的引數使用在 datatypes/datatypesclasses.h 和 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
此示例從“pathname”讀取要顯示的檔案,並且其型別為圖片(ILBM、JPEG、GIF、PNG 等)。
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.
使用 NewDTObject 載入資料型別後,程式應該建立一個視窗,然後資料型別物件可以使用單個命令新增到視窗或請求器中。
LONG realposition = AddDTObject( struct Window *win, struct Requester *req, Object *obj, LONG pos);
引數
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);
一旦資料型別物件不再需要,它將從視窗中刪除並處置,並釋放記憶體。
position = RemoveDTObject(window, object);
void DisposeDTObject(Object *o)
RemoveDTObject(win, gd->gd_DisplayObject);
DisposeDTObject (gd->gd_DisplayObject);
要從資料型別物件獲取屬性,可以使用 GetDTAttrs 函式
GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);
並檢查 dtn 結構中的結果,你可以檢索到
dtn->dtn_Header->dth_Name = Descriptive name of the datatype. dtn->dtn_Header->dth_GroupID = The group the datatype belongs to
GetDTString 函式返回給定 ID 的本地化資料型別字串。此字串可能是 syst、text、docu、soun、inst、musi、pict、anim 或 movi(參見 datatypes.h)。
GetDTString (dtn->dtn_Header->dth_GroupID)
其他可用於資料型別的函式:ObtainDataType()、ReleaseDataType()、SetDTAttrs()、RefreshDRObject()、DoAsyncLayout()、DoDTMethod()、GetDTMethods()、DTMethods()、PrintDTObject()。
資料型別
索引 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 );
函式
將物件新增到視窗 'win' 或請求器 'req' 中,位置由 'pos' 引數指定的工具列表中的位置。
輸入
win -- 應新增物件的視窗;如果為空則
nothing is done
req -- 應新增物件的請求器 obj -- 要新增的物件;如果為空則不執行任何操作 pos -- 物件在列表中的位置
結果
物件新增的位置(可能與你要求的不同)。
備註
當物件新增時,物件將收到一條包含 gpl_Initial 欄位設定為 1 的 GM_LAYOUT 訊息。
另請參閱 RemoveDTObject() intuition.library/AddGList()
CopyDTMethods()
ULONG * CopyDTMethods(
ULONG * methods,
ULONG * include,
ULONG * exclude );
函式
複製和修改方法陣列。這由想要向現有類新增支援方法的子類實現者使用。
輸入
methods -- 方法陣列;可能為空 include -- 要包含的方法陣列,以 ~0UL 結尾;可能為空 method -- 要排除的方法陣列,以 ~0UL 結尾;可能為空。
結果
新的方法陣列或 NULL(如果出現錯誤,例如記憶體不足)。
另請參閱
FindMethod() CopyDTTriggerMethods() FreeDTMethods()
CopyDTTriggerMethods()
struct DTMethod * CopyDTTriggerMethods(
struct DTMethod * methods,
struct DTMethod * include,
struct DTMethod * exclude );
函式
複製和修改 DTMethod:s 陣列。這由想要向現有類新增支援方法的子類實現者使用。
輸入
methods -- 方法陣列;可能為空 include -- 要包含的方法陣列,以 ~0UL 結尾;可能為空 method -- 要排除的方法陣列,以 ~0UL 結尾;可能為空
the dtm_Command and dtm_Method fields may have the options
described in the FindTriggerMethod to filter out the given
entries
結果
新的方法陣列或 NULL(如果出現錯誤,例如記憶體不足)。
備註
dtm_Label 和 dtm_Command 必須在物件存在期間有效,因為它們不會被複制。
A subclass that implment DTM_TRIGGER must send unknown trigger
方法到其超類。
另請參閱
FindTriggerMethod() CopyDTMethods() FreeDTMethods()
DisposeDTObject()
void DisposeDTObject(
Object * o );
函式
釋放透過 NewDTObjectA() 獲得的資料型別物件。
輸入
o -- 要釋放的資料型別物件;可能為空。
另請參閱
NewDTObjectA() DoAsyncLayout() 摘要
ULONG DoAsyncLayout(
Object * object,
struct gpLayout * gpl );
函式
執行物件的 DTM_ASYNCLAYOUT 方法 -- 非同步執行它會解除安裝 input.device。當收到 SIGBREAK_CTRL_C 時,方法應退出;此訊號表示資料已過時,該方法將再次被呼叫。
輸入
object -- 指向資料型別物件的指標 gpl -- gpLayout 訊息指標
DoDTDomainA() 摘要
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, ... );
函式
獲取資料型別物件的最大/最小/標稱域。
輸入
o -- 相關的資料型別物件 win -- 物件附加到的視窗 req -- 物件附加到的請求器 rport -- rastport;用於域計算 which -- 要獲取的域(GDOMAIN_,參見 <intuition/gadgetclass.h> domain -- 結果將放在這裡 attrs -- 附加屬性(子類特定)
結果
GM_DOMAIN 的返回值或 0(如果發生錯誤)。作為副作用,'domain' IBox 將填充請求的值。
備註
此函式需要一個物件來執行 GM_DOMAIN 方法。要實現類似的結果而無需物件,必須手動使用 CoerceMethodA()。
另請參閱 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, ... );
函式
執行特定資料型別方法。
輸入
o -- 指向資料型別物件的指標 win -- 物件附加到的視窗 req -- 物件附加到的請求器 msg -- 要傳送到物件的メッセージ
結果
指定方法返回的值。
另請參閱
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, ... );
函式
將資料型別物件繪製到 RastPort 中。在呼叫此函式之前,必須成功呼叫 ObtainDTDrawInfoA;它會呼叫物件的 DTM_DRAW 方法。
輸入
rp -- 指向要將物件繪製到的 RastPort 的指標 o -- 指向要繪製的資料型別物件的指標 x -- 繪製區域的左邊緣 y -- 繪製區域的頂部邊緣 w -- 繪製區域的寬度 h -- 繪製區域的高度 th -- 水平頂部(以單位表示) tv -- 垂直頂部(以單位表示) attrs -- 附加屬性
標籤
ADTA_Frame 用於動畫類物件(選擇應繪製的幀)。
結果
如果渲染成功,則為 TRUE,如果失敗,則為 FALSE。
備註
相關的 RastPort 必須支援裁剪,即具有附加到它的有效層結構;如果沒有,某些資料型別無法繪製,並且將返回 FALSE。
另請參閱 ObtainDataTypeA()
FindMethod()
ULONG * FindMethod(
ULONG * methods,
ULONG searchmethodid );
函式
在方法陣列中搜索特定方法。
輸入
methods -- 方法陣列;可能為空 searchmethodid -- 要搜尋的方法
結果
指向方法表條目的指標或 NULL(如果未找到該方法)。
另請參閱
GetDTMethods() CopyDTMethods()
FindToolNodeA()
struct ToolNode * FindToolNodeA(
struct List * toollist,
struct TagItem * attrs );
struct ToolNode * FindToolNode(
struct List * toollist,
TAG tag, ... );
函式
在給定工具節點列表中搜索特定工具。
輸入
toollist -- 列表或 struct ToolNode *(將被跳過)要
search in; may be NULL.
attrs -- 搜尋標籤;如果為空,則函式的結果將
simply be the following node.
標籤
TOOLA_Program -- 要搜尋的程式的名稱
TOOLA_Which -- 其中一個 TW_#? 型別
TOOLA_LaunchType -- 啟動模式:TF_SHELL、TF_WORKBENCH 或 TF_RX
結果
指向描述搜尋結果的 ToolNode 的指標(如果失敗則為 NULL)。
備註
dt->dtn_ToolList 中的條目在資料型別 'dt' 上保持鎖定期間有效(ObtainDataTypeA() 或 LockDataType())。
另請參閱 LaunchToolA()
FindTriggerMethod()
struct DTMethod * FindTriggerMethod(
struct DTMethod * methods,
STRPTR command,
ULONG method );
函式
在觸發方法陣列中搜索特定觸發方法(檢查 'command' 或 'method' 是否匹配)。
輸入
methods -- 觸發方法陣列;可能為空 command -- 觸發方法的名稱(可能為空;如果是,則為 'command'
is not matched against)
method -- 要搜尋的觸發方法的 ID(可能為 ~0;如果是,則不要
match against 'method'.
結果
指向觸發方法表條目的指標(struct DTMethod *)或 NULL(如果未找到該方法)。
另請參閱 GetDTTriggerMethods() CopyDTTriggerMethods()
FreeDTMethods()
VOID FreeDTMethods(
APTR methods );
函式
釋放從 CopyDTMethods() 或 CopyDTTriggerMethods() 獲取的陣列。
輸入
methods -- 方法陣列;可能為空
另請參閱
CopyDTMethods() CopyDTTriggerMethods() GetDTAttrsA() 摘要
ULONG GetDTAttrsA(
Object * o,
struct TagItem * attrs );
ULONG GetDTAttrs(
Object * o,
TAG tag, ... );
函式
獲取特定資料型別物件的屬性。
輸入
o -- 指向資料型別物件的指標;可能為空 attrs -- 要獲取的屬性,以 TAG_DONE 結尾;每個標籤的
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
結果
獲取的屬性數量。
備註
(#1) - 在 AROS 上,物件返回的“DataType”可能是
the real entry, so that the subclass can override
subformat information.
另請參閱 SetDTAttrsA() intuition.library/GetAttr()
GetDTMethods()
ULONG * GetDTMethods(
Object * object );
函式
獲取物件支援的方法列表。
輸入
object -- 指向資料型別物件的指標
結果
指向以 ~0 結尾的 ULONG 陣列的指標;該陣列僅在物件被釋放之前有效。
另請參閱 GetDTTriggerMethods()
GetDTString()
CONST_STRPTR GetDTString(
ULONG id );
函式
獲取指向本地化資料型別字串的指標。
輸入
id -- 要獲取的字串的 ID
結果
指向以 NULL 結尾的字串的指標。
GetDTTriggerMethodDataFlags()
ULONG GetDTTriggerMethodDataFlags(
ULONG method );
函式
獲取可能附加到 dtTrigger 方法主體中的 stt_Data 欄位的型別的資料型別。資料型別可以透過將方法 ID(在 STMF_METHOD_MASK 值中)與一個 STMD_ 識別符號進行或運算來指定。
STMD_VOID -- stt_Data 必須為空 STMD_ULONG -- stt_Data 包含一個無符號值 STMD_STRPTR -- stt_Data 是指向字串的指標 STMD_TAGLIST -- stt_Data 指向以
with TAG_DONE
在 STM_USER 以下的觸發方法在 <datatypes/datatypesclass.h> 中明確說明。
輸入
method -- struct DTMethod 中的 dtt_Method ID
結果
在 <datatypes/datatypesclass.h> 中定義的 STMD_ 識別符號之一
另請參閱 CopyDTTriggerMethods() FindTriggerMethod()
GetDTTriggerMethods()
struct DTMethod * GetDTTriggerMethods(
Object * object );
函式
獲取物件支援的觸發方法列表。
輸入
object -- 指向資料型別物件的指標
結果
指向以 STM_DONE 結尾的 DTMethod 列表的指標。此列表僅在物件被釋放之前有效。
示例
要呼叫特定方法,請執行以下操作
DoMethod(object, DTM_TRIGGER, myMethod);
備註
一些觸發方法需要一個引數(使用 NULL 引數呼叫這些方法是錯誤的)。使用 GetDTTriggerMethodDataFlags() 獲取請求引數的型別。
另請參閱 GetDTMethods()
LaunchToolA()
ULONG LaunchToolA(
struct Tool * tool,
STRPTR project,
struct TagItem * attrs );
ULONG LaunchTool(
struct Tool * tool,
STRPTR project,
TAG tag, ... );
函式
使用特定專案啟動應用程式。
輸入
tool -- 要使用的工具(可能為空,在這種情況下,此函式
returns 0)
project -- 要執行的專案的名稱或 NULL attrs -- 附加屬性
標籤
NP_Priority (BYTE) -- 啟動工具的優先順序(預設值為
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) -- 在啟動的應用程式程序之前不返回
finishes (defaults to FALSE).
結果
如果失敗則為零,否則為非零值。
另請參閱 NewDTObjectA()
LockDataType()
VOID LockDataType(
struct DataType * dt );
函式
鎖定從 ObtainDataTypeA() 獲取的 DataType 結構或資料型別物件(DTA_DataType)。
輸入
dt -- DataType 結構;可能為空
備註
對 LockDataType() 和 ObtainDataTypeA() 的呼叫必須有相應的 ReleaseDataType() 呼叫,否則會出現問題。
另請參閱 ObtainDataTypeA() ReleaseDataType()
NewDTObjectA()
Object * NewDTObjectA(
APTR name,
struct TagItem * attrs );
Object * NewDTObject(
APTR name,
TAG tag, ... );
函式
從 BOOPSI 類建立資料型別物件。
輸入
name -- 資料來源的名稱;通常是現有檔名 attrs -- 指向指定附加引數的 TagList 的指標
標籤
DTA_SourceType -- 源資料的型別(預設為 DTST_FILE)。
If the source is the clipboard the name field
contains the numeric clipboard unit.
DTA_Handle -- 可用於代替 'name' 欄位。如果
source is DTST_FILE, ths must be a valid FileHandle;
must be a valid IFFHandle if source is DTST_CLIPBOARD.
DTA_DataType -- 資料的類。資料是指向有效的
DataType; only used when creating a new object that
doens't have any source data.
DTA_GroupID -- 如果物件不是此型別,則使用 IoErr() 失敗
of ERROR_OBJECT_WRONG_TYPE.
GA_Left GA_RelRight GA_Top GA_RelBottom GA_Width GA_RelWidth GA_Height GA_RelHeight -- 指定物件相對於
window.
GA_ID -- 物件的 ID。
GA_UserData -- 物件的應用程式特定資料。
GA_Previous -- 列表中的上一個物件/工具。
結果
BOOPSI 物件。這可以在不同的上下文中使用,例如工具或影像。NULL 表示失敗 -- 在這種情況下,IoErr() 提供更多資訊
ERROR_REQUIRED_ARG_MISSING -- 未指定必需屬性。
ERROR_BAD_NUMBER -- 指定的組 ID 無效。
ERROR_OBJECT_WRONG_TYPE -- 物件資料型別與 DTA_GroupID 不匹配。
備註
此函式呼叫指定類的 OM_NEW 方法。
當不再需要時,應(最終)透過 DisposeDTObject() 釋放該物件。
另請參閱 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, ... );
函式
檢查 'handle' 指向的資料。
輸入
type -- 使用以下型別之一指定 'handle' 的流型別;
DTST_FILE - 'handle' is a BPTR lock
DTST_CLIPBOARD - 'handle' is a struct IFFHandle *
DTST_RAM - (v45) 'handle' is a STRPTR datatype-name
handle -- 要返回資料型別的控制代碼。 attrs -- 附加屬性。
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.
結果
指向 DataType 的指標,如果失敗則為 NULL。在後一種情況下,IoErr() 提供更多資訊
ERROR_NO_FREE_STORE -- 可用記憶體不足 ERROR_OBJECT_NOT_FOUND -- 無法開啟資料型別物件 ERROR_NOT_IMPLEMENTED -- 未知控制代碼型別
另請參閱 ReleaseDataType()
ObtainDTDrawInfoA()
APTR ObtainDTDrawInfoA(
Object * o,
struct TagItem * attrs );
APTR ObtainDTDrawInfo(
Object * o,
TAG tag, ... );
函式
準備一個數據型別物件以繪製到 RastPort 中;此函式將使用 opSet 訊息向該物件傳送 DTM_OBTAINDRAWINFO 方法。
輸入
o -- 指向要為其獲取 drawinfo 的資料型別物件的指標;
may be NULL in which case nothing is done
attrs -- 附加屬性
標籤
目前尚未定義。
結果
一個私有控制代碼,必須在應用程式完成繪製物件時傳遞給 ReleaseDTDrawInfo,或者在失敗時為 NULL。
另請參閱 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, ... );
函式
以非同步方式執行物件的 DTM_PRINT 方法。
輸入
object -- 指向資料型別物件的指標 window -- 指向物件已新增到其中的視窗的指標 requester -- 指向物件已新增到其中的請求者的指標
結果
成功時為 TRUE,否則為 FALSE。
備註
當應用程式呼叫 PrintDTObjectA() 時,它必須在接收到包含 DTA_PrinterStatus 標籤的 IDCMP_IDCMPUPDATE 之前不要觸碰 printerIO 聯合體。
To abort a print, send the DTM_ABORTPRINT method to the object.
這將使用 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, ... );
函式
重新整理指定物件,向物件傳送 GM_RENDER 訊息。
輸入
object -- 指向要重新整理的資料型別物件的指標;可以為 NULL window -- 指向視窗的指標;可以為 NULL req -- 必須為 NULL attrs -- 附加屬性(目前未定義)
另請參閱 AddDTObject() RemoveDTObject() intuition.library/RefreshGList()
ReleaseDataType()
VOID ReleaseDataType(
struct DataType * dt );
函式
釋放由 ObtainDataTypeA() 獲取的 DataType 結構。
輸入
dt -- 由 ObtainDataTypeA() 返回的 DataType 結構;NULL 是
a valid input.
另請參閱
ObtainDataTypeA() ReleaseDTDrawInfo() 概要
VOID ReleaseDTDrawInfo(
Object * o,
APTR handle );
函式
釋放從 ObtainDTDrawInfoA() 獲取的控制代碼;呼叫物件的 DTM_RELEASEDRAWINFO 方法,傳送 dtReleaseDrawInfo 訊息。
輸入
o -- 指向要釋放其 drawinfo 的資料型別物件的指標
release; may be NULL
handle -- 從 ObtainDTDrawInfoA() 獲取的控制代碼
結果
一個私有控制代碼,必須在應用程式完成繪製物件時傳遞給 ReleaseDTDrawInfo,或者在失敗時為 NULL。
另請參閱 DrawDTObjectA() ObtainDTDrawInfoA()
RemoveDTObject()
LONG RemoveDTObject(
struct Window * window,
Object * object );
函式
從指定視窗的物件列表中刪除一個物件;這將等待 AsyncLayout 程序準備就緒。該物件將收到型別為 DTM_REMOVEDTOBJECT 的訊息,作為已刪除的標誌。
輸入
window -- 指向相關視窗的指標 object -- 指向要刪除的物件的指標
結果
物件在從列表中刪除之前的位置;如果未找到該物件,則返回 -1。
另請參閱 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, ... );
函式
使用 DTM_WRITE 將物件的內容儲存到檔案。
輸入
o -- 要寫入檔案的 DataType 物件 win -- 物件附加到的視窗 req -- 物件附加到的請求者 file -- 要儲存物件的的檔名 mode -- 儲存模式(RAW、IFF 等),是 DTWM_ 識別符號之一 saveicon -- 是否應與檔案一起儲存圖示 attrs -- 附加屬性(這些屬性是特定於子類的)
結果
DTM_WRITE 的返回值。
備註
如果 DTM_WRITE 返回 0,則將刪除該檔案。
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, ... );
函式
設定資料型別物件的屬性。
輸入
o -- 指向要設定其屬性的資料型別物件的指標 win -- 物件已新增到其中的視窗 attrs -- 要設定的屬性(以 TAG_DONE 結束)
tags are specified in <datatypes/datatypesclass.h>
另請參閱 GetDTAttrsA() intuition.library/SetGadgetAttrsA() datatypes/datatypesclass.h
StartDragSelect()
ULONG StartDragSelect(
Object * o );
函式
由使用者啟動拖放選擇;只有當相關物件支援 DTM_SELECT、位於視窗或請求者中,並且沒有佈局程序正在處理該物件時,拖放選擇才會啟動。
輸入
o -- 相關的資料型別物件;可以為 NULL
結果
如果一切順利,則為 TRUE,否則為 FALSE。如果為 FALSE,則 IoErr() 提供更多資訊
ERROR_ACTION_NOT_KNOWN -- 該物件不支援 DTM_SELECT ERROR_OBJECT_IN_USE -- 該物件當前正在使用中
Picture.class 41.00
[edit | edit source]OM_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
[edit | edit source]OM_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
[edit | edit source]實現 animation.datatype(包括 boopsi 控制工具)。還必須提供一個子資料型別(即 avi、mpeg、divx 或任何其他可用的格式)以及一個基本的應用程式來演示 animation.datatype 的功能 -- 動畫相關的任何類的超類。
此類建立控制元件、縮放、重新對映和同步。
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, ... );
將資料型別物件繪製到 RastPort 中。在呼叫此函式之前,必須成功呼叫 ObtainDTDrawInfoA;它會呼叫物件的 DTM_DRAW 方法。
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 標籤用於 animationclass 物件(選擇要繪製的幀。
如果渲染成功,則為 TRUE,如果失敗,則為 FALSE。相關 RastPort 必須支援剪裁,即具有附加到它的有效圖層結構;否則,某些資料型別無法繪製,並且將返回 FALSE。
/*
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;
示例
[edit | edit source]#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);
}
這是 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 應用程式
[edit | edit source]#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;
}
聲音函式
[edit | edit source]void 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;
}
假設您正在嘗試操作影像?使用資料型別載入影像,但使用 ReadPixelArray 方法將影像資料讀取到 ARGB 陣列並處理源物件。對於影像,要獲取原始資料,請使用 PDTM_READPIXELARRAY(這是未壓縮的資料)。