[← Home](../README.md) · [Graphics](README.md) # RastPort — Drawing Primitives and Layers ## Overview `RastPort` is the primary drawing context in AmigaOS — the equivalent of a "device context" (Windows) or "graphics context" (X11). All graphics primitives (pixel, line, rectangle, polygon, text) operate through a RastPort, which bundles together a target `BitMap`, drawing pen colors, patterns, font, draw mode, and an optional `Layer` for clipping. Every Intuition window and screen has its own RastPort. When you draw into a window, you're drawing through its RastPort. ```mermaid flowchart TD subgraph "RastPort — Drawing Context" RP["struct RastPort"] RP --> BM["BitMap
(pixel storage)"] RP --> PEN["Pens
FgPen, BgPen, AOlPen"] RP --> DM["DrawMode
JAM1/JAM2/COMPLEMENT"] RP --> FONT["TextFont
(current font)"] RP --> PAT["AreaPtrn
(fill pattern)"] RP --> LAYER["Layer
(clipping region)"] RP --> CP["cp_x, cp_y
(cursor position)"] end APP["Application Code"] -->|"SetAPen, Move,
Draw, RectFill,
Text, ClipBlit"| RP RP -->|"Drawing operations"| BM LAYER -->|"Clips to visible region"| BM style RP fill:#e8f4fd,stroke:#2196f3,color:#333 style BM fill:#c8e6c9,stroke:#2e7d32,color:#333 style LAYER fill:#fff9c4,stroke:#f9a825,color:#333 ``` --- ## struct RastPort ```c /* graphics/rastport.h — NDK39 */ struct RastPort { struct Layer *Layer; /* associated layer (NULL = no clipping) */ struct BitMap *BitMap; /* target bitmap */ UWORD *AreaPtrn; /* area fill pattern */ struct TmpRas *TmpRas; /* temp raster for area fills/floods */ struct AreaInfo *AreaInfo; /* area fill vertex buffer */ struct GelsInfo *GelsInfo; /* GEL (BOB/VSprite) list */ UBYTE Mask; /* plane mask (which planes to draw to) */ BYTE FgPen; /* foreground pen color index */ BYTE BgPen; /* background pen color index */ BYTE AOlPen; /* area outline pen */ BYTE DrawMode; /* JAM1, JAM2, COMPLEMENT, INVERSVID */ BYTE AreaPtSz; /* area pattern size (log2) */ BYTE linpatcnt; /* line pattern counter */ BYTE dummy; UWORD Flags; /* FRST_DOT etc. */ UWORD LinePtrn; /* 16-bit line dash pattern */ WORD cp_x, cp_y; /* current pen position */ UWORD minterms[8]; WORD PenWidth; WORD PenHeight; struct TextFont *Font; /* current text font */ UBYTE AlgoStyle; /* algorithmic style flags */ UBYTE TxFlags; UWORD TxHeight; UWORD TxWidth; UWORD TxBaseline; WORD TxSpacing; APTR *RP_User; /* ... */ }; ``` --- ## Draw Modes The draw mode controls how new pixels combine with existing content: ```mermaid flowchart LR subgraph "JAM1 — Transparent" J1BG["Background
unchanged"] --- J1FG["Foreground
drawn with FgPen"] end subgraph "JAM2 — Opaque" J2BG["Background
drawn with BgPen"] --- J2FG["Foreground
drawn with FgPen"] end subgraph "COMPLEMENT — XOR" XBG["All pixels
XOR with existing"] end ``` ```c #define JAM1 0 /* draw FgPen only; background pixels are NOT touched */ #define JAM2 1 /* draw FgPen AND BgPen — fully opaque */ #define COMPLEMENT 2 /* XOR all drawn pixels with existing content */ #define INVERSVID 4 /* swap foreground/background (for text inverse) */ ``` | Mode | Text Example | Fill Example | Use Case | |---|---|---|---| | `JAM1` | Characters drawn, background shows through | Solid fill with FgPen | Transparent overlays, labels on images | | `JAM2` | Characters + background box drawn | Same as JAM1 for fills | Opaque text on busy backgrounds | | `COMPLEMENT` | XOR of text pixels with screen | XOR fill | Rubber-band selection, dragging cursors | | `JAM1 | INVERSVID` | Background drawn with FgPen, chars transparent | — | Highlighted/selected text | --- ## Drawing Primitives ### Pen and Position Setup ```c /* Set pen colors: */ SetAPen(rp, 1); /* foreground = color register 1 */ SetBPen(rp, 0); /* background = color register 0 */ SetDrMd(rp, JAM1); /* transparent background mode */ /* OS 3.0+ — use named pen for correct Workbench colors: */ SetAPen(rp, screen->RastPort.BitMap->Depth > 1 ? ObtainBestPen(screen->ViewPort.ColorMap, 0xFF000000, 0x00000000, 0x00000000, /* red */ OBP_Precision, PRECISION_GUI, TAG_DONE) : 1); ``` ### Lines and Pixels ```mermaid flowchart LR M["Move(rp, 10, 20)"] -->|"sets cp_x, cp_y"| D1["Draw(rp, 100, 20)"] D1 -->|"draws line,
updates cp"| D2["Draw(rp, 100, 80)"] D2 -->|"draws line,
updates cp"| D3["Draw(rp, 10, 80)"] D3 -->|"draws line,
updates cp"| D4["Draw(rp, 10, 20)"] style M fill:#e8f4fd,stroke:#2196f3,color:#333 ``` ```c /* Move cursor (no drawing): */ Move(rp, 100, 50); /* Draw line from current position to (x,y), update cp: */ Draw(rp, 200, 100); /* cp is now (200, 100) — next Draw continues from here */ /* Draw a connected polygon: */ Move(rp, 10, 10); Draw(rp, 100, 10); /* top edge */ Draw(rp, 100, 80); /* right edge */ Draw(rp, 10, 80); /* bottom edge */ Draw(rp, 10, 10); /* close: left edge */ /* Single pixel: */ WritePixel(rp, 160, 120); LONG color = ReadPixel(rp, 160, 120); /* Dashed lines: */ SetDrPt(rp, 0xF0F0); /* 16-bit pattern: 1111000011110000 */ Draw(rp, 200, 100); /* draws dashed line */ SetDrPt(rp, 0xFFFF); /* restore solid */ ``` ### Rectangles and Fills ```c /* Solid filled rectangle (uses FgPen + DrawMode): */ SetAPen(rp, 3); RectFill(rp, 10, 10, 100, 50); /* x1,y1 to x2,y2 inclusive */ /* Erase to background (clear a region): */ SetAPen(rp, 0); SetDrMd(rp, JAM1); RectFill(rp, 0, 0, 319, 255); /* Scroll a region (with clear): */ ScrollRaster(rp, dx, dy, x1, y1, x2, y2); /* Shifts content by (dx,dy); exposed area cleared to BgPen */ ``` ### Text Rendering ```mermaid flowchart LR ATTR["TextAttr
(name, size)"] -->|"OpenFont /
OpenDiskFont"| TF["TextFont"] TF -->|"SetFont(rp, font)"| RP["RastPort"] RP -->|"Move + Text"| OUT["Rendered text
on bitmap"] ``` ```c /* Set font: */ struct TextAttr ta = {"topaz.font", 8, 0, FPF_ROMFONT}; struct TextFont *font = OpenFont(&ta); SetFont(rp, font); /* Render text at position: */ Move(rp, 20, 30); /* baseline position */ Text(rp, "Hello Amiga", 11); /* Measure text width before rendering (for alignment): */ UWORD width = TextLength(rp, "Hello Amiga", 11); /* Right-align: */ Move(rp, screenWidth - width - 10, 30); Text(rp, "Hello Amiga", 11); /* Bold/italic (algorithmic): */ UWORD supported = AskSoftStyle(rp); SetSoftStyle(rp, FSF_BOLD | FSF_ITALIC, supported); Text(rp, "Bold Italic", 11); SetSoftStyle(rp, 0, supported); /* restore */ ``` ### Area Fills (Polygons) ```c /* Area fills require setup: TmpRas + AreaInfo */ UBYTE areaBuffer[5 * 5]; /* 5 vertices × 5 bytes each */ struct AreaInfo areaInfo; InitArea(&areaInfo, areaBuffer, 5); rp->AreaInfo = &areaInfo; PLANEPTR tmpRasData = AllocRaster(320, 256); struct TmpRas tmpRas; InitTmpRas(&tmpRas, tmpRasData, RASSIZE(320, 256)); rp->TmpRas = &tmpRas; /* Draw a filled triangle: */ AreaMove(rp, 100, 10); /* first vertex */ AreaDraw(rp, 200, 180); /* second vertex */ AreaDraw(rp, 20, 180); /* third vertex */ AreaEnd(rp); /* fill and close */ /* Cleanup: */ FreeRaster(tmpRasData, 320, 256); ``` ### Flood Fill ```c /* Flood fill from a seed point: */ /* Requires TmpRas (same setup as area fills) */ Flood(rp, 1, 50, 50); /* mode 1 = fill until FgPen color boundary */ /* mode 0 = fill all connected pixels of same color as seed */ ``` ### Blitting (Block Transfer) ```mermaid flowchart LR SRC["Source RastPort
(or BitMap)"] -->|"ClipBlit /
BltBitMapRastPort"| DST["Destination RastPort"] subgraph "Minterm Controls" MT["0xC0 = copy
0x30 = invert copy
0x50 = XOR
0x00 = clear"] end MT --> DST ``` ```c /* Copy region between RastPorts (respects clipping): */ ClipBlit(srcRP, sx, sy, /* source position */ dstRP, dx, dy, /* destination position */ width, height, 0xC0); /* minterm: straight copy */ /* Copy from BitMap to RastPort: */ BltBitMapRastPort(srcBM, sx, sy, dstRP, dx, dy, width, height, 0xC0); /* Common minterms: */ /* 0xC0 = A (copy source) */ /* 0x30 = NOT A (invert source) */ /* 0x50 = A XOR B (toggle) */ /* 0x00 = clear destination */ /* 0xFF = set all bits */ ``` --- ## Layers — Window Clipping When `rp->Layer != NULL`, all drawing is automatically clipped to the layer's visible region. Intuition creates layers for every window — this is how overlapping windows work without drawing over each other. ```mermaid flowchart TD subgraph "Screen" subgraph "Window A (front)" LA["Layer A
(fully visible)"] end subgraph "Window B (behind)" LB["Layer B
(partially obscured)"] end subgraph "Window C (behind both)" LC["Layer C
(mostly obscured)"] end end DRAW["Draw(windowB->RPort, ...)"] --> LB LB -->|"ClipRects exclude
obscured regions"| BM["BitMap
(only visible
portions drawn)"] style LA fill:#c8e6c9,stroke:#2e7d32,color:#333 style LB fill:#fff9c4,stroke:#f9a825,color:#333 style LC fill:#ffcdd2,stroke:#c62828,color:#333 ``` Each layer maintains a list of **ClipRects** — rectangles defining which parts of the layer are visible. When you draw to a partially obscured window, `layers.library` breaks your drawing operation into multiple clipped sub-draws, one per visible ClipRect. ```c /* Direct layer creation (Intuition does this for windows): */ struct Layer_Info *li = NewLayerInfo(); struct Layer *layer = CreateUpfrontLayer(li, bm, x1, y1, x2, y2, LAYERSIMPLE, /* or LAYERSMART, LAYERSUPER */ NULL); struct RastPort *rp = layer->rp; /* use this for drawing */ /* LAYERSIMPLE — no backing store; app must redraw damaged areas */ /* LAYERSMART — automatic backing store; OS handles redraw */ /* LAYERSUPER — super bitmap; full offscreen buffer */ /* Layer clipping is automatic — Draw, RectFill, Text all respect it */ Draw(rp, 200, 100); /* clipped to visible portion of layer */ /* Cleanup: */ DeleteLayer(0, layer); DisposeLayerInfo(li); ``` ### Layer Types | Type | Flag | Backing Store | Damage Handling | Memory | |---|---|---|---|---| | Simple | `LAYERSIMPLE` | None | App receives `IDCMP_REFRESHWINDOW` and must redraw | Minimal | | Smart | `LAYERSMART` | Auto-saved obscured regions | OS restores automatically | Moderate | | Super | `LAYERSUPER` | Full off-screen bitmap | Full bitmap always valid | High | > [!TIP] > **`WFLG_SIMPLE_REFRESH`** windows use the least memory but require the most application code (you must handle `IDCMP_REFRESHWINDOW`). **`WFLG_SMART_REFRESH`** is the default for most applications — Intuition saves/restores obscured regions automatically. --- ## Patterns ### Line Patterns ```c /* 16-bit repeating pattern for dashed lines: */ SetDrPt(rp, 0xFF00); /* ████████░░░░░░░░ — long dash */ SetDrPt(rp, 0xF0F0); /* ████░░░░████░░░░ — medium dash */ SetDrPt(rp, 0xAAAA); /* █░█░█░█░█░█░█░█░ — dotted */ SetDrPt(rp, 0xFCFC); /* ██████░░██████░░ — dash-dot */ ``` ### Area Fill Patterns ```c /* Area patterns are powers-of-2 height, 16 bits wide: */ UWORD checkerPattern[] = { 0x5555, 0xAAAA }; /* 2-line checkerboard */ rp->AreaPtrn = checkerPattern; rp->AreaPtSz = 1; /* log2(2) = 1 */ /* Now RectFill uses the pattern instead of solid fill: */ RectFill(rp, 10, 10, 100, 80); /* Multiplane patterns (one set per bitplane): */ UWORD brickPattern[] = { /* plane 0: */ 0xFFFF, 0x8080, 0xFFFF, 0x0808, /* plane 1: */ 0xFFFF, 0x8080, 0xFFFF, 0x0808 }; rp->AreaPtrn = brickPattern; rp->AreaPtSz = 2; /* log2(4 lines) = 2 */ rp->Mask |= 0x02; /* enable plane 1 pattern */ ``` --- ## Plane Mask — Selective Bitplane Drawing ```c /* Mask controls which bitplanes are affected by drawing: */ rp->Mask = 0xFF; /* all planes — default */ rp->Mask = 0x01; /* only plane 0 — fast for single-plane effects */ rp->Mask = 0x03; /* planes 0 and 1 only */ /* Use case: draw a 2-color overlay without disturbing other planes: */ rp->Mask = 0x04; /* only plane 2 */ SetAPen(rp, 4); /* color index with bit 2 set */ RectFill(rp, 0, 0, 319, 255); rp->Mask = 0xFF; /* restore */ ``` --- ## References - NDK39: `graphics/rastport.h`, `graphics/gfxmacros.h` - ADCD 2.1: `SetAPen`, `Move`, `Draw`, `Text`, `RectFill`, `ClipBlit` - See also: [bitmap.md](bitmap.md) — BitMap structure and allocation - See also: [layers.md](../../11_libraries/layers.md) — layers.library detailed reference - See also: [text_fonts.md](text_fonts.md) — font loading and rendering - See also: [blitter.md](blitter/blitter.md) — hardware Blitter used by BltBitMap