* clutter/cogl/cogl.h.in: api review touch ups.

* clutter/cogl/common/cogl-primitives.c: api review touch ups.
* clutter/cogl/gl/cogl-primitives.c: (cogl_path_fill),
(cogl_path_stroke): indentation.
* clutter/cogl/gles/cogl-primitives.c:
(_cogl_path_fill_nodes): free allocated resources.
* tests/test-cogl-primitives.c: updated to new API, added rotation to
test to show that cogl renders paths correct under perspective
distortion.
This commit is contained in:
Øyvind Kolås 2008-05-05 10:25:11 +00:00
parent bbe138298c
commit f2b44899f9
4 changed files with 176 additions and 298 deletions

View File

@ -960,44 +960,6 @@ void cogl_rectanglex (ClutterFixed x,
ClutterFixed y, ClutterFixed y,
ClutterFixed width, ClutterFixed width,
ClutterFixed height); ClutterFixed height);
#if 0
/**
* cogl_trapezoid:
* @y1: Y coordinate of the top two vertices.
* @x11: X coordinate of the top-left vertex.
* @x21: X coordinate of the top-right vertex.
* @y2: Y coordinate of the bottom two vertices.
* @x12: X coordinate of the bottom-left vertex.
* @x22: X coordinate of the bottom-right vertex.
*
* Fills a trapezoid at the given coordinates with the current
* drawing color in a highly optimized fashion.
**/
void cogl_trapezoid (gint y1,
gint x11,
gint x21,
gint y2,
gint x12,
gint x22);
/**
* cogl_trapezoidx:
* @y1: Y coordinate of the top two vertices.
* @x11: X coordinate of the top-left vertex.
* @x21: X coordinate of the top-right vertex.
* @y2: Y coordinate of the bottom two vertices.
* @x12: X coordinate of the bottom-left vertex.
* @x22: X coordinate of the bottom-right vertex.
*
* A fixed-point version of cogl_trapezoid.
**/
void cogl_trapezoidx (ClutterFixed y1,
ClutterFixed x11,
ClutterFixed x21,
ClutterFixed y2,
ClutterFixed x12,
ClutterFixed x22);
#endif
/** /**
* cogl_path_fill: * cogl_path_fill:
@ -1074,7 +1036,8 @@ void cogl_path_rel_line_to (ClutterFixed x,
* *
* Adds an elliptical arc segment to the current path. A straight line * Adds an elliptical arc segment to the current path. A straight line
* segment will link the current pen location with the first vertex * segment will link the current pen location with the first vertex
* of the arc. * of the arc. If you perform a move_to to the arcs start just before
* drawing it you create a free standing arc.
**/ **/
void cogl_path_arc (ClutterFixed center_x, void cogl_path_arc (ClutterFixed center_x,
ClutterFixed center_y, ClutterFixed center_y,
@ -1209,7 +1172,6 @@ void cogl_path_rectangle (ClutterFixed x,
* @center_y: Y coordinate of the ellipse center * @center_y: Y coordinate of the ellipse center
* @radius_x: X radius of the ellipse * @radius_x: X radius of the ellipse
* @radius_y: Y radius of the ellipse * @radius_y: Y radius of the ellipse
* @angle_step: Angle increment resolution for subdivision
* *
* Clears the previously constructed shape and constructs an ellipse * Clears the previously constructed shape and constructs an ellipse
* shape. * shape.
@ -1217,8 +1179,7 @@ void cogl_path_rectangle (ClutterFixed x,
void cogl_path_ellipse (ClutterFixed center_x, void cogl_path_ellipse (ClutterFixed center_x,
ClutterFixed center_y, ClutterFixed center_y,
ClutterFixed radius_x, ClutterFixed radius_x,
ClutterFixed radius_y, ClutterFixed radius_y);
ClutterAngle angle_step);
/** /**
* cogl_path_round_rectangle: * cogl_path_round_rectangle:

View File

@ -36,10 +36,10 @@
#define _COGL_MAX_BEZ_RECURSE_DEPTH 16 #define _COGL_MAX_BEZ_RECURSE_DEPTH 16
/* these are defined in the particular backend */ /* these are defined in the particular backend(float in gl vs fixed in gles)*/
void _cogl_path_clear_nodes (); void _cogl_path_clear_nodes ();
void _cogl_path_add_node (ClutterFixed x, void _cogl_path_add_node (ClutterFixed x,
ClutterFixed y); ClutterFixed y);
void void
cogl_path_move_to (ClutterFixed x, cogl_path_move_to (ClutterFixed x,
@ -48,7 +48,10 @@ cogl_path_move_to (ClutterFixed x,
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* FIXME: handle multiple contours maybe? */ /* FIXME: handle multiple contours maybe? */
/* at the moment, a move_to is an implicit instruction to create
* a new path.
*/
_cogl_path_clear_nodes (); _cogl_path_clear_nodes ();
_cogl_path_add_node (x, y); _cogl_path_add_node (x, y);
@ -60,12 +63,12 @@ cogl_path_move_to (ClutterFixed x,
void void
cogl_path_rel_move_to (ClutterFixed x, cogl_path_rel_move_to (ClutterFixed x,
ClutterFixed y) ClutterFixed y)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_path_move_to (ctx->path_pen.x + x, cogl_path_move_to (ctx->path_pen.x + x,
ctx->path_pen.y + y); ctx->path_pen.y + y);
} }
void void
@ -91,7 +94,7 @@ cogl_path_rel_line_to (ClutterFixed x,
} }
void void
cogl_path_close () cogl_path_close (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -101,18 +104,18 @@ cogl_path_close ()
void void
cogl_line (ClutterFixed x1, cogl_path_line (ClutterFixed x1,
ClutterFixed y1, ClutterFixed y1,
ClutterFixed x2, ClutterFixed x2,
ClutterFixed y2) ClutterFixed y2)
{ {
cogl_path_move_to (x1, y1); cogl_path_move_to (x1, y1);
cogl_path_line_to (x2, y2); cogl_path_line_to (x2, y2);
} }
void void
cogl_polyline (ClutterFixed *coords, cogl_path_polyline (ClutterFixed *coords,
gint num_points) gint num_points)
{ {
gint c = 0; gint c = 0;
@ -123,10 +126,10 @@ cogl_polyline (ClutterFixed *coords,
} }
void void
cogl_polygon (ClutterFixed *coords, cogl_path_polygon (ClutterFixed *coords,
gint num_points) gint num_points)
{ {
cogl_polyline (coords, num_points); cogl_path_polyline (coords, num_points);
cogl_path_close (); cogl_path_close ();
} }
@ -144,14 +147,14 @@ cogl_path_rectangle (ClutterFixed x,
} }
static void static void
_cogl_arc (ClutterFixed center_x, _cogl_path_arc (ClutterFixed center_x,
ClutterFixed center_y, ClutterFixed center_y,
ClutterFixed radius_x, ClutterFixed radius_x,
ClutterFixed radius_y, ClutterFixed radius_y,
ClutterAngle angle_1, ClutterAngle angle_1,
ClutterAngle angle_2, ClutterAngle angle_2,
ClutterAngle angle_step, ClutterAngle angle_step,
guint move_first) guint move_first)
{ {
ClutterAngle a = 0x0; ClutterAngle a = 0x0;
ClutterAngle temp = 0x0; ClutterAngle temp = 0x0;
@ -201,10 +204,13 @@ cogl_path_arc (ClutterFixed center_x,
ClutterAngle angle_2) ClutterAngle angle_2)
{ {
ClutterAngle angle_step = 10; ClutterAngle angle_step = 10;
_cogl_arc (center_x, center_y, /* it is documented that a move to is needed to create a freestanding
radius_x, radius_y, * arc
angle_1, angle_2, */
angle_step, 0 /* no move */); _cogl_path_arc (center_x, center_y,
radius_x, radius_y,
angle_1, angle_2,
angle_step, 0 /* no move */);
} }
@ -219,54 +225,39 @@ cogl_path_arc_rel (ClutterFixed center_x,
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_arc (ctx->path_pen.x + center_x, _cogl_path_arc (ctx->path_pen.x + center_x,
ctx->path_pen.y + center_y, ctx->path_pen.y + center_y,
radius_x, radius_y, radius_x, radius_y,
angle_1, angle_2, angle_1, angle_2,
angle_step, 0 /* no move */); angle_step, 0 /* no move */);
} }
void void
cogl_arc (ClutterFixed center_x, cogl_path_ellipse (ClutterFixed center_x,
ClutterFixed center_y, ClutterFixed center_y,
ClutterFixed radius_x, ClutterFixed radius_x,
ClutterFixed radius_y, ClutterFixed radius_y)
ClutterAngle angle_1,
ClutterAngle angle_2)
{
ClutterAngle angle_step = 10;
_cogl_arc (center_x, center_y,
radius_x, radius_y,
angle_1, angle_2,
angle_step, 1 /* move first */);
}
void
cogl_ellipse (ClutterFixed center_x,
ClutterFixed center_y,
ClutterFixed radius_x,
ClutterFixed radius_y)
{ {
ClutterAngle angle_step = 10; ClutterAngle angle_step = 10;
/* FIXME: if shows to be slow might be optimized /* FIXME: if shows to be slow might be optimized
* by mirroring just a quarter of it */ * by mirroring just a quarter of it */
_cogl_arc (center_x, center_y, _cogl_path_arc (center_x, center_y,
radius_x, radius_y, radius_x, radius_y,
0, CLUTTER_ANGLE_FROM_DEG(360), 0, CLUTTER_ANGLE_FROM_DEG(360),
angle_step, 1 /* move first */); angle_step, 1 /* move first */);
cogl_path_close(); cogl_path_close();
} }
void void
cogl_round_rectangle (ClutterFixed x, cogl_path_round_rectangle (ClutterFixed x,
ClutterFixed y, ClutterFixed y,
ClutterFixed width, ClutterFixed width,
ClutterFixed height, ClutterFixed height,
ClutterFixed radius, ClutterFixed radius,
ClutterAngle arc_step) ClutterAngle arc_step)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
ClutterFixed inner_width = width - (radius << 1); ClutterFixed inner_width = width - (radius << 1);
@ -307,73 +298,6 @@ cogl_round_rectangle (ClutterFixed x,
cogl_path_close (); cogl_path_close ();
} }
#if 0
static void
_cogl_path_bezier2_sub (CoglBezQuad *quad)
{
CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH];
CoglBezQuad *qleft;
CoglBezQuad *qright;
CoglBezQuad *q;
CoglFixedVec2 mid;
CoglFixedVec2 dif;
CoglFixedVec2 c1;
CoglFixedVec2 c2;
CoglFixedVec2 c3;
gint qindex;
/* Put first curve on stack */
quads[0] = *quad;
qindex = 0;
/* While stack is not empty */
while (qindex >= 0)
{
q = &quads[qindex];
/* Calculate distance of control point from its
* counterpart on the line between end points */
mid.x = ((q->p1.x + q->p3.x) >> 1);
mid.y = ((q->p1.y + q->p3.y) >> 1);
dif.x = (q->p2.x - mid.x);
dif.y = (q->p2.y - mid.y);
if (dif.x < 0) dif.x = -dif.x;
if (dif.y < 0) dif.y = -dif.y;
/* Cancel if the curve is flat enough */
if (dif.x + dif.y <= CFX_ONE
|| qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1)
{
/* Add subdivision point (skip last) */
if (qindex == 0) return;
_cogl_path_add_node (q->p3.x, q->p3.y);
--qindex; continue;
}
/* Left recursion goes on top of stack! */
qright = q; qleft = &quads[++qindex];
/* Subdivide into 2 sub-curves */
c1.x = ((q->p1.x + q->p2.x) >> 1);
c1.y = ((q->p1.y + q->p2.y) >> 1);
c3.x = ((q->p2.x + q->p3.x) >> 1);
c3.y = ((q->p2.y + q->p3.y) >> 1);
c2.x = ((c1.x + c3.x) >> 1);
c2.y = ((c1.y + c3.y) >> 1);
/* Add left recursion onto stack */
qleft->p1 = q->p1;
qleft->p2 = c1;
qleft->p3 = c2;
/* Add right recursion onto stack */
qright->p1 = c2;
qright->p2 = c3;
qright->p3 = q->p3;
}
}
#endif
static void static void
_cogl_path_bezier3_sub (CoglBezCubic *cubic) _cogl_path_bezier3_sub (CoglBezCubic *cubic)
@ -466,32 +390,6 @@ _cogl_path_bezier3_sub (CoglBezCubic *cubic)
} }
} }
#if 0
void
cogl_path_bezier2_to (ClutterFixed x1,
ClutterFixed y1,
ClutterFixed x2,
ClutterFixed y2)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglBezQuad quad;
/* Prepare quadratic curve */
quad.p1 = ctx->path_pen;
quad.p2.x = x1;
quad.p2.y = y1;
quad.p3.x = x2;
quad.p3.y = y2;
/* Run subdivision */
_cogl_path_bezier2_sub (&quad);
/* Add last point */
_cogl_path_add_node (quad.p3.x, quad.p3.y);
ctx->path_pen = quad.p3;
}
#endif
void void
cogl_path_curve_to (ClutterFixed x1, cogl_path_curve_to (ClutterFixed x1,
@ -539,3 +437,115 @@ cogl_rel_curve_to (ClutterFixed x1,
ctx->path_pen.x + x3, ctx->path_pen.x + x3,
ctx->path_pen.y + y3); ctx->path_pen.y + y3);
} }
/* If second order beziers were needed the following code could
* be re-enabled:
*/
#if 0
static void
_cogl_path_bezier2_sub (CoglBezQuad *quad)
{
CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH];
CoglBezQuad *qleft;
CoglBezQuad *qright;
CoglBezQuad *q;
CoglFixedVec2 mid;
CoglFixedVec2 dif;
CoglFixedVec2 c1;
CoglFixedVec2 c2;
CoglFixedVec2 c3;
gint qindex;
/* Put first curve on stack */
quads[0] = *quad;
qindex = 0;
/* While stack is not empty */
while (qindex >= 0)
{
q = &quads[qindex];
/* Calculate distance of control point from its
* counterpart on the line between end points */
mid.x = ((q->p1.x + q->p3.x) >> 1);
mid.y = ((q->p1.y + q->p3.y) >> 1);
dif.x = (q->p2.x - mid.x);
dif.y = (q->p2.y - mid.y);
if (dif.x < 0) dif.x = -dif.x;
if (dif.y < 0) dif.y = -dif.y;
/* Cancel if the curve is flat enough */
if (dif.x + dif.y <= CFX_ONE
|| qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1)
{
/* Add subdivision point (skip last) */
if (qindex == 0) return;
_cogl_path_add_node (q->p3.x, q->p3.y);
--qindex; continue;
}
/* Left recursion goes on top of stack! */
qright = q; qleft = &quads[++qindex];
/* Subdivide into 2 sub-curves */
c1.x = ((q->p1.x + q->p2.x) >> 1);
c1.y = ((q->p1.y + q->p2.y) >> 1);
c3.x = ((q->p2.x + q->p3.x) >> 1);
c3.y = ((q->p2.y + q->p3.y) >> 1);
c2.x = ((c1.x + c3.x) >> 1);
c2.y = ((c1.y + c3.y) >> 1);
/* Add left recursion onto stack */
qleft->p1 = q->p1;
qleft->p2 = c1;
qleft->p3 = c2;
/* Add right recursion onto stack */
qright->p1 = c2;
qright->p2 = c3;
qright->p3 = q->p3;
}
}
void
cogl_path_curve2_to (ClutterFixed x1,
ClutterFixed y1,
ClutterFixed x2,
ClutterFixed y2)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
CoglBezQuad quad;
/* Prepare quadratic curve */
quad.p1 = ctx->path_pen;
quad.p2.x = x1;
quad.p2.y = y1;
quad.p3.x = x2;
quad.p3.y = y2;
/* Run subdivision */
_cogl_path_bezier2_sub (&quad);
/* Add last point */
_cogl_path_add_node (quad.p3.x, quad.p3.y);
ctx->path_pen = quad.p3;
}
void
cogl_rel_curve2_to (ClutterFixed x1,
ClutterFixed y1,
ClutterFixed x2,
ClutterFixed y2)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_path_curve2_to (ctx->path_pen.x + x1,
ctx->path_pen.y + y2,
ctx->path_pen.x + x2,
ctx->path_pen.y + y2);
}
#endif

