PageRenderTime 85ms CodeModel.GetById 30ms app.highlight 38ms RepoModel.GetById 13ms 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
  1#include "TVout.h"

  2#include "wrapper.h"

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