跳轉到內容

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 替代品 sebauer@t-online.de (Sebastian Bauer)

AROS 之外的多數作業系統更喜歡 XML,但其他作業系統喜歡 doc、docx、ood、rtf 等。


最初,FTXT 被 AmigaOS 的剪貼簿用於剪下/複製功能,當前的應用程式僅使用原始 ASCII 資料。IFF FTXT 應該代表格式化的文字,但顯然支援的格式很少,這也會影響到可以放在剪貼簿上的內容(複製一個包含所有格式的表格並不容易)。


#include <graphics/text.h>
#include <graphics/rastport.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/classusr.h>

#ifndef LNF_MARKED
#define LNF_MARKED  (1<<15)
#endif


struct Text_Data
{
    LONG 	left, top;		/* Offsets of the gadget 			*/
    LONG 	width, height;		/* Dimensions of the gadget			*/
    LONG	fillpen, filltextpen;	/* pens for marking */

#ifndef COMPILE_DATATYPE
    struct Screen 	*screen;	/* Screen on which the gadget lies 		*/
    struct DrawInfo 	*drinfo;	/* Resulting from screen			*/

    struct RastPort 	*rp;
    APTR 	line_pool;
#else
    LONG 	update_type;
    LONG 	update_arg;
    LONG 	mouse_pressed;
    LONG	redraw;
#endif

    STRPTR 		title;
    UBYTE 		*buffer_allocated;
    ULONG 		buffer_allocated_len;
    struct List 	line_list;	/* double linked list of the lines		*/
    char *word_delim;
    LONG word_wrap;

    struct TextFont 	*font;
    struct TextAttr 	attr;

    LONG 	horiz_visible;
    LONG 	vert_visible;

    LONG 	vert_top;
    LONG 	horiz_top;

    LONG	horiz_unit;
    LONG	vert_unit;

    LONG 	vert_diff;		/* For optimized Scrolling			*/
    LONG 	use_vert_diff;
    LONG 	horiz_diff;
    LONG 	use_horiz_diff;

    LONG 	mark_x1;
    LONG 	mark_x2;
    LONG 	mark_y1;
    LONG 	mark_y2;
    struct Line *mark_line1;
    struct Line *mark_line2;
    LONG 	pressed;
    LONG 	copy_text;		/* if mb is released, copy the text into the clipboard */

    LONG 	doubleclick;		/* 1 if doubleclicked, 2 if trippleclicked 	*/
    LONG 	lastsecs;		/* For Doubleclick check			*/
    LONG 	lastmics;

    struct	TextExtent te;
    struct	RastPort font_rp;

    char	search_buffer[128];
    struct Process	*search_proc;	/* the search requester process */
    struct GadgetInfo	search_ginfo;	/* for the search process */
    int		search_line;
    int		search_pos;		/* x position */
    int		search_case;

#ifdef MORPHOS_AG_EXTENSION
    LONG        links;
    struct Line *marked_line;
    struct Line *selected_line;
    struct Line *last_marked_line;
    LONG        shinepen, shadowpen;
    BOOL        link_pressed;
    Object      *obj;
    UBYTE       word[128];     /* double clicked word */
    struct GadgetInfo *ginfo;
#endif
};


#ifdef __cplusplus

extern "C"
{
#endif

APTR Text_Create(void);
VOID Text_SetFrameBox( APTR mem, struct Screen *scr, struct RastPort *rp, LONG left, LONG top, LONG width, LONG height);
VOID Text_Load(APTR mem, STRPTR);
VOID Text_ChangeDimension( APTR mem, LONG left, LONG top, LONG width, LONG height);
VOID Text_Redraw( APTR mem );
VOID Text_Free(APTR mem);
ULONG Text_PageHeight( APTR mem );
ULONG Text_PageWidth( APTR mem );
ULONG Text_VisibleHeight( APTR mem );
ULONG Text_VisibleTop( APTR mem );
ULONG Text_VisibleHoriz( APTR mem );
VOID Text_SetVisibleTop( APTR mem, ULONG newy );
VOID Text_SetVisibleLeft( APTR mem, ULONG newx );
VOID Text_HandleMouse( APTR mem, LONG x, LONG y, LONG code, ULONG secs, ULONG mics);
VOID Text_Print( APTR mem );

#ifdef __cplusplus
}
#endif


AROS/workbench/classes/datatypes/picture/


/*
    Copyright (C) 1995-2020, The AROS Development Team. All rights reserved.
*/

#define	MIN(a,b) (((a) < (b)) ?	(a) : (b))
#define	MAX(a,b) (((a) > (b)) ?	(a) : (b))

#include <datatypes/pictureclass.h>
#include <graphics/gfx.h>

struct Picture_Data
{
    /*
     *	public entries,	accessible with	SET/GET
     */
    ULONG		  Precision;
    ULONG		  ModeID;
    struct BitMapHeader	  bmhd;
    struct BitMap	 *SrcBM; /* PDTA_BitMap	and PDTA_ClassBM */
    ULONG		  SrcColRegs[256 * 3]; /* PDTA_CRegs */
    struct BitMap	 *DestBM;
    UBYTE		 *MaskPlane;
    ULONG		  DestColRegs[256 * 3]; /* PDTA_GRegs */
    struct Screen	 *DestScreen;
    struct ColorRegister  ColMap[256];
    UBYTE		  ColTable[256];
    UWORD		  NumColors;
    UWORD		  NumPictures;
    UWORD		  WhichPicture;
    UWORD		  NumAlloc;
    UBYTE		  SparseTable[256];
    UWORD		  NumSparse;
    Point		  Grab;
    UWORD		  MaxDitherPens;
    UWORD		  DitherQuality;
    UWORD		  ScaleQuality;
    BOOL		  FreeSource;
    BOOL		  Remap;
    BOOL		  UseFriendBM;
    BOOL		  DestMode;
    BOOL		  DelayRead;
    BOOL		  DelayedRead;
    /*
     *	private	entries
     */
    UBYTE		  *SrcBuffer;
    ULONG		  SrcWidth;
    ULONG		  SrcWidthBytes;
    ULONG		  SrcHeight;
    LONG		  SrcPixelFormat;
    UWORD		  SrcPixelBytes;
    UWORD		  SrcDepth;
  
    ULONG		  DestWidth;
    ULONG		  DestHeight;
    ULONG		  ColTableXRGB[256];
    UWORD		  DestDepth;
  
    BOOL		  TrueColorSrc;
    BOOL		  TrueColorDest;
    BOOL		  Layouted;
    BOOL		  UseAsImage;
    BOOL		  KeepSrcBM;
    BOOL		  NoDelay;

    BOOL		  Scale;
    ULONG		  XScale;
    ULONG		  YScale;

    LONG		  ClickX;
    LONG		  ClickY;
    struct Screen         *RemapScreen;
};


The following items must be implemented:

library-framework               100% done
dispatcher-function             100% done

methods:                        
    OM_NEW			OK
    OM_DISPOSE			OK
    OM_UPDATE			part of OM_SET
    OM_SET			OK, see below
    OM_GET			OK, see below
    GM_RENDER                   OK
    GM_LAYOUT                   uses DTM_ASYNCLAYOUT
    GM_GOACTIVE                 superclass
    GM_HANDLEINPUT              superclass
    GM_HITTEST                  superclass
    DTM_PROCLAYOUT              uses DTM_ASYNCLAYOUT
    DTM_ASYNCLAYOUT             OK, improvements in speed and quality possible
    DTM_FRAMEBOX                superclass
    DTM_SELECT                  ?
    DTM_CLEARSELECTED           ?
    DTM_COPY                    missing
    DTM_PRINT                   missing
    DTM_WRITE                   missing
    PDTM_WRITEPIXELARRAY        OK
    PDTM_READPIXELARRAY         mostly done
    PDTM_SCALE                  in progress

