⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pw_draw.c

📁 Very very small GUI. Usefull for small system, without OS or small OS. Event driven, support user m
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <i_pwin.h>#include "guidebug.h"
/* -------------------------------------------------------------------------- *//** An array of bitmasks. Used for manipulating bits in bitmaps. */const Pw_Byte _bm_edgemask[2][9] = {        {0x00, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00},        {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF}};/* -------------------------------------------------------------------------- *//** *  Draws a point with clipping. *  @param gc   pointer to graphic context *  @param x    point x coord  *  @param y    point y coord  *  @param clip pointer to clip rectangle *  @return true if point is visible (i.e. drawn) *  @internal */ static Pw_Bool _DrawClipPoint(Pw_GC*        gc,                Pw_Coord      x,                Pw_Coord      y,               Pw_Rectangle* clip){    IPW_TRACE_ENTER(DR1);    IPW_TRACE2(DR1, d, x, y);    IPW_TRACE_RECT(DR1, clip);    /*     *  Check if point is inside clip (visible)     *  and draw it accordingly     */    if (IPW_RECT_IS_POINT_IN(x, y, clip))    {        gc->d.lld->draw_point(gc, x, y);        IPW_TRACE_EXIT_V(DR1, d, TRUE);        return(TRUE);    }    IPW_TRACE_EXIT_V(DR1, d, FALSE);    return(FALSE);}/** *  Draws a horizontal line with clipping. *  @param gc   pointer to graphic context *  @param x1   start point x coord  *  @param y1   start point y coord  *  @param x2   end point x coord  *  @param clip pointer to clip rectangle *  @return true if line is completely visible *  @internal */ static Pw_Bool _DrawClipHorLine(Pw_GC*        gc,                  Pw_Coord      x1,                  Pw_Coord      y1,                  Pw_Coord      x2,                 Pw_Rectangle* clip){    IPW_TRACE_ENTER(DR1);    IPW_TRACE3(DR1, d, x1, y1, x2);    IPW_TRACE_RECT(DR1, clip);    /*     *  First make shure that x1 is smaller than x2      *  (flip them if needed). Then check if the line's     *  y coord is inside the clip rectangle, if y      *  falls outside the line is not visible at all.      *  If y falls inside than clip the left side (x1) and     *  the right side (x2). If there is anything left     *  of the line - draw it.     */    if (x1 > x2)    {        Pw_Coord t;        t  = x1; x1 = x2; x2 = t;    }    if ((y1 >= clip->y) && (y1 < (clip->y + clip->h)))    {        Pw_Coord cx1 = x1;        Pw_Coord cx2 = x2;         if (cx1 < clip->x)            cx1 = clip->x;        if (cx2 >= (clip->x + clip->w))            cx2 = clip->x + clip->w - 1;        IPW_TRACE2(DR1, d, cx1, cx2);        if (cx1 == x1 && cx2 == x2)        {            gc->d.lld->draw_hor_line(gc, x1, y1, x2);            IPW_TRACE_EXIT_V(DR1, d, TRUE);             return(TRUE);         }        else if (cx1 <= cx2)        {            gc->d.lld->draw_hor_line(gc, cx1, y1, cx2);            IPW_TRACE_EXIT_V(DR1, d, FALSE);            return(FALSE);        }    }    IPW_TRACE_EXIT_V(DR1, d, FALSE);     return(FALSE);}/** *  Draws a vertical line with clipping. *  @param gc   pointer to graphic context *  @param x1   start point x coord  *  @param y1   start point y coord  *  @param y2   end point y coord  *  @param clip pointer to clip rectangle. *  @return true if line is completely visible  *  @internal */ static Pw_Bool _DrawClipVerLine(Pw_GC*        gc,                  Pw_Coord      x1,                  Pw_Coord      y1,                  Pw_Coord      y2,                 Pw_Rectangle* clip){    IPW_TRACE_ENTER(DR1);    IPW_TRACE3(DR1, d, x1, y1, y2);    IPW_TRACE_RECT(DR1, clip);    /*     *  First make shure that y1 is smaller than y2      *  (flip them if needed). Then check if the line's     *  x coord is inside the clip rectangle, if x      *  falls outside the line is not visible at all.      *  If x falls inside than clip the top side (y1) and     *  the bottom side (y2). If there is anything left     *  of the line - draw it.     */    if (y1 > y2)    {        Pw_Coord t;        t  = y1; y1 = y2; y2 = t;    }    if ((x1 >= clip->x) && (x1 < (clip->x + clip->w)))    {        Pw_Coord cy1 = y1;        Pw_Coord cy2 = y2;         if (cy1 < clip->y)            cy1 = clip->y;        if (cy2 >= (clip->y + clip->h))            cy2 = clip->y + clip->h - 1;        IPW_TRACE2(DR1, d, cy1, cy2);        if (cy1 == y1 && cy2 == y2)        {            gc->d.lld->draw_ver_line(gc, x1, y1, y2);            IPW_TRACE_EXIT_V(DR1, d, TRUE);             return(TRUE);         }        else if (cy1 <= cy2)        {            gc->d.lld->draw_ver_line(gc, x1, cy1, cy2);            IPW_TRACE_EXIT_V(DR1, d, FALSE);             return(FALSE);         }    }    IPW_TRACE_EXIT_V(DR1, d, FALSE);     return(FALSE);} /** *  Draws a line without clipping. *  @param gc pointer to graphic context *  @param x1 start point x coord  *  @param y1 start point y coord  *  @param x2 end point x coord  *  @param y2 end point y coord  *  @internal */ static void _DrawLine(Pw_GC*   gc,           Pw_Coord x1,           Pw_Coord y1,           Pw_Coord x2,          Pw_Coord y2){    Pw_Int dx, dy;    Pw_Int stepx, stepy;    IPW_TRACE_ENTER(DR2);    IPW_TRACE4(DR2, d, x1, x2, y1, y2);     /* Bresenham's line drawing algorithm */    dx = x2 - x1;    dy = y2 - y1;        if (dy < 0)     {         dy = -dy;          stepy = -1;     }     else     {         stepy = 1;     }    if (dx < 0)     {         dx = -dx;          stepx = -1;     }     else     {         stepx = 1;     }    dy <<= 1;    dx <<= 1;    gc->d.lld->draw_point(gc, x1, y1);    if (dx > dy)     {        Pw_Int fraction = dy - (dx >> 1);        while (x1 != x2)         {            if (fraction >= 0)             {                y1 += stepy;                fraction -= dx;            }            x1 += stepx;            fraction += dy;            gc->d.lld->draw_point(gc, x1, y1);        }    }     else     {        Pw_Int fraction = dx - (dy >> 1);        while (y1 != y2)         {            if (fraction >= 0)             {                x1 += stepx;                fraction -= dy;            }            y1 += stepy;            fraction += dx;            gc->d.lld->draw_point(gc, x1, y1);        }    }    IPW_TRACE_EXIT(DR2);} /** *  Draws a line with clipping. *  @param gc   pointer to graphic context *  @param x1   start point x coord  *  @param y1   start point y coord  *  @param x2   end point x coord  *  @param y2   end point y coord *  @param clip pointer to clip rectangle *  @todo make this smarter than point to point clipping *  @internal */ static void _DrawClipLine(Pw_GC*        gc,               Pw_Coord      x1,               Pw_Coord      y1,               Pw_Coord      x2,              Pw_Coord      y2,              Pw_Rectangle* clip){    Pw_Int dx, dy;    Pw_Int stepx, stepy;    IPW_TRACE_ENTER(DR2);    IPW_TRACE4(DR2, d, x1, y1, x2, y2);    IPW_TRACE_RECT(DR2, clip);    /* Bresenham's line drawing algorithm */    dx = x2 - x1;    dy = y2 - y1;        if (dy < 0)     {         dy = -dy;          stepy = -1;     }     else     {         stepy = 1;     }    if (dx < 0)     {         dx = -dx;          stepx = -1;     }     else     {         stepx = 1;     }    dy <<= 1;    dx <<= 1;    _DrawClipPoint(gc, x1, y1, clip);    if (dx > dy)     {        Pw_Int fraction = dy - (dx >> 1);        while (x1 != x2)         {            if (fraction >= 0)             {                y1 += stepy;                fraction -= dx;            }            x1 += stepx;            fraction += dy;            _DrawClipPoint(gc, x1, y1, clip);        }    }     else     {        Pw_Int fraction = dx - (dy >> 1);        while (y1 != y2)         {            if (fraction >= 0)             {                x1 += stepx;                fraction -= dy;            }            y1 += stepy;            fraction += dx;            _DrawClipPoint(gc, x1, y1, clip);        }    }    IPW_TRACE_EXIT(DR2);}/** *  Draws an ellipse without clipping. *  @param gc   pointer to graphic context *  @param x    ellipse center x coord  *  @param y    ellipse center y coord  *  @param rx   x radius *  @param ry   y radius *  @param fill if true the ellipse will be filled *  @internal */ static void _DrawEllipse(Pw_GC*   gc,              Pw_Coord x,              Pw_Coord y,              Pw_Coord rx,              Pw_Coord ry,             Pw_Bool  fill){    /* Algorithm from IEEE CG&A Sept 1984 p.24 */    Pw_Long t1 = rx * rx, t2 = t1 << 1, t3 = t2 << 1;    Pw_Long t4 = ry * ry, t5 = t4 << 1, t6 = t5 << 1;    Pw_Long t7 = rx * t5, t8 = t7 << 1, t9 = 0;    Pw_Long d1 = t2 - t7 + (t4 >> 1);    Pw_Long d2 = (t1 >> 1) - t8 + t5;    Pw_Int ex = rx, ey = 0;    IPW_TRACE_ENTER(DR2);    IPW_TRACE4(DR2, d, x, y, rx, ry);    while (d2 < 0)    {        if (fill)        {            gc->d.lld->draw_hor_line(gc, x - ex, y + ey, x + ex);            gc->d.lld->draw_hor_line(gc, x - ex, y - ey, x + ex);        }        else        {            gc->d.lld->draw_point(gc, x + ex, y + ey);            gc->d.lld->draw_point(gc, x + ex, y - ey);            gc->d.lld->draw_point(gc, x - ex, y + ey);            gc->d.lld->draw_point(gc, x - ex, y - ey);        }        ey++;                t9 += t3;            if (d1 < 0)        {            d1 += t9 + t2;            d2 += t9;        }        else        {            ex--;            t8 -= t6;            d1 += t9 + t2 - t8;            d2 += t9 + t5 - t8;        }    }    do    {        if (fill)        {            gc->d.lld->draw_hor_line(gc, x - ex, y + ey, x + ex);            gc->d.lld->draw_hor_line(gc, x - ex, y - ey, x + ex);        }        else        {            gc->d.lld->draw_point(gc, x + ex, y + ey);            gc->d.lld->draw_point(gc, x + ex, y - ey);            gc->d.lld->draw_point(gc, x - ex, y + ey);            gc->d.lld->draw_point(gc, x - ex, y - ey);        }        ex--;            t8 -= t6;            if (d2 < 0)        {            ey++;            t9 += t3;            d2 += t9 + t5 - t8;        }        else        {            d2 += t5 - t8;        }    }     while (ex >= 0);    IPW_TRACE_EXIT(DR2);}/** *  Draws an ellipse with clipping. *  @param gc   pointer to graphic context *  @param x    ellipse center x coord  *  @param y    ellipse center y coord  *  @param rx   x radius *  @param ry   y radius *  @param fill if true the ellipse will be filled *  @param clip pointer to clip rectangle *  @todo make this smarter than point to point clipping *  @internal */ static void	_DrawClipEllipse(Pw_GC*        gc,                 Pw_Coord      x,                 Pw_Coord      y,                 Pw_Coord      rx,                 Pw_Coord      ry,                 Pw_Bool       fill,                 Pw_Rectangle* clip){    /* Algorithm from IEEE CG&A Sept 1984 p.24 */    Pw_Long t1 = rx * rx, t2 = t1 << 1, t3 = t2 << 1;    Pw_Long t4 = ry * ry, t5 = t4 << 1, t6 = t5 << 1;    Pw_Long t7 = rx * t5, t8 = t7 << 1, t9 = 0;    Pw_Long d1 = t2 - t7 + (t4 >> 1);    Pw_Long d2 = (t1 >> 1) - t8 + t5;    Pw_Int ex = rx, ey = 0;    IPW_TRACE_ENTER(DR2);    IPW_TRACE4(DR2, d, x, y, rx, ry);    IPW_TRACE_RECT(DR2, clip);    while (d2 < 0)    {        if (fill)        {            _DrawClipHorLine(gc, x - ex, y + ey, x + ex, clip);            _DrawClipHorLine(gc, x - ex, y - ey, x + ex, clip);        }        else        {            _DrawClipPoint(gc, x + ex, y + ey, clip);            _DrawClipPoint(gc, x + ex, y - ey, clip);            _DrawClipPoint(gc, x - ex, y + ey, clip);            _DrawClipPoint(gc, x - ex, y - ey, clip);        }        ey++;                t9 += t3;            if (d1 < 0)        {            d1 += t9 + t2;            d2 += t9;        }        else        {            ex--;            t8 -= t6;            d1 += t9 + t2 - t8;            d2 += t9 + t5 - t8;        }    }    do    {        if (fill)        {            _DrawClipHorLine(gc, x - ex, y + ey, x + ex, clip);            _DrawClipHorLine(gc, x - ex, y - ey, x + ex, clip);        }        else        {            _DrawClipPoint(gc, x + ex, y + ey, clip);            _DrawClipPoint(gc, x + ex, y - ey, clip);            _DrawClipPoint(gc, x - ex, y + ey, clip);            _DrawClipPoint(gc, x - ex, y - ey, clip);        }        ex--;            t8 -= t6;            if (d2 < 0)        {            ey++;            t9 += t3;            d2 += t9 + t5 - t8;        }        else        {            d2 += t5 - t8;        }    }     while (ex >= 0);    IPW_TRACE_EXIT(DR2);} /** *  Draws a bitmap without clipping. *  @param gc   pointer to graphic context *  @param x    x coord of bitmap's top left corner *  @param y    y coord of bitmap's top left corner *  @param w    bitmap's width  *  @param h    bitmap's height *  @param bits bitmap bits array *  @internal */ static void _DrawBitmap(Pw_GC*    gc,             Pw_Coord  x,             Pw_Coord  y,             Pw_Coord  w,             Pw_Coord  h,             Pw_Byte*  bits) {    Pw_uInt  i, j;    Pw_Coord w8, rx;    IPW_TRACE_ENTER(DR2);    IPW_TRACE4(DR2, d, x, y, w, h);    /*     *  Calculate bitmap's width in bytes      *  (bitmap lines end always on byte border - and the unused      *  bits are just 0) and than draw each byte using draw_points     */    w8 = (w + 0x07) >> 3;    for (j = 0; j < h; j++) {        rx = x;        for (i = 0; i < w8; i++) {            gc->d.lld->draw_points (gc, rx, y, *bits); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -