diff options
Diffstat (limited to 'Bezier.c')
-rw-r--r-- | Bezier.c | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/Bezier.c b/Bezier.c new file mode 100644 index 0000000..a9d363c --- /dev/null +++ b/Bezier.c @@ -0,0 +1,651 @@ +/* + ********************************************************************************** + * + * Project : Imagine + * File : Bezier.c + * Version : $Id$ + * Author : Patrick LECOANET + * Created On : Thu Mar 23 21:59:43 1995 + * Last Modified By: Patrick Lecoanet + * Last Modified On: Thu Mar 23 23:10:45 1995 + * Update Count : 21 + * Purpose : implementation of Bezier arc item. + * + ********************************************************************************** + */ + +/*---------------- Distribution and Copyright ------------------- + * + * This software is copyright by the CENA/DGAC/FRANCE + * + * All rights reserved. + * + * No part of the material protected by this copyright notice + * may be reproduced or utilized for commercial use in any form + * without written permission of the copyright owner. + * + * It may be reproduced or utilized for R&D use in Non Profit + * Organization + * + *---------------------------------------------------------------*/ + +/*---------------- Disclaimer ----------------------------------- + * + * This software and its documentation are provided "AS IS" and + * without any expressed or implied warranties whatsoever. + * No warranties as to performance, merchantability, or fitness + * for a particular purpose exist. + * + * Because of the diversity of conditions and hardware under + * which this software may be used, no warranty of fitness for + * a particular purpose is offered. The user is advised to + * test the software thoroughly before relying on it. The user + * must assume the entire risk and liability of using this + * software. + * + * In no event shall any person or organization of people be + * held responsible for any direct, indirect, consequential + * or inconsequential damages or lost profits. + * + *-----------------END-PROLOGUE----------------------------------*/ + + + +/* + ********************************************************************************** + * + * Included files + * + ********************************************************************************** + */ + +#include "ReliefStyConv.h" +#include "RadarP.h" +#include "ItemP.h" +#include "GeoP.h" +#include "DrawP.h" +#include "ActionsP.h" + + +/* + ********************************************************************************** + * + * Constants. + * + ********************************************************************************** + */ + +static char rcsid[] = "$Id$"; + +static char invalid_attribute[] = "RadarBezier : Invalid attribute."; +static char invalid_pixmap[] = "RadarBezier : Pixmaps used in patterns must be of depth 1."; +static char read_only_attribute[] = "This attribute is read only."; + +static RadarList smoothed_points = NULL; +static RadarList control_points = NULL; + + +/* + ********************************************************************************** + * + * Specific Bezier item record + * + ********************************************************************************** + */ + +typedef struct _BezierItemStruct { + ItemHeader header; + + /* Public data */ + int x1; + int y1; + int x2; + int y2; + int xc1; + int yc1; + int xc2; + int yc2; + unsigned char spline_steps; + unsigned int line_width; + Pixel line_foreground; + Pixmap line_pattern; + + /* Private data */ +} BezierItemStruct, *BezierItem; + + +/* + ********************************************************************************** + * + * Init -- + * + ********************************************************************************** + */ + +static void +Init(Widget rw, + Item item + ) +{ + RadarPart *rp = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + + if (!smoothed_points) + smoothed_points = RadarListNew(0, sizeof(XPoint)); + if (!control_points) { + control_points = RadarListNew(4, sizeof(XPoint)); + RadarListAssertSize(control_points, 4); + } + + /* Init attributes */ + ITEM_COMMON_INIT(item, NULL, True, True, DEFAULT_BEZIER_PRIORITY); + + bzr->x1 = 0; + bzr->y1 = 0; + bzr->x2 = 0; + bzr->y2 = 0; + bzr->xc1 = 0; + bzr->yc1 = 0; + bzr->xc2 = 0; + bzr->yc2 = 0; + bzr->spline_steps = 10; + bzr->line_width = 1; + bzr->line_foreground = rp->foreground; + bzr->line_pattern = XtUnspecifiedPixmap; +} + + +/* + ********************************************************************************** + * + * Clone -- + * + ********************************************************************************** + */ + +static void +Clone(Widget rw, + Item item + ) +{ + BezierItem bzr = (BezierItem) item; + + item->user_data = NULL; +} + + +/* + ********************************************************************************** + * + * Remove -- + * + ********************************************************************************** + */ + +static void +Remove(Widget rw, + Item item + ) +{ + BezierItem bzr = (BezierItem) item; + +} + + +/* + ********************************************************************************** + * + * Configure -- + * + ********************************************************************************** + */ + +static void +Configure(Widget rw, + Item item, + RadarList attrs, + Boolean *draw_item, + Boolean *draw_label, + Boolean *compute_coord, + Boolean init + ) +{ + RadarPart *radar = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + Cardinal i, num_attrs; + RadarAttr *attr; + Boolean b_value; + int value; + Pixmap pattern; + + num_attrs = RadarListSize(attrs); + for (i = 0; i < num_attrs; i++) { + attr = (RadarAttr *) RadarListAt(attrs, i); + + switch (attr->name) { + ITEM_COMMON_CONFIGURE; + + case RadarItemX: + if ((int) attr->value != bzr->x1) { + bzr->x1 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemY: + if ((int) attr->value != bzr->y1) { + bzr->y1 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemX2: + if ((int) attr->value != bzr->xc1) { + bzr->xc1 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemY2: + if ((int) attr->value != bzr->yc1) { + bzr->yc1 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemX3: + if ((int) attr->value != bzr->xc2) { + bzr->xc2 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemY3: + if ((int) attr->value != bzr->yc2) { + bzr->yc2 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemX4: + if ((int) attr->value != bzr->x2) { + bzr->x2 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemY4: + if ((int) attr->value != bzr->y2) { + bzr->y2 = (int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemSplineSteps: + value = (unsigned char) attr->value; + if (value > 0 && + value <= 100 && + value != bzr->spline_steps) { + bzr->spline_steps = value; + *draw_item = True; + } + break; + + case RadarItemLineWidth: + if (((unsigned int) attr->value) != bzr->line_width) { + bzr->line_width = (unsigned int) attr->value; + *draw_item = *compute_coord = True; + } + break; + + case RadarItemLineForeground: + if ((Pixel) attr->value != bzr->line_foreground) { + bzr->line_foreground = (Pixel) attr->value; + *draw_item = True; + } + break; + + case RadarItemLinePattern: + if (!DRAW.ValidBitmap(XtDisplay(rw), (Pixmap) attr->value, &pattern)) { + XtAppWarning(radar->app_context, invalid_pixmap); + continue; + } + if (pattern != bzr->line_pattern) { + bzr->line_pattern = pattern; + *draw_item = True; + } + break; + + default: + XtAppWarning(radar->app_context, invalid_attribute); + break; + } + } +} + + +/* + ********************************************************************************** + * + * Query -- + * + ********************************************************************************** + */ + +static void +Query(Widget rw, + Item item, + RadarList attrs + ) +{ + RadarPart *radar = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + Cardinal i, num_attrs; + RadarAttr *attr; + + num_attrs = RadarListSize(attrs); + for (i = 0; i < num_attrs; i++) { + attr = (RadarAttr *) RadarListAt(attrs, i); + + switch (attr->name) { + ITEM_COMMON_QUERY; + + case RadarItemX: + *((int *) attr->value) = bzr->x1; + break; + + case RadarItemY: + *((int *) attr->value) = bzr->y1; + break; + + case RadarItemX2: + *((int *) attr->value) = bzr->xc1; + break; + + case RadarItemY2: + *((int *) attr->value) = bzr->yc1; + break; + + case RadarItemX3: + *((int *) attr->value) = bzr->xc2; + break; + + case RadarItemY3: + *((int *) attr->value) = bzr->yc2; + break; + + case RadarItemX4: + *((int *) attr->value) = bzr->x2; + break; + + case RadarItemY4: + *((int *) attr->value) = bzr->y2; + break; + + case RadarItemSplineSteps: + *((unsigned char *) attr->value) = bzr->spline_steps; + break; + + case RadarItemLineWidth: + *((unsigned int *) attr->value) = bzr->line_width; + break; + + case RadarItemLineForeground: + *((Pixel *) attr->value) = bzr->line_foreground; + break; + + case RadarItemLinePattern: + *((Pixmap *) attr->value) = bzr->line_pattern; + break; + + default: + XtAppWarning(radar->app_context, invalid_attribute); + break; + } + } +} + + +/* + ********************************************************************************** + * + * ComputeCoordinates -- + * + ********************************************************************************** + */ + +static void +ComputeCoordinates(Widget rw, + Item item + ) +{ + RadarPart *rp = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + XPoint *points; + int i, len; + Dimension dev_line_width; + + ResetBBox(&item->item_bounding_box); + if (!bzr->line_width) + return; + + points = (XPoint *) RadarListArray(control_points); + points[0].x = X_TO_DEVICE(rp, bzr->x1); + points[0].y = Y_TO_DEVICE(rp, bzr->y1); + points[1].x = X_TO_DEVICE(rp, bzr->xc1); + points[1].y = Y_TO_DEVICE(rp, bzr->yc1); + points[2].x = X_TO_DEVICE(rp, bzr->xc2); + points[2].y = Y_TO_DEVICE(rp, bzr->yc2); + points[3].x = X_TO_DEVICE(rp, bzr->x2); + points[3].y = Y_TO_DEVICE(rp, bzr->y2); + + item->connection_dev = points[0]; + + if (bzr->line_width > 1) + dev_line_width = MAX(1, LENGTH_TO_DEVICE(rp, bzr->line_width)); + else + dev_line_width = 1; + + RadarListEmpty(smoothed_points); + DRAW.GetBezierPath(control_points, bzr->spline_steps, smoothed_points); + + len = RadarListSize(smoothed_points); + points = (XPoint *) RadarListArray(smoothed_points); + for (i = 0; i < len; i++) + AddPointToBBox(&item->item_bounding_box, points[i].x, points[i].y); + + /* + * For thick lines adjust the bounding box. Add the line width in + * all directions, this overestimates the space but is fast. + */ + if (dev_line_width > 1) { + item->item_bounding_box.x -= dev_line_width; + item->item_bounding_box.y -= dev_line_width; + item->item_bounding_box.width += dev_line_width*2; + item->item_bounding_box.height += dev_line_width*2; + } +} + + +/* + ********************************************************************************** + * + * ToArea -- + * Tell if the object is entirely outside (-1), + * entirely inside (1) or in between (0). + * + ********************************************************************************** + */ + +static int +ToArea(Widget rw, + Item item, + XRectangle *area) +{ +} + + +/* + ********************************************************************************** + * + * Draw -- + * + ********************************************************************************** + */ + +static void +Draw(Widget rw, + Item item + ) +{ + RadarPart *radar = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + XGCValues values; + XPoint *points; + int len, i; + Dimension dev_line_width; + + if (bzr->line_width) { + points = (XPoint *) RadarListArray(control_points); + points[0].x = X_TO_DEVICE(radar, bzr->x1); + points[0].y = Y_TO_DEVICE(radar, bzr->y1); + points[1].x = X_TO_DEVICE(radar, bzr->xc1); + points[1].y = Y_TO_DEVICE(radar, bzr->yc1); + points[2].x = X_TO_DEVICE(radar, bzr->xc2); + points[2].y = Y_TO_DEVICE(radar, bzr->yc2); + points[3].x = X_TO_DEVICE(radar, bzr->x2); + points[3].y = Y_TO_DEVICE(radar, bzr->y2); + + if (bzr->line_width > 1) + dev_line_width = MAX(1, LENGTH_TO_DEVICE(radar, bzr->line_width)); + else + dev_line_width = 1; + + RadarListEmpty(smoothed_points); + DRAW.GetBezierPath(control_points, bzr->spline_steps, smoothed_points); + + len = RadarListSize(smoothed_points); + points = (XPoint *) RadarListArray(smoothed_points); + + values.foreground = bzr->line_foreground; + values.line_width = (dev_line_width == 1) ? 0 : dev_line_width; + if (bzr->line_pattern == XtUnspecifiedPixmap) { + values.fill_style = FillSolid; + XChangeGC(XtDisplay(rw), radar->gc, + GCFillStyle | GCLineWidth | GCForeground, &values); + } + else { + values.fill_style = FillStippled; + values.stipple = bzr->line_pattern; + XChangeGC(XtDisplay(rw), radar->gc, + GCFillStyle | GCStipple | GCLineWidth | GCForeground, &values); + } + + XDrawLines(XtDisplay(rw), radar->draw_buffer, radar->gc, + points, len, CoordModeOrigin); + } +} + + +/* + ********************************************************************************** + * + * Pick -- + * + ********************************************************************************** + */ + +static Boolean +Pick(Widget rw, + Item item, + XPoint *p, + Dimension aperture, + Boolean closest, + RadarList items) +{ + RadarPart *rp = &(((RadarWidget) rw)->radar); + BezierItem bzr = (BezierItem) item; + double dist, new_dist; + XPoint *points; + int len, i; + Dimension dev_line_width; + + points = (XPoint *) RadarListArray(control_points); + points[0].x = X_TO_DEVICE(rp, bzr->x1); + points[0].y = Y_TO_DEVICE(rp, bzr->y1); + points[1].x = X_TO_DEVICE(rp, bzr->xc1); + points[1].y = Y_TO_DEVICE(rp, bzr->yc1); + points[2].x = X_TO_DEVICE(rp, bzr->xc2); + points[2].y = Y_TO_DEVICE(rp, bzr->yc2); + points[3].x = X_TO_DEVICE(rp, bzr->x2); + points[3].y = Y_TO_DEVICE(rp, bzr->y2); + + if (bzr->line_width > 1) + dev_line_width = MAX(1, LENGTH_TO_DEVICE(rp, bzr->line_width)); + else + dev_line_width = 1; + + RadarListEmpty(smoothed_points); + DRAW.GetBezierPath(control_points, bzr->spline_steps, smoothed_points); + + len = RadarListSize(smoothed_points); + points = (XPoint *) RadarListArray(smoothed_points); + + dist = 1.0e40; + for (i = 0; i < len-1; i++) { + new_dist = LineToPointDist(&points[i], &points[i+1], p); + dist = MIN(dist, new_dist); + } + + /* + * Take the line width into account if it is meaningful. + */ + if (dist != 0 && dev_line_width > 1) + dist = MAX(0.0, dist - (((double) dev_line_width)/2.0)); + + return ACTIONS.AddToPickedItems(items, item, RADAR_CURRENT_POSITION, + dist, aperture, closest); +} + + +/* + ********************************************************************************** + * + * PostScript -- + * + ********************************************************************************** + */ + +static void +PostScript(Widget rw, + Item item, + PostScriptInfo ps_info) +{ +} + + +/* + ********************************************************************************** + * + * Exported functions struct -- + * + ********************************************************************************** + */ + +static ItemClassStruct BEZIER_ITEM_CLASS = { + sizeof(BezierItemStruct), + False, + 1, + Init, + Clone, + Remove, + Configure, + Query, + ComputeCoordinates, + ToArea, + Draw, + Pick, + PostScript +}; + +RadarItemClassId RadarBezier = (RadarItemClassId) &BEZIER_ITEM_CLASS; |