The following attributes must be supported:
    OBP_Precision         (I)   OK
    DTA_Methods           (G)   OK
    PDTA_ModeID           (ISG) OK, but not used internally
    PDTA_BitMapHeader     (G)   OK
    PDTA_BitMap           (ISG) OK
    PDTA_DestBitMap       (G)   OK, with limitations
    PDTA_ClassBitMap      (ISG) OK, can't be used in parallel with PDTA_BitMap
    PDTA_Screen           (ISG) OK, alternate mapping dest ? (additional Get)
    PDTA_ColorRegisters   (G)   OK, but not used internally
    PDTA_CRegs            (G)   OK
    PDTA_GRegs            (G)   OK
    PDTA_ColorTable       (G)   OK ? private
    PDTA_ColorTable2      (G)   OK ? private
    PDTA_NumColors        (ISG) OK
    PDTA_NumAlloc         (G)   OK
    PDTA_Allocated        (G)   not implemented, obsolete (wasn't clearly defined)
    PDTA_SparseTable      (I)   OK
    PDTA_NumSparse        (I)   OK
    PDTA_Grab             (ISG) OK ?
    PDTA_FreeSourceBitMap (ISG) OK (additional Get)
    PDTA_Remap            (I)   OK, set get ?
    PDTA_UseFriendBitMap  (ISG) OK, but not used internally
    PDTA_SourceMode       (ISG) OK, but ignored internally
    PDTA_DestMode         (ISG) OK, but ignored internally
    PDTA_MaxDitherPens    (ISG) OK ?
    PDTA_DitherQuality    (ISG) OK ?
    PDTA_AllocatedPens    (G)   OK ?
    PDTA_ScaleQuality     (ISG) OK, but not used internally
    PDTA_DelayRead        (I)   OK ?
    PDTA_DelayedRead      (SG)  OK ? (Set only by subclass)


AROS/workbench/classes/datatypes/sound.datatype 基於 Stephan Rupprechts 來自 Aminet 的 sounddt 41

AROS 只有兩種聲音資料型別,分別是 Wave 資料型別和 8SVX 資料型別。8SVX 資料型別首先檢視 OM_NEW 和 Read8SVX。但 Read 函式不會測試 DTST_RAM 和空檔案控制代碼。

只有 8 位聲音,仍然需要 16 位和 32 位聲音。

#ifndef DATATYPES_SOUNDCLASS_H
#include <datatypes/soundclass.h>
#endif
#include <intuition/classes.h>
#include <exec/execbase.h>

/****************************************************************************/

struct ClassBase
{
	/* std library stuff */
	struct Library			LibNode;
 	UWORD				pad_word;
#ifndef __AROS__
 	BPTR				LibSegment;
        struct ExecBase			*cb_SysBase;
#endif
 	struct SignalSemaphore	cb_LibLock;
 	/* library bases */
#if !defined(__MAXON__) && !defined(__AROS__)
	struct Library			*cb_IntuitionBase;
	struct Library			*cb_GfxBase;
	struct Library			*cb_DOSBase;
	struct Library			*cb_UtilityBase;
	struct Library			*cb_DataTypesBase;
	struct Library			*cb_IFFParseBase;
	struct Library			*cb_TapeDeckBase;
#endif
	Class	      			*cb_Class;
	ULONG				*cb_Methods;
	/* prefs */
	BOOL				cb_AIFF;
	BOOL				cb_AHI;
	ULONG				cb_AHIModeID;
	ULONG				cb_AHIMixFrequency;
	UWORD				cb_NomWidth;
	UWORD				cb_NomHeight;
	ULONG				cb_WfCol[3];
	ULONG				cb_BgCol[3];
	BOOL				cb_Compress;
	BOOL				cb_ForceAHIMode;
	ULONG				cb_BufferSize;
	UWORD				cb_Volume;
	BOOL				cb_ControlPanel;
	BOOL				cb_NoGTSlider;
};

/****************************************************************************/

struct InstanceData
{
	struct ClassBase	*ClassBase;
	struct SignalSemaphore	 Lock; 
	/* v39 tags */
	struct VoiceHeader  VoiceHeader;
	BYTE			*Sample;
	ULONG			 SampleLength;
	UWORD			 Frequency;
	UWORD			 Volume;
	UWORD			 Cycles;
	/* v40 tags */
	UWORD			 Continuous;
	struct Task		*SignalTask;
	BYTE			 SignalBit;
	/* v41 tags */
	UBYTE			 SampleType;
	ULONG			 Panning;
	/* v44 tags */
	struct timeval	 ReplayPeriod;
	BOOL			 LeftSample; // SDTA_Sample is SDTA_LeftSample?
	UWORD			 pad_word2;
	BYTE			*RightSample;
	BOOL			 SyncSampleChange;
	BOOL			 FreeSampleData;
	/* additional tags */
	BOOL			Immediate;
	BOOL			Repeat;
	BOOL			DelayedImmed;
	/* offset */
	ULONG			StartSample;
	ULONG			EndSample;
	/* private data */
	struct Process	*PlayerProc;
	struct MsgPort	*PlayerPort;
	/* for STM_STOP (doubleclick) */
	struct timeval		LastClick;
	/* DTM_SELECT */
	WORD			MinX;
	WORD			MaxX;
	BOOL			MarkMode;
	/* controlpanel */
	WORD			pad_word;
	WORD			TapeDeckHeight;
	BOOL			ControlPanel;
	struct Gadget		*TapeDeckGadget;
	struct Gadget		*VolumeSlider;
	struct Gadget		*ActiveMember;

	struct Screen		*Screen;	// DTM_DRAW
	struct DrawInfo	*DrawInfo;	// DTM_DRAW
	struct Window	*Window;
	struct Requester	*Requester;
	struct Gadget		*Gadget;

	struct ColorMap	*ColorMap;		// Needed to release allocated pens, GInfo of DTM_REMOVEDTOBJECT == NULL	
	WORD			WaveformPen;	// Drawing pens
	WORD			BackgroundPen;

	BOOL			ForceRefresh;	// bugfix (?) for gmv
};

/****************************************************************************/

struct ObjectMsg {
	struct Message	Message;
	ULONG			Command;
	APTR			Data;
//	ULONG			ErrorCode;
};

enum {
	COMMAND_INIT,
	COMMAND_EXIT,
	COMMAND_PLAY,
	COMMAND_STOP,
	COMMAND_PAUSE,
	COMMAND_PERVOL,
	COMMAND_NEXT_BUFFER
};

/****************************************************************************/



/*
    Copyright � 2015-2020, The AROS Development	Team. All rights reserved.
    $Id$
*/

#include <graphics/gfx.h>
#include <datatypes/pictureclass.h>
#include <datatypes/animationclass.h>
#include <datatypes/animationclassext.h>

#define	MIN(a,b) (((a) < (b)) ?	(a) : (b))
#define	MAX(a,b) (((a) > (b)) ?	(a) : (b))

/*
    api flags
 */
#define	ANIMDF_CONTROLPANEL     (1 << 0)
#define	ANIMDF_IMMEDIATE        (1 << 1)
#define	ANIMDF_REPEAT           (1 << 2)
#define	ANIMDF_REMAP            (1 << 3)
#define	ANIMDF_ADJUSTPALETTE    (1 << 4)
#define	ANIMDF_ADAPTFPS         (1 << 5)
#define	ANIMDF_FRAMESKIP        (1 << 6)
#define	ANIMDF_SMARTSKIP        (1 << 7)

/*
    special flags used by rendering/layout code
 */
#define ANIMDF_LAYOUT           (1 << 29)               
#define ANIMDF_REMAPPEDPENS     (1 << 30)               
#define ANIMDF_SHOWPANEL        (1 << 31)

#define ANIMPLAYER_TICKFREQ     ((struct RealTimeBase *)RealTimeBase)->rtb_Reserved1

struct ProcessPrivate;
struct Animation_Data;
struct AnimFrame;
BOOL ProcEnabled(struct ProcessPrivate *, volatile ULONG *, ULONG);
void cacheFrame(struct Animation_Data *, struct AnimFrame *);
void freeFrame(struct Animation_Data *, struct AnimFrame *);

struct AnimColor_Data
{
    struct SignalSemaphore      acd_PenLock;
    struct ColorMap             *acd_ColorMap;
    struct ColorRegister        *acd_ColorRegs;
    ULONG			*acd_CRegs;
    ULONG                       *acd_GRegs;

    UWORD                       acd_NumColors;
    UWORD                       acd_NumAlloc;

    UBYTE			*acd_ColorTable[2];
    UBYTE			*acd_Allocated;          /* pens we have actually allocated      */
    ULONG                       acd_PenPrecison;         /* precision to use allocating pens     */
};

struct AnimFrame_Data
{
    struct SignalSemaphore      afd_AnimFramesLock;
    struct List                 afd_AnimFrames;

    UWORD                       afd_Frames;              /* # of frames                          */
    UWORD                       afd_FrameCurrent;        /* # of current frame                   */
    UWORD                       afd_FramesStep;          /* how much to skip back/fwd            */
};

struct AnimTimer_Data
{
    UWORD                       atd_FramesPerSec;        /* Playback rate                        */
    UWORD                       atd_TicksPerFrame;       /* realtime.libraries tick frequency /
                                                           ad_FramesPerSec */
    UWORD                       atd_Tick;
};

/* our nodes used to play the anim! */
struct AnimFrame
{
    struct Node                 af_Node;
#define af_CacheBM af_Node.ln_Name
    ULONG                       af_Flags;
    struct adtNewFormatFrame    af_Frame;
};

#define AFFLAGB_READY      0
#define AFFLAGF_READY      (1 << 0)

/* for sanity, we embed the frame number in the ln_type/ln_pri fields */
static inline UWORD GetNODEID(struct AnimFrame *node) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    return *id_ptr;
}