View File

@ -68,55 +68,6 @@ cogl_rectanglex (ClutterFixed x,
CLUTTER_FIXED_TO_FLOAT (y + height)) ); CLUTTER_FIXED_TO_FLOAT (y + height)) );
} }
#if 0
void
cogl_trapezoid (gint y1,
gint x11,
gint x21,
gint y2,
gint x12,
gint x22)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glBegin (GL_QUADS) );
GE( glVertex2i (x11, y1) );
GE( glVertex2i (x21, y1) );
GE( glVertex2i (x22, y2) );
GE( glVertex2i (x12, y2) );
GE( glEnd () );
}
void
cogl_trapezoidx (ClutterFixed y1,
ClutterFixed x11,
ClutterFixed x21,
ClutterFixed y2,
ClutterFixed x12,
ClutterFixed x22)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glBegin (GL_QUADS) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x11),
CLUTTER_FIXED_TO_FLOAT (y1)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x21),
CLUTTER_FIXED_TO_FLOAT (y1)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x22),
CLUTTER_FIXED_TO_FLOAT (y2)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x12),
CLUTTER_FIXED_TO_FLOAT (y2)) );
GE( glEnd () );
}
#endif
void void
_cogl_path_clear_nodes () _cogl_path_clear_nodes ()
{ {
@ -219,7 +170,7 @@ _cogl_path_fill_nodes ()
} }
void void
cogl_fill () cogl_path_fill (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -231,7 +182,7 @@ cogl_fill ()
} }
void void
cogl_stroke () cogl_path_stroke (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);

