/*
 * Change Logs:
 * Date           Author       Notes
 * 2012-01-24     onelife      add mono color support
 */
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>

#define gfx_device      (rtgui_graphic_get_device()->device)
#define gfx_device_ops  rt_graphix_ops(gfx_device)

static void _pixel_mono_set_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint8_t pixel;

    pixel = rtgui_color_to_mono(*c);
    gfx_device_ops->set_pixel((char *)&pixel, x, y);
}

static void _pixel_rgb565p_set_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565p(*c);
    gfx_device_ops->set_pixel((char *)&pixel, x, y);
}

static void _pixel_rgb565_set_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565(*c);
    gfx_device_ops->set_pixel((char *)&pixel, x, y);
}

static void _pixel_rgb888_set_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint32_t pixel;

    pixel = rtgui_color_to_888(*c);
    gfx_device_ops->set_pixel((char *)&pixel, x, y);
}

static void _pixel_mono_get_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint8_t pixel;

    gfx_device_ops->get_pixel((char *)&pixel, x, y);
    *c = rtgui_color_from_mono(pixel);
}

static void _pixel_rgb565p_get_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint16_t pixel;

    gfx_device_ops->get_pixel((char *)&pixel, x, y);
    *c = rtgui_color_from_565p(pixel);
}

static void _pixel_rgb565_get_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint16_t pixel;

    gfx_device_ops->get_pixel((char *)&pixel, x, y);
    *c = rtgui_color_from_565(pixel);
}

static void _pixel_rgb888_get_pixel(rtgui_color_t *c, int x, int y)
{
    rt_uint32_t pixel;

    gfx_device_ops->get_pixel((char *)&pixel, x, y);
    *c = rtgui_color_from_888(pixel);
}

static void _pixel_mono_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
    rt_uint8_t pixel;

    pixel = rtgui_color_to_mono(*c);
    gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}

static void _pixel_rgb565p_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565p(*c);
    gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}

static void _pixel_rgb565_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565(*c);
    gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}

static void _pixel_rgb888_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
    rt_uint32_t pixel;

    pixel = rtgui_color_to_888(*c);
    gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}

static void _pixel_mono_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
    rt_uint8_t pixel;

    pixel = rtgui_color_to_mono(*c);
    gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}

static void _pixel_rgb565p_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565p(*c);
    gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}

static void _pixel_rgb565_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
    rt_uint16_t pixel;

    pixel = rtgui_color_to_565(*c);
    gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}

static void _pixel_rgb888_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
    rt_uint32_t pixel;

    pixel = rtgui_color_to_888(*c);
    gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}

static void _pixel_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
{
    if (x2 > x1)
        gfx_device_ops->blit_line((char *)pixels, x1, y, (x2 - x1));
    else
        gfx_device_ops->blit_line((char *)pixels, x2, y, (x1 - x2));
}

/* pixel device */
const struct rtgui_graphic_driver_ops _pixel_mono_ops =
{
    _pixel_mono_set_pixel,
    _pixel_mono_get_pixel,
    _pixel_mono_draw_hline,
    _pixel_mono_draw_vline,
    _pixel_draw_raw_hline,
};

const struct rtgui_graphic_driver_ops _pixel_rgb565p_ops =
{
    _pixel_rgb565p_set_pixel,
    _pixel_rgb565p_get_pixel,
    _pixel_rgb565p_draw_hline,
    _pixel_rgb565p_draw_vline,
    _pixel_draw_raw_hline,
};

const struct rtgui_graphic_driver_ops _pixel_rgb565_ops =
{
    _pixel_rgb565_set_pixel,
    _pixel_rgb565_get_pixel,
    _pixel_rgb565_draw_hline,
    _pixel_rgb565_draw_vline,
    _pixel_draw_raw_hline,
};

const struct rtgui_graphic_driver_ops _pixel_rgb888_ops =
{
    _pixel_rgb888_set_pixel,
    _pixel_rgb888_get_pixel,
    _pixel_rgb888_draw_hline,
    _pixel_rgb888_draw_vline,
    _pixel_draw_raw_hline,
};

const struct rtgui_graphic_driver_ops *rtgui_pixel_device_get_ops(int pixel_format)
{
    switch (pixel_format)
    {
    case RTGRAPHIC_PIXEL_FORMAT_MONO:
        return &_pixel_mono_ops;

    case RTGRAPHIC_PIXEL_FORMAT_RGB565:
        return &_pixel_rgb565_ops;

    case RTGRAPHIC_PIXEL_FORMAT_RGB565P:
        return &_pixel_rgb565p_ops;

    case RTGRAPHIC_PIXEL_FORMAT_RGB888:
        return &_pixel_rgb888_ops;
    }

    return RT_NULL;
}
