Graphviz 13.0.0~dev.20250121.0651
Loading...
Searching...
No Matches
gvloadimage_gdk.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <assert.h>
14#include <stdbool.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <util/alloc.h>
18#include <util/agxbuf.h>
19
21#include <gvc/gvio.h>
22
23#ifdef HAVE_PANGOCAIRO
24#include <cairo.h>
25#include <gdk-pixbuf/gdk-pixbuf.h>
26#include <gdk/gdk.h>
27
28#ifdef _MSC_VER //*dependencies
29 #pragma comment( lib, "gvc.lib" )
30 #pragma comment( lib, "glib-2.0.lib" )
31 #pragma comment( lib, "cairo.lib" )
32 #pragma comment( lib, "gobject-2.0.lib" )
33 #pragma comment( lib, "graph.lib" )
34 #pragma comment( lib, "gdk-pixbuf.lib" )
35#endif
36
37typedef enum {
38 FORMAT_BMP_CAIRO,
39 FORMAT_JPEG_CAIRO,
41 FORMAT_ICO_CAIRO,
43
44static void gdk_set_mimedata_from_file (cairo_surface_t *image, const char *mime_type, const char *file)
45{
46 FILE *fp;
47 unsigned char *data = NULL;
48 long len;
49 const char *id_prefix = "gvloadimage_gdk-";
50
51 fp = fopen (file, "rb");
52 if (fp == NULL)
53 return;
54 fseek (fp, 0, SEEK_END);
55 len = ftell(fp);
56 rewind(fp);
57 if (len > 0)
58 data = malloc ((size_t)len);
59 if (data) {
60 if (fread(data, (size_t)len, 1, fp) != 1) {
61 free (data);
62 data = NULL;
63 }
64 }
65 fclose(fp);
66
67 if (data) {
68 cairo_surface_set_mime_data (image, mime_type, data, (unsigned long)len, free, data);
69 agxbuf id = {0};
70 agxbprint(&id, "%s%s", id_prefix, file);
71 char *unique_id = agxbdisown(&id);
72 cairo_surface_set_mime_data(image, CAIRO_MIME_TYPE_UNIQUE_ID,
73 (unsigned char*)unique_id,
74 strlen(unique_id), free, unique_id);
75 }
76}
77
78static void gdk_set_mimedata(cairo_surface_t *image, usershape_t *us)
79{
80 switch (us->type) {
81 case FT_PNG:
82 gdk_set_mimedata_from_file (image, CAIRO_MIME_TYPE_PNG, us->name);
83 break;
84 case FT_JPEG:
85 gdk_set_mimedata_from_file (image, CAIRO_MIME_TYPE_JPEG, us->name);
86 break;
87 default:
88 break;
89 }
90}
91
93typedef struct {
94 cairo_surface_t *surface;
95 GdkPixbuf *origin;
96} data_t;
97
98static void gdk_freeimage(usershape_t *us)
99{
100 assert(us->data != NULL);
101 data_t *const data = us->data;
102 const bool is_last = cairo_surface_get_reference_count(data->surface) == 1;
103 cairo_surface_destroy(data->surface);
104 if (is_last) {
105 free(data->origin);
106 free(data);
107 }
108}
109
110static cairo_surface_t* gdk_loadimage(GVJ_t * job, usershape_t *us)
111{
112 cairo_t *cr = job->context; /* target context */
113 GdkPixbuf *image = NULL;
114 cairo_surface_t *cairo_image = NULL;
115 cairo_pattern_t *pattern;
116
117 assert(job);
118 assert(us);
119 assert(us->name);
120
121 if (us->data) {
122 if (us->datafree == gdk_freeimage) {
123 // use cached data
124 data_t *const data = us->data;
125 cairo_image = cairo_surface_reference(data->surface);
126 } else {
127 us->datafree(us); /* free incompatible cache data */
128 us->datafree = NULL;
129 us->data = NULL;
130 }
131 }
132 if (!cairo_image) { /* read file into cache */
134 return NULL;
135 switch (us->type) {
136 case FT_PNG:
137 case FT_JPEG:
138 case FT_BMP:
139 case FT_ICO:
140 case FT_TIFF:
141 // FIXME - should be using a stream reader
142 image = gdk_pixbuf_new_from_file(us->name, NULL);
143 break;
144 default:
145 image = NULL;
146 }
147 if (image) {
148 cairo_save (cr);
149 gdk_cairo_set_source_pixbuf (cr, image, 0, 0);
150 pattern = cairo_get_source (cr);
151 assert(cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SURFACE);
152 cairo_pattern_get_surface (pattern, &cairo_image);
153 cairo_image = cairo_surface_reference (cairo_image);
154 cairo_restore (cr);
155 gdk_set_mimedata (cairo_image, us);
156 data_t *const data = gv_alloc(sizeof(data_t));
157 *data = (data_t){.surface = cairo_surface_reference(cairo_image),
158 .origin = image};
159 us->data = data;
160 us->datafree = gdk_freeimage;
161 }
163 }
164 return cairo_image;
165}
166
167static void gdk_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
168{
169 (void)filled;
170
171 cairo_t *cr = job->context; /* target context */
172 cairo_surface_t *image;
173
174 image = gdk_loadimage(job, us);
175 if (image) {
176 cairo_save(cr);
177 cairo_translate(cr, b.LL.x, -b.UR.y);
178 cairo_scale(cr, (b.UR.x - b.LL.x) / us->w, (b.UR.y - b.LL.y) / us->h);
179 cairo_set_source_surface (cr, image, 0, 0);
180 cairo_paint (cr);
181 cairo_restore(cr);
182 cairo_surface_destroy (image);
183 }
184}
185
186static gvloadimage_engine_t engine_gdk = {
187 gdk_loadimage_cairo
188};
189
190#endif
191
193#ifdef HAVE_PANGOCAIRO
194 {FORMAT_BMP_CAIRO, "bmp:cairo", 1, &engine_gdk, NULL},
195 {FORMAT_JPEG_CAIRO, "jpe:cairo", 2, &engine_gdk, NULL},
196 {FORMAT_JPEG_CAIRO, "jpg:cairo", 2, &engine_gdk, NULL},
197 {FORMAT_JPEG_CAIRO, "jpeg:cairo", 2, &engine_gdk, NULL},
198 {FORMAT_PNG_CAIRO, "png:cairo", -1, &engine_gdk, NULL},
199 {FORMAT_ICO_CAIRO, "ico:cairo", 1, &engine_gdk, NULL},
200#endif
201 {0, NULL, 0, NULL, NULL}
202};
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:234
static char * agxbdisown(agxbuf *xb)
Definition agxbuf.h:327
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
static double len(glCompPoint p)
Definition glutils.c:150
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:163
void gvusershape_file_release(usershape_t *us)
bool gvusershape_file_access(usershape_t *us)
format_type
@ FORMAT_PNG_CAIRO
gvplugin_installed_t gvloadimage_gdk_types[]
T_cell image
Definition htmlparse.y:340
void * context
Definition gvcjob.h:295
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
Definition legal.c:50
ingroup plugin_api
Definition gvplugin.h:35
double x
Definition geom.h:29
double y
Definition geom.h:29
const char * name
Definition usershape.h:54
void(* datafree)(usershape_t *us)
Definition usershape.h:65
void * data
Definition usershape.h:63
imagetype_t type
Definition usershape.h:59
double h
Definition usershape.h:61
double w
Definition usershape.h:61
@ FT_BMP
Definition usershape.h:25
@ FT_ICO
Definition usershape.h:27
@ FT_TIFF
Definition usershape.h:27
@ FT_JPEG
Definition usershape.h:25
@ FT_PNG
Definition usershape.h:25