跳轉到內容

Aros/開發者/文件/庫/圖形

來自 Wikibooks,開放世界中的開放書籍
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 公共許可證

AROS 具有基於線的圖形模式,這對於基於多邊形和線框的繪圖實用程式非常有用。

它還具有用於影像(圖片)的點陣圖操作功能。

  • 8 位(256 色)graphics.library
  • 高達 32 位(1400 萬色)cybergraphics.library(它是 graphics 的擴充套件,因此如果需要,兩者都需要開啟)。

為了說明這一點,如果您只想將 RGB 影像顯示到螢幕上,那麼您使用 Cybergfx 塊畫素函式就不會有任何問題。但是,如果您實際上想進行一些塊多邊形填充並光柵化基元(點、線等),那麼您將需要 graphics.library。


您需要了解 Window/Screen/BitMaps 與 RastPort(TmpRas)/ViewPort/... 背後的原理。

在某些情況下,需要使用 CloneRastport 和相關函式來替換 rastport 內容。理想情況下,應使用視窗 rastport 的克隆,而不是直接操作。

ViewPortAddress 返回與指定視窗關聯的視窗的地址。視窗實際上是螢幕上顯示視窗的視窗。如果您想在視窗中使用任何圖形、文字或動畫基元,並且該基元需要指向視窗的指標,則可以使用此呼叫。

Returns the address of the viewport of a given window. Use this call, if you want to use any graphics, text or animation functions that require the address of a viewport for your window.
INPUTS       Window - pointer to a Window structure 
RESULT       Address of the Intuition ViewPort structure for the screen that your window is displayed on.


RastPort 的點陣圖(控制筆的數量、繪製模式和圖案)。

繪圖函式(資料移動、區域操作、文字、裁剪、顏色)。

動畫、圖層、顯示資料庫、Blitter、Copper、其他。


線形圖形

[編輯 | 編輯原始碼]

與早期的 AmigaOS(TM) 一樣,AROS 也提供了一些使用 graphics.library 與線形圖形相關的函式。這些函式包括設定顏色、繪製點(畫素)、繪製線條、矩形、圓形、圖案、區域填充等等。大多數函式都需要一個指向 RastPort 的指標,RastPort 是一個特殊的公共結構(模板),它由 Window 或 Layer 呼叫自動建立,並由 Window->RPort(RastPort 地址)引用。該值可用於 SetAPen(rp,FrontPenNumber)、SetOPen(rp,OutlinePenNumber)、Move(rp,x,y) 和 Draw(rp,x,y) 以及 Text(rp,pointer_to_text,ext_length) 函式命令。

每當開啟一個視窗時,也會準備一個繪製表面,並將資訊儲存在其自己的 rastport 中。每個繪圖操作都涉及一個 rastport。如果您想直接繪製到視窗中,請使用視窗的 rastport。

在某些情況下,可能需要使用 CloneRastport 和相關函式來替換 rastport 內容。理想情況下,應使用視窗 rastport 的克隆,而不是直接操作。

RastPort 的內部結構如下所示。

struct RastPort
{
    struct  Layer  *Layer;
    struct  BitMap *BitMap;
    UWORD          *AreaPtrn;  /* Ptr to areafill pattern */
    struct  TmpRas *TmpRas;
    struct  AreaInfo *AreaInfo;
    struct  GelsInfo *GelsInfo;
    UBYTE   Mask;              /* Write mask for this raster */
    BYTE    FgPen;             /* Foreground pen for this raster */
    BYTE    BgPen;             /* Background pen  */
    BYTE    AOlPen;            /* Areafill outline pen */
    BYTE    DrawMode;          /* Drawing mode for fill, lines, and text */
    BYTE    AreaPtSz;          /* 2^n words for areafill pattern */
    BYTE    linpatcnt;         /* Current line drawing pattern preshift */
    BYTE    dummy;
    UWORD   Flags;             /* Miscellaneous control bits */
    UWORD   LinePtrn;          /* 16 bits for textured lines */
    WORD    cp_x, cp_y;	       /* Current pen position */
    UBYTE   minterms[8];
    WORD    PenWidth;
    WORD    PenHeight;
    struct  TextFont *Font;    /* Current font address */
    UBYTE   AlgoStyle;         /* The algorithmically generated style */
    UBYTE   TxFlags;           /* Text specific flags */
    UWORD   TxHeight;          /* Text height */
    UWORD   TxWidth;           /* Text nominal width */
    UWORD   TxBaseline;        /* Text baseline */
    WORD    TxSpacing;         /* Text spacing (per character) */
    APTR    *RP_User;
    ULONG   longreserved[2];
#ifndef GFX_RASTPORT_1_2
    UWORD   wordreserved[7];   /* Used to be a node */
    UBYTE   reserved[8];       /* For future use */
#endif
};

WritePixel(rp,x,y) 函式使用單獨的 SetAPen() 指令設定的顏色繪製一個點。

其他可用的指令

void SetAPen( struct RastPort *rp, unsigned long pen ) - Set foreground colour using preset colour pens
void SetBPen( struct RastPort *rp, unsigned long pen ) - Set background colour using preset colour pens
void Move(struct RastPort rp, long x, long y) - Move to co-ordinates row x, column y in a Rastport (rp) where 0,0 is the top left of window.
void Draw(struct RastPort rp, long x, long y) - Draws a line from current position to row x, column y.
void DrawEllipse( struct RastPort *rp, long xCenter, long yCenter, long a, long b ) - Draw an Ellipse
ULONG ReadPixel( struct RastPort *rp, long x, long y ) - Read a pixel value
LONG WritePixel( struct RastPort *rp, long x, long y ) - Write a pixel
void PolyDraw( struct RastPort *rp, long count, WORD *polyTable ) - Draw a multi-lined polygon using an array of x,y points.

可以使用 SIMPLE_REFRESH(重繪)或 SMART_REFRESH 視窗或 SUPER_BITMAP(GIMMEZEROZERO)視窗來重新整理視窗。

/* Grid in a Window */
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/layers.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <intuition/intuition.h>

int main() {
    struct Window *myWindow;
    struct RastPort *rp;
    int closewin = FALSE, row, column;
    struct IntuiMessage *msg;
    ULONG msgClass;
    long startx,starty,width;

    myWindow = OpenWindowTags(NULL,
      WA_Left, 0, WA_Top, 0,
      WA_Width, 640, WA_Height, 400,
      WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW,
      WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | 
      WFLG_CLOSEGADGET | WFLG_ACTIVATE | WFLG_SMART_REFRESH,
      WA_Title, "Grid In a Window",
      WA_PubScreenName, "Workbench",
      TAG_DONE);
    /* Get Window's Rastport */
    rp = myWindow->RPort;
 
    /* Draw 8x8 grid of boxes */
    /* Set foreground color */
    SetAPen(rp, 1);
    for(row=1; row<=8; row++) {
      for(column=1; column<=8; column++) {
      /* Move to correct screen position and draw box */
      Move(rp, row*30, column*30);
      Draw(rp, row*30+30, column*30 + 0);
      Draw(rp, row*30+30, column*30 + 30);
      Draw(rp, row*30+0, column*30 + 30);
      Draw(rp, row*30+0, column*30 + 0);
      }
    }
 
    while (closewin == FALSE) {
       Wait(1L << myWindow->UserPort->mp_SigBit);
       msg = GT_GetIMsg(myWindow->UserPort);
       msgClass = msg->Class;
       GT_ReplyIMsg(msg);
       if (msgClass == IDCMP_CLOSEWINDOW) {
          CloseWindow(myWindow);
          closewin = TRUE;
       }
       if (msgClass == IDCMP_REFRESHWINDOW)
          RefreshWindowFrame(myWindow);
    }
 
  return(0);
}

請檢視 amilines 獲取另一個示例,並檢視 arosbattleships 獲取一個 ASCII 版本的網格。

設定背景顏色

[編輯 | 編輯原始碼]

如果您的視窗沒有邊框,您只需

SetRast(win->RPort, 2);

但是,如果您的視窗有邊框,則需要考慮它們。

{
  LONG l, t, w, h;

  l = win->BorderLeft;
  t = win->BorderTop;
  w = win->Width - win->BorderLeft - win->BorderRight;
  h = win->Height - win->BorderTop - win->BorderBottom;

  if (w > 0 && h > 0)
  {
    /* White background */
    SetAPen(win->RPort, 2);
    RectFill(win->RPort, l, t, l + w - 1, t + h - 1);

    ...
  }
}

另一種方法是使用 WA_BackFill 和自定義的 backfill hook。

如果您使用的是 graphics.library,那麼無論您的顯示器執行什麼,筆都限制在 0-255 8 位範圍內。

RectFill 始終繪製到 RastPort 中。之前在 RastPort 中的所有內容都將被覆蓋。如果您的視窗在後臺,則只會繪製未隱藏的部分。對於 SMART_REFRESH 視窗,隱藏的部分將被儲存起來,並在視窗移至前臺時顯示。這包括受 RectFill 影響的部分。RectFill 始終使用筆 A 繪製,因此 SetBPen 對其沒有影響。類似地,使用 JAM1 或 JAM2 也沒有影響。

/* beginning of your program */

scr = LockPubScreen (pubscreennname);
red_pen = ObtainBestPen (scr->ViewPort.ColorMap,
           0xffffffff, 0x00000000, 0x00000000,
           OBP_FailIfBad, FALSE,
           OBP_Precision, PRECISION_GUI,
           TAG_END);

/* middle part */

rastPort=MainWindow->RPort;
SetAPen (rastPort,red_pen);
RectFill (rastPort,20,20,150,50);

/* end of your program */

ReleasePen (scr->ViewPort.ColorMap, red_pen);
UnlockPubScreen (NULL,scr);

在這些情況下,實際上並不重要您是否使用筆,因為在 RGB 顯示器上,您可以分配一個筆並儘可能頻繁地更改其顏色,而不會影響您已經渲染的任何內容。

如果您需要為 RGB 顯示器上的區域筆設定任意顏色,則需要使用 LoadRGB32 來設定您選擇的筆(或多支筆)的顏色。在 RGB 顯示器上,您可以不斷更改筆的顏色,而不會影響已渲染的畫素。在索引顯示器上,您必須擔心首先找到與您所需顏色接近的合適筆。

如果您使用的是“筆 1”,然後使用 SetRGB32() 中的值更改“筆 1”的調色盤值,只需分配一個筆,設定其 RGB 值,用它進行渲染,再次更改 RGB 值,再渲染一些內容,並在完成後釋放該筆即可。您並不侷限於使用單一筆,您可以分配用於區域、填充等的筆。關於 SetRGB32(),文件明確指出它比使用單個顏色索引的 LoadRGB32() 更慢。

在 AFA OS 68k、AROS 和 MOS 上,可以使用該標籤來設定 RGB 前景和背景顏色。

RPTAG_FgColor:
RPTAG_BgColor:

SetRPAttrs( rastport, RPTAG_FgColor:, 0xRRGGBB, TAG_DONE );
/*
    Example for simple drawing routines
*/

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>

#include <graphics/gfxmacros.h>

#include <stdlib.h>

static struct Window *window;
static struct ColorMap *cm;
static struct RastPort *rp;

/*
    ObtainBestPen() returns -1 when it fails, therefore we
    initialize the pen numbers with -1 to simplify cleanup.
*/
static LONG pen1=-1;
static LONG pen2=-1;

static void draw_simple(void);
static void clean_exit(CONST_STRPTR s);
static void handle_events(void);

int main(void)
{
    window = OpenWindowTags(NULL,
        WA_Left,   50,
        WA_Top,    70,
        WA_Width,  400,
        WA_Height, 350,
    
        WA_Title,         "Simple Graphics",
        WA_Activate,      TRUE,
        WA_SmartRefresh,  TRUE,
        WA_NoCareRefresh, TRUE,
        WA_GimmeZeroZero, TRUE,
        WA_CloseGadget,   TRUE,
        WA_DragBar,       TRUE,
        WA_DepthGadget,   TRUE,
        WA_IDCMP,         IDCMP_CLOSEWINDOW,
        TAG_END);
    
    if (! window) clean_exit("Can't open window\n");
    
    rp = window->RPort;
    cm = window->WScreen->ViewPort.ColorMap;

    // Let's obtain two pens
    pen1 = ObtainBestPen(cm, 0xFFFF0000 , 0 , 0 , TAG_END);
    pen2 = ObtainBestPen(cm, 0 , 0 , 0xFFFF0000 , TAG_END);
    if ( !pen1 || !pen2) clean_exit("Can't allocate pen\n");
    
    draw_simple();
    handle_events();

    clean_exit(NULL);

    return 0;
}

static void draw_simple(void)
{
    WORD array[] = {                // Polygon for PolyDraw()
        50, 200,
        80, 180,
        90, 220,
        50, 200,
    };
    
    SetAPen(rp, pen1);              // Set foreground color
    SetBPen(rp, pen2);              // Set background color
    
    WritePixel(rp, 30, 70);         // Plot a point
    
    SetDrPt(rp, 0xFF00);            // Change line pattern. Set pixels are drawn
                                    // with APen, unset with BPen
    
    Move(rp, 20, 50);               // Move cursor to given point
    Draw(rp, 100, 80);              // Draw a line from current to given point
    
    DrawEllipse(rp, 70,30, 15, 10); // Draw an ellipse

    /*
        Draw a polygon. Note that the first line is draw from the
        end of the last Move() or Draw() command.
    */
    PolyDraw(rp, sizeof(array)/sizeof(WORD)/2, array);
    
    SetDrMd(rp, JAM1);             // We want to use only the foreground pen.
    Move(rp, 200, 80);
    Text(rp, "Text in default font", 20);
    
    SetDrPt(rp, 0xFFFF);           // Reset line pattern
}

static void handle_events(void)
{
    /*
        A simple event handler. This will be explained more detailed
        in the Intuition examples.
    */
    struct IntuiMessage *imsg;
    struct MsgPort *port = window->UserPort;
    BOOL terminated = FALSE;
        
    while (!terminated)
    {
        Wait(1L << port->mp_SigBit);
        if ((imsg = (struct IntuiMessage *)GetMsg(port)) != NULL)
        {
            switch (imsg->Class)
            {
                case IDCMP_CLOSEWINDOW:
                    terminated = TRUE;
                    break;
            }
            ReplyMsg((struct Message *)imsg);
        }
    }
}

static void clean_exit(CONST_STRPTR s)
{
    if (s) PutStr(s);

    // Give back allocated resourses
    if (pen1 != -1) ReleasePen(cm, pen1);
    if (pen2 != -1) ReleasePen(cm, pen2);
    if (window) CloseWindow(window);

    exit(0);
}



調色盤

[編輯 | 編輯原始碼]

到目前為止,我們只使用了 SetXPen() 函式來選擇繪圖筆。現在,我們來看看如何更改筆的紅、綠、藍值。

如果調色盤屬於我們

  • 我們可以使用 LoadRGB...、SetRGB... 函式隨意更改顏色。當我們開啟一個私有螢幕時,我們將獲得一個私有調色盤。

我們想要繪製到公共螢幕上的視窗中。

  • 我們必須使用 ObtainBestPenA() 函式查詢一個共享筆。否則,我們將更改其他應用程式使用的顏色。

