GDISP fixes and new routines. Many GWIN changes.

GDISP:
Fix gdisp???Arc to use (possibly) hardware accelerated routines.
Fix Arc orientation so 0 degrees is on x axis and 90 degrees points to
the top of screen (instead of the bottom).
Add rounded box routines (if ARC support is turned on).
Add a gdispDrawStringBox to match the gdispFillStringBox routine.
Repair prototypes in wrong place in gdisp.h

GWIN:
Extract the concept of a Window Handle to allow many new features.
Allow dynamic creation of window objects as well as static
initialisation.
Seperate the console code into a console specific window type.
Add buttons as a specific window type. The drawing code is complete, the
input (touch or mouse) is still to be implemented.
ugfx_release_2.6
Andrew Hannam 2012-10-30 18:18:29 +10:00
parent a55da05d2e
commit d3b4c499ab
7 changed files with 1268 additions and 780 deletions

View File

@ -166,6 +166,9 @@ extern "C" {
#endif
#if GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC
/* These routines can be hardware accelerated
* - Do not add a routine here unless it has also been added to the hardware acceleration layer
*/
/* Base Functions */
bool_t gdispInit(void);
@ -253,8 +256,9 @@ extern "C" {
#endif
/* Now obsolete functions */
#define gdispBlitArea(x, y, cx, cy, buffer) gdispBlitAreaEx(x, y, cx, cy, 0, 0, cx, buffer)
/* These routines are not hardware accelerated
* - Do not add a hardware accelerated routines here.
*/
/* Extra drawing functions */
void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
@ -263,17 +267,31 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
#if GDISP_NEED_TEXT
void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color);
void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor);
void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify);
void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgColor, justify_t justify);
coord_t gdispGetFontMetric(font_t font, fontmetric_t metric);
coord_t gdispGetCharWidth(char c, font_t font);
coord_t gdispGetStringWidth(const char* str, font_t font);
#endif
/* Extra Arc Functions */
#if GDISP_NEED_ARC
void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color);
void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color);
#endif
/* Support routine for packed pixel formats */
#ifndef gdispPackPixels
void gdispPackPixels(const pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color);
#endif
/* Macro definitions
*
*/
/* Now obsolete functions */
#define gdispBlitArea(x, y, cx, cy, buffer) gdispBlitAreaEx(x, y, cx, cy, 0, 0, cx, buffer)
/* Macro definitions for common gets and sets */
#define gdispSetPowerMode(powerMode) gdispControl(GDISP_CONTROL_POWER, (void *)(unsigned)(powerMode))
#define gdispSetOrientation(newOrientation) gdispControl(GDISP_CONTROL_ORIENTATION, (void *)(unsigned)(newOrientation))

View File

