From 75da5487df43fd475a4c469a05815222ff175ff1 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 26 Nov 2001 10:26:06 +0000 Subject: Traitement du clipping non rectangulaire. --- generic/Group.c | 116 ++++++++++++++++++++++++++++++++++++-------------------- generic/Item.c | 109 ++++++++++++++++++++++++++++++++++------------------ 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) { -- cgit v1.1