Zoltan Hudak / Mbed OS LCD_McuFriend_FSMC_STM32F407
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 #include "GraphicsDisplay.h"
00023 #define SWAP(a, b) { \
00024         a ^= b; \
00025         b ^= a; \
00026         a ^= b; \
00027     }
00028 
00029 /**
00030  * @brief
00031  * @note
00032  * @param
00033  * @retval
00034  */
00035 GraphicsDisplay::GraphicsDisplay(const char* name) :
00036     TextDisplay(name)
00037 {
00038     set_font((unsigned char*)Terminal6x8, 32, 127, true);
00039 
00040     //   foreground(0xFFFF);
00041     //   background(0x0000);
00042     char_x = 0;
00043     char_y = 0;
00044     oriented_width = 0;
00045     oriented_height = 0;
00046     fontzoomver = 1;
00047     fontzoomhor = 1;
00048     auto_up = true;
00049 }
00050 
00051 /**
00052  * @brief
00053  * @note
00054  * @param
00055  * @retval
00056  */
00057 void GraphicsDisplay::WindowMax(void)
00058 {
00059     window(0, 0, oriented_width, oriented_height);
00060 }
00061 
00062 /**
00063  * @brief
00064  * @note
00065  * @param
00066  * @retval
00067  */
00068 void GraphicsDisplay::set_width(int width)
00069 {
00070     oriented_width = width;
00071 }
00072 
00073 /**
00074  * @brief
00075  * @note
00076  * @param
00077  * @retval
00078  */
00079 void GraphicsDisplay::set_height(int height)
00080 {
00081     oriented_height = height;
00082 }
00083 
00084 /**
00085  * @brief
00086  * @note
00087  * @param
00088  * @retval
00089  */
00090 int GraphicsDisplay::width()
00091 {
00092     return oriented_width;
00093 }
00094 
00095 /**
00096  * @brief
00097  * @note
00098  * @param
00099  * @retval
00100  */
00101 int GraphicsDisplay::height()
00102 {
00103     return oriented_height;
00104 }
00105 
00106 /**
00107  * @brief
00108  * @note
00109  * @param
00110  * @retval
00111  */
00112 void GraphicsDisplay::circle(int x0, int y0, int r, unsigned short color)
00113 {
00114     int x = -r;
00115     int y = 0;
00116     int err = 2 - 2 * r;
00117     int e2;
00118 
00119     do
00120     {
00121         pixel(x0 - x, y0 + y, color);
00122         pixel(x0 + x, y0 + y, color);
00123         pixel(x0 + x, y0 - y, color);
00124         pixel(x0 - x, y0 - y, color);
00125         e2 = err;
00126         if (e2 <= y) {
00127             err += ++y * 2 + 1;
00128             if (-x == y && e2 <= x)
00129                 e2 = 0;
00130         }
00131 
00132         if (e2 > x)
00133             err += ++x * 2 + 1;
00134     } while (x <= 0);
00135     if (auto_up)
00136         copy_to_lcd();
00137 }
00138 
00139 /**
00140  * @brief
00141  * @note
00142  * @param
00143  * @retval
00144  */
00145 void GraphicsDisplay::fillcircle(int x0, int y0, int r, unsigned short color)
00146 {
00147     bool    old_auto_up = auto_up;
00148     if (auto_up)
00149         auto_up = false;
00150 
00151     int x = -r, y = 0, err = 2 - 2 * r, e2;
00152     do
00153     {
00154         vline(x0 - x, y0 - y, y0 + y, color);
00155         vline(x0 + x, y0 - y, y0 + y, color);
00156         e2 = err;
00157         if (e2 <= y) {
00158             err += ++y * 2 + 1;
00159             if (-x == y && e2 <= x)
00160                 e2 = 0;
00161         }
00162 
00163         if (e2 > x)
00164             err += ++x * 2 + 1;
00165     } while (x <= 0);
00166     if (old_auto_up) {
00167         auto_up = true;
00168         copy_to_lcd();
00169     }
00170 }
00171 
00172 /**
00173  * @brief
00174  * @note
00175  * @param
00176  * @retval
00177  */
00178 void GraphicsDisplay::hline(int x0, int x1, int y, unsigned short color)
00179 {
00180     int len = x1 - x0 + 1;
00181     window(x0, y, len, 1);
00182 
00183     //   for (int j=0; j<len; j++) window_pushpixel(color);
00184     window_pushpixel(color, len);
00185     if (auto_up)
00186         copy_to_lcd();
00187     return;
00188 }
00189 
00190 /**
00191  * @brief
00192  * @note
00193  * @param
00194  * @retval
00195  */
00196 void GraphicsDisplay::vline(int x, int y0, int y1, unsigned short color)
00197 {
00198     int len = y1 - y0 + 1;
00199     window(x, y0, 1, len);
00200 
00201     //  for (int y=0; y<len; y++) window_pushpixel(color);
00202     window_pushpixel(color, len);
00203     if (auto_up)
00204         copy_to_lcd();
00205     return;
00206 }
00207 
00208 /**
00209  * @brief
00210  * @note
00211  * @param
00212  * @retval
00213  */
00214 void GraphicsDisplay::line(int x0, int y0, int x1, int y1, unsigned short color)
00215 {
00216     //WindowMax();
00217     int dx = 0, dy = 0;
00218     int dx_sym = 0, dy_sym = 0;
00219     int dx_x2 = 0, dy_x2 = 0;
00220     int di = 0;
00221 
00222     dx = x1 - x0;
00223     dy = y1 - y0;
00224 
00225     if (dx == 0) {
00226 
00227         /* vertical line */
00228         if (y1 < y0)
00229             SWAP(y0, y1);
00230         vline(x0, y0, y1, color);
00231         return;
00232     }
00233 
00234     if (dx > 0) {
00235         dx_sym = 1;
00236     }
00237     else {
00238         dx_sym = -1;
00239     }
00240 
00241     if (dy == 0) {
00242 
00243         /* horizontal line */
00244         if (x1 < x0)
00245             SWAP(x1, x0);
00246         hline(x0, x1, y0, color);
00247         return;
00248     }
00249 
00250     if (dy > 0) {
00251         dy_sym = 1;
00252     }
00253     else {
00254         dy_sym = -1;
00255     }
00256 
00257     dx = dx_sym * dx;
00258     dy = dy_sym * dy;
00259 
00260     dx_x2 = dx * 2;
00261     dy_x2 = dy * 2;
00262 
00263     if (dx >= dy) {
00264         di = dy_x2 - dx;
00265         while (x0 != x1) {
00266             pixel(x0, y0, color);
00267             x0 += dx_sym;
00268             if (di < 0) {
00269                 di += dy_x2;
00270             }
00271             else {
00272                 di += dy_x2 - dx_x2;
00273                 y0 += dy_sym;
00274             }
00275         }
00276 
00277         pixel(x0, y0, color);
00278     }
00279     else {
00280         di = dx_x2 - dy;
00281         while (y0 != y1) {
00282             pixel(x0, y0, color);
00283             y0 += dy_sym;
00284             if (di < 0) {
00285                 di += dx_x2;
00286             }
00287             else {
00288                 di += dx_x2 - dy_x2;
00289                 x0 += dx_sym;
00290             }
00291         }
00292 
00293         pixel(x0, y0, color);
00294     }
00295 
00296     if (auto_up)
00297         copy_to_lcd();
00298     return;
00299 }
00300 
00301 /**
00302  * @brief
00303  * @note
00304  * @param
00305  * @retval
00306  */
00307 void GraphicsDisplay::rect(int x0, int y0, int x1, int y1, unsigned short color)
00308 {
00309     bool    old_auto_up = auto_up;
00310     if (auto_up)
00311         auto_up = 0;
00312     if (x1 > x0)
00313         hline(x0, x1, y0, color);
00314     else
00315         hline(x1, x0, y0, color);
00316 
00317     if (y1 > y0)
00318         vline(x0, y0, y1, color);
00319     else
00320         vline(x0, y1, y0, color);
00321 
00322     if (x1 > x0)
00323         hline(x0, x1, y1, color);
00324     else
00325         hline(x1, x0, y1, color);
00326 
00327     if (y1 > y0)
00328         vline(x1, y0, y1, color);
00329     else
00330         vline(x1, y1, y0, color);
00331     if (old_auto_up) {
00332         auto_up = true;
00333         copy_to_lcd();
00334     }
00335 
00336     return;
00337 }
00338 
00339 /**
00340  * @brief
00341  * @note
00342  * @param
00343  * @retval
00344  */
00345 void GraphicsDisplay::fillrect(int x0, int y0, int x1, int y1, unsigned short color)
00346 {
00347     if (x0 > x1)
00348         SWAP(x0, x1);
00349     if (y0 > y1)
00350         SWAP(y0, y1);
00351 
00352     int             h = y1 - y0 + 1;
00353     int             w = x1 - x0 + 1;
00354     unsigned int    pixels = h * w;
00355     window(x0, y0, w, h);
00356 
00357     //   for (unsigned int p=0; p<pixels; p++) window_pushpixel(color);
00358     window_pushpixel(color, pixels);
00359     if (auto_up)
00360         copy_to_lcd();
00361     return;
00362 }
00363 
00364 /**
00365  * @brief
00366  * @note
00367  * @param
00368  * @retval
00369  */
00370 void GraphicsDisplay::locate(int x, int y)
00371 {
00372     char_x = x;
00373     char_y = y;
00374 }
00375 
00376 /**
00377  * @brief
00378  * @note
00379  * @param
00380  * @retval
00381  */
00382 int GraphicsDisplay::columns()
00383 {
00384     return oriented_width / fonthor;
00385 }
00386 
00387 /**
00388  * @brief
00389  * @note
00390  * @param
00391  * @retval
00392  */
00393 int GraphicsDisplay::rows()
00394 {
00395     return oriented_height / fontvert;
00396 }
00397 
00398 /**
00399  * @brief
00400  * @note
00401  * @param
00402  * @retval
00403  */
00404 void GraphicsDisplay::set_font(unsigned char* f, unsigned char firstascii, unsigned char lastascii, bool proportional)
00405 {
00406     font = f;
00407 
00408     // read font parameter from start of array
00409     //fontoffset = font[0];                    // bytes / char
00410     fonthor = font[1];              // get hor size of font
00411     fontvert = font[2];             // get vert size of font
00412 
00413     //fontbpl = font[3];                       // bytes per line
00414     fontbpl = (fontvert + 7) >> 3;  //bytes per line, rounded up to multiple of 8
00415     fontoffset = (fonthor * fontbpl) + 1;
00416     firstch = firstascii;           // first ascii code present in font array (usually 32)
00417     lastch = lastascii;             // last ascii code present in font array (usually 127)
00418     fontprop = proportional;
00419     set_font_zoom(1, 1);
00420 }
00421 
00422 /**
00423  * @brief
00424  * @note
00425  * @param
00426  * @retval
00427  */
00428 void GraphicsDisplay::set_font_zoom(unsigned char x_mul, unsigned char y_mul)
00429 {
00430     fontzoomhor = ((x_mul == 0) ? 1 : x_mul);
00431     fontzoomver = ((y_mul == 0) ? 1 : y_mul);
00432 }
00433 
00434 /**
00435  * @brief
00436  * @note
00437  * @param
00438  * @retval
00439  */
00440 int GraphicsDisplay::_putc(int value)
00441 {
00442     if (value == '\n') {
00443 
00444         // new line
00445         char_x = 0;
00446         char_y = char_y + fontvert * fontzoomver;
00447         if (char_y >= oriented_height - fontvert * fontzoomver) {
00448             char_y = 0;
00449         }
00450     }
00451     else {
00452         character(char_x, char_y, value);
00453         if (auto_up)
00454             copy_to_lcd();
00455     }
00456 
00457     return value;
00458 }
00459 
00460 /**
00461  * @brief
00462  * @note
00463  * @param
00464  * @retval
00465  */
00466 void GraphicsDisplay::character(int x, int y, int c)
00467 {
00468     char_x = x;
00469     char_y = y;
00470 
00471     int             j, i, b;
00472     unsigned char*  zeichen;
00473     unsigned char   z, w, v;
00474 
00475     /*   // read font parameter from start of array
00476     offset = font[0];                    // bytes / char
00477     hor = font[1];                       // get hor size of font
00478     vert = font[2];                      // get vert size of font
00479     bpl = font[3];                       // bytes per line
00480 */
00481 
00482     if (char_x + fonthor * fontzoomhor > oriented_width) {
00483         char_x = 0;
00484         char_y = char_y + fontvert * fontzoomver;
00485         if (char_y > oriented_height - fontvert * fontzoomver) {
00486             char_y = 0;
00487         }
00488     }
00489 
00490     window(char_x, char_y, fonthor * fontzoomhor, fontvert * fontzoomver);  // char box
00491     if ((c < firstch) || (c > lastch)) {
00492 
00493         // test char range - if not exist fill with blank
00494         for (i = 0; i < fonthor * fontvert * fontzoomver; i++) {
00495             window_pushpixel(_background, fontzoomhor);                     //(color, howmany)
00496         }
00497     }
00498     else {
00499         zeichen = &font[((c - firstch) * fontoffset) + 4];                  // start of char bitmap
00500         w = zeichen[0]; // width of actual char
00501 
00502         // construct the char into the buffer
00503         for (j = 0; j < fontvert; j++) {
00504 
00505             //  vert line
00506             for (v = 0; v < fontzoomver; v++) {
00507 
00508                 // repeat horiz line for vertical zooming
00509                 for (i = 0; i < fonthor; i++) {
00510 
00511                     //  horz line
00512                     z = zeichen[(fontbpl * i) + ((j & 0xF8) >> 3) + 1];
00513                     b = 1 << (j & 0x07);
00514                     if ((z & b) == 0x00) {
00515 
00516                         //   pixel(char_x+i,char_y+j,0);
00517                         window_pushpixel(_background, fontzoomhor); //(color, howmany)
00518                     }
00519                     else {
00520 
00521                         //    pixel(char_x+i,char_y+j,1);
00522                         window_pushpixel(_foreground, fontzoomhor);
00523                     }
00524                 }
00525             }                                   //for each zoomed vert
00526         }
00527     }
00528 
00529     if (fontprop) {
00530         if ((w + 1) < fonthor)
00531             char_x += (w * fontzoomhor) + 1;    // put at least 1 blank after variable-width characters, except characters that occupy whole fonthor space like "_"
00532         else
00533             char_x += fonthor * fontzoomhor;
00534     }
00535     else
00536         char_x += fonthor * fontzoomhor;        // fixed width
00537 }
00538 
00539 /**
00540  * @brief
00541  * @note
00542  * @param
00543  * @retval
00544  */
00545 void GraphicsDisplay::Bitmap_BW(Bitmap_s bm, int x, int y)
00546 {
00547     int     h, v, b;
00548 
00549     //   int cropX;
00550     char    d;
00551     if (x < 0)
00552         x = 0;
00553     if (y < 0)
00554         y = 0;
00555 
00556     int cropX = (x + bm.xSize) - oriented_width;
00557     if (cropX < 0)
00558         cropX = 0;
00559     window(x, y, bm.xSize - cropX, bm.ySize);
00560     for (v = 0; v < bm.ySize; v++) {
00561 
00562         // lines
00563         if ((v + y) >= oriented_height)
00564             break;  // no need to crop Y
00565         for (h = 0; h < bm.xSize; h++) {
00566 
00567             // pixel
00568             if ((h + x) >= oriented_width)
00569                 break;
00570             d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
00571             b = 0x80 >> (h & 0x07);
00572             if ((d & b) == 0) {
00573                 window_pushpixel(_background);
00574             }
00575             else {
00576                 window_pushpixel(_foreground);
00577             }
00578         }
00579     }
00580 
00581     if (auto_up)
00582         copy_to_lcd();
00583 }
00584 
00585 /**
00586  * @brief
00587  * @note
00588  * @param
00589  * @retval
00590  */
00591 void GraphicsDisplay::Bitmap(int x, int y, int w, int h, unsigned char* bitmap)
00592 {
00593     int                 j;
00594     unsigned char       padd;
00595     unsigned short*     bitmap_ptr = (unsigned short*)bitmap;
00596 
00597     padd = w % 2;                           // the lines are padded to multiple of 4 bytes in a bitmap
00598     if (x < 0)
00599         x = 0;
00600     else
00601     if (x >= oriented_width)
00602         return;
00603     if (y < 0)
00604         y = 0;
00605     else
00606     if (y >= oriented_height)
00607         return;
00608 
00609     int cropX = (x + w) - oriented_width;
00610     if (cropX < 0)
00611         cropX = 0;
00612 
00613     int cropY = (y + h) - oriented_height;
00614     if (cropY < 0)
00615         cropY = 0;
00616     window(x, y, w - cropX, h - cropY);
00617     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)
00618     for (j = 0; j < h - cropY; j++) {
00619 
00620         //Lines
00621         window_pushpixelbuf(bitmap_ptr, w - cropX);
00622         bitmap_ptr -= w + padd;
00623     }
00624 
00625     if (auto_up)
00626         copy_to_lcd();
00627 }
00628 
00629 // local filesystem is not implemented in kinetis board , but you can add a SD card
00630 
00631 // fixme this whole functions needs testing and speedup
00632 int GraphicsDisplay::BMP_16(int x, int y, const char* Name_BMP)
00633 {
00634 #define OffsetPixelWidth    18
00635 #define OffsetPixelHeigh    22
00636 #define OffsetFileSize      34
00637 #define OffsetPixData       10
00638 #define OffsetBPP           28
00639     char                filename[50];
00640     unsigned char       BMP_Header[54];
00641     unsigned short      BPP_t;
00642     unsigned int        PixelWidth, PixelHeigh, start_data;
00643     unsigned int        i, off;
00644     int                 padd, j;
00645     unsigned short*     line;
00646 
00647     // get the filename
00648 
00649     i = 0;
00650     while (*Name_BMP != '\0') {
00651         filename[i++] = *Name_BMP++;
00652     }
00653 
00654     filename[i] = 0;
00655 
00656     FILE*   Image = fopen((const char*) &filename[0], "rb");    // open the bmp file
00657 
00658     if (!Image) {
00659         return(0);                                      // error file not found !
00660     }
00661 
00662     fread(&BMP_Header[0], 1, 54, Image);                // get the BMP Header
00663     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {
00664 
00665         // check magic byte
00666         fclose(Image);
00667         return(-1);                                     // error no BMP file
00668     }
00669 
00670     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00671     if (BPP_t != 0x0010) {
00672         fclose(Image);
00673         return(-2);                                     // error no 16 bit BMP
00674     }
00675 
00676     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00677     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00678     if (PixelHeigh > oriented_height + y || PixelWidth > oriented_width + x) {
00679         fclose(Image);
00680         return(-3);                                     // to big
00681     }
00682 
00683     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00684 
00685     line = (unsigned short*)malloc(2 * PixelWidth);     // we need a buffer for a line
00686     if (line == NULL) {
00687         return(-4);                                     // error no memory
00688     }
00689 
00690     // the bmp lines are padded to multiple of 4 bytes
00691     padd = -1;
00692     do
00693     {
00694         padd++;
00695     } while ((PixelWidth * 2 + padd) % 4 != 0);
00696 
00697     window(x, y, PixelWidth, PixelHeigh);
00698 
00699     //    wr_cmd(0x2C);  // send pixel
00700     for (j = PixelHeigh - 1; j >= 0; j--) {
00701 
00702         //Lines bottom up
00703         off = j * (PixelWidth * 2 + padd) + start_data; // start of line
00704         fseek(Image, off, SEEK_SET);
00705         fread(line, 1, PixelWidth * 2, Image);          // read a line - slow
00706 
00707         /*      for (i = 0; i < PixelWidth; i++)
00708         {        // copy pixel data to TFT
00709      //       wr_16(line[i]);                  // one 16 bit pixel
00710             window_pushpixel(line[i]);
00711 
00712         } */
00713         window_pushpixelbuf(line, PixelWidth);
00714     }
00715 
00716     free(line);
00717     fclose(Image);
00718     if (auto_up)
00719         copy_to_lcd();
00720     return(1);
00721 }
00722 
00723 /**
00724  * @brief
00725  * @note
00726  * @param
00727  * @retval
00728  */
00729 void GraphicsDisplay::cls(void)
00730 {
00731     unsigned int    pixels = (oriented_width * oriented_height);
00732     WindowMax();
00733     for (unsigned int i = 0; i < pixels; i++) {
00734         window_pushpixel(_background);
00735     }
00736 }
00737 
00738 /**
00739  * @brief
00740  * @note
00741  * @param
00742  * @retval
00743  */
00744 void GraphicsDisplay::set_auto_up(bool up)
00745 {
00746     if (up)
00747         auto_up = true;
00748     else
00749         auto_up = false;
00750 }
00751 
00752 /**
00753  * @brief
00754  * @note
00755  * @param
00756  * @retval
00757  */
00758 bool GraphicsDisplay::get_auto_up(void)
00759 {
00760     return(auto_up);
00761 }