@ -291,7 +291,7 @@
#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCS
#include <maths.h>
#include <math.h>
/*
* @brief Internal helper function for gdispDrawArc()
@ -307,7 +307,7 @@
* @notapi
*/
static void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
if (start >= 0 && start <= 180) {
if (/*start >= 0 && */start <= 180) {
float x_maxI = x + radius*cos(start*M_PI/180);
float x_minI;
@ -322,13 +322,13 @@
do {
if(x-a <= x_maxI && x-a >= x_minI)
GDISP_LLD(drawpixel)(x-a, y+b, color);
GDISP_LLD(drawpixel)(x-a, y-b, color);
if(x+a <= x_maxI && x+a >= x_minI)
GDISP_LLD(drawpixel)(x+a, y+b, color);
GDISP_LLD(drawpixel)(x+a, y-b, color);
if(x-b <= x_maxI && x-b >= x_minI)
GDISP_LLD(drawpixel)(x-b, y+a, color);
GDISP_LLD(drawpixel)(x-b, y-a, color);
if(x+b <= x_maxI && x+b >= x_minI)
GDISP_LLD(drawpixel)(x+b, y+a, color);
GDISP_LLD(drawpixel)(x+b, y-a, color);
if (P < 0) {
P = P + 3 + 2*a;
@ -356,13 +356,13 @@
do {
if(x-a <= x_maxII && x-a >= x_minII)
GDISP_LLD(drawpixel)(x-a, y-b, color);
GDISP_LLD(drawpixel)(x-a, y+b, color);
if(x+a <= x_maxII && x+a >= x_minII)
GDISP_LLD(drawpixel)(x+a, y-b, color);
GDISP_LLD(drawpixel)(x+a, y+b, color);
if(x-b <= x_maxII && x-b >= x_minII)
GDISP_LLD(drawpixel)(x-b, y-a, color);
GDISP_LLD(drawpixel)(x-b, y+a, color);
if(x+b <= x_maxII && x+b >= x_minII)
GDISP_LLD(drawpixel)(x+b, y-a, color);
GDISP_LLD(drawpixel)(x+b, y+a, color);
if (P < 0) {
P = P + 3 + 2*a;
@ -387,14 +387,96 @@
#endif
#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCFILLS
/*
* @brief Internal helper function for gdispDrawArc()
*
* @note DO NOT USE DIRECTLY!
*
* @param[in] x, y The middle point of the arc
* @param[in] start The start angle of the arc
* @param[in] end The end angle of the arc
* @param[in] radius The radius of the arc
* @param[in] color The color in which the arc will be drawn
*
* @notapi
*/
static void _fill_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
if (/*start >= 0 && */start <= 180) {
float x_maxI = x + radius*cos(start*M_PI/180);
float x_minI;
if (end > 180)
x_minI = x - radius;
else
x_minI = x + radius*cos(end*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxI && x-a >= x_minI)
GDISP_LLD(drawline)(x, y, x-a, y-b, color);
if(x+a <= x_maxI && x+a >= x_minI)
GDISP_LLD(drawline)(x, y, x+a, y-b, color);
if(x-b <= x_maxI && x-b >= x_minI)
GDISP_LLD(drawline)(x, y, x-b, y-a, color);
if(x+b <= x_maxI && x+b >= x_minI)
GDISP_LLD(drawline)(x, y, x+b, y-a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while(a <= b);
}
if (end > 180 && end <= 360) {
float x_maxII = x+radius*cos(end*M_PI/180);
float x_minII;
if(start <= 180)
x_minII = x - radius;
else
x_minII = x+radius*cos(start*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxII && x-a >= x_minII)
GDISP_LLD(drawline)(x, y, x-a, y+b, color);
if(x+a <= x_maxII && x+a >= x_minII)
GDISP_LLD(drawline)(x, y, x+a, y+b, color);
if(x-b <= x_maxII && x-b >= x_minII)
GDISP_LLD(drawline)(x, y, x-b, y+a, color);
if(x+b <= x_maxII && x+b >= x_minII)
GDISP_LLD(drawline)(x, y, x+b, y+a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while (a <= b);
}
}
void GDISP_LLD(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) {
(void)x;
(void)y;
(void)radius;
(void)startangle;
(void)endangle;
(void)color;
#warning "GDISP: FillArc Emulation Not Implemented Yet"
if(endangle < startangle) {
_fill_arc(x, y, startangle, 360, radius, color);
_fill_arc(x, y, 0, endangle, radius, color);
} else {
_fill_arc(x, y, startangle, endangle, radius, color);
}
}
#endif

View File

@ -88,4 +88,3 @@ struct font {
#endif /* _GDISP_FONTS_H */
/** @} */

View File

@ -45,52 +45,119 @@
* @name GWIN more complex functionality to be compiled
* @{
*/
/**
* @brief Should console functions be included.
* @details Defaults to TRUE
*/
#ifndef GWIN_NEED_CONSOLE
#define GWIN_NEED_CONSOLE TRUE
#endif
/**
* @brief Should button functions be included.
* @details Defaults to FALSE for now as implementation is not complete
*/
#ifndef GWIN_NEED_BUTTON
#define GWIN_NEED_BUTTON FALSE
#endif
/** @} */
/*===========================================================================*/
/* Low Level Driver details and error checks. */
/*===========================================================================*/
#if !GFX_USE_GDISP
#if !defined(GFX_USE_GDISP)
#error "GWIN: GFX_USE_GDISP must also be defined"
#endif
#include "gdisp.h"
#if !GDISP_NEED_CLIP
#warning "GWIN: Drawing can occur outside the defined window as GDISP_NEED_CLIP is FALSE"
#endif
#if GWIN_NEED_CONSOLE && !GDISP_NEED_TEXT
#error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_CONSOLE is defined."
#endif
#if GWIN_NEED_BUTTON && !GDISP_NEED_TEXT
#error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_BUTTON is defined."
#endif
#if GWIN_NEED_BUTTON
#warning "GWIN: Button support is not complete yet"
#endif
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @extends BaseAsynchronousChannelVMT
*
* @brief @p GWindow virtual methods table.
*/
struct GWindowVMT {
_base_asynchronous_channel_methods
};
typedef enum GWindowType_e {
GW_WINDOW, GW_CONSOLE, GW_BUTTON
} GWindowType;
struct GWindowText {
const struct GWindowVMT *vmt;
_base_asynchronous_channel_data
font_t font; // Current font
uint8_t fy; // Current font height
uint8_t fp; // Current font inter-character spacing
coord_t cx,cy; // Cursor position
};
typedef struct GWindow_t {
// A basic window
typedef struct GWindowObject_t {
GWindowType type; // What type of window is this
uint16_t flags; // Internal flags
coord_t x, y; // Screen relative position
coord_t width, height; // Dimensions of this window
color_t color, bgcolor; // Current drawing colors
#if GDISP_NEED_TEXT
struct GWindowText txt;
font_t font; // Current font
#endif
} GWindowObject, * GHandle;
#if GWIN_NEED_CONSOLE
// A console window. Supports wrapped text writing and a cursor.
typedef struct GConsoleObject_t {
GWindowObject gwin;
struct GConsoleWindowStream_t {
const struct GConsoleWindowVMT_t *vmt;
_base_asynchronous_channel_data
} stream;
coord_t cx,cy; // Cursor position
uint8_t fy; // Current font height
uint8_t fp; // Current font inter-character spacing
} GConsoleObject;
#endif
#if GWIN_NEED_BUTTON
typedef enum GButtonShape_e {
GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE
} GButtonShape;
typedef struct GButtonStyle_t {
GButtonShape shape;
color_t color_up_edge;
color_t color_up_fill;
color_t color_up_txt;
color_t color_dn_edge;
color_t color_dn_fill;
color_t color_dn_txt;
} GButtonStyle;
typedef enum GButtonType_e {
GBTN_NORMAL, GBTN_TOGGLE
} GButtonType;
typedef enum GButtonState_e {
GBTN_UP, GBTN_DOWN
} GButtonState;
// A button window
typedef struct GButtonObject_t {
GWindowObject gwin;
GButtonStyle style;
GButtonState state;
GButtonType type;
const char * txt;
void * callback; // To be fixed
void * inputsrc; // To be fixed
} GButtonObject;
#endif
coord_t x, y; // Screen relative position
coord_t width, height; // Dimensions of this window
color_t color, bgcolor; // Current drawing colors
} GWindow;
/*===========================================================================*/
/* External declarations. */
@ -101,70 +168,81 @@ extern "C" {
#endif
/* Base Functions */
bool_t gwinInit(GWindow *gw, coord_t x, coord_t y, coord_t width, coord_t height);
GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height);
void gwinDestroyWindow(GHandle gh);
/* Status Functions */
#define gwinGetScreenX(gw) ((gw)->x)
#define gwinGetScreenY(gw) ((gw)->y)
#define gwinGetWidth(gw) ((gw)->width)
#define gwinGetHeight(gw) ((gw)->height)
#define gwinGetScreenX(gh) ((gh)->x)
#define gwinGetScreenY(gh) ((gh)->y)
#define gwinGetWidth(gh) ((gh)->width)
#define gwinGetHeight(gh) ((gh)->height)
/* Set up for drawing */
#define gwinSetColor(gw, clr) (gw)->color = (clr)
#define gwinSetBgColor(gw, bgclr) (gw)->bgcolor = (bgclr)
#define gwinSetColor(gh, clr) (gh)->color = (clr)
#define gwinSetBgColor(gh, bgclr) (gh)->bgcolor = (bgclr)
/* Set up for text */
#if GDISP_NEED_TEXT
void gwinSetFont(GWindow *gw, font_t font);
#define gwinGetStream(gw) ((BaseSequentialStream *)gw)
void gwinSetFont(GHandle gh, font_t font);
#endif
/* Drawing Functions */
void gwinClear(GWindow *gw);
void gwinDrawPixel(GWindow *gw, coord_t x, coord_t y);
void gwinDrawLine(GWindow *gw, coord_t x0, coord_t y0, coord_t x1, coord_t y1);
void gwinDrawBox(GWindow *gw, coord_t x, coord_t y, coord_t cx, coord_t cy);
void gwinFillArea(GWindow *gw, coord_t x, coord_t y, coord_t cx, coord_t cy);
void gwinBlitArea(GWindow *gw, 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);
void gwinClear(GHandle gh);
void gwinDrawPixel(GHandle gh, coord_t x, coord_t y);
void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1);
void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy);
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);
/* Circle Functions */
#if GDISP_NEED_CIRCLE
void gwinDrawCircle(GWindow *gw, coord_t x, coord_t y, coord_t radius);
void gwinFillCircle(GWindow *gw, coord_t x, coord_t y, coord_t radius);
void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
#endif
/* Ellipse Functions */
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GWindow *gw, coord_t x, coord_t y, coord_t a, coord_t b);
void gwinFillEllipse(GWindow *gw, coord_t x, coord_t y, coord_t a, coord_t b);
void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b);
#endif
/* Arc Functions */
#if GDISP_NEED_ARC
void gwinDrawArc(GWindow *gw, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
void gwinFillArc(GWindow *gw, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
#endif
/* Read a pixel Function */
#if GDISP_NEED_PIXELREAD
color_t gwinGetPixelColor(GWindow *gw, coord_t x, coord_t y);
#endif
/* Scrolling Function - clears the area scrolled out */
#if GDISP_NEED_SCROLL
void gwinVerticalScroll(GWindow *gw, int lines);
color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y);
#endif
/* Extra Text Functions */
#if GDISP_NEED_TEXT
void gwinDrawChar(GWindow *gw, coord_t x, coord_t y, char c);
void gwinFillChar(GWindow *gw, coord_t x, coord_t y, char c);
void gwinDrawString(GWindow *gw, coord_t x, coord_t y, const char *str);
void gwinFillString(GWindow *gw, coord_t x, coord_t y, const char *str);
void gwinBoxString(GWindow *gw, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
void gwinPutChar(GWindow *gw, char c);
void gwinPutString(GWindow *gw, const char *str);
void gwinPutCharArray(GWindow *gw, const char *str, size_t n);
void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c);
void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c);
void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str);
void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str);
void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify);
#endif
#if GWIN_NEED_CONSOLE
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font);
BaseSequentialStream *gwinGetConsoleStream(GHandle gh);
void gwinPutChar(GHandle gh, char c);
void gwinPutString(GHandle gh, const char *str);
void gwinPutCharArray(GHandle gh, const char *str, size_t n);
#endif
#if GWIN_NEED_BUTTON
GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type);
void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style);
void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
void gwinButtonDraw(GHandle gh);
#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
//void gwinSetButtonCallback(GHandle gh, ????);
//void gwinSetButtonInput(GHandle gh, ????);
#endif
#ifdef __cplusplus
@ -175,4 +253,3 @@ void gwinPutCharArray(GWindow *gw, const char *str, size_t n);
#endif /* _GWIN_H */
/** @} */

