263 lines
6.5 KiB
C
263 lines
6.5 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* uC/GUI
|
|
* Universal graphic software for embedded applications
|
|
*
|
|
* (c) Copyright 2002, Micrium Inc., Weston, FL
|
|
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
|
|
*
|
|
* µC/GUI is protected by international copyright laws. Knowledge of the
|
|
* source code may not be used to write a similar product. This file may
|
|
* only be used in accordance with a license and should not be redistributed
|
|
* in any way. We appreciate your understanding and fairness.
|
|
*
|
|
----------------------------------------------------------------------
|
|
File : GUIARCFloat.C
|
|
Purpose : Draw Arc routines based on floating point
|
|
----------------------------------------------------------------------
|
|
Version-Date---Author-Explanation
|
|
----------------------------------------------------------------------
|
|
2.00.00 000325 RS First release of the new algorithm
|
|
----------------------------------------------------------------------
|
|
Known problems or limitations with current version
|
|
----------------------------------------------------------------------
|
|
None.
|
|
----------------------------------------------------------------------
|
|
Open issues
|
|
----------------------------------------------------------------------
|
|
None
|
|
---------------------------END-OF-HEADER------------------------------
|
|
*/
|
|
|
|
#include <stddef.h> /* needed for definition of NULL */
|
|
#include "arm_math.h"
|
|
#include "GUI_Protected.h"
|
|
|
|
/*********************************************************************
|
|
*
|
|
* Static code
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
/*********************************************************************
|
|
*
|
|
* _CalcX
|
|
*/
|
|
static void _CalcX(int *px, int y, U32 r2)
|
|
{
|
|
int x = *px;
|
|
U32 y2 = (U32)y * (U32)y;
|
|
U32 r2y2 = r2 - y2;
|
|
U32 x2;
|
|
if (y2 >= r2)
|
|
{
|
|
*px = 0;
|
|
return;
|
|
}
|
|
/* x2 = r2-y2 */
|
|
do
|
|
{
|
|
x++;
|
|
x2 = (U32)x * (U32)x;
|
|
} while (x2 < r2y2);
|
|
*px = x - 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* _CalcInterSectLin
|
|
*/
|
|
static float _CalcInterSectLin(float y, float y0, float y1, float x0, float x1)
|
|
{
|
|
if (y1 == y0)
|
|
{
|
|
return y0;
|
|
}
|
|
else
|
|
{
|
|
float Slope = (x1 - x0) / (y1 - y0);
|
|
return (y - y0) * Slope + x0;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* _DrawArc
|
|
*/
|
|
static void _DrawArc(int x0, int y0, int rx, int ry, int Angle0, int Angle1, int xMul, int yMul)
|
|
{
|
|
float afx[4];
|
|
float afy[4];
|
|
float ri = rx - (GUI_Context.PenSize + 1.5) / 2;
|
|
float ro = rx + (GUI_Context.PenSize + 1.5) / 2;
|
|
float fAngle0 = Angle0 * 3.1415926 / 180;
|
|
float fAngle1 = Angle1 * 3.1415926 / 180;
|
|
float sin0 = arm_sin_f32(fAngle0);
|
|
float sin1 = arm_sin_f32(fAngle1);
|
|
float cos0 = arm_cos_f32(fAngle0);
|
|
float cos1 = arm_cos_f32(fAngle1);
|
|
U32 ri2 = ri * ri;
|
|
U32 ro2 = ro * ro;
|
|
int y, yMax, yMin;
|
|
afy[0] = ri * sin0;
|
|
afy[1] = ro * sin0;
|
|
afy[2] = ri * sin1;
|
|
afy[3] = ro * sin1;
|
|
afx[0] = ri * cos0;
|
|
afx[1] = ro * cos0;
|
|
afx[2] = ri * cos1;
|
|
afx[3] = ro * cos1;
|
|
yMin = ceil(afy[0]);
|
|
yMax = floor(afy[3]);
|
|
/* Use Clipping rect to reduce calculation (if possible) */
|
|
if (GUI_Context.pClipRect_HL)
|
|
{
|
|
if (yMul == 1)
|
|
{
|
|
if (yMax > (GUI_Context.pClipRect_HL->y1 - y0))
|
|
yMax = (GUI_Context.pClipRect_HL->y1 - y0);
|
|
if (yMin < (GUI_Context.pClipRect_HL->y0 - y0))
|
|
yMin = (GUI_Context.pClipRect_HL->y0 - y0);
|
|
}
|
|
if (yMul == -1)
|
|
{
|
|
if (yMin > (GUI_Context.pClipRect_HL->y1 - y0))
|
|
yMin = (GUI_Context.pClipRect_HL->y1 - y0);
|
|
if (yMax < (GUI_Context.pClipRect_HL->y0 - y0))
|
|
yMax = (GUI_Context.pClipRect_HL->y0 - y0);
|
|
}
|
|
}
|
|
/* Start drawing lines ... */
|
|
{
|
|
int xMinDisp, xMaxDisp, xMin = 0, xMax = 0;
|
|
for (y = yMax; y >= yMin; y--)
|
|
{
|
|
_CalcX(&xMin, y, ri2);
|
|
_CalcX(&xMax, y, ro2);
|
|
if ((float)y < afy[1])
|
|
{
|
|
xMaxDisp = _CalcInterSectLin(y, afy[0], afy[1], afx[0], afx[1]);
|
|
}
|
|
else
|
|
{
|
|
xMaxDisp = xMax;
|
|
}
|
|
if ((float)y > afy[2])
|
|
{
|
|
xMinDisp = _CalcInterSectLin(y, afy[2], afy[3], afx[2], afx[3]);
|
|
}
|
|
else
|
|
{
|
|
xMinDisp = xMin;
|
|
}
|
|
if (xMul > 0)
|
|
LCD_HL_DrawHLine(xMinDisp + x0, yMul * y + y0, xMaxDisp + x0);
|
|
else
|
|
LCD_HL_DrawHLine(-xMaxDisp + x0, yMul * y + y0, -xMinDisp + x0);
|
|
}
|
|
}
|
|
#if 0 /* Test code */
|
|
{
|
|
int i;
|
|
GUI_SetColor( GUI_WHITE );
|
|
for (i=0; i<4; i++)
|
|
LCD_HL_DrawPixel(afx[i]+x0, afy[i]+y0);
|
|
}
|
|
#endif
|
|
GUI_USE_PARA(ry);
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* Public code
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
/*********************************************************************
|
|
*
|
|
* GL_DrawArc
|
|
*/
|
|
void GL_DrawArc(int x0, int y0, int rx, int ry, int a0, int a1)
|
|
{
|
|
int aEnd;
|
|
a0 += 360;
|
|
a1 += 360;
|
|
while (a0 >= 360)
|
|
{
|
|
a0 -= 360;
|
|
a1 -= 360;
|
|
}
|
|
/* Do first quadrant 0-90 degree */
|
|
DoFirst:
|
|
if (a1 <= 0)
|
|
return;
|
|
if (a0 < 90)
|
|
{
|
|
if (a0 < 0)
|
|
a0 = 0;
|
|
aEnd = (a1 < 90) ? a1 : 90;
|
|
_DrawArc(x0, y0, rx, ry, a0, aEnd, 1, -1);
|
|
}
|
|
a1 -= 90;
|
|
a0 -= 90;
|
|
/* Do second quadrant 90-180 degree */
|
|
if (a1 <= 0)
|
|
return;
|
|
if (a0 < 90)
|
|
{
|
|
if (a0 < 0)
|
|
a0 = 0;
|
|
aEnd = (a1 < 90) ? a1 : 90;
|
|
_DrawArc(x0, y0, rx, ry, 90 - aEnd, 90 - a0, -1, -1);
|
|
}
|
|
a1 -= 90;
|
|
a0 -= 90;
|
|
/* Do third quadrant 180-270 degree */
|
|
if (a1 <= 0)
|
|
return;
|
|
if (a0 < 90)
|
|
{
|
|
if (a0 < 0)
|
|
a0 = 0;
|
|
aEnd = (a1 < 90) ? a1 : 90;
|
|
_DrawArc(x0, y0, rx, ry, a0, aEnd, -1, 1);
|
|
}
|
|
a1 -= 90;
|
|
a0 -= 90;
|
|
/* Do last quadrant 270-360 degree */
|
|
if (a1 <= 0)
|
|
return;
|
|
if (a0 < 90)
|
|
{
|
|
if (a0 < 0)
|
|
a0 = 0;
|
|
aEnd = (a1 < 90) ? a1 : 90;
|
|
_DrawArc(x0, y0, rx, ry, 90 - aEnd, 90 - a0, 1, 1);
|
|
}
|
|
a1 -= 90;
|
|
a0 -= 90;
|
|
goto DoFirst;
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* GUI_DrawArc
|
|
*/
|
|
void GUI_DrawArc(int x0, int y0, int rx, int ry, int a0, int a1)
|
|
{
|
|
GUI_LOCK();
|
|
#if (GUI_WINSUPPORT)
|
|
WM_ADDORG(x0, y0);
|
|
WM_ITERATE_START(NULL)
|
|
{
|
|
#endif
|
|
GL_DrawArc(x0, y0, rx, ry, a0, a1);
|
|
#if (GUI_WINSUPPORT)
|
|
}
|
|
WM_ITERATE_END();
|
|
#endif
|
|
GUI_UNLOCK();
|
|
}
|
|
|
|
/*************************** End of file ****************************/
|