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 替代品 [email protected] (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(这是未压缩的数据)。