mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
display: add dcircle() and dellipse() rendering functions
For PythonExtra#2.
This commit is contained in:
parent
2bb5294578
commit
18a7b9ae5b
4 changed files with 127 additions and 0 deletions
|
@ -102,6 +102,8 @@ set(SOURCES_COMMON
|
|||
# MMU driver
|
||||
src/mmu/mmu.c
|
||||
# Rendering
|
||||
src/render/dcircle.c
|
||||
src/render/dellipse.c
|
||||
src/render/dhline.c
|
||||
src/render/dimage.c
|
||||
src/render/dline.c
|
||||
|
|
|
@ -212,6 +212,38 @@ void dhline(int y, int color);
|
|||
@color Line color (same values as dline() are allowed) */
|
||||
void dvline(int x, int color);
|
||||
|
||||
//---
|
||||
// Other geometric shapes
|
||||
//---
|
||||
|
||||
/* dcircle(): Circle with border
|
||||
|
||||
This function renders a circle defined by its middle point (xm, ym) and a
|
||||
radius r. The border and fill can be set separately. This function uses
|
||||
Bresenham's algorithm and only renders circles of odd diameter; if you want
|
||||
an even diameter, use dellipse() with a bounding box.
|
||||
|
||||
@xm @ym Coordinates of center
|
||||
@r Radius (integer, >= 0)
|
||||
@fill_color Color of the disc inside the circle, C_NONE to disable
|
||||
@border_color Color of the circle itself, C_NONE to disable */
|
||||
void dcircle(int xm, int ym, int r, int fill_color, int border_color);
|
||||
|
||||
/* dellipse(): Ellipse with border
|
||||
|
||||
This function renders a non-rotated ellipse, defined by its bounding box.
|
||||
The border and fill can be set separately. The border is as 1-pixel thin
|
||||
border given by Bresenham's algorithm.
|
||||
|
||||
To render an ellipse from its center coordinates (x,y) and semi-major/minor
|
||||
axes a/b, use dellipse(x-a, y-b, x+a, y+b, fill_color, border_color).
|
||||
|
||||
@x1 @y1 @x2 @y2 Ellipse's bounding box (both bounds included, like drect())
|
||||
@fill_color Color of the surface inside the ellipse, C_NONE to disable
|
||||
@border_color Color of the ellipse itself, C_NONE to disable */
|
||||
void dellipse(int x1, int y1, int x2, int y2, int fill_color,
|
||||
int border_color);
|
||||
|
||||
//---
|
||||
// Text rendering (topti)
|
||||
//---
|
||||
|
|
36
src/render/dcircle.c
Normal file
36
src/render/dcircle.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <gint/display.h>
|
||||
|
||||
/* Based on <http://members.chello.at/~easyfilter/bresenham.html> */
|
||||
void dcircle(int xm, int ym, int r, int fill_color, int border_color)
|
||||
{
|
||||
if(r < 0 || (fill_color == C_NONE && border_color == C_NONE)) return;
|
||||
|
||||
/* Circle is completely outside the rendering window */
|
||||
if(xm-r >= dwindow.right || xm+r < dwindow.left) return;
|
||||
if(ym-r >= dwindow.bottom || ym+r < dwindow.top) return;
|
||||
|
||||
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
|
||||
|
||||
/* The iteration is slightly changed from the original. We swap x/y in
|
||||
quadrants II. and IV. so that we get horizontal linesi nstead of a
|
||||
single arc rotated 4 times. However this means we have to go until
|
||||
x <= 0 instead of x < 0. */
|
||||
do {
|
||||
if(fill_color != C_NONE)
|
||||
dline(xm-x, ym+y, xm+x, ym+y, fill_color);
|
||||
dpixel(xm-x, ym+y, border_color); /* I. Quadrant */
|
||||
dpixel(xm+x, ym+y, border_color); /* II. Quadrant */
|
||||
|
||||
if(fill_color != C_NONE)
|
||||
dline(xm-x, ym-y, xm+x, ym-y, fill_color);
|
||||
dpixel(xm+x, ym-y, border_color); /* III. Quadrant */
|
||||
dpixel(xm-x, ym-y, border_color); /* IV. Quadrant */
|
||||
|
||||
r = err;
|
||||
if (r <= y) /* e_xy+e_y < 0 */
|
||||
err += ++y*2+1;
|
||||
if (r > x || err > y) /* e_xy+e_x > 0 or no 2nd y-step */
|
||||
err += ++x*2+1;
|
||||
}
|
||||
while (x <= 0);
|
||||
}
|
57
src/render/dellipse.c
Normal file
57
src/render/dellipse.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/defs/util.h>
|
||||
|
||||
/* Based on <http://members.chello.at/~easyfilter/bresenham.html> */
|
||||
void dellipse(int x1, int y1, int x2, int y2, int fill_color, int border_color)
|
||||
{
|
||||
if(fill_color == C_NONE && border_color == C_NONE) return;
|
||||
|
||||
if(x1 > x2) swap(x1, x2);
|
||||
if(y1 > y2) swap(y1, y2);
|
||||
|
||||
/* Ellipse is completely outside the rendering window */
|
||||
if(x1 >= dwindow.right || x2 < dwindow.left) return;
|
||||
if(y1 >= dwindow.bottom || y2 < dwindow.top) return;
|
||||
|
||||
int a = x2-x1, b = y2-y1, b1 = b&1; /* diameter */
|
||||
int dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
|
||||
int err = dx + dy + b1 * a * a, e2; /* error of 1.step */
|
||||
|
||||
y1 += (b + 1) / 2;
|
||||
y2 = y1-b1; /* starting pixel */
|
||||
a = 8 * a * a;
|
||||
b1 = 8 * b * b;
|
||||
|
||||
do {
|
||||
if(fill_color != C_NONE)
|
||||
dline(x1, y1, x2, y1, fill_color);
|
||||
dpixel(x2, y1, border_color); /* I. Quadrant */
|
||||
dpixel(x1, y1, border_color); /* II. Quadrant */
|
||||
|
||||
if(fill_color != C_NONE)
|
||||
dline(x1, y2, x2, y2, fill_color);
|
||||
dpixel(x1, y2, border_color); /* III. Quadrant */
|
||||
dpixel(x2, y2, border_color); /* IV. Quadrant */
|
||||
|
||||
e2 = 2 * err;
|
||||
if (e2 <= dy) {
|
||||
y1++;
|
||||
y2--;
|
||||
err += (dy += a);
|
||||
}
|
||||
if (e2 >= dx || 2 * err > dy) {
|
||||
x1++;
|
||||
x2--;
|
||||
err += (dx += b1);
|
||||
}
|
||||
}
|
||||
while (x1 <= x2);
|
||||
|
||||
while (y1 - y2 <= b) /* to early stop of flat ellipses a=1 */
|
||||
{
|
||||
dpixel(x1 - 1, y1, border_color); /* finish tip of ellipse */
|
||||
dpixel(x2 + 1, y1++, border_color);
|
||||
dpixel(x1 - 1, y2, border_color);
|
||||
dpixel(x2 + 1, y2--, border_color);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue