/*! \brief Fill inside of box with single line pattern. * \par Function Description * This function fills the inside of the box with a pattern made of lines. * The lines are drawn inside the box with an angle <B>angle1</B> from the * horizontal. The distance between two of these lines is given by * <B>pitch1</B> and their width by <B>fill_width</B>. * Parameters <B>angle2</B> and <B>pitch2</B> are unused here but kept for * compatbility with other box filling functions. * * The box is defined in the same way as it is in GDK : one point and the * width and height of the box. * * All parameters are given in pixel. * * Negative or null values for <B>pitch1</B> are not allowed as it leads to * an endless loop. * * \param [in] w_current Schematic top level * \param [in] color Box fill color. * \param [in] box Box definition * \param [in] fill_width BOX pattern fill width. * \param [in] angle1 1st angle for pattern. * \param [in] pitch1 1st pitch for pattern. * \param [in] angle2 (unused) * \param [in] pitch2 (unused) */ static void o_box_fill_hatch (GSCHEM_TOPLEVEL *w_current, COLOR *color, BOX *box, gint fill_width, gint angle1, gint pitch1, gint angle2, gint pitch2) { int i; GArray *lines; gschem_cairo_set_source_color (w_current, color); lines = g_array_new (FALSE, FALSE, sizeof (LINE)); m_hatch_box (box, angle1, pitch1, lines); for (i=0; i < lines->len; i++) { LINE *line = &g_array_index (lines, LINE, i); gschem_cairo_line (w_current, END_NONE, fill_width, line->x[0], line->y[0], line->x[1], line->y[1]); } gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, fill_width, -1, -1); g_array_free (lines, TRUE); }
/*! \brief Draw a line on screen. * \par Function Description * This function is used to draw a line on screen. The line is described * in the object which is referred by <B>o_current</B>. The line is displayed * according to the current state, described in the GSCHEM_TOPLEVEL object pointed * by <B>w_current</B>. * * It first checks if the object is valid or not. If not it returns and do * not output anything. That should never happen though. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] o_current The line OBJECT to draw. */ void o_line_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { int x1, y1, x2, y2; if (o_current->line == NULL) { return; } if (!o_line_visible (w_current, o_current->line, &x1, &y1, &x2, &y2)) { return; } gschem_cairo_line (w_current, o_current->line_end, o_current->line_width, x1, y1, x2, y2); gschem_cairo_set_source_color (w_current, o_drawing_color (w_current, o_current)); gschem_cairo_stroke (w_current, o_current->line_type, o_current->line_end, o_current->line_width, o_current->line_length, o_current->line_space); if (o_current->selected && w_current->draw_grips) { o_line_draw_grips (w_current, o_current); } }
/*! \brief draw rubbernet lines to the gc * \par Function Description * This function draws the rubbernets to the graphic context */ void o_net_draw_rubber(GSCHEM_TOPLEVEL *w_current) { int size = 0, w_magnetic_halfsize; if (w_current->toplevel->net_style == THICK) size = NET_WIDTH; gschem_cairo_set_source_color (w_current, x_color_lookup_dark (SELECT_COLOR)); if (w_current->magneticnet_mode) { if (w_current->magnetic_wx != -1 && w_current->magnetic_wy != -1) { w_magnetic_halfsize = max (4 * size, WORLDabs (w_current, MAGNETIC_HALFSIZE)); gschem_cairo_arc (w_current, size, w_current->magnetic_wx, w_current->magnetic_wy, w_magnetic_halfsize, 0, 360); } } /* Primary line */ gschem_cairo_line (w_current, END_NONE, size, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); /* Secondary line */ gschem_cairo_line (w_current, END_NONE, size, w_current->second_wx, w_current->second_wy, w_current->third_wx, w_current->third_wy); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, size, -1, -1); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_net_draw_stretch (GSCHEM_TOPLEVEL *w_current, int dx, int dy, int whichone, OBJECT *o_current) { int color; int dx1 = -1, dx2 = -1, dy1 = -1,dy2 = -1; if (o_current->line == NULL) { return; } if (o_current->saved_color != -1) { color = o_current->saved_color; } else { color = o_current->color; } if (whichone == 0) { dx1 = dx; dy1 = dy; dx2 = dy2 = 0; } else if (whichone == 1) { dx1 = dy1 = 0; dx2 = dx; dy2 = dy; } else { fprintf(stderr, _("Got an invalid which one in o_net_draw_stretch\n")); } gschem_cairo_line (w_current, END_NONE, 0, o_current->line->x[0] + dx1, o_current->line->y[0] + dy1, o_current->line->x[1] + dx2, o_current->line->y[1] + dy2); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (color)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); }
/*! \brief Draw box from GSCHEM_TOPLEVEL object. * \par Function Description * This function draws the box from the variables in the GSCHEM_TOPLEVEL * structure <B>*w_current</B>. * One corner of the box is at (<B>w_current->first_wx</B>, * <B>w_current->first_wy</B>) and the second corner is at * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * * \param [in] w_current The GSCHEM_TOPLEVEL object. */ void o_box_draw_rubber (GSCHEM_TOPLEVEL *w_current) { gschem_cairo_box (w_current, 0, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (SELECT_COLOR)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); }
/*! \brief Draw a bounding box or outline for OBJECT placement * * \par Function Description * This function draws either the OBJECTS in the place list * or a rectangle around their bounding box, depending upon the * currently selected w_current->actionfeedback_mode. This takes the * value BOUNDINGBOX or OUTLINE. * * 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_draw_rubber (GSCHEM_TOPLEVEL *w_current, int drawing) { TOPLEVEL *toplevel = w_current->toplevel; int diff_x, diff_y; int left, top, bottom, 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) { 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 */ 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; } } /* Draw with the appropriate mode */ if (w_current->last_drawb_mode == BOUNDINGBOX) { /* Find the bounds of the drawing to be done */ world_get_object_glist_bounds (toplevel, toplevel->page_current->place_list, &left, &top, &right, &bottom); gschem_cairo_box (w_current, 0, left + diff_x, top + diff_y, right + diff_x, bottom + diff_y); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (BOUNDINGBOX_COLOR)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); } else { o_glist_draw_place (w_current, diff_x, diff_y, toplevel->page_current->place_list); } /* Save movement constraints and drawing method for any * corresponding undraw operation. */ w_current->last_drawb_mode = w_current->actionfeedback_mode; w_current->drawbounding_action_mode = (w_current->CONTROLKEY) ? CONSTRAINED : FREE; }
/*! \brief Draw a line object after applying translation. * \par Function Description * This function is used to draw the line object described by * <B>*o_current</B> after applying a translation on the two directions of * <B>dx</B> and <B>dy</B> in world units. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] dx Delta x coordinate for line. * \param [in] dy Delta y coordinate for line. * \param [in] o_current Line OBJECT to draw. */ void o_line_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current) { if (o_current->line == NULL) { return; } gschem_cairo_line (w_current, END_NONE, 0, o_current->line->x[0] + dx, o_current->line->y[0] + dy, o_current->line->x[1] + dx, o_current->line->y[1] + dy); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (o_current->color)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); }
/*! \brief Draw a box described by OBJECT with translation * \par Function Description * This function daws the box object described by <B>*o_current</B> translated * by the vector (<B>dx</B>,<B>dy</B>). * The translation vector is in world unit. * * The box is displayed with the color of the object. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] dx Delta x coordinate for box. * \param [in] dy Delta y coordinate for box. * \param [in] o_current Box OBJECT to draw. */ void o_box_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current) { if (o_current->box == NULL) { return; } gschem_cairo_box (w_current, 0, o_current->box->upper_x + dx, o_current->box->upper_y + dy, o_current->box->lower_x + dx, o_current->box->lower_y + dy); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (o_current->color)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 1, -1, -1); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_pin_draw_rubber (GSCHEM_TOPLEVEL *w_current) { int size = 0; /* Pins are always first created as net pins, use net pin width */ if (w_current->toplevel->net_style == THICK) size = PIN_WIDTH_NET; gschem_cairo_line (w_current, END_NONE, size, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (SELECT_COLOR)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, size, -1, -1); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_net_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current) { int size = 0; if (o_current->line == NULL) { return; } if (w_current->toplevel->net_style == THICK) size = NET_WIDTH; gschem_cairo_line (w_current, END_NONE, size, o_current->line->x[0] + dx, o_current->line->y[0] + dy, o_current->line->x[1] + dx, o_current->line->y[1] + dy); gschem_cairo_set_source_color (w_current, x_color_lookup_dark (o_current->color)); gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, size, -1, -1); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_net_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { TOPLEVEL *toplevel = w_current->toplevel; int x1, y1, x2, y2; int size = 0; #if NET_DEBUG /* debug */ char *tempstring; GdkFont *font; #endif if (o_current == NULL) { return; } if (o_current->line == NULL) { return; } /* reuse line's routine */ if ( (toplevel->DONT_REDRAW == 1) || (!o_line_visible (w_current, o_current->line, &x1, &y1, &x2, &y2)) ) { return; } if (toplevel->net_style == THICK) size = NET_WIDTH; if (toplevel->override_color != -1 ) { gschem_cairo_set_source_color (w_current, x_color_lookup (toplevel->override_color)); } else { gschem_cairo_set_source_color (w_current, x_color_lookup (o_current->color)); } gschem_cairo_line (w_current, END_SQUARE, size, x1, y1, x2, y2); gschem_cairo_stroke (w_current, TYPE_SOLID, END_SQUARE, size, -1, -1); if (o_current->selected && w_current->draw_grips) { o_line_draw_grips (w_current, o_current); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_pin_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { TOPLEVEL *toplevel = w_current->toplevel; int x1, y1, x2, y2; int size = 0; OBJECT_END end; if (o_current->line == NULL) { return; } /* reuse line's routine */ if (!o_line_visible (w_current, o_current->line, &x1, &y1, &x2, &y2)) { return; } if (toplevel->pin_style == THICK) size = o_current->line_width; end = o_get_line_end (toplevel->print_output_capstyle); gschem_cairo_line (w_current, end, size, x1, y1, x2, y2); gschem_cairo_set_source_color (w_current, o_drawing_color (w_current, o_current)); gschem_cairo_stroke (w_current, TYPE_SOLID, end, size, -1, -1); /* draw the cue directly */ o_cue_draw_lowlevel(w_current, o_current, o_current->whichend); #if DEBUG printf("drawing pin\n"); #endif if (o_current->selected && w_current->draw_grips) { o_line_draw_grips (w_current, o_current); } }
/*! \brief Draw a box on the screen. * \par Function Description * This function is used to draw a box on screen. The box is described in * the OBJECT which is referred by <B>o_current</B>. The box is displayed * according to the current state, described in the GSCHEM_TOPLEVEL object * pointed by <B>w_current</B>. * * It first checks if the OBJECT pointed is valid or not. If not it * returns and do not output anything. That should never happen though. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] o_current BOX OBJECT to draw. */ void o_box_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { int angle1, pitch1, angle2, pitch2; FILL_FUNC fill_func; if (o_current->box == NULL) { return; } /* * The drawing of the box is divided in two steps : first step is to * draw the outline, the second is to draw the filling pattern inside * (if any). Finally the function takes care of the grips. */ /* * The values describing the line type are extracted from the <B>o_current</B> * pointed structure. These are the width of the line, the field called * length and the field called space and the desired end type for the line. * * Depending on the type of the line that has to be used to draw the box * the appropriate function is called. Values of space and length are * adapted to the type of line. The possible functions are the following : * #o_box_draw_solid(), #o_box_draw_dotted(), #o_box_draw_dashed() and * #o_box_draw_phantom(). * * The combination <B>length</B> == 0 and <B>space</B> == 0 is avoided as it * lead to an endless loop in function called after. If such a case is * encountered the box is drawn as a solid box independently of its * initial type. */ /* * The values needed for the fill operation are taken from the * <B>o_current</B> pointed OBJECT. It include the type of fill required, * the width of the lines (if the fill use line) and angles and pitchs * for hatch based filling. * * Once again the width of the line is important as if it is equal to * 0 it may not be displayed. That is definetely not what we are looking for. * * Depending on the type of fill that has to be used inside the box the * appropriate function is called. Values of <B>angle1</B>, * <B>angle2</B>, <B>pitch1</B> and <B>pitch2</B> are adapted to the type of * filling. The possible functions are the following : * #o_box_fill_hollow(), #o_box_fill_fill(), #o_box_fill_mesh() and * #o_box_fill_hatch(). * * The combination <B>pitch1</B> <= 0 and <B>pitch2</B> <= 0 is avoided as * it lead to an endless loop in function called after. It happens when * the zoom factor is too small for two lines separated by the pitch * to be distinct. If such a case is encountered the circle is filled * hollow (e.q. not filled). */ angle1 = o_current->fill_angle1; pitch1 = o_current->fill_pitch1; angle2 = o_current->fill_angle2; pitch2 = o_current->fill_pitch2; switch (o_current->fill_type) { case FILLING_HOLLOW: angle1 = -1; angle2 = -1; pitch1 = 1; pitch2 = 1; /* this function is empty ! however if it do not use it we have to add * a test before the call. Simply putting a return here instead is not * possible as it would prevent any hollow box from having its grips * drawn */ fill_func = o_box_fill_hollow; break; case FILLING_FILL: angle1 = -1; angle2 = -1; pitch1 = 1; pitch2 = 1; fill_func = o_box_fill_fill; break; case FILLING_MESH: fill_func = o_box_fill_mesh; break; case FILLING_HATCH: angle2 = -1; pitch2 = 1; fill_func = o_box_fill_hatch; break; case FILLING_VOID: default: angle1 = -1; angle2 = -1; pitch1 = 1; pitch2 = 1; fill_func = o_box_fill_hollow; fprintf (stderr, _("Unknown type for box (fill)!\n")); } if ((pitch1 <= 0) || (pitch2 <= 0)) fill_func = o_box_fill_fill; (*fill_func) (w_current, o_drawing_color (w_current, o_current), o_current->box, o_current->fill_width, angle1, pitch1, angle2, pitch2); gschem_cairo_set_source_color (w_current, o_drawing_color (w_current, o_current)); gschem_cairo_box (w_current, o_current->line_width, o_current->box->lower_x, o_current->box->lower_y, o_current->box->upper_x, o_current->box->upper_y); if (o_current->fill_type == FILLING_FILL) cairo_fill_preserve (w_current->cr); gschem_cairo_stroke (w_current, o_current->line_type, o_current->line_end, o_current->line_width, o_current->line_length, o_current->line_space); if (o_current->selected && w_current->draw_grips) o_box_draw_grips (w_current, o_current); }