static inline void SetNODEID(struct AnimFrame *node, UWORD id) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    *id_ptr = id;
}

struct Animation_Data
{
    ULONG                       ad_Flags;               /* object control flags                 */
    char                        *ad_BaseName;

    struct Window               *ad_Window;

    struct AnimFrame_Data       ad_FrameData;
    struct AnimTimer_Data       ad_TimerData;

    struct BitMap               *ad_FrameBM;        /* currently displayed frame            */
    struct BitMap               *ad_CacheBM;        /* .. */
    struct AnimFrame            *ad_KeyFrame;       /* animations key (first) frame         */

    UWORD                       ad_VertTop;             /* Y offset of visible rectangle        */
    UWORD                       ad_VertTotal;           
    UWORD                       ad_VertVis;
    UWORD                       ad_HorizTop;            /* X offset of visible rectangle        */
    UWORD                       ad_HorizTotal;
    UWORD                       ad_HorizVis;

    UWORD                       ad_RenderLeft;
    UWORD                       ad_RenderTop;
    UWORD                       ad_RenderWidth;
    UWORD                       ad_RenderHeight;

    IPTR                        ad_ModeID;
    struct BitMapHeader         ad_BitMapHeader;        /* objects embedded bitmap header       */

    struct AnimColor_Data       ad_ColorData;

    IPTR                        ad_ProcStack;
    struct ProcessPrivate       *ad_ProcessData;
    struct Process              *ad_BufferProc;         /* buffering process */
    struct Process              *ad_PlayerProc;         /* playback process */
    struct Player               *ad_Player;
    struct Hook                 ad_PlayerHook;

    struct Gadget               *ad_Tapedeck;
    ULONG                       ad_BufferTime;         /* (prefs) how many seconds to buffer  */
    ULONG                       ad_BufferStep;         /* (prefs) no of frames to try to load in one go */
    UBYTE                       ad_PlayerSourceLastState;
};

struct ProcessPrivate
{
    Object                      *pp_Object;
    struct Animation_Data       *pp_Data;
    char                        *pp_PlayBackName;
    char                        *pp_BufferingName;
    volatile ULONG              pp_PlayerFlags;
    volatile ULONG              pp_BufferFlags;
    ULONG                       pp_BufferFrames;       /* no of frames to buffer in total       */
    ULONG                       pp_BufferLevel;        /* no of frames buffered                 */
    IPTR                        pp_BufferSpecific;     /* specific frame to load                */
    struct AnimFrame            *pp_BufferFirst;       /* starting point to load from           */
    struct AnimFrame            *pp_PlaybackFrame;

    ULONG                       pp_BufferSigMask;
    BYTE                       pp_BufferEnable;
    BYTE                       pp_BufferDisable;
    BYTE                       pp_BufferFill;
    BYTE                       pp_BufferPurge;

    ULONG                       pp_PlaybackSigMask;
    BYTE                       pp_PlaybackEnable;
    BYTE                       pp_PlaybackDisable;
    BYTE                       pp_PlaybackTick;          /* signal frames needs to change      */
    BYTE                       pp_PlaybackSync;          /* signal position changed            */
};

#define PRIVPROCF_ENABLED       (1 << 0)
#define PRIVPROCF_RUNNING       (1 << 1)
#define PRIVPROCF_ACTIVE        (1 << 2)
#define PRIVPROCF_BUSY          (1 << 3)

#define TAG_PRIVATE             	(ADTA_Dummy + 100)
#define PRIVATE_INITPLAYER              (TAG_PRIVATE - 1)
#define PRIVATE_ALLOCCOLORTABLES        (TAG_PRIVATE - 2)
#define PRIVATE_MAPFRAMEPENS            (TAG_PRIVATE - 3)     
#define PRIVATE_FREECOLORTABLES         (TAG_PRIVATE - 4) 
#define PRIVATE_FREEPENS                (TAG_PRIVATE - 5)             
#define PRIVATE_ALLOCBUFFER             (TAG_PRIVATE - 6)
#define PRIVATE_RENDERFRAME             (TAG_PRIVATE - 7)
#define PRIVATE_REMAPFRAME              (TAG_PRIVATE - 8)

struct privAllocColorTables
{
    STACKED ULONG MethodID;
    STACKED ULONG NumColors;
};

struct privMapFramePens
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
};

struct privAllocBuffer
{
    STACKED ULONG MethodID;
    STACKED struct BitMap *Friend;
    STACKED UBYTE Depth;
};

struct privRenderFrame
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
    STACKED struct BitMap *Target;
};

#if DEBUG > 0
#define DFRAMES(...) bug(__VA_ARGS__);
#else
#define DFRAMES(...)
#endif




建立新的資料型別

[編輯 | 編輯原始碼]

其他文字子類是



原始規範提供了一些對 FTXT 的支援,FTXT 是 IFF 的“資料部分”或“FORM 型別”。文字儲存在一個或多個 FTXT 內部的“CHRS”塊中。每個 CHRS 包含一個與 ANSI/ISO 標準相容的 8 位文字流

  • 在 NUL(十六進位制 00)到十六進位制 1F 範圍內的 C0 終端控制字元。只有 LF(十六進位制 0A)和 ESC(十六進位制 1B)是重要的。ESC 啟動一個控制序列。LF 是行終止符,CR(十六進位制 0D)不被識別為終止符。
  • 在十六進位制 20 到十六進位制 7F 範圍內的 G0 圖形字元。SP(十六進位制 20)是空格字元。DEL(十六進位制 7F)是刪除字元,不使用。其餘的是標準 ASCII 可列印字元“!”(十六進位制 21)到“~”(十六進位制 7E)。
  • 在十六進位制 80 到十六進位制 9F 範圍內的 C1 擴充套件控制字元。以 CSI(十六進位制 9B)開頭的控制序列用於 FTXT 格式化。所有其他控制序列和 C1 控制字元均未使用。
  • G1 是在 NBSP(十六進位制 A0)到“y”(十六進位制 FF)範圍內的擴充套件圖形字元組。

可選的“FONS”儲存一個 FontSpecifier,如下所示。它將字型分配給一個編號的暫存器,以便可以在其他 CHRS 塊中按編號引用它。CHRS 文字使用字型 1,直到選擇另一個字型。如果字型 1 未指定,則使用選定的系統字型作為字型 1。SGR 序列具有引數 10-19,用於從十個預定義字型中選擇,這意味著 IFF FTXT 檔案中只有十個 FONS 塊有意義。

如果應用程式程式設計師開始使用符合 FTXT 規範的格式化文字,其他程式設計師將不再假設剪貼簿只包含純文字資料。因此,他們需要在剪貼簿處理例程中實現適當的控制程式碼剝離(同樣,根據 FTXT 規範)。

