gvloadimage_poppler.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 <stdlib.h>
  13. #include <sys/stat.h>
  14. #include <gvc/gvplugin_loadimage.h>
  15. #ifdef HAVE_PANGOCAIRO
  16. #ifdef HAVE_POPPLER
  17. #include <poppler.h>
  18. #include <cairo.h>
  19. typedef enum {
  20. FORMAT_PDF_CAIRO,
  21. } format_type;
  22. static void gvloadimage_poppler_free(usershape_t *us)
  23. {
  24. g_object_unref(us->data);
  25. }
  26. static PopplerDocument* gvloadimage_poppler_load(GVJ_t * job, usershape_t *us)
  27. {
  28. PopplerDocument *document = NULL;
  29. int num_pages;
  30. assert(job);
  31. assert(us);
  32. assert(us->name);
  33. if (us->data) {
  34. if (us->datafree == gvloadimage_poppler_free)
  35. document = us->data; /* use cached data */
  36. else {
  37. us->datafree(us); /* free incompatible cache data */
  38. us->data = NULL;
  39. us->datafree = NULL;
  40. }
  41. }
  42. if (!document) { /* read file into cache */
  43. if (!gvusershape_file_access(us))
  44. return NULL;
  45. switch (us->type) {
  46. case FT_PDF: {
  47. char *absolute;
  48. if (g_path_is_absolute(us->name)) {
  49. absolute = g_strdup (us->name);
  50. } else {
  51. char *dir = g_get_current_dir();
  52. absolute = g_build_filename(dir, us->name, NULL);
  53. free (dir);
  54. }
  55. GError *error = NULL;
  56. char *uri = g_filename_to_uri(absolute, NULL, &error);
  57. g_free(absolute);
  58. if (uri == NULL) {
  59. printf("%s\n", error->message);
  60. g_error_free(error);
  61. return NULL;
  62. }
  63. document = poppler_document_new_from_file (uri, NULL, &error);
  64. g_free(uri);
  65. if (document == NULL) {
  66. printf("%s\n", error->message);
  67. g_error_free(error);
  68. return NULL;
  69. }
  70. // check page 1 exists
  71. num_pages = poppler_document_get_n_pages (document);
  72. if (num_pages < 1) {
  73. printf("poppler fail: num_pages %d, must be at least 1", num_pages);
  74. return NULL;
  75. }
  76. break;
  77. }
  78. default:
  79. break;
  80. }
  81. if (document) {
  82. us->data = document;
  83. us->datafree = gvloadimage_poppler_free;
  84. }
  85. gvusershape_file_release(us);
  86. }
  87. return document;
  88. }
  89. static void gvloadimage_poppler_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
  90. {
  91. (void)filled;
  92. PopplerDocument* document = gvloadimage_poppler_load(job, us);
  93. PopplerPage* page;
  94. cairo_t *cr = job->context; /* target context */
  95. cairo_surface_t *surface; /* source surface */
  96. if (document) {
  97. // already done this once, so no err checking
  98. page = poppler_document_get_page (document, 0);
  99. cairo_save(cr);
  100. surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, (int)us->w, (int)us->h);
  101. cairo_surface_reference(surface);
  102. cairo_set_source_surface(cr, surface, 0, 0);
  103. cairo_translate(cr, b.LL.x, -b.UR.y);
  104. cairo_scale(cr, (b.UR.x - b.LL.x)/(us->w), (b.UR.y - b.LL.y)/(us->h));
  105. poppler_page_render (page, cr);
  106. cairo_paint (cr);
  107. cairo_restore(cr);
  108. }
  109. }
  110. static gvloadimage_engine_t engine_cairo = {
  111. gvloadimage_poppler_cairo
  112. };
  113. #endif
  114. #endif
  115. gvplugin_installed_t gvloadimage_poppler_types[] = {
  116. #ifdef HAVE_PANGOCAIRO
  117. #ifdef HAVE_POPPLER
  118. {FORMAT_PDF_CAIRO, "pdf:cairo", 1, &engine_cairo, NULL},
  119. #endif
  120. #endif
  121. {0, NULL, 0, NULL, NULL}
  122. };