View File

@ -86,54 +86,6 @@ cogl_rectanglex (ClutterFixed x,
} }
#if 0
void
cogl_trapezoid (gint y1,
gint x11,
gint x21,
gint y2,
gint x12,
gint x22)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glBegin (GL_QUADS) );
GE( glVertex2i (x11, y1) );
GE( glVertex2i (x21, y1) );
GE( glVertex2i (x22, y2) );
GE( glVertex2i (x12, y2) );
GE( glEnd () );
}
void
cogl_trapezoidx (ClutterFixed y1,
ClutterFixed x11,
ClutterFixed x21,
ClutterFixed y2,
ClutterFixed x12,
ClutterFixed x22)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glBegin (GL_QUADS) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x11),
CLUTTER_FIXED_TO_FLOAT (y1)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x21),
CLUTTER_FIXED_TO_FLOAT (y1)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x22),
CLUTTER_FIXED_TO_FLOAT (y2)) );
GE( glVertex2f (CLUTTER_FIXED_TO_FLOAT (x12),
CLUTTER_FIXED_TO_FLOAT (y2)) );
GE( glEnd () );
}
#endif
void void
_cogl_path_clear_nodes () _cogl_path_clear_nodes ()
@ -368,7 +320,7 @@ fill_close:
x0 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (iter->data)); x0 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (iter->data));
x1 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (next->data)); x1 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (next->data));
y0 = CLUTTER_INT_TO_FIXED (bounds_y + i); y0 = CLUTTER_INT_TO_FIXED (bounds_y + i);
y1 = CLUTTER_INT_TO_FIXED (bounds_y + i + 1) + 4096; y1 = CLUTTER_INT_TO_FIXED (bounds_y + i + 1) + 2048;
/* render scanlines 1.0625 high to avoid gaps when transformed */ /* render scanlines 1.0625 high to avoid gaps when transformed */
coords[span_no * 12 + 0] = x0; coords[span_no * 12 + 0] = x0;
@ -387,6 +339,10 @@ fill_close:
iter = next->next; iter = next->next;
} }
} }
for (i=0; i < bounds_h; i++)
{
g_slist_free (scanlines[i]);
}
/* render triangles */ /* render triangles */
cogl_enable (COGL_ENABLE_VERTEX_ARRAY cogl_enable (COGL_ENABLE_VERTEX_ARRAY
@ -400,7 +356,7 @@ fill_close:
} }
void void
cogl_fill () cogl_path_fill (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -412,7 +368,7 @@ cogl_fill ()
} }
void void
cogl_stroke () cogl_path_stroke (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);