調色盤索引 0(Amiga 4 色模式下的“淺灰色”)。執行速度最快!


使用多邊形區域繪製

[編輯 | 編輯原始碼]

區域操作是區域函式,允許快速繪製填充的多邊形和橢圓。

要使用這些函式,你需要一個 AreaInfo 結構體,它必須連線到 rastport。區域緩衝區必須是 WORD 對齊的(必須具有偶數地址)。每個頂點需要五個位元組。

#define AREA_SIZE 200
WORD areaBuffer[AREA_SIZE];
struct AreaInfo areaInfo = {0};
memset(areabuffer, 0, sizeof(areabuffer));
InitArea(&areaInfo, areaBuffer, sizeof(areaBuffer)/5);
rastPort->AreaInfo = &areaInfo;

AreaInfo 結構體列出了構成填充形狀的點。

struct AreaInfo
{
    WORD   *VctrTbl;	     /* ptr to start of vector table */
    WORD   *VctrPtr;	     /* ptr to current vertex */
    BYTE    *FlagTbl;	      /* ptr to start of vector flag table */
    BYTE    *FlagPtr;	      /* ptrs to areafill flags */
    WORD   Count;	     /* number of vertices in list */
    WORD   MaxCount;	     /* AreaMove/Draw will not allow Count>MaxCount*/
    WORD   FirstX,FirstY;    /* first point for this polygon */
};

此外,你還需要一個 TmpRas 結構體。它應該與你想要繪製的點陣圖具有相同的寬度和高度。圖形工作區由一個名為

struct TmpRas
{
    BYTE *RasPtr;
    LONG Size;
};
/* unoptimized for 32bit alignment of pointers */


#define WIDTH 400
#define HEIGHT 300
PLANEPTR rasplane = AllocRaster(WIDTH, HEIGHT);
struct TmpRas tmpRas = {0};
InitTmpRas(&tmpRas, rasPlane, WIDTH * HEIGHT);
rastPort->TmpRas = &tmpRas;

現在可以使用 InitArea、AreaMove、AreaDraw 和 AreaEnd 函式來生成填充的多邊形“區域”,只要設定一個 TmpRas 結構體,它可以繪製形狀的輪廓並用指定顏色填充它。

struct TmpRas *InitTmpRas( struct TmpRas *tmpRas, PLANEPTR buffer, long size )
void InitArea( struct AreaInfo *areaInfo, APTR vectorBuffer, long maxVectors )
ULONG SetOutlinePen( struct RastPort *rp, unsigned long pen )

LONG AreaMove( struct RastPort *rp, long x, long y )
LONG AreaDraw( struct RastPort *rp, long x, long y )
LONG AreaEnd( struct RastPort *rp )

InitArea() 	Initializes the AreaInfo
AreaMove() 	Closes open polygon and sets start point for a new one. You don't have to connect the end point to the start point.
AreaDraw() 	Add point to vector buffer
AreaEllipse() 	Add filled ellipse to vector buffer
AreaEnd() 	Start filling operation

區域使用 InitTmpRas 初始化,它為區域設定一個工作區域並用 Raster 和 InitArea 進行填充,它設定一個向量緩衝區來儲存區域座標,然後將指標與視窗的 Raster 結構體關聯,最終渲染到螢幕上。要建立區域,使用 AreaMove 設定起始位置,然後使用 AreaDraw 使用絕對 x,y 座標繪製每個後續位置,不需要將最後一個座標與第一個位置連線,因為 AreaEnd 會為你完成此操作。請注意,我使用 SetAPen 和 SetOutlinePen 設定區域的顏色和形狀周圍的線條。InitTmpRas 需要一個指向 TmpRas 結構體的指標,一個指向 Chip 記憶體中緩衝區的指標(使用 AllocMem 分配)用於視窗的區域(寬度高度 x 8)以及緩衝區的大小。AreaInfo 需要一個指向 AreaInfo 結構體的指標,一個用於儲存 x,y 向量的緩衝區,以及一個最大向量數(緩衝區 * 2 /5),它使用 Word 值而不是 UBYTE,因為它必須是字對齊的。然後將結構體分配給 Rastport,例如 rp->AreaInfo 和 rp->TmpRas,然後再使用區域。

Flood(rp,mode,x,y)

如果將負座標傳遞給這些 AreaMove() AreaDraw() 函式,則顯示屏會損壞。此外,即使對沒有負座標的進一步呼叫,新的繪圖也會損壞。

繪圖函式

透過使用 Move() 將筆位置設定為起始位置,並使用 Draw() 將其設定為結束位置來繪製一條線。

對於 Flood() 函式,你必須將 TmpRas 附加到 rastport。

Move() 	Change pen position
Draw() 	Draw line from pen position to given coordinates
DrawEllipse() 	Draw an ellipse
DrawCircle() 	Draw a circle (macro in graphics/gfxmacros.h)
PolyDraw() 	Draw connected lines from an array of points
WritePixel() 	Write a single pixel
ReadPixel() 	Read the pen value of a pixel
EraseRect() 	Fill rectangular area with current backfill hook (TODO: what's this?)
SetRast() 	Fill entire drawing area with given pen
RectFill() 	Fill rectangular area with current rastport settings
Flood() 	Flood fill an arbitrary shape

Data moving
BltBitMap() 	Copy rectangular area
BltBitMapRastPort() 	Copy rectangular area
BltRastPortBitMap() 	Copy rectangular area (AROS extension)
ClipBlit() 	Copy rectangular area with layers and clip rects. Use this if you want to blit into a window
BltClear() 	Set a memory block to zero. On classic Amigas this block has to be in chip ram.
BltMaskBitMapRastPort() 	Copy rectangular area with using a mask
BltPattern() 	Draw a rectangular pattern into a bitmap
BltTemplate() 	Draw a rectangular pattern into a bitmap
BitMapScale() 	Copy a rectangular area and change its size
ScalerDiv() 	Helper function for BitMapScale()
ScrollRaster() 	Move rectangular area within a bitmap
ScrollRasterBF() 	Move rectangular area, the vacated space is filled with EraseRect()
WriteChunkyPixels() 	Write rectangular area from array with pen values
WritePixelArray8() 	Write rectangular area from array with pen values
ReadPixelArray8() 	Read rectangular area into memory
WritePixelLine8() 	Write horiz. line from an array with pen values
ReadPixelLine8() 	Read horiz. line from an array into memory



填充 2D 多邊形區域

[編輯 | 編輯原始碼]
/*
    Copyright � 1995-2014, The AROS Development Team. All rights reserved.
    $Id$
*/

#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <graphics/gfx.h>
#include <devices/rawkeycodes.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

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

#include <aros/debug.h>

#define MAX_POINTS 50

#define MODE_ADDPOINTS 1
#define MODE_MOVEPOINTS 2

#define MSGMOUSEX ( ((msg->MouseX - win->BorderLeft) < 0) ? 0 : \
    	    	    ((msg->MouseX - win->BorderLeft) >= win->GZZWidth) ? win->GZZWidth - 1 : \
		    (msg->MouseX - win->BorderLeft) )

#define MSGMOUSEY ( ((msg->MouseY - win->BorderTop) < 0) ? 0 : \
    	    	    ((msg->MouseY - win->BorderTop) >= win->GZZHeight) ? win->GZZHeight - 1 : \
		    (msg->MouseY - win->BorderTop) )

static struct Window *win;
static struct RastPort *winrp, *drawrp;
static struct BitMap *drawbm;
static struct AreaInfo ai;
static struct TmpRas tr;
static void *trbuf;
static UBYTE aibuf[(MAX_POINTS + 1) * 5];
static WORD mode, actpoint, hipoint, numpoints;
static WORD outlinepen = -1, testfillpen = -1;
static BOOL outlinemode, testfill;
static WORD points[MAX_POINTS + 1][2];
static char wintitle[256];

#include "areatest2_fillpoly.h"

static void cleanup(char *msg)
{
    if (msg) printf("areatest2: %s\n", msg);
    
    if (outlinepen != -1) ReleasePen(win->WScreen->ViewPort.ColorMap, outlinepen);
    if (testfillpen != -1) ReleasePen(win->WScreen->ViewPort.ColorMap, testfillpen);
    if (drawbm) FreeBitMap(drawbm);
    if (drawrp) FreeRastPort(drawrp);
    
    if (trbuf)
    {
    	FreeRaster(trbuf, win->GZZWidth, win->GZZHeight);
    }
    
    if (win) CloseWindow(win);
    exit(0);    
}

static void updatetitle(void)
{
    char *title = "AreaTest2";
    
    switch(mode)
    {
    	case MODE_ADDPOINTS:
	    snprintf(wintitle,
	    	     sizeof(wintitle),
		     "Create points [%2d/%2d]. Press RETURN when done.",
		     actpoint + 1, MAX_POINTS);
	    title = wintitle;
	    break;

    	case MODE_MOVEPOINTS:
	    snprintf(wintitle,
	    	     sizeof(wintitle),
		     "Move points. Press RETURN to make new shape.");
	    title = wintitle;
	    break;
	    
    }
    
    SetWindowTitles(win, title, (char *)~0);
    
}

static void makewin(void)
{
    win = OpenWindowTags(0, WA_Title, (IPTR)"AreaTest2",
    	    	    	    WA_InnerWidth, 320,
			    WA_InnerHeight, 256,
			    WA_GimmeZeroZero, TRUE,
			    WA_CloseGadget, TRUE,
			    WA_DepthGadget, TRUE,
    	    	    	    WA_DragBar, TRUE,
			    WA_IDCMP, IDCMP_MOUSEBUTTONS |
			    	      IDCMP_MOUSEMOVE |
				      IDCMP_CLOSEWINDOW |
				      IDCMP_VANILLAKEY |
				      IDCMP_RAWKEY,
			    WA_Activate, TRUE,
			    WA_ReportMouse, TRUE,
			    TAG_DONE);
    if (!win) cleanup("Can't open window!");
    
    winrp = win->RPort;
     
    InitArea(&ai, aibuf, sizeof(aibuf) / 5);
    trbuf = AllocRaster(win->GZZWidth, win->GZZHeight);
    if (!trbuf) cleanup("TmpRas buffer allocation failed!");
    InitTmpRas(&tr, trbuf, RASSIZE(win->GZZWidth, win->GZZHeight));
    
    drawbm = AllocBitMap(win->GZZWidth, win->GZZHeight, 0, BMF_MINPLANES, win->RPort->BitMap);
    if (!drawbm) cleanup("Can't allocate draw bitmap!");
    
    drawrp = CreateRastPort();
    if (!drawrp) cleanup("Can't allocate draw rastport!");
    drawrp->BitMap = drawbm;
    
    drawrp->AreaInfo = &ai;
    drawrp->TmpRas = &tr;

    outlinepen = ObtainBestPen(win->WScreen->ViewPort.ColorMap, 0xFFFFFFFF,
    	    	    	    	    	    	    	    	0x00000000,
							     	0x00000000,
								OBP_FailIfBad, FALSE,
								TAG_DONE);
    
    testfillpen = ObtainBestPen(win->WScreen->ViewPort.ColorMap, 0x44444444,
    	    	    	    	    	    	    	    	 0x44444444,
							     	 0x44444444,
								 OBP_FailIfBad, FALSE,
								 TAG_DONE);

}

static void hilightpoint(WORD point)
{
    WORD x = points[point][0];
    WORD y = points[point][1];
    
    //kprintf("hilightpoint %d,%d\n", x, y);
    
    SetABPenDrMd(winrp, 2, 0, COMPLEMENT);
    Move(winrp, x - 3, y - 3);
    Draw(winrp, x + 3, y - 3),
    Draw(winrp, x + 3, y + 3);
    Draw(winrp, x - 3, y + 3),
    Draw(winrp, x - 3, y - 3);
}

static void clear(struct RastPort *rp)
{
    SetABPenDrMd(rp, 2, 0, JAM1);
    RectFill(rp, 0, 0, win->GZZWidth - 1, win->GZZHeight - 1);
}

static void paint(void)
{
    int i;
    
    if (numpoints == 0) return;
    
    switch(mode)
    {
    	case MODE_ADDPOINTS:
	    SetABPenDrMd(winrp, 1, 0, JAM1);
	    Move(winrp, points[0][0], points[0][1]);
	    PolyDraw(winrp, numpoints, (WORD *)points);	    
	    break;
	    
	case MODE_MOVEPOINTS:
	    clear(drawrp);
	    SetABPenDrMd(drawrp, testfill ? testfillpen : 1, 0, JAM1);
	    if (outlinemode)
	    {
	    	SetOutlinePen(drawrp, outlinepen);
	    }
	    else
	    {
	    	drawrp->Flags &= ~AREAOUTLINE;
	    }
	    
	    if (!testfill)
	    {
		AreaMove(drawrp, points[0][0], points[0][1]);
		for(i = 1; i < numpoints; i++)
		{
	    	    AreaDraw(drawrp, points[i][0], points[i][1]);
		}
		AreaEnd(drawrp);
	    }
	    else
	    {
	    	MyFillPolygon(drawrp, points, numpoints);
	    }
	    
	    BltBitMapRastPort(drawbm, 0, 0, winrp, 0, 0, win->GZZWidth, win->GZZHeight, 192);
	    break;
    }
}

static WORD pointundermouse(LONG x, LONG y)
{
    LONG i, dist;
    LONG best_i = 0, best_dist = 0x7fffffff;

    for(i = 0; i < numpoints; i++)
    {
	dist = (points[i][0] - x) * (points[i][0] - x) +
	       (points[i][1] - y) * (points[i][1] - y);

	if (dist < best_dist)
	{
	    best_dist = dist;
	    best_i = i;
	}
    }

    return (best_dist < 200) ? best_i : -1;
}

static void savepoly(WORD n)
{
    char s[200];
    BPTR fh;
    BOOL ok = FALSE;
    LONG err;
    
    snprintf(s, sizeof(s), "PROGDIR:polygon%d.dat", n);
    
    if ((fh = Open(s, MODE_NEWFILE)))
    {
    	WORD i = numpoints;
	
	if (Write(fh, &i, sizeof(i)) == sizeof(i))
	{
	    for(n = 0; n < numpoints; n++)
	    {
	    	i = points[n][0];		
		if (Write(fh, &i, sizeof(i)) != sizeof(i)) break;
		
		i = points[n][1];
		if (Write(fh, &i, sizeof(i)) != sizeof(i)) break;
		
	    }
	    
	    if (n == numpoints) ok = TRUE;
	}
	
	err = IoErr();
	
    	Close(fh);
    }
    else
    {
    	err = IoErr();
    }
    
    if (!ok) 
    {
    	Fault(err, "Saving failed", s, sizeof(s));
    }
    else
    {
    	strcpy(s, "Saved polygon");
    }

    SetWindowTitles(win, s, (char *)~0);
    Delay(75);
    updatetitle();

}

