void eda_cairo_arc (cairo_t *cr, int flags, double width, double x, double y, double radius, double start_angle, double sweep_angle) { int s_width; double x1, y1, x2, y2; double s_x, s_y, s_radius; double offset, dummy = 0; if (!(flags & EDA_CAIRO_ENABLE_HINTS)) { do_arc (cr, x, y, radius, start_angle, sweep_angle); return; } WORLDtoSCREEN (cr, x - radius, y + radius, &x1, &y1); WORLDtoSCREEN (cr, x + radius, y - radius, &x2, &y2); s_width = screen_width (cr, width); offset = ((s_width % 2) == 0) ? 0 : 0.5; s_x = (double)(x1 + x2) / 2.; s_y = (double)(y1 + y2) / 2.; s_radius = (double)(y2 - y1) / 2.; cairo_device_to_user (cr, &s_x, &s_y); cairo_device_to_user_distance (cr, &offset, &dummy); cairo_device_to_user_distance (cr, &s_radius, &dummy); do_arc (cr, s_x + offset, s_y + offset, s_radius, start_angle, sweep_angle); }
void eda_cairo_box (cairo_t *cr, int flags, double line_width, double x1, double y1, double x2, double y2) { int s_line_width; double s_x1, s_y1, s_x2, s_y2; double offset; if (!(flags & EDA_CAIRO_ENABLE_HINTS)) { cairo_rectangle (cr, x1, y1, (x2 - x1), (y2 - y1)); return; } WORLDtoSCREEN (cr, x1, y1, &s_x1, &s_y1); WORLDtoSCREEN (cr, x2, y2, &s_x2, &s_y2); s_line_width = screen_width (cr, line_width); offset = (line_width == -1 || (s_line_width % 2) == 0) ? 0 : 0.5; /* Allow filled boxes (inferred from line_width == -1) * to touch an extra pixel, so the filled span is inclusive */ if (line_width == -1) { if (s_x1 > s_x2) s_x1 += 1; else s_x2 += 1; if (s_y1 > s_y2) s_y1 += 1; else s_y2 += 1; } s_x1 += offset; s_y1 += offset; s_x2 += offset; s_y2 += offset; cairo_device_to_user (cr, &s_x1, &s_y1); cairo_device_to_user (cr, &s_x2, &s_y2); cairo_move_to (cr, s_x2, s_y2); cairo_line_to (cr, s_x1, s_y2); cairo_line_to (cr, s_x1, s_y1); cairo_line_to (cr, s_x2, s_y1); cairo_close_path (cr); }
void gschem_cairo_arc (GSCHEM_TOPLEVEL *w_current, int width, int x, int y, int radius, int start_angle, int end_angle) { int s_width; int x1, y1, x2, y2; double s_x, s_y, s_radius; double offset; WORLDtoSCREEN (w_current, x - radius, y + radius, &x1, &y1); WORLDtoSCREEN (w_current, x + radius, y - radius, &x2, &y2); s_width = screen_width (w_current, width); offset = ((s_width % 2) == 0) ? 0 : 0.5; s_x = (double)(x1 + x2) / 2.; s_y = (double)(y1 + y2) / 2.; s_radius = (double)(y2 - y1) / 2.; cairo_save (w_current->cr); cairo_translate (w_current->cr, s_x + offset, s_y + offset); /* Adjust for non-uniform X/Y scale factor. Note that the + 1 allows for the case where x2 == x1 or y2 == y1 */ cairo_scale (w_current->cr, (double)(x2 - x1 + 1) / (double)(y2 - y1 + 1), 1.); do_arc (w_current->cr, 0., 0., (double) s_radius, start_angle, end_angle); cairo_restore (w_current->cr); }
void gschem_cairo_box (GSCHEM_TOPLEVEL *w_current, int line_width, int x1, int y1, int x2, int y2) { int s_line_width; int s_x1, s_y1, s_x2, s_y2; double offset; WORLDtoSCREEN (w_current, x1, y1, &s_x1, &s_y1); WORLDtoSCREEN (w_current, x2, y2, &s_x2, &s_y2); s_line_width = screen_width (w_current, line_width); offset = (line_width == -1 || (s_line_width % 2) == 0) ? 0 : 0.5; /* Allow filled boxes (inferred from line_width == -1) * to touch an extra pixel, so the filled span is inclusive */ if (line_width == -1) { if (x1 > x2) x1 += 1; else x2 += 1; if (y1 > y2) y1 += 1; else y2 += 1; } cairo_move_to (w_current->cr, s_x2 + offset, s_y2 + offset); cairo_line_to (w_current->cr, s_x1 + offset, s_y2 + offset); cairo_line_to (w_current->cr, s_x1 + offset, s_y1 + offset); cairo_line_to (w_current->cr, s_x2 + offset, s_y1 + offset); cairo_close_path (w_current->cr); }
/*! \todo Finish function documentation * \brief * \par Function Description */ void o_line_invalidate_rubber (GSCHEM_TOPLEVEL *w_current) { int x1, y1, x2, y2; WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &x1, &y1); WORLDtoSCREEN (w_current, w_current->second_wx, w_current->second_wy, &x2, &y2); o_invalidate_rect (w_current, x1, y1, x2, y2); }
void gschem_cairo_line (GSCHEM_TOPLEVEL *w_current, int line_end, int w_line_width, int w_x1, int w_y1, int w_x2, int w_y2) { int x1, y1, x2, y2, line_width; double offset; double xoffset = 0; double yoffset = 0; int horizontal = 0; int vertical = 0; WORLDtoSCREEN (w_current, w_x1, w_y1, &x1, &y1); WORLDtoSCREEN (w_current, w_x2, w_y2, &x2, &y2); line_width = screen_width (w_current, w_line_width); offset = ((line_width % 2) == 0) ? 0 : 0.5; if (y1 == y2) horizontal = 1; if (x1 == x2) vertical = 1; /* Hint so the length of the line runs along a pixel boundary */ if (horizontal) yoffset = offset; else if (vertical) xoffset = offset; else xoffset = yoffset = offset; /* Now hint the ends of the lines */ switch (line_end) { case END_NONE: /* Line terminates at the passed coordinate */ /* Add an extra pixel to give an inclusive span */ if (horizontal) { if (x1 > x2) x1 += 1; else x2 += 1; } else if (vertical) { if (y1 > y2) y1 += 1; else y2 += 1; } break; case END_SQUARE: case END_ROUND: /* Line terminates half a width away from the passed coordinate */ if (horizontal) { xoffset = offset; } else if (vertical) { yoffset = offset; } break; } cairo_move_to (w_current->cr, x1 + xoffset, y1 + yoffset); cairo_line_to (w_current->cr, x2 + xoffset, y2 + yoffset); }
/*! \brief Invalidate bounding box or outline for OBJECT placement * * \par Function Description * This function invalidates the bounding box where objects would be * drawn by o_place_draw_rubber() * * The function applies manhatten mode constraints to the coordinates * before drawing if the CONTROL key is recording as being pressed in * the w_current structure. * * The "drawing" parameter is used to indicate if this drawing should * immediately use the selected feedback mode and positioning constraints. * * With drawing=TRUE, the selected conditions are used immediately, * otherwise the conditions from the last drawing operation are used, * saving the new state for next time. * * This function should be called with drawing=TRUE when starting a * rubberbanding operation and when otherwise refreshing the rubberbanded * outline (e.g. after a screen redraw). For any undraw operation, should * be called with drawing=FALSE, ensuring that the undraw XOR matches the * mode and constraints of the corresponding "draw" operation. * * If any mode / constraint changes are made between a undraw, redraw XOR * pair, the latter (draw) operation must be called with drawing=TRUE. If * no mode / constraint changes were made between the pair, it is not * harmful to call the draw operation with "drawing=FALSE". * * \param [in] w_current GSCHEM_TOPLEVEL which we're drawing for. * \param [in] drawing Set to FALSE for undraw operations to ensure * matching conditions to a previous draw operation. */ void o_place_invalidate_rubber (GSCHEM_TOPLEVEL *w_current, int drawing) { TOPLEVEL *toplevel = w_current->toplevel; int diff_x, diff_y; int left, top, bottom, right; int s_left, s_top, s_bottom, s_right; g_return_if_fail (toplevel->page_current->place_list != NULL); /* If drawing is true, then don't worry about the previous drawing * method and movement constraints, use with the current settings */ if (drawing) { /* Ensure we set this to flag there is "something" supposed to be * drawn when the invaliate call below causes an expose event. */ w_current->last_drawb_mode = w_current->actionfeedback_mode; w_current->drawbounding_action_mode = (w_current->CONTROLKEY) ? CONSTRAINED : FREE; } /* Calculate delta of X-Y positions from buffer's origin */ diff_x = w_current->second_wx - w_current->first_wx; diff_y = w_current->second_wy - w_current->first_wy; /* Adjust the coordinates according to the movement constraints */ /* Need to update the w_current->{first,second}_w{x,y} coords even * though we're only invalidating because the move rubberband code * (which may execute right after this function) expects these * coordinates to be correct. */ if (w_current->drawbounding_action_mode == CONSTRAINED) { if (abs (diff_x) >= abs (diff_y)) { w_current->second_wy = w_current->first_wy; diff_y = 0; } else { w_current->second_wx = w_current->first_wx; diff_x = 0; } } /* Find the bounds of the drawing to be done */ world_get_object_glist_bounds (toplevel, toplevel->page_current->place_list, &left, &top, &right, &bottom); WORLDtoSCREEN (w_current, left + diff_x, top + diff_y, &s_left, &s_top); WORLDtoSCREEN (w_current, right + diff_x, bottom + diff_y, &s_right, &s_bottom); o_invalidate_rect (w_current, s_left, s_top, s_right, s_bottom); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_net_invalidate_rubber (GSCHEM_TOPLEVEL *w_current) { TOPLEVEL *toplevel = w_current->toplevel; int size = 0, magnetic_halfsize; int bloat; int magnetic_x, magnetic_y; int first_x, first_y, third_x, third_y, second_x, second_y; int x1, y1, x2, y2; WORLDtoSCREEN (w_current, w_current->magnetic_wx, w_current->magnetic_wy, &magnetic_x, &magnetic_y); WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &first_x, &first_y); WORLDtoSCREEN (w_current, w_current->third_wx, w_current->third_wy, &third_x, &third_y); WORLDtoSCREEN (w_current, w_current->second_wx, w_current->second_wy, &second_x, &second_y); if (toplevel->net_style == THICK) { size = SCREENabs (w_current, NET_WIDTH); } size = max (size, 0); bloat = size / 2; if (w_current->magneticnet_mode) { if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) { magnetic_halfsize = max (4 * size, MAGNETIC_HALFSIZE); o_invalidate_rect (w_current, magnetic_x - magnetic_halfsize, magnetic_y - magnetic_halfsize, magnetic_x + magnetic_halfsize, magnetic_y + magnetic_halfsize); } } x1 = min (first_x, second_x) - bloat; x2 = max (first_x, second_x) + bloat; y1 = min (first_y, second_y) - bloat; y2 = max (first_y, second_y) + bloat; o_invalidate_rect (w_current, x1, y1, x2, y2); x1 = min (second_x, third_x) - bloat; x2 = max (second_x, third_x) + bloat; y1 = min (second_y, third_y) - bloat; y2 = max (second_y, third_y) + bloat; o_invalidate_rect (w_current, x1, y1, x2, y2); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description */ void o_pin_invalidate_rubber (GSCHEM_TOPLEVEL *w_current) { TOPLEVEL *toplevel = w_current->toplevel; int x1, y1, x2, y2; int min_x, min_y, max_x, max_y; int bloat = 0; WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &x1, &y1); WORLDtoSCREEN (w_current, w_current->second_wx, w_current->second_wy, &x2, &y2); /* Pins are always first created as net pins, use net pin width */ if (toplevel->net_style == THICK ) { bloat = SCREENabs (w_current, PIN_WIDTH_NET) / 2; } min_x = min (x1, x2) - bloat; max_x = max (x1, x2) + bloat; min_y = min (y1, y2) - bloat; max_y = max (y1, y2) + bloat; o_invalidate_rect (w_current, min_x, min_y, max_x, max_y); }
void eda_cairo_center_arc (cairo_t *cr, int flags, double center_width, double line_width, double x, double y, double radius, double start_angle, double sweep_angle) { int s_center_width, s_line_width; double s_x, s_y, dummy = 0; int s_diameter; double even_center_width; double even_line_width; double even_diameter; double center_offset; double s_radius; int do_radius_hint = TRUE; if (!(flags & EDA_CAIRO_ENABLE_HINTS)) { do_arc (cr, x, y, radius, start_angle, sweep_angle); return; } WORLDtoSCREEN (cr, x, y, &s_x, &s_y); s_diameter = SCREENabs (cr, 2 * radius); even_diameter = ((s_diameter % 2) == 0); s_radius = (double) s_diameter / 2.; /* Switch off radius hinting for small radii. If we don't, then we get * a very abrupt transition once the arc reaches a single pixel size. */ if (s_radius <= 1.) do_radius_hint = FALSE; /* Hint the center of the arc based on where a line * of thickness center_width (world) would drawn */ s_center_width = screen_width (cr, center_width); even_center_width = (center_width == -1 || (s_center_width % 2) == 0); center_offset = even_center_width ? 0. : 0.5; /* Hint the radius to land its extermity on the pixel grid */ s_line_width = screen_width (cr, line_width); even_line_width = (line_width == -1 || (s_line_width % 2) == 0); if (do_radius_hint) s_radius += ((even_center_width == even_line_width) == even_diameter) ? 0. : 0.5; s_x += center_offset; s_y += center_offset; cairo_device_to_user (cr, &s_x, &s_y); cairo_device_to_user_distance (cr, &s_radius, &dummy); do_arc (cr, s_x, s_y, s_radius, start_angle, sweep_angle); }
void gschem_cairo_center_arc (GSCHEM_TOPLEVEL *w_current, int center_width, int line_width, int x, int y, int radius, int start_angle, int end_angle) { int s_center_width, s_line_width; int s_x, s_y, s_diameter; int even_center_width; int even_line_width; int even_diameter; double center_offset; double s_radius; int do_radius_hint = TRUE; WORLDtoSCREEN (w_current, x, y, &s_x, &s_y); s_diameter = SCREENabs (w_current, 2 * radius); even_diameter = ((s_diameter % 2) == 0); s_radius = (double) s_diameter / 2.; /* Switch off radius hinting for small radii. If we don't, then we get * a very abrupt transition once the arc reaches a single pixel size. */ if (s_radius <= 1.) do_radius_hint = FALSE; /* Hint the center of the arc based on where a line * of thickness center_width (world) would drawn */ s_center_width = screen_width (w_current, center_width); even_center_width = (center_width == -1 || (s_center_width % 2) == 0); center_offset = even_center_width ? 0. : 0.5; /* Hint the radius to land its extermity on the pixel grid */ s_line_width = screen_width (w_current, line_width); even_line_width = (line_width == -1 || (s_line_width % 2) == 0); if (do_radius_hint) s_radius += ((even_center_width == even_line_width) == even_diameter) ? 0. : 0.5; do_arc (w_current->cr, (double) s_x + center_offset, (double) s_y + center_offset, (double) s_radius, start_angle, end_angle); }
void eda_cairo_line (cairo_t *cr, int flags, int line_end, double w_line_width, double w_x1, double w_y1, double w_x2, double w_y2) { double x1, y1, x2, y2; int line_width; double offset; double xoffset = 0; double yoffset = 0; double horizontal = 0; double vertical = 0; if (!(flags & EDA_CAIRO_ENABLE_HINTS)) { cairo_move_to (cr, w_x1, w_y1); cairo_line_to (cr, w_x2, w_y2); return; } WORLDtoSCREEN (cr, w_x1, w_y1, &x1, &y1); WORLDtoSCREEN (cr, w_x2, w_y2, &x2, &y2); line_width = screen_width (cr, w_line_width); offset = ((line_width % 2) == 0) ? 0 : 0.5; if (y1 == y2) horizontal = 1; if (x1 == x2) vertical = 1; /* Hint so the length of the line runs along a pixel boundary */ if (horizontal) yoffset = offset; else if (vertical) xoffset = offset; else xoffset = yoffset = offset; /* Now hint the ends of the lines */ switch (line_end) { case END_NONE: /* Line terminates at the passed coordinate */ /* Add an extra pixel to give an inclusive span */ if (horizontal) { if (x1 > x2) x1 += 1; else x2 += 1; } else if (vertical) { if (y1 > y2) y1 += 1; else y2 += 1; } break; case END_SQUARE: case END_ROUND: /* Line terminates half a width away from the passed coordinate */ if (horizontal) { xoffset = offset; } else if (vertical) { yoffset = offset; } break; } x1 += xoffset; y1 += yoffset; x2 += xoffset; y2 += yoffset; cairo_device_to_user (cr, &x1, &y1); cairo_device_to_user (cr, &x2, &y2); cairo_move_to (cr, x1, y1); cairo_line_to (cr, x2, y2); }
void eda_cairo_center_box (cairo_t *cr, int flags, double center_width, double line_width, double x, double y, double half_width, double half_height) { int s_center_width, s_line_width; int s_width, s_height; double s_half_width, s_half_height; double s_x, s_y; double even_center_width; double even_line_width; double even_width, even_height; double x1, y1, x2, y2; double center_offset; int do_width_hint = TRUE; int do_height_hint = TRUE; if (!(flags & EDA_CAIRO_ENABLE_HINTS)) { cairo_rectangle (cr, (x - half_width), (y - half_height), 2*half_width, 2*half_height); return; } WORLDtoSCREEN (cr, x, y, &s_x, &s_y); s_width = SCREENabs (cr, 2 * half_width); s_height = SCREENabs (cr, 2 * half_height); even_width = (s_width % 2 == 0); even_height = (s_width % 2 == 0); s_half_width = (double) s_width / 2.; s_half_height = (double) s_height / 2.; #if 0 /* Not as nice an effect as with arcs */ /* Switch off radius hinting for small radii. If we don't, then we get * a very abrupt transition once the box reaches a single pixel size. */ if (s_half_width <= 1.) do_width_hint = FALSE; if (s_half_height <= 1.) do_height_hint = FALSE; #endif /* Hint the center of the box based on where a line * of thickness center_width (world) would drawn */ s_center_width = screen_width (cr, center_width); even_center_width = (center_width == -1 || (s_center_width % 2) == 0); center_offset = even_center_width ? 0. : 0.5; /* Hint the half-widths to land the stroke on the pixel grid */ s_line_width = screen_width (cr, line_width); even_line_width = (line_width == -1 || (s_line_width % 2) == 0); if (do_width_hint) s_half_width += ((even_center_width == even_line_width) == even_width ) ? 0. : 0.5; if (do_height_hint) s_half_height += ((even_center_width == even_line_width) == even_height) ? 0. : 0.5; x1 = (double) s_x + center_offset - s_half_width; y1 = (double) s_y + center_offset - s_half_height; x2 = (double) s_x + center_offset + s_half_width; y2 = (double) s_y + center_offset + s_half_height; /* Allow filled boxes (inferred from line_width == -1) * to touch an extra pixel, so the filled span is inclusive */ if (line_width == -1) { x2 += 1; y2 += 1; } cairo_device_to_user (cr, &x1, &y1); cairo_device_to_user (cr, &x2, &y2); cairo_move_to (cr, x2, y2); cairo_line_to (cr, x1, y2); cairo_line_to (cr, x1, y1); cairo_line_to (cr, x2, y1); cairo_close_path (cr); }
void gschem_cairo_center_box (GSCHEM_TOPLEVEL *w_current, int center_width, int line_width, int x, int y, int half_width, int half_height) { int s_center_width, s_line_width; int s_width, s_height; double s_half_width, s_half_height; int s_x, s_y; int even_center_width; int even_line_width; int even_width, even_height; double x1, y1, x2, y2; double center_offset; int do_width_hint = TRUE; int do_height_hint = TRUE; WORLDtoSCREEN (w_current, x, y, &s_x, &s_y); s_width = SCREENabs (w_current, 2 * half_width); s_height = SCREENabs (w_current, 2 * half_height); even_width = (s_width % 2 == 0); even_height = (s_width % 2 == 0); s_half_width = (double) s_width / 2.; s_half_height = (double) s_height / 2.; #if 0 /* Not as nice an effect as with arcs */ /* Switch off radius hinting for small radii. If we don't, then we get * a very abrupt transition once the box reaches a single pixel size. */ if (s_half_width <= 1.) do_width_hint = FALSE; if (s_half_height <= 1.) do_height_hint = FALSE; #endif /* Hint the center of the box based on where a line * of thickness center_width (world) would drawn */ s_center_width = screen_width (w_current, center_width); even_center_width = (center_width == -1 || (s_center_width % 2) == 0); center_offset = even_center_width ? 0. : 0.5; /* Hint the half-widths to land the stroke on the pixel grid */ s_line_width = screen_width (w_current, line_width); even_line_width = (line_width == -1 || (s_line_width % 2) == 0); if (do_width_hint) s_half_width += ((even_center_width == even_line_width) == even_width ) ? 0. : 0.5; if (do_height_hint) s_half_height += ((even_center_width == even_line_width) == even_height) ? 0. : 0.5; x1 = (double) s_x + center_offset - s_half_width; y1 = (double) s_y + center_offset - s_half_height; x2 = (double) s_x + center_offset + s_half_width; y2 = (double) s_y + center_offset + s_half_height; /* Allow filled boxes (inferred from line_width == -1) * to touch an extra pixel, so the filled span is inclusive */ if (line_width == -1) { x2 += 1; y2 += 1; } cairo_move_to (w_current->cr, x2, y2); cairo_line_to (w_current->cr, x1, y2); cairo_line_to (w_current->cr, x1, y1); cairo_line_to (w_current->cr, x2, y1); cairo_close_path (w_current->cr); }