aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2001-11-26 10:26:06 +0000
committerlecoanet2001-11-26 10:26:06 +0000
commit75da5487df43fd475a4c469a05815222ff175ff1 (patch)
treeb4caa84772d1b46c35df7e5514c0dfcb7b5d75f1 /generic
parentc3a8c59d28e43c81e3437d39db869849ff6fdf02 (diff)
downloadtkzinc-75da5487df43fd475a4c469a05815222ff175ff1.zip
tkzinc-75da5487df43fd475a4c469a05815222ff175ff1.tar.gz
tkzinc-75da5487df43fd475a4c469a05815222ff175ff1.tar.bz2
tkzinc-75da5487df43fd475a4c469a05815222ff175ff1.tar.xz
Traitement du clipping non rectangulaire.
Diffstat (limited to 'generic')
-rw-r--r--generic/Group.c116
-rw-r--r--generic/Item.c109
2 files changed, 146 insertions, 79 deletions
diff --git a/generic/Group.c b/generic/Group.c
index d2f290b..8a32d30 100644
--- a/generic/Group.c
+++ b/generic/Group.c
@@ -234,12 +234,12 @@ SetXShape(Item grp)
Item clip = ((GroupItem) grp)->clip;
int i, j, num_pts, max_num_pts;
ZnPos min_x, min_y, max_x, max_y;
- ZnPoly poly;
+ ZnTriStrip tristrip;
ZnPoint *p;
ZnBool simple;
ZnDim width, height;
- XPoint *xpts, *xp;
- Region reg;
+ XPoint xpts[3], *xp2, *xpts2;
+ Region reg, reg_op, reg_to;
if (!wi->has_x_shape) {
return;
@@ -259,8 +259,10 @@ SetXShape(Item grp)
/*
* Get the clip shape.
*/
- simple = clip->class->GetClipVertices(clip, &poly);
- if (simple || (poly.num_contours == 0)) {
+ tristrip.num_strips = 0;
+ tristrip.fan = False;
+ simple = clip->class->GetClipVertices(clip, &tristrip);
+ if (simple || (tristrip.num_strips == 0)) {
/*
* Nothing to do: after normalisation the rectangular shape will
* fit exactly the window. We may test here if a shape is currently
@@ -274,13 +276,17 @@ SetXShape(Item grp)
else {
/*
* First make the vertices start at zero.
+ * In case of a fan we benefit from the fact that
+ * ALL the contour vertices are included in
+ * the tristrip, so we dont need to consider the
+ * center (arc in pie slice mode).
*/
- max_x = min_x = poly.contours[0].points[0].x;
- max_y = min_y = poly.contours[0].points[0].y;
- max_num_pts = poly.contours[0].num_points;
- for (j = 0; j < poly.num_contours; j++) {
- p = poly.contours[j].points;
- num_pts = poly.contours[j].num_points;
+ max_x = min_x = tristrip.strips[0].points[0].x;
+ max_y = min_y = tristrip.strips[0].points[0].y;
+ max_num_pts = tristrip.strips[0].num_points;
+ for (j = 0; j < tristrip.num_strips; j++) {
+ p = tristrip.strips[j].points;
+ num_pts = tristrip.strips[j].num_points;
if (num_pts > max_num_pts) {
max_num_pts = num_pts;
}
@@ -299,44 +305,67 @@ SetXShape(Item grp)
}
}
}
- for (j = 0; j < poly.num_contours; j++) {
- p = poly.contours[j].points;
- num_pts = poly.contours[j].num_points;
- for (i = 0; i < num_pts; i++, p++) {
- p->x -= min_x;
- p->y -= min_y;
- }
- }
max_x -= min_x;
max_y -= min_y;
+ XShapeCombineMask(wi->dpy, wi->full_reshape?ZnWindowId(wi->win):wi->real_top,
+ ShapeBounding, 0, 0, None, ShapeSet);
+ reg = XCreateRegion();
/*
- * Now normalize the shape and map it to the window size.
+ * Now normalize the shape and map it to the window size,
+ * then Translate it in a region and apply this region to
+ * the window.
*/
width = wi->width + 2*wi->inset;
height = wi->height + 2*wi->inset;
- xpts = (XPoint *) ZnMalloc(max_num_pts * sizeof(XPoint));
- XShapeCombineMask(wi->dpy, wi->full_reshape?ZnWindowId(wi->win):wi->real_top,
- ShapeBounding, 0, 0, None, ShapeSet);
- XShapeCombineRegion(wi->dpy, wi->full_reshape?wi->real_top:ZnWindowId(wi->win),
- ShapeBounding, 0, 0, None, ShapeSet);
- for (j = 0; j < poly.num_contours; j++) {
- p = poly.contours[j].points;
- num_pts = poly.contours[j].num_points;
- for (xp = xpts, i = 0; i < num_pts; i++, p++, xp++) {
- xp->x = (short) (p->x * width / max_x);
- xp->y = (short) (p->y * height / max_y);
- }
+ for (j = 0; j < tristrip.num_strips; j++) {
+ p = tristrip.strips[j].points;
+ num_pts = tristrip.strips[j].num_points;
+
/*
- * Translate it in a region and apply this region to the window.
+ * In case of a fan we benefit from the fact that
+ * ALL the contour vertices are included in
+ * the tristrip, so we can use the corresponding
+ * polygon instead of going through all the triangles.
*/
- reg = XPolygonRegion(xpts, num_pts, EvenOddRule);
- XShapeCombineRegion(wi->dpy, wi->full_reshape?wi->real_top:ZnWindowId(wi->win),
- ShapeBounding, 0, 0, reg,
- poly.holes[j]?ShapeSubtract:ShapeUnion);
- XDestroyRegion(reg);
+ if (tristrip.fan) {
+ xp2 = xpts2 = ZnMalloc(num_pts*sizeof(XPoint));
+ for (i = 0 ; i < num_pts; i++, p++, xp2++) {
+ xp2->x = (short) ((p->x - min_x) * width / max_x);
+ xp2->y = (short) ((p->y - min_y) * height / max_y);
+ }
+ reg_op = XPolygonRegion(xpts2, num_pts, EvenOddRule);
+ reg_to = XCreateRegion();
+ XUnionRegion(reg, reg_op, reg_to);
+ XDestroyRegion(reg);
+ XDestroyRegion(reg_op);
+ reg = reg_to;
+ ZnFree(xpts2);
+ }
+ else {
+ xpts[0].x = (short) ((p->x - min_x) * width / max_x);
+ xpts[0].y = (short) ((p->y - min_y) * height / max_y);
+ p++;
+ xpts[1].x = (short) ((p->x - min_x) * width / max_x);
+ xpts[1].y = (short) ((p->y - min_y) * height / max_y);
+ p++;
+ for (i = 2 ; i < num_pts; i++, p++) {
+ xpts[2].x = (short) ((p->x - min_x) * width / max_x);
+ xpts[2].y = (short) ((p->y - min_y) * height / max_y);
+ reg_op = XPolygonRegion(xpts, 3, EvenOddRule);
+ reg_to = XCreateRegion();
+ XUnionRegion(reg, reg_op, reg_to);
+ XDestroyRegion(reg);
+ XDestroyRegion(reg_op);
+ reg = reg_to;
+ xpts[0] = xpts[1];
+ xpts[1] = xpts[2];
+ }
+ }
}
- ZnFree(xpts);
+ XShapeCombineRegion(wi->dpy, wi->full_reshape?wi->real_top:ZnWindowId(wi->win),
+ ShapeBounding, 0, 0, reg, ShapeSet);
+ XDestroyRegion(reg);
}
}
#endif
@@ -420,14 +449,14 @@ PushClip(GroupItem group,
ZnBool set_gc)
{
WidgetInfo *wi = ((Item) group)->wi;
- ZnPoly poly;
+ ZnTriStrip tristrip;
ZnBool simple;
if ((group->clip != ZN_NO_ITEM) &&
((((Item) group) != wi->top_group) || !wi->reshape)) {
- simple = group->clip->class->GetClipVertices(group->clip, &poly);
+ simple = group->clip->class->GetClipVertices(group->clip, &tristrip);
/*printf("Group: PushClip group %d\n", ((Item) group)->id);*/
- ITEM_P.PushClip(wi, &poly, simple, set_gc);
+ ITEM_P.PushClip(wi, &tristrip, simple, set_gc);
}
}
@@ -861,8 +890,10 @@ Render(Item item)
GroupItem group = (GroupItem) item;
Item current_item;
WidgetInfo *wi = item->wi;
+#if 0
ZnBBox *clip_box;
ZnBBox bbox, old_damaged_area;
+#endif
unsigned char save_alpha = wi->alpha;
wi->alpha = wi->alpha * group->alpha / 100;
@@ -1142,6 +1173,7 @@ static ItemClassStruct GROUP_ITEM_CLASS = {
NULL, /* GetFieldSet */
NULL, /* GetAnchor */
NULL, /* GetClipVertices */
+ NULL, /* GetContours */
Coords,
NULL, /* InsertChars */
NULL, /* DeleteChars */
diff --git a/generic/Item.c b/generic/Item.c
index a9a5e3a..6e9cfbf 100644
--- a/generic/Item.c
+++ b/generic/Item.c
@@ -3136,7 +3136,7 @@ CurrentClip(WidgetInfo *wi,
*/
static void
PushClip(WidgetInfo *wi,
- ZnPoly *poly,
+ ZnTriStrip *tristrip,
ZnBool simple,
ZnBool set_gc)
{
@@ -3146,14 +3146,14 @@ PushClip(WidgetInfo *wi,
ClipState *previous_clip=NULL;
Region reg, reg_op, reg_to;
XRectangle rect;
- XPoint *xpts;
+ XPoint xpts[3], *xp2, *xpts2;
- if (poly->num_contours == 0) {
+ if (tristrip->num_strips == 0) {
return;
}
- max_num_pts = poly->contours[0].num_points;
- for (j = 0; j < poly->num_contours; j++) {
- num_pts = poly->contours[j].num_points;
+ max_num_pts = tristrip->strips[0].num_points;
+ for (j = 0; j < tristrip->num_strips; j++) {
+ num_pts = tristrip->strips[j].num_points;
if (num_pts > max_num_pts) {
num_pts = max_num_pts;
}
@@ -3176,39 +3176,63 @@ PushClip(WidgetInfo *wi,
* Compute the local region.
*/
if (simple) {
- rect.x = poly->contours[0].points[0].x;
- rect.y = poly->contours[0].points[0].y;
- rect.width = poly->contours[0].points[1].x - poly->contours[0].points[0].x;
- rect.height = poly->contours[0].points[1].y - poly->contours[0].points[0].y;
+ rect.x = tristrip->strips[0].points[0].x;
+ rect.y = tristrip->strips[0].points[0].y;
+ rect.width = tristrip->strips[0].points[1].x - tristrip->strips[0].points[0].x;
+ rect.height = tristrip->strips[0].points[1].y - tristrip->strips[0].points[0].y;
reg = XCreateRegion();
XUnionRectWithRegion(&rect, reg, reg);
/*printf("Adding a simple clip: %d, %d, %d, %d\n",
rect.x, rect.y, rect.width, rect.height);*/
}
else {
- xpts = (XPoint *) ZnMalloc(max_num_pts * sizeof(XPoint));
reg = XCreateRegion();
- for (j = 0; j < poly->num_contours; j++) {
- num_pts = poly->contours[j].num_points;
- p = poly->contours[j].points;
- for (i = 0; i < num_pts; i++, p++) {
- xpts[i].x = p->x;
- xpts[i].y = p->y;
- }
- reg_op = XPolygonRegion(xpts, num_pts, EvenOddRule);
- reg_to = XCreateRegion();
- if (poly->holes[j]) {
- XSubtractRegion(reg, reg_op, reg_to);
+ for (j = 0; j < tristrip->num_strips; j++) {
+ num_pts = tristrip->strips[j].num_points;
+ p = tristrip->strips[j].points;
+ /*
+ * In case of a fan we benefit from the fact that
+ * ALL the contour vertices are included in
+ * the tristrip, so we can use the corresponding
+ * polygon instead of going through all the triangles.
+ */
+ if (tristrip->fan) {
+ xp2 = xpts2 = ZnMalloc(num_pts*sizeof(XPoint));
+ for (i = 0 ; i < num_pts; i++, p++, xp2++) {
+ xp2->x = (short) p->x;
+ xp2->y = (short) p->y;
+ }
+ reg_op = XPolygonRegion(xpts2, num_pts, EvenOddRule);
+ reg_to = XCreateRegion();
+ XUnionRegion(reg, reg_op, reg_to);
+ XDestroyRegion(reg);
+ XDestroyRegion(reg_op);
+ reg = reg_to;
+ ZnFree(xpts2);
}
else {
- XUnionRegion(reg, reg_op, reg_to);
+ xpts[0].x = p->x;
+ xpts[0].y = p->y;
+ p++;
+ xpts[1].x = p->x;
+ xpts[1].y = p->y;
+ p++;
+ for (i = 2 ; i < num_pts; i++, p++) {
+ xpts[2].x = p->x;
+ xpts[2].y = p->y;
+ reg_op = XPolygonRegion(xpts, 3, EvenOddRule);
+ reg_to = XCreateRegion();
+ XUnionRegion(reg, reg_op, reg_to);
+ XDestroyRegion(reg);
+ XDestroyRegion(reg_op);
+ reg = reg_to;
+ xpts[0] = xpts[1];
+ xpts[1] = xpts[2];
+ }
}
- XDestroyRegion(reg);
- XDestroyRegion(reg_op);
- reg = reg_to;
}
- ZnFree(xpts);
}
+
/*
* Combine with previous region if any.
*/
@@ -3238,9 +3262,7 @@ PushClip(WidgetInfo *wi,
glStencilFunc(GL_EQUAL, num_clips, 0xFF);
glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-#if 0
if (simple) {
-#endif
/* printf("Clip box is : %d, %d, %d, %d, num_clips : %d\n",
rect.x, rect.y, rect.width, rect.height, num_clips);*/
glBegin(GL_QUADS);
@@ -3249,11 +3271,24 @@ PushClip(WidgetInfo *wi,
glVertex2f(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y);
glVertex2f(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y);
glEnd();
-#if 0
}
else {
+ for (j = 0; j < tristrip->num_strips; j++) {
+ num_pts = tristrip->strips[j].num_points;
+ p = tristrip->strips[j].points;
+ if (tristrip->fan) {
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2f(tristrip->center.x, tristrip->center.y);
+ }
+ else {
+ glBegin(GL_TRIANGLE_STRIP);
+ }
+ for (i = 0; i < num_pts; i++, p++) {
+ glVertex2f(p->x, p->y);
+ }
+ glEnd();
+ }
}
-#endif
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, num_clips+1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
@@ -4061,7 +4096,7 @@ FieldsEngine(FieldSet field_set,
ZnBBox label_clip_box, clip_bbox, bbox, *global_clip_box;
ZnBBox text_bbox, clip_text_bbox;
ZnPoint pts[2];
- ZnPoly poly;
+ ZnTriStrip tristrip;
ZnPoint text_pos;
ZnBBox pm_bbox, clip_pm_bbox;
ZnBool restore = False;
@@ -4149,8 +4184,8 @@ FieldsEngine(FieldSet field_set,
/*printf("clip\n");*/
pts[0] = clip_bbox.orig;
pts[1] = clip_bbox.corner;
- POLY_CONTOUR1(&poly, pts, 2);
- PushClip(wi, &poly, True, True);
+ TRI_STRIP1(&tristrip, pts, 2);
+ PushClip(wi, &tristrip, True, True);
}
(*cb)(wi, field_ptr, &bbox, &clip_bbox, &pm_bbox, &clip_pm_bbox, &text_pos);
@@ -4709,7 +4744,7 @@ Repair(WidgetInfo *wi)
XGCValues values;
XRectangle r;
ZnPoint pts[2];
- ZnPoly poly;
+ ZnTriStrip tristrip;
if (wi->render) {
#ifdef GLX
@@ -4782,8 +4817,8 @@ Repair(WidgetInfo *wi)
r.height = wi->damaged_area.corner.y - wi->damaged_area.orig.y;
pts[0] = wi->damaged_area.orig;
pts[1] = wi->damaged_area.corner;
- POLY_CONTOUR1(&poly, pts, 2);
- PushClip(wi, &poly, True, True);
+ TRI_STRIP1(&tristrip, pts, 2);
+ PushClip(wi, &tristrip, True, True);
/* Fill the background of the double buffer pixmap. */
if (wi->tile == ZnUnspecifiedImage) {