gvloadimage_gdiplus.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 <stdlib.h>
  12. #include <stddef.h>
  13. #include <string.h>
  14. #include <gvc/gvplugin_loadimage.h>
  15. #include "gvplugin_gdiplus.h"
  16. #include <stringapiset.h>
  17. #include <windows.h>
  18. #include <gdiplus.h>
  19. #include <vector>
  20. using namespace Gdiplus;
  21. static void gdiplus_freeimage(usershape_t *us) {
  22. delete reinterpret_cast<Image*>(us->data);
  23. }
  24. // convert a UTF-8 string to UTF-16
  25. static std::vector<wchar_t> utf8_to_utf16(const char *s) {
  26. // how much space do we need for the UTF-16 string?
  27. const int wide_count = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0);
  28. // translate it
  29. std::vector<wchar_t> utf16(wide_count);
  30. if (wide_count > 0) {
  31. (void)MultiByteToWideChar(CP_UTF8, 0, s, -1, utf16.data(), wide_count);
  32. } else {
  33. utf16.push_back(0);
  34. }
  35. return utf16;
  36. }
  37. static Image* gdiplus_loadimage(GVJ_t * job, usershape_t *us)
  38. {
  39. assert(job);
  40. (void)job;
  41. assert(us);
  42. assert(us->name);
  43. if (us->data && us->datafree != gdiplus_freeimage) {
  44. us->datafree(us); /* free incompatible cache data */
  45. us->data = nullptr;
  46. us->datafree = nullptr;
  47. }
  48. if (!us->data) { /* read file into cache */
  49. if (!gvusershape_file_access(us))
  50. return nullptr;
  51. /* create image from the usershape file */
  52. const std::vector<wchar_t> filename = utf8_to_utf16(us->name);
  53. us->data = Image::FromFile(filename.data());
  54. /* clean up */
  55. if (us->data)
  56. us->datafree = gdiplus_freeimage;
  57. gvusershape_file_release(us);
  58. }
  59. return reinterpret_cast<Image*>(us->data);
  60. }
  61. static void gdiplus_loadimage_gdiplus(GVJ_t * job, usershape_t *us, boxf b, bool)
  62. {
  63. /* get the image from usershape details, then blit it to the context */
  64. if (Image *image = gdiplus_loadimage(job, us)) {
  65. auto g = reinterpret_cast<Graphics*>(job->context);
  66. g->DrawImage(image, RectF(b.LL.x, b.LL.y, b.UR.x - b.LL.x, b.UR.y - b.LL.y));
  67. }
  68. }
  69. static gvloadimage_engine_t engine = {
  70. gdiplus_loadimage_gdiplus
  71. };
  72. gvplugin_installed_t gvloadimage_gdiplus_types[] = {
  73. {FORMAT_BMP, "bmp:gdiplus", 8, &engine, nullptr},
  74. {FORMAT_GIF, "gif:gdiplus", 8, &engine, nullptr},
  75. {FORMAT_JPEG, "jpe:gdiplus", 8, &engine, nullptr},
  76. {FORMAT_JPEG, "jpeg:gdiplus", 8, &engine, nullptr},
  77. {FORMAT_JPEG, "jpg:gdiplus", 8, &engine, nullptr},
  78. {FORMAT_PNG, "png:gdiplus", 8, &engine, nullptr},
  79. {0, nullptr, 0, nullptr, nullptr}
  80. };