aboutsummaryrefslogtreecommitdiff
path: root/generic/Draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/Draw.c')
-rw-r--r--generic/Draw.c2245
1 files changed, 0 insertions, 2245 deletions
diff --git a/generic/Draw.c b/generic/Draw.c
deleted file mode 100644
index 3c0a37c..0000000
--- a/generic/Draw.c
+++ /dev/null
@@ -1,2245 +0,0 @@
-/*
- * Draw.c -- Implementation of common drawing routines.
- *
- * Authors : Patrick Lecoanet.
- * Creation date : Sat Dec 10 12:51:30 1994
- *
- * $Id$
- */
-
-/*
- * Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
- *
- * See the file "Copyright" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- */
-
-
-/*
- **********************************************************************************
- *
- * The algorihms used to draw the arrows, to do the 3d effects and to
- * smooth the polygons are adapted from Tk.
- *
- **********************************************************************************
- */
-
-#include "Types.h"
-#include "Draw.h"
-#include "Geo.h"
-#include "List.h"
-#include "WidgetInfo.h"
-#include "Image.h"
-#include "tkZinc.h"
-
-#include <math.h>
-#include <stdarg.h>
-
-
-#define POLYGON_RELIEF_DRAW 0
-#define POLYGON_RELIEF_RENDER 1
-#define POLYGON_RELIEF_DIST 2
-#define POLYGON_RELIEF_BBOX 3
-#define POLYGON_RELIEF_IN_BBOX 4
-
-#define TOP_CONTRAST 13
-#define BOTTOM_CONTRAST 6
-#define MAX_INTENSITY 65535
-
-#define ARROW_SHAPE_B 10.0
-#define ARROW_SHAPE_C 5.0
-#define OPEN_ARROW_SHAPE_A 4.0
-#define CLOSED_ARROW_SHAPE_A ARROW_SHAPE_B
-
-#define LIGHTNING_SHAPE_A_RATIO 10.0
-#define LIGHTNING_SHAPE_B_RATIO 8.0
-
-#define LIGHTNING_POINTS 4
-#define CORNER_POINTS 3
-#define DOUBLE_CORNER_POINTS 4
-#define STRAIGHT_POINTS 2
-
-
-/*
- **********************************************************************************
- *
- * ZnSetLineStyle --
- *
- **********************************************************************************
- */
-void
-ZnSetLineStyle(ZnWInfo *wi,
- ZnLineStyle line_style)
-{
- if (wi->render) {
-#ifdef GL
- switch (line_style) {
- case ZN_LINE_DASHED :
- glLineStipple(1, 0xF0F0);
- glEnable(GL_LINE_STIPPLE);
- break;
- case ZN_LINE_MIXED :
- glLineStipple(1, 0x27FF);
- glEnable(GL_LINE_STIPPLE);
- break;
- case ZN_LINE_DOTTED :
- glLineStipple(1, 0x18C3);
- glEnable(GL_LINE_STIPPLE);
- break;
- default:
- glDisable(GL_LINE_STIPPLE);
- }
-#endif
- }
- else {
- XGCValues values;
- static const char dashed[] = { 8 };
- static const char dotted[] = { 2, 5 };
- static const char mixed[] = { 8, 5, 2, 5 };
-
- values.line_style = LineOnOffDash;
- switch (line_style) {
- case ZN_LINE_DASHED :
- XSetDashes(wi->dpy, wi->gc, 0, dashed, 1);
- break;
- case ZN_LINE_MIXED :
- XSetDashes(wi->dpy, wi->gc, 0, mixed, 4);
- break;
- case ZN_LINE_DOTTED :
- XSetDashes(wi->dpy, wi->gc, 0, dotted, 2);
- break;
- default:
- values.line_style = LineSolid;
- break;
- }
- XChangeGC(wi->dpy, wi->gc, GCLineStyle, &values);
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnLineShapePoints --
- * Compute the points describing the given line shape between point p1 and p2.
- * If bbox is non null, it is filled with the bounding box of the shape.
- *
- * For the time being this procedure handles straight lines, right and left
- * lightnings, right and left corners, right and left double corners..
- *
- *
- * Here are the parameters for lightnings:
- *
- * *******
- * ******* *
- * ****** *
- * ****** ******+ *
- * ****** ****** * *|
- * ****** ****** * * | LIGHTNING_SHAPE_A
- * ****** ****** * * |
- * ****** * * |
- * ..******.........................+.+.*........................******..
- * | * * ******
- * | * * ****** ******
- * | * * ****** ******
- * | * * ****** ******
- * | * ******* ******
- * | * ******
- * | * ******
- * | ********
- * | | | |
- * | |----| | LIGHTNING_SHAPE_B
- * | |
- * |--------------------------------| LENGTH / 2
- *
- **********************************************************************************
- */
-void
-ZnLineShapePoints(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim line_width,
- ZnLineShape shape,
- ZnBBox *bbox,
- ZnList to_points)
-{
- ZnPoint *points;
- unsigned int num_points, i;
-
- /*
- * Compute all line points according to shape.
- */
- if ((shape == ZN_LINE_LEFT_LIGHTNING) ||
- (shape == ZN_LINE_RIGHT_LIGHTNING)) {
- double alpha, theta;
- double length, length2;
- double shape_a, shape_b;
- double dx, dy;
- double temp;
-
- num_points = LIGHTNING_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[3] = *p2;
-
- dx = p2->x - p1->x;
- dy = p2->y - p1->y;
- length = hypot(dx, dy);
- shape_a = length/LIGHTNING_SHAPE_A_RATIO + line_width/2.0;
- shape_b = length/LIGHTNING_SHAPE_B_RATIO + line_width/2.0;
-
- if (shape == ZN_LINE_LEFT_LIGHTNING)
- alpha = atan2(shape_a, shape_b);
- else
- alpha = -atan2(shape_a, shape_b);
- length2 = hypot(shape_a, shape_b);
- theta = atan2(-dy, dx);
-
- dx = p1->x + dx/2;
- dy = p1->y + dy/2;
- temp = cos(theta + alpha) * length2;
- points[1].x = dx + temp;
- points[2].x = dx - temp;
- temp = sin(theta + alpha) * length2;
- points[1].y = dy - temp;
- points[2].y = dy + temp;
- }
- else if (shape == ZN_LINE_LEFT_CORNER ||
- shape == ZN_LINE_RIGHT_CORNER) {
- num_points = CORNER_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[2] = *p2;
-
- if (shape == ZN_LINE_LEFT_CORNER) {
- points[1].x = p1->x;
- points[1].y = p2->y;
- }
- else {
- points[1].x = p2->x;
- points[1].y = p1->y;
- }
- }
- else if (shape == ZN_LINE_DOUBLE_LEFT_CORNER ||
- shape == ZN_LINE_DOUBLE_RIGHT_CORNER) {
- int dx, dy;
-
- num_points = DOUBLE_CORNER_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[3] = *p2;
-
- if (shape == ZN_LINE_DOUBLE_LEFT_CORNER) {
- dy = (int) (p2->y - p1->y);
- points[1].x = p1->x;
- points[2].x = p2->x;
- points[1].y = points[2].y = p1->y + dy/2;
- }
- else {
- dx = (int) (p2->x - p1->x);
- points[1].x = points[2].x = p1->x + dx/2;
- points[1].y = p1->y;
- points[2].y = p2->y;
- }
- }
- else /* if (shape) == ZN_LINE_STRAIGHT) */ {
- num_points = STRAIGHT_POINTS;
- ZnListAssertSize(to_points, num_points);
- points = (ZnPoint *) ZnListArray(to_points);
-
- points[0] = *p1;
- points[1] = *p2;
- }
-
- /*
- * Fill in the bbox, if requested.
- */
- if (bbox) {
- ZnResetBBox(bbox);
- for (i = 0; i < num_points; i++) {
- ZnAddPointToBBox(bbox, points[i].x, points[i].y);
- }
-
- /* Enlarge to take line_width into account. */
- if (line_width > 1) {
- ZnDim lw_2 = (line_width+1)/2;
-
- bbox->orig.x -= lw_2;
- bbox->orig.y -= lw_2;
- bbox->corner.x += lw_2;
- bbox->corner.y += lw_2;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawLineShape --
- * Draw a line given the points describing its path. It is designed to work
- * with GetLineShape albeit it does fairly trivial things. In the future some
- * shapes might need cooperation between the two and the clients will be ready
- * for that.
- *
- *
- **********************************************************************************
- */
-void
-ZnDrawLineShape(ZnWInfo *wi,
- ZnPoint *p,
- unsigned int num_p,
- ZnLineStyle line_style,
- int foreground_pixel,
- ZnDim line_width,
- ZnLineShape shape)
-{
- XPoint *xpoints;
- unsigned int i;
- XGCValues values;
-
- /*
- * Setup GC.
- */
- ZnSetLineStyle(wi, line_style);
- values.foreground = foreground_pixel;
- values.line_width = (line_width == 1) ? 0 : (int) line_width;
- values.fill_style = FillSolid;
- values.join_style = JoinRound;
- values.cap_style = CapRound;
- XChangeGC(wi->dpy, wi->gc,
- GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
- ZnListAssertSize(ZnWorkXPoints, num_p);
- xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
- for (i = 0; i < num_p; i++) {
- xpoints[i].x = (short) p[i].x;
- xpoints[i].y = (short) p[i].y;
- }
- XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xpoints, (int) num_p, CoordModeOrigin);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetLineEnd --
- * Compute the points describing the given line end style at point p1 for
- * the line p1,p2. Point p1 is adjusted to fit the line end.
- * If bbox is non null, it is filled with the bounding box of the end.
- *
- * For the time being this procedure handles open/filled arrows.
- *
- * Here are the parameters describing arrows.
- *
- * * | ARROW_SHAPE_C
- * ** |
- * * ***************************
- * * *
- * * * +p1 +p2
- * | * |*
- * | * ***************************
- * | | **
- * | | *
- * | | |
- * |---| | ARROW_SHAPE_A
- * | |
- * |-------| ARROW_SHAPE_B
- *
- **********************************************************************************
- */
-void
-ZnGetLineEnd(ZnPoint *p1,
- ZnPoint *p2,
- ZnDim line_width,
- int cap_style,
- ZnLineEnd end_style,
- ZnPoint *points)
-{
- ZnReal dx, dy, length, temp, backup;
- ZnReal frac_height, sin_theta, cos_theta;
- ZnReal vert_x, vert_y;
- ZnReal shape_a, shape_b, shape_c;
-
- if (end_style != NULL) {
- shape_a = end_style->shape_a + 0.001;
- shape_b = end_style->shape_b + 0.001;
- shape_c = end_style->shape_c + line_width/2.0 + 0.001;
-
- frac_height = (line_width/2.0) / shape_c;
- dx = p1->x - p2->x;
- dy = p1->y - p2->y;
- length = hypot(dx, dy);
- if (length == 0) {
- sin_theta = cos_theta = 0.0;
- }
- else {
- sin_theta = dy/length;
- cos_theta = dx/length;
- }
-
- if (cap_style != CapProjecting) {
- temp = frac_height;
- }
- else {
- temp = line_width / shape_c;
- }
- backup = temp * shape_b + shape_a * (1.0 - temp) / 2.0;
- points[0].x = points[5].x = p1->x + backup * cos_theta;
- points[0].y = points[5].y = p1->y + backup * sin_theta;
-
- vert_x = points[0].x - shape_a*cos_theta;
- vert_y = points[0].y - shape_a*sin_theta;
- temp = shape_c*sin_theta;
- points[1].x = ZnNearestInt(points[0].x - shape_b*cos_theta + temp);
- points[4].x = ZnNearestInt(points[1].x - 2*temp);
- temp = shape_c*cos_theta;
- points[1].y = ZnNearestInt(points[0].y - shape_b*sin_theta - temp);
- points[4].y = ZnNearestInt(points[1].y + 2*temp);
- points[2].x = ZnNearestInt(points[1].x*frac_height + vert_x*(1.0-frac_height));
- points[2].y = ZnNearestInt(points[1].y*frac_height + vert_y*(1.0-frac_height));
- points[3].x = ZnNearestInt(points[4].x*frac_height + vert_x*(1.0-frac_height));
- points[3].y = ZnNearestInt(points[4].y*frac_height + vert_y*(1.0-frac_height));
- }
-}
-
-static ZnReal
-SegmentPosInRelief(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- int light_angle)
-{
- ZnReal angle, angle_step, origin, position;
- int num_colors, color_index;
-
- num_colors = ZN_RELIEF_STEPS*2+1;
- angle_step = M_PI / (num_colors-1);
- origin = -(ZnDegRad(light_angle))-(angle_step/2.0);
- if (relief == ZN_RELIEF_SUNKEN) {
- origin += M_PI;
- }
-
- angle = ZnProjectionToAngle(y1 - y2, x2 - x1) + M_PI - origin;
- while (angle < 0.0) {
- angle += 2*M_PI;
- }
- while (angle > 2*M_PI) {
- angle -= 2*M_PI;
- }
-
- color_index = (int) (angle/angle_step);
- if (color_index > num_colors-1) {
- color_index = 2*(num_colors-1)-color_index;
- }
- if ((color_index < 0) || (color_index >= num_colors)) {
- fprintf(stderr, "Color index out of gradient (should not happen).\n");
- if (color_index < 0) {
- color_index = 0;
- }
- if (color_index >= num_colors) {
- color_index = num_colors-1;
- }
- }
- position = 100*color_index/num_colors;
- /*printf("position %g, angle %g(%g), origin %g\n",
- position,
- RadianToDegrees(angle),
- angle,
- RadianToDegrees(origin));*/
- return position;
-}
-
-/*
- * ReliefColorOfSegment --
- * ReliefPixelOfSegment --
- */
-static XColor *
-ReliefColorOfSegment(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- int light_angle)
-{
- return ZnGetGradientColor(gradient,
- SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle),
- NULL);
-}
-
-static int
-ReliefPixelOfSegment(ZnReal x1,
- ZnReal y1,
- ZnReal x2,
- ZnReal y2,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- int light_angle)
-{
- return ZnGetGradientPixel(gradient,
- SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle));
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawRectangleRelief --
- * Draw the bevels inside bbox.
- *
- **********************************************************************************
- */
-void
-ZnDrawRectangleRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- XRectangle *bbox,
- ZnDim line_width)
-{
- XPoint bevel[4];
-
- /*
- * If we haven't enough space to draw, exit.
- */
- if ((bbox->width < 2*line_width) || (bbox->height < 2*line_width)) {
- return;
- }
-
- /*
- * Grooves and ridges are drawn with two recursives calls with
- * half the width of the original one.
- */
- if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
- ZnDim new_line_width;
- unsigned int offset;
- XRectangle internal_bbox;
-
- new_line_width = line_width/2.0;
- offset = (unsigned) (line_width - new_line_width);
- ZnDrawRectangleRelief(wi,
- (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED),
- gradient, bbox, new_line_width);
- internal_bbox = *bbox;
- internal_bbox.x += offset;
- internal_bbox.y += offset;
- internal_bbox.width -= offset*2;
- internal_bbox.height -= offset*2;
- ZnDrawRectangleRelief(wi,
- (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN),
- gradient, &internal_bbox, new_line_width);
- return;
- }
-
- XSetFillStyle(wi->dpy, wi->gc, FillSolid);
-
- bevel[0].x = bbox->x;
- bevel[0].y = bevel[1].y = bbox->y;
- bevel[1].x = bbox->x + bbox->width;
- bevel[2].y = bevel[3].y = bbox->y + (short) line_width;
- bevel[2].x = bevel[1].x - (short) line_width;
- bevel[3].x = bevel[0].x + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].y += bbox->height;
- bevel[2].y = bevel[1].y - (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].x -= bbox->width;
- bevel[2].x = bevel[1].x + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-
- bevel[0] = bevel[1];
- bevel[3] = bevel[2];
- bevel[1].x = bbox->x;
- bevel[1].y = bbox->y;
- bevel[2].x = bevel[3].x;
- bevel[2].y = bbox->y + (short) line_width;
- XSetForeground(wi->dpy, wi->gc,
- ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
- (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
- relief, gradient, wi->light_angle));
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
-}
-
-
-typedef struct {
- ZnWInfo *wi;
- ZnPoint *pp;
- ZnPoint *p0;
- ZnPoint *p1;
- double dist;
- ZnBBox *bbox;
- ZnReliefStyle relief;
- ZnGradient *gradient;
- unsigned short alpha;
- ZnBool smooth;
- int result;
- int count;
- ZnBool toggle;
-} PolygonData;
-
-static void
-DoPolygon(ZnPoint *p,
- unsigned int num_points,
- ZnDim line_width,
- ZnBool (*cb)(ZnPoint *bevels, PolygonData *pd),
- PolygonData *pd)
-{
- int i;
- unsigned int processed_points;
- ZnPoint *p1, *p11=NULL, *p2;
- ZnPoint pp1, pp2, new_pp1, new_pp2;
- ZnPoint perp, c, shift1, shift2;
- ZnPoint bevel_points[4];
- ZnBool folded, closed, colinear;
- ZnReal dx, dy;
-
- if (num_points < 2) {
- return;
- }
-
- /*
- * If the polygon is closed (last point is the same as first) open it by
- * dropping the last point. The algorithm closes the path automatically.
- * We remember this to decide if we draw the last bevel or not and if we
- * need to generate ends perpendicular to the path..
- */
- closed = False;
- if ((p->x == p[num_points-1].x) && (p->y == p[num_points-1].y)) {
- closed = True;
- num_points--;
- }
- /*printf("num_points=%d(%s)\n", num_points, closed?"closed":"");*/
-
- /*
- * We loop on all vertices of the polygon.
- * At each step we try to compute the corresponding border
- * corner `corner'. Then we build a polygon for the bevel.
- * Things look like this:
- *
- * bevel[1] /
- * * /
- * | /
- * | /
- * pp1 * * p[i-1]
- * | | bevel[0]
- * | |
- * | |
- * | | bevel[3]
- * | | p[i]
- * | | p1 p2
- * pp2 * *--------------------*
- * |
- * |
- * corner *----*--------------------*
- * bevel[2] new_pp1 new_pp2
- *
- * pp1 and pp2 are the ends of a segment // to p1 p2 at line_width
- * from it. These points are *NOT* necessarily on the perpendicular
- * going through p1 or p2.
- * This loop needs a bootstrap phase of two iterations (i.e we need to
- * process two points). This is why we start at the point before the last
- * and then wrap to the first point.
- * The algorithm discards any duplicate contiguous points.
- * It makes a special case if two consecutives edges are folded:
- *
- * bevel[1] pp1 pp2 a bevel[2]
- * *-----------*--------------*----------*
- * \
- * \
- * p[i-1] \ bevel[3]
- * *--------*-------------------------*---* corner
- * bevel[0] p2 p1 /
- * /
- * /
- * ----------*-----------*-------------*
- * new_pp1 new_pp2 c
- *
- * In such a case we need to compute a, c, corner from pp1, pp2, new_pp1
- * and new_pp2. We compute the perpendicular to p1,p2 through p1, intersect
- * it with pp1,pp2 to obtain a, intersect it with new_pp1, new_pp2 to
- * obtain c, shift a,c and intersect it with p1,p2 to obtain corner.
- *
- */
-
- processed_points = 0;
- if (!closed) {
- i = 0;
- p1 = p;
- }
- else {
- i = -2;
- p1 = &p[num_points-2];
- }
-
- for (p2 = p1+1; i < (int) num_points; i++, p2++) {
- /*
- * When it is time to wrap, do it
- */
- if ((i == -1) || (i == (int) num_points-1)) {
- p2 = p;
- }
- /*
- * Skip over close vertices.
- */
- dx = p2->x - p1->x;
- dy = p2->y - p1->y;
- if ((ABS(dx) < 1.0) && (ABS(dy) < 1.0)) {
- continue;
- }
-
- ZnShiftLine(p1, p2, line_width, &new_pp1, &new_pp2);
- bevel_points[3] = *p1;
- folded = False;
- colinear = False;
- /*
- * The first two cases are for `open' polygons. We compute
- * a bevel closure that is perpendicular to the path.
- */
- if ((processed_points == 0) && !closed) {
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
- }
- else if ((processed_points == num_points-1) && !closed) {
- perp.x = p1->x + (p11->y - p1->y);
- perp.y = p1->y - (p11->x - p1->x);
- ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);
- }
- else if (processed_points >= 1) {
- ZnReal dotp, dist, odx, ody;
-
- /*
- * The dot product of the two faces tell if the are
- * folded or colinear. The
- */
- odx = p11->x - p1->x;
- ody = p11->y - p1->y;
- dotp = odx*dx + ody*dy;
- dist = ZnLineToPointDist(p11, p2, p1, NULL);
- if ((dist < 4.0) && (dotp <= 0)) {
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
- colinear = True;
- }
- else {
- folded = !ZnIntersectLines(&new_pp1, &new_pp2, &pp1, &pp2, &bevel_points[2]);
- /*printf("new_pp1 %g@%g, new_pp2 %g@%g, pp1 %g@%g, pp2 %g@%g, inter %g@%g\n",
- new_pp1.x, new_pp1.y, new_pp2.x, new_pp2.y,
- pp1.x, pp1.y, pp2.x, pp2.y,
- bevel_points[2].x, bevel_points[2].y);*/
- folded = folded && (dotp < 0);
- if (folded) {
- /*printf("DoPolygonRelief: folded edges detected, %g@%g, %g@%g, %g@%g, %g@%g\n",
- pp1.x, pp1.y, pp2.x, pp2.y, new_pp1.x, new_pp1.y,
- new_pp2.x, new_pp2.y);*/
- perp.x = p1->x + (p2->y - p1->y);
- perp.y = p1->y - (p2->x - p1->x);
- ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);
- ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &c);
- ZnShiftLine(p1, &perp, line_width, &shift1, &shift2);
- ZnIntersectLines(p1, p2, &shift1, &shift2, &bevel_points[3]);
- }
- }
- }
-
- if ((processed_points >= 2) || (!closed && (processed_points == 1))) {
- if ((processed_points == num_points-1) && !closed) {
- pd->p0 = pd->p1 = NULL;
- }
- else {
- pd->p0 = p1;
- pd->p1 = p2;
- }
- if ((*cb)(bevel_points, pd)) {
- return;
- }
- }
-
- p11 = p1;
- p1 = p2;
- pp1 = new_pp1;
- pp2 = new_pp2;
- bevel_points[0] = bevel_points[3];
- if (folded) {
- bevel_points[1] = c;
- }
- else if ((processed_points >= 1) || !closed) {
- bevel_points[1] = bevel_points[2];
- }
-
- processed_points++;
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnGetPolygonReliefBBox --
- * Returns the bevelled polygon bounding box.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonBBoxCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- int i;
-
- for (i = 0; i < 4; i++) {
- ZnAddPointToBBox(pd->bbox, bevels[i].x, bevels[i].y);
- }
- return 0;
-}
-
-void
-ZnGetPolygonReliefBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnBBox *bbox)
-{
- PolygonData pd;
-
- pd.bbox = bbox;
- ZnResetBBox(bbox);
- DoPolygon(points, num_points, line_width, PolygonBBoxCB, &pd);
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPolygonReliefInBBox --
- * Returns (-1) if the relief is entirely outside the bbox, (1) if it is
- * entirely inside or (0) if in between
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonInBBoxCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- if (pd->count == 0) {
- pd->count++;
- pd->result = ZnPolygonInBBox(bevels, 4, pd->bbox, NULL);
- if (pd->result == 0) {
- return 1;
- }
- }
- else {
- if (ZnPolygonInBBox(bevels, 4, pd->bbox, NULL) != pd->result) {
- pd->result = 0;
- return 1;
- }
- }
- return 0;
-}
-
-int
-ZnPolygonReliefInBBox(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnBBox *area)
-{
- PolygonData pd;
-
- pd.bbox = area;
- pd.count = 0;
-
- DoPolygon(points, num_points, line_width, PolygonInBBoxCB, &pd);
-
- return pd.result;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnPolygonReliefToPointDist --
- * Returns the distance between the given point and
- * the bevelled polygon.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonDistCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- double new_dist;
-
- new_dist = ZnPolygonToPointDist(bevels, 4, pd->pp);
- if (new_dist < 0.0) {
- new_dist = 0.0;
- }
- if (new_dist < pd->dist) {
- pd->dist = new_dist;
- }
- return 0;
-}
-
-double
-ZnPolygonReliefToPointDist(ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnPoint *pp)
-{
- PolygonData pd;
-
- pd.dist = 1.0e40;
- pd.pp = pp;
- DoPolygon(points, num_points, line_width, PolygonDistCB, &pd);
-
- return pd.dist;
-}
-
-
-/*
- **********************************************************************************
- *
- * ZnDrawPolygonRelief --
- * Draw the bevels around path.
- *
- **********************************************************************************
- */
-static ZnBool
-PolygonDrawCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- ZnWInfo *wi = pd->wi;
- XPoint bevel_xpoints[5];
- XGCValues values;
- int j;
-
- values.foreground = ReliefPixelOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- pd->relief, pd->gradient,
- pd->wi->light_angle);
-
- values.fill_style = FillSolid;
- XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
-
- for (j = 0; j < 4; j++) {
- bevel_xpoints[j].x = ZnNearestInt(bevels[j].x);
- bevel_xpoints[j].y = ZnNearestInt(bevels[j].y);
- }
-
- XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4,
- Convex, CoordModeOrigin);
-
- return 0;
-}
-
-void
-ZnDrawPolygonRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width)
-{
- PolygonData pd;
-
- pd.wi = wi;
- pd.gradient = gradient;
-
- /*
- * Grooves and ridges are drawn with two calls. The first
- * with the original width, the second with half the width.
- */
- if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
- pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN;
- DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
- pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED;
- DoPolygon(points, num_points, line_width/2, PolygonDrawCB, &pd);
- }
- else {
- pd.relief = relief;
- DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
- }
-}
-
-/*
- **********************************************************************************
- *
- * ZnRenderPolygonRelief --
- * Draw the bevels around path using alpha enabled rendering.
- *
- **********************************************************************************
- */
-#ifdef GL
-static ZnBool
-PolygonRenderCB(ZnPoint *bevels,
- PolygonData *pd)
-{
- int i;
- ZnPoint p[6];
- XColor *c[8];
- XColor *color = ZnGetGradientColor(pd->gradient, 51.0, NULL);
- ZnReliefStyle relief, int_relief;
- ZnBool two_faces, round, rule;
-
- rule = pd->relief & ZN_RELIEF_RULE;
- round = pd->relief & ZN_RELIEF_ROUND;
- two_faces = pd->relief & ZN_RELIEF_TWO_FACES;
- relief = pd->relief & ZN_RELIEF_MASK;
- for (i = 0; i < 4; i++) {
- p[i].x = ZnNearestInt(bevels[i].x);
- p[i].y = ZnNearestInt(bevels[i].y);
- }
-
- if (two_faces) {
- p[4].x = (p[0].x+p[1].x)/2;
- p[4].y = (p[0].y+p[1].y)/2;
- p[5].x = (p[2].x+p[3].x)/2;
- p[5].y = (p[2].y+p[3].y)/2;
-
- if (relief == ZN_RELIEF_SUNKEN) {
- int_relief = ZN_RELIEF_RAISED;
- }
- else {
- int_relief = ZN_RELIEF_SUNKEN;
- }
- c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- relief, pd->gradient,
- pd->wi->light_angle);
- c[4]=c[5]=c[6]=c[7] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- int_relief, pd->gradient,
- pd->wi->light_angle);
- if (pd->smooth && pd->p0) {
- c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- relief, pd->gradient,
- pd->wi->light_angle);
- c[6]=c[7] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- int_relief, pd->gradient,
- pd->wi->light_angle);
- }
- if (round) {
- if (!rule) {
- c[0]=c[3]=c[5]=c[6]=color;
- }
- else {
- c[1]=c[2]=c[4]=c[7]=color;
- }
- }
- glBegin(GL_QUADS);
- glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
- glVertex2d(p[0].x, p[0].y);
-
- glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
- glVertex2d(p[4].x, p[4].y);
-
- glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
- glVertex2d(p[5].x, p[5].y);
-
- glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
- glVertex2d(p[3].x, p[3].y);
-
- glColor4us(c[4]->red, c[4]->green, c[4]->blue, pd->alpha);
- glVertex2d(p[4].x, p[4].y);
-
- glColor4us(c[5]->red, c[5]->green, c[5]->blue, pd->alpha);
- glVertex2d(p[1].x, p[1].y);
-
- glColor4us(c[6]->red, c[6]->green, c[6]->blue, pd->alpha);
- glVertex2d(p[2].x, p[2].y);
-
- glColor4us(c[7]->red, c[7]->green, c[7]->blue, pd->alpha);
- glVertex2d(p[5].x, p[5].y);
- glEnd();
- }
- else { /* Single face */
- c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
- bevels[3].x, bevels[3].y,
- relief, pd->gradient,
- pd->wi->light_angle);
- if (pd->smooth && pd->p0) {
- c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
- pd->p1->x, pd->p1->y,
- relief, pd->gradient,
- pd->wi->light_angle);
- }
- if (round) {
- c[1]=c[2] = color;
- }
- glBegin(GL_QUADS);
- glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
- glVertex2d(p[0].x, p[0].y);
- glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
- glVertex2d(p[1].x, p[1].y);
- glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
- glVertex2d(p[2].x, p[2].y);
- glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
- glVertex2d(p[3].x, p[3].y);
- glEnd();
- }
-
- return 0;
-}
-
-void
-ZnRenderPolygonRelief(ZnWInfo *wi,
- ZnReliefStyle relief,
- ZnGradient *gradient,
- ZnBool smooth,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width)
-{
- PolygonData pd;
-
- pd.wi = wi;
- pd.gradient = gradient;
- ZnGetGradientColor(gradient, 0.0, &pd.alpha);
- pd.alpha = ZnComposeAlpha(pd.alpha, wi->alpha);
- pd.smooth = smooth;
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- pd.relief = relief;
- pd.count = 0;
-
- DoPolygon(points, num_points, line_width, PolygonRenderCB, &pd);
-}
-
-void
-ZnRenderPolyline(ZnWInfo *wi,
- ZnPoint *points,
- unsigned int num_points,
- ZnDim line_width,
- ZnLineStyle line_style,
- int cap_style,
- int join_style,
- ZnLineEnd first_end,
- ZnLineEnd last_end,
- ZnGradient *gradient)
-{
- int num_clips = ZnListSize(wi->clip_stack);
- ZnPoint end_points[ZN_LINE_END_POINTS];
- ZnBool need_rcaps, thin, closed, transparent;
- int pass, num_passes, i, k, m;
- ZnPoint c1, c2;
- XColor *color;
- unsigned short alpha;
- ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
-
- /*
- * The code below draws curves thiner than the min
- * of GL_SMOOTH_LINE_WIDTH_RANGE and GL_SMOOTH_POINT_SIZE_RANGE
- * with a mix of anti-aliased lines and points. The curves that
- * are thicker are drawn using regular polygons.
- * BUG: The joints are drawn only rounded.
- * The caps can be either round or butt (but not projecting).
- */
- thin = ((line_width <= ce->max_line_width) &&
- (line_width <= ce->max_point_width));
- closed = (points->x == points[num_points-1].x) && (points->y == points[num_points-1].y);
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
- ZnSetLineStyle(wi, line_style);
- glLineWidth((GLfloat) line_width);
- /*
- * Do not use joints under this transparency value.
- */
- transparent = alpha < (65535 * 0.8);
- if (thin && transparent) {
- /*
- * This makes a special case for transparent lines.
- * In this case we need to avoid drawing twice a
- * single pixel. To achieve this we use the stencil
- * buffer to protect already drawn pixels, unfortunately
- * using antialiasing write in the stencil even if
- * the pixel area is not fully covered resulting in
- * a crack that can't be covered by points later on.
- * To handle this case we need to disable the stencil
- * which in turn result in erroneous alpha coverage.
- *
- * We have chosen to drawn transparent lines with a
- * correct coverage but NOT antialiased.
- */
- glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
- glDisable(GL_LINE_SMOOTH);
- }
- else {
- glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
- }
-
- num_passes = 1;
- if (transparent) {
- num_passes = 2;
- }
-
- for (pass = 0; pass < num_passes; pass++) {
- if (transparent) {
- if (pass == 0) {
- ZnGlStartClip(num_clips, True);
- }
- else {
- ZnGlRestoreStencil(num_clips, False);
- }
- }
- if (first_end) {
- ZnGetLineEnd(&points[0], &points[1], line_width, cap_style,
- first_end, end_points);
- glBegin(GL_TRIANGLE_FAN);
- for (m = 0; m < ZN_LINE_END_POINTS; m++) {
- glVertex2d(end_points[m].x, end_points[m].y);
- }
- glEnd();
- }
- if (last_end) {
- ZnGetLineEnd(&points[num_points-1], &points[num_points-2],
- line_width, cap_style, last_end, end_points);
- glBegin(GL_TRIANGLE_FAN);
- for (m = 0; m < ZN_LINE_END_POINTS; m++) {
- glVertex2d(end_points[m].x, end_points[m].y);
- }
- glEnd();
- }
- if (thin) {
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < (int) num_points; i++) {
- glVertex2d(points[i].x, points[i].y);
- }
- glEnd();
- }
- else {
- glBegin(GL_QUADS);
- for (i = 0; i < (int) num_points-1; i++) {
- ZnGetButtPoints(&points[i+1], &points[i], line_width, False, &c1, &c2);
- glVertex2d(c1.x, c1.y);
- glVertex2d(c2.x, c2.y);
- ZnGetButtPoints(&points[i], &points[i+1], line_width, False, &c1, &c2);
- glVertex2d(c1.x, c1.y);
- glVertex2d(c2.x, c2.y);
- }
- glEnd();
- }
-
- /* if (pass == 0) {
- ZnGlRenderClipped();
- }
- else {
- ZnGlEndClip(num_clips);
- break;
- }*/
- need_rcaps = ((line_width > 1) && (cap_style == CapRound));
- i = 0;
- k = num_points;
- if (closed) {
- k--;
- }
- if (!need_rcaps || first_end) {
- i++;
- }
- if ((!need_rcaps && !closed) || last_end) {
- k--;
- }
-
- if (thin) {
- glBegin(GL_POINTS);
- for ( ; i < k; i++) {
- glVertex2d(points[i].x, points[i].y);
- }
- glEnd();
- }
- else {
- int num_cpoints;
- ZnReal lw_2 = line_width / 2.0;
- ZnPoint *cpoints = ZnGetCirclePoints(3, ZN_CIRCLE_COARSE,
- 0.0, 2*M_PI, &num_cpoints, NULL);
-
- for ( ; i < k; i++) {
- glBegin(GL_TRIANGLE_FAN);
- glVertex2d(points[i].x, points[i].y);
- for (m = 0; m < num_cpoints; m++) {
- glVertex2d(points[i].x + cpoints[m].x*lw_2,
- points[i].y + cpoints[m].y*lw_2);
- }
- glEnd();
- }
- }
- }
-
- ZnGlEndClip(num_clips);
- if (thin) {
- glEnable(GL_LINE_SMOOTH);
- }
-}
-
-
-void
-ZnRenderIcon(ZnWInfo *wi,
- ZnImage image,
- ZnGradient *gradient,
- ZnPoint *origin,
- ZnBool modulate)
-{
- ZnPoint p[4];
- int width, height;
-
- ZnSizeOfImage(image, &width, &height);
- p[0] = *origin;
- p[1].x = origin->x;
- p[1].y = origin->y + height;
- p[2].x = origin->x + width;
- p[2].y = p[1].y;
- p[3].x = p[2].x;
- p[3].y = origin->y;
- ZnRenderImage(wi, image, gradient, p, modulate);
-}
-
-
-void
-ZnRenderImage(ZnWInfo *wi,
- ZnImage image,
- ZnGradient *gradient,
- ZnPoint *quad,
- ZnBool modulate)
-{
- XColor *color;
- unsigned short alpha;
- ZnReal t, s;
- GLuint texobj;
-
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- texobj = ZnImageTex(image, &t, &s);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texobj);
- if (modulate) {
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- else {
- glColor4us(65535, 65535, 65535, alpha);
- }
- glBegin(GL_QUADS);
- glTexCoord2d(0.0, 0.0);
- glVertex2d(quad[0].x, quad[0].y);
- glTexCoord2d(0.0, t);
- glVertex2d(quad[1].x, quad[1].y);
- glTexCoord2d(s, t);
- glVertex2d(quad[2].x, quad[2].y);
- glTexCoord2d(s, 0.0);
- glVertex2d(quad[3].x, quad[3].y);
- glEnd();
- glDisable(GL_TEXTURE_2D);
-}
-
-void
-ZnRenderTile(ZnWInfo *wi,
- ZnImage tile,
- ZnGradient *gradient,
- void (*cb)(void *),
- void *closure,
- ZnPoint *quad) /* Right now it's a ZnBBox */
-{
- ZnReal x, y, nx, ny, lx, ly, s, t, tiles, tilet;
- int width, height, num_clips = ZnListSize(wi->clip_stack);
- unsigned short alpha;
- GLuint texobj;
- XColor *color;
-
- if (gradient) {
- color = ZnGetGradientColor(gradient, 0.0, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
- }
- else {
- color = NULL;
- alpha = ZnComposeAlpha(100, wi->alpha);
- }
-
- if (cb) {
- /*
- * Setup the stencil buffer with the shape to be drawn.
- */
- ZnGlStartClip(num_clips, False);
-
- (*cb)(closure);
- ZnGlRestoreStencil(num_clips, True);
- }
-
- /*
- * Then texture map the quad through the shape.
- * The rectangle is drawn using quads, each
- * quad matching the size of the texture tile.
- */
- ZnSizeOfImage(tile, &width, &height);
- texobj = ZnImageTex(tile, &tilet, &tiles);
- glEnable(GL_TEXTURE_2D);
- if (color && ZnImageIsBitmap(tile)) {
- glColor4us(color->red, color->green, color->blue, alpha);
- }
- else {
- glColor4us(65535, 65535, 65535, alpha);
- }
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, texobj);
-
- y = quad[0].y;
- lx = quad[1].x;
- ly = quad[1].y;
- glBegin(GL_QUADS);
- do {
- x = quad[0].x;
- t = 1.0;
- ny = y + height;
- if (ny > ly) {
- ny = ly;
- t = (ly - y) / (ZnReal) height;
- }
- t *= tilet;
- do {
- s = 1.0;
- nx = x + width;
- if (nx > lx) {
- nx = lx;
- s = (lx - x) / (ZnReal) width;
- }
- s *= tiles;
- glTexCoord2d(0.0, 0.0);
- glVertex2d(x, y);
- glTexCoord2d(0.0, t);
- glVertex2d(x, ny);
- glTexCoord2d(s, t);
- glVertex2d(nx, ny);
- glTexCoord2d(s, 0.0);
- glVertex2d(nx, y);
- x = nx;
- }
- while (x != lx);
- y = ny;
- }
- while (y != ly);
- glEnd();
-
- if (cb) {
- ZnGlEndClip(num_clips);
- }
- glDisable(GL_TEXTURE_2D);
-}
-
-
-static void
-ComputeAxialGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnReal angle,
- ZnPoint *grad_geo)
-{
- ZnTransfo *transfo1, *transfo2;
- ZnContour *c;
- ZnBBox bbox;
- ZnPoint *points, p[4];
- unsigned int i;
-
- transfo1 = ZnTransfoNew();
- transfo2 = ZnTransfoNew();
- ZnRotateDeg(transfo1, angle);
- ZnRotateDeg(transfo2, -angle);
- c = shape->contours;
- ZnResetBBox(&bbox);
- for (i = 0; i < shape->num_contours; i++, c++) {
- ZnListAssertSize(ZnWorkPoints, c->num_points);
- points = ZnListArray(ZnWorkPoints);
- ZnTransformPoints(transfo1, c->points, points, c->num_points);
- ZnAddPointsToBBox(&bbox, points, c->num_points);
- }
- bbox.orig.x--;
- bbox.orig.y--;
- bbox.corner.x++;
- bbox.corner.y++;
- p[0] = bbox.orig;
- p[2] = bbox.corner;
- p[1].x = p[2].x;
- p[1].y = p[0].y;
- p[3].x = p[0].x;
- p[3].y = p[2].y;
- ZnTransfoSetIdentity(transfo1);
- ZnTransfoCompose(transfo1, transfo2, wi->current_transfo);
- ZnTransformPoints(transfo1, p, grad_geo, 4);
- ZnTransfoFree(transfo1);
- ZnTransfoFree(transfo2);
-}
-
-static void
-ComputeCircularGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnBool oval,
- ZnPoint *focal_pp, /* in percent of bbox */
- ZnReal angle,
- ZnPoint *grad_geo)
-{
- ZnReal dist, new, x, y, ff;
- ZnBBox bbox;
- ZnContour *c;
- ZnPoint offset, radius, focal_point;
- ZnPoint *points;
- ZnTransfo t1;
- unsigned int i, j;
-
- /*
- * Compute the shape bbox (which should be in the item space).
- */
- ZnResetBBox(&bbox);
- c = shape->contours;
- dist = 0.0;
- for (j = 0; j < shape->num_contours; j++, c++) {
- ZnAddPointsToBBox(&bbox, c->points, c->num_points);
- }
-
- /*
- * Find the gradient focal point in the item space.
- * The excursion of the focal point outside the item
- * bbox is clamped to avoid distorsions that take
- * place due to the rather simple algorithm used to
- * compute the maximum radius of the gradient.
- */
- focal_pp->x = fmod(focal_pp->x, 500.0);
- focal_pp->y = fmod(focal_pp->y, 500.0);
- offset.x = focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
- offset.y = focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
- focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + offset.x;
- focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + offset.y;
-
- /*
- * Find the max distance from the focal point.
- */
- if (oval) {
- /*
- * radius.x and radius.y are the shape radiuses.
- * ff is the distance from the bbox center to
- * the focal point.
- */
- radius.x = (bbox.corner.x-bbox.orig.x)/2;
- radius.y = (bbox.corner.y-bbox.orig.y)/2;
- ff = sqrt(offset.x*offset.x + offset.y*offset.y);
- /*
- * Compute the farthest point from the focal point
- * on a unit circle, then map it to the oval and
- * compute the distance between the two points.
- */
- if (ff > PRECISION_LIMIT) {
- x = offset.x/ff;
- y = offset.y/ff;
- x *= radius.x;
- y *= radius.y;
- x = x + offset.x;
- y = y + offset.y;
- }
- else {
- x = 0;
- y = MAX(radius.x, radius.y);
- }
- dist = x*x + y*y;
- }
- else {
- /*
- * Use the given shape
- */
- c = shape->contours;
- for (j = 0; j < shape->num_contours; j++, c++) {
- for (i = 0, points = c->points; i < c->num_points; i++, points++) {
- x = points->x - focal_point.x;
- y = points->y - focal_point.y;
- new = x*x+y*y;
- if (new > dist) {
- dist = new;
- }
- }
- }
- }
-
- /*
- * Create a transform to map a unit circle to another one that
- * could fill the item when centered at the focal point.
- */
- dist = sqrt(dist); /* Max radius plus a fuzz factor */
- ZnTransfoSetIdentity(&t1);
- ZnScale(&t1, dist, dist);
- ZnRotateDeg(&t1, -angle);
-
- /*
- * Then, center the oval on the focal point.
- */
- ZnTranslate(&t1, focal_point.x, focal_point.y, False);
- /*
- * Last, compose with the current transform.
- */
- ZnTransfoCompose((ZnTransfo *) grad_geo, &t1, wi->current_transfo);
-}
-
-static void
-ComputePathGradient(ZnWInfo *wi,
- ZnPoly *shape,
- ZnPoint *focal_pp, /* in percent of the bbox */
- ZnPoint *grad_geo)
-{
- ZnBBox bbox;
- ZnContour *c;
- ZnPoint focal_point;
- unsigned int j;
-
- /*
- * Compute the shape bbox (which should be in the item space).
- */
- ZnResetBBox(&bbox);
- c = shape->contours;
- for (j = 0; j < shape->num_contours; j++, c++) {
- ZnAddPointsToBBox(&bbox, c->points, c->num_points);
- }
-
- /*
- * Find the gradient center in the item space.
- */
- focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
- focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
- /*
- * Then convert it to device space.
- */
- ZnTransformPoint(wi->current_transfo, &focal_point, &grad_geo[0]);
-}
-
-void
-ZnComputeGradient(ZnGradient *grad,
- ZnWInfo *wi,
- ZnPoly *shape,
- ZnPoint *grad_geo)
-{
- switch (grad->type) {
- case ZN_AXIAL_GRADIENT:
- ComputeAxialGradient(wi, shape, grad->angle, grad_geo);
- break;
- case ZN_RADIAL_GRADIENT:
- case ZN_CONICAL_GRADIENT:
- ComputeCircularGradient(wi, shape, False, &grad->p, grad->angle, grad_geo);
- break;
- case ZN_PATH_GRADIENT:
- ComputePathGradient(wi, shape, &grad->p, grad_geo);
- break;
- }
-}
-
-void
-ZnRenderGradient(ZnWInfo *wi,
- ZnGradient *gradient, /* The gradient to be drawn (static
- * parameters). */
- void (*cb)(void *), /* A callback called to clip the shape
- * containing the gradient. */
- void *closure, /* The callback parameter. */
- ZnPoint *quad, /* The gradient geometric parameters
- * (dynamic). */
- ZnPoly *poly /* Used only by ZN_PATH_GRADIENT */
- )
-{
- unsigned short alpha, alpha2;
- int angle;
- unsigned int i, j;
- int type = gradient->type;
- XColor *color;
- ZnPoint dposa, dposb, dposc, dposd;
- ZnPoint p, dcontrol;
- ZnReal npos, pos, control;
- unsigned int num_clips = ZnListSize(wi->clip_stack);
- ZnPoint iquad[4];
-
- if (!cb && (type == ZN_AXIAL_GRADIENT)) { /* Render an aligned
- * axial gradient in the quad */
- angle = gradient->angle;
- /*
- * Adjust the quad for 90 180 and 270 degrees axial
- * gradients. Other angles not supported.
- */
- switch (angle) {
- case 90:
- iquad[0] = quad[3];
- iquad[3] = quad[2];
- iquad[2] = quad[1];
- iquad[1] = quad[0];
- quad = iquad;
- break;
- case 180:
- iquad[0] = quad[2];
- iquad[3] = quad[1];
- iquad[2] = quad[0];
- iquad[1] = quad[3];
- quad = iquad;
- break;
- case 270:
- iquad[0] = quad[1];
- iquad[3] = quad[0];
- iquad[2] = quad[3];
- iquad[1] = quad[2];
- quad = iquad;
- break;
- }
- }
-
- if (cb) {
- /*
- * Draw the gradient shape in the stencil using the provided
- * callback (clipping).
- */
- ZnGlStartClip(num_clips, False);
- (*cb)(closure);
- ZnGlRestoreStencil(num_clips, True);
- }
-
- if (type == ZN_AXIAL_GRADIENT) {
- /*
- * Then fill the axial gradient using the provided
- * quad and colors. The stencil will be restored
- * to its previous state in the process.
- */
- glBegin(GL_QUAD_STRIP);
- for (i = 0; i < gradient->num_actual_colors; i++) {
- color = gradient->actual_colors[i].rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[i].alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- pos = gradient->actual_colors[i].position;
- control = gradient->actual_colors[i].control;
- dposa.x = (quad[1].x - quad[0].x)*pos/100.0;
- dposa.y = (quad[1].y - quad[0].y)*pos/100.0;
- p.x = quad[0].x + dposa.x;
- p.y = quad[0].y + dposa.y;
- glVertex2d(p.x, p.y);
-
- dposb.x = (quad[2].x - quad[3].x)*pos/100.0;
- dposb.y = (quad[2].y - quad[3].y)*pos/100.0;
- p.x = quad[3].x + dposb.x;
- p.y = quad[3].y + dposb.y;
- glVertex2d(p.x, p.y);
-
- if ((control != 50.0) && (i != gradient->num_actual_colors-1)) {
- color = gradient->actual_colors[i].mid_rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[i].mid_alpha, wi->alpha);
- glColor4us(color->red, color->green, color->blue, alpha);
-
- npos = gradient->actual_colors[i+1].position;
- dposc.x = (quad[1].x - quad[0].x)*npos/100.0;
- dposc.y = (quad[1].y - quad[0].y)*npos/100.0;
- dcontrol.x = (dposc.x - dposa.x)*control/100.0;
- dcontrol.y = (dposc.y - dposa.y)*control/100.0;
- p.x = quad[0].x + dposa.x + dcontrol.x;
- p.y = quad[0].y + dposa.y + dcontrol.y;
- glVertex2d(p.x, p.y);
-
- dposd.x = (quad[2].x - quad[3].x)*npos/100.0;
- dposd.y = (quad[2].y - quad[3].y)*npos/100.0;
- dcontrol.x = (dposd.x - dposb.x)*control/100.0;
- dcontrol.y = (dposd.y - dposb.y)*control/100.0;
- p.x = quad[3].x + dposb.x + dcontrol.x;
- p.y = quad[3].y + dposb.y + dcontrol.y;
- glVertex2d(p.x, p.y);
- }
-
- }
- glEnd();
- }
- else if (type == ZN_RADIAL_GRADIENT) {
- ZnReal x, y, position, position2, position3;
- unsigned int num_p;
- ZnPoint *genarc, *tarc, p, focalp;
- XColor *color2;
-
- genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINE, 0.0, 2*M_PI, &num_p, NULL);
- ZnListAssertSize(ZnWorkPoints, num_p);
- tarc = ZnListArray(ZnWorkPoints);
- ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
- p.x = p.y = 0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
-
- position = 0.0;
- color = gradient->actual_colors[0].rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
- control = gradient->actual_colors[0].control;
- for (j = 1; j < gradient->num_actual_colors; j++) {
- position2 = gradient->actual_colors[j].position/100.0;
- if ((control != 50) && (j != gradient->num_actual_colors-1)) {
- glBegin(GL_QUAD_STRIP);
- color2 = gradient->actual_colors[j-1].mid_rgb;
- alpha2 = ZnComposeAlpha(gradient->actual_colors[j-1].mid_alpha, wi->alpha);
- position3 = position + (position2-position)*control/100.0;
- for (i = 0; i < num_p; i++) {
- x = focalp.x + (tarc[i].x-focalp.x) * position;
- y = focalp.y + (tarc[i].y-focalp.y) * position;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(x, y);
- x = focalp.x + (tarc[i].x-focalp.x) * position3;
- y = focalp.y + (tarc[i].y-focalp.y) * position3;
- glColor4us(color2->red, color2->green, color2->blue, alpha);
- glVertex2d(x, y);
- }
- position = position3;
- color = color2;
- alpha = alpha2;
- glEnd();
- }
- glBegin(GL_QUAD_STRIP);
- color2 = gradient->actual_colors[j].rgb;
- alpha2 = ZnComposeAlpha(gradient->actual_colors[j].alpha, wi->alpha);
- for (i = 0; i < num_p; i++) {
- x = focalp.x + (tarc[i].x-focalp.x) * position;
- y = focalp.y + (tarc[i].y-focalp.y) * position;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(x, y);
- x = focalp.x + (tarc[i].x-focalp.x) * position2;
- y = focalp.y + (tarc[i].y-focalp.y) * position2;
- glColor4us(color2->red, color2->green, color2->blue, alpha2);
- glVertex2d(x, y);
- }
- glEnd();
- position = position2;
- color = color2;
- alpha = alpha2;
- control = gradient->actual_colors[j].control;
- }
- }
- else if (type == ZN_PATH_GRADIENT) {
- ZnPoint p, pp, p2, pp2, p3, pp3;
- unsigned int num_p, k, ii;
- ZnPoint *points;
- ZnReal position;
-
- for (k = 0; k < poly->num_contours; k++) {
- /*if (poly->contours[k].cw) {
- continue;
- }*/
- points = poly->contours[k].points;
- num_p = poly->contours[k].num_points;
-
- for (i = 0; i < num_p; i++) {
- if (i == num_p-1) {
- ii = 0;
- }
- else {
- ii = i+1;
- }
-
- glBegin(GL_QUAD_STRIP);
- p.x = p.y = pp.x = pp.y = 0;
- control = gradient->actual_colors[0].control;
- position = gradient->actual_colors[0].position;
- alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
- color = gradient->actual_colors[0].rgb;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
- glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
- for (j = 0; j < gradient->num_actual_colors-1; j++) {
- position = gradient->actual_colors[j+1].position;
- p2.x = (points[i].x-quad[0].x)*position/100.0;
- p2.y = (points[i].y-quad[0].y)*position/100.0;
- pp2.x = (points[ii].x-quad[0].x)*position/100.0;
- pp2.y = (points[ii].y-quad[0].y)*position/100.0;
- if (control != 50) {
- color = gradient->actual_colors[j].mid_rgb;
- alpha = ZnComposeAlpha(gradient->actual_colors[j].mid_alpha, wi->alpha);
- p3.x = p.x+(p2.x-p.x)*control/100.0;
- p3.y = p.y+(p2.y-p.y)*control/100.0;
- pp3.x = pp.x+(pp2.x-pp.x)*control/100.0;
- pp3.y = pp.y+(pp2.y-pp.y)*control/100.0;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p3.x, quad[0].y+p3.y);
- glVertex2d(quad[0].x+pp3.x, quad[0].y+pp3.y);
- }
- control = gradient->actual_colors[j+1].control;
- alpha = ZnComposeAlpha(gradient->actual_colors[j+1].alpha, wi->alpha);
- color = gradient->actual_colors[j+1].rgb;
- p = p2;
- pp = pp2;
- glColor4us(color->red, color->green, color->blue, alpha);
- glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
- glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
- }
- glEnd();
- }
- }
- }
- else if (type == ZN_CONICAL_GRADIENT) {
- ZnReal position;
- unsigned int num_p;
- ZnPoint *genarc, *tarc, p, focalp;
- XColor col;
-
- genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINEST, 0.0, 2*M_PI, &num_p, NULL);
- ZnListAssertSize(ZnWorkPoints, num_p);
- tarc = ZnListArray(ZnWorkPoints);
- ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
- p.x = p.y = 0;
- ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
-
- glBegin(GL_TRIANGLE_STRIP);
- for (i = 0; i < num_p; i++) {
- position = i*100.0/(num_p-1);
- ZnInterpGradientColor(gradient, position, &col, &alpha);
- alpha = ZnComposeAlpha(alpha, wi->alpha);
-
- /*printf("position: %g --> color: %d %d %d, alpha: %d\n",
- position, col.red, col.green, col.blue, alpha);*/
-
- glColor4us(col.red, col.green, col.blue, alpha);
- glVertex2d(tarc[i].x, tarc[i].y);
- glVertex2d(focalp.x, focalp.y);
- }
- glEnd();
- }
-
- if (cb) {
- /*
- * Restore the previous GL state.
- */
- ZnGlEndClip(num_clips);
- }
-}
-
-
-void
-ZnRenderHollowDot(ZnWInfo *wi,
- ZnPoint *p,
- ZnReal size)
-{
- int num_clips = ZnListSize(wi->clip_stack);
-
- ZnGlStartClip(num_clips, False);
-
- glPointSize((GLfloat) (size-2));
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlRenderClipped();
-
- glPointSize((GLfloat) size);
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlRestoreStencil(num_clips, False);
-
- glBegin(GL_POINTS);
- glVertex2d(p->x, p->y);
- glEnd();
-
- ZnGlEndClip(num_clips);
-}
-#endif
-
-
-#ifdef GL
-void
-ZnRenderGlyph(ZnTexFontInfo *tfi,
- int c)
-{
- ZnTexGVI *tgvi;
-
- tgvi = ZnTexFontGVI(tfi, c);
- if (!tgvi) {
- return;
- }
- //printf("%c --> x0,y0: %d %d, tx0,ty0: %g %g, x1,y1: %d %d, tx1,ty1: %g %g, advance: %g\n",
- // c, tgvi->v0x, tgvi->v0y, tgvi->t0x, tgvi->t0y,
- // tgvi->v1x, tgvi->v1y, tgvi->t1x, tgvi->t1y,
- // tgvi->advance);
- glBegin(GL_QUADS);
- glTexCoord2f(tgvi->t0x, tgvi->t0y); glVertex2s(tgvi->v0x, tgvi->v0y);
- glTexCoord2f(tgvi->t0x, tgvi->t1y); glVertex2s(tgvi->v0x, tgvi->v1y);
- glTexCoord2f(tgvi->t1x, tgvi->t1y); glVertex2s(tgvi->v1x, tgvi->v1y);
- glTexCoord2f(tgvi->t1x, tgvi->t0y); glVertex2s(tgvi->v1x, tgvi->v0y);
- glEnd();
- glTranslatef(tgvi->advance, 0.0, 0.0);
-}
-
-#ifdef PTK_800
-void
-ZnRenderString(ZnTexFontInfo *tfi,
- unsigned char *string,
- unsigned int len)
-{
- while (len) {
- ZnRenderGlyph(tfi, *string);
- string++;
- len--;
- }
-}
-#else
-void
-ZnRenderString(ZnTexFontInfo *tfi,
- unsigned char *string,
- unsigned int len)
-{
- unsigned int clen;
- Tcl_UniChar c;
-
- while (len) {
- clen = Tcl_UtfToUniChar(string, &c);
-
- ZnRenderGlyph(tfi, c);
-
- string += clen;
- len -= clen;
- }
-}
-#endif
-#endif
-
-/*
- **********************************************************************************
- *
- * RenderTriangle --
- * This routine maps an image onto a triangle.
- * Image coordinates are chosen for each vertex of the triangle.
- * A simple affine tex mapping is used as in Zinc there is no way
- * to specify perspective deformation. No filtering is attempted
- * on the output pixels.
- *
- * In the comments below u and v are image coordinates and x and
- * y are triangle coordinates.
- * RenderAffineScanline is an helper function that draws a whole
- * scan line to the image with linear interpolation.
- *
- **********************************************************************************
- */
-static void
-RenderAffineScanline(XImage *image,
- XImage *mapped_image,
- ZnReal x1,
- ZnReal x2,
- ZnReal u1,
- ZnReal u2,
- ZnReal v1,
- ZnReal v2,
- int y)
-{
- ZnReal du, dv, width;
- int intx1, intx2, intu, intv;
- int i;
-
- /* Revert span ends if needed */
- if (x2 < x1) {
- ZnReal tmp;
- tmp = x1; x1 = x2; x2 = tmp;
- tmp = u1; u1 = u2; u2 = tmp;
- tmp = v1; v1 = v2; v2 = tmp;
- }
-
- /* Compute the interpolation factors */
- width = x2 - x1;
- if (width) {
- du = (u2 - u1) / width;
- dv = (v2 - v1) / width;
- }
- else {
- du = dv = 0;
- }
- intx1 = (int) floor(x1);
- intx2 = (int) floor(x2);
-
- /* Draw the line */
- for (i = intx1; i < intx2; i++) {
- intu = (int) floor(u1);
- intv = (int) floor(v1);
- XPutPixel(mapped_image, i, y, XGetPixel(image, intu, intv));
- u1 += du;
- v1 += dv;
- }
-}
-
-static void
-RenderTriangle(XImage *image,
- XImage *mapped_image,
- ZnPoint *tri,
- ZnPoint *im_coords)
-{
- ZnReal dx_A, dx_B; /* Interpolation factor in x / y */
- ZnReal du_A, du_B; /* in u / y */
- ZnReal dv_A, dv_B; /* in v / y */
- ZnReal x1, x2; /* Span in x */
- ZnReal u1, u2; /* Span in u */
- ZnReal v1, v2; /* Span in v */
- int height_A; /* Scan line # from top top vertex A */
- int height_B; /* Scan line # from top top vertex B */
- int y; /* Current scan line */
- int top, a, b; /* Top triangle vertex and other two */
- int i;
-
- /* Find top vertex and deduce the others. */
- top = 0;
- for (i = 1; i < 3; i++) {
- if (tri[i].y <= tri[top].y)
- top = i;
- }
- a = (top+1)%3;
- b = top-1;
- if (b < 0)
- b = 2;
-
- /* Initialize conversion parameters. */
- y = ZnNearestInt(tri[top].y);
- height_A = ZnNearestInt(tri[a].y - tri[top].y);
- height_B = ZnNearestInt(tri[b].y - tri[top].y);
- x1 = x2 = tri[top].x;
- u1 = u2 = im_coords[top].x;
- v1 = v2 = im_coords[top].y;
- if (height_A) {
- dx_A = (tri[a].x - tri[top].x) / height_A;
- du_A = (im_coords[a].x - im_coords[top].x) / height_A;
- dv_A = (im_coords[a].y - im_coords[top].y) / height_A;
- }
- else {
- dx_A = du_A = dv_A = 0;
- }
- if (height_B) {
- dx_B = (tri[b].x - tri[top].x) / height_B;
- du_B = (im_coords[b].x - im_coords[top].x) / height_B;
- dv_B = (im_coords[b].y - im_coords[top].y) / height_B;
- }
- else {
- dx_B = du_B = dv_B = 0;
- }
-
- /* Convert from top to bottom */
- for (i = 2; i > 0; ) {
- while (height_A && height_B) {
-
- /* Draw a scanline */
- RenderAffineScanline(image, mapped_image, x1, x2, u1, u2, v1, v2, y);
-
- /* Step the parameters*/
- y++;
- height_A--;
- height_B--;
- x1 += dx_A;
- x2 += dx_B;
- u1 += du_A;
- u2 += du_B;
- v1 += dv_A;
- v2 += dv_B;
- }
-
- /* If either height_A or height_B steps to zero, we have
- * encountered a vertex (A or B) and we are starting conversion
- * along a new edge. Update the parameters before proceeding. */
- if (!height_A) {
- int na = (a+1)%3;
-
- height_A = ZnNearestInt(tri[na].y - tri[a].y);
- if (height_A) {
- dx_A = (tri[na].x - tri[a].x) / height_A;
- du_A = (im_coords[na].x - im_coords[a].x) / height_A;
- dv_A = (im_coords[na].y - im_coords[a].y) / height_A;
- }
- else {
- dx_A = du_A = dv_A = 0;
- }
- x1 = tri[a].x;
- u1 = im_coords[a].x;
- v1 = im_coords[a].y;
- a = na;
- /* One less vertex to do */
- i--;
- }
-
- if (!height_B) {
- int nb = b - 1;
-
- if (nb < 0)
- nb = 2;
- height_B = ZnNearestInt(tri[nb].y - tri[b].y);
- if (height_B) {
- dx_B = (tri[nb].x - tri[b].x) / height_B;
- du_B = (im_coords[nb].x - im_coords[b].x) / height_B;
- dv_B = (im_coords[nb].y - im_coords[b].y) / height_B;
- }
- else {
- dx_B = du_B = dv_B = 0;
- }
- x2 = tri[b].x;
- u2 = im_coords[b].x;
- v2 = im_coords[b].y;
- b = nb;
- /* One less vertex to do */
- i--;
- }
- }
-}
-
-
-/*
- **********************************************************************************
- *
- * MapImage --
- * This procedure maps an image on a parallelogram given in poly.
- * The given parallelogram should fit in the destination image.
- * The parallelogram vertices must be ordered as for a triangle
- * strip:
- *
- * v0 ------------ v2
- * | |
- * | |
- * v1 ------------ v3
- *
- * The mapping is done by a simple affine mapping of the image on the
- * two triangles obtained by cutting the parallelogram along the diogonal
- * from the second vertex to the third vertex.
- *
- **********************************************************************************
- */
-void
-ZnMapImage(XImage *image,
- XImage *mapped_image,
- ZnPoint *poly)
-{
- ZnPoint triangle[3];
- ZnPoint im_coords[3];
-
- triangle[0] = poly[0];
- triangle[1] = poly[1];
- triangle[2] = poly[2];
- im_coords[0].x = 0.0;
- im_coords[0].y = 0.0;
- im_coords[1].x = 0.0;
- im_coords[1].y = image->height-1;
- im_coords[2].x = image->width-1;
- im_coords[2].y = 0.0;
- RenderTriangle(image, mapped_image, triangle, im_coords);
-
- triangle[0] = poly[1];
- triangle[1] = poly[2];
- triangle[2] = poly[3];
- im_coords[0].x = 0.0;
- im_coords[0].y = image->height-1;
- im_coords[1].x = image->width-1;
- im_coords[1].y = 0.0;
- im_coords[2].x = image->width-1;
- im_coords[2].y = image->height-1;
- RenderTriangle(image, mapped_image, triangle, im_coords);
-}