static BOOL loadpoly(WORD n)
{
    char s[200];
    BPTR fh;
    BOOL ok = FALSE;
    LONG err;
    WORD *temppoints;
    
    snprintf(s, sizeof(s), "PROGDIR:polygon%d.dat", n);
    
    if ((fh = Open(s, MODE_OLDFILE)))
    {
    	WORD i;
	
	if (Read(fh, &i, sizeof(i)) == sizeof(i))
	{
	    if ((temppoints = malloc(sizeof(WORD) * 2 * i)))
	    {	    
		for(n = 0; n < i; n++)
		{
		    if (Read(fh, &temppoints[n * 2], sizeof(WORD)) != sizeof(WORD)) break;
		    if (Read(fh, &temppoints[n * 2 + 1], sizeof(WORD)) != sizeof(WORD)) break;

		}

		if (n == i)
		{
		    numpoints = i;
		    for(i = 0; i < n; i++)
		    {
		    	points[i][0] = temppoints[i * 2];
		    	points[i][1] = temppoints[i * 2 + 1];
		    }
		    
		    ok = TRUE;
		}
		
		free(temppoints);
	    }
	    
	}
	
	err = IoErr();
	
    	Close(fh);
    }
    else
    {
    	err = IoErr();
    }
    
    if (!ok) 
    {
    	Fault(err, "Loading failed", s, sizeof(s));
    	SetWindowTitles(win, s, (char *)~0);
    	Delay(75);
    	updatetitle();
    }
  
    return ok;

}

