跳转到内容

Aros/开发者/文档/库/数据类型

来自维基教科书,开放世界中的开放书籍
Aros 维基教科书的导航栏
Aros 用户
Aros 用户文档
Aros 用户常见问题解答
Aros 用户应用程序
Aros 用户 DOS Shell
Aros/用户/AmigaLegacy
Aros 开发文档
Aros 开发者文档
从 AmigaOS/SDL 移植软件
Zune 初学者指南
Zune .MUI 类
SDL 初学者指南
Aros 开发者构建系统
特定平台
Aros x86 完整系统 HCL
Aros x86 音频/视频支持
Aros x86 网络支持
Aros Intel AMD x86 安装
Aros 存储支持 IDE SATA 等
Aros Poseidon USB 支持
x86-64 支持
Motorola 68k Amiga 支持
Linux 和 FreeBSD 支持
Windows Mingw 和 MacOSX 支持
Android 支持
Arm Raspberry Pi 支持
PPC Power Architecture
杂项
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 格式中。这在内存方面并不有效,但使事情更简单、更快。这里可以做一些优化。

为新的图形数据类型创建了一个模板 这里


AmigaGuide

[编辑 | 编辑源代码]
    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(这是未压缩的数据)。

华夏公益教科书