/* * Copyright (c) 1994, Riley Rainey, riley@netcon.com * * Permission to use, copy, modify and distribute (without charge) this * software, documentation, images, etc. is granted, provided that this * comment and the author's name is retained. * * This software is provided by the author as is, and without any expressed * or implied warranties, including, but not limited to, the implied * warranties of merchantability and fitness for a particular purpose. In no * event shall the author be liable for any direct, indirect, incidental, or * consequential damages arising in any way out of the use of this software. */ #include #include "gedit.h" void WorldToWidget(), DrawGrid(), DrawRuler(), DrawWidget(), StringSize(); extern void PointToXYZ(); #define MINIMUM_GRID_SPACING 50 #define MINIMUM_RULER_SPACING 50 #define RULER_MARGIN 2 #define RULER_MAJOR_LENGTH 7 #define RULER_MINOR1_LENGTH 4 #define RULER_MINOR2_LENGTH 2 #define RULER_THICKNESS 2 void RescaleView (w, factor) Widget w; double factor; { polygon_t *poly; point_t *q; view_info_t *p; register int i, j, xc, yc, zc; XtVaGetValues (w, XmNuserData, &p, NULL); switch (p->layout) { case VL_NXNY: case VL_NYX: xc = (p->width + 1) / 2; yc = (p->height + 1) / 2; zc = (p->other_view->height + 1) / 2; p->other_view->origin_x = p->origin_x = (p->origin_x - xc) * factor + xc; p->origin_y = (p->origin_y - yc) * factor + yc; p->other_view->origin_y = (p->other_view->origin_y - zc) * factor + zc; break; case VL_NXZ: xc = (p->width + 1) / 2; yc = (p->other_view->height + 1) / 2; zc = (p->height + 1) / 2; p->other_view->origin_x = p->origin_x = (p->origin_x - xc) * factor + xc; p->origin_y = (p->origin_y - zc) * factor + zc; p->other_view->origin_y = (p->other_view->origin_y - yc) * factor + yc; break; case VL_NYZ: xc = (p->other_view->height + 1) / 2; yc = (p->width + 1) / 2; zc = (p->height + 1) / 2; p->other_view->origin_x = p->origin_x = (p->origin_x - yc) * factor + yc; p->origin_y = (p->origin_y - zc) * factor + zc; p->other_view->origin_y = (p->other_view->origin_y - xc) * factor + xc; break; } pixel_scale /= factor; for (i=0, poly=polygon_list; i < polygon_max; ++i, ++poly) { for (j=0, q=poly->point; j < poly->num_points; ++j, ++q) { PointToXYZ (p, q); } } DrawWidget (w, False); DrawWidget (p->other_widget, False); } void DrawWidget (w, immediate) Widget w; Boolean immediate; { polygon_t *poly; point_t *q; view_info_t *p; register int i, j; int x1, y1, x2, y2; Display *dpy; Drawable d; Pixel fg, bg; XtVaGetValues (w, XmNuserData, &p, XmNforeground, &fg, XmNbackground, &bg, NULL); dpy = XtDisplay (w); d = XtWindow (w); if (d == 0) immediate = False; XSetForeground (dpy, p->gc, bg); if (immediate) XFillRectangle (dpy, d, p->gc, 0, 0, p->width, p->height); XFillRectangle (dpy, p->pixmap, p->gc, 0, 0, p->width, p->height); XSetForeground (dpy, p->gc, fg); XSetLineAttributes (dpy, p->gc, app_data.line_thickness, LineSolid, CapButt, JoinMiter); for (i=unsel_polygon; i >= 0; i = polygon_list[i].next) { poly = &polygon_list[i]; if (poly->num_points == 0) continue; WorldToWidget (p, &poly->point[poly->num_points-1], &x1, &y1); for (j=0, q=poly->point; j < poly->num_points; ++j, ++q) { WorldToWidget (p, q, &x2, &y2); if (immediate) XDrawLine (dpy, d, p->gc, x1, y1, x2, y2); XDrawLine (dpy, p->pixmap, p->gc, x1, y1, x2, y2); x1 = x2; y1 = y2; } } XSetForeground (dpy, p->gc, app_data.select_pixel); XSetLineAttributes (dpy, p->gc, app_data.selection_thickness, LineSolid, CapButt, JoinMiter); for (i=sel_polygon; i >= 0; i = polygon_list[i].next) { poly = &polygon_list[i]; if (poly->num_points == 0) continue; WorldToWidget (p, &poly->point[poly->num_points-1], &x1, &y1); for (j=0, q=poly->point; j < poly->num_points; ++j, ++q) { WorldToWidget (p, q, &x2, &y2); if (immediate) XDrawLine (dpy, d, p->gc, x1, y1, x2, y2); XDrawLine (dpy, p->pixmap, p->gc, x1, y1, x2, y2); x1 = x2; y1 = y2; } } if (immediate) DrawGrid (p, dpy, d); DrawGrid (p, dpy, p->pixmap); if (immediate) DrawRuler (p, dpy, d, bg); DrawRuler (p, dpy, p->pixmap, bg); if (immediate == False && d != 0) XCopyArea (dpy, p->pixmap, d, p->gc, 0, 0, p->width, p->height, 0, 0); } void DrawPolygon (w, poly, immediate) Widget w; polygon_t *poly; Boolean immediate; { point_t *q; view_info_t *p; register int j; int x1, y1, x2, y2; Display *dpy; Drawable d; Pixel fg, bg; XtVaGetValues (w, XmNuserData, &p, XmNforeground, &fg, XmNbackground, &bg, NULL); dpy = XtDisplay (w); d = XtWindow (w); if (d == 0) immediate = False; XSetForeground (dpy, p->gc, fg); XSetLineAttributes (dpy, p->gc, app_data.line_thickness, LineSolid, CapButt, JoinMiter); if (poly->num_points == 0) return; WorldToWidget (p, &poly->point[poly->num_points-1], &x1, &y1); for (j=0, q=poly->point; j < poly->num_points; ++j, ++q) { WorldToWidget (p, q, &x2, &y2); if (immediate) XDrawLine (dpy, d, p->gc, x1, y1, x2, y2); XDrawLine (dpy, p->pixmap, p->gc, x1, y1, x2, y2); x1 = x2; y1 = y2; } if (immediate == False && d != 0) XCopyArea (dpy, p->pixmap, d, p->gc, 0, 0, p->width, p->height, 0, 0); } void WorldToWidget (p, q, x, y) view_info_t *p; point_t *q; int *x, *y; { switch (p->layout) { case VL_NXZ: *x = q->x; *y = q->z; break; case VL_NXNY: *x = q->x; *y = q->y; break; case VL_NYX: *x = q->y; *y = q->x; break; case VL_NYZ: *x = q->y; *y = q->z; break; } } void DrawGrid (p, dpy, d) view_info_t *p; Display *dpy; Drawable d; { int exp, n, x, y; if (app_data.show_grid == False) return; XSetForeground (dpy, p->grid_gc, app_data.grid_pixel); for (exp = 1; ; exp *= 10) { if (exp / pixel_scale >= MINIMUM_GRID_SPACING) break; if (5.0 * exp / pixel_scale >= MINIMUM_GRID_SPACING) { exp = 5 * exp; break; } } /* * Y-axis lines */ for (x=p->origin_x, n = 0; x > 0; ) { XDrawLine (dpy, d, p->grid_gc, x, 0, x, p->height); ++ n; x = p->origin_x - (int) (n * exp / pixel_scale); } for (x=p->origin_x, n = 0; x < p->width; ) { ++ n; x = p->origin_x + (int) (n * exp / pixel_scale); XDrawLine (dpy, d, p->grid_gc, x, 0, x, p->height); } /* * X-axis lines */ for (y=p->origin_y, n = 0; y > 0; ) { XDrawLine (dpy, d, p->grid_gc, 0, y, p->width, y); ++ n; y = p->origin_y - (int) (n * exp / pixel_scale); } for (y=p->origin_y, n = 0; y < p->height; ) { ++ n; y = p->origin_y + (int) (n * exp / pixel_scale); XDrawLine (dpy, d, p->grid_gc, 0, y, p->width, y); } } void DrawSelectedPolygon (w, poly, immediate, erase) Widget w; polygon_t *poly; Boolean immediate, erase; { register int i; int x1, x2, y1, y2; point_t *q; view_info_t *p; Pixel bg; Display *dpy; Drawable d; dpy = XtDisplay (w); d = XtWindow (w); if (d == 0) immediate = False; XtVaGetValues (w, XmNuserData, &p, XmNbackground, &bg, NULL); if (erase) XSetForeground (dpy, p->gc, bg); else XSetForeground (dpy, p->gc, app_data.select_pixel); XSetLineAttributes (dpy, p->gc, app_data.selection_thickness, LineSolid, CapButt, JoinMiter); WorldToWidget (p, &poly->point[poly->num_points-1], &x1, &y1); for (i=0, q=poly->point; i < poly->num_points; ++i, ++q) { WorldToWidget (p, q, &x2, &y2); if (immediate) XDrawLine (dpy, d, p->gc, x1, y1, x2, y2); XDrawLine (dpy, p->pixmap, p->gc, x1, y1, x2, y2); x1 = x2; y1 = y2; } } void DrawRuler (p, dpy, d, bg) view_info_t *p; Display *dpy; Drawable d; Pixel bg; { int ruler_y, font_y, nseg, exp, n, x, xw, yw, xv; XSegment seg[256]; char s[32]; /* * we'll only display the horizontal ruler in the top window */ if (p->other_widget == twindow) return; if (app_data.show_ruler == False) return; for (exp = 1; ; exp *= 10) { if (exp / pixel_scale >= MINIMUM_RULER_SPACING) break; if (2.0 * exp / pixel_scale >= MINIMUM_RULER_SPACING) { exp = 2 * exp; break; } if (5.0 * exp / pixel_scale >= MINIMUM_RULER_SPACING) { exp = 5 * exp; break; } } ruler_y = p->height - (RULER_THICKNESS + 2 * RULER_MARGIN + RULER_MAJOR_LENGTH + app_data.ruler_font->max_bounds.ascent); font_y = ruler_y + RULER_THICKNESS + RULER_MARGIN + app_data.ruler_font->max_bounds.ascent - 2; XSetForeground (dpy, p->gc, bg); XFillRectangle (dpy, d, p->gc, 0, ruler_y, p->width, p->height - ruler_y); XSetForeground (dpy, p->gc, app_data.grid_pixel); seg[0].x1 = 0; seg[0].x2 = p->width - 1; seg[0].y1 = seg[0].y2 = ruler_y; nseg = 1; /* * Major tick marks */ for (x=p->origin_x, n = 0; x > 0; ) { seg[nseg].x1 = seg[nseg].x2 = x; seg[nseg].y1 = p->height - 1; seg[nseg].y2 = p->height - RULER_MAJOR_LENGTH; ++ nseg; xv = (int) (n * exp); sprintf (s, "%d", xv); StringSize (s, &xw, &yw); XDrawString (dpy, d, p->gc, x - xw / 2, font_y, s, strlen(s)); ++ n; x = p->origin_x - (int) (n * exp / pixel_scale); } for (x=p->origin_x, n = 0; x < p->width; ) { ++ n; x = p->origin_x + (int) (n * exp / pixel_scale); xv = (int) (n * exp); sprintf (s, "%d", xv); StringSize (s, &xw, &yw); XDrawString (dpy, d, p->gc, x - xw / 2, font_y, s, strlen(s)); seg[nseg].x1 = seg[nseg].x2 = x; seg[nseg].y1 = p->height - 1; seg[nseg].y2 = p->height - RULER_MAJOR_LENGTH; ++ nseg; } XSetLineAttributes (dpy, p->gc, RULER_THICKNESS, LineSolid, CapButt, JoinMiter); XDrawSegments (dpy, d, p->gc, seg, nseg); } void StringSize (s, xw, yw) char *s; int *xw, *yw; { *xw = XTextWidth (app_data.ruler_font, s, strlen (s)); *yw = app_data.ruler_font->max_bounds.ascent; }