static void image_set_props(Image *image, GPtrArray *props) { struct stat st; time_t mtime = 0; char *old_file = image->file ? g_strdup(image->file) : NULL; const GdkPixbuf *old_pixbuf = dia_image_pixbuf (image->image); gboolean was_inline = image->inline_data; object_set_props_from_offsets(&image->element.object, image_offsets, props); if (old_pixbuf != image->pixbuf) { if (!image->file || *image->file == '\0') { GdkPixbuf *pixbuf = NULL; image->inline_data = TRUE; /* otherwise we'll loose it */ /* somebody deleting the filename? */ if (!image->pixbuf && image->image) pixbuf = g_object_ref ((GdkPixbuf *)dia_image_pixbuf (image->image)); if (image->image) g_object_unref (image->image); image->image = dia_image_new_from_pixbuf (image->pixbuf ? image->pixbuf : pixbuf); image->pixbuf = (GdkPixbuf *)dia_image_pixbuf (image->image); if (pixbuf) g_object_unref (pixbuf); } else { if (image->pixbuf) message_warning ("FIXME: handle pixbuf change!"); } } /* use old value on error */ if (!image->file || g_stat (image->file, &st) != 0) mtime = image->mtime; else mtime = st.st_mtime; /* handle changing the image. */ if (image->file && image->pixbuf && was_inline && !image->inline_data) { /* export inline data */ if (was_inline && !image->inline_data) /* if saving fails we keep it inline */ image->inline_data = !dia_image_save (image->image, image->file); } else if (image->file && ((old_file && strcmp(image->file, old_file) != 0) || image->mtime != mtime)) { Element *elem = &image->element; DiaImage *img = NULL; if ((img = dia_image_load(image->file)) != NULL) image->image = img; else if (!image->pixbuf) /* dont overwrite inlined */ image->image = dia_image_get_broken(); elem->height = (elem->width*(float)dia_image_height(image->image))/ (float)dia_image_width(image->image); } g_free(old_file); /* remember it */ image->mtime = mtime; image_update_data(image); }
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); } } }
/*! * \brief Parse the SVG node from a shape file * * Fill the ShapeInfo display list with GraphicElement each got from * a single node within the shape's SVG part. * * \extends _ShapeInfo */ static void parse_svg_node(ShapeInfo *info, xmlNodePtr node, xmlNsPtr svg_ns, DiaSvgStyle *style, const gchar *filename) { xmlChar *str; /* walk SVG node ... */ for (node = node->xmlChildrenNode; node != NULL; node = node->next) { GraphicElement *el = NULL; DiaSvgStyle s; if (xmlIsBlankNode(node)) continue; if (node->type != XML_ELEMENT_NODE || node->ns != svg_ns) continue; dia_svg_style_init (&s, style); dia_svg_parse_style(node, &s, -1); if (!xmlStrcmp(node->name, (const xmlChar *)"line")) { GraphicElementLine *line = g_new0(GraphicElementLine, 1); el = (GraphicElement *)line; line->type = GE_LINE; str = xmlGetProp(node, (const xmlChar *)"x1"); if (str) { line->p1.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"y1"); if (str) { line->p1.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"x2"); if (str) { line->p2.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"y2"); if (str) { line->p2.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } } else if (!xmlStrcmp(node->name, (const xmlChar *)"polyline")) { GraphicElementPoly *poly; GArray *arr = g_array_new(FALSE, FALSE, sizeof(real)); real val, *rarr; gchar *tmp; int i; str = xmlGetProp(node, (const xmlChar *)"points"); tmp = (gchar *) str; while (tmp[0] != '\0') { /* skip junk */ while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-') tmp++; if (tmp[0] == '\0') break; val = g_ascii_strtod(tmp, &tmp); g_array_append_val(arr, val); } xmlFree(str); val = 0; if (arr->len % 2 == 1) g_array_append_val(arr, val); poly = g_malloc0(sizeof(GraphicElementPoly) + arr->len/2*sizeof(Point)); el = (GraphicElement *)poly; poly->type = GE_POLYLINE; poly->npoints = arr->len / 2; rarr = (real *)arr->data; for (i = 0; i < poly->npoints; i++) { poly->points[i].x = rarr[2*i]; poly->points[i].y = rarr[2*i+1]; } g_array_free(arr, TRUE); } else if (!xmlStrcmp(node->name, (const xmlChar *)"polygon")) { GraphicElementPoly *poly; GArray *arr = g_array_new(FALSE, FALSE, sizeof(real)); real val, *rarr; char *tmp; int i; str = xmlGetProp(node, (const xmlChar *)"points"); tmp = (char *) str; while (tmp[0] != '\0') { /* skip junk */ while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-') tmp++; if (tmp[0] == '\0') break; val = g_ascii_strtod(tmp, &tmp); g_array_append_val(arr, val); } xmlFree(str); val = 0; if (arr->len % 2 == 1) g_array_append_val(arr, val); poly = g_malloc0(sizeof(GraphicElementPoly) + arr->len/2*sizeof(Point)); el = (GraphicElement *)poly; poly->type = GE_POLYGON; poly->npoints = arr->len / 2; rarr = (real *)arr->data; for (i = 0; i < poly->npoints; i++) { poly->points[i].x = rarr[2*i]; poly->points[i].y = rarr[2*i+1]; } g_array_free(arr, TRUE); } else if (!xmlStrcmp(node->name, (const xmlChar *)"rect")) { GraphicElementRect *rect = g_new0(GraphicElementRect, 1); real corner_radius = 0.0; el = (GraphicElement *)rect; rect->type = GE_RECT; str = xmlGetProp(node, (const xmlChar *)"x"); if (str) { rect->corner1.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } else rect->corner1.x = 0; str = xmlGetProp(node, (const xmlChar *)"y"); if (str) { rect->corner1.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } else rect->corner1.y = 0; str = xmlGetProp(node, (const xmlChar *)"width"); if (str) { rect->corner2.x = rect->corner1.x + g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"height"); if (str) { rect->corner2.y = rect->corner1.y + g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"rx"); if (str) { corner_radius = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"ry"); if (str) { if(corner_radius != 0.0) { /* calculate the mean value of rx and ry */ corner_radius = (corner_radius+g_ascii_strtod((gchar *) str, NULL))/2; } else { corner_radius = g_ascii_strtod((gchar *) str, NULL); } xmlFree(str); } rect->corner_radius = corner_radius; } else if (!xmlStrcmp(node->name, (const xmlChar *)"text")) { GraphicElementText *text = g_new(GraphicElementText, 1); el = (GraphicElement *)text; text->type = GE_TEXT; text->object = NULL; str = xmlGetProp(node, (const xmlChar *)"x"); if (str) { text->anchor.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } else text->anchor.x = 0; str = xmlGetProp(node, (const xmlChar *)"y"); if (str) { text->anchor.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } else text->anchor.y = 0; str = xmlGetProp(node, (const xmlChar *)"font-size"); if (str) { text->s.font_height = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } else text->s.font_height = 0.8; str = xmlNodeGetContent(node); if (str) { text->string = g_strdup((gchar *) str); xmlFree(str); } else text->string = g_strdup(""); } else if (!xmlStrcmp(node->name, (const xmlChar *)"circle")) { GraphicElementEllipse *ellipse = g_new0(GraphicElementEllipse, 1); el = (GraphicElement *)ellipse; ellipse->type = GE_ELLIPSE; str = xmlGetProp(node, (const xmlChar *)"cx"); if (str) { ellipse->center.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"cy"); if (str) { ellipse->center.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"r"); if (str) { ellipse->width = ellipse->height = 2 * g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } } else if (!xmlStrcmp(node->name, (const xmlChar *)"ellipse")) { GraphicElementEllipse *ellipse = g_new0(GraphicElementEllipse, 1); el = (GraphicElement *)ellipse; ellipse->type = GE_ELLIPSE; str = xmlGetProp(node, (const xmlChar *)"cx"); if (str) { ellipse->center.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"cy"); if (str) { ellipse->center.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"rx"); if (str) { ellipse->width = 2 * g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"ry"); if (str) { ellipse->height = 2 * g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } } else if (!xmlStrcmp(node->name, (const xmlChar *)"path")) { str = xmlGetProp(node, (const xmlChar *)"d"); if (str) { parse_path(info, (char *) str, &s, filename); xmlFree(str); } } else if (!xmlStrcmp(node->name, (const xmlChar *)"image")) { GraphicElementImage *image = g_new0(GraphicElementImage, 1); el = (GraphicElement *)image; image->type = GE_IMAGE; str = xmlGetProp(node, (const xmlChar *)"x"); if (str) { image->topleft.x = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"y"); if (str) { image->topleft.y = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"width"); if (str) { image->width = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"height"); if (str) { image->height = g_ascii_strtod((gchar *) str, NULL); xmlFree(str); } str = xmlGetProp(node, (const xmlChar *)"xlink:href"); if (!str) /* this doesn't look right but it appears to work w/o namespace --hb */ str = xmlGetProp(node, (const xmlChar *)"href"); if (str) { gchar *imgfn = NULL; const char* data = strchr((char *)str, ','); /* first check for inlined data */ if (data) { GdkPixbuf *pixbuf = pixbuf_decode_base64 (data+1); if (pixbuf) { image->image = dia_image_new_from_pixbuf (pixbuf); g_object_unref (pixbuf); } } else { imgfn = g_filename_from_uri((gchar *) str, NULL, NULL); if (!imgfn) /* despite it's name it ensures an absolute filename */ imgfn = custom_get_relative_filename(filename, (gchar *) str); image->image = dia_image_load(imgfn); } if (!image->image) g_debug("failed to load image file %s", imgfn ? imgfn : "(data:)"); g_free(imgfn); xmlFree(str); } /* w/o the image we would crash later */ if (!image->image) image->image = dia_image_get_broken(); } else if (!xmlStrcmp(node->name, (const xmlChar *)"g")) { if (!is_subshape(node)) { /* add elements from the group element */ parse_svg_node(info, node, svg_ns, &s, filename); } else { /* add elements from the group element, but make it a subshape */ GraphicElementSubShape *subshape = g_new0(GraphicElementSubShape, 1); ShapeInfo* tmpinfo = g_new0(ShapeInfo, 1); xmlChar *v_anchor_attr = xmlGetProp(node, (const xmlChar*)"v_anchor"); xmlChar *h_anchor_attr = xmlGetProp(node, (const xmlChar*)"h_anchor"); parse_svg_node(tmpinfo, node, svg_ns, &s, filename); tmpinfo->shape_bounds.top = DBL_MAX; tmpinfo->shape_bounds.left = DBL_MAX; tmpinfo->shape_bounds.bottom = -DBL_MAX; tmpinfo->shape_bounds.right = -DBL_MAX; update_bounds( tmpinfo ); update_bounds( info ); subshape->half_width = (tmpinfo->shape_bounds.right-tmpinfo->shape_bounds.left) / 2.0; subshape->half_height = (tmpinfo->shape_bounds.bottom-tmpinfo->shape_bounds.top) / 2.0; subshape->center.x = tmpinfo->shape_bounds.left + subshape->half_width; subshape->center.y = tmpinfo->shape_bounds.top + subshape->half_height; subshape->type = GE_SUBSHAPE; subshape->display_list = tmpinfo->display_list; subshape->v_anchor_method = OFFSET_METHOD_FIXED; subshape->h_anchor_method = OFFSET_METHOD_FIXED; subshape->default_scale = 0.0; if (!v_anchor_attr || !strcmp((const char*)v_anchor_attr,"fixed.top")) subshape->v_anchor_method = OFFSET_METHOD_FIXED; else if (v_anchor_attr && !strcmp((const char*)v_anchor_attr,"fixed.bottom")) subshape->v_anchor_method = -OFFSET_METHOD_FIXED; else if (v_anchor_attr && !strcmp((const char*)v_anchor_attr,"proportional")) subshape->v_anchor_method = OFFSET_METHOD_PROPORTIONAL; else fprintf( stderr, "illegal v_anchor `%s', defaulting to fixed.top\n", v_anchor_attr ); if (!h_anchor_attr || !strcmp((const char*)h_anchor_attr,"fixed.left")) subshape->h_anchor_method = OFFSET_METHOD_FIXED; else if (h_anchor_attr && !strcmp((const char*)h_anchor_attr,"fixed.right")) subshape->h_anchor_method = -OFFSET_METHOD_FIXED; else if (h_anchor_attr && !strcmp((const char*)h_anchor_attr,"proportional")) subshape->h_anchor_method = OFFSET_METHOD_PROPORTIONAL; else fprintf( stderr, "illegal h_anchor `%s', defaulting to fixed.left\n", h_anchor_attr ); info->subshapes = g_list_append(info->subshapes, subshape); /* gfree( tmpinfo );*/ xmlFree(v_anchor_attr); xmlFree(h_anchor_attr); el = (GraphicElement *)subshape; } } if (el) { el->any.s = s; if (el->any.s.font) el->any.s.font = g_object_ref(s.font); info->display_list = g_list_append(info->display_list, el); } if (s.font) dia_font_unref (s.font); } }
static DiaObject * image_load(ObjectNode obj_node, int version, DiaContext *ctx) { Image *image; Element *elem; DiaObject *obj; int i; AttributeNode attr; char *diafile_dir; image = g_malloc0(sizeof(Image)); elem = &image->element; obj = &elem->object; obj->type = &image_type; obj->ops = &image_ops; element_load(elem, obj_node, ctx); image->border_width = 0.1; attr = object_find_attribute(obj_node, "border_width"); if (attr != NULL) image->border_width = data_real(attribute_first_data(attr), ctx); image->border_color = color_black; attr = object_find_attribute(obj_node, "border_color"); if (attr != NULL) data_color(attribute_first_data(attr), &image->border_color, ctx); image->line_style = LINESTYLE_SOLID; attr = object_find_attribute(obj_node, "line_style"); if (attr != NULL) image->line_style = data_enum(attribute_first_data(attr), ctx); image->dashlength = DEFAULT_LINESTYLE_DASHLEN; attr = object_find_attribute(obj_node, "dashlength"); if (attr != NULL) image->dashlength = data_real(attribute_first_data(attr), ctx); image->draw_border = TRUE; attr = object_find_attribute(obj_node, "draw_border"); if (attr != NULL) image->draw_border = data_boolean(attribute_first_data(attr), ctx); image->keep_aspect = TRUE; attr = object_find_attribute(obj_node, "keep_aspect"); if (attr != NULL) image->keep_aspect = data_boolean(attribute_first_data(attr), ctx); attr = object_find_attribute(obj_node, "file"); if (attr != NULL) { image->file = data_filename(attribute_first_data(attr), ctx); } else { image->file = g_strdup(""); } element_init(elem, 8, NUM_CONNECTIONS); for (i=0;i<NUM_CONNECTIONS;i++) { obj->connections[i] = &image->connections[i]; image->connections[i].object = obj; image->connections[i].connected = NULL; } image->connections[8].flags = CP_FLAGS_MAIN; image->image = NULL; if (strcmp(image->file, "")!=0) { diafile_dir = get_directory(dia_context_get_filename(ctx)); if (g_path_is_absolute(image->file)) { /* Absolute pathname */ image->image = dia_image_load(image->file); if (image->image == NULL) { /* Not found as abs path, try in same dir as diagram. */ char *temp_string; const char *image_file_name = image->file; const char *psep; psep = strrchr(image->file, G_DIR_SEPARATOR); /* try the other G_OS as well */ if (!psep) psep = strrchr(image->file, G_DIR_SEPARATOR == '/' ? '\\' : '/'); if (psep) image_file_name = psep + 1; temp_string = g_build_filename(diafile_dir, image_file_name, NULL); image->image = dia_image_load(temp_string); if (image->image != NULL) { /* Found file in same dir as diagram. */ message_warning(_("The image file '%s' was not found in the specified directory.\n" "Using the file '%s' instead.\n"), image->file, temp_string); g_free(image->file); image->file = temp_string; } else { g_free(temp_string); image->image = dia_image_load((char *)image_file_name); if (image->image != NULL) { char *tmp; /* Found file in current dir. */ message_warning(_("The image file '%s' was not found in the specified directory.\n" "Using the file '%s' instead.\n"), image->file, image_file_name); tmp = image->file; image->file = g_strdup(image_file_name); g_free(tmp); } else { message_warning(_("The image file '%s' was not found.\n"), image_file_name); } } } } else { /* Relative pathname: */ char *temp_string; temp_string = g_build_filename (diafile_dir, image->file, NULL); image->image = dia_image_load(temp_string); if (image->image != NULL) { /* Found file in same dir as diagram. */ g_free(image->file); image->file = temp_string; } else { g_free(temp_string); image->image = dia_image_load(image->file); if (image->image == NULL) { /* Didn't find file in current dir. */ message_warning(_("The image file '%s' was not found.\n"), image->file); } } } g_free(diafile_dir); } /* if we don't have an image yet try to recover it from inlined data */ if (!image->image) { attr = object_find_attribute(obj_node, "pixbuf"); if (attr != NULL) { GdkPixbuf *pixbuf = data_pixbuf (attribute_first_data(attr)); if (pixbuf) { image->image = dia_image_new_from_pixbuf (pixbuf); image->inline_data = TRUE; /* avoid loosing it */ /* FIXME: should we reset the filename? */ g_object_unref (pixbuf); } } } /* update mtime */ { struct stat st; if (g_stat (image->file, &st) != 0) st.st_mtime = 0; image->mtime = st.st_mtime; } image_update_data(image); return &image->element.object; }