// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// dvx_draw.h  -- Layer 2: Drawing primitives for DVX GUI
//
// Provides all 2D drawing operations: rectangle fills, bitmap blits, text
// rendering, bevels, lines, and cursor/icon rendering. Every function in
// this layer draws into the display's backbuffer and clips to the display's
// current clip rectangle  -- no direct LFB writes happen here.
//
// This layer is deliberately stateless beyond the clip rect on DisplayT.
// All drawing context (colors, fonts, bevel styles) is passed explicitly
// to each function. This means the draw layer can be used by any caller
// (compositor, WM, widgets) without worrying about shared mutable state.
//
// Performance strategy: the hot inner loops (span fill, span copy) are
// dispatched through BlitOpsT function pointers that resolve to asm on
// DOS. The text rendering functions (drawTextN, drawTermRow) are optimized
// to batch operations per scanline rather than per glyph, which matters
// when rendering 80-column terminal screens on a 486.
#ifndef DVX_DRAW_H
#define DVX_DRAW_H

#include "dvxTypes.h"

// Populate a BlitOpsT with the correct span functions for the display's
// pixel depth. Must be called once after videoInit().
void drawInit(BlitOpsT *ops, const DisplayT *d);

// Fill a rectangle with a solid color. Clips to the display clip rect.
// This is the workhorse for backgrounds, window fills, and clear operations.
void rectFill(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);

// Copy a rectangle from an arbitrary source buffer into the backbuffer.
// Used to blit per-window content buffers during compositing. srcX/srcY
// specify the origin within the source buffer, allowing sub-rectangle blits.
void rectCopy(DisplayT *d, const BlitOpsT *ops, int32_t dstX, int32_t dstY, const uint8_t *srcBuf, int32_t srcPitch, int32_t srcX, int32_t srcY, int32_t w, int32_t h);

// Copy with grayscale conversion. Each pixel's RGB is converted to
// luminance (0.299R + 0.587G + 0.114B) for a disabled/grayed appearance.
void rectCopyGrayscale(DisplayT *d, const BlitOpsT *ops, int32_t dstX, int32_t dstY, const uint8_t *srcBuf, int32_t srcPitch, int32_t srcX, int32_t srcY, int32_t w, int32_t h);

// Copy with color-key transparency. Pixels matching keyColor are skipped,
// letting the destination (background) show through.
void rectCopyTransparent(DisplayT *d, const BlitOpsT *ops, int32_t dstX, int32_t dstY, const uint8_t *srcBuf, int32_t srcPitch, int32_t srcX, int32_t srcY, int32_t w, int32_t h, uint32_t keyColor);

// Draw a beveled frame. The bevel is drawn as overlapping horizontal and
// vertical spans  -- top/left in highlight color, bottom/right in shadow.
// The face color fills the interior if non-zero.
void drawBevel(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, const BevelStyleT *style);

// Draw a single character glyph. When opaque is true, the background color
// fills the entire cell; when false, only foreground pixels are drawn
// (transparent background). Returns the advance width (always charWidth).
int32_t drawChar(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, char ch, uint32_t fg, uint32_t bg, bool opaque);

// Draw a null-terminated string. Calls drawChar per character.
void drawText(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, uint32_t fg, uint32_t bg, bool opaque);

// Optimized batch text rendering for a known character count. Computes
// clip bounds once for the entire run, fills the background in a single
// rectFill, then overlays glyph foreground pixels. Significantly faster
// than drawChar-per-character for long runs (e.g. terminal rows, list items).
void drawTextN(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, int32_t count, uint32_t fg, uint32_t bg, bool opaque);

// Returns the pixel width of a null-terminated string (count * charWidth).
int32_t textWidth(const BitmapFontT *font, const char *text);

// Scan text for an & prefix and return the following character as a
// lowercase accelerator key. "&File" -> 'f', "E&xit" -> 'x'.
// Used by menu and button construction to extract keyboard shortcuts.
char accelParse(const char *text);

