diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gfx_compilers.h | 1 | ||||
-rw-r--r-- | src/gmisc/gmisc.h | 2 | ||||
-rw-r--r-- | src/gos/gos_x_heap.c | 112 | ||||
-rw-r--r-- | src/gos/gos_x_threads.c | 7 | ||||
-rw-r--r-- | src/gos/gos_x_threads.h | 2 | ||||
-rw-r--r-- | src/gos/gos_x_threads_cortexm01.h | 57 | ||||
-rw-r--r-- | src/gos/gos_x_threads_cortexm347.h | 33 | ||||
-rw-r--r-- | src/gos/gos_x_threads_cortexm47fp.h | 37 | ||||
-rw-r--r-- | src/gtimer/gtimer.c | 2 | ||||
-rw-r--r-- | src/gwin/gwin.c | 14 | ||||
-rw-r--r-- | src/gwin/gwin.h | 34 |
11 files changed, 186 insertions, 115 deletions
diff --git a/src/gfx_compilers.h b/src/gfx_compilers.h index 2449c05e..46d6c8b1 100644 --- a/src/gfx_compilers.h +++ b/src/gfx_compilers.h @@ -625,6 +625,7 @@ #pragma diag_remark 767 // Turn off warning: conversion from pointer to smaller integer #pragma diag_remark 188 // Turn off warning: enumerated type mixed with another type #pragma diag_remark 68 // Turn off warning: integer conversion resulted in a change of sign + #pragma diag_remark 111 // Turn off warning: statement is unreachable #ifndef GFXINLINE // Get the Keil definition for inline #define GFXINLINE __inline #endif diff --git a/src/gmisc/gmisc.h b/src/gmisc/gmisc.h index f805345c..21178774 100644 --- a/src/gmisc/gmisc.h +++ b/src/gmisc/gmisc.h @@ -473,7 +473,7 @@ extern "C" { * @note This function works both with convex and concave polygons * * @param[in] pntarray The array of points that form the polygon - * @param[in] cnt The number of points in the point array @pntarray + * @param[in] cnt The number of points in the point array @p pntarray * @param[in] p The point to test * * @return @p TRUE if the point @p p is inside or on the edge of the polygon @p pntarray, @p FALSE otherwise. diff --git a/src/gos/gos_x_heap.c b/src/gos/gos_x_heap.c index 7e79d1c6..813d0199 100644 --- a/src/gos/gos_x_heap.c +++ b/src/gos/gos_x_heap.c @@ -34,7 +34,6 @@ // Slot structure - user memory follows typedef struct memslot { - struct memslot *next; // The next memslot size_t sz; // Includes the size of this memslot. } memslot; @@ -48,13 +47,10 @@ #define Ptr2Slot(p) ((memslot *)(p) - 1) #define Slot2Ptr(pslot) ((pslot)+1) - static memslot * firstSlot; - static memslot * lastSlot; static memslot * freeSlots; static char heap[GFX_OS_HEAP_SIZE]; void _gosHeapInit(void) { - lastSlot = 0; gfxAddHeapBlock(heap, GFX_OS_HEAP_SIZE); } @@ -62,18 +58,12 @@ if (sz < sizeof(memslot)+sizeof(freeslot)) return; - if (lastSlot) - lastSlot->next = (memslot *)ptr; - else - firstSlot = lastSlot = freeSlots = (memslot *)ptr; - - lastSlot->next = 0; - lastSlot->sz = sz; - NextFree(lastSlot) = 0; + ((memslot *)ptr)->sz = sz; + gfxFree(Slot2Ptr((memslot *)ptr)); } void *gfxAlloc(size_t sz) { - register memslot *prev, *p, *new; + register memslot *prev, *p, *pnew; if (!sz) return 0; sz = GetSlotSize(sz); @@ -81,23 +71,22 @@ // Loop till we have a block big enough if (p->sz < sz) continue; + // Can we save some memory by splitting this block? if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { - new = (memslot *)((char *)p + sz); - new->next = p->next; - p->next = new; - new->sz = p->sz - sz; + pnew = (memslot *)((char *)p + sz); + pnew->sz = p->sz - sz; p->sz = sz; - if (lastSlot == p) - lastSlot = new; - NextFree(new) = NextFree(p); - NextFree(p) = new; + NextFree(pnew) = NextFree(p); + NextFree(p) = pnew; } + // Remove it from the free list if (prev) NextFree(prev) = NextFree(p); else freeSlots = NextFree(p); + // Return the result found return Slot2Ptr(p); } @@ -106,7 +95,7 @@ } void *gfxRealloc(void *ptr, size_t oldsz, size_t sz) { - register memslot *prev, *p, *new; + register memslot *prev, *p, *pfree; (void) oldsz; if (!ptr) @@ -120,19 +109,14 @@ sz = GetSlotSize(sz); // If the next slot is free (and contiguous) merge it into this one - if ((char *)p + p->sz == (char *)p->next) { - for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { - if (new == p->next) { - p->next = new->next; - p->sz += new->sz; - if (prev) - NextFree(prev) = NextFree(new); - else - freeSlots = NextFree(new); - if (lastSlot == new) - lastSlot = p; - break; - } + for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { + if (pfree == (memslot *)((char *)p + p->sz)) { + p->sz += pfree->sz; + if (prev) + NextFree(prev) = NextFree(pfree); + else + freeSlots = NextFree(pfree); + break; } } @@ -140,50 +124,54 @@ if (sz < p->sz) { // Can we save some memory by splitting this block? if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { - new = (memslot *)((char *)p + sz); - new->next = p->next; - p->next = new; - new->sz = p->sz - sz; + pfree = (memslot *)((char *)p + sz); + pfree->sz = p->sz - sz; p->sz = sz; - if (lastSlot == p) - lastSlot = new; - NextFree(new) = freeSlots; - freeSlots = new; + NextFree(pfree) = freeSlots; + freeSlots = pfree; } return Slot2Ptr(p); } // We need to do this the hard way - new = gfxAlloc(sz); - if (new) + pfree = gfxAlloc(sz); + if (pfree) return 0; - memcpy(new, ptr, p->sz - sizeof(memslot)); + memcpy(pfree, ptr, p->sz - sizeof(memslot)); gfxFree(ptr); - return new; + return pfree; } void gfxFree(void *ptr) { - register memslot *prev, *p, *new; + register memslot *prev, *p, *pfree; if (!ptr) return; p = Ptr2Slot(ptr); - // If the next slot is free (and contiguous) merge it into this one - if ((char *)p + p->sz == (char *)p->next) { - for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { - if (new == p->next) { - p->next = new->next; - p->sz += new->sz; - if (prev) - NextFree(prev) = NextFree(new); - else - freeSlots = NextFree(new); - if (lastSlot == new) - lastSlot = p; - break; - } + // Find a free slot that is contiguous precceding and merge it into us + for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { + if (p == (memslot *)((char *)pfree + pfree->sz)) { + pfree->sz += p->sz; + if (prev) + NextFree(prev) = NextFree(pfree); + else + freeSlots = NextFree(pfree); + p = pfree; + break; + } + } + + // Find a free slot that is contiguous after and merge it into this one + for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { + if (pfree == (memslot *)((char *)p + p->sz)) { + p->sz += pfree->sz; + if (prev) + NextFree(prev) = NextFree(pfree); + else + freeSlots = NextFree(pfree); + break; } } diff --git a/src/gos/gos_x_threads.c b/src/gos/gos_x_threads.c index 7afd224a..b696ee77 100644 --- a/src/gos/gos_x_threads.c +++ b/src/gos/gos_x_threads.c @@ -122,6 +122,7 @@ void gfxSleepMilliseconds(delaytime_t ms) { case TIME_INFINITE: while(1) gfxYield(); + return; } // Convert our delay to ticks @@ -143,6 +144,7 @@ void gfxSleepMicroseconds(delaytime_t ms) { case TIME_INFINITE: while(1) gfxYield(); + return; } // Convert our delay to ticks @@ -212,12 +214,12 @@ static thread mainthread; // The main thread context * If they don't exist compile them to be the standard setjmp() function. * Similarly for longjmp(). */ - #if (!defined(setjmp) && !defined(_setjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL + #if (!defined(setjmp) && !defined(_setjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 #define CXT_SAVE setjmp #else #define CXT_SAVE _setjmp #endif - #if (!defined(longjmp) && !defined(_longjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL + #if (!defined(longjmp) && !defined(_longjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 #define CXT_RESTORE longjmp #else #define CXT_RESTORE _longjmp @@ -346,6 +348,7 @@ static thread mainthread; // The main thread context uint32_t i; // Copy the stack frame + s = 0; #if AUTO_DETECT_STACKFRAME if (STACK_DIR_UP) { // Stack grows up nf = (char *)(t) + sizeof(thread) + sizeof(jmp_buf) + STACK_BASE; diff --git a/src/gos/gos_x_threads.h b/src/gos/gos_x_threads.h index ee7a9cd0..585585c5 100644 --- a/src/gos/gos_x_threads.h +++ b/src/gos/gos_x_threads.h @@ -90,7 +90,7 @@ extern "C" { threadreturn_t gfxThreadWait(gfxThreadHandle thread); gfxThreadHandle gfxThreadMe(void); - /** The following is not part of the public ugfx API has some operating systems + /** The following is not part of the public ugfx API as some operating systems * simply do not provide this capability. * For RAW32 we need it anyway so we might as well declare it here. */ diff --git a/src/gos/gos_x_threads_cortexm01.h b/src/gos/gos_x_threads_cortexm01.h index 8a44bd35..15a90b2a 100644 --- a/src/gos/gos_x_threads_cortexm01.h +++ b/src/gos/gos_x_threads_cortexm01.h @@ -27,8 +27,10 @@ "mov r6, r10 \n\t" "mov r7, r11 \n\t" "push {r4, r5, r6, r7} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" + "mov r4, sp \n\t" + "str r4, %[oldtcxt] \n\t" + "ldr r4, %[newtcxt] \n\t" + "mov sp, r4 \n\t" "pop {r4, r5, r6, r7} \n\t" "mov r8, r4 \n\t" "mov r9, r5 \n\t" @@ -41,15 +43,17 @@ } static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; + newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); __asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t" "mov r4, r8 \n\t" "mov r5, r9 \n\t" "mov r6, r10 \n\t" "mov r7, r11 \n\t" "push {r4, r5, r6, r7} \n\t" - "str sp, %[oldtcxt] \n\t" - "ldr sp, %[newtcxt] \n\t" + "mov r4, sp \n\t" + "str r4, %[oldtcxt] \n\t" + "ldr r4, %[newtcxt] \n\t" + "mov sp, r4 \n\t" : [newtcxt] "=m" (newt->cxt) : [oldtcxt] "m" (oldt->cxt) : "memory"); @@ -59,8 +63,12 @@ } #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + #define GFX_THREADS_DONE + #define _gfxThreadsInit() static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) { + PRESERVE8 + // Save the old context push {r4, r5, r6, r7, lr} mov r4, r8 @@ -68,10 +76,12 @@ mov r6, r10 mov r7, r11 push {r4, r5, r6, r7} - str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt + mov r4, sp + str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt // Load the new context - ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt + ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt + mov sp, r4 pop {r4, r5, r6, r7} mov r8, r4 mov r9, r5 @@ -81,11 +91,14 @@ } static __asm void _gfxStartThread(thread *oldt, thread *newt) { + PRESERVE8 + // Calculate where to generate the new context - // newt->cxt = (char *)newt + newt->size; - ldr r2,[r1,#__cpp(offsetof(thread,size))] - add r2,r2,r1 - str r2,[r1,#__cpp(offsetof(thread,cxt))] + // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); + ldr r2,[r1,#__cpp(offsetof(thread,size))] + add r2,r2,r1 + and r2, r2, #0xFFFFFFF8 + str r2,[r1,#__cpp(offsetof(thread,cxt))] // Save the old context push {r4, r5, r6, r7, lr} @@ -94,20 +107,24 @@ mov r6, r10 mov r7, r11 push {r4, r5, r6, r7} - str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt + mov r4, sp + str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt // Load the new (imcomplete) context - ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt + ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt + mov sp, r4 // Run the users function - we save some code because gfxThreadExit() never returns // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param)); - LDR r2,__cpp(&_gfxCurrentThread) - LDR r2,[r2,#0] - LDR r0,[r2,#__cpp(offsetof(thread,param))] - LDR r1,[r2,#__cpp(offsetof(thread,fn))] - BLX r1 - MOV r4,r0 - BL gfxThreadExit + ldr r2,=__cpp(&_gfxCurrentThread) + ldr r2,[r2,#0] + ldr r0,[r2,#__cpp(offsetof(thread,param))] + ldr r1,[r2,#__cpp(offsetof(thread,fn))] + blx r1 + mov r4,r0 + bl __cpp(gfxThreadExit) + + ALIGN } #else diff --git a/src/gos/gos_x_threads_cortexm347.h b/src/gos/gos_x_threads_cortexm347.h index 03c13052..40d30138 100644 --- a/src/gos/gos_x_threads_cortexm347.h +++ b/src/gos/gos_x_threads_cortexm347.h @@ -32,7 +32,7 @@ } static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; + newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" "str sp, %[oldtcxt] \n\t" "ldr sp, %[newtcxt] \n\t" @@ -45,8 +45,12 @@ } #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + #define GFX_THREADS_DONE + #define _gfxThreadsInit() static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) { + PRESERVE8 + // Save the old context push {r4, r5, r6, r7, r8, r9, r10, r11, lr} str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt @@ -57,11 +61,14 @@ } static __asm void _gfxStartThread(thread *oldt, thread *newt) { + PRESERVE8 + // Calculate where to generate the new context - // newt->cxt = (char *)newt + newt->size; - ldr r2,[r1,#__cpp(offsetof(thread,size))] - add r2,r2,r1 - str r2,[r1,#__cpp(offsetof(thread,cxt))] + // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); + ldr r2,[r1,#__cpp(offsetof(thread,size))] + add r2,r2,r1 + and r2, r2, #0xFFFFFFF8 + str r2,[r1,#__cpp(offsetof(thread,cxt))] // Save the old context push {r4, r5, r6, r7, r8, r9, r10, r11, lr} @@ -72,13 +79,15 @@ // Run the users function - we save some code because gfxThreadExit() never returns // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param)); - LDR r2,__cpp(&_gfxCurrentThread) - LDR r2,[r2,#0] - LDR r0,[r2,#__cpp(offsetof(thread,param))] - LDR r1,[r2,#__cpp(offsetof(thread,fn))] - BLX r1 - MOV r4,r0 - BL gfxThreadExit + ldr r2,=__cpp(&_gfxCurrentThread) + ldr r2,[r2,#0] + ldr r0,[r2,#__cpp(offsetof(thread,param))] + ldr r1,[r2,#__cpp(offsetof(thread,fn))] + blx r1 + mov r4,r0 + bl __cpp(gfxThreadExit) + + ALIGN } #else diff --git a/src/gos/gos_x_threads_cortexm47fp.h b/src/gos/gos_x_threads_cortexm47fp.h index 9767ac9a..f5eeff80 100644 --- a/src/gos/gos_x_threads_cortexm47fp.h +++ b/src/gos/gos_x_threads_cortexm47fp.h @@ -12,10 +12,6 @@ * The context is saved at the current stack location and a pointer is maintained in the thread structure. */ -#if !CORTEX_USE_FPU - #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M?_FP with hardware floating point support but CORTEX_USE_FPU is FALSE. Try using GFX_CPU_GFX_CPU_CORTEX_M? instead" -#endif - #if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64 #define GFX_THREADS_DONE #define _gfxThreadsInit() @@ -33,7 +29,7 @@ } static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxStartThread(thread *oldt, thread *newt) { - newt->cxt = (char *)newt + newt->size; + newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); __asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t" "vpush {s16-s31} \n\t" "str sp, %[oldtcxt] \n\t" @@ -47,8 +43,12 @@ } #elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC + #define GFX_THREADS_DONE + #define _gfxThreadsInit() static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) { + PRESERVE8 + // Save the old context push {r4, r5, r6, r7, r8, r9, r10, r11, lr} vpush {s16-s31} @@ -61,11 +61,14 @@ } static __asm void _gfxStartThread(thread *oldt, thread *newt) { + PRESERVE8 + // Calculate where to generate the new context - // newt->cxt = (char *)newt + newt->size; - ldr r2,[r1,#__cpp(offsetof(thread,size))] - add r2,r2,r1 - str r2,[r1,#__cpp(offsetof(thread,cxt))] + // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7); + ldr r2,[r1,#__cpp(offsetof(thread,size))] + add r2,r2,r1 + and r2, r2, #0xFFFFFFF8 + str r2,[r1,#__cpp(offsetof(thread,cxt))] // Save the old context push {r4, r5, r6, r7, r8, r9, r10, r11, lr} @@ -77,13 +80,15 @@ // Run the users function - we save some code because gfxThreadExit() never returns // gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param)); - LDR r2,__cpp(&_gfxCurrentThread) - LDR r2,[r2,#0] - LDR r0,[r2,#__cpp(offsetof(thread,param))] - LDR r1,[r2,#__cpp(offsetof(thread,fn))] - BLX r1 - MOV r4,r0 - BL gfxThreadExit + ldr r2,=__cpp(&_gfxCurrentThread) + ldr r2,[r2,#0] + ldr r0,[r2,#__cpp(offsetof(thread,param))] + ldr r1,[r2,#__cpp(offsetof(thread,fn))] + blx r1 + mov r4,r0 + bl __cpp(gfxThreadExit) + + ALIGN } #else diff --git a/src/gtimer/gtimer.c b/src/gtimer/gtimer.c index eda88d5a..22ec9ed2 100644 --- a/src/gtimer/gtimer.c +++ b/src/gtimer/gtimer.c @@ -109,7 +109,7 @@ static DECLARE_THREAD_FUNCTION(GTimerThreadHandler, arg) { lastTime = tm; gfxMutexExit(&mutex); } -// THREAD_RETURN(0); + THREAD_RETURN(0); } void _gtimerInit(void) diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 586636ec..c5082ea0 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -281,6 +281,14 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } #endif +#if GDISP_NEED_DUALCIRCLE + void gwinFillDualCircle(GHandle gh, coord_t x, coord_t y, coord_t radius1, coord_t radius2) { + if (!_gwinDrawStart(gh)) return; + gdispGFillDualCircle(gh->display, gh->x+x, gh->y+y, radius1, gh->bgcolor, radius2, gh->color); + _gwinDrawEnd(gh); + } +#endif + #if GDISP_NEED_ELLIPSE void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { if (!_gwinDrawStart(gh)) return; @@ -307,6 +315,12 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor gdispGFillArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); _gwinDrawEnd(gh); } + + void gwinDrawThickArc(GHandle gh, coord_t x, coord_t y, coord_t startradius, coord_t endradius, coord_t startangle, coord_t endangle) { + if (!_gwinDrawStart(gh)) return; + gdispGDrawThickArc(gh->display, gh->x+x, gh->y+y, startradius, endradius, startangle, endangle, gh->color); + _gwinDrawEnd(gh); + } #endif #if GDISP_NEED_ARCSECTORS diff --git a/src/gwin/gwin.h b/src/gwin/gwin.h index 5912046b..c3d18c31 100644 --- a/src/gwin/gwin.h +++ b/src/gwin/gwin.h @@ -718,6 +718,24 @@ extern "C" { void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius); #endif + #if GDISP_NEED_DUALCIRCLE || defined(__DOXYGEN__) + /** + * @brief Draw two filled circles with the same centre in the window. + * @note Uses the current foreground color to draw the inner circle + * @note Uses the current background color to draw the outer circle + * @note May leave GDISP clipping to this window's dimensions + * @pre GDISP_NEED_DUALCIRCLE must be TRUE in your gfxconf.h + * + * @param[in] gh The window handle + * @param[in] x,y The center of the circle + * @param[in] radius1 The radius of the larger circle + * @param[in] radius2 The radius of the smaller circle + * + * @api + */ + void gwinFillDualCircle(GHandle gh, coord_t x, coord_t y, coord_t radius1, coord_t radius2); + #endif + #if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__) /** * @brief Draw an ellipse. @@ -776,6 +794,22 @@ extern "C" { * @api */ void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle); + + /* + * @brief Draw a thick arc in the window. + * @note Uses the current foreground color to draw the thick 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] startradius The inner radius of the thick arc + * @param[in] endradius The outer radius of the thick arc + * @param[in] startangle The start angle (0 to 360) + * @param[in] endangle The end angle (0 to 360) + * + * @api + */ + void gwinDrawThickArc(GHandle gh, coord_t x, coord_t y, coord_t startradius, coord_t endradius, coord_t startangle, coord_t endangle); #endif #if GDISP_NEED_ARCSECTORS || defined(__DOXYGEN__) |