// algorithm from drawCircle rearranged with hlines drawn between points on the raidus void SmartMatrix::fillCircle(int16_t x0, int16_t y0, uint16_t radius, const rgb24& fillColor) { int a = radius, b = 0; int radiusError = 1 - a; if (radius == 0) return; // only draw one line per row, skipping the top and bottom bool hlineDrawn = true; while (a >= b) { // this pair sweeps from horizontal center down drawFastHLine((a - 1) + x0, (-a + 1) + x0, b + y0, fillColor); // this pair sweeps from horizontal center up drawFastHLine((a - 1) + x0, (-a + 1) + x0, -b + y0, fillColor); if (b > 1 && !hlineDrawn) { drawFastHLine((b - 1) + x0, (-b + 1) + x0, a + y0, fillColor); drawFastHLine((b - 1) + x0, (-b + 1) + x0, -a + y0, fillColor); hlineDrawn = true; } b++; if (radiusError < 0) { radiusError += 2 * b + 1; } else { a--; hlineDrawn = false; radiusError += 2 * (b - a + 1); } } }
// Draw a rectangle void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); }
// Rounded rectangles void FramebufferGFX::drawRoundRect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t r, uint16_t color) { // From Adafruit library (modified) int16_t w = x1 - x0; int16_t h = y1 - y0; int16_t x = x0; int16_t y = y0; if (x0 > x1) { x = x1; w = -w; } if (y0 > y1) { y = y1; h = -h; } // smarter version drawFastHLine(x+r , y , w-2*r, color); // Top drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom drawFastVLine(x , y+r , h-2*r, color); // Left drawFastVLine(x+w-1, y+r , h-2*r, color); // Right // draw four corners drawCircleHelper(x+r , y+r , r, 1, color); drawCircleHelper(x+w-r-1, y+r , r, 2, color); drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); drawCircleHelper(x+r , y+h-r-1, r, 8, color); }
// draw a rectangle void GOFi2cOLED::drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); }
void Arduboy::drawRect (int16_t x, int16_t y, int16_t w, int16_t h, uint8_t color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); }
// draw a rectangle void Adafruit_GFX::drawRect(int16 x, int16 y, int16 w, int16 h, uint32 color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); }
void SmartMatrix::drawRoundRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t radius, const rgb24& outlineColor) { if (x1 < x0) SWAPint(x1, x0); if (y1 < y0) SWAPint(y1, y0); // decrease large radius that would break shape if(radius > (x1-x0)/2) radius = (x1-x0)/2; if(radius > (y1-y0)/2) radius = (y1-y0)/2; int a = radius, b = 0; int radiusError = 1 - a; // draw straight part of outline drawFastHLine(x0 + radius, x1 - radius, y0, outlineColor); drawFastHLine(x0 + radius, x1 - radius, y1, outlineColor); drawFastVLine(x0, y0 + radius, y1 - radius, outlineColor); drawFastVLine(x1, y0 + radius, y1 - radius, outlineColor); // convert coordinates to point at center of rounded sections x0 += radius; x1 -= radius; y0 += radius; y1 -= radius; while (a >= b) { // this pair sweeps from far left towards right drawPixel(-a + x0, -b + y0, outlineColor); drawPixel(-a + x0, b + y1, outlineColor); // this pair sweeps from far right towards left drawPixel(a + x1, -b + y0, outlineColor); drawPixel(a + x1, b + y1, outlineColor); // this pair sweeps from very top towards bottom drawPixel(-b + x0, -a + y0, outlineColor); drawPixel(b + x1, -a + y0, outlineColor); // this pair sweeps from bottom up drawPixel(-b + x0, a + y1, outlineColor); drawPixel(b + x1, a + y1, outlineColor); b++; if (radiusError < 0) { radiusError += 2 * b + 1; } else { a--; radiusError += 2 * (b - a + 1); } } }
// draw a rounded rectangle! void GOFi2cOLED::drawRoundRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color) { // smarter version drawFastHLine(x+r , y , w-2*r, color); // Top drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom drawFastVLine( x , y+r , h-2*r, color); // Left drawFastVLine( x+w-1, y+r , h-2*r, color); // Right // draw four corners drawCircleHelper(x+r , y+r , r, 1, color); drawCircleHelper(x+w-r-1, y+r , r, 2, color); drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); drawCircleHelper(x+r , y+h-r-1, r, 8, color); }
// Draw a rounded rectangle void Adafruit_GFX_AS::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) { // smarter version drawFastHLine(x+r , y , w-2*r, color); // Top drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom drawFastVLine(x , y+r , h-2*r, color); // Left drawFastVLine(x+w-1, y+r , h-2*r, color); // Right // draw four corners drawCircleHelper(x+r , y+r , r, 1, color); drawCircleHelper(x+w-r-1, y+r , r, 2, color); drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); drawCircleHelper(x+r , y+h-r-1, r, 8, color); }
// Rectangles void FramebufferGFX::drawRect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { int16_t w = x1 - x0; int16_t h = y1 - y0; int16_t x = x0; int16_t y = y0; if (x0 > x1) { x = x1; w = -w; } if (y0 > y1) { y = y1; h = -h; } // (x, y) is lower corner drawFastHLine(x, y, w, color); // top drawFastHLine(x, y + h, w, color); // bottom drawFastVLine(x, y, h, color); // left drawFastVLine(x + w, y, h, color); // right }
//***************************************************************************** void testfastlines(unsigned int color1, unsigned int color2) { unsigned int x; unsigned int y; fillScreen(BLACK); for (y = 0; y < height() - 1; y += 8) { drawFastHLine(0, y, width() - 1, color1); } delay(100); for (x = 0; x < width() - 1; x += 8) { drawFastVLine(x, 0, height() - 1, color2); } delay(100); }
void SmartMatrix::fillRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, const rgb24& color) { int i; // Loop only works if y1 > y0 if (y0 > y1) { SWAPint(y0, y1); }; // Putting the x coordinates in order saves multiple swaps in drawFastHLine if (x0 > x1) { SWAPint(x0, x1); }; for (i = y0; i <= y1; i++) { drawFastHLine(x0, x1, i, color); } }
void FramebufferGFX::fillRect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { int16_t w = x1 - x0; int16_t h = y1 - y0; int16_t x = x0; int16_t y = y0; if (x0 > x1) { x = x1; w = -w; } if (y0 > y1) { y = y1; h = -h; } // (x, y) is lower corner. draw fill lines from top to bottom. for (int16_t i=0; i<h; i++) { drawFastHLine(x, y + i, w, color); } }
/*************************************************************************************** ** Function name: drawUnicode ** Descriptions: draw a unicode ***************************************************************************************/ ICACHE_FLASH_ATTR int Adafruit_GFX_AS::drawUnicode(uint16_t uniCode, uint16_t x, uint16_t y, uint8_t size) { if (size) uniCode -= 32; uint16_t width = 0; uint16_t height = 0; const uint8_t *flash_address = 0; int8_t gap = 0; #ifdef LOAD_FONT2 if (size == 2) { flash_address = chrtbl_f16[uniCode]; width = *(widtbl_f16+uniCode); height = chr_hgt_f16; gap = 1; } #endif // if (size == 3) { // flash_address = pgm_read_word(&chrtbl_f24[uniCode]); // width = pgm_read_byte(widtbl_f24+uniCode); // height = chr_hgt_f24; // gap = 0; // } #ifdef LOAD_FONT4 if (size == 4) { flash_address = chrtbl_f32[uniCode]; width = *(widtbl_f32+uniCode); height = chr_hgt_f32; gap = -3; } #endif // if (size == 5) { // flash_address = pgm_read_word(&chrtbl_f48[uniCode]); // width = pgm_read_byte(widtbl_f48+uniCode); // height = chr_hgt_f48; // gap = -3; // } #ifdef LOAD_FONT6 if (size == 6) { flash_address = chrtbl_f64[uniCode]; width = *(widtbl_f64+uniCode); height = chr_hgt_f64; gap = -3; } #endif #ifdef LOAD_FONT7 if (size == 7) { flash_address = chrtbl_f7s[uniCode]; width = *(widtbl_f7s+uniCode); height = chr_hgt_f7s; gap = 2; } #endif uint16_t w = (width+ 7) / 8; uint16_t pX = 0; uint16_t pY = y; uint16_t color = 0; uint8_t line = 0; for(int i=0; i<height; i++) { if (textcolor != textbgcolor) drawFastHLine(x, pY, width+gap, textbgcolor); for (int k = 0;k < w; k++) { line = *(flash_address + w*i + k); if(line) { pX = x + k*8; if(line & 0x80) drawPixel(pX, pY, textcolor); if(line & 0x40) drawPixel(pX+1, pY, textcolor); if(line & 0x20) drawPixel(pX+2, pY, textcolor); if(line & 0x10) drawPixel(pX+3, pY, textcolor); if(line & 0x8) drawPixel(pX+4, pY, textcolor); if(line & 0x4) drawPixel(pX+5, pY, textcolor); if(line & 0x2) drawPixel(pX+6, pY, textcolor); if(line & 0x1) drawPixel(pX+7, pY, textcolor); } } pY++; } return width+gap; // x + }
void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color){ if (y0 == y1) { if (x1 > x0) { drawFastHLine(x0, y0, x1 - x0 + 1, color); } else if (x1 < x0) { drawFastHLine(x1, y0, x0 - x1 + 1, color); } else { drawPixel(x0, y0, color); } return; } else if (x0 == x1) { if (y1 > y0) { drawFastVLine(x0, y0, y1 - y0 + 1, color); } else { drawFastVLine(x0, y1, y0 - y1 + 1, color); } return; } bool steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int16_t dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int16_t err = dx / 2; int16_t ystep; if (y0 < y1) { ystep = 1; } else { ystep = -1; } SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); int16_t xbegin = x0; if (steep) { for (; x0<=x1; x0++) { err -= dy; if (err < 0) { int16_t len = x0 - xbegin; if (len) { VLine(y0, xbegin, len + 1, color); } else { Pixel(y0, x0, color); } xbegin = x0 + 1; y0 += ystep; err += dx; } } if (x0 > xbegin + 1) { VLine(y0, xbegin, x0 - xbegin, color); } } else { for (; x0<=x1; x0++) { err -= dy; if (err < 0) { int16_t len = x0 - xbegin; if (len) { HLine(xbegin, y0, len + 1, color); } else { Pixel(x0, y0, color); } xbegin = x0 + 1; y0 += ystep; err += dx; } } if (x0 > xbegin + 1) { HLine(xbegin, y0, x0 - xbegin, color); } } writecommand_last(CMD_NOP); SPI.endTransaction(); }
void SmartMatrix::drawRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, const rgb24& color) { drawFastHLine(x0, x1, y0, color); drawFastHLine(x0, x1, y1, color); drawFastVLine(x0, y0, y1, color); drawFastVLine(x1, y0, y1, color); }
// Code from http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html void SmartMatrix::fillFlatSideTriangleInt(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, const rgb24& color) { int16_t t1x, t2x, t1y, t2y; bool changed1 = false; bool changed2 = false; int8_t signx1, signx2, signy1, signy2, dx1, dy1, dx2, dy2; int i; int8_t e1, e2; t1x = t2x = x1; t1y = t2y = y1; // Starting points dx1 = abs(x2 - x1); dy1 = abs(y2 - y1); dx2 = abs(x3 - x1); dy2 = abs(y3 - y1); if (x2 - x1 < 0) { signx1 = -1; } else signx1 = 1; if (x3 - x1 < 0) { signx2 = -1; } else signx2 = 1; if (y2 - y1 < 0) { signy1 = -1; } else signy1 = 1; if (y3 - y1 < 0) { signy2 = -1; } else signy2 = 1; if (dy1 > dx1) { // swap values SWAPint(dx1, dy1); changed1 = true; } if (dy2 > dx2) { // swap values SWAPint(dy2, dx2); changed2 = true; } e1 = 2 * dy1 - dx1; e2 = 2 * dy2 - dx2; for (i = 0; i <= dx1; i++) { drawFastHLine(t1x, t2x, t1y, color); while (dx1 > 0 && e1 >= 0) { if (changed1) t1x += signx1; else t1y += signy1; e1 = e1 - 2 * dx1; } if (changed1) t1y += signy1; else t1x += signx1; e1 = e1 + 2 * dy1; /* here we rendered the next point on line 1 so follow now line 2 * until we are on the same y-value as line 1. */ while (t2y != t1y) { while (dx2 > 0 && e2 >= 0) { if (changed2) t2x += signx2; else t2y += signy2; e2 = e2 - 2 * dx2; } if (changed2) t2y += signy2; else t2x += signx2; e2 = e2 + 2 * dy2; } } }
void screenkeys::drawRect(uint8_t x,uint8_t y,uint8_t w,uint8_t h,bool color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); }
void SmartMatrix::fillRoundRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t radius, const rgb24& outlineColor, const rgb24& fillColor) { if (x1 < x0) SWAPint(x1, x0); if (y1 < y0) SWAPint(y1, y0); // decrease large radius that would break shape if(radius > (x1-x0)/2) radius = (x1-x0)/2; if(radius > (y1-y0)/2) radius = (y1-y0)/2; int a = radius, b = 0; int radiusError = 1 - a; if (radius == 0) { fillRectangle(x0, y0, x1, y1, outlineColor, fillColor); } // draw straight part of outline drawFastHLine(x0 + radius, x1 - radius, y0, outlineColor); drawFastHLine(x0 + radius, x1 - radius, y1, outlineColor); drawFastVLine(x0, y0 + radius, y1 - radius, outlineColor); drawFastVLine(x1, y0 + radius, y1 - radius, outlineColor); // convert coordinates to point at center of rounded sections x0 += radius; x1 -= radius; y0 += radius; y1 -= radius; // only draw one line per row/column, skipping the sides bool hlineDrawn = true; bool vlineDrawn = true; while (a >= b) { // this pair sweeps from far left towards right drawPixel(-a + x0, -b + y0, outlineColor); drawPixel(-a + x0, b + y1, outlineColor); // this pair sweeps from far right towards left drawPixel(a + x1, -b + y0, outlineColor); drawPixel(a + x1, b + y1, outlineColor); if (!vlineDrawn) { drawFastVLine(-a + x0, (-b + 1) + y0, (b - 1) + y1, fillColor); drawFastVLine(a + x1, (-b + 1) + y0, (b - 1) + y1, fillColor); vlineDrawn = true; } // this pair sweeps from very top towards bottom drawPixel(-b + x0, -a + y0, outlineColor); drawPixel(b + x1, -a + y0, outlineColor); // this pair sweeps from bottom up drawPixel(-b + x0, a + y1, outlineColor); drawPixel(b + x1, a + y1, outlineColor); if (!hlineDrawn) { drawFastHLine((-b + 1) + x0, (b - 1) + x1, -a + y0, fillColor); drawFastHLine((-b + 1) + x0, (b - 1) + x1, a + y1, fillColor); hlineDrawn = true; } b++; if (radiusError < 0) { radiusError += 2 * b + 1; } else { a--; hlineDrawn = false; vlineDrawn = false; radiusError += 2 * (b - a + 1); } } // draw rectangle in center fillRectangle(x0 - a, y0 - a, x1 + a, y1 + a, fillColor); }
void FramebufferGFX::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { // From Adafruit library int16_t a, b, y, last; // Sort coordinates by Y order (y2 >= y1 >= y0) if (y0 > y1) { swap(y0, y1); swap(x0, x1); } if (y1 > y2) { swap(y2, y1); swap(x2, x1); } if (y0 > y1) { swap(y0, y1); swap(x0, x1); } if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing a = b = x0; if(x1 < a) a = x1; else if(x1 > b) b = x1; if(x2 < a) a = x2; else if(x2 > b) b = x2; drawFastHLine(a, y0, b-a+1, color); return; } int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1, dy12 = y2 - y1, sa = 0, sb = 0; // For upper part of triangle, find scanline crossings for segments // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 // is included here (and second loop will be skipped, avoiding a /0 // error there), otherwise scanline y1 is skipped here and handled // in the second loop...which also avoids a /0 error here if y0=y1 // (flat-topped triangle). if(y1 == y2) last = y1; // Include y1 scanline else last = y1-1; // Skip it for(y=y0; y<=last; y++) { a = x0 + sa / dy01; b = x0 + sb / dy02; sa += dx01; sb += dx02; /* longhand: a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); */ if(a > b) swap(a,b); drawFastHLine(a, y, b-a+1, color); } // For lower part of triangle, find scanline crossings for segments // 0-2 and 1-2. This loop is skipped if y1=y2. sa = dx12 * (y - y1); sb = dx02 * (y - y0); for(; y<=y2; y++) { a = x1 + sa / dy12; b = x0 + sb / dy02; sa += dx12; sb += dx02; /* longhand: a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); */ if(a > b) swap(a,b); drawFastHLine(a, y, b-a+1, color); } }