typedef struct {
  UBYTE id;     /* 0 through 9 is a font id number referenced by an SGR
                   control sequence selective parameter of 10 through 19.
                   Other values are reserved for future standardization. */
  UBYTE pad1;   /* reserved for future use; store 0 here                 */
  UBYTE proportional; /* proportional font-- 0=unknown, 1=no, 2=yes      */
  UBYTE serif;  /* serif font-- 0 = unknown, 1 = no, 2 = yes             */
  char  name[]; /* A NUL-terminated string naming the preferred font.    */
  } FontSpecifier;


其他可以儲存多個影像的影像檔案資料型別,例如 INFO、ICO、ICNS 等,為 AROS 圖片資料型別添加了“WhichPicture”和“GetNumPictures”PDTA 方法。我們可以使用圖片資料型別顯示多個影像!

新增一個函式來計算影像目錄(IFD)以獲取 GetNumPictures 會很容易。

TIFF 資料型別可以使用 PDTA_GetNumPictures 計數目錄,並且可以使用 PDTA_WhichPicture 設定當前目錄。所以現在它可以顯示多個影像了。




/*
    Copyright © 1995-2005, The AROS Development Team. All rights reserved.
    $Id: bmpclass.c 30902 2009-03-14 13:38:20Z mazze $
*/

/**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <cybergraphx/cybergraphics.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>

#include <aros/symbolsets.h>

#include "debug.h"

#include "methods.h"

/* Open superclass */
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);

/**************************************************************************************************/

#define FILEBUFSIZE 65536
#define MAXCOLORS   256

typedef struct {
    struct IFFHandle    *filehandle;

    UBYTE               *filebuf;
    UBYTE               *filebufpos;
    long                filebufbytes;
    long                filebufsize;
    UBYTE               *linebuf;
    UBYTE               *linebufpos;
    long                linebufbytes;
    long                linebufsize;
    
    APTR                codecvars;
} BmpHandleType;

typedef struct
{
    WORD        bfType;             //  0 ASCII "BM"
    ULONG       bfSize;             //  2 Size in bytes of the file
    WORD        bfReserved1;        //  6 Zero
    WORD        bfReserved2;        //  8 Zero
    ULONG       bfOffBits;          // 10 Byte offset in files where image begins
} FileBitMapHeader __attribute__((packed));    // 14

typedef struct
{
    ULONG       biSize;             //  0 Size of this header, 40 bytes
    LONG        biWidth;            //  4 Image width in pixels
    LONG        biHeight;           //  8 Image height in pixels
    WORD        biPlanes;           // 12 Number of image planes, must be 1
    WORD        biBitCount;         // 14 Bits per pixel, 1, 4, 8, 24, or 32
    ULONG       biCompression;      // 16 Compression type, below
    ULONG       biSizeImage;        // 20 Size in bytes of compressed image, or zero
    LONG        biXPelsPerMeter;    // 24 Horizontal resolution, in pixels/meter
    LONG        biYPelsPerMeter;    // 28 Vertical resolution, in pixels/meter
    ULONG       biClrUsed;          // 32 Number of colors used, below
    ULONG       biClrImportant;     // 36 Number of "important" colors
} BitmapInfoHeader __attribute__((packed));    // 40

/* "BM" backwards, due to LE byte order */
#define BITMAP_ID "MB"

/**************************************************************************************************/

static void BMP_Exit(BmpHandleType *bmphandle, LONG errorcode)
{
    D(if (errorcode) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode));
    if (bmphandle->filebuf)
    {
	FreeMem(bmphandle->filebuf, bmphandle->filebufsize);
    }
    if (bmphandle->linebuf)
    {
	FreeMem(bmphandle->linebuf, bmphandle->linebufsize);
    }
    if (bmphandle->codecvars)
    {
	FreeVec(bmphandle->codecvars);
    }
    SetIoErr(errorcode);
}

/**************************************************************************************************/

/* buffered file access, useful for RLE */
BOOL SaveBMP_EmptyBuf(BmpHandleType *bmphandle, long minbytes)
{
    long                bytes, bytestowrite;
    
    bytestowrite = bmphandle->filebufsize - (bmphandle->filebufbytes + minbytes);
    D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes, (long)bytestowrite));
    bytes = Write(bmphandle->filehandle, bmphandle->filebuf, bytestowrite);
    if ( bytes < bytestowrite )
    {
	D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes));
	return FALSE;
    }
    bmphandle->filebufpos = bmphandle->filebuf;
    bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
    D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
    return TRUE;
}

/* buffered file access, useful for RLE */
BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
{
    long                i, bytes;
    
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    if ( bmphandle->filebufbytes >= 0 )
	return TRUE;
    bytes = bmphandle->filebufbytes + minbytes;
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
    if (bytes > 0)
    {
	//D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
	for (i=0; i<bytes; i++)     /* copy existing bytes to start of buffer */
	    bmphandle->filebuf[i] = bmphandle->filebufpos[i];
    }
    bmphandle->filebufpos = bmphandle->filebuf;
    bytes = Read(bmphandle->filehandle, bmphandle->filebuf + bytes, bmphandle->filebufsize - bytes);
    if (bytes < 0 ) bytes = 0;
    bmphandle->filebufbytes += bytes;
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- >minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    if (bmphandle->filebufbytes >= 0)
	return TRUE;
    return FALSE;
}

static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
			    struct ColorRegister *colormap, ULONG *colregs)
{
    unsigned int        i, j;

    if (numcolors && numcolors <= MAXCOLORS)
    {
	j = 0;
	for (i = 0; i < numcolors; i++)
	{
	    if ( (bmphandle->filebufbytes -= 4) < 0 && !LoadBMP_FillBuf(bmphandle, 4) )
	    {
		D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
		return FALSE;
	    }
	    /* BGR0 format for MS Win files, BGR format for OS/2 files */
	    colormap[i].blue = *(bmphandle->filebufpos)++;
	    colormap[i].green = *(bmphandle->filebufpos)++;
	    colormap[i].red = *(bmphandle->filebufpos)++;
	    bmphandle->filebufpos++;
	    colregs[j++] = ((ULONG)colormap[i].red)<<24;
	    colregs[j++] = ((ULONG)colormap[i].green)<<24;
	    colregs[j++] = ((ULONG)colormap[i].blue)<<24;
	    // D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
	}
	D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors));
    }
    return TRUE;
}

