#pragma once #include "../util/minmax.h" #include "color.h" #include "stdint.h" #include "string.h" static inline void __graphics_CopyBuffer32( void *from, // Source image of the copy int fromOffsetX, // OffsetX of the region to copy from int fromOffsetY, // OffsetY of the region to copy from int fromSizeX, // SizeX of the entire source image int fromSizeY, // SizeY of the entire source image void *to, // Destination image of the copy int toOffsetX, // OffsetX of the target region int toOffsetY, // OffsetY of the target region int toSizeX, // SizeX of the entire destination image int toSizeY, // SizeY of the entire destination image int countX, // Size of the copying region int countY) { int beginX = intmax3(0, -fromOffsetX, -toOffsetX), beginY = intmax3(0, -fromOffsetY, -toOffsetY); int endX = intmin3(countX, fromSizeX - fromOffsetX, toSizeX - toOffsetX), endY = intmin3(countY, fromSizeY - fromOffsetY, toSizeY - toOffsetY); #define PIXEL_BYTES ((intptr_t)4) for (int i = beginY; i < endY; i++) memcpy( ((intptr_t)toOffsetX + beginX + (intptr_t)toSizeX * (toOffsetY + i)) * PIXEL_BYTES + (uint8_t *)to, ((intptr_t)fromOffsetX + beginX + (intptr_t)fromSizeX * (fromOffsetY + i)) * PIXEL_BYTES + (uint8_t *)from, (endX - beginX) * PIXEL_BYTES); #undef PIXEL_BYTES } // Blends ARGB Premultiplied Alpha image onto (opaque) buffer // See: https://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha/ static inline void __graphics_RenderBuffer32( void *from, // Source image of the render int fromOffsetX, // OffsetX of the region to render from int fromOffsetY, // OffsetY of the region to render from int fromSizeX, // SizeX of the entire source image int fromSizeY, // SizeY of the entire source image void *to, // Destination image of the render int toOffsetX, // OffsetX of the target region int toOffsetY, // OffsetY of the target region int toSizeX, // SizeX of the entire destination image int toSizeY, // SizeY of the entire destination image int countX, // Size of the render region int countY) { int beginX = intmax3(0, -fromOffsetX, -toOffsetX), beginY = intmax3(0, -fromOffsetY, -toOffsetY); int endX = intmin3(countX, fromSizeX - fromOffsetX, toSizeX - toOffsetX), endY = intmin3(countY, fromSizeY - fromOffsetY, toSizeY - toOffsetY); for (int x = beginX; x < endX; x++) for (int y = beginY; y < endY; y++) { HelosGraphics_Color *src = ((intptr_t)fromOffsetX + x + (intptr_t)fromSizeX * (fromOffsetY + y)) + (HelosGraphics_Color *)from, *dest = ((intptr_t)toOffsetX + x + (intptr_t)toSizeX * (toOffsetY + y)) + (HelosGraphics_Color *)to; if (src->A == 0) continue; else if (src->A == 0xff) *(uint32_t *)dest = *(uint32_t *)src & 0x00ffffffu; else { // blend HelosGraphics_Color color = { .B = (uint8_t)(src->B + ((int)dest->B) * (0xff - src->A) / 0xff), .G = (uint8_t)(src->G + ((int)dest->G) * (0xff - src->A) / 0xff), .R = (uint8_t)(src->R + ((int)dest->R) * (0xff - src->A) / 0xff), .A = 0}; *dest = color; } } }