From 885b3d53b3a491c62fb0634b78cb9857723ac15d Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Mon, 11 Feb 2013 09:25:26 +0100 Subject: removed GDISP_LLD() macro --- src/gwin/button.c | 275 --------------------------- src/gwin/console.c | 158 ---------------- src/gwin/graph.c | 362 ----------------------------------- src/gwin/gwin.c | 544 ----------------------------------------------------- src/gwin/gwin.mk | 5 - 5 files changed, 1344 deletions(-) delete mode 100644 src/gwin/button.c delete mode 100644 src/gwin/console.c delete mode 100644 src/gwin/graph.c delete mode 100644 src/gwin/gwin.c delete mode 100644 src/gwin/gwin.mk (limited to 'src/gwin') diff --git a/src/gwin/button.c b/src/gwin/button.c deleted file mode 100644 index 8a904d95..00000000 --- a/src/gwin/button.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/** - * @file src/gwin/button.c - * @brief GWIN sub-system button code. - * - * @defgroup Button Button - * @ingroup GWIN - * - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gfx.h" - -#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__) - -#include - -#include "gwin/internal.h" - -static const GButtonStyle GButtonDefaultStyle = { - GBTN_3D, - HTML2COLOR(0x404040), // color_up_edge; - HTML2COLOR(0xE0E0E0), // color_up_fill; - HTML2COLOR(0x000000), // color_up_txt; - HTML2COLOR(0x404040), // color_dn_edge; - HTML2COLOR(0x808080), // color_dn_fill; - HTML2COLOR(0x404040), // color_dn_txt; - }; - -// Process an event callback -static void gwinButtonCallback(void *param, GEvent *pe) { - GSourceListener *psl; - #define gh ((GHandle)param) - #define gbw ((GButtonObject *)param) - #define gsh ((GSourceHandle)param) - #define pme ((GEventMouse *)pe) - #define pte ((GEventTouch *)pe) - #define pxe ((GEventToggle *)pe) - #define pbe ((GEventGWinButton *)pe) - - switch (pe->type) { - #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE - case GEVENT_MOUSE: - case GEVENT_TOUCH: - // Ignore anything other than the primary mouse button going up or down - if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT)) - return; - - if (gbw->state == GBTN_UP) { - // Our button is UP: Test for button down over the button - if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT) - && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width - && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) { - gbw->state = GBTN_DOWN; - gwinButtonDraw((GHandle)param); - } - return; - } - - // Our button is DOWN - - // Skip more mouse downs - if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) - return; - - // This must be a mouse up - set the button as UP - gbw->state = GBTN_UP; - gwinButtonDraw((GHandle)param); - - // If the mouse up was over the button then create the event - if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width - && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) - break; - - return; - #endif - - #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE - case GEVENT_TOGGLE: - // State has changed - update the button - gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP; - gwinButtonDraw((GHandle)param); - - // Trigger the event on button down (different than for mouse/touch) - if (gbw->state == GBTN_DOWN) - break; - - return; - #endif - - default: - return; - } - - // Trigger a GWIN Button Event - psl = 0; - while ((psl = geventGetSourceListener(gsh, psl))) { - if (!(pe = geventGetEventBuffer(psl))) - continue; - pbe->type = GEVENT_GWIN_BUTTON; - pbe->button = gh; - geventSendEvent(psl); - } - - #undef pbe - #undef pme - #undef pte - #undef pxe - #undef gsh - #undef gbw - #undef gh -} - -GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) { - if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject)))) - return 0; - gb->gwin.type = GW_BUTTON; - gwinSetFont(&gb->gwin, font); - gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle); - gb->type = type; - gb->state = GBTN_UP; - gb->txt = ""; - geventListenerInit(&gb->listener); - geventRegisterCallback(&gb->listener, gwinButtonCallback, gb); - return (GHandle)gb; -} - -void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) { - #define gbw ((GButtonObject *)gh) - if (gh->type != GW_BUTTON) - return; - - gbw->style.shape = style->shape; - gbw->style.color_up_edge = style->color_up_edge; - gbw->style.color_up_fill = style->color_up_fill; - gbw->style.color_dn_edge = style->color_dn_edge; - gbw->style.color_dn_fill = style->color_dn_fill; - gbw->style.color_up_txt = style->color_up_txt; - gbw->style.color_dn_txt = style->color_dn_txt; - #undef gbw -} - -void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) { - #define gbw ((GButtonObject *)gh) - if (gh->type != GW_BUTTON) - return; - - // Dispose of the old string - if ((gh->flags & GBTN_FLG_ALLOCTXT)) { - gh->flags &= ~GBTN_FLG_ALLOCTXT; - if (gbw->txt) { - chHeapFree((void *)gbw->txt); - gbw->txt = ""; - } - } - // Alloc the new text if required - if (txt && useAlloc) { - char *str; - - if ((str = (char *)chHeapAlloc(NULL, strlen(txt)+1))) { - gh->flags |= GBTN_FLG_ALLOCTXT; - strcpy(str, txt); - } - txt = (const char *)str; - } - - gbw->txt = txt ? txt : ""; - #undef gbw -} - -void gwinButtonDraw(GHandle gh) { - color_t cedge; - color_t cfill; - color_t ctxt; - const char * txt; - #define gbw ((GButtonObject *)gh) - #define RND_CNR_SIZE 5 - - if (gh->type != GW_BUTTON) - return; - - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - - // Get the text (safely) - txt = gh->font && gbw->txt ? gbw->txt : ""; - - // Determine the colors to use - switch(gbw->state) { - case GBTN_DOWN: - cedge = gbw->style.color_dn_edge; - cfill = gbw->style.color_dn_fill; - ctxt = gbw->style.color_dn_txt; - break; - case GBTN_UP: default: - cedge = gbw->style.color_up_edge; - cfill = gbw->style.color_up_fill; - ctxt = gbw->style.color_up_txt; - break; - } - - // Draw according to the shape specified. - switch(gbw->style.shape) { -#if GDISP_NEED_ARC - case GBTN_ROUNDED: - if (gh->width >= 2*RND_CNR_SIZE+10) { - gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill); - gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter); - gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge); - break; - } - /* Fall Through */ -#endif - case GBTN_SQUARE: - gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter); - gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge); - break; -#if GDISP_NEED_ELLIPSE - case GBTN_ELLIPSE: - gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill); - gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter); - gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge); - break; -#endif - case GBTN_3D: default: - gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter); - gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge); - gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge); - break; - } - #undef gbw -} - -#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE - bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) { - if (gh->type != GW_BUTTON) - return FALSE; - - return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA); - } -#endif - -#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE - bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh) { - if (gh->type != GW_BUTTON) - return FALSE; - - return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON); - } -#endif - -#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */ -/** @} */ - diff --git a/src/gwin/console.c b/src/gwin/console.c deleted file mode 100644 index 9be7ee34..00000000 --- a/src/gwin/console.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/** - * @file src/gwin/console.c - * @brief GWIN sub-system console code. - * - * @defgroup Console Console - * @ingroup GWIN - * - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gfx.h" - -#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__) - -#include - -#include "gwin/internal.h" - -#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE -#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE - -/* - * Stream interface implementation. The interface is write only - */ - -#define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream)))) - -static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } -static size_t GWinStreamRead(void *ip, uint8_t *bp, size_t n) { (void)ip; (void)bp; (void)n; return 0; } -static msg_t GWinStreamPut(void *ip, uint8_t b) { gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } -static msg_t GWinStreamGet(void *ip) {(void)ip; return RDY_OK; } -static msg_t GWinStreamPutTimed(void *ip, uint8_t b, systime_t time) { (void)time; gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } -static msg_t GWinStreamGetTimed(void *ip, systime_t timeout) { (void)ip; (void)timeout; return RDY_OK; } -static size_t GWinStreamWriteTimed(void *ip, const uint8_t *bp, size_t n, systime_t time) { (void)time; gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } -static size_t GWinStreamReadTimed(void *ip, uint8_t *bp, size_t n, systime_t time) { (void)ip; (void)bp; (void)n; (void)time; return 0; } - -struct GConsoleWindowVMT_t { - _base_asynchronous_channel_methods -}; - -static const struct GConsoleWindowVMT_t GWindowConsoleVMT = { - GWinStreamWrite, - GWinStreamRead, - GWinStreamPut, - GWinStreamGet, - GWinStreamPutTimed, - GWinStreamGetTimed, - GWinStreamWriteTimed, - GWinStreamReadTimed -}; - -GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) { - if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject)))) - return 0; - gc->gwin.type = GW_CONSOLE; - gwinSetFont(&gc->gwin, font); - gc->stream.vmt = &GWindowConsoleVMT; - gc->cx = 0; - gc->cy = 0; - return (GHandle)gc; -} - -BaseSequentialStream *gwinGetConsoleStream(GHandle gh) { - if (gh->type != GW_CONSOLE) - return 0; - return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream); -} - -void gwinPutChar(GHandle gh, char c) { - uint8_t width; - #define gcw ((GConsoleObject *)gh) - - if (gh->type != GW_CONSOLE || !gh->font) return; - - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - - if (c == '\n') { - gcw->cx = 0; - gcw->cy += gcw->fy; - // We use lazy scrolling here and only scroll when the next char arrives - } else if (c == '\r') { - // gcw->cx = 0; - } else { - width = gdispGetCharWidth(c, gh->font) + gcw->fp; - if (gcw->cx + width >= gh->width) { - gcw->cx = 0; - gcw->cy += gcw->fy; - } - - if (gcw->cy + gcw->fy > gh->height) { -#if GDISP_NEED_SCROLL - /* scroll the console */ - gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor); - /* reset the cursor to the start of the last line */ - gcw->cx = 0; - gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy; -#else - /* clear the console */ - gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); - /* reset the cursor to the top of the window */ - gcw->cx = 0; - gcw->cy = 0; -#endif - } - -#if GWIN_CONSOLE_USE_CLEAR_LINES - /* clear to the end of the line */ - if (gcw->cx == 0) - gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor); -#endif -#if GWIN_CONSOLE_USE_FILLED_CHARS - gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); -#else - gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); -#endif - - /* update cursor */ - gcw->cx += width; - } - #undef gcw -} - -void gwinPutString(GHandle gh, const char *str) { - while(*str) - gwinPutChar(gh, *str++); -} - -void gwinPutCharArray(GHandle gh, const char *str, size_t n) { - while(n--) - gwinPutChar(gh, *str++); -} - -#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */ -/** @} */ - diff --git a/src/gwin/graph.c b/src/gwin/graph.c deleted file mode 100644 index a9d20c4b..00000000 --- a/src/gwin/graph.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/** - * @file src/gwin/graph.c - * @brief GWIN sub-system button code. - * - * @defgroup Graph Graph - * @ingroup GWIN - * - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gfx.h" - -#if (GFX_USE_GWIN && GWIN_NEED_GRAPH) || defined(__DOXYGEN__) - -#include "gwin/internal.h" - -#define GGRAPH_FLG_CONNECTPOINTS (GWIN_FIRST_CONTROL_FLAG<<0) -#define GGRAPH_ARROW_SIZE 5 - -static const GGraphStyle GGraphDefaultStyle = { - { GGRAPH_POINT_DOT, 0, White }, // point - { GGRAPH_LINE_DOT, 2, Gray }, // line - { GGRAPH_LINE_SOLID, 0, White }, // x axis - { GGRAPH_LINE_SOLID, 0, White }, // y axis - { GGRAPH_LINE_NONE, 0, White, 0 }, // x grid - { GGRAPH_LINE_NONE, 0, White, 0 }, // y grid - GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS // flags -}; - -static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointStyle *style) { - if (style->type == GGRAPH_POINT_NONE) - return; - - // Convert to device space. Note the y-axis is inverted. - x += gg->gwin.x + gg->xorigin; - y = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y; - - if (style->size <= 1) { - gdispDrawPixel(x, y, style->color); - return; - } - - switch(style->type) { - case GGRAPH_POINT_SQUARE: - gdispDrawBox(x-style->size, y-style->size, 2*style->size, 2*style->size, style->color); - break; -#if GDISP_NEED_CIRCLE - case GGRAPH_POINT_CIRCLE: - gdispDrawCircle(x, y, style->size, style->color); - break; -#endif - case GGRAPH_POINT_DOT: - default: - gdispDrawPixel(x, y, style->color); - break; - } -} - -static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t y1, const GGraphLineStyle *style) { - coord_t dy, dx; - coord_t addx, addy; - coord_t P, diff, i; - coord_t run_on, run_off, run; - - if (style->type == GGRAPH_LINE_NONE) - return; - - // Convert to device space. Note the y-axis is inverted. - x0 += gg->gwin.x + gg->xorigin; - y0 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y0; - x1 += gg->gwin.x + gg->xorigin; - y1 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y1; - - if (style->size <= 0) { - // Use the driver to draw a solid line - gdispDrawLine(x0, y0, x1, y1, style->color); - return; - } - - switch (style->type) { - case GGRAPH_LINE_DOT: - run_on = 1; - run_off = -style->size; - break; - - case GGRAPH_LINE_DASH: - run_on = style->size; - run_off = -style->size; - break; - - case GGRAPH_LINE_SOLID: - default: - // Use the driver to draw a solid line - gdispDrawLine(x0, y0, x1, y1, style->color); - return; - } - - // Use Bresenham's algorithm modified to draw a stylized line - run = 0; - if (x1 >= x0) { - dx = x1 - x0; - addx = 1; - } else { - dx = x0 - x1; - addx = -1; - } - if (y1 >= y0) { - dy = y1 - y0; - addy = 1; - } else { - dy = y0 - y1; - addy = -1; - } - - if (dx >= dy) { - dy *= 2; - P = dy - dx; - diff = P - dx; - - for(i=0; i<=dx; ++i) { - if (run++ >= 0) { - if (run >= run_on) - run = run_off; - gdispDrawPixel(x0, y0, style->color); - } - if (P < 0) { - P += dy; - x0 += addx; - } else { - P += diff; - x0 += addx; - y0 += addy; - } - } - } else { - dx *= 2; - P = dx - dy; - diff = P - dy; - - for(i=0; i<=dy; ++i) { - if (run++ >= 0) { - if (run >= run_on) - run = run_off; - gdispDrawPixel(x0, y0, style->color); - } - if (P < 0) { - P += dx; - y0 += addy; - } else { - P += diff; - x0 += addx; - y0 += addy; - } - } - } -} - -GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject)))) - return 0; - gg->gwin.type = GW_GRAPH; - gg->xorigin = gg->yorigin = 0; - gg->lastx = gg->lasty = 0; - gwinGraphSetStyle(&gg->gwin, &GGraphDefaultStyle); - return (GHandle)gg; -} - -void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) { - #define gg ((GGraphObject *)gh) - - if (gh->type != GW_GRAPH) - return; - - gg->style.point.type = pstyle->point.type; - gg->style.point.size = pstyle->point.size; - gg->style.point.color = pstyle->point.color; - gg->style.line.type = pstyle->line.type; - gg->style.line.size = pstyle->line.size; - gg->style.line.color = pstyle->line.color; - gg->style.xaxis.type = pstyle->xaxis.type; - gg->style.xaxis.size = pstyle->xaxis.size; - gg->style.xaxis.color = pstyle->xaxis.color; - gg->style.yaxis.type = pstyle->yaxis.type; - gg->style.yaxis.size = pstyle->yaxis.size; - gg->style.yaxis.color = pstyle->yaxis.color; - gg->style.xgrid.type = pstyle->xgrid.type; - gg->style.xgrid.size = pstyle->xgrid.size; - gg->style.xgrid.color = pstyle->xgrid.color; - gg->style.xgrid.spacing = pstyle->xgrid.spacing; - gg->style.ygrid.type = pstyle->ygrid.type; - gg->style.ygrid.size = pstyle->ygrid.size; - gg->style.ygrid.color = pstyle->ygrid.color; - gg->style.ygrid.spacing = pstyle->ygrid.spacing; - gg->style.flags = pstyle->flags; - - #undef gg -} - -void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y) { - #define gg ((GGraphObject *)gh) - - if (gh->type != GW_GRAPH) - return; - - gg->xorigin = x; - gg->yorigin = y; - - #undef gg -} - -void gwinGraphDrawAxis(GHandle gh) { - #define gg ((GGraphObject *)gh) - coord_t i, xmin, ymin, xmax, ymax; - - if (gh->type != GW_GRAPH) - return; - - xmin = -gg->xorigin; - xmax = gh->width-gg->xorigin-1; - ymin = -gg->yorigin; - ymax = gh->height-gg->yorigin-1; - - // x grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle - if (gg->style.xgrid.type != GGRAPH_LINE_NONE && gg->style.xgrid.spacing >= 2) { - for(i = gg->style.xgrid.spacing; i <= xmax; i += gg->style.xgrid.spacing) - lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid); - for(i = -gg->style.xgrid.spacing; i >= xmin; i -= gg->style.xgrid.spacing) - lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid); - } - - // y grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle - if (gg->style.ygrid.type != GGRAPH_LINE_NONE && gg->style.ygrid.spacing >= 2) { - for(i = gg->style.ygrid.spacing; i <= ymax; i += gg->style.ygrid.spacing) - lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid); - for(i = -gg->style.ygrid.spacing; i >= ymin; i -= gg->style.ygrid.spacing) - lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid); - } - - // x axis - lineto(gg, xmin, 0, xmax, 0, &gg->style.xaxis); - if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS)) { - if (xmin > 0 || xmin < -(GGRAPH_ARROW_SIZE+1)) { - lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis); - lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis); - } - } - if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS)) { - if (xmax < 0 || xmax > (GGRAPH_ARROW_SIZE+1)) { - lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis); - lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis); - } - } - - // y axis - lineto(gg, 0, ymin, 0, ymax, &gg->style.yaxis); - if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS)) { - if (ymin > 0 || ymin < -(GGRAPH_ARROW_SIZE+1)) { - lineto(gg, 0, ymin, GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis); - lineto(gg, 0, ymin, -GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis); - } - } - if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS)) { - if (ymax < 0 || ymax > (GGRAPH_ARROW_SIZE+1)) { - lineto(gg, 0, ymax, GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis); - lineto(gg, 0, ymax, -GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis); - } - } - - #undef gg -} - -void gwinGraphStartSet(GHandle gh) { - if (gh->type != GW_GRAPH) - return; - - gh->flags &= ~GGRAPH_FLG_CONNECTPOINTS; -} - -void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) { - #define gg ((GGraphObject *)gh) - - if (gh->type != GW_GRAPH) - return; - - if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) { - // Draw the line - lineto(gg, gg->lastx, gg->lasty, x, y, &gg->style.line); - - // Redraw the previous point because the line may have overwritten it - pointto(gg, gg->lastx, gg->lasty, &gg->style.point); - - } else - gh->flags |= GGRAPH_FLG_CONNECTPOINTS; - - // Save this point for next time. - gg->lastx = x; - gg->lasty = y; - - // Draw this point. - pointto(gg, x, y, &gg->style.point); - - #undef gg -} - -void gwinGraphDrawPoints(GHandle gh, const GGraphPoint *points, unsigned count) { - #define gg ((GGraphObject *)gh) - unsigned i; - const GGraphPoint *p; - - if (gh->type != GW_GRAPH) - return; - - // Draw the connecting lines - for(p = points, i = 0; i < count; p++, i++) { - if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) { - // Draw the line - lineto(gg, gg->lastx, gg->lasty, p->x, p->y, &gg->style.line); - - // Redraw the previous point because the line may have overwritten it - if (i == 0) - pointto(gg, gg->lastx, gg->lasty, &gg->style.point); - - } else - gh->flags |= GGRAPH_FLG_CONNECTPOINTS; - - // Save this point for next time. - gg->lastx = p->x; - gg->lasty = p->y; - } - - - // Draw the points. - for(p = points, i = 0; i < count; p++, i++) - pointto(gg, p->x, p->y, &gg->style.point); - - #undef gg -} - -#endif /* GFX_USE_GWIN && GWIN_NEED_GRAPH */ -/** @} */ - diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c deleted file mode 100644 index 4eef79ad..00000000 --- a/src/gwin/gwin.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/** - * @file src/gwin/gwin.c - * @brief GWIN sub-system code. - * - * @defgroup Window Window - * @ingroup GWIN - * - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gfx.h" - -#if GFX_USE_GWIN || defined(__DOXYGEN__) - -#include "gwin/internal.h" - -// Internal routine for use by GWIN components only -// Initialise a window creating it dynamicly if required. -GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) { - coord_t w, h; - - // Check the window size against the screen size - w = gdispGetWidth(); - h = gdispGetHeight(); - if (x < 0) { width += x; x = 0; } - if (y < 0) { height += y; y = 0; } - if (x >= w || y >= h) return 0; - if (x+width > w) width = w - x; - if (y+height > h) height = h - y; - - // Allocate the structure if necessary - if (!gw) { - if (!(gw = (GWindowObject *)chHeapAlloc(NULL, size))) - return 0; - gw->flags = GWIN_FLG_DYNAMIC; - } else - gw->flags = 0; - - // Initialise all basic fields (except the type) - gw->x = x; - gw->y = y; - gw->width = width; - gw->height = height; - gw->color = White; - gw->bgcolor = Black; -#if GDISP_NEED_TEXT - gw->font = 0; -#endif - return (GHandle)gw; -} - -/** - * @brief Create a basic window. - * @return NULL if there is no resultant drawing area, otherwise a window handle. - * - * @param[in] gw The window structure to initialise. If this is NULL the structure is dynamically allocated. - * @param[in] x,y The screen co-ordinates for the bottom left corner of the window - * @param[in] width The width of the window - * @param[in] height The height of the window - * @note The default drawing color gets set to White and the background drawing color to Black. - * @note No default font is set so make sure to set one before drawing any text. - * @note The dimensions and position may be changed to fit on the real screen. - * @note The window is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color) - * - * @api - */ -GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject)))) - return 0; - gw->type = GW_WINDOW; - return (GHandle)gw; -} - -/** - * @brief Destroy a window (of any type). Releases any dynamicly allocated memory. - * - * @param[in] gh The window handle - * - * @api - */ -void gwinDestroyWindow(GHandle gh) { - // Clean up any type specific dynamic memory allocations - switch(gh->type) { -#if GWIN_NEED_BUTTON - case GW_BUTTON: - if ((gh->flags & GBTN_FLG_ALLOCTXT)) { - gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure - chHeapFree((void *)((GButtonObject *)gh)->txt); - } - break; -#endif - default: - break; - } - - // Clean up the structure - if (gh->flags & GWIN_FLG_DYNAMIC) { - gh->flags = 0; // To be sure, to be sure - chHeapFree((void *)gh); - } -} - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Set the current font for this window. - * - * @param[in] gh The window handle - * @param[in] font The font to use for text functions - * - * @api - */ -void gwinSetFont(GHandle gh, font_t font) { - gh->font = font; -#if GWIN_NEED_CONSOLE - if (font && gh->type == GW_CONSOLE) { - ((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight); - ((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding); - } -#endif -} -#endif - -/** - * @brief Clear the window - * @note Uses the current background color to clear the window - * - * @param[in] gh The window handle - * - * @api - */ -void gwinClear(GHandle gh) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); - - #if GWIN_NEED_CONSOLE - if (gh->type == GW_CONSOLE) { - ((GConsoleObject *)gh)->cx = 0; - ((GConsoleObject *)gh)->cy = 0; - } - #endif -} - -/** - * @brief Set a pixel in the window - * @note Uses the current foreground color to set the pixel - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The coordinates of the pixel - * - * @api - */ -void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawPixel(gh->x+x, gh->y+y, gh->color); -} - -/** - * @brief Draw a line in the window - * @note Uses the current foreground color to draw the line - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x0,y0 The start position - * @param[in] x1,y1 The end position - * - * @api - */ -void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawLine(gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color); -} - -/** - * @brief Draw a box in the window - * @note Uses the current foreground color to draw the box - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The start position - * @param[in] cx,cy The size of the box (outside dimensions) - * - * @api - */ -void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawBox(gh->x+x, gh->y+y, cx, cy, gh->color); -} - -/** - * @brief Fill an rectangular area in the window - * @note Uses the current foreground color to fill the box - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The start position - * @param[in] cx,cy The size of the box (outside dimensions) - * - * @api - */ -void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillArea(gh->x+x, gh->y+y, cx, cy, gh->color); -} - -/** - * @brief Fill an area in the window using the supplied bitmap. - * @details The bitmap is in the pixel format specified by the low level driver - * @note If GDISP_NEED_ASYNC is defined then the buffer must be static - * or at least retained until this call has finished the blit. You can - * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE. - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x, y The start filled area - * @param[in] cx, cy The width and height to be filled - * @param[in] srcx, srcy The bitmap position to start the fill from - * @param[in] srccx The width of a line in the bitmap. - * @param[in] buffer The pixels to use to fill the area. - * - * @api - */ -void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispBlitAreaEx(gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer); -} - -#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__) -/** - * @brief Draw a circle in the window. - * @note Uses the current foreground color to draw the circle - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x, y The center of the circle - * @param[in] radius The radius of the circle - * - * @api - */ -void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawCircle(gh->x+x, gh->y+y, radius, gh->color); -} -#endif - -#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__) -/** - * @brief Draw a filled circle in the window. - * @note Uses the current foreground color to draw the filled circle - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x, y The center of the circle - * @param[in] radius The radius of the circle - * - * @api - */ -void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillCircle(gh->x+x, gh->y+y, radius, gh->color); -} -#endif - -#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__) -/** - * @brief Draw an ellipse. - * @note Uses the current foreground color to draw the ellipse - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The center of the ellipse - * @param[in] a,b The dimensions of the ellipse - * - * @api - */ -void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawEllipse(gh->x+x, gh->y+y, a, b, gh->color); -} -#endif - -#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__) -/** - * @brief Draw an filled ellipse. - * @note Uses the current foreground color to draw the filled ellipse - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The center of the ellipse - * @param[in] a,b The dimensions of the ellipse - * - * @api - */ -void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillEllipse(gh->x+x, gh->y+y, a, b, gh->color); -} -#endif - -#if GDISP_NEED_ARC || defined(__DOXYGEN__) -/* - * @brief Draw an arc in the window. - * @note Uses the current foreground color to draw the arc - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The center point - * @param[in] radius The radius of the arc - * @param[in] start The start angle (0 to 360) - * @param[in] end The end angle (0 to 360) - * - * @api - */ -void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); -} -#endif - -#if GDISP_NEED_ARC || defined(__DOXYGEN__) -/* - * @brief Draw a filled arc in the window. - * @note Uses the current foreground color to draw the filled arc - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The center point - * @param[in] radius The radius of the arc - * @param[in] start The start angle (0 to 360) - * @param[in] end The end angle (0 to 360) - * - * @api - */ -void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); -} -#endif - -#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__) -/** - * @brief Get the color of a pixel in the window. - * @return The color of the pixel. - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position in the window - * - * @api - */ -color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) { - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - return gdispGetPixelColor(gh->x+x, gh->y+y); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text character at the specified position in the window. - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text - * @param[in] c The character to draw - * - * @api - */ -void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawChar(gh->x+x, gh->y+y, c, gh->font, gh->color); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text character with a filled background at the specified position in the window. - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character and fills the background using the background drawing color - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text - * @param[in] c The character to draw - * - * @api - */ -void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillChar(gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text string in the window - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text - * @param[in] str The string to draw - * - * @api - */ -void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawString(gh->x+x, gh->y+y, str, gh->font, gh->color); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text string with a filled background in the window - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character and fills the background using the background drawing color - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text - * @param[in] str The string to draw - * - * @api - */ -void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillString(gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text string verticly centered within the specified box. - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character. - * @note The specified box does not need to align with the window box - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text (need to define top-right or base-line - check code) - * @param[in] cx,cy The width and height of the box - * @param[in] str The string to draw - * @param[in] justify Justify the text left, center or right within the box - * - * @api - */ -void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispDrawStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify); -} -#endif - -#if GDISP_NEED_TEXT || defined(__DOXYGEN__) -/** - * @brief Draw a text string verticly centered within the specified filled box. - * @pre The font must have been set. - * @note Uses the current foreground color to draw the character and fills the background using the background drawing color - * @note The entire box is filled. Note this box does not need to align with the window box - * @note May leave GDISP clipping to this window's dimensions - * - * @param[in] gh The window handle - * @param[in] x,y The position for the text (need to define top-right or base-line - check code) - * @param[in] cx,cy The width and height of the box - * @param[in] str The string to draw - * @param[in] justify Justify the text left, center or right within the box - * - * @api - */ -void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { - if (!gh->font) return; - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - gdispFillStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify); -} -#endif - -#endif /* GFX_USE_GWIN */ -/** @} */ - diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk deleted file mode 100644 index 947d11f3..00000000 --- a/src/gwin/gwin.mk +++ /dev/null @@ -1,5 +0,0 @@ -GFXSRC += $(GFXLIB)/src/gwin/gwin.c \ - $(GFXLIB)/src/gwin/console.c \ - $(GFXLIB)/src/gwin/button.c \ - $(GFXLIB)/src/gwin/graph.c - \ No newline at end of file -- cgit v1.2.3 From 1bfc5a9f85e7c3296095105ca8e3ee1215b22be8 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Mon, 11 Feb 2013 09:25:45 +0100 Subject: removed GDISP_LLD() macro - fix --- src/gwin/button.c | 275 +++++++++++++++++++++++++++ src/gwin/console.c | 158 ++++++++++++++++ src/gwin/graph.c | 362 +++++++++++++++++++++++++++++++++++ src/gwin/gwin.c | 544 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/gwin/gwin.mk | 5 + 5 files changed, 1344 insertions(+) create mode 100644 src/gwin/button.c create mode 100644 src/gwin/console.c create mode 100644 src/gwin/graph.c create mode 100644 src/gwin/gwin.c create mode 100644 src/gwin/gwin.mk (limited to 'src/gwin') diff --git a/src/gwin/button.c b/src/gwin/button.c new file mode 100644 index 00000000..8a904d95 --- /dev/null +++ b/src/gwin/button.c @@ -0,0 +1,275 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file src/gwin/button.c + * @brief GWIN sub-system button code. + * + * @defgroup Button Button + * @ingroup GWIN + * + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gfx.h" + +#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__) + +#include + +#include "gwin/internal.h" + +static const GButtonStyle GButtonDefaultStyle = { + GBTN_3D, + HTML2COLOR(0x404040), // color_up_edge; + HTML2COLOR(0xE0E0E0), // color_up_fill; + HTML2COLOR(0x000000), // color_up_txt; + HTML2COLOR(0x404040), // color_dn_edge; + HTML2COLOR(0x808080), // color_dn_fill; + HTML2COLOR(0x404040), // color_dn_txt; + }; + +// Process an event callback +static void gwinButtonCallback(void *param, GEvent *pe) { + GSourceListener *psl; + #define gh ((GHandle)param) + #define gbw ((GButtonObject *)param) + #define gsh ((GSourceHandle)param) + #define pme ((GEventMouse *)pe) + #define pte ((GEventTouch *)pe) + #define pxe ((GEventToggle *)pe) + #define pbe ((GEventGWinButton *)pe) + + switch (pe->type) { + #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + case GEVENT_MOUSE: + case GEVENT_TOUCH: + // Ignore anything other than the primary mouse button going up or down + if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT)) + return; + + if (gbw->state == GBTN_UP) { + // Our button is UP: Test for button down over the button + if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT) + && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width + && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) { + gbw->state = GBTN_DOWN; + gwinButtonDraw((GHandle)param); + } + return; + } + + // Our button is DOWN + + // Skip more mouse downs + if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) + return; + + // This must be a mouse up - set the button as UP + gbw->state = GBTN_UP; + gwinButtonDraw((GHandle)param); + + // If the mouse up was over the button then create the event + if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width + && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) + break; + + return; + #endif + + #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + case GEVENT_TOGGLE: + // State has changed - update the button + gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP; + gwinButtonDraw((GHandle)param); + + // Trigger the event on button down (different than for mouse/touch) + if (gbw->state == GBTN_DOWN) + break; + + return; + #endif + + default: + return; + } + + // Trigger a GWIN Button Event + psl = 0; + while ((psl = geventGetSourceListener(gsh, psl))) { + if (!(pe = geventGetEventBuffer(psl))) + continue; + pbe->type = GEVENT_GWIN_BUTTON; + pbe->button = gh; + geventSendEvent(psl); + } + + #undef pbe + #undef pme + #undef pte + #undef pxe + #undef gsh + #undef gbw + #undef gh +} + +GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) { + if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject)))) + return 0; + gb->gwin.type = GW_BUTTON; + gwinSetFont(&gb->gwin, font); + gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle); + gb->type = type; + gb->state = GBTN_UP; + gb->txt = ""; + geventListenerInit(&gb->listener); + geventRegisterCallback(&gb->listener, gwinButtonCallback, gb); + return (GHandle)gb; +} + +void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) { + #define gbw ((GButtonObject *)gh) + if (gh->type != GW_BUTTON) + return; + + gbw->style.shape = style->shape; + gbw->style.color_up_edge = style->color_up_edge; + gbw->style.color_up_fill = style->color_up_fill; + gbw->style.color_dn_edge = style->color_dn_edge; + gbw->style.color_dn_fill = style->color_dn_fill; + gbw->style.color_up_txt = style->color_up_txt; + gbw->style.color_dn_txt = style->color_dn_txt; + #undef gbw +} + +void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) { + #define gbw ((GButtonObject *)gh) + if (gh->type != GW_BUTTON) + return; + + // Dispose of the old string + if ((gh->flags & GBTN_FLG_ALLOCTXT)) { + gh->flags &= ~GBTN_FLG_ALLOCTXT; + if (gbw->txt) { + chHeapFree((void *)gbw->txt); + gbw->txt = ""; + } + } + // Alloc the new text if required + if (txt && useAlloc) { + char *str; + + if ((str = (char *)chHeapAlloc(NULL, strlen(txt)+1))) { + gh->flags |= GBTN_FLG_ALLOCTXT; + strcpy(str, txt); + } + txt = (const char *)str; + } + + gbw->txt = txt ? txt : ""; + #undef gbw +} + +void gwinButtonDraw(GHandle gh) { + color_t cedge; + color_t cfill; + color_t ctxt; + const char * txt; + #define gbw ((GButtonObject *)gh) + #define RND_CNR_SIZE 5 + + if (gh->type != GW_BUTTON) + return; + + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + + // Get the text (safely) + txt = gh->font && gbw->txt ? gbw->txt : ""; + + // Determine the colors to use + switch(gbw->state) { + case GBTN_DOWN: + cedge = gbw->style.color_dn_edge; + cfill = gbw->style.color_dn_fill; + ctxt = gbw->style.color_dn_txt; + break; + case GBTN_UP: default: + cedge = gbw->style.color_up_edge; + cfill = gbw->style.color_up_fill; + ctxt = gbw->style.color_up_txt; + break; + } + + // Draw according to the shape specified. + switch(gbw->style.shape) { +#if GDISP_NEED_ARC + case GBTN_ROUNDED: + if (gh->width >= 2*RND_CNR_SIZE+10) { + gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill); + gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter); + gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge); + break; + } + /* Fall Through */ +#endif + case GBTN_SQUARE: + gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter); + gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge); + break; +#if GDISP_NEED_ELLIPSE + case GBTN_ELLIPSE: + gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill); + gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter); + gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge); + break; +#endif + case GBTN_3D: default: + gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter); + gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge); + gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge); + break; + } + #undef gbw +} + +#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) { + if (gh->type != GW_BUTTON) + return FALSE; + + return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA); + } +#endif + +#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh) { + if (gh->type != GW_BUTTON) + return FALSE; + + return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON); + } +#endif + +#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */ +/** @} */ + diff --git a/src/gwin/console.c b/src/gwin/console.c new file mode 100644 index 00000000..9be7ee34 --- /dev/null +++ b/src/gwin/console.c @@ -0,0 +1,158 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file src/gwin/console.c + * @brief GWIN sub-system console code. + * + * @defgroup Console Console + * @ingroup GWIN + * + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gfx.h" + +#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__) + +#include + +#include "gwin/internal.h" + +#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE +#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE + +/* + * Stream interface implementation. The interface is write only + */ + +#define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream)))) + +static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } +static size_t GWinStreamRead(void *ip, uint8_t *bp, size_t n) { (void)ip; (void)bp; (void)n; return 0; } +static msg_t GWinStreamPut(void *ip, uint8_t b) { gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } +static msg_t GWinStreamGet(void *ip) {(void)ip; return RDY_OK; } +static msg_t GWinStreamPutTimed(void *ip, uint8_t b, systime_t time) { (void)time; gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } +static msg_t GWinStreamGetTimed(void *ip, systime_t timeout) { (void)ip; (void)timeout; return RDY_OK; } +static size_t GWinStreamWriteTimed(void *ip, const uint8_t *bp, size_t n, systime_t time) { (void)time; gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } +static size_t GWinStreamReadTimed(void *ip, uint8_t *bp, size_t n, systime_t time) { (void)ip; (void)bp; (void)n; (void)time; return 0; } + +struct GConsoleWindowVMT_t { + _base_asynchronous_channel_methods +}; + +static const struct GConsoleWindowVMT_t GWindowConsoleVMT = { + GWinStreamWrite, + GWinStreamRead, + GWinStreamPut, + GWinStreamGet, + GWinStreamPutTimed, + GWinStreamGetTimed, + GWinStreamWriteTimed, + GWinStreamReadTimed +}; + +GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) { + if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject)))) + return 0; + gc->gwin.type = GW_CONSOLE; + gwinSetFont(&gc->gwin, font); + gc->stream.vmt = &GWindowConsoleVMT; + gc->cx = 0; + gc->cy = 0; + return (GHandle)gc; +} + +BaseSequentialStream *gwinGetConsoleStream(GHandle gh) { + if (gh->type != GW_CONSOLE) + return 0; + return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream); +} + +void gwinPutChar(GHandle gh, char c) { + uint8_t width; + #define gcw ((GConsoleObject *)gh) + + if (gh->type != GW_CONSOLE || !gh->font) return; + + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + + if (c == '\n') { + gcw->cx = 0; + gcw->cy += gcw->fy; + // We use lazy scrolling here and only scroll when the next char arrives + } else if (c == '\r') { + // gcw->cx = 0; + } else { + width = gdispGetCharWidth(c, gh->font) + gcw->fp; + if (gcw->cx + width >= gh->width) { + gcw->cx = 0; + gcw->cy += gcw->fy; + } + + if (gcw->cy + gcw->fy > gh->height) { +#if GDISP_NEED_SCROLL + /* scroll the console */ + gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor); + /* reset the cursor to the start of the last line */ + gcw->cx = 0; + gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy; +#else + /* clear the console */ + gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); + /* reset the cursor to the top of the window */ + gcw->cx = 0; + gcw->cy = 0; +#endif + } + +#if GWIN_CONSOLE_USE_CLEAR_LINES + /* clear to the end of the line */ + if (gcw->cx == 0) + gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor); +#endif +#if GWIN_CONSOLE_USE_FILLED_CHARS + gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); +#else + gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); +#endif + + /* update cursor */ + gcw->cx += width; + } + #undef gcw +} + +void gwinPutString(GHandle gh, const char *str) { + while(*str) + gwinPutChar(gh, *str++); +} + +void gwinPutCharArray(GHandle gh, const char *str, size_t n) { + while(n--) + gwinPutChar(gh, *str++); +} + +#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */ +/** @} */ + diff --git a/src/gwin/graph.c b/src/gwin/graph.c new file mode 100644 index 00000000..a9d20c4b --- /dev/null +++ b/src/gwin/graph.c @@ -0,0 +1,362 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file src/gwin/graph.c + * @brief GWIN sub-system button code. + * + * @defgroup Graph Graph + * @ingroup GWIN + * + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gfx.h" + +#if (GFX_USE_GWIN && GWIN_NEED_GRAPH) || defined(__DOXYGEN__) + +#include "gwin/internal.h" + +#define GGRAPH_FLG_CONNECTPOINTS (GWIN_FIRST_CONTROL_FLAG<<0) +#define GGRAPH_ARROW_SIZE 5 + +static const GGraphStyle GGraphDefaultStyle = { + { GGRAPH_POINT_DOT, 0, White }, // point + { GGRAPH_LINE_DOT, 2, Gray }, // line + { GGRAPH_LINE_SOLID, 0, White }, // x axis + { GGRAPH_LINE_SOLID, 0, White }, // y axis + { GGRAPH_LINE_NONE, 0, White, 0 }, // x grid + { GGRAPH_LINE_NONE, 0, White, 0 }, // y grid + GWIN_GRAPH_STYLE_XAXIS_ARROWS|GWIN_GRAPH_STYLE_YAXIS_ARROWS // flags +}; + +static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointStyle *style) { + if (style->type == GGRAPH_POINT_NONE) + return; + + // Convert to device space. Note the y-axis is inverted. + x += gg->gwin.x + gg->xorigin; + y = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y; + + if (style->size <= 1) { + gdispDrawPixel(x, y, style->color); + return; + } + + switch(style->type) { + case GGRAPH_POINT_SQUARE: + gdispDrawBox(x-style->size, y-style->size, 2*style->size, 2*style->size, style->color); + break; +#if GDISP_NEED_CIRCLE + case GGRAPH_POINT_CIRCLE: + gdispDrawCircle(x, y, style->size, style->color); + break; +#endif + case GGRAPH_POINT_DOT: + default: + gdispDrawPixel(x, y, style->color); + break; + } +} + +static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t y1, const GGraphLineStyle *style) { + coord_t dy, dx; + coord_t addx, addy; + coord_t P, diff, i; + coord_t run_on, run_off, run; + + if (style->type == GGRAPH_LINE_NONE) + return; + + // Convert to device space. Note the y-axis is inverted. + x0 += gg->gwin.x + gg->xorigin; + y0 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y0; + x1 += gg->gwin.x + gg->xorigin; + y1 = gg->gwin.y + gg->gwin.height - 1 - gg->yorigin - y1; + + if (style->size <= 0) { + // Use the driver to draw a solid line + gdispDrawLine(x0, y0, x1, y1, style->color); + return; + } + + switch (style->type) { + case GGRAPH_LINE_DOT: + run_on = 1; + run_off = -style->size; + break; + + case GGRAPH_LINE_DASH: + run_on = style->size; + run_off = -style->size; + break; + + case GGRAPH_LINE_SOLID: + default: + // Use the driver to draw a solid line + gdispDrawLine(x0, y0, x1, y1, style->color); + return; + } + + // Use Bresenham's algorithm modified to draw a stylized line + run = 0; + if (x1 >= x0) { + dx = x1 - x0; + addx = 1; + } else { + dx = x0 - x1; + addx = -1; + } + if (y1 >= y0) { + dy = y1 - y0; + addy = 1; + } else { + dy = y0 - y1; + addy = -1; + } + + if (dx >= dy) { + dy *= 2; + P = dy - dx; + diff = P - dx; + + for(i=0; i<=dx; ++i) { + if (run++ >= 0) { + if (run >= run_on) + run = run_off; + gdispDrawPixel(x0, y0, style->color); + } + if (P < 0) { + P += dy; + x0 += addx; + } else { + P += diff; + x0 += addx; + y0 += addy; + } + } + } else { + dx *= 2; + P = dx - dy; + diff = P - dy; + + for(i=0; i<=dy; ++i) { + if (run++ >= 0) { + if (run >= run_on) + run = run_off; + gdispDrawPixel(x0, y0, style->color); + } + if (P < 0) { + P += dx; + y0 += addy; + } else { + P += diff; + x0 += addx; + y0 += addy; + } + } + } +} + +GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) { + if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject)))) + return 0; + gg->gwin.type = GW_GRAPH; + gg->xorigin = gg->yorigin = 0; + gg->lastx = gg->lasty = 0; + gwinGraphSetStyle(&gg->gwin, &GGraphDefaultStyle); + return (GHandle)gg; +} + +void gwinGraphSetStyle(GHandle gh, const GGraphStyle *pstyle) { + #define gg ((GGraphObject *)gh) + + if (gh->type != GW_GRAPH) + return; + + gg->style.point.type = pstyle->point.type; + gg->style.point.size = pstyle->point.size; + gg->style.point.color = pstyle->point.color; + gg->style.line.type = pstyle->line.type; + gg->style.line.size = pstyle->line.size; + gg->style.line.color = pstyle->line.color; + gg->style.xaxis.type = pstyle->xaxis.type; + gg->style.xaxis.size = pstyle->xaxis.size; + gg->style.xaxis.color = pstyle->xaxis.color; + gg->style.yaxis.type = pstyle->yaxis.type; + gg->style.yaxis.size = pstyle->yaxis.size; + gg->style.yaxis.color = pstyle->yaxis.color; + gg->style.xgrid.type = pstyle->xgrid.type; + gg->style.xgrid.size = pstyle->xgrid.size; + gg->style.xgrid.color = pstyle->xgrid.color; + gg->style.xgrid.spacing = pstyle->xgrid.spacing; + gg->style.ygrid.type = pstyle->ygrid.type; + gg->style.ygrid.size = pstyle->ygrid.size; + gg->style.ygrid.color = pstyle->ygrid.color; + gg->style.ygrid.spacing = pstyle->ygrid.spacing; + gg->style.flags = pstyle->flags; + + #undef gg +} + +void gwinGraphSetOrigin(GHandle gh, coord_t x, coord_t y) { + #define gg ((GGraphObject *)gh) + + if (gh->type != GW_GRAPH) + return; + + gg->xorigin = x; + gg->yorigin = y; + + #undef gg +} + +void gwinGraphDrawAxis(GHandle gh) { + #define gg ((GGraphObject *)gh) + coord_t i, xmin, ymin, xmax, ymax; + + if (gh->type != GW_GRAPH) + return; + + xmin = -gg->xorigin; + xmax = gh->width-gg->xorigin-1; + ymin = -gg->yorigin; + ymax = gh->height-gg->yorigin-1; + + // x grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle + if (gg->style.xgrid.type != GGRAPH_LINE_NONE && gg->style.xgrid.spacing >= 2) { + for(i = gg->style.xgrid.spacing; i <= xmax; i += gg->style.xgrid.spacing) + lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid); + for(i = -gg->style.xgrid.spacing; i >= xmin; i -= gg->style.xgrid.spacing) + lineto(gg, i, ymin, i, ymax, (GGraphLineStyle *)&gg->style.xgrid); + } + + // y grid - this code assumes that the GGraphGridStyle is a superset of GGraphListStyle + if (gg->style.ygrid.type != GGRAPH_LINE_NONE && gg->style.ygrid.spacing >= 2) { + for(i = gg->style.ygrid.spacing; i <= ymax; i += gg->style.ygrid.spacing) + lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid); + for(i = -gg->style.ygrid.spacing; i >= ymin; i -= gg->style.ygrid.spacing) + lineto(gg, xmin, i, xmax, i, (GGraphLineStyle *)&gg->style.ygrid); + } + + // x axis + lineto(gg, xmin, 0, xmax, 0, &gg->style.xaxis); + if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_NEGATIVE_ARROWS)) { + if (xmin > 0 || xmin < -(GGRAPH_ARROW_SIZE+1)) { + lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis); + lineto(gg, xmin, 0, xmin+GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis); + } + } + if ((gg->style.flags & GWIN_GRAPH_STYLE_XAXIS_POSITIVE_ARROWS)) { + if (xmax < 0 || xmax > (GGRAPH_ARROW_SIZE+1)) { + lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, GGRAPH_ARROW_SIZE, &gg->style.xaxis); + lineto(gg, xmax, 0, xmax-GGRAPH_ARROW_SIZE, -GGRAPH_ARROW_SIZE, &gg->style.xaxis); + } + } + + // y axis + lineto(gg, 0, ymin, 0, ymax, &gg->style.yaxis); + if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_NEGATIVE_ARROWS)) { + if (ymin > 0 || ymin < -(GGRAPH_ARROW_SIZE+1)) { + lineto(gg, 0, ymin, GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis); + lineto(gg, 0, ymin, -GGRAPH_ARROW_SIZE, ymin+GGRAPH_ARROW_SIZE, &gg->style.yaxis); + } + } + if ((gg->style.flags & GWIN_GRAPH_STYLE_YAXIS_POSITIVE_ARROWS)) { + if (ymax < 0 || ymax > (GGRAPH_ARROW_SIZE+1)) { + lineto(gg, 0, ymax, GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis); + lineto(gg, 0, ymax, -GGRAPH_ARROW_SIZE, ymax-GGRAPH_ARROW_SIZE, &gg->style.yaxis); + } + } + + #undef gg +} + +void gwinGraphStartSet(GHandle gh) { + if (gh->type != GW_GRAPH) + return; + + gh->flags &= ~GGRAPH_FLG_CONNECTPOINTS; +} + +void gwinGraphDrawPoint(GHandle gh, coord_t x, coord_t y) { + #define gg ((GGraphObject *)gh) + + if (gh->type != GW_GRAPH) + return; + + if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) { + // Draw the line + lineto(gg, gg->lastx, gg->lasty, x, y, &gg->style.line); + + // Redraw the previous point because the line may have overwritten it + pointto(gg, gg->lastx, gg->lasty, &gg->style.point); + + } else + gh->flags |= GGRAPH_FLG_CONNECTPOINTS; + + // Save this point for next time. + gg->lastx = x; + gg->lasty = y; + + // Draw this point. + pointto(gg, x, y, &gg->style.point); + + #undef gg +} + +void gwinGraphDrawPoints(GHandle gh, const GGraphPoint *points, unsigned count) { + #define gg ((GGraphObject *)gh) + unsigned i; + const GGraphPoint *p; + + if (gh->type != GW_GRAPH) + return; + + // Draw the connecting lines + for(p = points, i = 0; i < count; p++, i++) { + if ((gh->flags & GGRAPH_FLG_CONNECTPOINTS)) { + // Draw the line + lineto(gg, gg->lastx, gg->lasty, p->x, p->y, &gg->style.line); + + // Redraw the previous point because the line may have overwritten it + if (i == 0) + pointto(gg, gg->lastx, gg->lasty, &gg->style.point); + + } else + gh->flags |= GGRAPH_FLG_CONNECTPOINTS; + + // Save this point for next time. + gg->lastx = p->x; + gg->lasty = p->y; + } + + + // Draw the points. + for(p = points, i = 0; i < count; p++, i++) + pointto(gg, p->x, p->y, &gg->style.point); + + #undef gg +} + +#endif /* GFX_USE_GWIN && GWIN_NEED_GRAPH */ +/** @} */ + diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c new file mode 100644 index 00000000..4eef79ad --- /dev/null +++ b/src/gwin/gwin.c @@ -0,0 +1,544 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file src/gwin/gwin.c + * @brief GWIN sub-system code. + * + * @defgroup Window Window + * @ingroup GWIN + * + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gfx.h" + +#if GFX_USE_GWIN || defined(__DOXYGEN__) + +#include "gwin/internal.h" + +// Internal routine for use by GWIN components only +// Initialise a window creating it dynamicly if required. +GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) { + coord_t w, h; + + // Check the window size against the screen size + w = gdispGetWidth(); + h = gdispGetHeight(); + if (x < 0) { width += x; x = 0; } + if (y < 0) { height += y; y = 0; } + if (x >= w || y >= h) return 0; + if (x+width > w) width = w - x; + if (y+height > h) height = h - y; + + // Allocate the structure if necessary + if (!gw) { + if (!(gw = (GWindowObject *)chHeapAlloc(NULL, size))) + return 0; + gw->flags = GWIN_FLG_DYNAMIC; + } else + gw->flags = 0; + + // Initialise all basic fields (except the type) + gw->x = x; + gw->y = y; + gw->width = width; + gw->height = height; + gw->color = White; + gw->bgcolor = Black; +#if GDISP_NEED_TEXT + gw->font = 0; +#endif + return (GHandle)gw; +} + +/** + * @brief Create a basic window. + * @return NULL if there is no resultant drawing area, otherwise a window handle. + * + * @param[in] gw The window structure to initialise. If this is NULL the structure is dynamically allocated. + * @param[in] x,y The screen co-ordinates for the bottom left corner of the window + * @param[in] width The width of the window + * @param[in] height The height of the window + * @note The default drawing color gets set to White and the background drawing color to Black. + * @note No default font is set so make sure to set one before drawing any text. + * @note The dimensions and position may be changed to fit on the real screen. + * @note The window is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color) + * + * @api + */ +GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) { + if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject)))) + return 0; + gw->type = GW_WINDOW; + return (GHandle)gw; +} + +/** + * @brief Destroy a window (of any type). Releases any dynamicly allocated memory. + * + * @param[in] gh The window handle + * + * @api + */ +void gwinDestroyWindow(GHandle gh) { + // Clean up any type specific dynamic memory allocations + switch(gh->type) { +#if GWIN_NEED_BUTTON + case GW_BUTTON: + if ((gh->flags & GBTN_FLG_ALLOCTXT)) { + gh->flags &= ~GBTN_FLG_ALLOCTXT; // To be sure, to be sure + chHeapFree((void *)((GButtonObject *)gh)->txt); + } + break; +#endif + default: + break; + } + + // Clean up the structure + if (gh->flags & GWIN_FLG_DYNAMIC) { + gh->flags = 0; // To be sure, to be sure + chHeapFree((void *)gh); + } +} + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Set the current font for this window. + * + * @param[in] gh The window handle + * @param[in] font The font to use for text functions + * + * @api + */ +void gwinSetFont(GHandle gh, font_t font) { + gh->font = font; +#if GWIN_NEED_CONSOLE + if (font && gh->type == GW_CONSOLE) { + ((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight); + ((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding); + } +#endif +} +#endif + +/** + * @brief Clear the window + * @note Uses the current background color to clear the window + * + * @param[in] gh The window handle + * + * @api + */ +void gwinClear(GHandle gh) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); + + #if GWIN_NEED_CONSOLE + if (gh->type == GW_CONSOLE) { + ((GConsoleObject *)gh)->cx = 0; + ((GConsoleObject *)gh)->cy = 0; + } + #endif +} + +/** + * @brief Set a pixel in the window + * @note Uses the current foreground color to set the pixel + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The coordinates of the pixel + * + * @api + */ +void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawPixel(gh->x+x, gh->y+y, gh->color); +} + +/** + * @brief Draw a line in the window + * @note Uses the current foreground color to draw the line + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x0,y0 The start position + * @param[in] x1,y1 The end position + * + * @api + */ +void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawLine(gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color); +} + +/** + * @brief Draw a box in the window + * @note Uses the current foreground color to draw the box + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The start position + * @param[in] cx,cy The size of the box (outside dimensions) + * + * @api + */ +void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawBox(gh->x+x, gh->y+y, cx, cy, gh->color); +} + +/** + * @brief Fill an rectangular area in the window + * @note Uses the current foreground color to fill the box + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The start position + * @param[in] cx,cy The size of the box (outside dimensions) + * + * @api + */ +void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillArea(gh->x+x, gh->y+y, cx, cy, gh->color); +} + +/** + * @brief Fill an area in the window using the supplied bitmap. + * @details The bitmap is in the pixel format specified by the low level driver + * @note If GDISP_NEED_ASYNC is defined then the buffer must be static + * or at least retained until this call has finished the blit. You can + * tell when all graphics drawing is finished by @p gdispIsBusy() going FALSE. + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x, y The start filled area + * @param[in] cx, cy The width and height to be filled + * @param[in] srcx, srcy The bitmap position to start the fill from + * @param[in] srccx The width of a line in the bitmap. + * @param[in] buffer The pixels to use to fill the area. + * + * @api + */ +void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispBlitAreaEx(gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer); +} + +#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__) +/** + * @brief Draw a circle in the window. + * @note Uses the current foreground color to draw the circle + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x, y The center of the circle + * @param[in] radius The radius of the circle + * + * @api + */ +void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawCircle(gh->x+x, gh->y+y, radius, gh->color); +} +#endif + +#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__) +/** + * @brief Draw a filled circle in the window. + * @note Uses the current foreground color to draw the filled circle + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x, y The center of the circle + * @param[in] radius The radius of the circle + * + * @api + */ +void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillCircle(gh->x+x, gh->y+y, radius, gh->color); +} +#endif + +#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__) +/** + * @brief Draw an ellipse. + * @note Uses the current foreground color to draw the ellipse + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The center of the ellipse + * @param[in] a,b The dimensions of the ellipse + * + * @api + */ +void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawEllipse(gh->x+x, gh->y+y, a, b, gh->color); +} +#endif + +#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__) +/** + * @brief Draw an filled ellipse. + * @note Uses the current foreground color to draw the filled ellipse + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The center of the ellipse + * @param[in] a,b The dimensions of the ellipse + * + * @api + */ +void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillEllipse(gh->x+x, gh->y+y, a, b, gh->color); +} +#endif + +#if GDISP_NEED_ARC || defined(__DOXYGEN__) +/* + * @brief Draw an arc in the window. + * @note Uses the current foreground color to draw the arc + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The center point + * @param[in] radius The radius of the arc + * @param[in] start The start angle (0 to 360) + * @param[in] end The end angle (0 to 360) + * + * @api + */ +void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); +} +#endif + +#if GDISP_NEED_ARC || defined(__DOXYGEN__) +/* + * @brief Draw a filled arc in the window. + * @note Uses the current foreground color to draw the filled arc + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The center point + * @param[in] radius The radius of the arc + * @param[in] start The start angle (0 to 360) + * @param[in] end The end angle (0 to 360) + * + * @api + */ +void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); +} +#endif + +#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__) +/** + * @brief Get the color of a pixel in the window. + * @return The color of the pixel. + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position in the window + * + * @api + */ +color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + return gdispGetPixelColor(gh->x+x, gh->y+y); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text character at the specified position in the window. + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text + * @param[in] c The character to draw + * + * @api + */ +void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawChar(gh->x+x, gh->y+y, c, gh->font, gh->color); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text character with a filled background at the specified position in the window. + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character and fills the background using the background drawing color + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text + * @param[in] c The character to draw + * + * @api + */ +void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillChar(gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text string in the window + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text + * @param[in] str The string to draw + * + * @api + */ +void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawString(gh->x+x, gh->y+y, str, gh->font, gh->color); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text string with a filled background in the window + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character and fills the background using the background drawing color + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text + * @param[in] str The string to draw + * + * @api + */ +void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillString(gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text string verticly centered within the specified box. + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character. + * @note The specified box does not need to align with the window box + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text (need to define top-right or base-line - check code) + * @param[in] cx,cy The width and height of the box + * @param[in] str The string to draw + * @param[in] justify Justify the text left, center or right within the box + * + * @api + */ +void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispDrawStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify); +} +#endif + +#if GDISP_NEED_TEXT || defined(__DOXYGEN__) +/** + * @brief Draw a text string verticly centered within the specified filled box. + * @pre The font must have been set. + * @note Uses the current foreground color to draw the character and fills the background using the background drawing color + * @note The entire box is filled. Note this box does not need to align with the window box + * @note May leave GDISP clipping to this window's dimensions + * + * @param[in] gh The window handle + * @param[in] x,y The position for the text (need to define top-right or base-line - check code) + * @param[in] cx,cy The width and height of the box + * @param[in] str The string to draw + * @param[in] justify Justify the text left, center or right within the box + * + * @api + */ +void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { + if (!gh->font) return; + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gdispFillStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify); +} +#endif + +#endif /* GFX_USE_GWIN */ +/** @} */ + diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk new file mode 100644 index 00000000..3c560f43 --- /dev/null +++ b/src/gwin/gwin.mk @@ -0,0 +1,5 @@ +GFXSRC += $(GFXLIB)/src/gwin/gwin.c \ + $(GFXLIB)/src/gwin/console.c \ + $(GFXLIB)/src/gwin/button.c \ + $(GFXLIB)/src/gwin/graph.c + -- cgit v1.2.3