gvloadimage_rsvg.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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 <assert.h>
  11. #include <common/render.h>
  12. #include <common/utils.h>
  13. #include <stdbool.h>
  14. #include <stddef.h>
  15. #include <gvc/gvplugin_loadimage.h>
  16. #include <librsvg/rsvg.h>
  17. #ifndef RSVG_CAIRO_H
  18. #include <librsvg/rsvg-cairo.h>
  19. #endif
  20. #include <cairo-svg.h>
  21. typedef enum {
  22. FORMAT_SVG_CAIRO,
  23. } format_type;
  24. static void gvloadimage_rsvg_free(usershape_t *us)
  25. {
  26. g_object_unref(us->data);
  27. }
  28. static RsvgHandle* gvloadimage_rsvg_load(GVJ_t * job, usershape_t *us)
  29. {
  30. RsvgHandle* rsvgh = NULL;
  31. GError *err = NULL;
  32. assert(job);
  33. assert(us);
  34. assert(us->name);
  35. if (us->data) {
  36. if (us->datafree == gvloadimage_rsvg_free)
  37. rsvgh = us->data; /* use cached data */
  38. else {
  39. us->datafree(us); /* free incompatible cache data */
  40. us->data = NULL;
  41. }
  42. }
  43. if (!rsvgh) { /* read file into cache */
  44. if (!gvusershape_file_access(us))
  45. return NULL;
  46. switch (us->type) {
  47. case FT_SVG: {
  48. const char *const safe_path = safefile(us->name);
  49. assert(safe_path != NULL &&
  50. "gvusershape_file_access did not validate file path");
  51. rsvgh = rsvg_handle_new_from_file(safe_path, &err);
  52. if (rsvgh == NULL) {
  53. fprintf(stderr, "rsvg_handle_new_from_file returned an error: %s\n", err->message);
  54. g_error_free(err);
  55. return NULL;
  56. }
  57. rsvg_handle_set_dpi(rsvgh, POINTS_PER_INCH);
  58. break;
  59. }
  60. default:
  61. rsvgh = NULL;
  62. }
  63. if (rsvgh) {
  64. us->data = rsvgh;
  65. us->datafree = gvloadimage_rsvg_free;
  66. }
  67. gvusershape_file_release(us);
  68. }
  69. return rsvgh;
  70. }
  71. static void gvloadimage_rsvg_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
  72. {
  73. (void)filled;
  74. RsvgHandle* rsvgh = gvloadimage_rsvg_load(job, us);
  75. cairo_t *cr = job->context; /* target context */
  76. cairo_surface_t *surface; /* source surface */
  77. if (rsvgh) {
  78. cairo_save(cr);
  79. surface = cairo_svg_surface_create(NULL, us->w, us->h);
  80. cairo_surface_reference(surface);
  81. cairo_set_source_surface(cr, surface, 0, 0);
  82. cairo_translate(cr, b.LL.x, -b.UR.y);
  83. cairo_scale(cr, (b.UR.x - b.LL.x) / us->w, (b.UR.y - b.LL.y) / us->h);
  84. #if LIBRSVG_MAJOR_VERSION > 2 || (LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION >= 46)
  85. const RsvgRectangle viewport = {.width = b.UR.x - b.LL.x,
  86. .height = b.UR.y - b.LL.y};
  87. rsvg_handle_render_document(rsvgh, cr, &viewport, NULL);
  88. #else
  89. rsvg_handle_render_cairo(rsvgh, cr);
  90. #endif
  91. cairo_paint (cr);
  92. cairo_restore(cr);
  93. }
  94. }
  95. static gvloadimage_engine_t engine_cairo = {
  96. gvloadimage_rsvg_cairo
  97. };
  98. gvplugin_installed_t gvloadimage_rsvg_types[] = {
  99. {FORMAT_SVG_CAIRO, "svg:cairo", 1, &engine_cairo, NULL},
  100. {0, NULL, 0, NULL, NULL}
  101. };