static void handleall(void)
{
    struct IntuiMessage *msg;
    WORD    	    	 i;
    BOOL    	    	 quitme = FALSE, lmbdown = FALSE;
    
    mode = MODE_ADDPOINTS;
    updatetitle();
    clear(winrp);
    
    while(!quitme)
    {
    	WaitPort(win->UserPort);
    	while((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
	{
	    switch(msg->Class)
	    {
	    	case IDCMP_CLOSEWINDOW:
		    quitme = TRUE;
		    break;
		    
		case IDCMP_MOUSEBUTTONS:
		    if (msg->Code == SELECTDOWN)
		    {
		    	lmbdown = TRUE;
			
			switch(mode)
			{
		    	    case MODE_ADDPOINTS:
				points[actpoint][0] = MSGMOUSEX;
				points[actpoint][1] = MSGMOUSEY;
				actpoint++;
				numpoints++;
				if (numpoints == MAX_POINTS)
				{
			    	    mode = MODE_MOVEPOINTS;
				    actpoint = -1;
				    hipoint = -1;
				}
				paint();
				updatetitle();
				break;
				
			    case MODE_MOVEPOINTS:
			    	actpoint = pointundermouse(MSGMOUSEX, MSGMOUSEY);
			    	break;
				
			}
		    }
		    else if (msg->Code == SELECTUP)
		    {
		    	lmbdown = FALSE;
			
			switch(mode)
			{
			    case MODE_MOVEPOINTS:
			    	actpoint = -1;
				hipoint = -1;
				break;
			}
		    }
		    
		    break;
		    
		case IDCMP_MOUSEMOVE:
		    switch(mode)
		    {
		    	case MODE_MOVEPOINTS:
			    if ((actpoint >= 0) && lmbdown)
			    {
			    	points[actpoint][0] = MSGMOUSEX;
				points[actpoint][1] = MSGMOUSEY;
				paint();
			    }
			    else if (!lmbdown)
			    {
			    	WORD new_hipoint = pointundermouse(MSGMOUSEX, MSGMOUSEY);
				
				if (new_hipoint != hipoint)
				{
				    if (hipoint >= 0) hilightpoint(hipoint);
				    hipoint = new_hipoint;
				    if (hipoint >= 0) hilightpoint(hipoint);
				}
			    }
			    
			    break;
		    }
		    break;
		    
		case IDCMP_VANILLAKEY:
		    switch(msg->Code)
		    {
		    	case 27:
			    quitme = TRUE;
			    break;
			    
		    	case 13:
			    switch(mode)
			    {
			    	case MODE_ADDPOINTS:
				    if (numpoints >= 2)
				    {
			    	    	mode = MODE_MOVEPOINTS;
				    	actpoint = -1;
					hipoint = -1;
					paint();
					updatetitle();
				    }
				    break;
				    
				case MODE_MOVEPOINTS:
				    actpoint = numpoints = 0;
				    mode = MODE_ADDPOINTS;
				    clear(winrp);
				    updatetitle();
				    break;
			    }
			    break;

    	    	    	case '4':
			    if (mode == MODE_MOVEPOINTS)
			    {
				for(i = 0; i < numpoints; i++)
				{
			    	    if (points[i][0] > 0) points[i][0]--;				
				}
				hipoint = -1;
				paint();
			    }
			    break;

    	    	    	case '6':
			    if (mode == MODE_MOVEPOINTS)
			    {
				for(i = 0; i < numpoints; i++)
				{
			    	    if (points[i][0] < win->GZZWidth - 1) points[i][0]++;				
				}
				hipoint = -1;
				paint();
			    }
			    break;

    	    	    	case '8':
			    if (mode == MODE_MOVEPOINTS)
			    {
				for(i = 0; i < numpoints; i++)
				{
			    	    if (points[i][1] > 0) points[i][1]--;				
				}
				hipoint = -1;
				paint();
			    }
			    break;

    	    	    	case '2':
			    if (mode == MODE_MOVEPOINTS)
			    {
				for(i = 0; i < numpoints; i++)
				{
			    	    if (points[i][1] < win->GZZHeight - 1) points[i][1]++;				
				}
				hipoint = -1;
				paint();
			    }
			    break;
			
			case 'o':
			case 'O':
			    outlinemode = !outlinemode;
			    if (mode == MODE_MOVEPOINTS)
			    {
			    	hipoint = -1;
				paint();
				SetWindowTitles(win, outlinemode ? "Outline Mode: ON" : "Outline Mode: OFF", (char *)~0);
				Delay(30);
				updatetitle();
			    }
			    break;
			    
			case 'f':
			case 'F':
			case 'R':
			case 'r':
			    testfill = !testfill;
			    if (mode == MODE_MOVEPOINTS)
			    {
			    	hipoint = -1;
				paint();
				SetWindowTitles(win, testfill ? "Test Fillroutine: ON" : "Test Fillroutine: OFF", (char *)~0);
				Delay(30);
				updatetitle();
			    }
			    break;
		    }
		    break;
		    
		case IDCMP_RAWKEY:
		    switch(mode)
		    {
		    	case MODE_MOVEPOINTS:
			    if (lmbdown && actpoint >= 0)
			    {
			    	BOOL changed = FALSE;
				
			    	switch(msg->Code)
				{
				    case CURSORLEFT:
				    	if (points[actpoint][0] > 0)
					{
					    points[actpoint][0]--;
					    changed = TRUE;
					}
					break;
					
				    case CURSORRIGHT:
				    	if (points[actpoint][0] < win->GZZWidth - 1)
					{
					    points[actpoint][0]++;
					    changed = TRUE;
					}
				    	break;
					
				    case CURSORUP:
				    	if (points[actpoint][1] > 0)
					{
					    points[actpoint][1]--;
					    changed = TRUE;
					}
					break;
					
				    case CURSORDOWN:
				    	if (points[actpoint][1] < win->GZZHeight - 1)
					{
					    points[actpoint][1]++;
					    changed = TRUE;
					}
				    	break;
				    	
				} /* switch(msg->Code) */
				
				if (changed) paint();
				
			    } /* if (!lmbdown && hipoint >= 0) */
			    else
			    {
			    	switch(msg->Code)
				{
				    case RAWKEY_F1:
				    case RAWKEY_F2:
				    case RAWKEY_F3:
				    case RAWKEY_F4:
				    case RAWKEY_F5:
				    case RAWKEY_F6:
				    case RAWKEY_F7:
				    case RAWKEY_F8:
				    case RAWKEY_F9:
				    case RAWKEY_F10:
				    	if (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
					{
				    	    savepoly(msg->Code - RAWKEY_F1 + 1);
					}
					else
					{
					    loadpoly(msg->Code - RAWKEY_F1 + 1);
					    hipoint = -1;
					    paint();
					}
					break;
				    
				}
			    }
			    break;
			    			    
			case MODE_ADDPOINTS:
			    switch(msg->Code)
			    {
				    case RAWKEY_F1:
				    case RAWKEY_F2:
				    case RAWKEY_F3:
				    case RAWKEY_F4:
				    case RAWKEY_F5:
				    case RAWKEY_F6:
				    case RAWKEY_F7:
				    case RAWKEY_F8:
				    case RAWKEY_F9:
				    case RAWKEY_F10:
				    	if (!(msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
					{
					    if (loadpoly(msg->Code - RAWKEY_F1 + 1))
					    {
					    	hipoint = -1;
						actpoint = -1;
						mode = MODE_MOVEPOINTS;
					    	paint();
					    }
					}
					break;
			    }
			    break;
			    
		    } /* switch(mode) */
		    break;
		    
	    } /* switch(msg->Class) */
	    ReplyMsg((struct Message *)msg);
	    
	} /* while((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
	
    } /*while(!quitme) */
    
}

int main(void)
{
    makewin();
    handleall();
    cleanup(0);    
    return 0;
}


點陣圖

[編輯 | 編輯原始碼]

雖然開啟螢幕或視窗會自動設定 RastPort,但 BitMap 結構體需要你自己設定。BitMap 告訴圖形庫繪圖區域位於記憶體中的哪個位置以及它是如何排列的。

struct BitMap
{
    UWORD   BytesPerRow;
    UWORD   Rows;
    UBYTE   Flags;
    UBYTE   Depth;
    UWORD   pad;
    PLANEPTR Planes[8];
};
static struct Window *win;
static struct BitMap *drawbm;
static struct RastPort *winrp, *drawrp;
static struct AreaInfo ai;
static struct TmpRas tr;
static void *trbuf;

/* Initialize the RastPort and link the BitMap to it. */
InitRastPort(&rastPort);
rastPort.BitMap = &bitMap;
struct RastPort *offscreen_buffer_rp;
offscreen_buffer_rp &myBufferRP;
  • 分配一個視窗。
  • 建立一個與你的視窗可見區域大小相同的輔助點陣圖,作為螢幕外緩衝區。
  • 建立一個第二個輔助點陣圖,其大小是瓷磚大小的合理倍數。
  • 將你的瓷磚渲染到第二個點陣圖中。

如果繪製到螢幕外點陣圖,則建立自己的臨時 rastport,然後將臨時點陣圖 blit 到視窗的 rastport 中。

建立螢幕外點陣圖時,確保它擁有自己的 rastport,該 rastport 具有與視窗使用的 rastport 相同的屬性(例如調色盤等)。

    screen = LockPubScreen(NULL);
    if (screen)
    {
        printf("screen bitmap %p\n", screen->RastPort.BitMap);
        bitmap = AllocBitMap(400, 300, 32, BMF_MINPLANES | /*BMF_DISPLAYABLE | */ BMF_SPECIALFMT | SHIFT_PIXFMT(PIXFMT_ABGR32), screen->RastPort.BitMap);

如果你希望它完全無閃爍,你可能需要將其繪製到螢幕外點陣圖中,更新文字,然後將整個內容 blit 到視窗中。

 struct RastPort rp;
 struct * Bitmap PBM, ULONG screenDepth, flags, BOOL isStandardBM; 
 InitRastPort (& rp); 
 screenDepth GetBitMapAttr = (pWin-> WScreen-> RastPort.BitMap, BMA_DEPTH); 
 isStandardBM GetBitMapAttr = (pWin-> WScreen-> RastPort . BitMap, BMA_FLAGS) & BMF_STANDARD; 
 flags = (FindPort ("FBlit")?0:BMF_DISPLAYABLE) | (isStandardBM? 0: BMF_MINPLANES);

/* friend_bitmap clones the existing bitmap's pixel format in graphics RAM and has all the correct alignment for blitting and stuff */
 PBM = AllocBitMap (IMAGE_WIDTH, IMAGE_HEIGHT, screenDepth, flags, pWin-> WScreen-> RastPort.BitMap)
if (! PBM) return / * quit if allocation failed * /
 = rp.BitMap PBM, / * binds to BitMap RastPort * / 
 WriteChunkyPixels (& rp, 0, 0, IMAGE_WIDTH-1 IMAGE_HEIGHT-1 Image IMAGE_WIDTH);

 /* draw the Bitmap in the window */
 BltBitMapRastPort (struct Bitmap * bitmap_source, src_x WORD, WORD src_y,
                    struct * RastPort rastport_dest, dest_x WORD, WORD dest_y,
                    WORD width, WORD height UBYTE minterm); bitmap_source
static struct RastPort *Alloctemprp(struct RastPort *rp)
{
   struct Layer_Info *li;
   struct Layer *l;
   struct BitMap *tempbm;
   ULONG bmwidth, bmheight, bmdepth;

   bmwidth  = GetBitMapAttr(rp->BitMap,BMA_WIDTH);
   bmheight = GetBitMapAttr(rp->BitMap,BMA_HEIGHT);
   bmdepth  = GetBitMapAttr(rp->BitMap,BMA_DEPTH);

   if(tempbm = AllocBitMap(bmwidth,bmheight,bmdepth,BMF_MINPLANES,rp->BitMap))
   {
       if (rp && rp->Layer)
       {
          if ((li = NewLayerInfo()) != NULL)
          {
              if ((l = CreateUpfrontHookLayer(li,
                                             tempbm,
                                             rp->Layer->bounds.MinX,
                                             rp->Layer->bounds.MinY,
                                             rp->Layer->bounds.MaxX,
                                             rp->Layer->bounds.MaxY,
                                             LAYERSIMPLE,
                                             LAYERS_NOBACKFILL,
                                             NULL)) != NULL)
             {
                InstallLayerHook(l,(struct Hook *)rp->Layer->BackFill);
                return (l->rp);
             }
             DisposeLayerInfo(li);
          }
       }
       FreeBitMap(tempbm);
   }
   return (NULL);
}

static void Freetemprp(struct RastPort *rp)
{
    struct Layer_Info *li;
    struct BitMap *bm = NULL;
    if(rp)
    {
        bm = rp->BitMap;
    }
    if (rp && rp->Layer)
    {
       li = rp->Layer->LayerInfo;
//       InstallLayerInfoHook(li,LAYERS_NOBACKFILL);
       InstallLayerHook(rp->Layer,LAYERS_NOBACKFILL);
       DeleteLayer(0,rp->Layer);
       DisposeLayerInfo(li);
    }
    if(bm)
    {
        FreeBitMap(bm);
    }
}

分配一個位圖,其輔助點陣圖設定為除 NULL 之外的其他值。否則,將在常規記憶體中建立具有緩衝區的點陣圖 - 這種點陣圖無法鎖定(特別是作業系統託管模式)。在託管顯示驅動程式上,點陣圖根本不是畫素陣列。它只是一個底層作業系統的 blob。它可以被模擬(臨時分配畫素陣列,複製資料,然後在解鎖時複製回來)。

如果你的視窗有尺寸工具或進行簡單的重新整理,最好將圖片放在後臺緩衝區中,這樣你就可以輕鬆地重新繪製暴露的區域。

始終使用 GetBitMapAttr() 查詢深度,例如 ULONG depth = GetBitMapAttr(screen->RastPort.BitMap, BMA_DEPTH); 否則,即使對於 24 位和 32 位螢幕,你也會得到“8”。不確定超級點陣圖是否已準備好用於真彩色螢幕,或者 AROS 中超級點陣圖視窗的實現是否已損壞,需要額外的測試。我的建議是,不要使用超級點陣圖視窗。你可以使用 ClipBlit() 將內容 blit 到視窗中。

你使用 RectFill() 填充背景或使用 WritePixelArray() 在文字後面繪製圖像的程式碼需要移動/複製/放入一個函式,並從你的內部迴圈呼叫。或者,你可以在兩種情況下都安裝一個後臺填充鉤子,並在其中執行 EraseRect()。

鉤子是你在程式碼中編寫的自定義函式,用於處理從攔截主程式碼(例如處理訊息)時出現的特定情況。該函式必須被設計為接受三個引數,其順序和型別已給出。

避免使用直接渲染到螢幕的 struct BitMap 中的技巧。你將盲目地覆蓋顯示屏的內容。RastPort 是用於正確繪圖的,它們負責裁剪和將隱藏的部分儲存在單獨的點陣圖中。但是,只有在它完全是你的螢幕並且作業系統沒有在上面顯示任何東西(即使是標題欄)的情況下,才允許直接在 BitMap 上繪製。或者它是你自己記憶體中的 BitMap。

使用 AllocBitMap() 建立的點陣圖沒有裁剪矩形。這意味著當你繪製到點陣圖之外時,你正在破壞記憶體。你可以處理你的繪製操作,或者你可以安裝裁剪矩形。有兩種可能性:

在 SetRPAttrsA() 中使用標籤 RPTAG_ClipRectangle

    struct Rectangle rect = {0, 0, 399, 299};
    SetRPAttrs(&rastPort, RPTAG_ClipRectangle, &rect, TAG_DONE);

安裝一個層

    li = NewLayerInfo())
    rastPort.Layer = CreateUpfrontLayer(li, rastPort->BitMap, 0, 0, width - 1, height - 1, 0, NULL))

    ...

    DeleteLayer(0,rastPort.Layer)
    DisposeLayerInfo(li)

後者與 AmigaOS 相容。

有幾種不同的方法可以將一個位圖複製到另一個位圖。BltBitMap(點陣圖到點陣圖 - 最容易崩潰)、ClipBlit(rastport 到 rastport - 銷燬目標的部分)和 BltBitmapRastPort(點陣圖到 rastport)。

一個最小項值(ABC、ABNC 和 ANBC),描述了影像必須如何複製

來自 blit.h

#define ABC 0x80
#define ABNC 0x40
#define ANBC 0x20
#define ANBNC 0x10
#define NABC 0x08
#define NABNC 0x04
#define NANBC 0x02
#define NANBNC 0x01

最小項 0xC0 將是 ABC|ABNC,最小項 0xE0 將是 ABC|ABNC|ANBC

但是,在使用圖形卡時,這並不明顯,只有某些非常特定的工作值。0xE0(不支援 0xC0)的值用於對影像進行一次無修改的複製。

BltBitMapRastPort 支援 0xC0,BltMaskBitMapRastPort 忽略它。

以下是繪製圖像的呼叫方法

BltBitMapRastPort (PBM, 0, 0, pWin-> RPORT, dest_x, dest_y, IMAGE_WIDTH, IMAGE_HEIGHT, 0xE0);

請記住,在使用函式 FreeBitMap () 退出程式之前,先釋放點陣圖。

請注意,AutoDoc FreeBitMap () 建議在釋放點陣圖之前呼叫 WaitBlit (),以確保沒有寫入它。

 
/* Spy is a toy to view the next screen as "iconified" in a window on the current screen (using graphics library BitMapScale function). */

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

#include <graphics/scale.h>

#include <stdio.h>

static const char version[] = "$VER: Spy 41.1.2 (29.08.2008) by Olivier Tigréat";

void redraw(struct Window *spy_window, struct BitMap *wbm, struct Screen *observed_screen);

void redraw(struct Window *spy_window, struct BitMap *wbm, struct Screen *observed_screen)
{
    
    struct RastPort temprp;
    InitRastPort(&temprp);
    temprp.BitMap = wbm;

    struct BitScaleArgs bms_args;
    bms_args.bsa_SrcBitMap = observed_screen->RastPort.BitMap;
    bms_args.bsa_DestBitMap = temprp.BitMap;
    
    bms_args.bsa_Flags = 0;

    bms_args.bsa_SrcWidth = observed_screen->Width;
    bms_args.bsa_SrcHeight = observed_screen->Height;

    bms_args.bsa_SrcX = 0;
    bms_args.bsa_SrcY = 0;
    bms_args.bsa_DestX = 0;
    bms_args.bsa_DestY = 0;
    bms_args.bsa_XSrcFactor = observed_screen->Width;
    bms_args.bsa_XDestFactor = spy_window->GZZWidth;
    bms_args.bsa_YSrcFactor = observed_screen->Height;
    bms_args.bsa_YDestFactor = spy_window->GZZHeight;

    BitMapScale(&bms_args);

    ClipBlit(             &temprp,                      0,                     0,
                spy_window->RPort, spy_window->BorderLeft, spy_window->BorderTop,
             spy_window->GZZWidth,  spy_window->GZZHeight,                0x00C0);

    DeinitRastPort(&temprp);

}

int main()
{
    int retval   = 0;                           /* Return code for main() (Shell error code) */
    int closewin = FALSE;                       /* Flag used to end program */
    struct IntuiMessage *imsg;                  /* Structure to store Intuition message data */
    ULONG signals;                              /* User interaction reported by signals */
    struct Screen *screen = NULL, *observed_screen = NULL;
    struct Window *spy_window = NULL;           /* Our Spy window  */
    struct BitMap *scaledBitMap = NULL;         /* BitMap structure for scaled representation */
    IPTR depth = 0 ;

        
    if (NULL == (screen = LockPubScreen(NULL)))
    {
        retval = RETURN_ERROR;
        puts("LockPubScreen() failed to lock current screen");
    }
    
    else
        depth = GetBitMapAttr(screen->RastPort.BitMap, BMA_DEPTH);
        
    if (depth == 0)
    {
        retval = RETURN_ERROR;
        puts("GetBitMapAttr() failed to get depth of screen");
    }
    
    else
        observed_screen = screen->NextScreen;
        
    if (!(scaledBitMap = AllocBitMap(                   screen->Width,
                                                       screen->Height,
                                                                depth,
                                                      BMF_DISPLAYABLE,
                                     observed_screen->RastPort.BitMap) ) )
    {
        UnlockPubScreen(NULL,screen);
        retval = RETURN_ERROR;
        puts("AllocBitMap() failed to allocate/initialise BitMap");
    }
    
    else
    {
        struct TagItem initial_tags[] = 
        {
            {          WA_Width , 160                                  },
            {         WA_Height , 120                                  },
            {           WA_Left , 400                                  },
            {            WA_Top , screen->BarHeight + 1                },
            {       WA_BackFill , (IPTR)LAYERS_NOBACKFILL              },
            {  WA_GimmeZeroZero , FALSE                                },
            {    WA_SizeBBottom , TRUE                                 },
            {        WA_DragBar , TRUE                                 },
            {        WA_RMBTrap , TRUE                                 },
            {    WA_DepthGadget , TRUE                                 },
            {    WA_CloseGadget , TRUE                                 },
            {     WA_SizeGadget , TRUE                                 },
            {  WA_NoCareRefresh , TRUE                                 },
            {          WA_IDCMP , IDCMP_CLOSEWINDOW|IDCMP_CHANGEWINDOW },
            {       WA_MinWidth , 80                                   },
            {      WA_MinHeight , 80                                   },
            {       WA_MaxWidth , -1                                   },
            {      WA_MaxHeight , -1                                   },
            {          WA_Title , (IPTR)"Spy"                          },
            {       WA_BackFill , (IPTR)LAYERS_NOBACKFILL              },
            {                     TAG_DONE                             }
        };
        
        
        if ( !(spy_window = OpenWindowTagList(NULL,initial_tags)))
        {
            UnlockPubScreen(NULL,screen);
            closewin = TRUE;
            retval = RETURN_ERROR;
            puts("OpenWindowTags() failed to open spy window");
        }
        
        else
        {
            UnlockPubScreen(NULL,screen);
            redraw(spy_window,scaledBitMap,observed_screen);
    
            while((closewin == FALSE))
            {
                signals = Wait(1L << spy_window->UserPort->mp_SigBit | SIGBREAKF_CTRL_C); /* Wait for an event! */
                if (signals & (1L << spy_window->UserPort->mp_SigBit))
                {
                    while ((imsg = (struct IntuiMessage *)GetMsg(spy_window->UserPort)))
                    {
                        switch (imsg->Class)
                        {
                            case IDCMP_CLOSEWINDOW:                     /* Check here if Close Window selected */
                                closewin = TRUE;                        /* so while loop will end there */
                                break;
                            case IDCMP_CHANGEWINDOW:
                                redraw(spy_window,scaledBitMap,observed_screen);
                                break;
                            case IDCMP_REFRESHWINDOW:
                                redraw(spy_window,scaledBitMap,observed_screen);
                                break;
                            default:
                                puts("Unknown IDCMP message");
                        } /* switch (imsg->Class) */
                           ReplyMsg((struct Message *)imsg);
                       } /* while ((imsg = (struct IntuiMessage *)GetMsg(spy_window->UserPort))) */
                } /* if(signals & (1L << spy_window->UserPort->mp_SigBit)) */
                if (signals & SIGBREAKF_CTRL_C)
                {
                    puts("Spy execution aborted with CTRL_C signal");
                    closewin = TRUE;
                } /* if (signals & SIGBREAKF_CTRL_C) */
            } /* while((closewin == FALSE)) */
        } /* else after if( !(spy_window... */
    } /* else after else if (!(scaledBitMap... */
    
    if (closewin == TRUE)
    {
        if (scaledBitMap) FreeBitMap(scaledBitMap);
        if (spy_window) CloseWindow(spy_window);             /* Close window */
        spy_window = NULL;
    }

    if(retval)
    {
        PrintFault(IoErr(), "spy");
    }
    return retval;
}

使用 256 色 IFF 到 C,調色盤主要是黑色,但螢幕處於真彩色模式?影像資料僅包含筆號。IFF2C 不會建立顏色表嗎?這只是一個關於框的圖片。PPaint 為我提供了一個包含 256 個值的陣列,標記為“調色盤”。如何將其放入螢幕調色盤?

是否需要分別從影像中提取調色盤,如果是,如何設定我的螢幕以使用它?你可以使用 OpenScreenTags() 的 SA_Colors 屬性。或者,你可以使用 graphics.library 中的 LoadRGB32()。另外:影像資料必須是 (UBYTE *) 而不是 (UWORD *),否則由於端序錯誤會導致影像損壞。

我的思路是否正確?是否有更簡單的方法來實現?這取決於你真正想做什麼。如果你想載入影像並將其 blit 到螢幕上,使用 Datatype 系統可能更好。

從技術上講,struct BitMap 應該在 MEMF_PUBLIC 中分配,而位平面應該在 MEMF_CHIP 中分配。這樣,指向位平面的指標就可以位於快速 RAM 中,而位平面本身不會位於快速 RAM 中。作為臨時解決方法,建議在 pc-i386 上使用 MEMF_ANY 分配位平面。無論如何,是否有必要從 chipmem 分配位平面,因為據我所知,可顯示的點陣圖是在 68k 上透過 HIDD 分配的?struct BitMap 不應該與其位平面獲得相同的記憶體型別嗎?

你將 bltmask 設定為晶片 RAM 中與要 blit 的點陣圖大小相同的字對齊的單位元平面。掩碼中的 0 表示不復制任何內容,而 1 表示將源點陣圖複製到目標點陣圖。

可以使用掩碼(BltMaskBitMapRastPort(),它透過掩碼將矩形區域從點陣圖移動到 RastPort - 軟體渲染)實現透明效果。

只需將一個“無層”rastport指向它,開銷就會很低。某些簿記將得到尊重,例如rastport掩碼。大多數rastport例程首先要做的事情是檢查rastport上是否掛著層,如果有,它們就會進入一種剪下型別的東西。BltMaskBitMapRastPort()以非最佳方式執行其功能,因此它可以執行分層操作。為層掩碼或其他內容保留一個源運算元。

描述如何複製影像的最小項值(支援的值為 ABC、ABNC 和 ANBC)

#define ABC 0x80
#define ABNC 0x40
#define ANBC 0x20
#define ANBNC 0x10
#define NABC 0x08
#define NABNC 0x04
#define NANBC 0x02
#define NANBNC 0x01

將一個通道指定為“切換”源和背景的最小項必須包含 4 個項。(2 個包含“掩碼設定” && 源,2 個包含“掩碼清除” && 背景)

但是,在使用圖形卡時,這並不明顯,只有某些非常特定的工作值。0xE0(不支援 0xC0)的值用於對影像進行一次無修改的複製。

最小項 0xC0 將是 ABC|ABNC,最小項 0xE0 將是 ABC|ABNC|ANBC。BltBitMapRastPort 支援 0xC0,BltMaskBitMapRastPort 忽略它。0xC0 是一個“與”最小項 - 結果是通道 A 和 B 的“與”運算。

您不能相信函式使用的“最小項”與實際 blit 中使用的“最小項”相同。

{
/* printf("%s: mask= %p\n", __FUNCTION__, mask); */
if (mask) {
BltMaskBitMapRastPort(bm, 0, 0, _rp(obj), dst_x, dst_y, w, h, ABC|ABNC|ANBC, mask);
} 
else 
{
BltBitMapRastPort(bm, 0, 0, _rp(obj), dst_x, dst_y, w, h, ABC|ABNC);
}
}
 	
if (scaled_bm) {
WaitBlit();
FreeBitMap(scaled_bm);
}
 	
return 0;
}

交錯 blit 僅影響不透明 blit,因為掩碼必須與交錯透明 blit 上的源影像一樣大。無論透明 blit 如何儲存,都會以非交錯模式執行。此外,在分配點陣圖/螢幕時,必須使用特定標誌請求交錯模式。

如果源和目標點陣圖是交錯的,則 BltMaskBitMapRastPort() 的掩碼 也必須是交錯/重複的。目前尚不清楚這是否是錯誤或功能。如果您嘗試從交錯 blit 到交錯 blit,則必須使用這些可怕的重複掩碼之一。使掩碼也交錯,即在下一行之前重複掩碼中的所有行 次(這意味著包含與源點陣圖一樣多的平面),依此類推。

這意味著我必須建立一個大小為 word_aligned_width*height*depth 位的塊作為掩碼嗎?是的,但前提是源點陣圖是交錯的。基本上,您必須在掩碼中重複每行 次。解決此問題的變通方法

1-plane mask         interleaved mask in case of 3-plane source bm

11110000             11110000
11001100             11110000
00001111             11110000
                     11001100
                     11001100
                     11001100
                     00001111
                     00001111
                     00001111

動畫

[edit | edit source]

Amiga 的特殊之處在於,與其他作業系統相比,它的作業系統更緊密地適應了硬體的工作方式(與硬體的抽象程度更低)。因此,現在很多後續內容僅為了向後相容。

精靈

[edit | edit source]

大多數精靈內容(滑鼠指標 #0)已幾乎完全從 graphics.library 的處理中移除。為了提供程式碼重用,僅保留了 AllocSpriteData()。其餘部分在 monitorclass 中完成,它更適合在那裡,並且可以用比使用 graphics.library 精靈處理更簡單的方式完成很多事情。

struct GelsInfo
{
    BYTE sprRsrvd;                     /* flag of which sprites to reserve from vsprite system */
    UBYTE Flags;                       /* system use */
    struct VSprite *gelHead, *gelTail; /* dummy vSprites for list management*/
    WORD *nextLine;                    /* pointer to array of 8 WORDS for sprite available lines */ 
    WORD **lastColor;                  /* pointer to array of 8 pointers for color-last-assigned to vSprites */ 
    struct collTable *collHandler;     /* addresses of collision routines */
    WORD leftmost, rightmost, topmost, bottommost;
    APTR firstBlissObj,lastBlissObj;    /* system use only */
};

AmigaOS(TM) 獲取精靈資料並在您的程式初始化時將其複製到其中,然後當您需要移動或顯示它們時,您請求作業系統使用一些精靈,使用 GetSprite;當不再需要看到它們時,您釋放精靈,當不再需要精靈圖形時,您釋放精靈資料。

AmigaOS(TM) FreeSprite 釋放了您為 Viewport 使用 GetSprite 保留的 8 個硬體精靈中的一個;將其返回以供作業系統(或需要使用精靈的其他程式)使用。FreeSpriteData 應釋放包含精靈結構資料的記憶體 - 精靈的畫素資料等。

硬體

[edit | edit source]

AmigaOS(TM) 曾經有一個名為 InitGels() 的函式,它啟動 VSprite,但目前在 AROS 中沒有實現...

   struct VSprite  *vsHead;
   struct VSprite  *vsTail;
   struct GelsInfo *gInfo;
   InitGels(vsHead, vsTail, gInfo);

簡單精靈始終為 16 位寬(sprite.h)

GetSprite()  Attempts to allocates a sprite for exclusive use
ChangeSprite()  Modifies a Simple Sprite's image data
MoveSprite()  Changes a Simple Sprite's position
FreeSprite()  Relinquishes a sprite so it can be used by others

makeVSprite() 和 freeVSprite() 函式

虛擬

[edit | edit source]

AROS 有 VSprites (gels.h),但它們僅供滑鼠指標 (精靈 #0) 使用,它將它們轉換為簡單精靈並顯示它們。

struct VSprite {
    struct VSprite *NextVSprite;  /* system only */
    struct VSprite *PrevVSprite;
    struct VSprite *DrawPath;
    struct VSprite *ClearPath;
    WORD            OldY, OldX;
    WORD            Flags;        /* */
    WORD            Y, X;         /* */
    WORD            Height;
    WORD            Width;
    WORD            Depth;
    WORD            MeMask;       /* */
    WORD            HitMask;
    WORD           *ImageData;
    WORD           *BorderLine;
    WORD           *CollMask;
    WORD           *SprColors;
    struct Bob     *VSBob;
    BYTE            PlanePick;    /* */
    BYTE            PlaneOnOff;
    VUserStuff      VUserExt;
    };

與 Amiga 的 Blitter 晶片相關,因此實際上只在 AROS m68k 埠中實現...

struct Bob
  {
  WORD               Flags;     /* general purpose flags                 */
  WORD              *SaveBuffer;/* buffer for background save            */
  WORD              *ImageShadow; /* shadow mask of image                */
  struct Bob        *Before;   /* draw this Bob before Bobs on this list */
  struct Bob        *After;     /* draw this Bob after Bobs on this list */
  struct VSprite    *BobVSprite;/* this Bob's VSprite definition         */
  struct AnimComp   *BobComp;   /* pointer to this Bob's AnimComp def    */
  struct DBufPacket *DBuffer;   /* pointer to this Bob's dBuf packet     */
  BUserStuff         BUserExt;  /* Bob user extension                    */
  };

碰撞

[edit | edit source]

AROS 有 SetCollision() 函式....

字型渲染

[edit | edit source]
這裡

void Text(struct RastPort *rp, CONST_STRPTR string, ULONG count)

void SetFont(struct RastPort *rp, struct TextFont *textFont)

struct TextFont {
    struct Message tf_Message; /* reply message for font removal */
                               /* font name in LN       | used in this */
    UWORD   tf_YSize;          /* font height           | order to best */
    UBYTE   tf_Style;          /* font style            | match a font */
    UBYTE   tf_Flags;          /* preferences and flags / request. */
    UWORD   tf_XSize;      /* nominal font width */
    UWORD   tf_Baseline;   /* distance from the top of char to baseline */
    UWORD   tf_BoldSmear;  /* smear to affect a bold enhancement */

    UWORD   tf_Accessors;  /* access count */

    UBYTE   tf_LoChar;     /* the first character described here */
    UBYTE   tf_HiChar;     /* the last character described here */
    APTR    tf_CharData;   /* the bit character data */

    UWORD   tf_Modulo;     /* the row modulo for the strike font data */
    APTR    tf_CharLoc;    /* ptr to location data for the strike font */
                           /*   2 words: bit offset then size */
    APTR    tf_CharSpace;  /* ptr to words of proportional spacing data */
    APTR    tf_CharKern;   /* ptr to words of kerning data */
};

需要在寫入文字之前使用 SetDrMd(rp,mode) 設定繪製模式。但是,如果我使用 SetRPAttrs 設定和 SetDrMd 繪製,則背景不會顯示,但文字不會重新整理,並且會反覆重繪,最終變得無法閱讀。必須在繪製新文字之前重新整理背景。

為了渲染字型,我們使用 BlitColorExpansion() 方法。為了加速,傳遞給此方法的源點陣圖必須透過相同的驅動程式分配。第一個可能的(也是最簡單的方法)是為每個驅動程式儲存一個單獨的字型點陣圖。我真的很不喜歡它,因為它會浪費大量的記憶體。

如果點陣圖是使用 PutTemplate() 方法建立的。那麼為什麼不能直接使用 PutTemplate() 生成文字呢?如果我們仔細觀察,會發現 BltTemplate() 在某些情況下已經使用(用於軟體生成的斜體和下劃線樣式)。所以也許只需實現加速的 PutTemplate() 和 PutAlphaTemplate() 並完全放棄 BlitColorExpansion() 就可以了?

已刪除 font->bitmap 轉換和 BlitColorExpansion() 支援。現在 BltTemplate() 用於字型渲染。

BltTemplate — 在 RastPort 中的矩形中繪製形狀。

BltTemplate(SrcTemplate, SrcX, SrcMod, rp, DstX, DstY, SizeX, SizeY)

此函式以當前顏色和繪製模式在指定位置將模板中的影像繪製到 RastPort 中。假設模板不與目標重疊。

如果模板超出 RastPort 邊界,則將其截斷到該邊界。

注意:SrcTemplate 指標應指向模板掩碼的“最近”字(向下取整)。掩碼的精細對齊是透過在 0 到 15 十進位制範圍內設定 SrcX 位偏移量來實現的。

 SrcTemplate  - pointer to the first (nearest) word of the template mask.
 SrcX         - x bit offset into the template mask (range 0..15).
 SrcMod       - number of bytes per row in template mask.
 rp           - pointer to destination RastPort.
 DstX, DstY   - x and y coordinates of the upper left corner of the destination for the blit.
 SizeX, SizeY - size of the rectangle to be used as the template.

SetAPen() 設定前景顏色 SetBPen() 設定背景顏色 SetDrMd() 設定繪製模式 Text() 將一些文字寫入視窗 TextLength() 估計文字塊的畫素長度 RectFill() 繪製一個矩形 SetFont() 將字型設定為 rastport SetSoftStyle() 設定字型的樣式(粗體、斜體等) Move() 將某種不可見的“海龜”設定為 rastport Draw() 從最後一個“海龜”點繪製一條線到此點

在文字框中滾動時,您可以重新繪製所有內容,也可以使用 ScrollWindowRaster() 僅重新整理滾入的內容。當然,滾動只有在滾動事件滾動的距離小於可見頁面時才有意義。

將視窗層回填鉤子設定為 NULL。然後,AmigaOS 將不會用當前背景顏色(通常為筆 #0)填充損壞的區域。如果您始終注意重新整理,則可以透過這種方式完全避免閃爍。

w:Aros/Developer/Docs/Examples/GfxLibraryExample

文字編輯器

[edit | edit source]

通常,您將整個文字儲存在內部緩衝區中,然後僅繪製可見的緩衝區部分。您分別繪製每個部分,並在繪製部分之前設定字型和顏色。

您應該做的是根據儲存在記憶體中的文字和指示您滾動距離的值繪製文字。稍後,您可以新增最佳化措施,以避免重新繪製整個視窗,方法是使用 blitter 滾動已經可見的部分。

我是否需要使用視窗的 rastport?是的,並使用 WFLG_GIMMEZEROZERO 標誌視窗。使用 ClearEOL() 和 ClearScreen() 清除行尾和螢幕的其餘部分。這些是來自 graphics.library 的函式,非常適合與文字編輯器一起使用。

如何在視窗中獲得游標?您可以使用 SetAPen() 和 SetBPen() 鍵入字母,或者使用 SetDrMd() 和 COMPLEMENT。

如何儲存從視窗中滾出的文字?您將文字儲存在邏輯文字部分的緩衝區中(顯示的是物理部分)。在文字編輯器中儲存緩衝區的最佳方法是將其儲存在字串列表中。

如何在文字的同一行/行中使用不同的顏色?這很簡單。使用 Text() 寫入文字,RastPort 的內部游標將使您移動到單詞/單詞的末尾。使用 SetAPen() 和 SetBPen() 更改顏色,然後寫入行的其餘部分。

文字處理器

[edit | edit source]

如何在文字的同一行/行中使用不同的字型?這很棘手!然後您想製作 Word 或 WordWorth 型別的程式。您必須編寫適當的函式來涵蓋這一點。它比簡單的文字編輯器(非文字處理器)需要更多努力。

坦白說,我認為顯示的細節與程式的其餘部分相比並不重要——從鍵盤、滑鼠和 GUI 輸入接收輸入,維護當前文字資料庫,決定如何處理視窗大小的變化。例如,文字是換行還是在右邊緣被截斷?如果是換行,那麼您需要在每側的行的之間顯示額外的行,並且您必須將該新的部分行插入資料庫中。

如果您認真對待這項工作,可以先設計和實現資料庫。您可以始終使用現有的工具和類顯示內容。然後,稍後您可以編寫所有 WYSIWYG 函式以很好地顯示它。

文字完全儲存在一個文字緩衝區中。您在視窗上繪製文字緩衝區中可見的部分,以滿足需求。請不要引入一個包含可見文字的第二個緩衝區的概念。

您需要快速訪問文字,逐行訪問。一個建議是使用一個指向字串的指標陣列。每個指標都指向一行文字。當您插入或刪除一行時,您只需要移動指標陣列,而不需要移動整個文字。即使文字的大小為 GB,這也非常快,並且開銷非常低。當您將文字載入到記憶體時,它也非常快。您可以將所有內容載入到一個塊中(如果需要,也可以載入到幾個大塊中),並只設置索引陣列中的指標。然後用 0 位元組替換返回值,或者編寫您的視覺化內容,以表示您尊重返回值。如果一行被編輯並且變大,它會從記憶體池中分配自己的記憶體緩衝區。

但是,在 AmigaOS 環境中,一個更簡潔的方法是為每一行文字使用一個 Exec List 節點。在重新繪製顯示時,遍歷 List 的速度與遍歷表格一樣快。另一方面,插入/刪除(行)操作變得微不足道,因為您不必更改指向其他行的任何指標。緩衝區中的所有文字都可以儲存在一個單一列表中,每行一個節點。要顯示列表的一部分,您只需要維護幾個指標,一個指向視窗中第一行的節點,另一個指向最後一行的節點。每當文字滾動時,您就使用 Prev() 和 Next() 呼叫一次移動一個指標。困難的部分是保持對跨越兩行或多行的文字行的控制。每當視窗寬度或字型大小發生改變,或者使用者在某一行插入文字時,您必須重新訪問文字在受影響行之間的分割。無論您使用查詢表還是 List,問題都是一樣的。

但是,列表的開銷更大。當編輯小文字檔案時,所有方法都沒有問題。當文字檔案非常大時,問題就開始了。許多文字編輯器在這裡速度很慢,例如,如果您載入一個 1 GB 的文字檔案。構建這樣的連結串列所花費的時間比陣列要多。在陣列中的插入或刪除成本沒有那麼高,請記住,現在的 CPU 每秒可以移動 GB 級別的記憶體,並且與鍵入字元相比,插入刪除操作很少見。

需要一些與文字一起的格式化資訊。格式化資訊直接儲存在行的文字中。

額外的函式應該首先保留/鎖定當前由 MOS/OS4 擴充套件使用的 LVO,然後在最後保留一個 LVO 塊(100 個?)。在這個塊之後,可以新增 AROS 函式。

OrRectRegionND() ClearRectRegionND() OrRegionRegionND() ClearRegionRegionND() XorRegionRegionND() XorRectRegionND() AreRegionsEqual() ScrollRegion() (*) SwapRegions() BltRastPortBitMap() (*) ShowImminentReset() (**)

除了最後一個之外,我認為其他函式都是公共擴充套件/改進,而不是私有函式。例如,“ND”代表“非破壞性”。原始的區域函式都會將結果區域“返回”到源區域之一(即它們修改/破壞它)。

AndRegionRegion():

   R2 = R1 intersected with R2;

The ND versions don't do that. AndRegionRegionND():

   R3 = R1 intersected with R2;

當然,您可以使用標準(舊的)區域函式來模擬這一點,但是僅僅因為您可以使用大量的 WritePixel() 來模擬 RectFill(),並不意味著移除 RectFill() 是一個好主意。

DPaint(1-3)使用 RectFill() 在 JAM2 模式下手動填充工具區域。這毫無意義,JAM2 應該覆蓋所有內容。經過多次測試後,我終於找到了原因:DPaint 直接指向 RastPort 並修改了 RastPort->mintern[0] 值,以便位平面 0 被反轉,但位平面 1 按正常方式繪製。AOS 顯然在每次 SetAPen()、BPen、DrMd 呼叫後重新計算所有 mintern 值,這些值隨後被使用 blitter 的任何繪圖例程使用。(mintern[0] = plane0, mintern[1] = plane1 等)可能不值得麻煩去實現,但它是一個有趣的實現預設值。(這甚至在 OS39 上也能工作)。

以不影響 MOS/OS4 未來相容性的方式擴充套件 3.x 庫的主題已列入 ABI V1 的議程。

建議將盡可能多的內容從核心庫中移出,並放入一些新的元件中。例如,這些區域操作函式可以移動到類似 gfxutils.library 的東西中。此外,這將減小 Kickstart 的大小。

我認為,所有 API 擴充套件都應該經過仔細設計,而不是僅僅因為某個應用程式的作者說這將是一件好事就將其作為駭客來實現。如果我們仔細研究這些函式,我們可以注意到它們 99% 的程式碼是重複的。例如,AndRegionRegionND() 事實上僅僅是

struct Region *r3 = CopyRegion(r1);
AndRegionRegion(r3, r2);

檢視內部結構,我們可以認為 CopyRegion() 是一個非常有用的函式,因為它不僅僅是兩三行程式碼,而且沒有真正的替代方案。所以應該保留。這樣,我們可以減少擴充套件的數量。

另一個例子是 dos.library 的 SetError() 函式。在內部,它是兩行程式碼。此外,它恰好被啟動程式碼使用。目前這還不錯,但是當 m68k AROS 出現時,這意味著在 m68k AROS 下構建的應用程式將無法在例如經典 AmigaOS 上執行,即使使用版本檢查也是如此。這個函式完全可以移到 libamiga.a 中。此外,它可以被重新命名為 SetErrorOutput() 以實現 AmigaOS4 相容性。

http://www.amigacoding.com/index.php/Graphics.library

看一下 struct MonitorSpec 中的 ms_transform() 和 ms_translate() 回撥。名稱暗示了它們的目的是以某種方式轉換螢幕座標。這意味著我們的圖形子系統可以在一些其他的座標(而不是畫素)中工作,自動處理螢幕縱橫比等?查看了 MorphOS 程式碼,ms_translate() 是一個存根,它只是將一個 Rectangle 結構複製到另一個 Rectangle 結構。ms_transform() 只是返回。

在實現 GetMonitorList() 和 FreeMonitorList() 時,注意到它們的原始 LVO 已經被 StartScreenNotifyTagList() 和 EndScreenNotify() 函式使用。LVO 不會與任何東西發生衝突,除了兩個私有的 AmigaOS v3 函式,它們用於將 DisplayInfo 新增到系統中。它們被基於磁碟的影片模式驅動程式使用(DEVS:Monitors 的內容)。

  • monitorclass 是一個 BOOPSI 類,不是我發明的。
  • 為了建立一個 BOOPSI 物件,我們必須呼叫 intuition.library/NewObject()。
  • 在 AROS 中,新增顯示驅動程式是透過 graphics.library/AddDisplayDriverA() 完成的,這是一個 AROS 特定的函式(因為在其他作業系統中沒有這個函式的公共等效項)。
  • monitorclass 物件的建立需要以某種方式與 AddDisplayDriverA() 繫結。
  • 如果我們實現一些其他的 AROS 特定的 API,那麼我們實際上不需要 monitorclass,我們可以直接基於這個 API。

在以前的版本中,同步物件和 MonitorSpec 是獨立的實體。graphics.library 列舉所有同步物件,併為它們建立相應的 MonitorSpec。存在以下缺陷

  • 在 MonitorSpec 或同步發生改變後,需要同步資料。
  • 資料重複(50% 的同步物件資料重複了 MonitorSpec 資料)。
  • 需要大量的程式碼來複制重複的資料。
  • 由於(2),記憶體碎片過多。

此外,存在嚴格的關係“一個同步 == 一個 MonitorSpec”。同步物件需要知道相關的 MonitorSpec,而 MonitorSpec 需要知道相關的同步物件。這進一步讓我想到,MonitorSpec 可以完全合併在一起。這樣,它將以更好的方式進行管理(例如,更好地實現可變/常量同步物件,以及更好地處理沒有 SpecialMonitor 新增的 MonitorSpec)。使 MonitorSpec 自注冊的解決方案變得非常明顯。這允許擺脫新增/刪除程式碼。當一個顯示驅動程式被釋放時,它的同步物件會被釋放,這會導致關聯的 MonitorSpec 從 graphics.library 列表中自動移除。

監視器驅動程式是另一個令人沮喪的章節——關於它們的文件一無所有,只有一組 gfx 庫中的鉤子和視窗結構(IIRC),顏色表完全沒有文件,並帶有大量有效負載,這些有效負載被塞入其中,因為檢視和視窗被完全記錄並且無法擴充套件。

現在移到了 monitorclass

GfxNew() 和 GfxFree() 也是由 Commodore 發明的。事實上,可以使用 AllocMem()/FreeMem(),但由於存在一些程式碼重複,決定不這樣做。

但是,使用者介面上的操作在內部會轉換為點陣圖上的操作。螢幕上的操作會轉換為視窗上的操作。graphics.library 中缺少一些功能,但在 HIDD API 中存在,並且可以安全地使用它(這些是資訊查詢呼叫,而不是渲染呼叫)。

GetDisplayInfoData() 不提供這種合成能力資訊。GetDisplayInfoData() 在保留欄位中返回所需的指標(這最初是為 CGX 實現的)。然而,這裡我們有一個小問題...

顯示驅動程式使用 graphics.library/AddDisplayDriverA() 註冊自己。但是,Intuition 如何知道註冊了一個新驅動程式(以便建立 monitorclass 物件)呢?

再次有以下解決方案

  • 驅動程式可以呼叫 Intuition 的函式(反過來將呼叫圖形函式)。
  • 圖形可以呼叫 Intuition 的一些函式來建立一個 monitorclass 物件。
  • Intuition 可以修補 AddDisplayDriverA() 以新增自己的程式碼。
  • 顯示驅動程式可以自己建立 BOOPSI 物件。

我對它們的看法

  • 這將真正使圖形在沒有 Intuition 的情況下無法執行(無法新增顯示驅動程式)。此外,它不會減少 AROS 特定擴充套件的數量(看看 include/graphics/driver.h - 這些是絕對需要的,並且它們的數量會增加)。
  • 這就是我打算做的事情。
  • 討厭作業系統自我修補!!!尤其是在沒有補丁的情況下可以做到這一點時。此外,graphics.library 需要在它的 DisplayInfoDataBase 中保留一個指向 monitorclass 物件的指標(以便 Intuition 可以透過模式 ID 來查詢它)。
  • 這會導致每個驅動程式中的程式碼重複,這很糟糕。這種方法傾向於變成 OS 3.1 中使用顯示驅動程式的方式。

此外,我必須將這段程式碼新增到每個顯示驅動程式中,這是一個費時費力並且破壞了向後相容性的工作。

相信在 MorphOS 中,所有這些都是由 cgxsystem.library 管理的。在那裡(就像在經典的 AmigaOS 中一樣),DisplayInfoDataBase 只是一個靜態列表,而 Intuition 似乎還有一個靜態列表。CGX 只建立所需的專案,並將它們全部推入各自的列表中。我們只在一個地方有所不同——我們沒有 cgxsystem.library(它完全是 CGX 的私有庫),並且此功能已合併到 graphics.library 中。

AROS 並沒有新增新的公共庫函式。它添加了一個新的公共 BOOPSI 類,它更容易避免衝突,特別是如果決定實現 MorphOS 二進位制相容性的話。

看起來圖形庫的故事並不比 dos 庫的故事遜色。一些跡象表明,Amiga graphics.library API 只是對底層東西的封裝。例如,GetDisplayInfoData() 的內部實現很可能是基於標籤列表的,並且看起來還有更多選項可以查詢。

瞭解更多資訊,請點選這裡

關於 graphics.library 程式碼,有兩點需要注意:

  • 已經支援 RAM(包括 ChipRAM)中的平面點陣圖。
  • graphics.library 從池中分配臨時平面點陣圖 HIDD 物件,並將點陣圖附加到它們以對它們進行操作。

這意味著你可以

  • 為 planarbm 類新增一些屬性來處理可顯示的點陣圖(那些具有銅列表的點陣圖)。除了點陣圖之外,還應該將銅列表附加到臨時物件。
  • 實現一個驅動程式,它能夠使用 Show 或 ShowViewPorts 方法來顯示這些物件。

對於 ABI v1,graphics/displayinfo.h 中 struct QueryHeader 中的所有欄位應該從 ULONG 更改為 IPTR。這是因為最初這個結構是兩個 TagItems。在某些情況下,它可以使用 utility.library 中的標籤列表函式進行處理。

背後的想法是,我們為每個 RastPort 附加了一個 GC(圖形上下文)HIDD 物件。這個物件需要分配/釋放。在早期,CreateRastPort() 和 DeleteRastPort() 做了這件事。如今,GC 物件在第一次嘗試使用 RastPort 時自動分配。然後,這個物件被快取,並附帶一個使用計數器。當一些繪圖操作開始時,使用計數器會遞增。當操作結束時,它會遞減。這些物件應該被一些垃圾收集器銷燬,但還沒有實現。一個 DeInitRastPort() 函式存在,它強制進行 GC 銷燬。因此,實際上,CreateRastPort() 和 DeleteRastPort() 已過時。

與 AOS 不同,AROS 需要一個 rastport 清理函式 (DeInitRastPort()),否則可能會發生記憶體洩漏。這就是為什麼程式碼為尚未存在的 rastport 垃圾收集器做好準備的原因。對於在移植程式碼中忘記使用 DeinitRastPort() 的情況(或者理論上對於具有理論 68k 模擬器的 68k 二進位制檔案)。但是垃圾收集器永遠無法確定一個 rastport 是否確實已死,並且永遠不會再次使用。因此,即使在殺死 driverdata/gc_object 之後,也可能在一段時間後再次使用 rastport。在這種情況下,必須從 RastPort 結構中的資訊重新建立 driverdata/gc_object。

driverdata/gc_object 垃圾收集可能會有一些負面影響,所以想法是隻對手動建立(或克隆)的 rastport 使用它。但不是對使用 CreateRastPort() 或 CloneRastPort() 建立的 rastport 使用,因為在這種情況下,程式設計師會知道他們必須使用 DeleteRastPort() 來釋放它。其中一個負面影響可能是速度,但也可能是使用了一些新的 AROS rastport 功能(如裁剪矩形),這些功能沒有儲存在 RastPort 結構中(而是儲存在 DriverData 結構中),因此在 driverdata/gc_object 被垃圾收集殺死但 rastport 稍後再次使用的情況下無法重新建立。所以在這種情況下,應用程式必須使用 CreateRastPort() 或 CloneRastPort() 來防止垃圾收集發生。

RastPort 清理和 DeinitRastPort() 的要求正在開發中。

當你想要新增一些新功能並且私有空間已滿時該怎麼辦?與現在使用 ClipRect 一樣。設定擴充套件屬性會分配擴充套件空間。在此之後,是的,你需要 deinit。在 x86-64 上添加了更多私有空間。!!! 二進位制相容性已破壞 !!! 刪除了 PatOrigin 屬性以釋放 RastPort 中可用的空間。沒有找到它們背後的理由,只需調整圖案起始地址即可。

圖案大小假定等於源點陣圖。所以,如果點陣圖的大小為 (x, y),而我們不是從 (0, 0) 開始,而是從某個偏移量開始,它將從哪裡獲取額外的畫素呢?好吧,這樣的功能可以更好地作為具有額外引數的獨立函式來實現。Origin 用於圖案的對齊方式 == 就像圖案的迴圈滾動。例如,如果你有一個棋盤格圖案,你可能希望它以這樣的方式對齊,使其“開始”正好位於內部視窗區域的 (x,y) 處,這取決於視窗邊框大小,因為大多數視窗是非 GZZ 的,(0,0) 在視窗邊框上方。

考慮按設計破壞的 ClipRect 刪除。在很多情況下都不可用,並且維護它會帶來很多麻煩。也許我說得太苛刻了。但是,第一個問題。新增它的理由是什麼?因為在很多情況下,擁有像這樣的裁剪支援比 layers.library/InstallClipRegion() 更加容易和快速。因為當你在一個部分隱藏的智慧重新整理層中安裝裁剪區域時,這甚至可能導致在層裁剪矩形點陣圖之間來回 blit。

我腦海中的主要用途是用於在多列列表檢視中裁剪 Text() 之類的東西,即在短時間內可能進行大量裁剪的地方。其他作業系統也有它。但 IMHO 它們有它是因為繪圖的理念截然不同。這些作業系統中沒有後臺儲存。實際上,沒有類似於 Layers 的東西;當一個視窗開啟時,它只是佔據了螢幕點陣圖的一部分,而隱藏的部分就消失不見了(是的,程式設計師每次都必須重新繪製它)。就像 AOS 中的簡單重新整理視窗(這也是在 AROS 中執行效果最好的視窗,因為智慧重新整理視窗缺乏一些最佳化,以避免諸如備份/恢復螢幕外裁剪矩形點陣圖之類的事情,即使層操作根本沒有影響它們)。但如今,即使是這些作業系統都支援後臺儲存,因為它們需要它來進行合成。

如果我們在一個部分覆蓋的智慧重新整理視窗上安裝 ClipRegion,就會建立兩組遮擋的 ClipRects。第一組是從整個視窗建立的,第二組表示第一組與 ClipRegion 的交集。因此,第二組中的 ClipRects 是第一組的子裁剪矩形,並且它們具有重複的儲存點陣圖。每次移動視窗時,我們都必須將這些片段重新組合,這需要兩組 blit。這很慢。但如果我們擴充套件 ClipRects,使其能夠引用已存在點陣圖的一部分呢?這樣,第二組(裁剪)中的 ClipRects 就可以重複使用第一組的儲存點陣圖。這將消除不必要的 blit 並減少記憶體使用量。這種最佳化將使它對現有應用程式透明地工作,除非其中一些應用程式透過手動遍歷 ClipRects 來進行渲染。此外,ClipRegion 允許使用比一個矩形更復雜的形狀。

為什麼很麻煩?因為讓它正常工作需要大量的新增內容。你知道 layers.library 的 DoHookClipRect() 函式嗎?它應該做與 do_render_func() 目前做的一樣。只是它忽略了這個 ClipRect,它不知道它。希望在 RastPort 上實現一些複雜操作的公眾,預計會使用它。並且,如果有人想在 RastPort 上設定一個 ClipRect,這將使其無法正常工作。對於這樣的特殊情況,我可能會使用 SetRPAttrs() 使 rastport 標誌可變,該標誌告訴像 DoHookClipRects() 這樣的函式是否應用 rastport 裁剪矩形。回撥函式本身不應該處理 rastport 裁剪矩形本身。在編寫 RPTAG_ClipRectangle 之後的一段時間添加了它,因為它是一個簡單的擴充套件(沒有裁剪矩形?-> 假設點陣圖邊界是裁剪矩形),我發現應用程式可以在點陣圖之外渲染總是很愚蠢。

  • RastPort 變得自包含。不再需要額外的資料,這些資料需要顯式釋放。GC 物件內建在 RastPort 中。因此,GC 操作快得多。
  • CreateRastPort()、CloneRastPort()、FreeRastPort()、DeinitRastPort() 已移至 libarossupport,主要是為了支援舊程式碼。如果在 RastPort 上安裝了 ClipRect,仍然需要進行 RastPort 清理。這可以透過 FreeVec(rp->RP_Extra) 來完成。
  • 正確實現了 RPTAG_PenMode,與 MorphOS 相容。

AROS 有一個特殊功能,允許為 rastport 設定一個裁剪矩形,該裁剪矩形也可以用於(連線到)螢幕外點陣圖。使用它可以防止在點陣圖邊界之外進行渲染(= AROS 原生中的記憶體損壞/崩潰和 AROS 託管/X11 中的 X11 錯誤訊息)。也許很久以前就發生了?我在啟用了 mungwall 的 Darwin 託管環境中測試了這個更改。對於 X11 驅動程式,你可能會使用一個 X11 畫素圖作為點陣圖,所以不會出現記憶體損壞 - 只有 X11 錯誤會顯示。

方法 HIDD_BM_PutPixel 應該使用 HIDDT_Pixel 型別作為最後一個引數。如果 64 位編譯器抱怨由於 64 位 (IPTR) 到 32 位 (HIDD_Pixel) 的縮放而丟失了一些資料,那麼你需要以其他方式修復函式體。

將 Point ExtendedNode.xln_Init 指向虛擬函式。防止 WB2.0+ 監視器驅動程式崩潰。這個 xln_Init() 函式的作用。它獲取兩個引數:節點指標和標誌。對於 MONITOR_SPEC_TYPE 節點,標誌值被放入 ms_Flags 成員中。然後,如果設定了 MSF_REQUEST_SPECIAL 位,將分配 SpecialMonitor 結構並附加它。因此,這個初始化函式負責在結構中設定一些預設值。我可以實現它,但我決定不這樣做,因為對 AROS 來說它無論如何都是無用的。

現在關於“驅動程式”本身。這個程式可以被視為 graphics.library 的一部分,放在磁碟上。它所做的只是將顯示模式的資訊插入 graphics.library 的模式資料庫中。資料庫是一個結構,指向由 GfxBase->DisplayInfoDataBase 指向的結構。我開始記錄我發現的東西,但沒有時間做太多。DisplayInfoDataBase 文件在這裡。MonitorSpecs 和模式 ID 屬性中的所有值都是硬編碼常量。它們中的一些具有不同的變體,具體取決於 GfxBase->ChipRevBits 指定的晶片組。GfxBase->Bugs 中還有魔法位號 5。實際上,這個變數是一些內部標誌。如果設定了位 5,VGA 驅動程式將選擇略微不同的常量集。我猜這個位是由 VGAOnly 程式設定的。還有 GfxBase->ProgData 指向一些東西,我猜是某些晶片組常量。顯示驅動程式掃描這段記憶體,搜尋其中的某些東西,並將它們複製到它們建立的每個顯示模式 ID 的 VecInfo->Data 指向的結構中。我沒有理解這些操作的確切目的。

實際上,我認為如果 GfxBase->DisplayInfoDataBase 為 NULL,驅動程式將優雅地失敗,並且不會執行任何操作。要麼我錯了,要麼是出了問題。我認為你只需要提供驅動程式失敗的條件。它不應該插入自己的 MonitorSpec,也不應該嘗試插入資料庫記錄。使用兩個私有的 graphics.library 函式填充模式 DB:AddDisplayInfoData() 和 SetDisplayInfoData()。它們的 LVO 被 AROS 特定的函式佔據。我不記得值,但你可以搜尋函式名稱,很容易找到它們。我也考慮過讓這些驅動程式工作的可能性,但是

  • 這需要反向工程並重新實現 AmigaOS graphics.library 的大部分內容,這可能是版權侵權。
  • 用 AROS 自己的方式重新實現整個東西要容易得多。使用 AROS 自己的基礎設施。如果你看一下 AmigaOS 中模式資料庫的實現,你就會明白 AROS 的實現要好得多。

AROS PolyDraw,rkm 說,計數是一個字值,但在 AROS 中它是一個長值。在 MOS 和 OS4 上,它似乎也是一個字值,因為 amiblitz 在 MOS 和 OS4 上執行良好。Amiblitz 在 AROS 68k 上失敗,會無限繪製線條,因為高位暫存器包含隨機高值。也許是包含檔案中的錯誤,但在 amiga 開發者 CD 檔案中是這麼寫的。例如,void PolyDraw( struct RastPort *, WORD, WORD * );

struct ViewPort {
   struct   ViewPort *Next;
   struct   ColorMap  *ColorMap;    /* table of colors for this viewport, if nil MakeVPort assumes default */
   struct   CopList  *DspIns;       /* user by MakeView() */
   struct   CopList  *SprIns;       /* used by sprite stuff */
   struct   CopList  *ClrIns;       /* used by sprite stuff */
   struct   UCopList *UCopIns;      /* User copper list */
   WORD     DWidth,DHeight;
   WORD     DxOffset,DyOffset;
   UWORD    Modes;
   UBYTE    SpritePriorities;       /* used by makevp */
   UBYTE    ExtendedModes;
   struct   RasInfo *RasInfo;
};

struct View {
   struct ViewPort *ViewPort;
   struct cprlist *LOFCprList;   /* used for interlaced and noninterlaced */
   struct cprlist *SHFCprList;   /* only used during interlace */
   WORD DyOffset,DxOffset;       /* complete View positioning offsets are +- adjustments to standard #s */
   UWORD   Modes;                /* such as INTERLACE, GENLOC */
};

/* these structures are obtained via GfxNew */
/* and disposed by GfxFree */

struct ViewExtra {
    struct ExtendedNode n;
    struct View *View;           /* backwards link */
    struct MonitorSpec *Monitor; /* monitors for this view */
};
/* this structure is obtained via GfxNew */
/* and disposed by GfxFree */

struct ViewPortExtra {
    struct   ExtendedNode n;
    struct   ViewPort *ViewPort;       /* backwards link */
    struct   Rectangle DisplayClip;    /* makevp display clipping information */
};
#define EXTEND_VSTRUCT	0x1000	/* unused bit in Modes field of View */
/* defines used for Modes in IVPargs */
#define GENLOCK_VIDEO	0x0002
#define LACE		0x0004
#define SUPERHIRES	0x0020
#define PFBA		0x0040
#define EXTRA_HALFBRITE 0x0080
#define GENLOCK_AUDIO	0x0100
#define DUALPF		0x0400
#define HAM		0x0800
#define EXTENDED_MODE	0x1000
#define VP_HIDE	0x2000
#define SPRITES	0x4000
#define HIRES		0x8000
#define VPF_A2024		0x40
#define VPF_AGNUS		0x20
#define VPF_TENHZ		0x20

struct RasInfo	/* used by callers to and InitDspC() */ {
   struct   RasInfo *Next;          /* used for dualpf */
   struct   BitMap *BitMap;
   WORD     RxOffset,RyOffset;      /* scroll offsets in this BitMap */
};

struct ColorMap {
    UBYTE    Flags;
    UBYTE    Type;
    UWORD    Count;
    APTR     ColorTable;
    struct   ViewPortExtra *cm_vpe;
    UWORD    *TransparencyBits;
    UBYTE    TransparencyPlane;
    UBYTE    reserved1;
    UWORD    reserved2;
    struct   ViewPort *cm_vp;
    APTR     NormalDisplayInfo;
    APTR     CoerceDisplayInfo;
    struct   TagItem *cm_batch_items;
    ULONG    VPModeID;
};

/* if Type == 0 then ColorMap is V1.2/V1.3 compatible */
/* if Type != 0 then ColorMap is V36	   compatible */
#define COLORMAP_TYPE_V1_2	0x00
#define COLORMAP_TYPE_V1_4	0x01
#define COLORMAP_TYPE_V36 COLORMAP_TYPE_V1_4	/* use this definition */

/* Flags variable */
#define COLORMAP_TRANSPARENCY	0x01
#define COLORPLANE_TRANSPARENCY	0x02
#define BORDER_BLANKING		0x04
#define BORDER_NOTRANSPARENCY	0x08
#define VIDEOCONTROL_BATCH	0x10
#define USER_COPPER_CLIP	0x20
struct	ExtendedNode	{
   struct      Node  *xln_Succ;
   struct      Node  *xln_Pred;
   UBYTE       xln_Type;
   BYTE        xln_Pri;
   char        *xln_Name;
   UBYTE       xln_Subsystem;
   UBYTE       xln_Subtype;
   LONG        xln_Library;
   LONG        (*xln_Init)();
};

#define SS_GRAPHICS          0x02
#define	VIEW_EXTRA_TYPE	        1
#define	VIEWPORT_EXTRA_TYPE     2
#define	SPECIAL_MONITOR_TYPE    3
#define	MONITOR_SPEC_TYPE       4

struct	MonitorSpec {
    struct      ExtendedNode  ms_Node;
    UWORD       ms_Flags;
    LONG        ratioh;
    LONG        ratiov;
    UWORD       total_rows;
    UWORD       total_colorclocks;
    UWORD       DeniseMaxDisplayColumn;
    UWORD       BeamCon0;
    UWORD       min_row;
    struct      SpecialMonitor  *ms_Special;
    UWORD       ms_OpenCount;
    LONG        (*ms_transform)();
    LONG        (*ms_translate)();
    LONG        (*ms_scale)();
    UWORD       ms_xoffset;
    UWORD       ms_yoffset;
    struct      Rectangle  ms_LegalView;
    LONG        (*ms_maxoscan)();            /* maximum legal overscan */
    LONG        (*ms_videoscan)();           /* video display overscan */
    UWORD       DeniseMinDisplayColumn;
    ULONG       DisplayCompatible;
    struct      List DisplayInfoDataBase;
    struct      SignalSemaphore DisplayInfoDataBaseSemaphore;
    ULONG       ms_reserved00;
    ULONG       ms_reserved01;
};

struct	SpecialMonitor {
    struct      ExtendedNode   spm_Node;
    UWORD       spm_Flags;
    int	(*do_monitor)();
    int	(*reserved1)();
    int	(*reserved2)();
    int	(*reserved3)();
    struct      AnalogSignalInterval hblank;
    struct      AnalogSignalInterval vblank;
    struct      AnalogSignalInterval hsync;
    struct      AnalogSignalInterval vsync;
};


點陣圖

點陣圖是 AROS 的繪圖板。它們的座標系原點位於左上角。x 軸從左到右,y 軸從上到下。可能的顏色數量取決於點陣圖的深度。

Depth 	Colors
1 	2
2 	4
3 	8
4 	16
5 	32
6 	64
7 	128
8 	256
15 	32,768
16 	65,536
24 	16,777,216

1 到 8 的深度是 LUT(查詢表)模式。這意味著每種顏色的紅色、綠色和藍色(RGB)值儲存在表中。然後索引將作為筆號儲存在點陣圖中。

15 和 16 的深度稱為高顏色,24 稱為真彩色。與 LUT 模式不同,RGB 值直接儲存在點陣圖中。

圖形庫對高/真彩色模式的支援有限。一些繪圖函式僅適用於 LUT 模式。要完全訪問,您需要使用 cybergraphics 庫中的函式。

GetBitMapAttr() Query bitmap attributes. (Don't peek at bitmap.)
AllocBitMap() 	Allocate and initialize bitmap
InitBitMap() 	Initialize bitmap
FreeBitMap() 	Free resources allocated by a bitmap
AllocRaster() 	Allocate a single bitplane
FreeRaster() 	Free a single bitplane
CopySBitMap() 	Syncronize super-bitmap (see Intuition)
SyncSBitMap() 	Syncronize super-bitmap
RastPort

點陣圖與大多數繪圖函式之間的連線透過一個 rastport 完成。rastport 包含有關繪圖筆、線和區域圖案、繪圖模式和文字字型的資訊。

您可以將多個 rastport 連線到一個位圖。這允許在不同的繪圖配置之間快速切換。但是,在 AROS 中無法簡單地複製 rastport;您必須使用 CloneRastPort() 函式。

一些 Intuition 元素,例如螢幕和視窗,已經有一個 RastPort 元素。您可以立即將其用於繪圖操作。物件結構 RastPort 螢幕 struct Screen RastPort 視窗 struct Window *RPort

如果您建立了一個位圖並想要在其中繪圖,您必須自己建立 rastport。警告:此示例已簡化,缺少返回值檢查

struct BitMap *bm = AllocBitMap(400, 300, 8, BMF_CLEAR, NULL); struct RastPort *rp = CreateRastPort(); rp->BitMap = bm; ... WritePixel(rp, 50, 30); ... FreeRastPort(rp); FreeBitMap(bm);

rastport 包含 3 支筆。A(前景色,主色)筆,B(背景色,副色)筆和 O(區域輪廓)筆。後者由區域填充和填充填充函式使用。


繪圖模式

    JAM1: draw only with A pen.

    JAM2: draw bit 1 in a pattern with A pen, bit 0 with B pen

    COMPLEMENT: for each set bit, the state in the target is reversed

    INVERSVID: is used for text rendering
            JAM1|INVERSVID: transparent letters outlined in foreground color
            JAM2|INVERSVID: like previous, but letter in background color.

待辦事項:檢查繪圖模式是否真的可用。


模式

The line pattern can be set with the macro SetDrPt(). The second parameter is a 16 bit pattern:

SetDrPt(&rastPort, 0xCCCC);

The pattern can be reset with:

SetDrPt(&rastPort, ~0);

For area patterns a macro SetAfPt() exists. The width is 16 bit, the height a power of two (2, 4, 8, 16, ...). The third parameter is the n in 2^n=height:

UWORD areaPattern[] =
{
    0x5555, 0xAAAA
};
SetAfPt(&rastPort, areaPattern, 1);

Colored patterns are possible with a negative value for the height. The number of bitplanes in the pattern must be the same as in the target bitmap.

Reset of area pattern:

SetAfPt(&rastPort, NULL, 0);

CloneRastPort() 	Copy rastport
CreateRastPort() 	Create rastport
InitRastPort() 	Initialize rastport
DeinitRastPort() 	Deinitialize rastport
FreeRastPort() 	Free rastport
SetAPen() 	Set primary pen
GetAPen() 	Get primary pen
SetBPen() 	Set secondary pen
GetBPen() 	Get secondary pen
SetOPen() 	Set area outline pen and switch outline mode on *
SetOutlinePen() 	Get area outline pen
GetOutlinePen() 	Get area outline pen
BNDRYOFF() 	Switch off area outline mode *
SetDrMd() 	Set drawing mode
GetDrMd() 	Get drawing mode
SetDrPt() 	Set line pattern *
SetAfPt() 	Set area pattern *
SetABPenDrMd() 	Set primary & secondary pen and drawing mode in one step
SetRPAttrsA() 	Set misc. drawing attributes
GetRPAttrsA() 	Get misc. drawing attributes
InitTmpRas() 	Initialize a TmpRas structure.
SetWriteMask() 	Set write mask

* Macro in graphics/gfxmacros.h
LONG BltBitMap(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, LONG xDest,      
               LONG yDest, LONG xSize, LONG ySize, ULONG minterm, ULONG mask, PLANEPTR tempA)
void BltTemplate(PLANEPTR source, LONG xSrc, LONG srcMod, struct RastPort *destRP, LONG xDest, 
                 LONG yDest, LONG xSize, LONG ySize) 
void BltBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, 
                   LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm) 
void BltMaskBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, 
                   LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, PLANEPTR bltMask) 
void BltRastPortBitMap(struct RastPort *srcRastPort, LONG xSrc, LONG ySrc, struct BitMap *destBitMap, 
              LONG xDest, LONG yDest, ULONG xSize, ULONG ySize, ULONG minterm)

BOOL InitRastPort(struct RastPort *rp) 
void InitVPort(struct ViewPort *vp) 
ULONG MrgCop(struct View *view) 
ULONG MakeVPort(struct View *view, struct ViewPort *viewport) 
void LoadView(struct View *view) 
void WaitBlit() 
void SetRast(struct RastPort *rp, ULONG pen)

void Move(struct RastPort *rp, WORD x, WORD y) 
void Draw(struct RastPort *rp, LONG x, LONG y) 
ULONG AreaMove(struct RastPort *rp, WORD x, WORD y) 
ULONG AreaDraw(struct RastPort *rp, WORD x, WORD y) 
LONG AreaEnd(struct RastPort *rp)
void WaitTOF() 
void QBlit(struct bltnode *bn) 
void InitArea(struct AreaInfo *areainfo, void *buffer, WORD maxvectors) 
void SetRGB4(struct ViewPort *vp, ULONG n, ULONG r, ULONG g, ULONG b) 
void QBSBlit(struct bltnode *bn) 
void BltClear(void *memBlock, ULONG bytecount, ULONG flags) 
void RectFill(struct RastPort *rp, LONG xMin, LONG yMin, LONG xMax, LONG yMax) 
void BltPattern(struct RastPort *rp, PLANEPTR mask, LONG xMin, LONG yMin, LONG xMax, LONG yMax, ULONG byteCnt) 
void DrawEllipse(struct RastPort *rp, LONG xCenter, LONG yCenter, LONG a, LONG b) 
ULONG AreaEllipse(struct RastPort *rp, WORD cx, WORD cy, WORD a, WORD b) 
void LoadRGB4(struct ViewPort *vp, UWORD *colors, LONG count)

LONG ReadPixel(struct RastPort *rp, LONG x, LONG y) 
LONG WritePixel(struct RastPort *rp, LONG x, LONG y) 
BOOL Flood(struct RastPort *rp, ULONG mode, LONG x, LONG y) 
void PolyDraw(struct RastPort *rp, LONG count, WORD *polyTable) 
void SetAPen(struct RastPort *rp, ULONG pen) 
void SetBPen(struct RastPort *rp, ULONG pen) 
void SetDrMd(struct RastPort *rp, ULONG drawMode) 
void InitView(struct View *view) 
void InitBitMap(struct BitMap *bm, BYTE depth, UWORD width, UWORD height) 
void ScrollRaster(struct RastPort *rp, LONG dx, LONG dy, LONG xMin, LONG yMin, LONG xMax, LONG yMax)

PLANEPTR AllocRaster(ULONG width, ULONG height) (D0, D1)
void FreeRaster(PLANEPTR p, ULONG width, ULONG height) (A0, D0, D1)

BOOL AttemptLockLayerRom(struct Layer *l) (A5)
struct ExtendedNode *GfxNew(ULONG node_type) (D0)
void GfxFree(struct ExtendedNode *node) (A0)
void GfxAssociate(void *pointer, struct ExtendedNode *node) (A0, A1)

void BitMapScale(struct BitScaleArgs *bitScaleArgs) (A0)
UWORD ScalerDiv(UWORD factor, UWORD numerator, UWORD denominator) (D0, D1, D2)

void TextExtent(struct RastPort *rp, CONST_STRPTR string, ULONG count, struct TextExtent *textExtent) 
ULONG TextFit(struct RastPort *rp, CONST_STRPTR string, ULONG strLen, struct TextExtent *textExtent, struct TextExtent *constrainingExtent, LONG strDirection, ULONG constrainingBitWidth, ULONG constrainingBitHeight)

struct ExtendedNode *GfxLookUp(void *pointer) (A0)
ULONG VideoControl(struct ColorMap *cm, struct TagItem *tags) (A0, A1)
struct MonitorSpec *OpenMonitor(STRPTR monitor_name, ULONG display_id) (A1, D0)
LONG CloseMonitor(struct MonitorSpec *monitor_spec) (A0)
DisplayInfoHandle FindDisplayInfo(ULONG ID) (D0)
ULONG NextDisplayInfo(ULONG last_ID) (D0)

ULONG GetDisplayInfoData(DisplayInfoHandle handle, UBYTE *buf, ULONG size, ULONG tagID, ULONG ID) 
void FontExtent(struct TextFont *font, struct TextExtent *fontExtent) (A0, A1)

LONG ReadPixelLine8(struct RastPort *rp, LONG xstart, LONG ystart, ULONG width, UBYTE *array, struct RastPort *tempRP) (A0, D0, D1, D2, A2, A1)
LONG WritePixelLine8(struct RastPort *rp, LONG xstart, LONG ystart, ULONG width, UBYTE *array, struct RastPort *tempRP) (A0, D0, D1, D2, A2, A1)
LONG ReadPixelArray8(struct RastPort *rp, LONG xstart, LONG ystart, LONG xstop, LONG ystop, UBYTE *array, struct RastPort *temprp) (A0, D0, D1, D2, D3, A2, A1)
LONG WritePixelArray8(struct RastPort *rp, ULONG xstart, ULONG ystart, ULONG xstop, ULONG ystop, UBYTE *array, struct RastPort *temprp) (A0, D0, D1, D2, D3, A2, A1)

ULONG GetVPModeID(struct ViewPort *vp) 
ULONG ModeNotAvailable(ULONG modeID) 
WORD WeighTAMatch(struct TextAttr *reqTextAttr, struct TextAttr *targetTextAttr, struct TagItem *targetTags) 
void EraseRect(struct RastPort *rp, LONG xMin, LONG yMin, LONG xMax, LONG yMax) 
ULONG ExtendFont(struct TextFont *font, struct TagItem *fontTags) 
void StripFont(struct TextFont *font) 
UWORD CalcIVG(struct View *View, struct ViewPort *ViewPort) 
LONG AttachPalExtra(struct ColorMap *cm, struct ViewPort *vp) 
LONG ObtainBestPenA(struct ColorMap *cm, ULONG r, ULONG g, ULONG b, struct TagItem *tags) 
struct Region *ClearRegionRegionND(struct Region *R1, struct Region *R2)

void SetRGB32(struct ViewPort *vp, ULONG n, ULONG r, ULONG g, ULONG b) 
ULONG GetAPen(struct RastPort *rp) 
ULONG GetBPen(struct RastPort *rp) 
ULONG GetDrMd(struct RastPort *rp) 
ULONG GetOutlinePen(struct RastPort *rp) 
void LoadRGB32(struct ViewPort *vp, const ULONG *table) 
ULONG SetChipRev(ULONG ChipRev) 
void SetABPenDrMd(struct RastPort *rp, ULONG apen, ULONG bpen, ULONG drawMode) 
void GetRGB32(struct ColorMap *cm, ULONG firstcolor, ULONG ncolors, ULONG *table)

struct BitMap *AllocBitMap(ULONG sizex, ULONG sizey, ULONG depth, ULONG flags, struct BitMap *friend_bitmap) (D0, D1, D2, D3, A0)
void FreeBitMap(struct BitMap *bm) (A0)
LONG GetExtSpriteA(struct ExtSprite *sprite, struct TagItem *tags) (A2, A1)
ULONG CoerceMode(struct ViewPort *RealViewPort, ULONG MonitorID, ULONG Flags) (A0, D0, D1)
void ChangeVPBitMap(struct ViewPort *vp, struct BitMap *bm, struct DBufInfo *db) (A0, A1, A2)
void ReleasePen(struct ColorMap *cm, ULONG n) (A0, D0)
LONG ObtainPen(struct ColorMap *cm, ULONG n, ULONG r, ULONG g, ULONG b, ULONG flags) (A0, D0, D1, D2, D3, D4)
IPTR GetBitMapAttr(struct BitMap *bitmap, ULONG attribute) (A0, D1)
struct DBufInfo *AllocDBufInfo(struct ViewPort *vp) (A0)
void FreeDBufInfo(struct DBufInfo *db) (A1)
ULONG SetOutlinePen(struct RastPort *rp, ULONG pen) (A0, D0)
ULONG SetWriteMask(struct RastPort *rp, ULONG mask) (A0, D0)
void SetMaxPen(struct RastPort *rp, ULONG maxpen) (A0, D0)
void SetRGB32CM(struct ColorMap *cm, ULONG n, ULONG r, ULONG g, ULONG b) (A0, D0, D1, D2, D3)
void ScrollRasterBF(struct RastPort *rp, LONG dx, LONG dy, LONG xMin, LONG yMin, LONG xMax, LONG yMax) (A1, D0, D1, D2, D3, D4, D5)
ULONG FindColor(struct ColorMap *cm, ULONG r, ULONG g, ULONG b, ULONG maxpen) (A3, D1, D2, D3, D4)

struct ExtSprite *AllocSpriteDataA(struct BitMap *bitmap, struct TagItem *tagList) (A2, A1)
LONG ChangeExtSpriteA(struct ViewPort *vp, struct ExtSprite *oldsprite, struct ExtSprite *newsprite, struct TagItem *tags) (A0, A1, A2, A3)
void FreeSpriteData(struct ExtSprite *extsp) (A2)
void SetRPAttrsA(struct RastPort *rp, struct TagItem *tags) (A0, A1)
void GetRPAttrsA(struct RastPort *rp, struct TagItem *tags) (A0, A1)
ULONG BestModeIDA(struct TagItem *TagItems) (A0)
void WriteChunkyPixels(struct RastPort *rp, LONG xstart, LONG ystart, LONG xstop, LONG ystop, UBYTE *array, LONG bytesperrow) (A0, D0, D1, D2, D3, A2, D4)

struct RastPort *CreateRastPort() ()
struct RastPort *CloneRastPort(struct RastPort *rp) (A1)
void DeinitRastPort(struct RastPort *rp) (A1)
void FreeRastPort(struct RastPort *rp) (A1)
LONG AddDisplayDriverA(APTR gfxhidd, struct TagItem *tags) (A0, A1)

LONG WritePixels8(struct RastPort *rp, UBYTE *array, ULONG modulo, LONG xstart, LONG ystart, LONG xstop, LONG ystop, HIDDT_PixelLUT *pixlut, BOOL do_update)

LONG FillRectPenDrMd(struct RastPort *rp, LONG x1, LONG y1, LONG x2, LONG y2, HIDDT_Pixel pix, HIDDT_DrawMode drmd, BOOL do_update)

LONG DoRenderFunc(struct RastPort *rp, Point *src, struct Rectangle *rr, RENDERFUNC render_func, APTR funcdata, BOOL do_update) 
LONG DoPixelFunc(struct RastPort *rp, LONG x, LONG y, PIXELFUNC render_func, APTR funcdata, BOOL do_update)

struct Region *XorRegionRegionND(struct Region *R1, struct Region *R2) 
struct Region *XorRectRegionND(struct Region *Reg, struct Rectangle *Rect) 
BOOL ClearRegionRegion(struct Region *R1, struct Region *R2) 
struct Region *CopyRegion(struct Region *region) 
BOOL AreRegionsEqual(struct Region *R1, struct Region *R2) 
BOOL IsPointInRegion(struct Region *Reg, WORD x, WORD y) 
BOOL ScrollRegion(struct Region *region, struct Rectangle *rect, WORD dx, WORD dy) 
void SwapRegions(struct Region *region1, struct Region *region2) 
BOOL AndRectRect(struct Rectangle *rect1, struct Rectangle *rect2, struct Rectangle *intersect) 
struct Region *NewRectRegion(WORD MinX, WORD MinY, WORD MaxX, WORD MaxY) 
BOOL SetRegion(struct Region *src, struct Region *dest) 
void AndRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
BOOL OrRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
struct Region *NewRegion() ()
BOOL ClearRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
void ClearRegion(struct Region *region) (A0)
void DisposeRegion(struct Region *region) (A0)
BOOL XorRectRegion(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
struct Region *OrRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
struct Region *ClearRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
struct Region *OrRegionRegionND(struct Region *R1, struct Region *R2) (A0, A1)
BOOL OrRegionRegion(struct Region *R1, struct Region *R2) (A0, A1)
BOOL XorRegionRegion(struct Region *R1, struct Region *R2) (A0, A1)
BOOL AndRegionRegion(struct Region *R1, struct Region *R2) (A0, A1)
struct Region *AndRectRegionND(struct Region *Reg, struct Rectangle *Rect) (A0, A1)
struct Region *AndRegionRegionND(struct Region *R1, struct Region *R2) (A0, A1)

WORD TextLength(struct RastPort *rp, CONST_STRPTR string, ULONG count) 
void Text(struct RastPort *rp, CONST_STRPTR string, ULONG count) 
void SetFont(struct RastPort *rp, struct TextFont *textFont) 
struct TextFont *OpenFont(struct TextAttr *textAttr) 
void CloseFont(struct TextFont *textFont) 
ULONG AskSoftStyle(struct RastPort *rp) 
ULONG SetSoftStyle(struct RastPort *rp, ULONG style, ULONG enable) 
void ClearEOL(struct RastPort *rp) 
void ClearScreen(struct RastPort *rp) 
void AskFont(struct RastPort *rp, struct TextAttr *textAttr) 
void AddFont(struct TextFont *textFont) 
void RemFont(struct TextFont *textFont)

void AddBob(struct Bob *bob, struct RastPort *rp) 
void AddVSprite(struct VSprite *vs, struct RastPort *rp) 
void DoCollision(struct RastPort *rp) 
void DrawGList(struct RastPort *rp, struct ViewPort *vp) 
void InitGels(struct VSprite *head, struct VSprite *tail, struct GelsInfo *GInfo) 
void InitMasks(struct VSprite *vs) 
void RemIBob(struct Bob *bob, struct RastPort *rp, struct ViewPort *vp) 
void RemVSprite(struct VSprite *vs) 
void SetCollision(ULONG num, VOID_FUNC routine, struct GelsInfo *GInfo) 
void SortGList(struct RastPort *rp) 
void AddAnimOb(struct AnimOb *anOb, struct AnimOb **anKey, struct RastPort *rp) 
void Animate(struct AnimOb **anKey, struct RastPort *rp) 
BOOL GetGBuffers(struct AnimOb *anOb, struct RastPort *rp, BOOL db) 
void InitGMasks(struct AnimOb *anOb) 
WORD GetSprite(struct SimpleSprite *sprite, WORD pick) 
void FreeSprite(WORD pick) 
void ChangeSprite(struct ViewPort *vp, struct SimpleSprite *s, void *newdata) 
void MoveSprite(struct ViewPort *vp, struct SimpleSprite *sprite, WORD x, WORD y) 
void LockLayerRom(struct Layer *l) 
void UnlockLayerRom(struct Layer *l) 
void SyncSBitMap(struct Layer *l) 
void CopySBitMap(struct Layer *l) 
void OwnBlitter() 
void DisownBlitter() 
struct TmpRas *InitTmpRas(struct TmpRas *tmpras, void *buffer, ULONG size) 
void SetRGB4CM(struct ColorMap *cm, WORD n, UBYTE r, UBYTE g, UBYTE b) (A0, D0, D1, D2, D3)

void FreeVPortCopLists(struct ViewPort *vp) 
void FreeCopList(struct CopList *coplist) 
void ClipBlit(struct RastPort *srcRP, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, 
              LONG yDest, LONG xSize, LONG ySize, UBYTE minterm) 
void FreeCprList(struct cprlist *cprList) 
struct ColorMap *GetColorMap(ULONG entries) 
void FreeColorMap(struct ColorMap *colormap) 
ULONG GetRGB4(struct ColorMap *colormap, LONG entry) 
void ScrollVPort(struct ViewPort *vp) (A0) 
struct CopList *UCopperListInit(struct UCopList *ucl, WORD n) 
void FreeGBuffers(struct AnimOb *anOb, struct RastPort *rp, BOOL db) 
void CBump(struct UCopList *ucl) 
void CMove(struct UCopList *ucl, void *reg, WORD value) 
void CWait(struct UCopList *ucl, WORD v, WORD h) 
LONG VBeamPos() 
void WaitBOVP(struct ViewPort *vp) 
void ShowImminentReset()
華夏公益教科書