diff options
| author | Bernard Xiong <[email protected]> | 2016-02-08 09:59:48 +0800 |
|---|---|---|
| committer | Bernard Xiong <[email protected]> | 2016-02-08 09:59:48 +0800 |
| commit | 490196b1b96f13e95aa04a13ad71788e1b534f06 (patch) | |
| tree | a649913615b6f2d682ba795e46fb439abdca6f5d /components/gui/src/dc.c | |
| parent | 55bbe7290e7fa00c74d151e57afed15ca8c41344 (diff) | |
[GUI Engine] Add RTGUI as a GUI Engine
Diffstat (limited to 'components/gui/src/dc.c')
| -rw-r--r-- | components/gui/src/dc.c | 1923 |
1 files changed, 1923 insertions, 0 deletions
diff --git a/components/gui/src/dc.c b/components/gui/src/dc.c new file mode 100644 index 0000000000..59d0e7ec4a --- /dev/null +++ b/components/gui/src/dc.c @@ -0,0 +1,1923 @@ +/* + * File : dc.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + * 2010-09-20 richard modified rtgui_dc_draw_round_rect + * 2010-09-27 Bernard fix draw_mono_bmp issue + * 2011-04-25 Bernard fix fill polygon issue, which found by loveic + */ + +/* for sin/cos etc */ +#include <math.h> + +#include <rtgui/dc.h> +#include <rtgui/dc_hw.h> +#include <rtgui/dc_client.h> + +#include <rtgui/rtgui_system.h> +#include <rtgui/rtgui_server.h> +#include <rtgui/widgets/window.h> +#include <rtgui/widgets/title.h> + +#include <string.h> /* for strlen */ +#include <stdlib.h> /* fir qsort */ + +static int _int_compare(const void *a, const void *b) +{ + return (*(const int *) a) - (*(const int *) b); +} + +void rtgui_dc_destory(struct rtgui_dc *dc) +{ + if (dc == RT_NULL) return; + + dc->engine->fini(dc); + rtgui_free(dc); +} +RTM_EXPORT(rtgui_dc_destory); + +void rtgui_dc_draw_line(struct rtgui_dc *dc, int x1, int y1, int x2, int y2) +{ + if (dc == RT_NULL) return; + + if (y1 == y2) + { + rtgui_dc_draw_hline(dc, x1, x2, y1); + } + else if (x1 == x2) + { + rtgui_dc_draw_vline(dc, x1, y1, y2); + } + else + { + int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py; + register rt_base_t i; + /* rtgui_rect_t rect; */ + + dx = x2 - x1; /* the horizontal distance of the line */ + dy = y2 - y1; /* the vertical distance of the line */ + +#define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */ + + dxabs = _UI_ABS(dx); + dyabs = _UI_ABS(dy); + sdx = rtgui_sgn(dx); + sdy = rtgui_sgn(dy); + x = dyabs >> 1; + y = dxabs >> 1; + px = x1; + py = y1; + + if (dxabs >= dyabs) /* the line is more horizontal than vertical */ + { + for (i = 0; i < dxabs; i++) + { + y += dyabs; + if (y >= dxabs) + { + y -= dxabs; + py += sdy; + } + px += sdx; + + /* draw this point */ + rtgui_dc_draw_point(dc, px, py); + } + } + else /* the line is more vertical than horizontal */ + { + for (i = 0; i < dyabs; i++) + { + x += dxabs; + if (x >= dyabs) + { + x -= dyabs; + px += sdx; + } + py += sdy; + + /* draw this point */ + rtgui_dc_draw_point(dc, px, py); + } + } + } +} +RTM_EXPORT(rtgui_dc_draw_line); + +void rtgui_dc_draw_horizontal_line(struct rtgui_dc *dc, int x1, int x2, int y) +{ + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = RTGUI_DC_FC(dc); + + RTGUI_DC_FC(dc) = dark_grey; + rtgui_dc_draw_hline(dc, x1, x2, y); + + y ++; + + RTGUI_DC_FC(dc) = high_light; + rtgui_dc_draw_hline(dc, x1, x2, y); + + /* restore color */ + RTGUI_DC_FC(dc) = color; +} +RTM_EXPORT(rtgui_dc_draw_horizontal_line); + +void rtgui_dc_draw_vertical_line(struct rtgui_dc *dc, int x, int y1, int y2) +{ + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = RTGUI_DC_FC(dc); + + RTGUI_DC_FC(dc) = dark_grey; + rtgui_dc_draw_vline(dc, x, y1, y2); + + x ++; + + RTGUI_DC_FC(dc) = high_light; + rtgui_dc_draw_vline(dc, x, y1, y2); + + /* restore color */ + RTGUI_DC_FC(dc) = color; +} +RTM_EXPORT(rtgui_dc_draw_vertical_line); + +void rtgui_dc_draw_rect(struct rtgui_dc *dc, struct rtgui_rect *rect) +{ + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1); + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1); + + rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2); + rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2); +} +RTM_EXPORT(rtgui_dc_draw_rect); + +void rtgui_dc_fill_rect_forecolor(struct rtgui_dc *dc, struct rtgui_rect *rect) +{ + rtgui_color_t save_color; + /*save the background color of dc*/ + save_color = RTGUI_DC_BC(dc); + /*set the background color to fore color*/ + RTGUI_DC_BC(dc) = RTGUI_DC_FC(dc); + dc->engine->fill_rect(dc, rect); + /*restore the background color of dc*/ + RTGUI_DC_BC(dc) = save_color; +} +RTM_EXPORT(rtgui_dc_fill_rect_forecolor); + +void rtgui_dc_draw_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r) +{ + RT_ASSERT(((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r)); + + if (r < 0) + { + return; + } + + if (r == 0) + { + rtgui_dc_draw_rect(dc, rect); + return; + } + + if (((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r)) + { + rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y1 + r, r, 180, 270); + rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y1 + r, r, 270, 360); + rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y2 - r, r, 90, 180); + rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y2 - r, r, 0, 90); + + rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y1); + rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y2); + rtgui_dc_draw_vline(dc, rect->x1, rect->y1 + r, rect->y2 - r); + rtgui_dc_draw_vline(dc, rect->x2, rect->y1 + r, rect->y2 - r); + } +} +RTM_EXPORT(rtgui_dc_draw_round_rect); + +void rtgui_dc_fill_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r) +{ + struct rtgui_rect rect_temp; + + RT_ASSERT(((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r)); + + if (((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r)) + { + rect_temp.x1 = rect->x1 + r; + rect_temp.y1 = rect->y1; + rect_temp.x2 = rect->x2 - r; + rect_temp.y2 = rect->y2; + rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground + + rect_temp.x1 = rect->x1; + rect_temp.y1 = rect->y1 + r; + rect_temp.x2 = rect->x1 + r; + rect_temp.y2 = rect->y2 - r; + rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground + + rect_temp.x1 = rect->x2 - r; + rect_temp.y1 = rect->y1 + r; + rect_temp.x2 = rect->x2; + rect_temp.y2 = rect->y2 - r; + rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground + + rtgui_dc_fill_circle(dc, rect->x1 + r, rect->y1 + r, r); + rtgui_dc_fill_circle(dc, rect->x2 - r, rect->y2 - r, r); + rtgui_dc_fill_circle(dc, rect->x2 - r, rect->y1 + r, r); + rtgui_dc_fill_circle(dc, rect->x1 + r, rect->y2 - r, r); + } +} +RTM_EXPORT(rtgui_dc_fill_round_rect); + +void rtgui_dc_draw_shaded_rect(struct rtgui_dc *dc, rtgui_rect_t *rect, + rtgui_color_t c1, rtgui_color_t c2) +{ + RT_ASSERT(dc != RT_NULL); + + RTGUI_DC_FC(dc) = c1; + rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2); + rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1); + + RTGUI_DC_FC(dc) = c2; + rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2); + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1); +} +RTM_EXPORT(rtgui_dc_draw_shaded_rect); + +void rtgui_dc_fill_gradient_rectv(struct rtgui_dc *dc, rtgui_rect_t *rect, + rtgui_color_t c1, rtgui_color_t c2) +{ + int y, step; + rtgui_color_t fc; + + RT_ASSERT(dc != RT_NULL); + RT_ASSERT(rect != RT_NULL); + + step = rtgui_rect_height(*rect); + fc = RTGUI_DC_FC(dc); + + for (y = rect->y1; y < rect->y2; y++) + { + RTGUI_DC_FC(dc) = RTGUI_ARGB(((int)RTGUI_RGB_A(c2) - RTGUI_RGB_A(c1)) * (y - rect->y1) / step + RTGUI_RGB_A(c1), + ((int)RTGUI_RGB_R(c2) - RTGUI_RGB_R(c1)) * (y - rect->y1) / step + RTGUI_RGB_R(c1), + ((int)RTGUI_RGB_G(c2) - RTGUI_RGB_G(c1)) * (y - rect->y1) / step + RTGUI_RGB_G(c1), + ((int)RTGUI_RGB_B(c2) - RTGUI_RGB_B(c1)) * (y - rect->y1) / step + RTGUI_RGB_B(c1)); + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, y); + } + + RTGUI_DC_FC(dc) = fc; +} +RTM_EXPORT(rtgui_dc_fill_gradient_rectv); + +void rtgui_dc_draw_focus_rect(struct rtgui_dc *dc, rtgui_rect_t *rect) +{ + int x, y; + + for (x = rect->x1; x < rect->x2 - 1; x += 2) + { + rtgui_dc_draw_point(dc, x, rect->y1); + rtgui_dc_draw_point(dc, x, rect->y2 - 1); + } + + for (y = rect->y1; y < rect->y2; y += 2) + { + rtgui_dc_draw_point(dc, rect->x1, y); + rtgui_dc_draw_point(dc, rect->x2 - 1, y); + } +} +RTM_EXPORT(rtgui_dc_draw_focus_rect); + +void rtgui_dc_draw_text(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect) +{ + rt_uint32_t len; + struct rtgui_font *font; + struct rtgui_rect text_rect; + + RT_ASSERT(dc != RT_NULL); + + font = RTGUI_DC_FONT(dc); + if (font == RT_NULL) + { + /* use system default font */ + font = rtgui_font_default(); + } + + /* text align */ + rtgui_font_get_metrics(font, text, &text_rect); + rtgui_rect_moveto_align(rect, &text_rect, RTGUI_DC_TEXTALIGN(dc)); + + len = strlen((const char *)text); + rtgui_font_draw(font, dc, text, len, &text_rect); +} +RTM_EXPORT(rtgui_dc_draw_text); + +void rtgui_dc_draw_text_stroke(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect, + rtgui_color_t color_stroke, rtgui_color_t color_core) +{ + int x, y; + rtgui_rect_t r; + rtgui_color_t fc; + + RT_ASSERT(dc != RT_NULL); + + fc = RTGUI_DC_FC(dc); + RTGUI_DC_FC(dc) = color_stroke; + for (x = -1; x < 2; x++) + { + for (y = -1; y < 2; y++) + { + r = *rect; + rtgui_rect_moveto(&r, x, y); + rtgui_dc_draw_text(dc, text, &r); + } + } + RTGUI_DC_FC(dc) = color_core; + rtgui_dc_draw_text(dc, text, rect); + RTGUI_DC_FC(dc) = fc; +} +RTM_EXPORT(rtgui_dc_draw_text_stroke); + +/* + * draw a monochrome color bitmap data + */ +void rtgui_dc_draw_mono_bmp(struct rtgui_dc *dc, int x, int y, int w, int h, const rt_uint8_t *data) +{ + int i, j, k; + + /* get word bytes */ + w = (w + 7) / 8; + + /* draw mono bitmap data */ + for (i = 0; i < h; i ++) + for (j = 0; j < w; j++) + for (k = 0; k < 8; k++) + if (((data[i * w + j] >> (7 - k)) & 0x01) != 0) + rtgui_dc_draw_point(dc, x + 8 * j + k, y + i); +} +RTM_EXPORT(rtgui_dc_draw_mono_bmp); + +void rtgui_dc_draw_byte(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data) +{ + rtgui_dc_draw_mono_bmp(dc, x, y, 8, h, data); +} +RTM_EXPORT(rtgui_dc_draw_byte); + +void rtgui_dc_draw_word(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data) +{ + rtgui_dc_draw_mono_bmp(dc, x, y, 16, h, data); +} +RTM_EXPORT(rtgui_dc_draw_word); + +void rtgui_dc_draw_border(struct rtgui_dc *dc, rtgui_rect_t *rect, int flag) +{ + rtgui_rect_t r; + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = RTGUI_DC_FC(dc); + + r = *rect; + switch (flag) + { + case RTGUI_BORDER_RAISE: + rtgui_dc_draw_shaded_rect(dc, &r, high_light, black); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey); + break; + + case RTGUI_BORDER_SUNKEN: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey); + break; + + case RTGUI_BORDER_BOX: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey); + break; + + case RTGUI_BORDER_STATIC: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + break; + + case RTGUI_BORDER_EXTRA: + RTGUI_DC_FC(dc) = light_grey; + rtgui_dc_draw_rect(dc, &r); + break; + + case RTGUI_BORDER_SIMPLE: + RTGUI_DC_FC(dc) = black; + rtgui_dc_draw_rect(dc, &r); + break; + + default: + break; + } + + /* restore color */ + RTGUI_DC_FC(dc) = color; +} +RTM_EXPORT(rtgui_dc_draw_border); + +void rtgui_dc_draw_polygon(struct rtgui_dc *dc, const int *vx, const int *vy, int count) +{ + int i; + const int *x1, *y1, *x2, *y2; + + /* + * Sanity check + */ + if (count < 3) return; + + /* + * Pointer setup + */ + x1 = x2 = vx; + y1 = y2 = vy; + x2++; + y2++; + + /* + * Draw + */ + for (i = 1; i < count; i++) + { + rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2); + x1 = x2; + y1 = y2; + x2++; + y2++; + } + rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy); +} +RTM_EXPORT(rtgui_dc_draw_polygon); + +void rtgui_dc_fill_polygon(struct rtgui_dc *dc, const int *vx, const int *vy, int count) +{ + int i; + int y, xa, xb; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *poly_ints = RT_NULL; + + /* + * Sanity check number of edges + */ + if (count < 3) return; + + /* + * Allocate temp array, only grow array + */ + poly_ints = (int *) rtgui_malloc(sizeof(int) * count); + if (poly_ints == RT_NULL) return ; /* no memory, failed */ + + /* + * Determine Y maximal + */ + miny = vy[0]; + maxy = vy[0]; + for (i = 1; (i < count); i++) + { + if (vy[i] < miny) miny = vy[i]; + else if (vy[i] > maxy) maxy = vy[i]; + } + + /* + * Draw, scanning y + */ + for (y = miny; (y <= maxy); y++) + { + ints = 0; + for (i = 0; (i < count); i++) + { + if (!i) + { + ind1 = count - 1; + ind2 = 0; + } + else + { + ind1 = i - 1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) + { + x1 = vx[ind1]; + x2 = vx[ind2]; + } + else if (y1 > y2) + { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } + else + { + continue; + } + + if (((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2))) + { + poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); + } + } + + qsort(poly_ints, ints, sizeof(int), _int_compare); + + for (i = 0; (i < ints); i += 2) + { + xa = poly_ints[i] + 1; + xa = (xa >> 16) + ((xa & 32768) >> 15); + xb = poly_ints[i + 1] - 1; + xb = (xb >> 16) + ((xb & 32768) >> 15); + rtgui_dc_draw_hline(dc, xa, xb, y); + } + } + + /* release memory */ + rtgui_free(poly_ints); +} +RTM_EXPORT(rtgui_dc_fill_polygon); + +void rtgui_dc_draw_circle(struct rtgui_dc *dc, int x, int y, int r) +{ + rtgui_dc_draw_ellipse(dc, x, y, r, r); +} +RTM_EXPORT(rtgui_dc_draw_circle); + +enum +{ + QUARTER_BTM, + QUARTER_BTM_LEFT, + QUARTER_BTM_RIGHT, + QUARTER_TOP, + QUARTER_TOP_LEFT, + QUARTER_TOP_RIGHT, + QUARTER_FULL, +}; + +static void _fill_quarter_circle(struct rtgui_dc *dc, + rt_int16_t ox, rt_int16_t oy, + rt_int16_t rad, int quadrant) +{ + /* Midpoint circle algorithm. */ + int dk, x, y; + + dk = 1 - rad; + x = 0; + y = rad; + + while (x <= y) + { + switch (quadrant) + { + case QUARTER_BTM: + rtgui_dc_draw_hline(dc, ox - x, ox + x, oy + y); + rtgui_dc_draw_hline(dc, ox - y, ox + y, oy + x); + break; + case QUARTER_BTM_LEFT: + rtgui_dc_draw_hline(dc, ox, ox + x, oy + y); + rtgui_dc_draw_hline(dc, ox, ox + y, oy + x); + break; + case QUARTER_BTM_RIGHT: + rtgui_dc_draw_hline(dc, ox, ox - x, oy + y); + rtgui_dc_draw_hline(dc, ox, ox - y, oy + x); + break; + case QUARTER_TOP_RIGHT: + rtgui_dc_draw_hline(dc, ox, ox - x, oy - y); + rtgui_dc_draw_hline(dc, ox, ox - y, oy - x); + break; + case QUARTER_TOP_LEFT: + rtgui_dc_draw_hline(dc, ox, ox + x, oy - y); + rtgui_dc_draw_hline(dc, ox, ox + y, oy - x); + break; + case QUARTER_TOP: + rtgui_dc_draw_hline(dc, ox - x, ox + x, oy - y); + rtgui_dc_draw_hline(dc, ox - y, ox + y, oy - x); + break; + case QUARTER_FULL: + rtgui_dc_draw_hline(dc, ox - x, ox + x, oy + y); + rtgui_dc_draw_hline(dc, ox - y, ox + y, oy + x); + rtgui_dc_draw_hline(dc, ox - x, ox + x, oy - y); + rtgui_dc_draw_hline(dc, ox - y, ox + y, oy - x); + break; + default: + RT_ASSERT(0); + }; + + if (dk > 0) + { + y--; + dk += 2 * (x - y) + 5; + } + else + { + dk += 2 * x + 3; + } + x++; + } +} + +void rtgui_dc_fill_circle(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r) +{ + /* + * Sanity check radius + */ + if (r < 0) + return; + + /* + * Special case for r=0 - draw a point + */ + if (r == 0) + { + rtgui_dc_draw_point(dc, x, y); + return; + } + + _fill_quarter_circle(dc, x, y, r, QUARTER_FULL); +} +RTM_EXPORT(rtgui_dc_fill_circle); + +void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end) +{ + rt_int16_t cx = 0; + rt_int16_t cy = r; + rt_int16_t df = 1 - r; + rt_int16_t d_e = 3; + rt_int16_t d_se = -2 * r + 5; + rt_int16_t xpcx, xmcx, xpcy, xmcy; + rt_int16_t ypcy, ymcy, ypcx, ymcx; + rt_uint8_t drawoct; + int startoct, endoct, oct, stopval_start, stopval_end; + double temp; + + stopval_start = 0; + stopval_end = 0; + temp = 0; + + /* Sanity check radius */ + if (r < 0) return ; + /* Special case for r=0 - draw a point */ + if (r == 0) + { + rtgui_dc_draw_point(dc, x, y); + return; + } + + /* + * Draw arc + */ + + // Octant labelling + // + // \ 5 | 6 / + // \ | / + // 4 \ | / 7 + // \|/ + //------+------ +x + // /|\ + // 3 / | \ 0 + // / | \ + // / 2 | 1 \ + // +y + + drawoct = 0; // 0x00000000 + // whether or not to keep drawing a given octant. + // For example: 0x00111100 means we're drawing in octants 2-5 + + // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. + while (start < 0) start += 360; + while (end < 0) end += 360; + /* Fixup angles */ + start = start % 360; + end = end % 360; + + + // now, we find which octants we're drawing in. + startoct = start / 45; + endoct = end / 45; + oct = startoct - 1; // we increment as first step in loop + + //stopval_start, stopval_end; // what values of cx to stop at. + do + { + oct = (oct + 1) % 8; + + if (oct == startoct) + { + // need to compute stopval_start for this octant. Look at picture above if this is unclear + switch (oct) + { + case 0: + case 3: + temp = sin(start * M_PI / 180); + break; + case 1: + case 6: + temp = cos(start * M_PI / 180); + break; + case 2: + case 5: + temp = -cos(start * M_PI / 180); + break; + case 4: + case 7: + temp = -sin(start * M_PI / 180); + break; + } + temp *= r; + stopval_start = (int)temp; // always round down. + // This isn't arbitrary, but requires graph paper to explain well. + // The basic idea is that we're always changing drawoct after we draw, so we + // stop immediately after we render the last sensible pixel at x = ((int)temp). + + // and whether to draw in this octant initially + if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array + else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false + } + + if (oct == endoct) + { + // need to compute stopval_end for this octant + switch (oct) + { + case 0: + case 3: + temp = sin(end * M_PI / 180); + break; + case 1: + case 6: + temp = cos(end * M_PI / 180); + break; + case 2: + case 5: + temp = -cos(end * M_PI / 180); + break; + case 4: + case 7: + temp = -sin(end * M_PI / 180); + break; + } + temp *= r; + stopval_end = (int)temp; + + // and whether to draw in this octant initially + if (startoct == endoct) + { + // note: we start drawing, stop, then start again in this case + // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true + if (start > end) + { + // unfortunately, if we're in the same octant and need to draw over the whole circle, + // we need to set the rest to true, because the while loop will end at the bottom. + drawoct = 255; + } + else + { + drawoct &= 255 - (1 << oct); + } + } + else if (oct % 2) drawoct &= 255 - (1 << oct); + else drawoct |= (1 << oct); + } + else if (oct != startoct) // already verified that it's != endoct + { + drawoct |= (1 << oct); // draw this entire segment + } + } + while (oct != endoct); + + // so now we have what octants to draw and when to draw them. all that's left is the actual raster code. + do + { + ypcy = y + cy; + ymcy = y - cy; + if (cx > 0) + { + xpcx = x + cx; + xmcx = x - cx; + // always check if we're drawing a certain octant before adding a pixel to that octant. + if (drawoct & 4) rtgui_dc_draw_point(dc, xmcx, ypcy); // drawoct & 4 = 22; drawoct[2] + if (drawoct & 2) rtgui_dc_draw_point(dc, xpcx, ypcy); + if (drawoct & 32) rtgui_dc_draw_point(dc, xmcx, ymcy); + if (drawoct & 64) rtgui_dc_draw_point(dc, xpcx, ymcy); + } + else + { + if (drawoct & 6) rtgui_dc_draw_point(dc, x, ypcy); // 4 + 2; drawoct[2] || drawoct[1] + if (drawoct & 96) rtgui_dc_draw_point(dc, x, ymcy); // 32 + 64 + } + + xpcy = x + cy; + xmcy = x - cy; + if (cx > 0 && cx != cy) + { + ypcx = y + cx; + ymcx = y - cx; + if (drawoct & 8) rtgui_dc_draw_point(dc, xmcy, ypcx); + if (drawoct & 1) rtgui_dc_draw_point(dc, xpcy, ypcx); + if (drawoct & 16) rtgui_dc_draw_point(dc, xmcy, ymcx); + if (drawoct & 128) rtgui_dc_draw_point(dc, xpcy, ymcx); + } + else if (cx == 0) + { + if (drawoct & 24) rtgui_dc_draw_point(dc, xmcy, y); // 8 + 16 + if (drawoct & 129) rtgui_dc_draw_point(dc, xpcy, y); // 1 + 128 + } + + /* + * Update whether we're drawing an octant + */ + if (stopval_start == cx) + { + // works like an on-off switch because start & end may be in the same octant. + if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct); + else drawoct |= (1 << startoct); + } + if (stopval_end == cx) + { + if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct); + else drawoct |= (1 << endoct); + } + + /* + * Update pixels + */ + if (df < 0) + { + df += d_e; + d_e += 2; + d_se += 2; + } + else + { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + + cx++; + } + while (cx <= cy); +} +RTM_EXPORT(rtgui_dc_draw_arc); + +void rtgui_dc_draw_annulus(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r1, rt_int16_t r2, rt_int16_t start, rt_int16_t end) +{ + rt_int16_t start_x, start_y; + rt_int16_t end_x, end_y; + double temp; + rt_int16_t temp_val = 0; + + /* Sanity check radius */ + if ((r1 < 0) || (r2 < 0)) return ; + /* Special case for r=0 - draw a point */ + if ((r1 == 0) && (r2 == 0)) + { + rtgui_dc_draw_point(dc, x, y); + return; + } + + while (start < 0) start += 360; + while (end < 0) end += 360; + + rtgui_dc_draw_arc(dc, x, y, r1, start, end); + rtgui_dc_draw_arc(dc, x, y, r2, start, end); + + temp = cos(start * M_PI / 180); + temp_val = (int)(temp * r1); + start_x = x + temp_val; + temp_val = (int)(temp * r2); + end_x = x + temp_val; + + temp = sin(start * M_PI / 180); + temp_val = (int)(temp * r1); + start_y = y + temp_val; + temp_val = (int)(temp * r2); + end_y = y + temp_val; + + rtgui_dc_draw_line(dc, start_x, start_y, end_x, end_y); + + temp = cos(end * M_PI / 180); + temp_val = (int)(temp * r1); + start_x = x + temp_val; + temp_val = (int)(temp * r2); + end_x = x + temp_val; + + temp = sin(end * M_PI / 180); + temp_val = (int)(temp * r1); + start_y = y + temp_val; + temp_val = (int)(temp * r2); + end_y = y + temp_val; + + rtgui_dc_draw_line(dc, start_x, start_y, end_x, end_y); +} +RTM_EXPORT(rtgui_dc_draw_annulus); + +void rtgui_dc_draw_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry) +{ + int ix, iy; + int h, i, j, k; + int oh, oi, oj, ok; + int xmh, xph, ypk, ymk; + int xmi, xpi, ymj, ypj; + int xmj, xpj, ymi, ypi; + int xmk, xpk, ymh, yph; + + /* + * Sanity check radii + */ + if ((rx < 0) || (ry < 0)) return; + + /* + * Special case for rx=0 - draw a vline + */ + if (rx == 0) + { + rtgui_dc_draw_vline(dc, x, y - ry, y + ry); + return; + } + + /* + * Special case for ry=0 - draw a hline + */ + if (ry == 0) + { + rtgui_dc_draw_hline(dc, x - rx, x + rx, y); + return; + } + + /* + * Init vars + */ + oh = oi = oj = ok = 0xFFFF; + + if (rx > ry) + { + ix = 0; + iy = rx * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) + { + xph = x + h; + xmh = x - h; + if (k > 0) + { + ypk = y + k; + ymk = y - k; + rtgui_dc_draw_point(dc, xmh, ypk); + rtgui_dc_draw_point(dc, xph, ypk); + rtgui_dc_draw_point(dc, xmh, ymk); + rtgui_dc_draw_point(dc, xph, ymk); + } + else + { + rtgui_dc_draw_point(dc, xmh, y); + rtgui_dc_draw_point(dc, xph, y); + } + ok = k; + xpi = x + i; + xmi = x - i; + if (j > 0) + { + ypj = y + j; + ymj = y - j; + rtgui_dc_draw_point(dc, xmi, ypj); + rtgui_dc_draw_point(dc, xpi, ypj); + rtgui_dc_draw_point(dc, xmi, ymj); + rtgui_dc_draw_point(dc, xpi, ymj); + } + else + { + rtgui_dc_draw_point(dc, xmi, y); + rtgui_dc_draw_point(dc, xpi, y); + } + oj = j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + } + while (i > h); + } + else + { + ix = 0; + iy = ry * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) + { + xmj = x - j; + xpj = x + j; + if (i > 0) + { + ypi = y + i; + ymi = y - i; + rtgui_dc_draw_point(dc, xmj, ypi); + rtgui_dc_draw_point(dc, xpj, ypi); + rtgui_dc_draw_point(dc, xmj, ymi); + rtgui_dc_draw_point(dc, xpj, ymi); + } + else + { + rtgui_dc_draw_point(dc, xmj, y); + rtgui_dc_draw_point(dc, xpj, y); + } + oi = i; + xmk = x - k; + xpk = x + k; + if (h > 0) + { + yph = y + h; + ymh = y - h; + rtgui_dc_draw_point(dc, xmk, yph); + rtgui_dc_draw_point(dc, xpk, yph); + rtgui_dc_draw_point(dc, xmk, ymh); + rtgui_dc_draw_point(dc, xpk, ymh); + } + else + { + rtgui_dc_draw_point(dc, xmk, y); + rtgui_dc_draw_point(dc, xpk, y); + } + oh = h; + } + + ix = ix + iy / ry; + iy = iy - ix / ry; + } + while (i > h); + } +} +RTM_EXPORT(rtgui_dc_draw_ellipse); + +void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry) +{ + int ix, iy; + int h, i, j, k; + int oh, oi, oj, ok; + int xmh, xph; + int xmi, xpi; + int xmj, xpj; + int xmk, xpk; + + /* + * Special case for rx=0 - draw a vline + */ + if (rx == 0) + { + rtgui_dc_draw_vline(dc, x, y - ry, y + ry); + return; + } + + /* special case for ry=0 - draw a hline */ + if (ry == 0) + { + rtgui_dc_draw_hline(dc, x - rx, x + rx, y); + return; + } + + /* + * Init vars + */ + oh = oi = oj = ok = 0xFFFF; + + /* + * Draw + */ + if (rx > ry) + { + ix = 0; + iy = rx * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if ((ok != k) && (oj != k)) + { + xph = x + h; + xmh = x - h; + if (k > 0) + { + rtgui_dc_draw_hline(dc, xmh, xph, y + k); + rtgui_dc_draw_hline(dc, xmh, xph, y - k); + } + else + { + rtgui_dc_draw_hline(dc, xmh, xph, y); + } + ok = k; + } + if ((oj != j) && (ok != j) && (k != j)) + { + xmi = x - i; + xpi = x + i; + if (j > 0) + { + rtgui_dc_draw_hline(dc, xmi, xpi, y + j); + rtgui_dc_draw_hline(dc, xmi, xpi, y - j); + } + else + { + rtgui_dc_draw_hline(dc, xmi, xpi, y); + } + oj = j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + + } + while (i > h); + } + else + { + ix = 0; + iy = ry * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if ((oi != i) && (oh != i)) + { + xmj = x - j; + xpj = x + j; + if (i > 0) + { + rtgui_dc_draw_hline(dc, xmj, xpj, y + i); + rtgui_dc_draw_hline(dc, xmj, xpj, y - i); + } + else + { + rtgui_dc_draw_hline(dc, xmj, xpj, y); + } + oi = i; + } + if ((oh != h) && (oi != h) && (i != h)) + { + xmk = x - k; + xpk = x + k; + if (h > 0) + { + rtgui_dc_draw_hline(dc, xmk, xpk, y + h); + rtgui_dc_draw_hline(dc, xmk, xpk, y - h); + } + else + { + rtgui_dc_draw_hline(dc, xmk, xpk, y); + } + oh = h; + } + ix = ix + iy / ry; + iy = iy - ix / ry; + } + while (i > h); + } +} +RTM_EXPORT(rtgui_dc_fill_ellipse); + +void rtgui_dc_draw_pie(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rad, rt_int16_t start, rt_int16_t end) +{ + double angle, start_angle, end_angle; + double deltaAngle; + double dr; + int numpoints, i; + int *vx, *vy; + + /* Sanity check radii */ + if (rad < 0) return ; + + /* + * Fixup angles + */ + start = start % 360; + end = end % 360; + + /* + * Special case for rad=0 - draw a point + */ + if (rad == 0) + { + rtgui_dc_draw_point(dc, x, y); + return; + } + + /* + * Variable setup + */ + dr = (double) rad; + deltaAngle = 3.0 / dr; + start_angle = (double) start * (2.0 * M_PI / 360.0); + end_angle = (double) end * (2.0 * M_PI / 360.0); + if (start > end) + { + end_angle += (2.0 * M_PI); + } + + /* We will always have at least 2 points */ + numpoints = 2; + + /* Count points (rather than calculating it) */ + angle = start_angle; + while (angle < end_angle) + { + angle += deltaAngle; + numpoints++; + } + + /* Allocate combined vertex array */ + vx = vy = (int *) rtgui_malloc(2 * sizeof(int) * numpoints); + if (vx == RT_NULL) return ; + + /* Update point to start of vy */ + vy += numpoints; + + /* Center */ + vx[0] = x; + vy[0] = y; + + /* First vertex */ + angle = start_angle; + vx[1] = x + (int)(dr * cos(angle)); + vy[1] = y + (int)(dr * sin(angle)); + + if (numpoints < 3) + { + rtgui_dc_draw_line(dc, vx[0], vy[0], vx[1], vy[1]); + } + else + { + /* Calculate other vertices */ + i = 2; + angle = start_angle; + while (angle < end_angle) + { + angle += deltaAngle; + if (angle > end_angle) + { + angle = end_angle; + } + vx[i] = x + (int)(dr * cos(angle)); + vy[i] = y + (int)(dr * sin(angle)); + i++; + } + + /* Draw */ + rtgui_dc_draw_polygon(dc, vx, vy, numpoints); + } + + /* Free combined vertex array */ + rtgui_free(vx); + return; +} +RTM_EXPORT(rtgui_dc_draw_pie); + +// Octant labelling +// +// \ 5 | 6 / +// \ | / +// 4 \ | / 7 +// \|/ +//------+------ +x +// /|\ +// 3 / | \ 0 +// / | \ +// / 2 | 1 \ +// +y +static void _draw_octant(struct rtgui_dc *dc, + rt_int16_t ox, rt_int16_t oy, + rt_int16_t y1, rt_int16_t y2, rt_int16_t x, int oct) +{ + switch (oct % 8) + { + case 0: + rtgui_dc_draw_line(dc, ox + x, oy + y1, ox + x, oy + y2); + break; + case 1: + /* Ugly hack to get the edge right. */ + y2 += 1; + y1 += 1; + x -= 1; + rtgui_dc_draw_line(dc, ox + y1, oy + x, ox + y2, oy + x); + break; + case 2: + y2 -= 1; + y1 -= 1; + x -= 1; + rtgui_dc_draw_line(dc, ox - y2, oy + x, ox - y1, oy + x); + break; + case 3: + x -= 1; + rtgui_dc_draw_line(dc, ox - x, oy + y1, ox - x, oy + y2); + break; + case 4: + x -= 1; + rtgui_dc_draw_line(dc, ox - x, oy - y2, ox - x, oy - y1); + break; + case 5: + y2 -= 1; + y1 -= 1; + rtgui_dc_draw_line(dc, ox - y2, oy - x, ox - y1, oy - x); + break; + case 6: + y2 += 1; + y1 += 1; + rtgui_dc_draw_line(dc, ox + y1, oy - x, ox + y2, oy - x); + break; + case 7: + rtgui_dc_draw_line(dc, ox + x, oy - y2, ox + x, oy - y1); + break; + }; +} + +static void _fill_small_pie(struct rtgui_dc *dc, + rt_int16_t ox, rt_int16_t oy, + rt_int16_t rad, rt_int16_t start, rt_int16_t end, + int oct) +{ + /* Midpoint circle algorithm. */ + int dk, x, y; + /* Start X, end X, */ + rt_int16_t sx, ex, ty, my; + enum {ST_NONE, ST_ARC, ST_TRI} st; + + RT_ASSERT(0 <= start && start <= 45); + RT_ASSERT(0 <= end && end <= 45); + if (start == end) + return; + RT_ASSERT(start < end); + RT_ASSERT(rad > 0); + + /* cos(90 - start) == sin(start) */ + sx = rad * sin(start * M_PI / 180); + ex = rad * sin(end * M_PI / 180); + + dk = 1 - rad; + x = 0; + y = rad; + + st = ST_NONE; + my = ex; + while (x <= y) + { + rt_int16_t lx; + + if (x < sx) + { + } + else if (x == sx) + { + /* Start point. */ + st = ST_ARC; + ty = y; + } + else if (x <= ex) + { + /* Between the pie. */ + RT_ASSERT(st == ST_ARC); + } + else /* x > ex */ + { + /* End. */ + st = ST_TRI; + my = y; + break; + } + + /* Drawing. */ + if (st == ST_ARC) + { + lx = y * sx / ty; + /* Change from math coordinate to plot coordinate. */ + _draw_octant(dc, ox, oy, lx, x, y, oct); + } + + /* Midpoint increment. */ + if (dk > 0) + { + y--; + dk += 2 * (x - y) + 5; + } + else + { + dk += 2 * x + 3; + } + x++; + } + /* Draw bottom part. */ + for (; y >= 0; y--) + { + rt_int16_t lx, rx; + + lx = y * sx / ty; + rx = y * ex / my; + + _draw_octant(dc, ox, oy, lx, rx, y, oct); + } +} + +void rtgui_dc_fill_pie(struct rtgui_dc *dc, + rt_int16_t x, rt_int16_t y, rt_int16_t rad, + rt_int16_t start, rt_int16_t end) +{ + /* Sanity check radii */ + if (rad < 0) + return; + if (rad == 0) + { + rtgui_dc_draw_point(dc, x, y); + return; + } + + if (end - start >= 360) + { + rtgui_dc_fill_circle(dc, x, y, rad); + return; + } + if (start == end) + return; + + /* + * Fixup angles + */ + while (start < 0) + { + start += 360; + end += 360; + } + while (start >= 360) + { + start -= 360; + end -= 360; + } + + if (end < start) + end += 360; + + while (start / 45 != end / 45) + { + /* The start and end are not in the same piece. */ + if ((start / 45) % 2) + { + _fill_small_pie(dc, x, y, rad, + 0, 45 - start % 45, start / 45); + start += 45 - start % 45; + } + else + { + _fill_small_pie(dc, x, y, rad, + start % 45, 45, start / 45); + start += 45 - start % 45; + } + } + if ((start / 45) % 2) + { + _fill_small_pie(dc, x, y, rad, + 90 - end % 90, 90 - start % 90, start / 45); + } + else + { + _fill_small_pie(dc, x, y, rad, + start % 45, end % 45, start / 45); + } + + return; +} +RTM_EXPORT(rtgui_dc_fill_pie); + +/* + * set gc of dc + */ +void rtgui_dc_set_gc(struct rtgui_dc *dc, rtgui_gc_t *gc) +{ + RT_ASSERT(dc != RT_NULL); + + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + owner->gc = *gc; + break; + } + case RTGUI_DC_HW: + { + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + RT_ASSERT(dc_hw->owner != RT_NULL); + dc_hw->owner->gc = *gc; + break; + } + case RTGUI_DC_BUFFER: + { + struct rtgui_dc_buffer *dc_buffer; + + dc_buffer = (struct rtgui_dc_buffer *)dc; + dc_buffer->gc = *gc; + break; + } + } +} +RTM_EXPORT(rtgui_dc_set_gc); + +/* + * get gc of dc + */ +rtgui_gc_t *rtgui_dc_get_gc(struct rtgui_dc *dc) +{ + rtgui_gc_t *gc = RT_NULL; + + RT_ASSERT(dc != RT_NULL); + + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + gc = &owner->gc; + break; + } + case RTGUI_DC_HW: + { + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + RT_ASSERT(dc_hw->owner != RT_NULL); + gc = &dc_hw->owner->gc; + break; + } + case RTGUI_DC_BUFFER: + { + struct rtgui_dc_buffer *dc_buffer; + + dc_buffer = (struct rtgui_dc_buffer *)dc; + gc = &dc_buffer->gc; + break; + } + } + + return gc; +} +RTM_EXPORT(rtgui_dc_get_gc); + +/* + * get visible status of dc + */ +rt_bool_t rtgui_dc_get_visible(struct rtgui_dc *dc) +{ + rt_bool_t result = RT_TRUE; + + RT_ASSERT(dc != RT_NULL); + + if (rtgui_graphic_driver_is_vmode()) + return RT_TRUE; + + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) result = RT_FALSE; + break; + } + case RTGUI_DC_HW: + { + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + if (!RTGUI_WIDGET_IS_DC_VISIBLE(dc_hw->owner)) result = RT_FALSE; + break; + } + + default: + /* use default value */ + break; + } + + return result; +} +RTM_EXPORT(rtgui_dc_get_visible); + +/* + * get rect of dc + */ +void rtgui_dc_get_rect(struct rtgui_dc *dc, rtgui_rect_t *rect) +{ + RT_ASSERT(dc != RT_NULL); + + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + /* we should return the clipped rectangular information */ + rect->x1 = owner->clip.extents.x1 - owner->extent.x1; + rect->y1 = owner->clip.extents.y1 - owner->extent.y1; + rect->x2 = rect->x1 + owner->clip.extents.x2 - owner->clip.extents.x1; + rect->y2 = rect->y1 + owner->clip.extents.y2 - owner->clip.extents.y1; + // rtgui_widget_get_rect(owner, rect); + break; + } + case RTGUI_DC_HW: + { + rtgui_widget_t *owner; + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + owner = dc_hw->owner; + rtgui_widget_get_rect(owner, rect); + break; + } + case RTGUI_DC_BUFFER: + { + struct rtgui_dc_buffer *dc_buffer; + + dc_buffer = (struct rtgui_dc_buffer *)dc; + rtgui_rect_init(rect, 0, 0, dc_buffer->width, dc_buffer->height); + break; + } + } + + return; +} +RTM_EXPORT(rtgui_dc_get_rect); + +rt_uint8_t rtgui_dc_get_pixel_format(struct rtgui_dc *dc) +{ + rt_uint8_t pixel_fmt; + + RT_ASSERT(dc != RT_NULL); + + switch (dc->type) + { + case RTGUI_DC_CLIENT: + case RTGUI_DC_HW: + { + struct rtgui_graphic_driver *hw_driver; + + hw_driver = rtgui_graphic_driver_get_default(); + pixel_fmt = hw_driver->pixel_format; + break; + } + case RTGUI_DC_BUFFER: + { + struct rtgui_dc_buffer *dc_buffer; + + dc_buffer = (struct rtgui_dc_buffer *)dc; + pixel_fmt = dc_buffer->pixel_format; + break; + } + default: + RT_ASSERT(0); + } + + return pixel_fmt; +} +RTM_EXPORT(rtgui_dc_get_pixel_format); + +void rtgui_dc_logic_to_device(struct rtgui_dc *dc, struct rtgui_point *point) +{ + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + point->x += owner->extent.x1; + point->y += owner->extent.y1; + break; + } + case RTGUI_DC_HW: + { + rtgui_widget_t *owner; + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + owner = dc_hw->owner; + point->x += owner->extent.x1; + point->y += owner->extent.y1; + break; + } + + case RTGUI_DC_BUFFER: /* no conversion */ + break; + } +} +RTM_EXPORT(rtgui_dc_logic_to_device); + +void rtgui_dc_rect_to_device(struct rtgui_dc *dc, struct rtgui_rect *rect) +{ + switch (dc->type) + { + case RTGUI_DC_CLIENT: + { + rtgui_widget_t *owner; + /* get owner */ + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + + rtgui_rect_moveto(rect, owner->extent.x1, owner->extent.y1); + break; + } + case RTGUI_DC_HW: + { + rtgui_widget_t *owner; + struct rtgui_dc_hw *dc_hw; + + dc_hw = (struct rtgui_dc_hw *) dc; + owner = dc_hw->owner; + rtgui_rect_moveto(rect, owner->extent.x1, owner->extent.y1); + break; + } + + case RTGUI_DC_BUFFER: /* no conversion */ + break; + } +} +RTM_EXPORT(rtgui_dc_rect_to_device); + +extern struct rt_mutex cursor_mutex; +extern void rtgui_mouse_show_cursor(void); +extern void rtgui_mouse_hide_cursor(void); + +struct rtgui_dc *rtgui_dc_begin_drawing(rtgui_widget_t *owner) +{ + struct rtgui_dc *dc; + struct rtgui_widget *widget; + struct rtgui_win *win; + + RT_ASSERT(owner != RT_NULL); + + win = owner->toplevel; + if (win == RT_NULL) + return RT_NULL; + + if (!(win->flag & RTGUI_WIN_FLAG_ACTIVATE) && + (win->outer_clip.extents.x1 == win->outer_clip.extents.x2 || + win->outer_clip.extents.y1 == win->outer_clip.extents.y2)) + return RT_NULL; + + /* increase drawing count */ + win->drawing ++; + + /* always drawing on the virtual mode */ + if (rtgui_graphic_driver_is_vmode() == RT_FALSE) + { + /* set the initial visible as true */ + RTGUI_WIDGET_DC_SET_VISIBLE(owner); + + /* check the visible of widget */ + widget = owner; + while (widget != RT_NULL) + { + if (RTGUI_WIDGET_IS_HIDE(widget)) + { + RTGUI_WIDGET_DC_SET_UNVISIBLE(owner); + win->drawing --; + return RT_NULL; + } + widget = widget->parent; + } + } + + rtgui_screen_lock(RT_WAITING_FOREVER); + + /* create client or hardware DC */ + if ((rtgui_region_is_flat(&owner->clip) == RT_EOK) && + rtgui_rect_is_equal(&(owner->extent), &(owner->clip.extents)) == RT_EOK) + dc = rtgui_dc_hw_create(owner); + else + dc = rtgui_dc_client_create(owner); + + if (dc == RT_NULL) + { + /* restore drawing counter */ + win->drawing--; + rtgui_screen_unlock(); + } + else if (win->drawing == 1 && rtgui_graphic_driver_is_vmode() == RT_FALSE) + { +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER); + rtgui_mouse_hide_cursor(); +#endif + + if (! RTGUI_IS_WINTITLE(win)) + { + /* send draw begin to server */ + struct rtgui_event_update_begin eupdate; + RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate)); + eupdate.rect = RTGUI_WIDGET(win)->extent; + + rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate)); + } + } + + return dc; +} +RTM_EXPORT(rtgui_dc_begin_drawing); + +void rtgui_dc_end_drawing(struct rtgui_dc *dc) +{ + struct rtgui_widget *owner; + struct rtgui_win *win; + + RT_ASSERT(dc != RT_NULL); + + /* get owner */ + if (dc->type == RTGUI_DC_CLIENT) + owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type); + else if (dc->type == RTGUI_DC_HW) + owner = ((struct rtgui_dc_hw *)dc)->owner; + else return ; /* bad DC type */ + /* get window */ + win = owner->toplevel; + + /* decrease drawing counter */ + win->drawing --; + if (win->drawing == 0 && rtgui_graphic_driver_is_vmode() == RT_FALSE) + { +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_release(&cursor_mutex); + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + + if (RTGUI_IS_WINTITLE(win)) + { + /* update screen */ + rtgui_graphic_driver_screen_update(rtgui_graphic_driver_get_default(), + &(owner->extent)); + } + else + { + /* send to server for window update */ + struct rtgui_event_update_end eupdate; + RTGUI_EVENT_UPDATE_END_INIT(&(eupdate)); + eupdate.rect = owner->extent; + + rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate)); + } + } + + dc->engine->fini(dc); + rtgui_screen_unlock(); +} +RTM_EXPORT(rtgui_dc_end_drawing); + |