// Draw text with & accelerator markers. The character after & is drawn
// with an underline to indicate the keyboard shortcut. && produces a
// literal &. Used for menu items and button labels.
void drawTextAccel(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, uint32_t fg, uint32_t bg, bool opaque);

// Measure text width excluding & markers (so "&File" measures as 4 chars).
int32_t textWidthAccel(const BitmapFontT *font, const char *text);

// Draw a 1-bit AND/XOR masked bitmap. Used for software-rendered mouse
// cursors. See CursorT for the mask encoding conventions.
void drawMaskedBitmap(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *andMask, const uint16_t *xorData, uint32_t fgColor, uint32_t bgColor);

// Render an entire row of terminal character cells (ch/attr byte pairs)
// in a single pass. Each cell's foreground and background colors are
// looked up from a 16-color palette. Attribute bit 7 controls blink:
// when blinkVisible is false, blinking characters are hidden. cursorCol
// specifies which column to draw inverted as the text cursor (-1 for none).
// This function exists because rendering an 80-column terminal row
// character-by-character would be unacceptably slow on target hardware.
void drawTermRow(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, int32_t cols, const uint8_t *lineData, const uint32_t *palette, bool blinkVisible, int32_t cursorCol);

// Draw a 1px dotted rectangle (alternating pixels). Used for keyboard
// focus indicators on buttons and other focusable widgets, matching the
// Windows 3.x focus rectangle convention.
void drawFocusRect(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);

// Compute the (x, y) origin for rendering `text` centered both
// horizontally and vertically inside the rect (rectX, rectY, rectW,
// rectH).  Measures `text` with textWidthAccel (ignores & markers) and
// the font's charHeight.  Writes results to *outX / *outY.
void calcCenteredText(const BitmapFontT *font, int32_t rectX, int32_t rectY, int32_t rectW, int32_t rectH, const char *text, int32_t *outX, int32_t *outY);

// Draw `text` with &-accelerator markers, automatically choosing
// between the enabled and disabled (embossed) rendering paths.  Saves
// the if/else block every widget paints around drawTextAccel /
// drawTextAccelEmbossed.
void drawWidgetTextAccel(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, uint32_t fg, uint32_t bg, bool opaque, bool enabled, const ColorSchemeT *colors);

// Draw a pressable 2px bevel.  When pressed is true, highlight/shadow
// colors swap to produce the "sunken" look (button pressed, toggle
// checked).  face is the fill color; pass 0 to leave the interior
// alone.  Used by buttons, checkboxes, toggle bars, etc.
void drawPressableBevel(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, bool pressed, uint32_t face, const ColorSchemeT *colors);

// Draw a 1px rectangle outline (4 edges) in a single color.  Issues a
// top/bottom drawHLine and left/right drawVLine, clipped like the underlying
// primitives.  Replaces the repeated 4-line outline idiom used for tooltips,
// debug borders, and title-bar gadget icons.
void drawRectOutline(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);

// Paint a complete scrollbar: sunken trough bevel, an arrow button at each
// end, and a raised thumb at (barW + thumbPos) along the track.  orient
// selects the axis; thumbSize <= 0 suppresses the thumb entirely.
void drawScrollbar(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, ScrollbarOrientE orient, int32_t x, int32_t y, int32_t length, int32_t barW, int32_t thumbPos, int32_t thumbSize);

// Draw a small triangular arrow glyph centered in a scrollbar button.
// dir selects the direction (up/down/left/right).
void drawScrollbarArrow(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t x, int32_t y, int32_t size, ScrollArrowDirE dir);

// Horizontal line (1px tall rectangle fill, but with simpler clipping).
void drawHLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, uint32_t color);

// Vertical line (1px wide, drawn pixel-by-pixel down each scanline).
void drawVLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t h, uint32_t color);

#endif // DVX_DRAW_H
