Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 17:15:58 by
1.7.2