/*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 69): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. -Shteryana Shopova * ---------------------------------------------------------------------------- */ #include #include #include #include #include "cg.h" enum cg_rect_clip_method { CG_RCT_COHEN_SUTHERLAND = 0, CG_RCT_LIANG_BARSKY = 1, CG_RCT_NICHOLL_LEE_NICHOLL = 2, }; /* A rectangle defined by one of its digonals. */ struct cg_rectangle { gint x1_; gint y1_; gint x2_; gint y2_; }; typedef void (*cg_rect_clip_cb) (GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment); static void cg_rect_clip_cs(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment); static void cg_rect_clip_lb(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment); static void cg_rect_clip_nln(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment); static void cg_rect_clip(enum cg_rect_clip_method method); /* Obligatory basic callbacks for the "Rectangle" menu items. */ void cg_rectangle_cs(GtkWidget *w, gpointer data) { g_message ("Hello, cg_rectangle_cs!\n"); cg_rect_clip(CG_RCT_COHEN_SUTHERLAND); } void cg_rectangle_lb(GtkWidget *w, gpointer data) { g_message ("Hello, cg_rectangle_lb!\n"); cg_rect_clip(CG_RCT_LIANG_BARSKY); } void cg_rectangle_nln(GtkWidget *w, gpointer data) { g_message ("Hello, cg_rectangle_nln!\n"); cg_rect_clip(CG_RCT_NICHOLL_LEE_NICHOLL); } /* * A global structure to hold the info for the segment * that is being clipped. */ static struct _cg_rectangle_clip { gboolean seg_set; /* segment line defined*/ gulong button_id; /* button press/release handler id */ gulong motion_id; /* mouse motion handler id */ cg_rect_clip_cb clip_cb; /* the clipping callback */ struct cg_segment_line segment; /* the segment line being clipped */ struct cg_rectangle rectangle; /* restricting rectangle */ } cg_rectangle; /* * Helpers to sort four values in ascending order. */ struct sort_gint { gint val_; TAILQ_ENTRY(sort_gint) link; } sort_pts[4]; TAILQ_HEAD(sorted_l, sort_gint); struct sorted_l sorted_list; static void cg_insert_sorted(struct sorted_l *list, struct sort_gint *new_e) { struct sort_gint *temp; if ((temp = TAILQ_FIRST(list)) == NULL) TAILQ_INSERT_HEAD(list, new_e, link); else { while ((temp = TAILQ_NEXT(temp, link)) != NULL) { if (new_e->val_ < temp->val_) { TAILQ_INSERT_BEFORE(temp, new_e, link); return; } } TAILQ_INSERT_TAIL(list, new_e, link); } } static struct sorted_l * cg_sort_values(gint x1_, gint x2_, gint x3_, gint x4_) { gint i; sorted_list.tqh_first = NULL; sorted_list.tqh_last = &(sorted_list).tqh_first; bzero(&sort_pts, sizeof(sort_pts)); /* Sort the points - find x_min and y_min . */ sort_pts[0].val_ = x1_; sort_pts[1].val_ = x2_; sort_pts[2].val_ = x3_; sort_pts[3].val_ = x4_; for (i = 0; i < 4; i++) cg_insert_sorted(&sorted_list, &sort_pts[i]); return (&sorted_list); } /* Refresh the area where changes were made. */ static void cg_rect_clip_refresh(struct cg_rectangle *rectangle, struct cg_segment_line *segment) { GdkRectangle update_area; gint x_min, x_max, y_min, y_max; struct sorted_l *list; list = cg_sort_values(rectangle->x1_, rectangle->x2_, segment->x1_, segment->x2_); x_min = (TAILQ_FIRST(list))->val_; x_max = (TAILQ_LAST(list, sorted_l))->val_; list = cg_sort_values(rectangle->y1_, rectangle->y2_, segment->y1_, segment->y2_); y_min = (TAILQ_FIRST(list))->val_; y_max = (TAILQ_LAST(list, sorted_l))->val_; update_area.x = x_min; update_area.y = y_min; update_area.width = x_max - x_min + 1; update_area.height = y_max - y_min + 1; gtk_widget_draw(GTK_WIDGET(drawing_area), &update_area); } static void cg_rect_fix_line(GdkDrawable *drawable, GdkGC *gc, struct cg_segment_line *segment, gint x, gint y) { GtkWidget *toplevel; toplevel = gtk_widget_get_toplevel(GTK_WIDGET(drawing_area)); /* Clear previous line. */ gdk_draw_line(drawable, toplevel->style->white_gc, segment->x1_, segment->y1_, segment->x2_, segment->y2_); cg_line_drawing_refresh(segment->x1_, segment->y1_, segment->x2_, segment->y2_); segment->x2_ = x; segment->y2_ = y; /* Draw the new line. */ gdk_draw_line(drawable, gc, segment->x1_, segment->y1_, segment->x2_, segment->y2_); cg_line_drawing_refresh(segment->x1_, segment->y1_, segment->x2_, segment->y2_); } static void cg_rect_fix_clip(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, cg_rect_clip_cb clip_cb, struct cg_segment_line *segment, struct cg_rectangle *rectangle, gint x_new, gint y_new) { gint x, y, width, height; toplevel = gtk_widget_get_toplevel(GTK_WIDGET(drawing_area)); if ((width = rectangle->x1_ - rectangle->x2_) < 0) { x = rectangle->x1_; width = abs(width); } else x = rectangle->x2_; if ((height = rectangle->y1_ - rectangle->y2_) < 0) { y = rectangle->y1_; height = abs(height); } else y = rectangle->y2_; /* Clear previous rectangle and refresh drawing. */ gdk_draw_rectangle(drawable, toplevel->style->white_gc, FALSE, x, y, width, height); cg_line_drawing_refresh(x, y, x + width, y + height); /* Redo the line with the main color. */ gdk_draw_line(drawable, toplevel->style->fg_gc[w_state], segment->x1_, segment->y1_, segment->x2_, segment->y2_); cg_line_drawing_refresh(segment->x1_, segment->y1_, segment->x2_, segment->y2_); rectangle->x2_ = x_new; rectangle->y2_ = y_new; if ((width = rectangle->x1_ - rectangle->x2_) < 0) { x = rectangle->x1_; width = abs(width); } else x = rectangle->x2_; if ((height = rectangle->y1_ - rectangle->y2_) < 0) { y = rectangle->y1_; height = abs(height); } else y = rectangle->y2_; /* Draw the new rectangle and refresh drawing. */ gdk_draw_rectangle(drawable, toplevel->style->fg_gc[w_state], FALSE, x, y, width, height); cg_line_drawing_refresh(x, y, x + width, y + height); /* Clip the segment. */ clip_cb(drawable, toplevel, w_state, rectangle, segment); /* Refresh the drawing area. */ cg_rect_clip_refresh(rectangle, segment); } static gint cg_rect_motion_notify_event(GtkWidget *widget, GdkEventMotion *event) { int x, y; GdkModifierType state; GtkWidget *toplevel; if (event->is_hint) gdk_window_get_pointer (event->window, &x, &y, &state); else { x = event->x; y = event->y; state = event->state; } if (cg_pixmap == NULL || (state & GDK_BUTTON1_MASK) == 0) return (TRUE); toplevel = gtk_widget_get_toplevel(GTK_WIDGET(drawing_area)); if (!cg_rectangle.seg_set) { cg_rect_fix_line(cg_pixmap, toplevel->style->fg_gc[GTK_WIDGET_STATE(widget)], &cg_rectangle.segment, x, y); return (TRUE); } cg_rect_fix_clip(cg_pixmap, toplevel, GTK_WIDGET_STATE(widget), cg_rectangle.clip_cb, &cg_rectangle.segment, &cg_rectangle.rectangle, x, y); return (TRUE); } static gint cg_rect_button_press_event(GtkWidget *widget, GdkEventButton *event); static gint cg_rect_button_release_event(GtkWidget *widget, GdkEventButton *event) { GtkWidget *toplevel; if (cg_pixmap == NULL || event->button != 1) return (TRUE); /* Unconnect the motion and the button release signals. */ g_signal_handler_disconnect(GTK_OBJECT(drawing_area), cg_rectangle.motion_id); g_signal_handler_disconnect(GTK_OBJECT(drawing_area), cg_rectangle.button_id); toplevel = gtk_widget_get_toplevel(GTK_WIDGET(drawing_area)); if (!cg_rectangle.seg_set) { cg_rect_fix_line(cg_pixmap, toplevel->style->fg_gc[GTK_WIDGET_STATE(widget)], &cg_rectangle.segment, event->x, event->y); cg_rectangle.seg_set = TRUE; /* Hook the button press signal again. */ cg_rectangle.button_id = g_signal_connect(GTK_OBJECT(drawing_area), "button_press_event", (GtkSignalFunc) cg_rect_button_press_event, NULL); return (TRUE); } cg_rect_fix_clip(cg_pixmap, toplevel, GTK_WIDGET_STATE(widget), cg_rectangle.clip_cb, &cg_rectangle.segment, &cg_rectangle.rectangle, event->x, event->y); return (TRUE); } static gint cg_rect_button_press_event(GtkWidget *widget, GdkEventButton *event) { if (cg_pixmap == NULL || event->button != 1) return (TRUE); if (!cg_rectangle.seg_set) { cg_rectangle.segment.x1_ = event->x; cg_rectangle.segment.y1_ = event->y; } else { cg_rectangle.rectangle.x1_ = event->x; cg_rectangle.rectangle.y1_ = event->y; } /* Unconnect the button press signal. */ g_signal_handler_disconnect(GTK_OBJECT(drawing_area), cg_rectangle.button_id); /* Connect the motion and the button release signal handler. */ cg_rectangle.button_id = g_signal_connect(GTK_OBJECT(drawing_area), "button_release_event", (GtkSignalFunc) cg_rect_button_release_event, NULL); cg_rectangle.motion_id = g_signal_connect(GTK_OBJECT(drawing_area), "motion_notify_event", (GtkSignalFunc) cg_rect_motion_notify_event, NULL); return (TRUE); } static void cg_rect_clip(enum cg_rect_clip_method method) { bzero(&cg_rectangle, sizeof(cg_rectangle)); switch (method) { case CG_RCT_COHEN_SUTHERLAND: cg_rectangle.clip_cb = cg_rect_clip_cs; break; case CG_RCT_LIANG_BARSKY: cg_rectangle.clip_cb = cg_rect_clip_lb; break; case CG_RCT_NICHOLL_LEE_NICHOLL: cg_rectangle.clip_cb = cg_rect_clip_nln; break; default: return; } cg_rectangle.button_id = g_signal_connect(GTK_OBJECT(drawing_area), "button_press_event", (GtkSignalFunc) cg_rect_button_press_event, NULL); } enum cg_segment_cs_e { CG_SEG_CS_UP = 0, CG_SEG_CS_DOWN = 1, CG_SEG_CS_RIGHT = 2, CG_SEG_CS_LEFT = 3, }; #define CG_SBIT_ISSET(bitmap, bit) ((bitmap) & (1 << (bit))) #define CG_SBIT_SET(bitmap, bit) ((bitmap) |= (1 << (bit))) #define CG_SBIT_CLEAR(bitmap, bit) ((bitmap) &= ~(1 << (bit))) gushort cs_get_cs_bits(gint x, gdouble y, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max) { gushort bitmap = 0; if (x > x_max) CG_SBIT_SET(bitmap, CG_SEG_CS_RIGHT); else if (x < x_min) CG_SBIT_SET(bitmap, CG_SEG_CS_LEFT); if (y > y_max) CG_SBIT_SET(bitmap, CG_SEG_CS_UP); else if (y < y_min) CG_SBIT_SET(bitmap, CG_SEG_CS_DOWN); return (bitmap); } static void cg_rect_drawing_refresh(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3, gint x4, gint y4) { gint x_min, x_max, y_min, y_max; x_min = x_max = x1; y_min = y_max = y1; /* Refresh drawing area. */ if (x2 < x_min) x_min = x2; if (x2 > x_max) x_min = x2; if (x3 < x_min) x_min = x3; if (x3 > x_max) x_max = x3; if (x4 < x_min) x_min = x4; if (x4 > x_max) x_max = x4; if (y2 < y_min) y_min = y2; if (y2 > y_max) y_max = y2; if (y3 < y_min) y_min = y3; if (y3 > y_max) y_max = y3; if (y4 < y_min) y_min = y4; if (y4 > y_max) y_max = y4; cg_line_drawing_refresh(x_min, y_min, x_max, y_max); } struct cg_seg_fp { gdouble x1_; gdouble y1_; gdouble x2_; gdouble y2_; }; static void cg_rect_clip_cs(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment) { gint i; gdouble delta; gdouble z, x_min, x_max, y_min, y_max; gushort bitmaps[2]; struct cg_seg_fp seg; seg.x1_ = segment->x1_; seg.y1_ = segment->y1_; seg.x2_ = segment->x2_; seg.y2_ = segment->y2_; if (rectangle->x1_ > rectangle->x2_) { x_min = rectangle->x2_; x_max = rectangle->x1_; } else if (rectangle->x1_ < rectangle->x2_) { x_min = rectangle->x1_; x_max = rectangle->x2_; } else return; if (rectangle->y1_ < rectangle->y2_) { y_min = rectangle->y1_; y_max = rectangle->y2_; } else if (rectangle->y1_ > rectangle->y2_) { y_min = rectangle->y2_; y_max = rectangle->y1_; } else return; delta = (gdouble) (seg.y2_ - seg.y1_) / (gdouble) (seg.x2_ - seg.x1_); for (i = 0; i < 16; i++) { bitmaps[0] = cs_get_cs_bits(seg.x1_, seg.y1_, x_min, x_max, y_min, y_max); bitmaps[1] = cs_get_cs_bits(seg.x2_, seg.y2_, x_min, x_max, y_min, y_max); if ((bitmaps[0] & bitmaps[1]) != 0) return; if (bitmaps[0] == 0 && bitmaps[1] == 0) { /* We're done. */ gdk_draw_line(drawable, toplevel->style->mid_gc[w_state], seg.x1_, seg.y1_, seg.x2_, seg.y2_); cg_line_drawing_refresh(seg.x1_, seg.y1_, seg.x2_, seg.y2_); return; } if (CG_SBIT_ISSET(bitmaps[0], CG_SEG_CS_UP)) { /* Cut the upper part of point 1. */ z = (1. / delta) * (y_max - seg.y1_) + seg.x1_; seg.x1_ = z; seg.y1_ = y_max; continue; } if (CG_SBIT_ISSET(bitmaps[1], CG_SEG_CS_UP)) { /* Cut the upper part of point 2. */ z = (1. / delta) * (y_max - seg.y1_) + seg.x1_; seg.x2_ = z; seg.y2_ = y_max; continue; } if (CG_SBIT_ISSET(bitmaps[0], CG_SEG_CS_DOWN)) { /* Cut the lower part of point 1. */ z = (1. / delta) * (y_min - seg.y1_) + seg.x1_; seg.x1_ = z; seg.y1_ = y_min; continue; } if (CG_SBIT_ISSET(bitmaps[1], CG_SEG_CS_DOWN)) { /* Cut the lower part of point 2. */ z = (1. / delta) * (y_min - seg.y1_) + seg.x1_; seg.x2_ = z; seg.y2_ = y_min; continue; } if (CG_SBIT_ISSET(bitmaps[0], CG_SEG_CS_RIGHT)) { /* Cut the right part of point 1. */ z = delta * (x_max - seg.x1_) + seg.y1_; seg.x1_ = x_max; seg.y1_ = z; continue; } if (CG_SBIT_ISSET(bitmaps[1], CG_SEG_CS_RIGHT)) { /* Cut the right part of point 2. */ z = delta * (x_max - seg.x1_) + seg.y1_; seg.x2_ = x_max; seg.y2_ = z; continue; } if (CG_SBIT_ISSET(bitmaps[0], CG_SEG_CS_LEFT)) { /* Cut the left part of point 1. */ z = delta * (x_min - seg.x1_) + seg.y1_; seg.x1_ = x_min; seg.y1_ = z; continue; } if (CG_SBIT_ISSET(bitmaps[1], CG_SEG_CS_LEFT)) { /* Cut the left part of point 2. */ z = delta * (x_min - seg.x1_) + seg.y1_; seg.x2_ = x_min; seg.y2_ = z; continue; } } g_message ("rectangle - FAILED!!!"); } static void cg_rect_clip_lb(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment) { gint i; gdouble x_min, x_max, y_min, y_max, dx, dy, R[4], Q[4]; gdouble t[4] = { 0, 0, 0, 0 }, t_in, t_out; if (rectangle->x1_ > rectangle->x2_) { x_min = rectangle->x2_; x_max = rectangle->x1_; } else if (rectangle->x1_ < rectangle->x2_) { x_min = rectangle->x1_; x_max = rectangle->x2_; } else return; if (rectangle->y1_ < rectangle->y2_) { y_min = rectangle->y1_; y_max = rectangle->y2_; } else if (rectangle->y1_ > rectangle->y2_) { y_min = rectangle->y2_; y_max = rectangle->y1_; } else return; dx = segment->x2_ - segment->x1_; dy = segment->y2_ - segment->y1_; R[0] = 0 - dx; R[1] = dx; R[2] = 0 - dy; R[3] = dy; Q[0] = segment->x1_ - x_min; Q[1] = x_max - segment->x1_; Q[2] = segment->y1_ - y_min; Q[3] = y_max - segment->y1_; for (i = 0; i < 4; i++) { if (R[i] != 0) t[i] = Q[i] / R[i]; else if (Q[i] < 0) return; } for (i = 0, t_in = 0; i < 4; i++) { if (t_in < t[i] && R[i] < 0) t_in = t[i]; } for (i = 0, t_out = 1; i < 4; i++) { if (t_out > t[i] && R[i] > 0) t_out = t[i]; } if (t_in > t_out) return; gdk_draw_line(drawable, toplevel->style->mid_gc[w_state], segment->x1_ + t_in * dx, segment->y1_ + t_in * dy, segment->x1_ + t_out * dx, segment->y1_ + t_out *dy); x_min = segment->x1_ + t_in * dx; x_max = segment->x1_ + t_out * dx; y_min = segment->y1_ + t_in * dy; y_max = segment->y1_ + t_out *dy; /* Refresh drawing area. */ cg_rect_drawing_refresh(x_min, y_min, x_max, y_max, rectangle->x1_, rectangle->y1_, rectangle->x2_, rectangle->y2_); } #define VECTOR_PR(x1, x2, x3, y1, y2, y3) \ ((y2) - (y1))*((x3) - (x1)) -\ ((x2) - (x1))*((y3) - (y1)) static void cg_rect_clip_nln_ld(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { gdouble vector_pr, dydx, x_init, y_init; if (seg->x2_ < x_min || seg->y2_ < y_min) return; vector_pr = VECTOR_PR(seg->x1_, seg->x2_, x_min, seg->y1_, seg->y2_, y_min); dydx = (seg->y2_ - seg->y1_) / (seg->x2_ - seg->x1_); x_init = seg->x1_; y_init = seg->y1_; if (vector_pr > 0) { if (seg->y2_ <= y_max) { /* (x2_, y2_) is inside the rectangle, clip (x1_, y1_) */ seg->y1_ += dydx * (x_min - seg->x1_); seg->x1_ = x_min; if (seg->x2_ > x_max) { seg->y2_ = y_init + dydx * (x_max - x_init); seg->x2_ = x_max; } } else { if (VECTOR_PR(x_init, seg->x2_, x_min, y_init, seg->y2_, y_max) > 0) return; seg->y1_ += dydx * (x_min - seg->x1_); seg->x1_ = x_min; if (seg->x2_ <= x_max) { seg->y2_ = y_max; seg->x2_ = x_init + (y_max - y_init) * (1. / dydx); } else if (VECTOR_PR(x_init, seg->x2_, x_max, y_init, seg->y2_, y_max) > 0) { seg->y2_ = y_max; seg->x2_ = x_init + (y_max - y_init) * (1. / dydx); } else { seg->x2_ = x_max; seg->y2_ = y_init + dydx * (x_max - x_init); } } } else { if (seg->x2_ <= x_max) { seg->x1_ = x_init + (y_min - y_init) * (1. / dydx); seg->y1_ = y_min; if (seg->y2_ > y_max) { seg->y2_ = y_max; seg->x2_ = x_init + (y_max - y_init) * (1/dydx); } } else { if (VECTOR_PR(x_init, seg->x2_, x_max, y_init, seg->y2_, y_min) < 0) return; seg->x1_ = x_init + (y_min - y_init) * (1. / dydx); seg->y1_ = y_min; if (seg->y2_ <= y_max) { seg->x2_ = x_max; seg->y2_ = y_init + dydx * (x_max - x_init); } else if (VECTOR_PR(x_init, seg->x2_, x_max, y_init, seg->y2_, y_max) > 0) { seg->y2_ = y_max; seg->x2_ = x_init + (y_max - y_init) * (1. / dydx); } else { seg->x2_ = x_max; seg->y2_ = y_init + dydx * (x_max - x_init); } } } /* We're done. */ gdk_draw_line(drawable, toplevel->style->mid_gc[w_state], seg->x1_, seg->y1_, seg->x2_, seg->y2_); cg_rect_drawing_refresh(seg->x1_, seg->y1_, seg->x2_, seg->y2_, x_min, y_min, x_max, y_max); } static void cg_rect_clip_nln_cd(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_rd(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_lc(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_cc(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_rc(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_lu(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_cu(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln_ru(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, gdouble x_min, gdouble x_max, gdouble y_min, gdouble y_max, struct cg_seg_fp *seg) { } static void cg_rect_clip_nln(GdkDrawable *drawable, GtkWidget *toplevel, GtkStateType w_state, struct cg_rectangle *rectangle, struct cg_segment_line *segment) { gdouble x_min, x_max, y_min, y_max; struct cg_seg_fp seg; seg.x1_ = segment->x1_; seg.y1_ = segment->y1_; seg.x2_ = segment->x2_; seg.y2_ = segment->y2_; if (rectangle->x1_ > rectangle->x2_) { x_min = rectangle->x2_; x_max = rectangle->x1_; } else if (rectangle->x1_ < rectangle->x2_) { x_min = rectangle->x1_; x_max = rectangle->x2_; } else return; if (rectangle->y1_ < rectangle->y2_) { y_min = rectangle->y1_; y_max = rectangle->y2_; } else if (rectangle->y1_ > rectangle->y2_) { y_min = rectangle->y2_; y_max = rectangle->y1_; } else return; if (seg.x1_ < x_min && seg.y1_ < y_min) { /* Left-Down Area - 1 */ cg_rect_clip_nln_ld(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_min && seg.x1_ < x_max && seg.y1_ < y_min) { /* Center-Down Area - 2 */ cg_rect_clip_nln_cd(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_max && seg.y1_ < y_min) { /* Right-Down Area - 3 */ cg_rect_clip_nln_rd(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ < x_min && seg.y1_ >= y_min && seg.y1_ < y_max) { /* Left-Center Area - 4 */ cg_rect_clip_nln_lc(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_min && seg.x1_ < x_max && seg.y1_ >= y_min && seg.y1_ < y_max) { /* Center-Center Area - 5 */ cg_rect_clip_nln_cc(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_max && seg.y1_ >= y_min && seg.y1_ < y_max) { /* Right-Center Area - 6 */ cg_rect_clip_nln_rc(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ < x_min && seg.y1_ >= y_max) { /* Left-Upper Area - 7 */ cg_rect_clip_nln_lu(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_min && seg.x1_ < x_max && seg.y1_ >= y_max) { /* Center-Upper Area - 8 */ cg_rect_clip_nln_cu(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else if (seg.x1_ >= x_max && seg.y1_ >= y_max) { /* Right-Upper Area - 9 */ cg_rect_clip_nln_ru(drawable, toplevel, w_state, x_min, x_max, y_min, y_max, &seg); } else { g_message("NLN - Unknown Area!\n"); return; } }