You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Surface_OSX.cxx 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Copyright 2016 Pierre Ossman for Cendio AB
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #include <assert.h>
  19. #include <ApplicationServices/ApplicationServices.h>
  20. #include <FL/Fl_RGB_Image.H>
  21. #include <FL/Fl_Window.H>
  22. #include <FL/x.H>
  23. #include <rdr/Exception.h>
  24. #include "Surface.h"
  25. void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  26. {
  27. unsigned char* out;
  28. int x, y;
  29. r = (unsigned)r * a / 255;
  30. g = (unsigned)g * a / 255;
  31. b = (unsigned)b * a / 255;
  32. out = data;
  33. for (y = 0;y < width();y++) {
  34. for (x = 0;x < height();x++) {
  35. *out++ = b;
  36. *out++ = g;
  37. *out++ = r;
  38. *out++ = a;
  39. }
  40. }
  41. }
  42. void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
  43. {
  44. CGRect rect;
  45. CGContextSaveGState(fl_gc);
  46. // Reset the transformation matrix back to the default identity
  47. // matrix as otherwise we get a massive performance hit
  48. CGContextConcatCTM(fl_gc, CGAffineTransformInvert(CGContextGetCTM(fl_gc)));
  49. // macOS Coordinates are from bottom left, not top left
  50. src_y = height() - (src_y + h);
  51. y = Fl_Window::current()->h() - (y + h);
  52. // We have to use clipping to partially display an image
  53. rect.origin.x = x;
  54. rect.origin.y = y;
  55. rect.size.width = w;
  56. rect.size.height = h;
  57. CGContextClipToRect(fl_gc, rect);
  58. rect.origin.x = x - src_x;
  59. rect.origin.y = y - src_y;
  60. rect.size.width = width();
  61. rect.size.height = height();
  62. CGContextDrawImage(fl_gc, rect, image);
  63. CGContextRestoreGState(fl_gc);
  64. }
  65. void Surface::alloc()
  66. {
  67. CGColorSpaceRef lut;
  68. CGDataProviderRef provider;
  69. data = new unsigned char[width() * height() * 4];
  70. lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
  71. if (!lut) {
  72. lut = CGColorSpaceCreateDeviceRGB();
  73. if (!lut)
  74. throw rdr::Exception("CGColorSpaceCreateDeviceRGB");
  75. }
  76. provider = CGDataProviderCreateWithData(NULL, data,
  77. width() * height() * 4, NULL);
  78. if (!provider)
  79. throw rdr::Exception("CGDataProviderCreateWithData");
  80. image = CGImageCreate(width(), height(), 8, 32, width() * 4, lut,
  81. kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
  82. provider, NULL, false, kCGRenderingIntentDefault);
  83. CGColorSpaceRelease(lut);
  84. CGDataProviderRelease(provider);
  85. if (!image)
  86. throw rdr::Exception("CGImageCreate");
  87. }
  88. void Surface::dealloc()
  89. {
  90. CGImageRelease(image);
  91. delete [] data;
  92. }
  93. void Surface::update(const Fl_RGB_Image* image)
  94. {
  95. int x, y;
  96. const unsigned char* in;
  97. unsigned char* out;
  98. assert(image->w() == width());
  99. assert(image->h() == height());
  100. // Convert data and pre-multiply alpha
  101. in = (const unsigned char*)image->data()[0];
  102. out = data;
  103. for (y = 0;y < image->h();y++) {
  104. for (x = 0;x < image->w();x++) {
  105. switch (image->d()) {
  106. case 1:
  107. *out++ = in[0];
  108. *out++ = in[0];
  109. *out++ = in[0];
  110. *out++ = 0xff;
  111. break;
  112. case 2:
  113. *out++ = (unsigned)in[0] * in[1] / 255;
  114. *out++ = (unsigned)in[0] * in[1] / 255;
  115. *out++ = (unsigned)in[0] * in[1] / 255;
  116. *out++ = in[1];
  117. break;
  118. case 3:
  119. *out++ = in[2];
  120. *out++ = in[1];
  121. *out++ = in[0];
  122. *out++ = 0xff;
  123. break;
  124. case 4:
  125. *out++ = (unsigned)in[2] * in[3] / 255;
  126. *out++ = (unsigned)in[1] * in[3] / 255;
  127. *out++ = (unsigned)in[0] * in[3] / 255;
  128. *out++ = in[3];
  129. break;
  130. }
  131. in += image->d();
  132. }
  133. if (image->ld() != 0)
  134. in += image->ld() - image->w() * image->d();
  135. }
  136. }