gvloadimage_gdk.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. #include "config.h"
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <util/agxbuf.h>
  15. #include <gvc/gvplugin_loadimage.h>
  16. #include <gvc/gvio.h>
  17. #ifdef HAVE_PANGOCAIRO
  18. #include <cairo.h>
  19. #include <gdk-pixbuf/gdk-pixbuf.h>
  20. #include <gdk/gdk.h>
  21. #ifdef _MSC_VER //*dependencies
  22. #pragma comment( lib, "gvc.lib" )
  23. #pragma comment( lib, "glib-2.0.lib" )
  24. #pragma comment( lib, "cairo.lib" )
  25. #pragma comment( lib, "gobject-2.0.lib" )
  26. #pragma comment( lib, "graph.lib" )
  27. #pragma comment( lib, "gdk-pixbuf.lib" )
  28. #endif
  29. typedef enum {
  30. FORMAT_BMP_CAIRO,
  31. FORMAT_JPEG_CAIRO,
  32. FORMAT_PNG_CAIRO,
  33. FORMAT_ICO_CAIRO,
  34. } format_type;
  35. static void gdk_set_mimedata_from_file (cairo_surface_t *image, const char *mime_type, const char *file)
  36. {
  37. FILE *fp;
  38. unsigned char *data = NULL;
  39. long len;
  40. const char *id_prefix = "gvloadimage_gdk-";
  41. fp = fopen (file, "rb");
  42. if (fp == NULL)
  43. return;
  44. fseek (fp, 0, SEEK_END);
  45. len = ftell(fp);
  46. rewind(fp);
  47. if (len > 0)
  48. data = malloc ((size_t)len);
  49. if (data) {
  50. if (fread(data, (size_t)len, 1, fp) != 1) {
  51. free (data);
  52. data = NULL;
  53. }
  54. }
  55. fclose(fp);
  56. if (data) {
  57. cairo_surface_set_mime_data (image, mime_type, data, (unsigned long)len, free, data);
  58. agxbuf id = {0};
  59. agxbprint(&id, "%s%s", id_prefix, file);
  60. char *unique_id = agxbdisown(&id);
  61. cairo_surface_set_mime_data(image, CAIRO_MIME_TYPE_UNIQUE_ID,
  62. (unsigned char*)unique_id,
  63. strlen(unique_id), free, unique_id);
  64. }
  65. }
  66. static void gdk_set_mimedata(cairo_surface_t *image, usershape_t *us)
  67. {
  68. switch (us->type) {
  69. case FT_PNG:
  70. gdk_set_mimedata_from_file (image, CAIRO_MIME_TYPE_PNG, us->name);
  71. break;
  72. case FT_JPEG:
  73. gdk_set_mimedata_from_file (image, CAIRO_MIME_TYPE_JPEG, us->name);
  74. break;
  75. default:
  76. break;
  77. }
  78. }
  79. static void gdk_freeimage(usershape_t *us)
  80. {
  81. cairo_surface_destroy(us->data);
  82. }
  83. static cairo_surface_t* gdk_loadimage(GVJ_t * job, usershape_t *us)
  84. {
  85. cairo_t *cr = job->context; /* target context */
  86. GdkPixbuf *image = NULL;
  87. cairo_surface_t *cairo_image = NULL;
  88. cairo_pattern_t *pattern;
  89. assert(job);
  90. assert(us);
  91. assert(us->name);
  92. if (us->data) {
  93. if (us->datafree == gdk_freeimage) {
  94. cairo_image = cairo_surface_reference(us->data); /* use cached data */
  95. } else {
  96. us->datafree(us); /* free incompatible cache data */
  97. us->datafree = NULL;
  98. us->data = NULL;
  99. }
  100. }
  101. if (!cairo_image) { /* read file into cache */
  102. if (!gvusershape_file_access(us))
  103. return NULL;
  104. switch (us->type) {
  105. case FT_PNG:
  106. case FT_JPEG:
  107. case FT_BMP:
  108. case FT_ICO:
  109. case FT_TIFF:
  110. // FIXME - should be using a stream reader
  111. image = gdk_pixbuf_new_from_file(us->name, NULL);
  112. break;
  113. default:
  114. image = NULL;
  115. }
  116. if (image) {
  117. cairo_save (cr);
  118. gdk_cairo_set_source_pixbuf (cr, image, 0, 0);
  119. pattern = cairo_get_source (cr);
  120. assert(cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SURFACE);
  121. cairo_pattern_get_surface (pattern, &cairo_image);
  122. cairo_image = cairo_surface_reference (cairo_image);
  123. cairo_restore (cr);
  124. gdk_set_mimedata (cairo_image, us);
  125. us->data = cairo_surface_reference(cairo_image);
  126. us->datafree = gdk_freeimage;
  127. }
  128. gvusershape_file_release(us);
  129. }
  130. return cairo_image;
  131. }
  132. static void gdk_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
  133. {
  134. (void)filled;
  135. cairo_t *cr = job->context; /* target context */
  136. cairo_surface_t *image;
  137. image = gdk_loadimage(job, us);
  138. if (image) {
  139. cairo_save(cr);
  140. cairo_translate(cr, b.LL.x, -b.UR.y);
  141. cairo_scale(cr, (b.UR.x - b.LL.x)/(us->w), (b.UR.y - b.LL.y)/(us->h));
  142. cairo_set_source_surface (cr, image, 0, 0);
  143. cairo_paint (cr);
  144. cairo_restore(cr);
  145. cairo_surface_destroy (image);
  146. }
  147. }
  148. static gvloadimage_engine_t engine_gdk = {
  149. gdk_loadimage_cairo
  150. };
  151. #endif
  152. gvplugin_installed_t gvloadimage_gdk_types[] = {
  153. #ifdef HAVE_PANGOCAIRO
  154. {FORMAT_BMP_CAIRO, "bmp:cairo", 1, &engine_gdk, NULL},
  155. {FORMAT_JPEG_CAIRO, "jpe:cairo", 2, &engine_gdk, NULL},
  156. {FORMAT_JPEG_CAIRO, "jpg:cairo", 2, &engine_gdk, NULL},
  157. {FORMAT_JPEG_CAIRO, "jpeg:cairo", 2, &engine_gdk, NULL},
  158. {FORMAT_PNG_CAIRO, "png:cairo", -1, &engine_gdk, NULL},
  159. {FORMAT_ICO_CAIRO, "ico:cairo", 1, &engine_gdk, NULL},
  160. #endif
  161. {0, NULL, 0, NULL, NULL}
  162. };