diff --git a/native/module_pyfb.c b/native/module_pyfb.c index d4f0079..6fc93d0 100644 --- a/native/module_pyfb.c +++ b/native/module_pyfb.c @@ -255,6 +255,39 @@ static PyObject* pyfunc_pyfb_sdrawCircle(PyObject* self, PyObject* args) { return PyLong_FromLong(exitcode); } +/** + * Python wrapper for the pyfb_drawEllipse function. + * + * @param self The function + * @param args The arguments, expecting long of the fbnum, long of the xm, long of the ym, long of the a, long of the b, long of the color + * + * @return Just 0 + */ +static PyObject* pyfunc_pyfb_sdrawEllipse(PyObject* self, PyObject* args) { + unsigned char fbnum_c; + unsigned long int xm; + unsigned long int ym; + unsigned long int a; + unsigned long int b; + uint32_t color_val; + + if(!PyArg_ParseTuple(args, "bkkkkI", &fbnum_c, &xm, &ym, &a, &b, &color_val)) { + PyErr_SetString(PyExc_TypeError, "Expecting arguments of type (byte, long, long, long, long, long)"); + return NULL; + } + + // now parse the color + struct pyfb_color color; + pyfb_initcolor_u32(&color, color_val); + + // and invoke the target function + pyfb_sdrawEllipse((uint8_t)fbnum_c, xm, ym, a, b, &color); + + // and return just 0 + int exitcode = 0; + return PyLong_FromLong(exitcode); +} + // The module def /** @@ -268,6 +301,7 @@ static PyMethodDef pyfb_methods[] = { {"pyfb_drawHorizontalLine", pyfunc_pyfb_sdrawHorizontalLine, METH_VARARGS, "Draw a horizontal line on the framebuffer"}, {"pyfb_drawVerticalLine", pyfunc_pyfb_sdrawVerticalLine, METH_VARARGS, "Draw a vertical line on the framebuffer"}, {"pyfb_drawCircle", pyfunc_pyfb_sdrawCircle, METH_VARARGS, "Draw a circle on the framebuffer"}, + {"pyfb_drawEllipse", pyfunc_pyfb_sdrawEllipse, METH_VARARGS, "Draw a ellipse on the framebuffer"}, {"pyfb_flushBuffer", pyfunc_pyfb_flushBuffer, METH_VARARGS, "Flush the offscreen buffer to the framebuffer"}, {"pyfb_getResolution", pyfunc_pyfb_getResolution, METH_VARARGS, "Returns a tupel of the framebuffer resolution"}, {NULL, NULL, 0, NULL}}; diff --git a/native/paint.c b/native/paint.c index 45401cb..f897858 100644 --- a/native/paint.c +++ b/native/paint.c @@ -219,6 +219,80 @@ void pyfb_sdrawCircle(uint8_t fbnum, pyfb_drawCircle(fbnum, xm, ym, radius, color); + // ready, so return + pyfb_fbunlock(fbnum); +} + +void __APISTATUS_internal pyfb_drawEllipse(uint8_t fbnum, + unsigned long int xm, + unsigned long int ym, + unsigned long int a, + unsigned long int b, + struct pyfb_color* color) { + long int al = ULI_TO_LI(a); + long int bl = ULI_TO_LI(b); + long int dx = 0; + long int dy = bl; + long a2 = al * al; + long b2 = bl * bl; + long err = b2 - (2 * bl - 1) * a2; + long e2 = 0; + + struct pyfb_videomode_info vinfo; + pyfb_vinfo(fbnum, &vinfo); + + const long int xres = ULI_TO_LI(vinfo.vinfo.xres); + const long int yres = ULI_TO_LI(vinfo.vinfo.yres); + + do { + SET_PIXEL_OR_IGNORE(fbnum, xm + dx, ym + dy, xres, yres, color); + SET_PIXEL_OR_IGNORE(fbnum, xm - dx, ym + dy, xres, yres, color); + SET_PIXEL_OR_IGNORE(fbnum, xm - dx, ym - dy, xres, yres, color); + SET_PIXEL_OR_IGNORE(fbnum, xm + dx, ym - dy, xres, yres, color); + e2 = 2 * err; + + if(e2 < (2 * dx + 1) * b2) { + ++dx; + err += (2 * dx + 1) * b2; + } + + if(e2 > -(2 * dy - 1) * a2) { + --dy; + err -= (2 * dy - 1) * a2; + } + } while(dy >= 0); + + while(dx++ < a) { + SET_PIXEL_OR_IGNORE(fbnum, xm + dx, ym, xres, yres, color); + SET_PIXEL_OR_IGNORE(fbnum, xm - dx, ym, xres, yres, color); + } +} + +void pyfb_sdrawEllipse(uint8_t fbnum, + unsigned long int xm, + unsigned long int ym, + unsigned long int a, + unsigned long int b, + struct pyfb_color* color) { + // fist check if fbnum is valid + if(fbnum >= MAX_FRAMEBUFFERS) { + PyErr_SetString(PyExc_ValueError, "The framebuffer number is not valid"); + return; + } + + // Ok, then lock + pyfb_fblock(fbnum); + + // next test, if the device is in use + if(!pyfb_fbused(fbnum)) { + // this framebuffer is not in use, so reject + PyErr_SetString(PyExc_IOError, "The framebuffer is not opened"); + pyfb_fbunlock(fbnum); + return; + } + + pyfb_drawEllipse(fbnum, xm, ym, a, b, color); + // ready, so return pyfb_fbunlock(fbnum); } \ No newline at end of file diff --git a/native/pyframebuffer.h b/native/pyframebuffer.h index d456394..eba3f3a 100644 --- a/native/pyframebuffer.h +++ b/native/pyframebuffer.h @@ -442,6 +442,40 @@ extern void __APISTATUS_internal pyfb_drawCircle(uint8_t fbnum, unsigned long int radius, struct pyfb_color* color); +/** + * Safe version to draw a ellipse on the screen. + * + * @param fbnum The framebuffer number + * @param xm The x coordinate of the middle point + * @param ym The y coordinate of the middle point + * @param a The long half axis + * @param b The short half axis + * @param color The color value + */ +extern void pyfb_sdrawEllipse(uint8_t fbnum, + unsigned long int xm, + unsigned long int ym, + unsigned long int a, + unsigned long int b, + struct pyfb_color* color); + +/** + * Unsafe version to draw a ellipse on the screen. + * + * @param fbnum The framebuffer number + * @param xm The x coordinate of the middle point + * @param ym The y coordinate of the middle point + * @param a The long half axis + * @param b The short half axis + * @param color The color value + */ +extern void __APISTATUS_internal pyfb_drawEllipse(uint8_t fbnum, + unsigned long int xm, + unsigned long int ym, + unsigned long int a, + unsigned long int b, + struct pyfb_color* color); + /** * Paints the content of the offscreen buffer to the framebuffer. This function must be callen * because this is the only operation that is required to paint the content of the offscreen diff --git a/pyframebuffer/__init__.py b/pyframebuffer/__init__.py index a782e79..99991e6 100644 --- a/pyframebuffer/__init__.py +++ b/pyframebuffer/__init__.py @@ -216,6 +216,19 @@ def drawCircle(self, xm, ym, radius, color): color = getColorValue(color) fb.pyfb_drawCircle(self.fbnum, xm, ym, radius, color) + def drawEllipse(self, xm, ym, a, b, color): + """ + Draws a ellipse on the offscreen buffer. + + @param xm The x coordinate of the middle + @param ym The y coordinate of the middle + @param a The long half axis + @param b The short half axis + @param color The color value + """ + color = getColorValue(color) + fb.pyfb_drawEllipse(self.fbnum, xm, ym, a, b, color) + def openfb(num): """