milsko/src/backend/cairo.c
2026-07-19 20:37:04 +09:00

265 lines
8.5 KiB
C

#include <Mw/Milsko.h>
#include "../../external/stb_ds.h"
cairo_call_table_t cairo_call_tbl;
void MwLLCairoPolygon(struct _MwLLCairo handle, MwPoint* points, int points_count, MwLLColor color) {
int i;
cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle.front_cairo);
for(i = 0; i < points_count; i++) {
if(i == 0) {
cairo_move_to(handle.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle.front_cairo);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_SOURCE);
cairo_fill(handle.front_cairo);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER);
};
void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) {
int i;
cairo_set_antialias(handle.front_cairo, CAIRO_ANTIALIAS_NONE);
cairo_set_line_cap(handle.front_cairo, CAIRO_LINE_CAP_SQUARE);
cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle.front_cairo);
for(i = 0; i < 2; i++) {
if(i == 0) {
cairo_move_to(handle.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle.front_cairo);
cairo_stroke(handle.front_cairo);
};
MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height) {
MwLLPixmap r = malloc(sizeof(*r));
(void)handle;
if(width >= INT16_MAX) width = INT16_MAX;
if(height >= INT16_MAX) height = INT16_MAX;
r->common.width = width;
r->common.height = height;
r->common.raw = malloc(4 * width * height);
memcpy(r->common.raw, data, 4 * width * height);
r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
MwLLPixmapUpdate(r);
return r;
}
void MwLLCairoPixmapUpdate(MwLLPixmap r) {
int i;
unsigned char* d;
cairo_surface_flush(r->wayland.cs);
d = cairo_image_surface_get_data(r->wayland.cs);
for(i = 0; i < r->common.width * r->common.height * 4; i += 4) {
MwU32* p = (MwU32*)&d[i];
*p <<= 8;
*p |= r->common.raw[i + 3];
*p <<= 8;
*p |= r->common.raw[i + 0];
*p <<= 8;
*p |= r->common.raw[i + 1];
*p <<= 8;
*p |= r->common.raw[i + 2];
}
cairo_surface_mark_dirty(r->wayland.cs);
}
void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) {
cairo_surface_destroy(pixmap->wayland.cs);
free(pixmap->common.raw);
free(pixmap);
}
void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_t* c;
cairo_surface_t* cs;
cairo_t* selected_cairo = handle.selected_cairo ? handle.selected_cairo : handle.front_cairo;
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height);
c = cairo_create(cs);
if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return;
if(rect->width >= INT16_MAX) rect->width = INT16_MAX;
if(rect->height >= INT16_MAX) rect->height = INT16_MAX;
cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height);
cairo_set_source_surface(c, pixmap->cairo.cs, 0, 0);
cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER);
cairo_paint(c);
cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y);
cairo_paint(selected_cairo);
cairo_destroy(c);
cairo_surface_destroy(cs);
};
void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
if(data) {
cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
} else {
cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
}
cairo->front_cairo = cairo_create(cairo->front_cs);
}
void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
if(data) {
cairo->back_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
} else {
cairo->back_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
}
cairo->back_cairo = cairo_create(cairo->back_cs);
}
void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->front_cairo);
cairo_surface_destroy(cairo->front_cs);
};
void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->back_cairo);
cairo_surface_destroy(cairo->back_cs);
};
void MwLLCairoDestroy(struct _MwLLCairo handle) {
// MwLLCairoFrontDestroy(&handle);
// MwLLCairoBackDestroy(&handle);
}
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
MwLL r;
r = malloc(sizeof(*r));
memset(r, 0, sizeof(*r));
MwLLCreateCommon(r);
r->cairo.width = width;
r->cairo.height = height;
r->cairo.x = x;
r->cairo.y = x;
r->cairo.toplevel = !parent;
r->cairo.parent = parent;
MwLLCairoFrontSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height);
MwLLCairoBackSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height);
return r;
}
static void MwLLDestroyImpl(MwLL handle) {
MwLLCairoDestroy(handle->cairo);
free(handle);
}
static void MwLLBeginDrawImpl(MwLL handle) {
handle->cairo.selected_cairo = handle->cairo.front_cairo;
}
static void MwLLEndDrawImpl(MwLL handle) {
}
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
MwLLCairoPolygon(handle->cairo, points, points_count, color);
}
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
MwLLCairoLine(handle->cairo, points, color);
}
static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) {
MwLLColor c = malloc(sizeof(*c));
MwLLColorUpdate(handle, c, r, g, b);
return c;
}
static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) {
(void)handle;
c->common.red = r;
c->common.green = g;
c->common.blue = b;
}
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
(void)handle;
*x = handle->cairo.x;
*y = handle->cairo.y;
*w = handle->cairo.width;
*h = handle->cairo.height;
}
static void MwLLSetXYImpl(MwLL handle, int x, int y) {
handle->cairo.x = x;
handle->cairo.y = y;
}
static void MwLLSetWHImpl(MwLL handle, int w, int h) {
handle->cairo.width = w;
handle->cairo.height = h;
}
static void MwLLFreeColorImpl(MwLLColor color) {}
static MwBool lmao = MwFALSE;
static int MwLLPendingImpl(MwLL handle) {
lmao = !lmao;
return lmao;
}
static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, draw, NULL);
}
static void MwLLSetTitleImpl(MwLL handle, const char* title) {}
static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) {
return MwLLCairoCreatePixmap(handle->cairo, data, width, height);
}
static void MwLLPixmapUpdateImpl(MwLLPixmap r) {
MwLLCairoPixmapUpdate(r);
}
static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
MwLLCairoPixmapUpdate(pixmap);
}
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
MwLLCairoDrawPixmap(handle->cairo, rect, pixmap);
}
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {}
static void MwLLForceRenderImpl(MwLL handle) {}
static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {}
static void MwLLDetachImpl(MwLL handle, MwPoint* point) {}
static void MwLLShowImpl(MwLL handle, int show) {}
static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {}
static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {}
static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) {}
static void MwLLFocusImpl(MwLL handle) {}
static void MwLLGrabPointerImpl(MwLL handle, int toggle) {}
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {}
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {}
static void MwLLMakeToolWindowImpl(MwLL handle) {}
static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {}
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {}
static void MwLLBeginStateChangeImpl(MwLL handle) {}
static void MwLLEndStateChangeImpl(MwLL handle) {}
static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) {}
static MwBool MwLLDoModernImpl(MwLL handle) {
return MwFALSE;
}
static void MwLLRaiseImpl(MwLL handle) {}
static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
static int MwLLCairoCallInitImpl(void) {
if(cairo_load_funcs() != 0) {
return 1;
}
return 0;
}
#include "call.c"
CALL(Cairo);