/**************************************************************************************************/
static BOOL LoadBMP(struct IClass *cl, Object *o)
{
    BmpHandleType           *bmphandle;
    UBYTE                   *filebuf;
    IPTR                    sourcetype;
    ULONG                   bfSize, bfOffBits;
    ULONG                   biSize, biWidth, biHeight, biCompression;
    ULONG                   biClrUsed, biClrImportant;
    UWORD                   biPlanes, biBitCount;
    ULONG                   alignwidth, alignbytes, pixelfmt;
    long                    x, y;
    int                     cont, byte;
    struct BitMapHeader     *bmhd;
    struct ColorRegister    *colormap;
    ULONG                   *colorregs;
    STRPTR                  name;

    D(bug("bmp.datatype/LoadBMP()\n"));

    if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    bmphandle->filebuf = NULL;
    bmphandle->linebuf = NULL;
    bmphandle->codecvars = NULL;
    
    
    if( GetDTAttrs(o,   DTA_SourceType    , (IPTR)&sourcetype ,
			DTA_Handle        , (IPTR)&(bmphandle->filehandle),
			PDTA_BitMapHeader , (IPTR)&bmhd,
			TAG_DONE) != 3 )
    {
	BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
    
    if ( sourcetype == DTST_RAM && bmphandle->filehandle == NULL && bmhd )
    {
	D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
	BMP_Exit(bmphandle, 0);
	return TRUE;
    }
    if ( sourcetype != DTST_FILE || !bmphandle->filehandle || !bmhd )
    {
	D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
	BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }
    
    /* initialize buffered file reads */
    bmphandle->filebufbytes = 0;
    bmphandle->filebufsize = FILEBUFSIZE;
    if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    /* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 14) < 0 && !LoadBMP_FillBuf(bmphandle, 14) )
    {
	D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 14;
    if( filebuf[0] != 'B' && filebuf[1] != 'M' )
    {
	D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    /* byte-wise access isn't elegant, but it is endianess-safe */
    bfSize = (filebuf[5]<<24) | (filebuf[4]<<16) | (filebuf[3]<<8) | filebuf[2];
    bfOffBits = (filebuf[13]<<24) | (filebuf[12]<<16) | (filebuf[11]<<8) | filebuf[10];
    D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize, bfOffBits));

    /* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 40) < 0 && !LoadBMP_FillBuf(bmphandle, 40) )
    {
	D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 40;

    /* get image size attributes */
    biSize = (filebuf[3]<<24) | (filebuf[2]<<16) | (filebuf[1]<<8) | filebuf[0];
    biWidth = (filebuf[7]<<24) | (filebuf[6]<<16) | (filebuf[5]<<8) | filebuf[4];
    biHeight = (filebuf[11]<<24) | (filebuf[10]<<16) | (filebuf[9]<<8) | filebuf[8];
    biPlanes = (filebuf[13]<<8) | filebuf[12];
    biBitCount = (filebuf[15]<<8) | filebuf[14];
    biCompression = (filebuf[19]<<24) | (filebuf[18]<<16) | (filebuf[17]<<8) | filebuf[16];
    biClrUsed = (filebuf[35]<<24) | (filebuf[34]<<16) | (filebuf[33]<<8) | filebuf[32];
    biClrImportant = (filebuf[39]<<24) | (filebuf[38]<<16) | (filebuf[37]<<8) | filebuf[36];
    D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
	  biWidth, biHeight, (long)biBitCount, biClrUsed, biClrImportant, biCompression, biSize));
    if (biSize != 40 || biPlanes != 1 || biCompression != 0)
    {
	D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
	BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }

    /* check color mode */
    pixelfmt = PBPAFMT_LUT8;
    switch (biBitCount)
    {
	case 1:
	    alignwidth = (biWidth + 31) & ~31UL;
	    alignbytes = alignwidth / 8;
	    break;
	case 4:
	    alignwidth = (biWidth + 7) & ~7UL;
	    alignbytes = alignwidth / 2;
	    break;
	case 8:
	    alignwidth = (biWidth + 3) & ~3UL;
	    alignbytes = alignwidth;
	    break;
	case 24:
	    alignbytes = (biWidth + 3) & ~3UL;
	    alignwidth = alignbytes * 3;
	    pixelfmt = PBPAFMT_RGB;
	    break;
	default:
	    D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
	    BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	    return FALSE;
    }
    D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));

    /* set BitMapHeader with image size */
    bmhd->bmh_Width  = bmhd->bmh_PageWidth  = biWidth;
    bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
    bmhd->bmh_Depth  = biBitCount;

    /* get empty colormap, then fill in colormap to use*/
    if (biBitCount != 24)
    {
	if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
			    PDTA_CRegs, (IPTR)&colorregs,
			    TAG_DONE ) == 2) ||
	    !(colormap && colorregs) )
	{
	    D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
	if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
	{
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
    }
    }
    /* skip offset */
    bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
    D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
    if ( bfOffBits < 0 ||
	( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
    {
	D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    bmphandle->filebufpos += bfOffBits;

    /* Pass attributes to picture.datatype */
    GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
    SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
			      DTA_NominalHoriz, biWidth,
			      DTA_NominalVert , biHeight,
			      DTA_ObjName     , (IPTR)name,
			      TAG_DONE);

    /* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
    bmphandle->linebufsize = bmphandle->linebufbytes = alignwidth;
    if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    cont = 1;
    for (y=biHeight-1; y>=0 && cont; y--)
    {
	int r, g, b;
	
	bmphandle->linebufpos = bmphandle->linebuf;
	if (biBitCount == 24)
	{
	    if ( (bmphandle->filebufbytes -= alignwidth) < 0 && !LoadBMP_FillBuf(bmphandle, alignwidth) )
	    {
		D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
		//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
		//return FALSE;
		cont = 0;
	    }
	    for (x=0; x<alignbytes; x++)
	    {
		b = *(bmphandle->filebufpos)++;
		g = *(bmphandle->filebufpos)++;
		r = *(bmphandle->filebufpos)++;
		*(bmphandle->linebufpos)++ = r;
		*(bmphandle->linebufpos)++ = g;
		*(bmphandle->linebufpos)++ = b;
	    }
	}
	else
	{
	    for (x=0; x<alignbytes; x++)
	    {
		if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
		{
		    D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
		    //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
		    //return FALSE;
		    cont = 0;
		    break;              
		}
		byte = *(bmphandle->filebufpos)++;
		switch (biBitCount)
		{
		    case 1:
			for (b=0; b<8; b++)
			{
			    *(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
			    byte <<= 1;
			}
			break;
		    case 4:
			*(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
			*(bmphandle->linebufpos)++ = (byte & 0x0f);
			break;
		    case 8:
			*(bmphandle->linebufpos)++ = byte;
			break;
		    case 24:
			*(bmphandle->linebufpos)++ = byte;
			break;
		}
	    }
	}
	if
	(
	    !DoSuperMethod(cl, o,
			   PDTM_WRITEPIXELARRAY,	/* Method_ID */
			   (IPTR)bmphandle->linebuf,	/* PixelData */
			   pixelfmt,			/* PixelFormat */
			   alignwidth,			/* PixelArrayMod (number of bytes per row) */
			   0,				/* Left edge */
			   y,				/* Top edge */
			   biWidth,			/* Width */
			   1				/* Height (here: one line) */
	    )
	)
	{
	    D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
    }
    //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));

    D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
    BMP_Exit(bmphandle, 0);
    return TRUE;
}

/**************************************************************************************************/

