From c9d289f9239c96073873ea8e8ad4904b222c9513 Mon Sep 17 00:00:00 2001 From: Annika Date: Tue, 7 Jul 2026 03:25:10 -0700 Subject: [PATCH] added missing files --- buffer.cpp | 46 ++++++++ draw | Bin 0 -> 41184 bytes draw.cpp | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++ surface.cpp | 80 ++++++++++++++ 4 files changed, 439 insertions(+) create mode 100644 buffer.cpp create mode 100755 draw create mode 100644 draw.cpp create mode 100644 surface.cpp diff --git a/buffer.cpp b/buffer.cpp new file mode 100644 index 0000000..a6babec --- /dev/null +++ b/buffer.cpp @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include "datatypes.cpp" +#include "helpers.cpp" + +namespace UwU { + // Buffer object - can be a wayland surface or a virtual buffer + class Buffer { + public: + Buffer(uint16_t width, uint16_t height) { + uint8_t pixels[width * height * 4]; + this->pixels = pixels; + this->width = width; + this->height = height; + this->stride = width * 4; + } + // Buffer(uint8_t* pixels, uint16_t width, uint16_t height, uint16_t stride) { + // this->pixels = pixels; + // this->width = width; + // this->height = height; + // this->stride = stride; + // } + Buffer() {} + uint8_t* pixels; + uint16_t width; + uint16_t height; + uint16_t stride; + + void drawPixel(Coord2 coord, Color color) { + size_t i = (size_t)coord.y * stride + (size_t)coord.x * 4; + uint8_t b0 = pixels[i + 0]; + uint8_t g0 = pixels[i + 1]; + uint8_t r0 = pixels[i + 2]; + uint8_t b = Helpers::lerp8(b0, color.b, color.a); + uint8_t g = Helpers::lerp8(g0, color.g, color.a); + uint8_t r = Helpers::lerp8(r0, color.r, color.a); + pixels[i + 0] = b; // B + pixels[i + 1] = g; // G + pixels[i + 2] = r; // R + pixels[i + 3] = 0xff; // A + return; + } + }; +} \ No newline at end of file diff --git a/draw b/draw new file mode 100755 index 0000000000000000000000000000000000000000..cf98c585ac88d73c168a53277d348044bb8a2be3 GIT binary patch literal 41184 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 literal 0 HcmV?d00001 diff --git a/draw.cpp b/draw.cpp new file mode 100644 index 0000000..96568e8 --- /dev/null +++ b/draw.cpp @@ -0,0 +1,313 @@ +/* Example program that links against the waymini library. + * No external dependencies beyond waymini itself and the C standard library. + */ + +#include "waymini.h" + +#include +#include +#include +#include + +#include "datatypes.cpp" +#include "helpers.cpp" +#include "triangle.cpp" +#include "buffer.cpp" +#include "surface.cpp" + +// this should be handled elsewhere, eventually, maybe, probably +static void onKey(void *user, uint32_t keycode, uint32_t state) { + if (keycode == 1) { + exit(1); + } + (void)user; + const char *label = state ? "down" : "up "; + printf("key %s: %u\n", label, keycode); + fflush(stdout); +} + +namespace UwU { + + class Draw { + private: + class Surface surface; + // void putPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 0xff) { + // size_t i = (size_t)y * surface.getStride() + (size_t)x * 4; + // uint8_t b0 = pixels[i + 0]; + // uint8_t g0 = pixels[i + 1]; + // uint8_t r0 = pixels[i + 2]; + // b = Helpers::lerp8(b0, b, a); + // g = Helpers::lerp8(g0, g, a); + // r = Helpers::lerp8(r0, r, a); + // pixels[i + 0] = b; // B + // pixels[i + 1] = g; // G + // pixels[i + 2] = r; // R + // pixels[i + 3] = 0xff; // A + // } + + // plot lines if m <= 1 + void lineLow(int32_t x0, int32_t y0, int32_t x1, int32_t y1, Color color) { + int32_t dx = x1 - x0; + int32_t dy = y1 - y0; + int32_t yi = 1; + if (dy < 0) { + yi = -1; + dy = -dy; + } + int32_t d = (2 * dy) - dx; + int32_t y = y0; + for (int32_t x = x0; x < x1; x++) { + // putPixel(x, y, color.r, color.g, color.b, color.a); + surface.buffer.drawPixel(Coord2((uint16_t)x, (uint16_t)y), color); + if (d > 0) { + y += yi; + d += (2 * (dy - dx)); + } else { + d += (2 * dy); + } + } + return; + } + + // plot lines if m >1 + void lineHigh(int32_t x0, int32_t y0, int32_t x1, int32_t y1, Color color) { + int32_t dx = x1 - x0; + int32_t dy = y1 - y0; + int32_t xi = 1; + if (dx < 0) { + xi = -1; + dx = -dx; + } + int32_t d = (2 * dx) - dy; + int32_t x = x0; + for (int32_t y = y0; y < y1; y++) { + // putPixel(x, y, color.r, color.g, color.b, color.a); + surface.buffer.drawPixel(Coord2((uint16_t)x, (uint16_t)y), color); + if (d > 0) { + x += xi; + d += (2 * (dx - dy)); + } else { + d += (2 * dx); + } + } + return; + } + + public: + + + Draw(uint16_t width, uint16_t height, waymini_key_cb onKey) + : surface(width, height, onKey) {} + + bool shouldClose() { + return surface.shouldClose(); + } + + void updateSize() { + surface.updateSize(); + return; + } + + uint16_t getWidth() { + return surface.getWidth(); + } + + uint16_t getHeight() { + return surface.getHeight(); + } + + uint16_t getStride() { + return surface.getStride(); + } + + void present() { + surface.present(); + return; + } + + void destroy() { + surface.destroy(); + return; + } + + // Draw a rectangle (duh) + void rectangle(Coord2 point0, Coord2 point1, Color color) { + if (point0.x > getWidth() || point0.y > getHeight() || point1.x > getWidth() || point1.y > getHeight()) {return;}; + for (uint32_t y = point0.y; y < point1.y; y++) { + for (uint32_t x = point0.x; x < point1.x; x++) { + // putPixel(x, y, color.r, color.g, color.b, color.a); + surface.buffer.drawPixel(Coord2((uint16_t)x, (uint16_t)y), color); + } + } + return; + } + + // Draws a rectangle with a 4-point color gradient + void rectangleGradient(Coord2 point0, Coord2 point1, Color colorUL, Color colorUR, Color colorLL, Color colorLR) { + // convert to int32_t and ensure x1>x0 && y1>y0 + int32_t x0, y0, x1, y1; + if (point0.x > point1.x) { + x0 = (int32_t)point1.x; + x1 = (int32_t)point0.x; + } else { + x0 = (int32_t)point0.x; + x1 = (int32_t)point1.x; + } + if (point0.y > point1.y) { + y0 = (int32_t)point1.y; + y1 = (int32_t)point0.y; + } else { + y0 = (int32_t)point0.y; + y1 = (int32_t)point1.y; + } + + // setup gradient coefficient arrays + int32_t w = x1 - x0 + 1; + int32_t h = y1 - y0 + 1; + int16_t xGrad[w]; + int16_t yGrad[h]; + + // calculate gradient coefficients + Helpers::bresenham(0, 0, w - 1, 255, xGrad); + Helpers::bresenham(0, 0, h - 1, 255, yGrad); + + // for each point calculate, alpha blend and print color + Color Lmix = Color(); + Color Rmix = Color(); + Color Xmix = Color(); + for (int32_t y = y0; y <= y1; y++) { + Lmix = Helpers::lerpColor(colorUL, colorLL, (uint8_t)yGrad[y - y0]); + Rmix = Helpers::lerpColor(colorUR, colorLR, (uint8_t)yGrad[y - y0]); + for (int32_t x = x0; x <= x1; x++) { + Xmix = Helpers::lerpColor(Lmix, Rmix, (uint8_t)xGrad[x - x0]); + // putPixel(x, y, Xmix.r, Xmix.g, Xmix.b, Xmix.a); + surface.buffer.drawPixel(Coord2((uint16_t)x, (uint16_t)y), Xmix); + } + } + return; + } + + // Fill a simple gradient. Each row is stride bytes. + void rainbow() { + for (uint32_t y = 0; y < getHeight(); y++) { + for (uint32_t x = 0; x < getWidth(); x++) { + surface.buffer.drawPixel(Coord2((uint16_t)x, (uint16_t)y), Color( + (uint8_t)(y * 255 / getHeight()), + 0x00, + (uint8_t)(x * 255 / getWidth()), + 0xff)); + // size_t i = (size_t)y * getStride() + (size_t)x * 4; + // pixels[i + 0] = (uint8_t)(y * 255 / getHeight()); // B + // pixels[i + 1] = 0x00; // G + // pixels[i + 2] = (uint8_t)(x * 255 / getWidth()); // R + // pixels[i + 3] = 0xFF; // A + } + } + } + + // Draw a single point + void point (Coord2 point, Color color) { + if (point.x > getWidth() || point.y > getHeight()) {return;}; + // putPixel(point.x, point.y, color.r, color.g, color.b, color.a); + surface.buffer.drawPixel(point, color); + } + + // Uses Bresenham's line algorithm to draw line of any slope + void line (Coord2 point0, Coord2 point1, Color color) { + if (point0.x > getWidth() || point0.y > getHeight() || point1.x > getWidth() || point1.y > getHeight()) {return;}; + int32_t x0 = (int32_t)point0.x; + int32_t y0 = (int32_t)point0.y; + int32_t x1 = (int32_t)point1.x; + int32_t y1 = (int32_t)point1.y; + if (abs(y1 - y0) < abs(x1 - x0)) { + if (x0 > x1) { + lineLow(x1, y1, x0, y0, color); + } else { + lineLow(x0, y0, x1, y1, color); + } + } else { + if (y0 > y1) { + lineHigh(x1, y1, x0, y0, color); + } else { + lineHigh(x0, y0, x1, y1, color); + } + } + } + + // Draw a horizontally bounded trapezoid + // coords.y1 >= coords.y0 + // todo move to private and add public checks + void trapezoid (Trapezoid coords, Color color) { + printf("(%u, %u, %u, %u, %u, %u)", coords.y0, coords.y1, coords.xl0, coords.xl1, coords.xr0, coords.xr1); + uint16_t height = 1 + coords.y1 - coords.y0; + int16_t LeftBound[height]; + int16_t RightBound[height]; + + Helpers::bresenham(0, coords.xl0, coords.y1 - coords.y0, coords.xl1, LeftBound); + Helpers::bresenham(0, coords.xr0, coords.y1 - coords.y0, coords.xr1, RightBound); + + printf("leftbound\n"); + for (uint16_t i = 0; i < height; i++) { + printf("(%u, %u)\n", i, LeftBound[i]); + } + printf("rightbound\n"); + for (uint16_t i = 0; i < height; i++) { + printf("(%u, %u)\n", i, RightBound[i]); + } + + for (uint16_t i = 0; i < height; i++) { + for (uint16_t x = LeftBound[i]; x <= RightBound[i]; x++) { + // printf("(%u, %u)", x, i + coords.y0); + surface.buffer.drawPixel(Coord2(x, i + coords.y0), color); + } + } + return; + } + + // Draw a triangle + void triangle (uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, Color color) { + Triangle triangle = Triangle(x0, y0, x1, y1, x2, y2); + triangle.draw(surface.buffer, color); + return; + } + }; + } + +int main(void) { + uint32_t w = 800, h = 480; + UwU::Color fuchsia = UwU::Color(0xb00b6940); + UwU::Color red = UwU::Color(0xff0000ff); + UwU::Color green = UwU::Color(0x00ff00ff); + UwU::Color blue = UwU::Color(0x0000ffff); + UwU::Color alpha = UwU::Color(0x00000000); + printf("r: %u, g:%u, b:%u, a:%u\n", fuchsia.r, fuchsia.g, fuchsia.b, fuchsia.a); + + // struct waymini *wm = waymini_create(w, h, on_key, NULL); + UwU::Draw draw = UwU::Draw(w, h, onKey); + + draw.rainbow(); + + + draw.rectangle(UwU::Coord2(69, 69), UwU::Coord2(420, 420), fuchsia); + draw.rectangleGradient(UwU::Coord2(200, 200), UwU::Coord2(600, 400), red, blue, alpha, red); + + draw.trapezoid(UwU::Trapezoid(300, 400, 360, 380, 600, 400), green); + draw.triangle(280, 100, 240, 290, 320, 300, green); + + + draw.point(UwU::Coord2(387, 43), green); + draw.line(UwU::Coord2(300, 100), UwU::Coord2(250, 469), green); + draw.line(UwU::Coord2(250, 100), UwU::Coord2(300, 469), green); + draw.line(UwU::Coord2(300, 100), UwU::Coord2(469, 250), green); + draw.line(UwU::Coord2(469, 100), UwU::Coord2(300, 250), green); + draw.line(UwU::Coord2(100, 300), UwU::Coord2(250, 469), green); + draw.line(UwU::Coord2(250, 300), UwU::Coord2(100, 469), green); + draw.line(UwU::Coord2(100, 300), UwU::Coord2(469, 250), green); + draw.line(UwU::Coord2(469, 300), UwU::Coord2(100, 250), green); + draw.present(); + + while (!draw.shouldClose()) {} + + draw.destroy(); + return 0; +} diff --git a/surface.cpp b/surface.cpp new file mode 100644 index 0000000..d11d318 --- /dev/null +++ b/surface.cpp @@ -0,0 +1,80 @@ +#pragma once + +#include "waymini.h" + +#include +#include +#include +#include + +#include "datatypes.cpp" +#include "buffer.cpp" + +namespace UwU { + class Surface { + public: + Surface(uint16_t width, uint16_t height, waymini_key_cb onKey) { + this->wm = waymini_create((uint32_t)width, (uint32_t)height, onKey, NULL); + if (!this->wm) exit(1); + + // this->buffer = Buffer( + // (uint8_t*)waymini_get_pixels(this->wm), + // waymini_get_width(this->wm), + // waymini_get_height(this->wm), + // waymini_get_stride(this->wm)); + this->buffer.pixels = (uint8_t*)waymini_get_pixels(this->wm); + this->buffer.width = waymini_get_width(this->wm); + this->buffer.height = waymini_get_height(this->wm); + this->buffer.stride = waymini_get_stride(this->wm); + printf("surface: %ux%u stride=%u\n", waymini_get_width(this->wm), waymini_get_height(this->wm), waymini_get_stride(this->wm)); + + if (!this->buffer.pixels) { + waymini_destroy(this->wm); + exit(1); + } + } + class Buffer buffer; + struct waymini* wm; + + // get current size of wayland surface and update buffer + void updateSize() { + buffer.width = waymini_get_width(wm); + buffer.height = waymini_get_height(wm); + buffer.stride = waymini_get_stride(wm); + return; + } + + uint32_t getWidth() { + updateSize(); + return buffer.width; + } + + uint32_t getHeight() { + updateSize(); + return buffer.height; + } + + uint32_t getStride() { + updateSize(); + return buffer.stride; + } + + void present() { + waymini_present(wm); + return; + } + + void destroy() { + waymini_destroy(wm); + return; + } + + bool shouldClose() { + if (waymini_should_close(wm) || waymini_dispatch(wm) < 0) { + return true; + } else { + return false; + } + } + }; +} \ No newline at end of file