static void _do_bezier (WpgImportRenderer *ren, WPGPoint *pts, int iNum) { int num_points = (iNum + 2) / 3; int i; int ofs = ren->Box.Height; BezPoint *bps; g_return_if_fail (num_points > 1); bps = g_alloca (num_points * sizeof(BezPoint)); bps[0].type = BEZ_MOVE_TO; bps[0].p1.x = pts[0].x / WPU_PER_DCM; bps[0].p1.y = (ofs - pts[0].y) / WPU_PER_DCM; for (i = 1; i < num_points; ++i) { bps[i].type = BEZ_CURVE_TO; /* although declared as unsigned (WORD) these values have to be treaded * as signed, because they can move in both directions. */ bps[i].p1.x = (gint16)pts[i*3-2].x / WPU_PER_DCM; bps[i].p1.y = (ofs - (gint16)pts[i*3-2].y) / WPU_PER_DCM; bps[i].p2.x = (gint16)pts[i*3-1].x / WPU_PER_DCM; bps[i].p2.y = (ofs - (gint16)pts[i*3-1].y) / WPU_PER_DCM; bps[i].p3.x = (gint16)pts[i*3 ].x / WPU_PER_DCM; bps[i].p3.y = (ofs - (gint16)pts[i*3 ].y) / WPU_PER_DCM; } /* XXX: should we fold this calls into one? What's closing a WPG PolyCurve? */ if (ren->LineAttr.Type != WPG_LA_NONE) DIA_RENDERER_GET_CLASS(ren)->draw_bezier (DIA_RENDERER(ren), bps, num_points, &ren->stroke); if (ren->FillAttr.Type != WPG_FA_HOLLOW) DIA_RENDERER_GET_CLASS(ren)->draw_beziergon (DIA_RENDERER(ren), bps, num_points, &ren->fill, NULL); }
static void _do_ellipse (WpgImportRenderer *ren, WPGEllipse* pEll) { int h = ren->Box.Height; Point center; center.x = pEll->x / WPU_PER_DCM; center.y = (h - pEll->y) / WPU_PER_DCM; if (fabs(pEll->EndAngle - pEll->StartAngle) < 360) { /* WPG arcs are counter-clockwise so ensure that end is bigger than start */ real arcEnd = pEll->EndAngle; if (arcEnd < pEll->StartAngle) arcEnd += 360; if (ren->LineAttr.Type != WPG_LA_NONE) DIA_RENDERER_GET_CLASS(ren)->draw_arc (DIA_RENDERER(ren), ¢er, 2 * pEll->rx / WPU_PER_DCM, 2 * pEll->ry / WPU_PER_DCM, pEll->StartAngle, arcEnd, &ren->stroke); if (ren->FillAttr.Type != WPG_FA_HOLLOW) DIA_RENDERER_GET_CLASS(ren)->fill_arc (DIA_RENDERER(ren), ¢er, 2 * pEll->rx / WPU_PER_DCM, 2 * pEll->ry / WPU_PER_DCM, pEll->StartAngle, arcEnd, &ren->fill); } else { DIA_RENDERER_GET_CLASS(ren)->draw_ellipse (DIA_RENDERER(ren), ¢er, 2 * pEll->rx / WPU_PER_DCM, 2 * pEll->ry / WPU_PER_DCM, (ren->FillAttr.Type != WPG_FA_HOLLOW) ? &ren->fill : NULL, (ren->LineAttr.Type != WPG_LA_NONE) ? &ren->stroke : NULL); } }
static void draw_object(DiaRenderer *self, DiaObject *object) { /* wrap in <g></g> * We could try to be smart and count the objects we using for the object. * If it is only one the grouping is superfluous and should be removed. */ DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); SvgRenderer *svg_renderer = SVG_RENDERER (self); int n_children = 0; xmlNodePtr child, group; g_queue_push_tail (svg_renderer->parents, renderer->root); /* modifying the root pointer so everything below us gets into the new node */ renderer->root = group = xmlNewNode (renderer->svg_name_space, (const xmlChar *)"g"); object->ops->draw(object, DIA_RENDERER (renderer)); /* no easy way to count? */ child = renderer->root->children; while (child != NULL) { child = child->next; ++n_children; } renderer->root = g_queue_pop_tail (svg_renderer->parents); /* if there is only one element added to the group node unpack it again */ if (1 == n_children) { xmlAddChild (renderer->root, group->children); xmlUnlinkNode (group); /* dont free the children */ xmlFree (group); } else { xmlAddChild (renderer->root, group); } }
/* dia export funtion */ static gboolean export_data(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { WpgRenderer *renderer; FILE *file; Rectangle *extent; real width, height; file = g_fopen(filename, "wb"); /* "wb" for binary! */ if (file == NULL) { dia_context_add_message_with_errno (ctx, errno, _("Can't open output file %s"), dia_context_get_filename(ctx)); return FALSE; } renderer = g_object_new (WPG_TYPE_RENDERER, NULL); renderer->file = file; renderer->ctx = ctx; extent = &data->extents; /* use extents */ DIAG_NOTE(g_message("export_data extents %f,%f -> %f,%f", extent->left, extent->top, extent->right, extent->bottom)); width = extent->right - extent->left; height = extent->bottom - extent->top; #if 0 /* extend to use full range */ renderer->Scale = 0.001; if (width > height) while (renderer->Scale * width < 3276.7) renderer->Scale *= 10.0; else while (renderer->Scale * height < 3276.7) renderer->Scale *= 10.0; #else /* scale from Dia's cm to WPU (1/1200 inch) */ renderer->Scale = WPU_PER_DCM; /* avoid int16 overflow */ if (width > height) while (renderer->Scale * width > 32767) renderer->Scale /= 10.0; else while (renderer->Scale * height > 32767) renderer->Scale /= 10.0; renderer->XOffset = - extent->left; renderer->YOffset = extent->bottom; #endif renderer->Box.Width = width * renderer->Scale; renderer->Box.Height = height * renderer->Scale; renderer->Box.Flag = 0; renderer->Box.Version = 0; data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); g_object_unref(renderer); return TRUE; }
gboolean PyDia_export_data(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { DiaPyRenderer *renderer; { FILE *file; file = g_fopen(filename, "w"); /* "wb" for binary! */ if (file == NULL) { dia_context_add_message_with_errno(ctx, errno, _("Couldn't open '%s' for writing.\n"), dia_context_get_filename(ctx)); return FALSE; } else fclose (file); } renderer = g_object_new (DIA_TYPE_PY_RENDERER, NULL); renderer->filename = g_strdup (filename); renderer->diagram_data = PyDiaDiagramData_New(data); /* The Python Renderer object was created at PyDia_Register */ renderer->self = (PyObject*)user_data; /* this will call the required callback functions above */ data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); g_object_unref(renderer); return TRUE; }
DiaRenderer * new_gdk_renderer(DDisplay *ddisp) { DiaGdkRenderer *renderer; GType renderer_type = 0; renderer = g_object_new (DIA_TYPE_GDK_RENDERER, NULL); renderer->transform = dia_transform_new (&ddisp->visible, &ddisp->zoom_factor); if (!DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer)) { static const GInterfaceInfo irenderer_iface_info = { (GInterfaceInitFunc) dia_gdk_renderer_iface_init, NULL, /* iface_finalize */ NULL /* iface_data */ }; renderer_type = DIA_TYPE_GDK_RENDERER; /* register the interactive renderer interface */ g_type_add_interface_static (renderer_type, DIA_TYPE_INTERACTIVE_RENDERER_INTERFACE, &irenderer_iface_info); } renderer->parent_instance.is_interactive = 1; renderer->gc = NULL; renderer->pixmap = NULL; renderer->clip_region = NULL; return DIA_RENDERER(renderer); }
static void end_render (DiaRenderer *self) { SvgRenderer *renderer = SVG_RENDERER (self); g_assert (g_queue_is_empty (renderer->parents)); DIA_RENDERER_CLASS (parent_class)->end_render (DIA_RENDERER (self)); }
static gboolean export_render_eps(DiaPsRenderer *renderer, DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { FILE *outfile; outfile = g_fopen(filename, "w"); if (outfile == NULL) { dia_context_add_message_with_errno (ctx, errno, _("Can't open output file %s"), dia_context_get_filename(ctx)); return FALSE; } renderer->file = outfile; renderer->scale = 28.346 * data->paper.scaling; renderer->extent = data->extents; renderer->pstype = (guint)user_data; if (renderer->pstype & PSTYPE_EPSI) { /* Must store the diagram for making a preview */ renderer->diagram = data; } if (renderer->file) { renderer->title = g_strdup (diafilename); data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); } fclose(outfile); return TRUE; }
static void draw_object (DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { WmfRenderer *renderer = WMF_RENDERER (self); W32::XFORM xFormPrev = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; int mode = W32::GetGraphicsMode (renderer->hFileDC); gboolean fallback = FALSE; if (matrix) { if ( W32::SetGraphicsMode (renderer->hFileDC, GM_ADVANCED) && W32::GetWorldTransform (renderer->hFileDC, &xFormPrev)) { W32::XFORM xForm; xForm.eM11 = matrix->xx; xForm.eM12 = matrix->yx; xForm.eM21 = matrix->xy; xForm.eM22 = matrix->yy; xForm.eDx = matrix->x0; xForm.eDy = matrix->y0; if (!W32::SetWorldTransform (renderer->hFileDC, &xForm)) fallback = TRUE; } } if (fallback) DIA_RENDERER_CLASS (parent_class)->draw_object (self, object, matrix); else object->ops->draw(object, DIA_RENDERER (renderer)); if (matrix) W32::SetWorldTransform (renderer->hFileDC, &xFormPrev); W32::SetGraphicsMode (renderer->hFileDC, mode); }
static void _dae_draw(DiagramAsElement *dae, DiaRenderer *renderer) { DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); Element *elem = &dae->element; if (!dae->data) { /* just draw the box */ Point lower_right = { elem->corner.x + elem->width, elem->corner.y + elem->height }; renderer_ops->draw_rect(renderer,&elem->corner, &lower_right, &dae->border_color); } else { if (FALSE) { /* if the renderer supports transformations ... */ /* temporary messing with it (not enough) */ dae->data->paper.scaling *= dae->scale; data_render (dae->data, DIA_RENDERER (renderer), NULL, NULL, NULL); dae->data->paper.scaling /= dae->scale; } else { /* we have to render to an image and draw that */ if (!dae->image) { /* lazy creation */ gchar *imgfname = NULL; gint fd = g_file_open_tmp ("diagram-as-elementXXXXXX.png", &imgfname, NULL); if (fd != -1) { DiaExportFilter *ef = filter_export_get_by_name ("cairo-alpha-png"); if (!ef) /* prefer cairo with alpha, but don't require it */ ef = filter_guess_export_filter (imgfname); close(fd); if (ef) { DiaContext *ctx = dia_context_new ("Diagram as Object"); dia_context_set_filename (ctx, imgfname); if (ef->export_func (dae->data, ctx, imgfname, dae->filename, ef->user_data)) { DiaImage *tmp_image = dia_image_load (imgfname); /* some extra gymnastics to create an image w/o filename */ if (tmp_image) { dae->image = dia_image_new_from_pixbuf ((GdkPixbuf *)dia_image_pixbuf (tmp_image)); g_object_unref (tmp_image); } /* FIXME: where to put the message in case of an error? */ dia_context_release (ctx); } } /* found a filter */ g_unlink (imgfname); g_free (imgfname); } /* temporary file created*/ } /* only if we have no image yet */ if (dae->image) renderer_ops->draw_image (renderer, &elem->corner, elem->width, elem->height, dae->image); } } }
static void _make_stroke (WpgImportRenderer *ren) { WPGColorRGB c; g_return_if_fail (ren->pPal != NULL); c = ren->pPal[ren->LineAttr.Color]; ren->stroke.red = c.r / 255.0; ren->stroke.green = c.g / 255.0; ren->stroke.blue = c.b / 255.0; ren->stroke.alpha = 1.0; switch (ren->LineAttr.Type) { case WPG_LA_SOLID: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_SOLID, 0.0); break; case WPG_LA_MEDIUMDASH: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_DASHED, 0.66); break; case WPG_LA_SHORTDASH: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_DASHED, 0.33); break; case WPG_LA_DASHDOT: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_DASH_DOT, 1.0); break; case WPG_LA_DASHDOTDOT: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_DASH_DOT_DOT, 1.0); break; case WPG_LA_DOTS: DIA_RENDERER_GET_CLASS(ren)->set_linestyle (DIA_RENDERER(ren), LINESTYLE_DOTTED, 1.0); break; } DIA_RENDERER_GET_CLASS(ren)->set_linewidth (DIA_RENDERER(ren), ren->LineAttr.Width / WPU_PER_DCM); }
static void _do_rect (WpgImportRenderer *ren, Point *points) { if (ren->LineAttr.Type != WPG_LA_NONE || ren->FillAttr.Type != WPG_FA_HOLLOW) DIA_RENDERER_GET_CLASS(ren)->draw_rect (DIA_RENDERER(ren), &points[0], &points[1], (ren->FillAttr.Type != WPG_FA_HOLLOW) ? &ren->fill : NULL, (ren->LineAttr.Type != WPG_LA_NONE) ? &ren->stroke : NULL); }
DiaRenderer * PyDia_new_renderer_wrapper (PyObject *self) { DiaPyRenderer *wrapper; wrapper = g_object_new (DIA_TYPE_PY_RENDERER, NULL); wrapper->self = self; return DIA_RENDERER (wrapper); }
static void _do_polygon (WpgImportRenderer *ren, Point *points, int iNum) { g_return_if_fail (iNum > 2); if (ren->LineAttr.Type == WPG_LA_NONE && ren->FillAttr.Type == WPG_FA_HOLLOW) return; /* nothing to do */ DIA_RENDERER_GET_CLASS(ren)->draw_polygon (DIA_RENDERER(ren), points, iNum, (ren->FillAttr.Type != WPG_FA_HOLLOW) ? &ren->fill : NULL, (ren->LineAttr.Type != WPG_LA_NONE) ? &ren->stroke : NULL); }
DiaRenderer * new_gdk_renderer(DDisplay *ddisp) { DiaGdkRenderer *renderer; renderer = g_object_new (DIA_TYPE_GDK_INTERACTIVE_RENDERER, NULL); renderer->transform = dia_transform_new (&ddisp->visible, &ddisp->zoom_factor); return DIA_RENDERER(renderer); }
DiaRenderer * new_libart_renderer(DiaTransform *trans, int interactive) { DiaLibartRenderer *renderer; renderer = g_object_new(DIA_TYPE_LIBART_RENDERER, NULL); renderer->transform = trans; renderer->parent_instance.is_interactive = interactive; return DIA_RENDERER (renderer); }
static void export_svg(DiagramData *data, const gchar *filename, const gchar *diafilename, void* user_data) { DiaSvgRenderer *renderer; if ((renderer = new_svg_renderer(data, filename))) { data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); g_object_unref(renderer); } }
static gboolean export_shape(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { DiaSvgRenderer *renderer; int i; gchar *point; gchar *png_filename = NULL; DiaExportFilter *exportfilter; gfloat old_scaling; Rectangle *ext = &data->extents; gfloat scaling_x, scaling_y; /* create the png preview shown in the toolbox */ point = strrchr(filename, '.'); if (point == NULL || strcmp(point, ".shape") != 0) { dia_context_add_message(ctx, _("Shape files must end in .shape, or they cannot be loaded by Dia")); return FALSE; } i = (int)(point-filename); point = g_strndup(filename, i); png_filename = g_strdup_printf("%s.png",point); g_free(point); /* we are especially requesting the libart/png cause it is the only one with the size-hack */ exportfilter = filter_export_get_by_name ("png-libart"); /* ... but the code below does not use the size-hack anymore ... */ if (!exportfilter) exportfilter = filter_guess_export_filter(png_filename); if (!exportfilter) { dia_context_add_message(ctx, _("Can't export PNG icon without export plugin!")); } else { /* get the scaling right */ old_scaling = data->paper.scaling; scaling_x = 22/((ext->right - ext->left) * 20); scaling_y = 22/((ext->bottom - ext->top) * 20); data->paper.scaling = MIN(scaling_x, scaling_y); exportfilter->export_func(data, ctx, png_filename, diafilename, exportfilter->user_data); data->paper.scaling = old_scaling; } g_free(png_filename); /* create the shape */ if((renderer = new_shape_renderer(data, filename))) { data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); g_object_unref (renderer); return TRUE; } /* Create a sheet entry if applicable (../../sheets exists) */ return FALSE; }
/* plug-in interface : export function */ static gboolean export_data(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { HpglRenderer *renderer; FILE *file; Rectangle *extent; real width, height; file = g_fopen(filename, "w"); /* "wb" for binary! */ if (!file) { dia_context_add_message_with_errno(ctx, errno, _("Can't open output file %s."), dia_context_get_filename(ctx)); return FALSE; } renderer = g_object_new(HPGL_TYPE_RENDERER, NULL); renderer->file = file; extent = &data->extents; /* use extents */ DIAG_NOTE(g_message("export_data extents %f,%f -> %f,%f", extent->left, extent->top, extent->right, extent->bottom)); width = extent->right - extent->left; height = extent->bottom - extent->top; renderer->scale = 0.001; if (width > height) while (renderer->scale * width < 3276.7) renderer->scale *= 10.0; else while (renderer->scale * height < 3276.7) renderer->scale *= 10.0; renderer->offset = 0.0; /* just to have one */ renderer->size.x = width * renderer->scale; renderer->size.y = height * renderer->scale; #if 0 /* OR: set page size and scale */ fprintf(renderer->file, "PS0;SC%d,%d,%d,%d;\n", hpgl_scale(renderer, extent->left), hpgl_scale(renderer, extent->right), hpgl_scale(renderer, extent->bottom), hpgl_scale(renderer, extent->top)); #endif data_render(data, DIA_RENDERER(renderer), NULL, NULL, NULL); g_object_unref(renderer); return TRUE; }
static void dia_gdk_interactive_renderer_init(DiaGdkInteractiveRenderer *object) { DiaGdkRenderer *renderer = DIA_GDK_RENDERER(object); DiaRenderer *dia_renderer = DIA_RENDERER(object); dia_renderer->is_interactive = 1; renderer->gc = NULL; renderer->pixmap = NULL; renderer->clip_region = NULL; }
static void cairo_interactive_renderer_init (DiaCairoInteractiveRenderer *object, void *p) { DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (object); DiaRenderer *dia_renderer = DIA_RENDERER(object); dia_renderer->is_interactive = 1; renderer->pixmap = NULL; renderer->highlight_color = NULL; }
/*! * \brief Render the given object optionally transformed by matrix * @param self explicit this pointer * @param object the _DiaObject to draw * @param matrix the trnsformation matrix to use or NULL */ static void draw_object (DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); cairo_matrix_t before; if (matrix) { cairo_get_matrix (renderer->cr, &before); g_assert (sizeof(cairo_matrix_t) == sizeof(DiaMatrix)); cairo_transform (renderer->cr, (cairo_matrix_t *)matrix); } object->ops->draw(object, DIA_RENDERER (renderer)); if (matrix) cairo_set_matrix (renderer->cr, &before); }
DiaRenderer * new_psprint_renderer(DiagramData *dia, FILE *file) { DiaPsRenderer *renderer; #ifdef HAVE_FREETYPE renderer = g_object_new (DIA_TYPE_PS_FT2_RENDERER, NULL); #else renderer = g_object_new (DIA_TYPE_PS_RENDERER, NULL); #endif renderer->file = file; renderer->pstype = PSTYPE_PS; return DIA_RENDERER(renderer); }
/*! * \brief Render the given object optionally transformed by matrix * @param self explicit this pointer * @param object the _DiaObject to draw * @param matrix the transformation matrix to use or NULL */ static void draw_object (DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); cairo_matrix_t before; if (matrix) { /* at least in SVG the intent of an invalid matrix is not rendering */ if (!dia_matrix_is_invertible(matrix)) return; cairo_get_matrix (renderer->cr, &before); g_assert (sizeof(cairo_matrix_t) == sizeof(DiaMatrix)); cairo_transform (renderer->cr, (cairo_matrix_t *)matrix); } object->ops->draw(object, DIA_RENDERER (renderer)); if (matrix) cairo_set_matrix (renderer->cr, &before); }
static gboolean export_dxf(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { DxfRenderer *renderer; FILE *file; int i; Layer *layer; gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar buf2[G_ASCII_DTOSTR_BUF_SIZE]; file = g_fopen(filename, "w"); if (file == NULL) { dia_context_add_message_with_errno (ctx, errno, _("Can't open output file %s"), dia_context_get_filename(ctx)); return FALSE; } renderer = g_object_new(DXF_TYPE_RENDERER, NULL); renderer->file = file; /* drawing limits */ fprintf(file, " 0\nSECTION\n 2\nHEADER\n"); fprintf(file, " 9\n$EXTMIN\n 10\n%s\n 20\n%s\n", g_ascii_formatd (buf, sizeof(buf), "%g", data->extents.left), g_ascii_formatd (buf2, sizeof(buf2), "%g", -data->extents.bottom)); fprintf(file, " 9\n$EXTMAX\n 10\n%s\n 20\n%s\n", g_ascii_formatd (buf, sizeof(buf), "%g", data->extents.right), g_ascii_formatd (buf2, sizeof(buf2), "%g", -data->extents.top)); fprintf(file, " 0\nENDSEC\n"); /* write layer description */ fprintf(file," 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n"); /* some dummy entry to make it work for more DXF viewers */ fprintf(file," 2\nLAYER\n 70\n255\n"); for (i=0; i<data->layers->len; i++) { layer = (Layer *) g_ptr_array_index(data->layers, i); fprintf(file," 0\nLAYER\n 2\n%s\n",layer->name); if(layer->visible) fprintf(file," 62\n%d\n",i+1); else fprintf(file," 62\n%d\n",(-1)*(i+1)); } fprintf(file, " 0\nENDTAB\n 0\nENDSEC\n"); /* write graphics */ fprintf(file," 0\nSECTION\n 2\nENTITIES\n"); init_attributes(renderer); DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer), NULL); for (i=0; i<data->layers->len; i++) { layer = (Layer *) g_ptr_array_index(data->layers, i); renderer->layername = layer->name; layer_render(layer, DIA_RENDERER(renderer), NULL, NULL, data, 0); } DIA_RENDERER_GET_CLASS(renderer)->end_render(DIA_RENDERER(renderer)); g_object_unref(renderer); return TRUE; }
static gboolean export_data(DiagramData *data, DiaContext *ctx, const gchar *filename, const gchar *diafilename, void* user_data) { DiaCairoRenderer *renderer; GdkColor color; int width, height; GdkPixbuf* pixbuf = NULL; GError* error = NULL; Rectangle rect; real zoom = 1.0; cairo_t *cctx; const char* format = (const char*)user_data; rect.left = data->extents.left; rect.top = data->extents.top; rect.right = data->extents.right; rect.bottom = data->extents.bottom; /* quite arbitrary */ zoom = 20.0 * data->paper.scaling; /* Adding a bit of padding to account for rounding errors. Better to * pad than to clip. See bug #413275 */ width = ceil((rect.right - rect.left) * zoom) + 1; height = ceil((rect.bottom - rect.top) * zoom) + 1; renderer = g_object_new (dia_cairo_renderer_get_type(), NULL); renderer->scale = zoom; renderer->surface = cairo_surface_reference (cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height)); cctx = cairo_create (renderer->surface); /* draw background */ color_convert (&data->bg_color, &color); gdk_cairo_set_source_color (cctx, &color); cairo_rectangle (cctx, 0, 0, width, height); cairo_fill (cctx); data_render (data, DIA_RENDERER (renderer), NULL, NULL, NULL); #if GTK_CHECK_VERSION(3,0,0) pixbuf = gdk_pixbuf_get_from_surface (renderer->surface, 0, 0, width, height); #else { GdkPixmap *pixmap; cairo_t *cr; pixmap = gdk_pixmap_new (NULL, width, height, 24); cr = gdk_cairo_create (pixmap); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface (cr, renderer->surface, 0, 0); cairo_paint (cr); pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, gdk_colormap_get_system (), 0, 0, 0, 0, width, height); } #endif if (pixbuf) { gdk_pixbuf_save (pixbuf, filename, format, &error, NULL); g_object_unref (pixbuf); } else { dia_context_add_message(ctx, _("Failed to create pixbuf from drawable.")); } if (error) { dia_context_add_message(ctx, _("Could not save file:\n%s\n%s"), dia_context_get_filename(ctx), error->message); g_error_free (error); } g_object_unref (renderer); return TRUE; }
/* * renderer methods */ static void draw_object(DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DrsRenderer *renderer = DRS_RENDERER (self); DiaMatrix *m = g_queue_peek_tail (renderer->matrices); xmlNodePtr node; g_queue_push_tail (renderer->parents, renderer->root); renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"object", NULL); xmlSetProp(node, (const xmlChar *)"type", (xmlChar *)object->type->name); /* if it looks like intdata store it as well */ if ((int)object->type->default_user_data > 0 && (int)object->type->default_user_data < 0xFF) { gchar buffer[30]; g_snprintf(buffer, sizeof(buffer), "%d", (int)object->type->default_user_data); xmlSetProp(node, (const xmlChar *)"intdata", (xmlChar *)buffer); } if (renderer->save_props) { xmlNodePtr props_node; props_node = xmlNewChild(node, NULL, (const xmlChar *)"properties", NULL); object_save_props (object, props_node, renderer->ctx); } if (matrix) { DiaMatrix *m2 = g_new (DiaMatrix, 1); if (m) dia_matrix_multiply (m2, matrix, m); else *m2 = *matrix; g_queue_push_tail (renderer->matrices, m2); /* lazy creation of our transformer */ if (!renderer->transformer) renderer->transformer = dia_transform_renderer_new (self); } /* special handling for group objects: * - for the render branch use DiaTransformRenderer, but not it's draw_object, * to see all the children's draw_object ourself * - for the object branch we rely on this draw_object being called so need * to inline group_draw here * - to maintain the correct transform build our own queue of matrices like * the DiaTransformRenderer would do through it's draw_object */ { g_queue_push_tail (renderer->parents, renderer->root); renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"render", NULL); if (renderer->transformer) { DiaMatrix *m = g_queue_peek_tail (renderer->matrices); if (IS_GROUP (object)) { /* reimplementation of group_draw to use this draw_object method */ GList *list; DiaObject *obj; list = group_objects (object); while (list != NULL) { obj = (DiaObject *) list->data; DIA_RENDERER_GET_CLASS(self)->draw_object(self, obj, m); list = g_list_next(list); } } else { /* just the leaf */ DIA_RENDERER_GET_CLASS(renderer->transformer)->draw_object(renderer->transformer, object, m); } } else { object->ops->draw(object, DIA_RENDERER (renderer)); } renderer->root = g_queue_pop_tail (renderer->parents); } renderer->root = g_queue_pop_tail (renderer->parents); if (matrix) g_queue_pop_tail (renderer->matrices); /* one lost demand destruction */ if (renderer->transformer && g_queue_is_empty (renderer->matrices)) { g_object_unref (renderer->transformer); renderer->transformer = NULL; } }