View File

@ -9,6 +9,11 @@ current stable: 1.3
FIX: Nokia 6610 fix
FEATURE: New driver: Win32
FEATURE: implementation of gdispFillArc()
FIX: Hardware accelerate Arc routines
FIX: Fix axis orientation for Arc routines
FEATURE: new gdisp rounded box routines
FEATURE: new gdispDrawStringBox()
FEATURE: GWIN infrastructure
*** changes after 1.2 ***
@ -41,4 +46,3 @@ FEATURE: added SSD1963 DMA support
FEATURE: added touchpad interface for storing calibration values (#define TOUCHPAD_STORE_CALIBRATION)
CHANGE: replaced every GDISP_XXX macro with GDISP_XXX
CHANGE: removed last digit of version number

View File

@ -494,220 +494,124 @@
}
#endif
#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
/*
* @brief Draw an arc.
* @pre The GDISP must be in powerOn or powerSleep mode.
*
* @param[in] x0,y0 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)
* @param[in] color The color of the arc
*
* @api
*/
void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
chMtxLock(&gdispMutex);
GDISP_LLD(drawarc)(x, y, radius, start, end, color);
chMtxUnlock();
}
#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC
void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC);
p->drawarc.x = x;
p->drawarc.y = y;
p->drawarc.radius = radius;
p->drawarc.start = start;
p->drawarc.end = end;
p->drawarc.color = color;
chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
}
#endif
#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) || defined(__DOXYGEN__)
/*
* @brief Draw a filled arc.
* @pre The GDISP must be in powerOn or powerSleep mode.
* @note Not very efficient currently - does lots of overdrawing
*
* @param[in] x0,y0 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)
* @param[in] color The color of the arc
*
* @api
*/
void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
chMtxLock(&gdispMutex);
GDISP_LLD(fillarc)(x, y, radius, start, end, color);
chMtxUnlock();
}
#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC
void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC);
p->fillarc.x = x;
p->fillarc.y = y;
p->fillarc.radius = radius;
p->fillarc.start = start;
p->fillarc.end = end;
p->fillarc.color = color;
chMBPost(&gdispMailbox, (msg_t)p, TIME_INFINITE);
}
#endif
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
#include "math.h"
/*
* @brief Internal helper function for gdispDrawArc()
/**
* @brief Draw a rectangular box with rounded corners
* @pre The GDISP unit must be in powerOn or powerSleep mode.
*
* @note DO NOT USE DIRECTLY!
*
* @param[in] x, y The middle point of the arc
* @param[in] start The start angle of the arc
* @param[in] end The end angle of the arc
* @param[in] radius The radius of the arc
* @param[in] color The color in which the arc will be drawn
*
* @notapi
*/
void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
if(start > 0 && start <= 180) {
float x_maxI = x + radius*cos(start*M_PI/180);
float x_minI;
if (end > 180)
x_minI = x - radius;
else
x_minI = x + radius*cos(end*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxI && x-a >= x_minI)
gdispDrawPixel(x-a, y+b, color);
if(x+a <= x_maxI && x+a >= x_minI)
gdispDrawPixel(x+a, y+b, color);
if(x-b <= x_maxI && x-b >= x_minI)
gdispDrawPixel(x-b, y+a, color);
if(x+b <= x_maxI && x+b >= x_minI)
gdispDrawPixel(x+b, y+a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while(a <= b);
}
if (end > 180 && end <= 360) {
float x_maxII = x+radius*cos(end*M_PI/180);
float x_minII;
if(start <= 180)
x_minII = x - radius;
else
x_minII = x+radius*cos(start*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxII && x-a >= x_minII)
gdispDrawPixel(x-a, y-b, color);
if(x+a <= x_maxII && x+a >= x_minII)
gdispDrawPixel(x+a, y-b, color);
if(x-b <= x_maxII && x-b >= x_minII)
gdispDrawPixel(x-b, y-a, color);
if(x+b <= x_maxII && x+b >= x_minII)
gdispDrawPixel(x+b, y-a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while (a <= b);
}
}
/*
* @brief Draw an arc.
* @pre The GDISP must be in powerOn or powerSleep mode.
*
* @param[in] x0,y0 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)
* @param[in] color The color of the arc
* @param[in] x,y The start position
* @param[in] cx,cy The size of the box (outside dimensions)
* @param[in] radius The radius of the rounded corners
* @param[in] color The color to use
*
* @api
*/
void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
if(end < start) {
_draw_arc(x, y, start, 360, radius, color);
_draw_arc(x, y, 0, end, radius, color);
} else {
_draw_arc(x, y, start, end, radius, color);
void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
if (2*radius > cx || 2*radius > cy) {
gdispDrawBox(x, y, cx, cy, color);
return;
}
gdispDrawArc(x+radius, y+radius, radius, 90, 180, color);
gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color);
gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color);
gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color);
gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color);
gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color);
gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color);
}
#endif
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
/*
* @brief Internal helper function for gdispFillArc()
/**
* @brief Draw a filled rectangular box with rounded corners
* @pre The GDISP unit must be in powerOn or powerSleep mode.
*
* @note DO NOT USE DIRECTLY!
* @note Not very efficient currently - does lots of overdrawing
*
* @param[in] x, y The middle point of the arc
* @param[in] start The start angle of the arc
* @param[in] end The end angle of the arc
* @param[in] radius The radius of the arc
* @param[in] color The color in which the arc will be drawn
*
* @notapi
*/
void _fill_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) {
if(start > 0 && start <= 180) {
float x_maxI = x + radius*cos(start*M_PI/180);
float x_minI;
if (end > 180)
x_minI = x - radius;
else
x_minI = x + radius*cos(end*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxI && x-a >= x_minI)
gdispDrawLine(x, y, x-a, y+b, color);
if(x+a <= x_maxI && x+a >= x_minI)
gdispDrawLine(x, y, x+a, y+b, color);
if(x-b <= x_maxI && x-b >= x_minI)
gdispDrawLine(x, y, x-b, y+a, color);
if(x+b <= x_maxI && x+b >= x_minI)
gdispDrawLine(x, y, x+b, y+a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while(a <= b);
}
if (end > 180 && end <= 360) {
float x_maxII = x+radius*cos(end*M_PI/180);
float x_minII;
if(start <= 180)
x_minII = x - radius;
else
x_minII = x+radius*cos(start*M_PI/180);
int a = 0;
int b = radius;
int P = 1 - radius;
do {
if(x-a <= x_maxII && x-a >= x_minII)
gdispDrawLine(x, y, x-a, y-b, color);
if(x+a <= x_maxII && x+a >= x_minII)
gdispDrawLine(x, y, x+a, y-b, color);
if(x-b <= x_maxII && x-b >= x_minII)
gdispDrawLine(x, y, x-b, y-a, color);
if(x+b <= x_maxII && x+b >= x_minII)
gdispDrawLine(x, y, x+b, y-a, color);
if (P < 0) {
P = P + 3 + 2*a;
a = a + 1;
} else {
P = P + 5 + 2*(a - b);
a = a + 1;
b = b - 1;
}
} while (a <= b);
}
}
/*
* @brief Draw a filled arc.
* @pre The GDISP must be in powerOn or powerSleep mode.
* @note Not very efficient currently - does lots of overdrawing
*
* @param[in] x0,y0 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)
* @param[in] color The color of the arc
* @param[in] x,y The start position
* @param[in] cx,cy The size of the box (outside dimensions)
* @param[in] radius The radius of the rounded corners
* @param[in] color The color to use
*
* @api
*/
void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) {
if(end < start) {
_fill_arc(x, y, start, 360, radius, color);
_fill_arc(x, y, 0, end, radius, color);
} else {
_fill_arc(x, y, start, end, radius, color);
void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
coord_t radius2;
radius2 = radius*2;
if (radius2 > cx || radius2 > cy) {
gdispFillArea(x, y, cx, cy, color);
return;
}
gdispFillArc(x+radius, y+radius, radius, 90, 180, color);
gdispFillArea(x+radius+1, y, cx-radius2, radius, color);
gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color);
gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color);
gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color);
gdispFillArea(x, y+radius, cx, cy-radius2, color);
}
#endif
@ -877,10 +781,9 @@ void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t
* @brief Draw a rectangular box.
* @pre The GDISP unit must be in powerOn or powerSleep mode.
*
* @param[in] x0,y0 The start position
* @param[in] cx,cy The size of the box (outside dimensions)
* @param[in] color The color to use
* @param[in] filled Should the box should be filled
* @param[in] x,y The start position
* @param[in] cx,cy The size of the box (outside dimensions)
* @param[in] color The color to use
*
* @api
*/
@ -928,6 +831,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
char c;
int first;
if (!str) return;
first = 1;
p = font->charPadding * font->xscale;
while(*str) {
@ -969,6 +874,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
char c;
int first;
if (!str) return;
first = 1;
h = font->height * font->yscale;
p = font->charPadding * font->xscale;
@ -998,6 +905,137 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
/**
* @brief Draw a text string verticly centered within the specified box.
* @pre The GDISP unit must be in powerOn or powerSleep mode.
*
* @param[in] x,y The position for the text (need to define top-right or base-line - check code)
* @param[in] str The string to draw
* @param[in] color The color to use
* @param[in] justify Justify the text left, center or right within the box
*
* @api
*/
void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) {
/* No mutex required as we only call high level functions which have their own mutex */
coord_t w, h, p, ypos, xpos;
char c;
int first;
const char *rstr;
if (!str) str = "";
h = font->height * font->yscale;
p = font->charPadding * font->xscale;
/* Oops - font too large for the area */
if (h > cy) return;
/* See if we need to fill above the font */
ypos = (cy - h + 1)/2;
if (ypos > 0) {
y += ypos;
cy -= ypos;
}
/* See if we need to fill below the font */
ypos = cy - h;
if (ypos > 0)
cy -= ypos;
/* get the start of the printable string and the xpos */
switch(justify) {
case justifyCenter:
/* Get the length of the entire string */
w = gdispGetStringWidth(str, font);
if (w <= cx)
xpos = x + (cx - w)/2;
else {
/* Calculate how much of the string we need to get rid of */
ypos = (w - cx)/2;
xpos = 0;
first = 1;
while(*str) {
/* Get the next printable character */
c = *str++;
w = _getCharWidth(font, c) * font->xscale;
if (!w) continue;
/* Handle inter-character padding */
if (p) {
if (!first) {
xpos += p;
if (xpos > ypos) break;
} else
first = 0;
}
/* Print the character */
xpos += w;
if (xpos > ypos) break;
}
xpos = ypos - xpos + x;
}
break;
case justifyRight:
/* Find the end of the string */
for(rstr = str; *str; str++);
xpos = x+cx - 2;
first = 1;
for(str--; str >= rstr; str--) {
/* Get the next printable character */
c = *str;
w = _getCharWidth(font, c) * font->xscale;
if (!w) continue;
/* Handle inter-character padding */
if (p) {
if (!first) {
if (xpos - p < x) break;
xpos -= p;
} else
first = 0;
}
/* Print the character */
if (xpos - w < x) break;
xpos -= w;
}
str++;
break;
case justifyLeft:
/* Fall through */
default:
xpos = x+1;
break;
}
/* Print characters until we run out of room */
first = 1;
while(*str) {
/* Get the next printable character */
c = *str++;
w = _getCharWidth(font, c) * font->xscale;
if (!w) continue;
/* Handle inter-character padding */
if (p) {
if (!first) {
if (xpos + p > x+cx) break;
xpos += p;
} else
first = 0;
}
/* Print the character */
if (xpos + w > x+cx) break;
gdispDrawChar(xpos, y, c, font, color);
xpos += w;
}
}
#endif
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
/**
* @brief Draw a text string verticly centered within the specified box. The box background is filled with the specified background color.
* @pre The GDISP unit must be in powerOn or powerSleep mode.
* @note The entire box is filled
*
* @param[in] x,y The position for the text (need to define top-right or base-line - check code)
@ -1015,6 +1053,8 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
int first;
const char *rstr;
if (!str) str = "";
h = font->height * font->yscale;
p = font->charPadding * font->xscale;

1258
src/gwin.c

File diff suppressed because it is too large Load Diff