Basically i glued Peter Drescher and Simon Ford libs in a GraphicsDisplay class, then derived TFT or LCD class (which inherits Protocols class), then the most derived ones (Inits), which are per-display and are the only part needed to be adapted to diff hw.

Fork of UniGraphic by GraphicsDisplay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GraphicsDisplay.cpp Source File

GraphicsDisplay.cpp

00001 /* mbed UniGraphic library - Graphics class
00002  * Copyright (c) 2015 Giuliano Dianda
00003  * Released under the MIT License: http://mbed.org/license/mit
00004  *
00005  * Derived work of:
00006  *
00007  * mbed GraphicsDisplay Display Library Base Class
00008  * Copyright (c) 2007-2009 sford
00009  * Released under the MIT License: http://mbed.org/license/mit
00010  *
00011  * mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00012  * Copyright (c) 2013 Peter Drescher - DC2PD
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022  
00023 
00024  
00025 #include "GraphicsDisplay.h"
00026 #define SWAP(a, b)  { a ^= b; b ^= a; a ^= b; }
00027 GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
00028     set_font((unsigned char*)Terminal6x8,32,127,true);
00029  //   foreground(0xFFFF);
00030  //   background(0x0000);
00031     char_x = 0;
00032     char_y = 0;
00033     oriented_width=0;
00034     oriented_height=0;
00035     auto_up = true;
00036 }
00037     
00038 void GraphicsDisplay::WindowMax (void)
00039 {
00040     window (0, 0, oriented_width,  oriented_height);
00041 }
00042 void GraphicsDisplay::set_width(int width)
00043 {
00044     oriented_width = width;
00045 }
00046 void GraphicsDisplay::set_height(int height)
00047 {
00048     oriented_height = height;
00049 }
00050 int GraphicsDisplay::width()
00051 {
00052     return oriented_width;
00053 }
00054 int GraphicsDisplay::height()
00055 {
00056     return oriented_height;
00057 }
00058 void GraphicsDisplay::circle(int x0, int y0, int r, unsigned short color)
00059 {
00060     int x = -r, y = 0, err = 2-2*r, e2;
00061     do {
00062         pixel(x0-x, y0+y,color);
00063         pixel(x0+x, y0+y,color);
00064         pixel(x0+x, y0-y,color);
00065         pixel(x0-x, y0-y,color);
00066         e2 = err;
00067         if (e2 <= y) {
00068             err += ++y*2+1;
00069             if (-x == y && e2 <= x) e2 = 0;
00070         }
00071         if (e2 > x) err += ++x*2+1;
00072     } while (x <= 0);
00073     if(auto_up) copy_to_lcd();
00074 }
00075 void GraphicsDisplay::fillcircle(int x0, int y0, int r, unsigned short color)
00076 {
00077     bool old_auto_up=auto_up;
00078     if(auto_up) auto_up=false;
00079     int x = -r, y = 0, err = 2-2*r, e2;
00080     do {
00081         vline(x0-x, y0-y, y0+y, color);
00082         vline(x0+x, y0-y, y0+y, color);
00083         e2 = err;
00084         if (e2 <= y) {
00085             err += ++y*2+1;
00086             if (-x == y && e2 <= x) e2 = 0;
00087         }
00088         if (e2 > x) err += ++x*2+1;
00089     } while (x <= 0);
00090     if(old_auto_up)
00091     {
00092         auto_up=true;
00093         copy_to_lcd();
00094     }
00095 }
00096 void GraphicsDisplay::hline(int x0, int x1, int y, unsigned short color)
00097 {
00098     int len = x1 - x0 + 1;
00099     window(x0,y,len,1);
00100  //   for (int j=0; j<len; j++) window_pushpixel(color);
00101     window_pushpixel(color, len);
00102     if(auto_up) copy_to_lcd();
00103     return;
00104 }
00105 void GraphicsDisplay::vline(int x, int y0, int y1, unsigned short color)
00106 {
00107     int len = y1 - y0 + 1;
00108     window(x,y0,1,len);
00109   //  for (int y=0; y<len; y++) window_pushpixel(color);
00110     window_pushpixel(color, len);
00111     if(auto_up) copy_to_lcd();
00112     return;
00113 }
00114 void GraphicsDisplay::line(int x0, int y0, int x1, int y1, unsigned short color)
00115 {
00116     //WindowMax();
00117     int   dx = 0, dy = 0;
00118     int   dx_sym = 0, dy_sym = 0;
00119     int   dx_x2 = 0, dy_x2 = 0;
00120     int   di = 0;
00121 
00122     dx = x1-x0;
00123     dy = y1-y0;
00124 
00125     if (dx == 0) {        /* vertical line */
00126         if (y1 < y0) SWAP(y0,y1);
00127         vline(x0,y0,y1,color);
00128         return;
00129     }
00130 
00131     if (dx > 0) {
00132         dx_sym = 1;
00133     } else {
00134         dx_sym = -1;
00135     }
00136     if (dy == 0) {        /* horizontal line */
00137         if (x1 < x0) SWAP(x1,x0);
00138         hline(x0,x1,y0,color);
00139         return;
00140     }
00141 
00142     if (dy > 0) {
00143         dy_sym = 1;
00144     } else {
00145         dy_sym = -1;
00146     }
00147 
00148     dx = dx_sym*dx;
00149     dy = dy_sym*dy;
00150 
00151     dx_x2 = dx*2;
00152     dy_x2 = dy*2;
00153 
00154     if (dx >= dy) {
00155         di = dy_x2 - dx;
00156         while (x0 != x1) {
00157 
00158             pixel(x0, y0, color);
00159             x0 += dx_sym;
00160             if (di<0) {
00161                 di += dy_x2;
00162             } else {
00163                 di += dy_x2 - dx_x2;
00164                 y0 += dy_sym;
00165             }
00166         }
00167         pixel(x0, y0, color);
00168     } else {
00169         di = dx_x2 - dy;
00170         while (y0 != y1) {
00171             pixel(x0, y0, color);
00172             y0 += dy_sym;
00173             if (di < 0) {
00174                 di += dx_x2;
00175             } else {
00176                 di += dx_x2 - dy_x2;
00177                 x0 += dx_sym;
00178             }
00179         }
00180         pixel(x0, y0, color);
00181     }
00182     if(auto_up) copy_to_lcd();
00183     return;
00184 }
00185 void GraphicsDisplay::rect(int x0, int y0, int x1, int y1, unsigned short color)
00186 {
00187     bool old_auto_up=auto_up;
00188     if(auto_up) auto_up=0;
00189     if (x1 > x0) hline(x0,x1,y0,color);
00190     else  hline(x1,x0,y0,color);
00191 
00192     if (y1 > y0) vline(x0,y0,y1,color);
00193     else vline(x0,y1,y0,color);
00194 
00195     if (x1 > x0) hline(x0,x1,y1,color);
00196     else  hline(x1,x0,y1,color);
00197 
00198     if (y1 > y0) vline(x1,y0,y1,color);
00199     else vline(x1,y1,y0,color);
00200     if(old_auto_up)
00201     {
00202         auto_up=true;
00203         copy_to_lcd();
00204     }
00205     return;
00206 }
00207 void GraphicsDisplay::fillrect(int x0, int y0, int x1, int y1, unsigned short color)
00208 {
00209     if(x0 > x1) SWAP(x0,x1);
00210     if(y0 > y1) SWAP(y0,y1);
00211      
00212     int h = y1 - y0 + 1;
00213     int w = x1 - x0 + 1;
00214     unsigned int pixels = h * w;
00215     window(x0,y0,w,h);
00216  //   for (unsigned int p=0; p<pixels; p++) window_pushpixel(color);
00217     window_pushpixel(color, pixels);
00218     if(auto_up) copy_to_lcd();
00219     return;
00220 }
00221 void GraphicsDisplay::locate(int x, int y)
00222 {
00223     char_x = x;
00224     char_y = y;
00225 }
00226 int GraphicsDisplay::columns()
00227 {
00228     return oriented_width / fonthor;
00229 }
00230 int GraphicsDisplay::rows()
00231 {
00232     return oriented_height / fontvert;
00233 }
00234 void GraphicsDisplay::set_font(unsigned char* f, unsigned char firstascii, unsigned char lastascii, bool proportional)
00235 {
00236     font = f;
00237     // read font parameter from start of array
00238     //fontoffset = font[0];                    // bytes / char
00239     fonthor = font[1];                       // get hor size of font
00240     fontvert = font[2];                      // get vert size of font
00241     //fontbpl = font[3];                       // bytes per line
00242     fontbpl = (fontvert+7)>>3; //bytes per line, rounded up to multiple of 8
00243     fontoffset = (fonthor*fontbpl)+1;
00244     firstch = firstascii;   // first ascii code present in font array (usually 32)
00245     lastch = lastascii;     // last ascii code present in font array (usually 127)
00246     fontprop=proportional;
00247 }
00248 int GraphicsDisplay::_putc(int value)
00249 {
00250     if (value == '\n') {    // new line
00251         char_x = 0;
00252         char_y = char_y + fontvert;
00253         if (char_y >= oriented_height - fontvert) {
00254             char_y = 0;
00255         }
00256     } else {
00257         character(char_x, char_y, value);
00258         if(auto_up) copy_to_lcd();
00259     }
00260     return value;
00261 }
00262 void GraphicsDisplay::character(int x, int y, int c)
00263 {
00264     char_x=x;
00265     char_y=y;
00266     int j,i,b;
00267     unsigned char* zeichen;
00268     unsigned char z,w;
00269 
00270     if ((c < firstch) || (c > lastch)) return;   // test char range
00271 
00272  /*   // read font parameter from start of array
00273     offset = font[0];                    // bytes / char
00274     hor = font[1];                       // get hor size of font
00275     vert = font[2];                      // get vert size of font
00276     bpl = font[3];                       // bytes per line
00277 */
00278     if (char_x + fonthor > oriented_width) {
00279         char_x = 0;
00280         char_y = char_y + fontvert;
00281         if (char_y > oriented_height - fontvert) {
00282             char_y = 0;
00283         }
00284     }
00285     window(char_x, char_y,fonthor,fontvert); // char box
00286     zeichen = &font[((c-firstch) * fontoffset) + 4]; // start of char bitmap
00287     w = zeichen[0];                          // width of actual char
00288     // construct the char into the buffer
00289     for (j=0; j<fontvert; j++) {  //  vert line
00290         for (i=0; i<fonthor; i++) {   //  horz line
00291             z =  zeichen[(fontbpl * i) + ((j & 0xF8) >> 3)+1];
00292             b = 1 << (j & 0x07);
00293             if (( z & b ) == 0x00) {
00294              //   pixel(char_x+i,char_y+j,0);
00295                 window_pushpixel(_background);
00296             } else {
00297             //    pixel(char_x+i,char_y+j,1);
00298                 window_pushpixel(_foreground);
00299             }
00300         }
00301     }
00302     if(fontprop)
00303     {
00304         if((w+1)<fonthor) char_x += w+1; // put at least 1 blank after variable-width characters, except characters that occupy whole fonthor space like "_"
00305         else char_x += fonthor;
00306     }
00307     else char_x += fonthor; // fixed width
00308 }
00309 void GraphicsDisplay::Bitmap_BW(Bitmap_s bm, int x, int y)
00310 {
00311     int h,v,b;
00312  //   int cropX;
00313     char d;
00314     if(x<0) x=0;
00315     if(y<0) y=0;
00316     int cropX = (x+bm.xSize)-oriented_width;
00317     if(cropX<0) cropX=0; 
00318     window(x, y, bm.xSize-cropX, bm.ySize);
00319     for(v=0; v < bm.ySize; v++) {   // lines
00320         if((v + y) >= oriented_height) break; // no need to crop Y
00321         for(h=0; h < bm.xSize; h++) { // pixel
00322             if((h + x) >= oriented_width) break;
00323             d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
00324             b = 0x80 >> (h & 0x07);
00325             if((d & b) == 0) {
00326                 window_pushpixel(_background);
00327             } else {
00328                 window_pushpixel(_foreground);
00329             }
00330         }
00331     }
00332     if(auto_up) copy_to_lcd();
00333 }
00334 void GraphicsDisplay::Bitmap(int x, int y, int w, int h,unsigned char *bitmap)
00335 {
00336     int  j;
00337     unsigned char  padd;
00338     unsigned short *bitmap_ptr = (unsigned short *)bitmap;    
00339 
00340     padd = w%2; // the lines are padded to multiple of 4 bytes in a bitmap
00341     if(x<0) x=0;
00342     else if(x>=oriented_width) return;
00343     if(y<0) y=0;
00344     else if(y>=oriented_height) return;
00345     int cropX = (x+w)-oriented_width;
00346     if(cropX<0) cropX=0;
00347     int cropY = (y+h)-oriented_height;
00348     if(cropY<0) cropY=0;
00349     window(x, y, w-cropX, h-cropY);
00350     bitmap_ptr += ((h - 1)* (w + padd)); // begin of last line in array (first line of image)(standard bmp scan direction is left->right bottom->top)
00351     for (j = 0; j < h-cropY; j++) {         //Lines
00352         window_pushpixelbuf(bitmap_ptr, w-cropX);
00353         bitmap_ptr -= w+padd;
00354     }
00355     if(auto_up) copy_to_lcd();
00356 }
00357 
00358 // local filesystem is not implemented in kinetis board , but you can add a SD card
00359 // fixme this whole functions needs testing and speedup
00360 int GraphicsDisplay::BMP_16(int x, int y, const char *Name_BMP)
00361 {
00362 
00363 #define OffsetPixelWidth    18
00364 #define OffsetPixelHeigh    22
00365 #define OffsetFileSize      34
00366 #define OffsetPixData       10
00367 #define OffsetBPP           28
00368 
00369     char filename[50];
00370     unsigned char BMP_Header[54];
00371     unsigned short BPP_t;
00372     unsigned int PixelWidth,PixelHeigh,start_data;
00373     unsigned int    i,off;
00374     int padd,j;
00375     unsigned short *line;
00376 
00377     // get the filename
00378     i=0;
00379     while (*Name_BMP!='\0') {
00380         filename[i++]=*Name_BMP++;
00381     }
00382     filename[i] = 0;  
00383     
00384     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
00385     if (!Image) {
00386         return(0);      // error file not found !
00387     }
00388 
00389     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00390 
00391     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00392         fclose(Image);
00393         return(-1);     // error no BMP file
00394     }
00395 
00396     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00397     if (BPP_t != 0x0010) {
00398         fclose(Image);
00399         return(-2);     // error no 16 bit BMP
00400     }
00401 
00402     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00403     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00404     if (PixelHeigh > oriented_height + y || PixelWidth > oriented_width + x) {
00405         fclose(Image);
00406         return(-3);      // to big
00407     }
00408 
00409     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00410 
00411     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
00412     if (line == NULL) {
00413         return(-4);         // error no memory
00414     }
00415 
00416     // the bmp lines are padded to multiple of 4 bytes
00417     padd = -1;
00418     do {
00419         padd ++;
00420     } while ((PixelWidth * 2 + padd)%4 != 0);
00421 
00422     window(x, y,PixelWidth ,PixelHeigh);
00423 //    wr_cmd(0x2C);  // send pixel
00424     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
00425         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
00426         fseek(Image, off ,SEEK_SET);
00427         fread(line,1,PixelWidth * 2,Image);       // read a line - slow 
00428   /*      for (i = 0; i < PixelWidth; i++)
00429         {        // copy pixel data to TFT
00430      //       wr_16(line[i]);                  // one 16 bit pixel   
00431             window_pushpixel(line[i]);
00432             
00433         } */
00434         window_pushpixelbuf(line, PixelWidth);
00435      }
00436     free (line);
00437     fclose(Image);
00438     if(auto_up) copy_to_lcd();
00439     return(1);
00440 }
00441 
00442 void GraphicsDisplay::cls (void)
00443 {
00444     unsigned int pixels = ( oriented_width * oriented_height);
00445     WindowMax();
00446     for (unsigned int i = 0; i < pixels; i++)
00447     {
00448         window_pushpixel(_background);
00449     }
00450 }
00451 void GraphicsDisplay::set_auto_up(bool up)
00452 {
00453     if(up) auto_up = true;
00454     else auto_up = false;
00455 }
00456 bool GraphicsDisplay::get_auto_up(void)
00457 {
00458     return (auto_up);
00459 }
00460 
00461