PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/core/TVoutSFML/Overlay.cpp

https://github.com/jonneva/mb
C++ | 275 lines | 217 code | 21 blank | 37 comment | 54 complexity | 74b287a6661c787b6f8bea35881c7c39 MD5 | raw file
Possible License(s): LGPL-2.1
  1. #include "TVout.h"
  2. #include "wrapper.h"
  3. // Bitmap overlay functions
  4. void overlaybitmap(int16_t x, int16_t y, const unsigned char * bmp,
  5. uint16_t i, uint8_t width, uint8_t lines) {
  6. uint8_t temp, lshift, rshift, save, xtra;
  7. uint16_t si = 0;
  8. rshift = x&7;
  9. lshift = 8-rshift;
  10. if (width == 0) {
  11. //width = pgm_read_byte((uint32_t)(bmp) + i);
  12. width = bmp[i];
  13. i++;
  14. }
  15. if (lines == 0) {
  16. //lines = pgm_read_byte((uint32_t)(bmp) + i);
  17. lines = bmp[i];
  18. i++;
  19. }
  20. if (width&7) {
  21. xtra = width&7;
  22. width = width/8;
  23. width++;
  24. }
  25. else {
  26. xtra = 8;
  27. width = width/8;
  28. }
  29. for (uint8_t l = 0; l < lines; l++) {
  30. if (y+l >= 0) {// added this to allow clipped sky
  31. si = ((y + l) % display.vres)*display.hres + x/8;
  32. //si = (y + l)*display.hres + x/8;
  33. if (width == 1)
  34. temp = 0xff >> rshift + xtra;
  35. else
  36. temp = 0;
  37. save = display.screen[si];
  38. //temp = pgm_read_byte((uint32_t)(bmp) + i++);
  39. temp = bmp[i++];
  40. display.screen[si++] |= temp >> rshift;
  41. for ( uint16_t b = i + width-1; i < b; i++) {
  42. if (si % display.hres == 0) {
  43. // wrapped around to the left side
  44. si -= display.hres;
  45. }
  46. save = display.screen[si];
  47. display.screen[si] |= temp << lshift;
  48. //temp = pgm_read_byte((uint32_t)(bmp) + i);
  49. temp = bmp[i];
  50. display.screen[si++] |= temp >> rshift;
  51. }
  52. if (si % display.hres == 0) {
  53. // wrapped around to the left side
  54. si -= display.hres; // added *2 to make wrap on same row
  55. }
  56. if (rshift + xtra < 8)
  57. display.screen[si-1] |= (save & (0xff >> rshift + xtra)); //test me!!!
  58. display.screen[si] |= temp << lshift;
  59. } else {i+=width; }// increment bitmap pointe
  60. }
  61. } // end of bitmap
  62. void erasebitmap(uint8_t x, uint8_t y, const unsigned char * bmp,
  63. uint16_t i, uint8_t width, uint8_t lines) {
  64. uint8_t temp, lshift, rshift, save, xtra;
  65. uint16_t si = 0;
  66. rshift = x&7;
  67. lshift = 8-rshift;
  68. if (width == 0) {
  69. //width = pgm_read_byte((uint32_t)(bmp) + i);
  70. width = bmp[i];
  71. i++;
  72. }
  73. if (lines == 0) {
  74. //lines = pgm_read_byte((uint32_t)(bmp) + i);
  75. lines = bmp[i];
  76. i++;
  77. }
  78. if (width&7) {
  79. xtra = width&7;
  80. width = width/8;
  81. width++;
  82. }
  83. else {
  84. xtra = 8;
  85. width = width/8;
  86. }
  87. for (uint8_t l = 0; l < lines; l++) {
  88. si = ((y + l) % display.vres)*display.hres + x/8;
  89. //si = (y + l)*display.hres + x/8;
  90. if (width == 1)
  91. temp = 0xff >> rshift + xtra;
  92. else
  93. temp = 0;
  94. save = display.screen[si];
  95. //temp = pgm_read_byte((uint32_t)(bmp) + i++);
  96. temp = bmp[i++];
  97. display.screen[si++] &= ~(temp >> rshift);
  98. for ( uint16_t b = i + width-1; i < b; i++) {
  99. if (si % display.hres == 0) {
  100. // wrapped around to the left side
  101. si -= display.hres;
  102. }
  103. save = display.screen[si];
  104. display.screen[si] &= ~(temp << lshift);
  105. //temp = pgm_read_byte((uint32_t)(bmp) + i);
  106. temp = bmp[i];
  107. display.screen[si++] &= ~(temp >> rshift);
  108. }
  109. if (si % display.hres == 0) {
  110. // wrapped around to the left side
  111. si -= display.hres;
  112. }
  113. if (rshift + xtra < 8)
  114. display.screen[si-1] &= ~(save & (0xff >> rshift + xtra)); //test me!!!
  115. if (rshift + xtra - 8 > 0)
  116. display.screen[si] &= ~(temp << lshift);
  117. }
  118. } // end of bitmap
  119. void alphabitmap(int8_t x, int8_t y, const unsigned char * bmp, const unsigned char * alpha) {
  120. // NEEDS AT LEAST 1 byte wide bitmap !!!! Alpha needs to be same size !
  121. uint8_t temp, lshift=0, rshift=0, save, xtra, width, lines;
  122. uint8_t atemp, maskedbyte, onbits, offbits;
  123. uint16_t i=0, si = 0;
  124. if (x>=0) {
  125. // NORMAL CASE, NOT CROPPED
  126. rshift = x&7; // rshift = bits OVER even bytes, eg. 14 = 110
  127. lshift = 8-rshift; // lshift = bits UNTIL next even byte, eg. 2 = 10
  128. width = bmp[i]; i++; //width = pgm_read_byte((uint32_t)(bmp) + i);
  129. lines = bmp[i]; i++;//lines = pgm_read_byte((uint32_t)(bmp) + i);
  130. if (width&7) { // if width is not divisible by 8
  131. xtra = width&7; // xtra is amount of xtra bits
  132. width = width/8; // width is width in even bytes
  133. width++; // plus one uneven one ...
  134. } else { // width IS divisible by 8
  135. xtra = 8; // xtra = 1000b
  136. width = width/8; // width = even num of bytes
  137. }
  138. // START Y LOOP
  139. for (uint8_t l = 0; l < lines; l++) {
  140. si = ((y + l) % display.vres)*display.hres + x/8; //index to screen
  141. save = display.screen[si]; // Save is the screen byte
  142. atemp = alpha[i]; // read first byte of alpha data
  143. temp = bmp[i]; i++; // temp = pgm_read_byte((uint32_t)(bmp) + i++); //bmp data
  144. onbits = temp & atemp; // get bits that should be turned on
  145. offbits = ~temp & atemp; // get bits that should be turned off
  146. temp = (onbits >> rshift ) | save; // add onbits
  147. temp = temp & (~(offbits >> rshift)); // delete offbits
  148. display.screen[si] = temp; si++; //first byte to screen buffer, increment
  149. // START X LOOP
  150. for ( uint16_t b = i + width-1; i < b; i++) {
  151. if (si % display.hres == 0) {
  152. //si -= display.hres; // wrap disabled
  153. } else {
  154. // draw the leftovers of a previous shifted byte first
  155. save = display.screen[si]; // get byte at si
  156. temp = (onbits << lshift ) | save; // add onbits
  157. temp = temp & (~(offbits << lshift)); // delete offbits
  158. }
  159. save = temp; // waiting for ls bits of the next bmp byte
  160. // add the leftside bits of a new image byte
  161. atemp = alpha[i]; // read byte of alpha data
  162. temp = bmp[i];
  163. onbits = temp & atemp; // get bits that should be turned on
  164. offbits = ~temp & atemp; // get bits that should be turned off
  165. temp = (onbits >> rshift) | save; // add onbits
  166. temp = temp & (~(offbits >> rshift)); // delete offbits
  167. display.screen[si] = temp; // was temp
  168. si++; // increment screen index to next screen byte
  169. }
  170. // END OF X LOOP
  171. if (si % display.hres == 0) { // now drawing last byte of row, check for edge
  172. //si -= display.hres; // I need to disable this
  173. } else {
  174. save = display.screen[si]; // get next screen byte
  175. temp = (onbits << lshift ) | save; // add leftover onbits
  176. temp = temp & (~(offbits << lshift)); // delete leftover
  177. display.screen[si] = temp;// save; //temp; // store 8-lshift leftmost bits
  178. }
  179. }
  180. // END OF LINES (Y) LOOP
  181. } else
  182. {
  183. // CROPPED CASE
  184. rshift = x&7; // rshift = bits OVER even bytes, eg. 14 = 110
  185. if (rshift) {
  186. lshift = 8-rshift; // lshift = bits UNTIL next even byte, eg. 2 = 10
  187. } else {
  188. rshift = 8; // avoid divisible by eight cases = masks second byte
  189. }
  190. width = bmp[i]; i++; //width = pgm_read_byte((uint32_t)(bmp) + i);
  191. if (width <= -x) return; // its not visible anymore
  192. lines = bmp[i]; i++;//lines = pgm_read_byte((uint32_t)(bmp) + i);
  193. width+=x; // delete cropped width from width
  194. if (width&7) { // if width is not divisible by 8
  195. xtra = 8-width&7; // xtra is amount of xtra bits
  196. width = width/8; // width is width in even bytes
  197. //width++; // plus one uneven one ...
  198. } else { // width IS divisible by 8
  199. xtra = 0; // no extra
  200. width = width/8; // width = even num of bytes
  201. //width++;
  202. }
  203. // START Y LOOP
  204. for (uint8_t l = 0; l < lines; l++) {
  205. i+=-x/8; // increment bmp pointer i to point to first visible byte
  206. si = ((y + l) % display.vres)*display.hres; // si is index to screen
  207. // START X LOOP
  208. for ( uint16_t b = i + width; i < b;) {
  209. // Add left shifted bits of first byte
  210. save = display.screen[si]; // Save is the screen byte
  211. atemp = alpha[i]; // read first byte of alpha data
  212. temp = bmp[i]; // temp = pgm_read_byte((uint32_t)(bmp) + i++); //bmp data
  213. onbits = temp & atemp; // get bits that should be turned on
  214. offbits = ~temp & atemp; // get bits that should be turned off
  215. temp = (onbits << lshift ) | save; // add onbits to screen pixel
  216. save = temp & (~(offbits << lshift)); // delete offbits, store result
  217. // Add right shifted bits of second byte
  218. atemp = alpha[i+1]; // read first byte of alpha data
  219. temp = bmp[i+1]; // temp = pgm_read_byte((uint32_t)(bmp) + i++); //bmp data
  220. onbits = temp & atemp; // get bits that should be turned on
  221. offbits = ~temp & atemp; // get bits that should be turned off
  222. temp = (onbits >> rshift ) | save; // add onbits to intermediate result
  223. temp = temp & (~(offbits >> rshift)); // delete offbits, store result
  224. //temp = 0xFF;
  225. display.screen[si] = temp; si++; //first byte to screen buffer, increment
  226. i++;
  227. }
  228. // END OF X LOOP
  229. if (xtra) { // There are extra bits remaining
  230. save = display.screen[si]; // Save is the screen byte
  231. atemp = alpha[i]; // read first byte of alpha data
  232. temp = bmp[i]; // temp = pgm_read_byte((uint32_t)(bmp) + i++); //bmp data
  233. onbits = temp & atemp; // get bits that should be turned on
  234. offbits = ~temp & atemp; // get bits that should be turned off
  235. temp = (onbits << lshift ) | save; // add onbits to screen pixel
  236. save = temp & (~(offbits << lshift)); // delete offbits, store result
  237. // Add right shifted bits of second byte, will be masked out if unnecessary
  238. atemp = alpha[i+1]; // read first byte of alpha data
  239. temp = bmp[i+1]; // temp = pgm_read_byte((uint32_t)(bmp) + i++); //bmp data
  240. onbits = temp & atemp; // get bits that should be turned on
  241. offbits = ~temp & atemp; // get bits that should be turned off
  242. temp = (onbits >> rshift ); // add onbits to intermediate result
  243. temp = temp & (~(offbits >> rshift)); // delete offbits, store result
  244. temp = (temp >> xtra) << xtra; // clean unwanted bits
  245. temp = temp | save; //bugfix
  246. //temp = 0xff;
  247. display.screen[si] = temp; //first byte to screen buffer, increment
  248. if ((-x&7)>xtra && lshift) i++; // cases where last si byte includes only a part of last i byte, also avoid divisible by eight cases
  249. }
  250. i++;
  251. }
  252. // END OF LINES (Y) LOOP
  253. }
  254. } // end of alphabitmap