// Drawing primitives. // // All primitives clip to the surface rectangle. Out-of-bounds draws are // silent no-ops, not errors. samplePixel returns 0 for off-surface reads. // Primitives operate on color indices; per-scanline palette resolution // happens only at display time. #ifndef JOEYLIB_DRAW_H #define JOEYLIB_DRAW_H #include "asset.h" #include "platform.h" #include "surface.h" #include "types.h" // Fill the entire surface with a single color index. Writes color 0 is // a legitimate clear-to-black and does not skip. void surfaceClear(SurfaceT *s, uint8_t colorIndex); // Plot a single pixel. Off-surface coordinates are no-ops. void drawPixel(SurfaceT *s, int16_t x, int16_t y, uint8_t colorIndex); // Read a pixel value. Off-surface coordinates return 0. uint8_t samplePixel(const SurfaceT *s, int16_t x, int16_t y); // Plot a line from (x0, y0) to (x1, y1) using Bresenham. Endpoints // are inclusive. Off-surface pixels are skipped per-pixel; lines that // pass entirely off-surface draw nothing. Horizontal and vertical // runs hit fast paths. void drawLine(SurfaceT *s, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t colorIndex); // Outline a rectangle (1-pixel-wide border). 1xN / Nx1 degenerate // to vertical / horizontal lines; 1x1 to a single pixel. Negative or // zero dimensions are no-ops. void drawRect(SurfaceT *s, int16_t x, int16_t y, uint16_t w, uint16_t h, uint8_t colorIndex); // Fill a solid rectangle. Negative or zero dimensions are no-ops. void fillRect(SurfaceT *s, int16_t x, int16_t y, uint16_t w, uint16_t h, uint8_t colorIndex); // Outline a circle of radius r centered at (cx, cy) using Bresenham // midpoint. r == 0 plots a single pixel. void drawCircle(SurfaceT *s, int16_t cx, int16_t cy, uint16_t r, uint8_t colorIndex); // Fill a disk of radius r centered at (cx, cy). r == 0 plots a single // pixel. Spans are emitted per scanline using midpoint symmetry. void fillCircle(SurfaceT *s, int16_t cx, int16_t cy, uint16_t r, uint8_t colorIndex); // Flood fill a 4-connected region starting at (x, y). Replaces every // pixel of the original color reached via N/S/E/W steps. No-op if // (x, y) is off-surface or already matches newColor. void floodFill(SurfaceT *s, int16_t x, int16_t y, uint8_t newColor); // Flood fill a 4-connected region starting at (x, y), stopping at // boundary pixels of color boundaryColor. Replaces every reachable // pixel that is not boundaryColor with newColor. Used for vector-art // rendering (e.g. Sierra-style picture playback): outline a closed // region with drawLine in boundaryColor, then fill with this. void floodFillBounded(SurfaceT *s, int16_t x, int16_t y, uint8_t newColor, uint8_t boundaryColor); // Blit an asset onto the surface at (x, y). Source nibbles overwrite // destination nibbles verbatim -- the caller is responsible for // matching the asset's palette to the destination palette (typically // via joeyAssetApplyPalette). Clipped to the surface; off-surface // rows / columns are skipped. void surfaceBlit(SurfaceT *dst, const JoeyAssetT *src, int16_t x, int16_t y); // Like surfaceBlit, but source pixels equal to transparentIndex are // skipped, leaving the destination pixel unchanged at that position. // The standard convention is transparentIndex = 0. void surfaceBlitMasked(SurfaceT *dst, const JoeyAssetT *src, int16_t x, int16_t y, uint8_t transparentIndex); #endif