inline s32 RoundFloatToInt(float value)
{
    return static_cast<s32>(value + 0.5);
}

struct V4: public ImVec4
{
    using ImVec4::ImVec4;
    float &a = ImVec4::w;
    float &r = ImVec4::x;
    float &g = ImVec4::y;
    float &b = ImVec4::z;
};

inline u32 V4ToARGB(V4 c)
{
    u32 result = ((RoundFloatToInt(c.a * 255.0) & 0xff) << 24
                  | (RoundFloatToInt(c.r * 255.0) & 0xff) << 16
                  | (RoundFloatToInt(c.g * 255.0) & 0xff) <<  8
                  | (RoundFloatToInt(c.b * 255.0) & 0xff) <<  0);
    return result;
}

struct OffscreenBuffer
{
    s32 width;
    s32 height;
    u8 *pixels;
    s32 pitch;
    const int BytesPerPixel;
};

inline void PutPixelUnchecked(OffscreenBuffer *buffer, s32 x, s32 y, V4 color)
{
        u32 *pixel = reinterpret_cast<u32 *>(buffer->pixels
                                             + y * buffer->pitch
                                             + x * buffer->BytesPerPixel);
        *pixel = V4ToARGB(color);
}

inline void PutPixel(OffscreenBuffer *buffer, s32 x, s32 y, V4 color)
{
    if (x >= 0 && x < buffer->width && y >= 0 && y < buffer->height)
    {
        PutPixelUnchecked(buffer, x, y, color);
    }
}

void DrawRectangle(OffscreenBuffer *buffer,
        float realMinX, float realMinY,
        float realMaxX, float realMaxY,
        V4 color)

{
    s32 minX = RoundFloatToInt(realMinX);
    s32 minY = RoundFloatToInt(realMinY);
    s32 maxX = RoundFloatToInt(realMaxX);
    s32 maxY = RoundFloatToInt(realMaxY);

    if (minX < 0)
        minX = 0;

    if (minY < 0)
        minY = 0;

    if (maxX > buffer->width)
        maxX = buffer->width;

    if (maxY > buffer->height)
        maxY = buffer->height;


    u8 *row = buffer->pixels + minY * buffer->pitch;

    for (s32 y = minY; y < maxY; ++y)
    {
        u32 *dstPixel = reinterpret_cast<u32 *>(row + minX * buffer->BytesPerPixel);

        for (s32 x = minX; x < maxX; ++x)
        {
            float a = color.a;
            float srcR = color.r * 255.0;
            float srcG = color.g * 255.0;
            float srcB = color.b * 255.0;

            float dstR = ((*dstPixel >> 16) & 0xff);
            float dstG = ((*dstPixel >>  8) & 0xff);
            float dstB = ((*dstPixel >>  0) & 0xff);

            dstR = (1 - a) * dstR + a * srcR;
            dstG = (1 - a) * dstG + a * srcG;
            dstB = (1 - a) * dstB + a * srcB;

            *dstPixel = (RoundFloatToInt(dstR) << 16 |
                         RoundFloatToInt(dstG) <<  8 |
                         RoundFloatToInt(dstB) <<  0);

            ++dstPixel;
        }

        row += buffer->pitch;
    }
}
