/* Actually draws a page. If page is NULL, uses the first open page. */ static void export_draw_page (PAGE *page) { const GList *contents; GList *iter; cairo_t *cr; cr = eda_renderer_get_cairo_context (renderer); if (page == NULL) { const GList *pages = geda_list_get_glist (toplevel->pages); g_assert (pages != NULL && pages->data != NULL); page = (PAGE *) pages->data; } /* Draw background */ eda_cairo_set_source_color (cr, OUTPUT_BACKGROUND_COLOR, eda_renderer_get_color_map (renderer)); cairo_paint (cr); /* Draw objects & cues */ contents = s_page_objects (page); for (iter = (GList *) contents; iter != NULL; iter = g_list_next (iter)) eda_renderer_draw (renderer, (OBJECT *) iter->data); for (iter = (GList *) contents; iter != NULL; iter = g_list_next (iter)) eda_renderer_draw_cues (renderer, (OBJECT *) iter->data); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_move_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer) { GList *s_iter; int diff_x, diff_y; gboolean net_rubber_band_mode; g_return_if_fail (w_current != NULL); o_place_draw_rubber (w_current, renderer); net_rubber_band_mode = gschem_options_get_net_rubber_band_mode (w_current->options); if (!net_rubber_band_mode) return; diff_x = w_current->second_wx - w_current->first_wx; diff_y = w_current->second_wy - w_current->first_wy; for (s_iter = w_current->stretch_list; s_iter != NULL; s_iter = g_list_next (s_iter)) { STRETCH *s_current = s_iter->data; OBJECT *object = s_current->object; int whichone = s_current->whichone; /* We can only stretch nets and buses */ switch (object->type) { case OBJ_NET: case OBJ_BUS: break; default: continue; } g_return_if_fail ((whichone >= 0) && (whichone < 2)); /* Apply stretch */ object->line->x[whichone] += diff_x; object->line->y[whichone] += diff_y; /* Draw stretched object */ eda_renderer_draw (renderer, object); /* Restore original geometry */ object->line->x[whichone] -= diff_x; object->line->y[whichone] -= diff_y; } }
/*! \brief Draw path from GschemToplevel object. * \par Function Description * This function draws a path with an exclusive or function over the sheet. * The color of the box is <B>SELECT_COLOR</B>. The path is * described by the two points (<B>w_current->first_wx</B>, * <B>w_current->first_wy</B>) and (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>). * * \param [in] w_current The GschemToplevel object. */ void o_path_draw_rubber_grips (GschemToplevel *w_current, EdaRenderer *renderer) { OBJECT object; /* Setup a fake object to pass the drawing routine */ memset (&object, 0, sizeof (OBJECT)); object.type = OBJ_PATH; object.color = SELECT_COLOR; object.line_width = 0; /* clamped to 1 pixel in circle_path */ object.path = path_copy_modify (w_current->which_object->path, 0, 0, w_current->second_wx, w_current->second_wy, w_current->which_grip); eda_renderer_draw (renderer, &object); g_free (object.path->sections); g_free (object.path); }
/*! \brief Draw path creation preview. * \par Function Description * Draw a preview of the path currently being drawn, including a * helper line showing the control point of the node being drawn (if * applicable). */ void o_path_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer) { OBJECT object; int added_sections = 0; /* Draw a helper for when we're dragging a control point */ if (w_current->first_wx != w_current->second_wx || w_current->first_wy != w_current->second_wy) { double wwidth = 0; cairo_t *cr = eda_renderer_get_cairo_context (renderer); GArray *color_map = eda_renderer_get_color_map (renderer); int flags = eda_renderer_get_cairo_flags (renderer); eda_cairo_line (cr, flags, END_NONE, wwidth, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy); eda_cairo_set_source_color (cr, SELECT_COLOR, color_map); eda_cairo_stroke (cr, flags, TYPE_SOLID, END_NONE, wwidth, -1, -1); } /* Now draw the rest of the path */ /* Calculate any new sections */ added_sections = path_next_sections (w_current); /* Setup a fake object to pass the drawing routine */ memset (&object, 0, sizeof (OBJECT)); object.type = OBJ_PATH; object.color = SELECT_COLOR; object.line_width = 0; /* clamped to 1 pixel in circle_path */ object.path = w_current->temp_path; eda_renderer_draw (renderer, &object); /* Throw away the added sections again */ w_current->temp_path->num_sections -= added_sections; }
/*! \brief Draw a page. * \par Function Description * Draws the \a page on the Cairo context \a cr, which should have * dimensions \a cr_width and \a cr_height. If the Pango context \a * pc is provided, it is used for rendering of text. The parameter \a * is_color controls whether to enable color printing, and \a * is_raster should be set if drawing to a raster surface such as an * image. * * \param toplevel A #TOPLEVEL structure. * \param page The #PAGE to be rendered. * \param cr The Cairo context to render to. * \param pc A Pango context for text rendering, or NULL. * \param cr_width The width of the drawing area. * \param cr_height The height of the drawing area. * \param is_color TRUE if drawing should be in color; FALSE otherwise. * \param is_raster TRUE if drawing to a raster image surface; FALSE otherwise. */ static void x_print_draw_page (TOPLEVEL *toplevel, PAGE *page, cairo_t *cr, PangoContext *pc, double cr_width, double cr_height, gboolean is_color, gboolean is_raster) { EdaRenderer *renderer; cairo_matrix_t mtx; GArray *color_map; int status, wx_min, wy_min, wx_max, wy_max; double w_width, w_height, scale; GList *iter; /* First, calculate a transformation matrix for the cairo * context. We want to center the extents of the page in the * available page area. */ status = world_get_object_glist_bounds (toplevel, s_page_objects (page), &wx_min, &wy_min, &wx_max, &wy_max); /* If there are no printable objects, draw nothing. */ if (!status) return; w_width = wx_max - wx_min; w_height = wy_max - wy_min; scale = fmin (cr_width / w_width, cr_height / w_height); cairo_matrix_init (&mtx, scale, 0, 0, -scale, - (wx_min + 0.5*w_width) * scale + 0.5*cr_width, (wy_min + 0.5*w_height) * scale + 0.5*cr_height); /* Second, build the color map. If no color printing is desired, * transform the print color map into a black-and-white color map by * making the background color transparent and replacing all other * enabled colors with solid black. */ color_map = g_array_sized_new (FALSE, FALSE, sizeof(GedaColor), MAX_COLORS); color_map = g_array_append_vals (color_map, print_colors, MAX_COLORS); if (!is_color) { int i; for (i = 0; i < MAX_COLORS; i++) { GedaColor *c = &g_array_index (color_map, GedaColor, i); if (!c->enabled) continue; /* Disable background color & fully-transparent colors */ if (c->a == 0 || i == BACKGROUND_COLOR) { c->enabled = FALSE; continue; } /* Set any remaining colors solid black */ c->r = 0; c->g = 0; c->b = 0; c->a = ~0; } } /* Thirdly, create and initialise a renderer */ renderer = EDA_RENDERER (g_object_new (EDA_TYPE_RENDERER, "cairo-context", cr, "pango-context", pc, "color-map", color_map, "render-flags", is_raster ? EDA_RENDERER_FLAG_HINTING : 0, NULL)); /* Finally, actually do drawing */ cairo_save (cr); cairo_transform (cr, &mtx); /* Draw background */ eda_cairo_set_source_color (cr, BACKGROUND_COLOR, color_map); cairo_paint (cr); /* Draw all objects and cues */ for (iter = (GList *) s_page_objects (page); iter != NULL; iter = g_list_next (iter)) { eda_renderer_draw (renderer, (OBJECT *) iter->data); } for (iter = (GList *) s_page_objects (page); iter != NULL; iter = g_list_next (iter)) { eda_renderer_draw_cues (renderer, (OBJECT *) iter->data); } cairo_restore (cr); g_object_unref (renderer); g_array_free (color_map, TRUE); }
/*! \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. * * \param w_current GschemToplevel which we're drawing for. * \param renderer Renderer to use for drawing. */ void o_place_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer) { int diff_x, diff_y; cairo_t *cr = eda_renderer_get_cairo_context (renderer); g_return_if_fail (w_current != NULL); GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); g_return_if_fail (page->place_list != NULL); /* Don't worry about the previous drawing method and movement * constraints, use with the current settings */ w_current->last_drawb_mode = w_current->actionfeedback_mode; w_current->drawbounding_action_mode = (w_current->CONTROLKEY && ! ((w_current->event_state == PASTEMODE) || (w_current->event_state == COMPMODE) || (w_current->event_state == TEXTMODE))) ? 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; } } /* Translate the cairo context to the required offset before drawing. */ cairo_save (cr); cairo_translate (cr, diff_x, diff_y); /* Draw with the appropriate mode */ if (w_current->last_drawb_mode == BOUNDINGBOX) { GArray *map = eda_renderer_get_color_map (renderer); int flags = eda_renderer_get_cairo_flags (renderer); int left, top, bottom, right; /* Find the bounds of the drawing to be done */ world_get_object_glist_bounds (page->toplevel, page->place_list, &left, &top, &right, &bottom); /* Draw box outline */ eda_cairo_box (cr, flags, 0, left, top, right, bottom); eda_cairo_set_source_color (cr, BOUNDINGBOX_COLOR, map); eda_cairo_stroke (cr, flags, TYPE_SOLID, END_NONE, 0, -1, -1); } else { GList *iter; for (iter = page->place_list; iter != NULL; iter = g_list_next (iter)) { eda_renderer_draw (renderer, (OBJECT *) iter->data); } } cairo_restore (cr); }