static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
    BmpHandleType           *bmphandle;
    UBYTE                   *filebuf;
    unsigned int            width, height, widthxheight, numplanes, numcolors;
    struct BitMapHeader     *bmhd;
    struct BitMap           *bm;
    struct RastPort         rp;
    long                    *colorregs;
    int                     i, j, ret;

    D(bug("bmp.datatype/SaveBMP()\n"));

    if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    bmphandle->filebuf = NULL;
    bmphandle->linebuf = NULL;
    bmphandle->codecvars = NULL;

    /* A NULL file handle is a NOP */
    if( !dtw->dtw_FileHandle )
    {
	D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
	BMP_Exit(bmphandle, 0);
	return TRUE;
    }
    bmphandle->filehandle = dtw->dtw_FileHandle;

    /* Get BitMap and color palette */
    if( GetDTAttrs( o,  PDTA_BitMapHeader, (IPTR)&bmhd,
			PDTA_BitMap,       (IPTR)&bm,
			PDTA_CRegs,        (IPTR)&colorregs,
			PDTA_NumColors,    (IPTR)&numcolors,
			TAG_DONE ) != 4UL ||
	!bmhd || !bm || !colorregs || !numcolors)
    {
	D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
#if 0
    /* Check if this is a standard BitMap */
    if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
    {
	D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
#endif
    /* initialize buffered file reads */
    bmphandle->filebufsize = FILEBUFSIZE;
    bmphandle->filebufbytes = bmphandle->filebufsize;
    if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    /* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
    {
	D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 13;

    /* set screen descriptor attributes (from BitMapHeader) */
    width = bmhd->bmh_PageWidth;
    height = bmhd->bmh_PageHeight;
    numplanes = bmhd->bmh_Depth - 1;
    numcolors = 1 << (numplanes + 1);
    D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
    filebuf[6] = width & 0xff;
    filebuf[7] = width >> 8;
    filebuf[8] = height & 0xff;
    filebuf[9] = height >> 8;
    filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
    filebuf[11] = 0;    /* this is fillcolor */
    filebuf[12] = 0;    /* this is pixel aspect ratio, 0 means unused */

    /* write screen colormap, we don't use an image colormap */
    for (i = 0; i < numcolors*3; i += 3)
    {
	if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
	{
	    BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	    return FALSE;
	}
	*(bmphandle->filebufpos)++ = colorregs[i] >> 24;
	*(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
	*(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
    }

    /* write image header, image has same size as screen */
    if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 10;
    filebuf[0] = ',';       /* header ID */
    filebuf[1] = filebuf[2] = 0;    /* no left edge */
    filebuf[3] = filebuf[4] = 0;    /* no top edge */
    filebuf[5] = width & 0xff;
    filebuf[6] = width >> 8;
    filebuf[7] = height & 0xff;
    filebuf[8] = height >> 8;
    filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */

    /* Now read the picture data from the bitplanes and write it to a chunky buffer */
    /* For now, we use a full picture pixel buffer, not a single line */
    widthxheight = width*height;
    bmphandle->linebufsize = bmphandle->linebufbytes = widthxheight;
    if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    InitRastPort(&rp);
    rp.BitMap=bm;
    for (j=0; j<height; j++)
    {
	for (i=0; i<width; i++)
	{
	    ret = (UBYTE)ReadPixel(&rp, i, j);  /* very slow, to be changed */
	    *(bmphandle->linebufpos)++ = ret;
	}
    }
    bmphandle->linebufpos = bmphandle->linebuf;

    /* write the chunky buffer to file, after encoding */
    
    /* write end-of-BMP marker */
    if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    *(bmphandle->filebufpos)++ = ';';

    /* flush write buffer to file and exit */
    SaveBMP_EmptyBuf(bmphandle, 0);
    D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
    BMP_Exit(bmphandle, 0);
    return TRUE;
}

/**************************************************************************************************/

IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
{
    Object *newobj;
    
    D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
    
    newobj = (Object *)DoSuperMethodA(cl, o, msg);
    if (newobj)
    {
	if (!LoadBMP(cl, newobj))
	{
	    CoerceMethod(cl, newobj, OM_DISPOSE);
	    newobj = NULL;
	}
    }

    return (IPTR)newobj;
}

/**************************************************************************************************/

IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
{
    D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
    if( (dtw -> dtw_Mode) == DTWM_RAW )
    {
	/* Local data format requested */
	return SaveBMP(cl, o, dtw );
    }
    else
    {
	/* Pass msg to superclass (which writes an IFF ILBM picture)... */
	return DoSuperMethodA( cl, o, (Msg)dtw );
    }
}




/*
    Copyright © 1995-2001, The AROS Development Team. All rights reserved.
    $Id: ppmclass.c 30902 2009-03-14 13:38:20Z mazze $
*/

/**********************************************************************/

#define DEBUGMETHODS 0

/**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>

#include <aros/symbolsets.h>

ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);

#include "debug.h"

#include "methods.h"

/**************************************************************************************************/

IPTR PPM__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{
 IPTR RetVal;
 char *Title;
 IPTR sourcetype;
 BPTR FileHandle;
 struct BitMapHeader *bmhd;
 char LineBuffer[128];
 long Width, Height, NumChars;
 unsigned int i;
 unsigned char *RGBBuffer;

 D(bug("ppm.datatype/OM_NEW: Entering\n"));

 D(bug("ppm.datatype/OM_NEW: cl: 0x%lx o: 0x%lx msg: 0x%lx\n", (unsigned long) cl, (unsigned long) o, (unsigned long) msg));

 RetVal=DoSuperMethodA(cl, o, (Msg) msg);
 if(!RetVal)
 {
  D(bug("ppm.datatype/OM_NEW: DoSuperMethod failed\n"));
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: DoSuperMethod: 0x%lx\n", (unsigned long) RetVal));

    if( GetDTAttrs((Object *) RetVal,
			DTA_SourceType    , (IPTR)&sourcetype ,
			DTA_Handle        , (IPTR)&FileHandle,
			DTA_Name          , (IPTR)&Title,
			PDTA_BitMapHeader , (IPTR)&bmhd,
			TAG_DONE) != 4 )
    {
        D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) error !\n"));
	CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
	SetIoErr(ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
    D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) successful\n"));
    
    if ( sourcetype == DTST_RAM && FileHandle == NULL )
    {
	D(bug("ppm.datatype/OM_NEW: Creating an empty object\n"));
	return TRUE;
    }
    if ( sourcetype != DTST_FILE || !FileHandle || !bmhd )
    {
	D(bug("ppm.datatype/OM_NEW: Unsupported sourcetype mode\n"));
	SetIoErr(ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }

 D(bug("ppm.datatype/OM_NEW: Title: %s\n", Title?Title:"[none]"));

 Seek(FileHandle, 0, OFFSET_BEGINNING);
 D(bug("ppm.datatype/OM_NEW: Seek successful\n"));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 1 failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(!(LineBuffer[0]=='P' && LineBuffer[1]=='6'))
 {
  D(bug("ppm.datatype/OM_NEW: Not a P6 PPM\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: It's a P6 PPM\n"));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 2 failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(LineBuffer[0]=='#')
 {
  D(bug("ppm.datatype/OM_NEW: Line 2 is a comment\n"));

  if(!FGets(FileHandle, LineBuffer, 128))
  {
   D(bug("ppm.datatype/OM_NEW: FGets line 3 after comment failed\n"));

   SetIoErr(ERROR_OBJECT_WRONG_TYPE);
   CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
   return(0);
  }
 }

 NumChars=StrToLong(LineBuffer, (LONG *)&Width);

 if(!((NumChars>0) && (Width>0)))
 {
  D(bug("ppm.datatype/OM_NEW: StrToLong(Width) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Width: %ld\n", (long) Width));
 D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));

 NumChars=StrToLong(LineBuffer+NumChars, (LONG *)&Height);

 if(!((NumChars>0) && (Height>0)))
 {
  D(bug("ppm.datatype/OM_NEW: StrToLong(Height) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Height: %ld\n", (long) Height));
 D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 3 (4) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(!(LineBuffer[0]=='2' && LineBuffer[1]=='5' && LineBuffer[2]=='5'))
 {
  D(bug("ppm.datatype/OM_NEW: Wrong depth\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Header successful read\n"));

 bmhd->bmh_Width  = Width;
 bmhd->bmh_Height = Height;
 bmhd->bmh_PageWidth = bmhd->bmh_Width;
 bmhd->bmh_PageHeight = bmhd->bmh_Height;

 D(bug("ppm.datatype/OM_NEW: Using 24 bit colors\n"));
 bmhd->bmh_Depth = 24;

 /* Get a buffer for one line of RGB triples */
 RGBBuffer=AllocVec(Width*3, MEMF_ANY | MEMF_CLEAR);
 if(!RGBBuffer)
 {
  D(bug("ppm.datatype/OM_NEW: AllocVec(RGBBuffer) failed\n"));
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  SetIoErr(ERROR_NO_FREE_STORE);
  return(0);
 }
 D(bug("ppm.datatype/OM_NEW: RGBBuffer successfully allocated\n"));

 /* Flush filehandle, so that unbuffered Read() can be used after buffered FGets() */
 Flush(FileHandle);

 /* Copy picture line by line to picture.datatype using WRITEPIXELARRAY method */
 for(i=0; i<Height; i++)
 {
  if(!(Read(FileHandle, RGBBuffer, (Width*3))==(Width*3)))
  {
   D(bug("ppm.datatype/OM_NEW: Read(RGBBuffer) failed, maybe file too short\n"));
   FreeVec(RGBBuffer);
   CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
   SetIoErr(ERROR_OBJECT_WRONG_TYPE);
   return(0);
  }
  if(!DoSuperMethod(cl, (Object *) RetVal,
		PDTM_WRITEPIXELARRAY,	/* Method_ID */
		(IPTR) RGBBuffer,	/* PixelData */
		PBPAFMT_RGB,		/* PixelFormat */
		Width*3,		/* PixelArrayMod (number of bytes per row) */
		0,			/* Left edge */
		i,			/* Top edge */
		Width,			/* Width */
		1))			/* Height (here: one line) */
   {
	D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY failed\n"));
	FreeVec(RGBBuffer);
	CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
	return(0);
   }
 }
 D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY of whole picture done\n"));

 FreeVec(RGBBuffer);

 SetDTAttrs((Object *) RetVal, NULL, NULL, DTA_ObjName,      (IPTR) Title,
					   DTA_NominalHoriz, Width,
					   DTA_NominalVert,  Height,
					   TAG_DONE);

 D(bug("ppm.datatype/OM_NEW: Leaving. (24 bit mode)\n"));
 return(RetVal);
} /* PPM_New() */

/**************************************************************************************************/

static BOOL PPM_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
    BPTR		    filehandle;
    unsigned int            width, height, numplanes, y;
    UBYTE		    *linebuf;
    struct BitMapHeader     *bmhd;
    long                    *colorregs;

    D(bug("ppm.datatype/PPM_Save()\n"));

    /* A NULL file handle is a NOP */
    if( !dtw->dtw_FileHandle )
    {
	D(bug("ppm.datatype/PPM_Save() --- empty Filehandle - just testing\n"));
	return TRUE;
    }
    filehandle = dtw->dtw_FileHandle;

    /* Get BitMapHeader and color palette */
    if( GetDTAttrs( o,  PDTA_BitMapHeader, (IPTR) &bmhd,
			PDTA_CRegs,        (IPTR) &colorregs,
			TAG_DONE ) != 2UL ||
	!bmhd || !colorregs )
    {
	D(bug("ppm.datatype/PPM_Save() --- missing attributes\n"));
	SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }

    width = bmhd->bmh_Width;
    height = bmhd->bmh_Height;
    numplanes = bmhd->bmh_Depth;
    if( numplanes != 24 )
    {
	D(bug("ppm.datatype/PPM_Save() --- color depth %d, can save only depths of 24\n", numplanes));
	SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    D(bug("ppm.datatype/PPM_Save() --- Picture size %d x %d (x %d bit)\n", width, height, numplanes));

    /* Write header to file */
    if( FPrintf( filehandle, "P6\n#Created by AROS ppm.datatype aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n%ld %ld\n255\n",
	(long)width, (long)height ) == -1 )
    {
	D(bug("ppm.datatype/PPM_Save() --- writing header failed\n"));
	return FALSE;
    }

    /* Now read the picture data line by line and write it to a chunky buffer */
    if( !(linebuf = AllocVec(width*3, MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    D(bug("ppm.datatype/PPM_Save() --- copying picture with READPIXELARRAY\n"));
    for (y=0; y<height; y++)
    {
	if(!DoSuperMethod(cl, o,
			PDTM_READPIXELARRAY,	/* Method_ID */
			(IPTR)linebuf,		/* PixelData */
			PBPAFMT_RGB,		/* PixelFormat */
			width,			/* PixelArrayMod (number of bytes per row) */
			0,			/* Left edge */
			y,			/* Top edge */
			width,			/* Width */
			1))			/* Height */
	{
	    D(bug("ppm.datatype/PPM_Save() --- READPIXELARRAY line %d failed !\n", y));
	    FreeVec(linebuf);
	    SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
	if( FWrite( filehandle, linebuf, width*3, 1 ) != 1 )
	{
	    D(bug("ppm.datatype/PPM_Save() --- writing picture data line %d failed !\n", y));
	    FreeVec(linebuf);
	    return FALSE;
	}
    }

    D(bug("ppm.datatype/PPM_Save() --- Normal Exit\n"));
    FreeVec(linebuf);
    SetIoErr(0);
    return TRUE;
}

/**************************************************************************************************/

IPTR PPM__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{
    if( (dtw -> dtw_Mode) == DTWM_RAW )
    {
	/* Local data format requested */
	return PPM_Save(cl, o, dtw );
    }
    else
    {
	/* Pass msg to superclass (which writes an IFF ILBM picture)... */
	return DoSuperMethodA( cl, o, (Msg)dtw );
    }
}

/**************************************************************************************************/

#if DEBUGMETHODS

STATIC IPTR DT_NotifyMethod(struct IClass *cl, struct Gadget *g, struct opUpdate *msg)
{
 return(DoSuperMethodA(cl, (Object *) g, (Msg) msg));
}

/**************************************************************************************************/
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
 IPTR RetVal;

 D(bug("ppm.datatype/OM_SET: Entering\n"));

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 return(RetVal);
}

/**************************************************************************************************/
STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{
 IPTR RetVal;

 D(bug("ppm.datatype/OM_GET: Entering\n"));

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 return(RetVal);
}

/**************************************************************************************************/

STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{
 IPTR RetVal;
 const char L[]="GM_LAYOUT";
 const char P[]="DTM_PROCLAYOUT";
 const char A[]="DTM_ASYNCLAYOUT";
 const char U[]="Unknown Method";
 char *MethodName;

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 D(bug("ppm.datatype/%s: RetVal 0x%lx\n", MethodName, (unsigned int) RetVal));

 D(bug("ppm.datatype/%s: Leaving\n", MethodName));

 return(RetVal);
}

#endif /* DEBUGMETHODS */


IPTR DTD__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{

} /* DTD_OM_New() */

/**************************************************************************************************/

static BOOL DTD_Load(struct IClass *cl, Object *o)
{

}

static BOOL DTD_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{

}

IPTR DTD__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{

}

/**************************************************************************************************/

STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{

}

STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{

}

STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{

}




聲音資料型別 Sound_Write 函式是 SuperMethod。通常,當資料型別具有兩種方法時:OM_NEW 和 DTM_WRITE。第一個將資料型別的 Load 函式與 Datatypes 庫連結,用於獲取新的資料型別。第二個連結資料型別的 Save 函式,或者如果 DT Write 方法不是 DTWM_RAW,則它應該委託給 SuperMethod。在這種情況下,它將 DTWM_IFF 訊息傳送到聲音資料型別函式 Sound_Write。

是否最好使用 DTMethod 在緩衝區上解壓縮,然後使用此未壓縮的緩衝區?對於聲音,使用 SDTA_Sample(或 SDTA_LeftSample/SDTA_RightSample)屬性獲取資料。可以使用 SDTA_Sample 標籤檢索樣本資料,但 AmigaOS 不支援 SDTA_SampleType,因此您只能從那裡獲取 8 位樣本資料。AROS 和 MorphOS 在這裡更先進。

任何應用程式都會查詢您的類支援的方法。確保如果您選擇實現對 OM_GET/DTA_Methods 標籤的支援,您返回的方法也應該包含您的超類支援的方法。否則,使用者將無法使用“複製”或“列印”等函式。


    NAME
        sound.datatype -- root data type for sounds.

    FUNCTION
        The sound.datatype is the super-class for any sound related
        classes.

    METHODS
        OM_NEW -- Create a new sound object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of a sound object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.  On SELECTDOWN, the
            sound will start playing.

        GM_HANDLEINPUT -- Handle input.  Currently input (other than
            SELECTDOWN) doesn't affect the sound.

        GM_RENDER -- Cause the graphic to render.  Currently the graphic
            for the sound is just a static icon.

        DTM_TRIGGER -- Cause an event to occur.  Currently the only
            trigger event is STM_PLAY, which will cause the sound to start
            playing.

            NOTE: Subclasses which support streaming data access may
                  support more than just the STM_PLAY event.

        DTM_COPY -- Copy the entire sound to the clipboard as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

        DTM_WRITE -- Write the entire sound to a file as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

    TAGS
        SDTA_VoiceHeader (struct VoiceHeader *) -- Set and get the base
            information for the sound.  VoiceHeader is defined in
            <datatypes/soundclass.h>.

            NOTE: Up to and including V40 sound.datatype never returned
                  a valid VoiceHeader for OM_GET and the VoiceHeader data
                  was ignored in the OM_NEW/OM_SET cases. This was fixed
                  in V44.

            Applicability is (ISG).

        SDTA_Sample (BYTE *) -- Set and get the sound data.  Starting
            with V40 the sample data does not need to be in CHIP memory.
            Starting with V44 the sample data does not need to start
            on a WORD-aligned address. Setting SDTA_Sample to NULL
            will stop sound replay if sound.datatype was started
            playing with a non-NULL SDTA_Sample parameter.

            The SDTA_Sample parameter selects mono playback on any
            sound channel that is currently available.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SampleLength (ULONG) -- Length of the sound data in bytes.
            Starting with V44 the sample data does not need to be
            an even number of bytes. Setting SDTA_SampleLength to 0
            will stop sound replay.

            Applicability is (ISG).

        SDTA_Period (UWORD) -- Set and get the period of the sound
            (in timing intervals per sample). This attribute can be
            used to affect a playing sound. Please note that the
            Amiga audio hardware does not reliably support playback
            periods shorter than 124; sound.datatype will limit the
            period to valid intervals (V44).

            Default for this tag is 394.  Applicability is (ISG).

        SDTA_Volume (UWORD) -- Set and get the volume of the sound. This
            attribute can be used to affect a playing sound.

            Valid range is from 0 to 64.  Default for this tag is 64.
            Applicability is (ISG).

        SDTA_Cycles (UWORD) -- Set and get the number of cycles the
            sound will be played.

            Default for this tag is 1.  Applicability is (ISG).

        The following tags are new for V40.

        SDTA_SignalTask (struct Task *) -- Task to signal when the
            is complete, or if SDTA_Continuous is TRUE, when
            the next buffer is needed.

            Default for this tag is NULL. Applicability is (IS).

        SDTA_SignalBit (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable.

            NOTE: Due to a bug in sound.datatype V40 SDTA_SignalBit was
                  actually implemented as a signal mask as opposed to a
                  bit number. The documentation now reflects this. If you
                  intend to use a signal bit number instead of the mask,
                  use the new V44 tag SDTA_SignalBitNumber below.

            Default for this tag is 0. Applicability is (IS).

        SDTA_Continuous (BOOL) -- Used to indicate that the sound
            datatype will be fed a continuous stream of data.

            Default for this tag is FALSE. Applicability is (I).

        The following tags are new for V44.

        SDTA_SignalBitMask (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable. This tag is an alias for SDTA_SignalBit.

            Default for this tag is 0. Applicability is (IS).

        SDTA_SignalBitNumber (BYTE) -- Signal bit to use with SDTA_SignalTask
            or -1 to disable.

            Default for this tag is -1. Applicability is (IS).

        SDTA_SamplesPerSec (UWORD) -- Set and get the replay frequency of
            a sound (in Hz). This attribute can be used to affect a playing
            sound. Unlike the SDTA_Period tag, which serves the same purpose,
            this tag automatically takes the system clock value into account.
            Please note that the Amiga audio hardware does not reliably
            support playback rates beyond 28,000 samples per second;
            sound.datatype will limit the replay frequency to valid
            intervals.

            Applicability is (ISG).

        SDTA_ReplayPeriod (struct timeval *) -- Get the replay period,
            i.e. the time it takes for the complete sound to be played.
            If the sample size has not been set yet, the timeval tv_sec
            and tv_micro members will be set to 0. If the sample is to
            be played continuously, both timeval members will be set
            to 0xFFFFFFFF.

            Applicability is (G).

        SDTA_Pan (BYTE) -- Set the stereo panning; this must be set to
            a number in the range of -64..64. A value of -64 will
            pan the sound to the left channel, silencing the right
            channel; a value of 64 will pan the sound to the right
            channel and silence the left channel. To center playback,
            use a panning value of 0. The panning value only takes
            effect if a stereo sound is being played.

            Default for this tag is 0. Applicability is (IS).

        SDTA_FreeSampleData (BOOL) -- This tag controls whether
            sound.datatype will call FreeVec() on the sample data
            attached to an object. If the SDTA_Continuous attribute was
            set to TRUE, sound.datatype will never free any data attached
            to an object. It is safe to attach the same sample to
            more than one channel as sound.datatype will make sure that
            no sample data is freed twice.

            Default for this tag is FALSE. Applicability is (IS).

        SDTA_LeftSample (BYTE *) -- Set and get the left channel sound data.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_LeftSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_LeftSample parameter.

            The SDTA_LeftSample parameter alone selects mono playback on
            any left sound channel that is currently available. Used together
            with the SDTA_RightSample parameter, stereo playback on any
            available stereo channels is selected.

            The SDTA_LeftSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_RightSample (BYTE *) -- Set and get the right channel sound data
.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_RightSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_RightSample parameter.

            The SDTA_RightSample parameter alone selects mono playback on
            any right sound channel that is currently available. Used
            together with the SDTA_LeftSample parameter, stereo playback
            on any available stereo channels is selected.

            The SDTA_RightSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SyncSampleChange (BOOL) -- If SDTA_Continuous was set to TRUE,
            sound.datatype will expect a continuous stream of data to be
            played. By specifying "SDTA_SyncSampleChange,TRUE" you request
            that new sound data will be played only if the old data has
            been played completely (otherwise, playback would restart
            immediately with the new sound). If playback is currently in
            progress, the Task to change the sample data will be made to
            wait until playback of the old sound has finished.

            Default for this tag is FALSE. Applicability is (IS).

        DTA_Immediate (BOOL) -- Select and query whether playback should
            start immediately after the object has passed the layout
            process.

            Default for this tag is FALSE. Applicability is (ISG).

        DTA_Repeat (BOOL) -- Select and query whether playback should
            loop indefinitely, regardless of the current SDTA_Cycles
            settings.

            Default for this tag is FALSE. Applicability is (ISG).

    NOTES
        You cannot switch between mono and stereo playback on the fly while
        the sound is still playing. First, stop the sound, then change the
        SDTA_Sample/SDTA_LeftSample/SDTA_LeftSample attributes.

        The sound.datatype implementation has been cleaned up for V44 to
        allow for streaming subclasses to be written. Such subclasses will
        always return NULL when their SDTA_LeftSample, SDTA_RightSample and
        SDTA_Sample attributes are queried. However, they will never return
        0 for the SDTA_SampleLength and SDTA_SamplesPerSec attributes since
        these can be used to calculate the length of the entire sample.
        Streaming subclasses will respond to the DTM_TRIGGER method, to
        start, stop playback, etc. but may not support any other methods
        which rely upon the entire sample to reside in memory.


超文字

[編輯 | 編輯原始碼]

AmigaOS 使用者嘗試使用它來提供 HTML、圖片、動畫和音訊的組合。

到目前為止,AROS 還沒有任何類似的東西。



如何編譯資料型別

[編輯 | 編輯原始碼]

構建 dtdesc 工具,這是您需要的。原始碼位於 tools/dtdesc 中。該工具用於從 .dtd 檔案建立資料型別描述符。類庫以通常的方式構建,使用通常的交叉編譯器。

一個包,以便可以獨立於整個構建系統輕鬆構建資料型別。為原生 AROS 編譯了 createdtdesc 和 examinedtdesc。另一個需要的工具是 genmodule。

需要一個 READ/WRITEPIXELARRAY 介面,它取代了以前的 SET PDTA_BitMap 和 GET PDTA_DestBtMap 介面。如果一個位圖被 SET(舊介面),它會在佈局過程中被轉換為 LUT8 格式。僅當 Prefs 設定了它或應用程式透過 GET PDTA_DestBitMap 請求它時,才會建立目標點陣圖。

RENDER 方法選擇以下函式之一進行顯示

  • cgfx/WritePixelArray:真彩色圖片 -> 真彩色螢幕
  • cgfx/WriteLUTPixelArray:顏色對映圖片 -> 真彩色螢幕
  • graphics/WriteChunkyPixels:顏色對映圖片 -> 顏色對映塊狀螢幕
  • graphics/BltBitMapRastPort:顏色對映圖片 -> 顏色對映平面螢幕

真彩色圖片 -> 顏色對映螢幕在佈局過程中處理,使用固定的顏色對映和一些簡單的但快速的抖動演算法(一維誤差傳播)。Floyd-Steinberg 抖動演算法可用於獲得稍微好一些的結果(二維誤差傳播)。透過計算顏色對映(例如中值切割演算法)可以獲得更好的結果,但這要慢得多。

顏色對映資料始終儲存在 LUT8 格式中,或為舊版儲存在 BitMap 格式中。真彩色資料始終儲存在 ARGB 格式中。這在記憶體方面並不有效,但使事情更簡單、更快。這裡可以做一些最佳化。

為新的圖形資料型別建立了一個模板 這裡


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(這是未壓縮的資料)。

華夏公益教科書