gvloadimage_quartz.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 <string.h>
  15. #include <gvc/gvplugin_loadimage.h>
  16. #include "gvplugin_quartz.h"
  17. static size_t file_data_provider_get_bytes(void *info, void *buffer, size_t count)
  18. {
  19. return fread(buffer, 1, count, (FILE*)info);
  20. }
  21. static void file_data_provider_rewind(void *info)
  22. {
  23. rewind(info);
  24. }
  25. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000
  26. static off_t file_data_provider_skip_forward(void *info, off_t count)
  27. {
  28. fseek((FILE*)info, count, SEEK_CUR);
  29. return count;
  30. }
  31. /* bridge FILE* to a sequential CGDataProvider */
  32. static CGDataProviderSequentialCallbacks file_data_provider_callbacks = {
  33. 0,
  34. file_data_provider_get_bytes,
  35. file_data_provider_skip_forward,
  36. file_data_provider_rewind,
  37. NULL
  38. };
  39. #else
  40. static void file_data_provider_skip_bytes(void *info, size_t count)
  41. {
  42. fseek((FILE*)info, count, SEEK_CUR);
  43. }
  44. /* bridge FILE* to a sequential CGDataProvider */
  45. static CGDataProviderCallbacks file_data_provider_callbacks = {
  46. file_data_provider_get_bytes,
  47. file_data_provider_skip_bytes,
  48. file_data_provider_rewind,
  49. NULL
  50. };
  51. #endif
  52. static void quartz_freeimage(usershape_t *us)
  53. {
  54. CGImageRelease(us->data);
  55. }
  56. static CGImageRef quartz_loadimage(GVJ_t * job, usershape_t *us)
  57. {
  58. assert(job);
  59. assert(us);
  60. assert(us->name);
  61. if (us->data && us->datafree != quartz_freeimage) {
  62. us->datafree(us); /* free incompatible cache data */
  63. us->data = NULL;
  64. us->datafree = NULL;
  65. }
  66. if (!us->data) { /* read file into cache */
  67. if (!gvusershape_file_access(us))
  68. return NULL;
  69. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000
  70. CGDataProviderRef data_provider = CGDataProviderCreateSequential(us->f, &file_data_provider_callbacks);
  71. #else
  72. CGDataProviderRef data_provider = CGDataProviderCreate(us->f, &file_data_provider_callbacks);
  73. #endif
  74. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040
  75. /* match usershape format to a UTI for type hinting, if possible */
  76. format_type hint_format_type;
  77. switch (us->type) {
  78. case FT_BMP:
  79. hint_format_type = FORMAT_BMP;
  80. break;
  81. case FT_GIF:
  82. hint_format_type = FORMAT_GIF;
  83. break;
  84. case FT_PNG:
  85. hint_format_type = FORMAT_PNG;
  86. break;
  87. case FT_JPEG:
  88. hint_format_type = FORMAT_JPEG;
  89. break;
  90. case FT_PDF:
  91. hint_format_type = FORMAT_PDF;
  92. break;
  93. default:
  94. hint_format_type = FORMAT_NONE;
  95. break;
  96. }
  97. CFStringRef uti_hint = format_to_uti(hint_format_type);
  98. CFDictionaryRef options = hint_format_type == FORMAT_NONE ? NULL : CFDictionaryCreate(
  99. kCFAllocatorDefault,
  100. (const void **)&kCGImageSourceTypeIdentifierHint,
  101. (const void **)&uti_hint,
  102. 1,
  103. &kCFTypeDictionaryKeyCallBacks,
  104. &kCFTypeDictionaryValueCallBacks);
  105. /* get first image from usershape file */
  106. CGImageSourceRef image_source = CGImageSourceCreateWithDataProvider(data_provider, options);
  107. us->data = CGImageSourceCreateImageAtIndex(image_source, 0, NULL);
  108. if (image_source)
  109. CFRelease(image_source);
  110. if (options)
  111. CFRelease(options);
  112. #else
  113. switch (us->type) {
  114. case FT_PNG:
  115. us->data = CGImageCreateWithPNGDataProvider(data_provider, NULL, false, kCGRenderingIntentDefault);
  116. break;
  117. case FT_JPEG:
  118. us->data = CGImageCreateWithJPEGDataProvider(data_provider, NULL, false, kCGRenderingIntentDefault);
  119. break;
  120. default:
  121. us->data = NULL;
  122. break;
  123. }
  124. #endif
  125. /* clean up */
  126. if (us->data)
  127. us->datafree = quartz_freeimage;
  128. CGDataProviderRelease(data_provider);
  129. gvusershape_file_release(us);
  130. }
  131. return us->data;
  132. }
  133. static void quartz_loadimage_quartz(GVJ_t * job, usershape_t *us, boxf b, bool filled)
  134. {
  135. (void)filled;
  136. /* get the image from usershape details, then blit it to the context */
  137. CGImageRef image = quartz_loadimage(job, us);
  138. if (image)
  139. CGContextDrawImage((CGContextRef)job->context, CGRectMake(b.LL.x, b.LL.y, b.UR.x - b.LL.x, b.UR.y - b.LL.y), image);
  140. }
  141. static gvloadimage_engine_t engine = {
  142. quartz_loadimage_quartz
  143. };
  144. gvplugin_installed_t gvloadimage_quartz_types[] = {
  145. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040
  146. {FORMAT_BMP, "bmp:quartz", 8, &engine, NULL},
  147. {FORMAT_GIF, "gif:quartz", 8, &engine, NULL},
  148. {FORMAT_PDF, "pdf:quartz", 8, &engine, NULL},
  149. #endif
  150. {FORMAT_JPEG, "jpe:quartz", 8, &engine, NULL},
  151. {FORMAT_JPEG, "jpeg:quartz", 8, &engine, NULL},
  152. {FORMAT_JPEG, "jpg:quartz", 8, &engine, NULL},
  153. {FORMAT_PNG, "png:quartz", 8, &engine, NULL},
  154. {0, NULL, 0, NULL, NULL}
  155. };