gvdevice_gdiplus.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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 <gvc/gvplugin_device.h>
  12. #include <gvc/gvplugin_render.h>
  13. #include <gvc/gvio.h>
  14. #include "gvplugin_gdiplus.h"
  15. using namespace Gdiplus;
  16. static void gdiplus_format(GVJ_t *job)
  17. {
  18. UseGdiplus();
  19. /* allocate memory and attach stream to it */
  20. HGLOBAL buffer = GlobalAlloc(GMEM_MOVEABLE, 0);
  21. IStream *stream = nullptr;
  22. CreateStreamOnHGlobal(buffer, FALSE, &stream); /* FALSE means don't deallocate buffer when releasing stream */
  23. Bitmap bitmap(
  24. job->width, /* width in pixels */
  25. job->height, /* height in pixels */
  26. job->width * BYTES_PER_PIXEL, /* bytes per row: exactly width # of pixels */
  27. PixelFormat32bppPARGB, /* pixel format: corresponds to CAIRO_FORMAT_ARGB32 */
  28. (BYTE*)job->imagedata); /* pixel data from job */
  29. SaveBitmapToStream(bitmap, stream, job->device.id);
  30. /* blast the streamed buffer back to the gvdevice */
  31. /* NOTE: this is somewhat inefficient since we should be streaming directly to gvdevice rather than buffering first */
  32. /* ... however, GDI+ requires any such direct IStream to implement Seek Read, Write, Stat methods and gvdevice really only offers a write-once model */
  33. stream->Release();
  34. gvwrite(job, (const char*)GlobalLock(buffer), GlobalSize(buffer));
  35. GlobalFree(buffer);
  36. }
  37. static gvdevice_engine_t gdiplus_engine = {
  38. nullptr, /* gdiplus_initialize */
  39. gdiplus_format,
  40. nullptr, /* gdiplus_finalize */
  41. };
  42. static gvdevice_features_t device_features_gdiplus = {
  43. GVDEVICE_BINARY_FORMAT
  44. | GVDEVICE_DOES_TRUECOLOR,/* flags */
  45. {0.,0.}, /* default margin - points */
  46. {0.,0.}, /* default page width, height - points */
  47. {96.,96.}, /* dpi */
  48. };
  49. gvplugin_installed_t gvdevice_gdiplus_types_for_cairo[] = {
  50. {FORMAT_BMP, "bmp:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  51. {FORMAT_GIF, "gif:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  52. {FORMAT_JPEG, "jpe:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  53. {FORMAT_JPEG, "jpeg:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  54. {FORMAT_JPEG, "jpg:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  55. {FORMAT_PNG, "png:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  56. {FORMAT_TIFF, "tif:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  57. {FORMAT_TIFF, "tiff:cairo", 8, &gdiplus_engine, &device_features_gdiplus},
  58. {0, nullptr, 0, nullptr, nullptr}
  59. };