diff --git a/examples/Standard/DrawLineThickness/DrawLineThickness.ino b/examples/Standard/DrawLineThickness/DrawLineThickness.ino new file mode 100644 index 00000000..fb02f661 --- /dev/null +++ b/examples/Standard/DrawLineThickness/DrawLineThickness.ino @@ -0,0 +1,290 @@ +#define LGFX_AUTODETECT +#include + +LGFX tft; + +/*\ + * + * ⚠️ Some of those features use a lot of maths, don't expect FTL performances :-) + * + * Features: + * + * - Antialiased thick lines, filled with plain color or gradient + * - Antialiased circles, filled with plain color or gradient + * - Rectangular fill with linear or radial gradient + * + * LGFX Methods: + * + * NOTE: COLOR can be any of uint8_t, uint16_t, uint32_t, RGBColor, rgb888_t, rgb565_t, rgb888_t, etc + * + * - Draw thick+smooth lines: + * void drawWideLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, float thick, COLOR color) + * + * - Draw thick+smooth lines (gradient fill): + * void drawWideLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, float thick, const colors_t gradient) + * + * - Draw wedge line: + * void drawWedgeLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, float thick0, float thick1, COLOR color) + * + * - Draw wedge line (gradient fill): + * void drawWedgeLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, float thick0, float thick1, const colors_t gradient) + * + * - Fill smooth circle with single color (redundant with fillSmoothCircle(), kept for benchmark): + * void drawSpot(int32_t x, int32_t y, float radius, COLOR fg_color) + * + * - Fill smooth circle, like fillSmoothCircle() but with gradient fill: + * void drawGradientSpot(int32_t x, int32_t y, float radius, const colors_t gradient) + * + * - Draw antialiased line: + * void drawSmoothLine( LovyanGFX* gfx, int32_t x0, int32_t y0, int32_t x1, int32_t y1, COLOR color ) + * + * - Draw gradient line (not smoothed, used for filling): + * void drawGradientLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const colors_t gradient ) + * void drawGradientHLine(int32_t x, int32_t y, uint32_t w, const colors_t gradient ) + * void drawGradientVLine(int32_t x, int32_t y, uint32_t h, const colors_t gradient ) + * + * - Fill rect with radial/linear gradient (fill_style_t can be any of RADIAL, HLINEAR or VLINEAR): + * void fillGradientRect(int32_t x, int32_t y, uint32_t w, uint32_t h, COLOR start, COLOR end, fill_style_t style=RADIAL ) + * void fillGradientRect(int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t gradient, fill_style_t style=RADIAL ) + * + * - Create a gradient item from a sized array of colors or from a pointer to an array of colors: + * colors_t createGradient( rgb888_t[] colors ) + * colors_t createGradient( rgb888_t* colors, uint32_t count ) + * + * - Example: + * lgfx::rgb888_t colors[] = { {0x00,0xff,0x00}, {0xff,0xff,0x00}, {0xff,0x80,0x00}, {0xff,0x00,0x00} }; + * auto gradient = tft.createGradient( colors ); // create a gradient item + * tft.fillGradientRect( 10, 10, 200, 200, gradient, HLINEAR ); + * + * +\*/ + +// a couple of colors array for the gradient examples +static constexpr const lgfx::rgb888_t heatMap[] = { {0, 0xff, 0}, {0xff, 0xff, 0}, {0xff, 0x80, 0}, {0xff, 0, 0}, {0x80, 0, 0} }; // green => yellow => orange => red => dark red +static constexpr const lgfx::rgb888_t greyscale[] = { {0,0,0}, {0xff,0xff,0xff} }; // black => white +// a couple of gradient examples based on colors arrays +static constexpr const lgfx::colors_t heatMapGradient = { heatMap, sizeof(heatMap)/sizeof(lgfx::rgb888_t) }; +static constexpr const lgfx::colors_t greyScaleGradient = { greyscale, sizeof(greyscale)/sizeof(lgfx::rgb888_t) }; +// for degrees to radians conversions +static constexpr double deg2rad = M_PI/180.0; + + +// some constant values based on display width/height +struct constValues_t +{ + const uint32_t middleX = (tft.width()/2)-1; + const uint32_t middleY = (tft.height()/2)-1; + const uint32_t r1 = std::min(tft.width(),tft.height()) *.39; + const uint32_t r2 = r1/5; + const uint32_t r3 = std::min(tft.width(),tft.height()) *.45; + const uint32_t r4 = std::min(tft.width(),tft.height()) *.37; + const uint32_t thick1 = std::min(tft.width(),tft.height())/35; + const uint32_t thick2 = std::min(tft.width(),tft.height())/75; + const uint32_t thick3 = std::min(tft.width(),tft.height())/150; + const uint32_t bw0 = std::max(tft.width(),tft.height())/4; + const uint32_t bw1 = std::max(tft.width(),tft.height())/8; + const uint32_t max_thickness = std::min(tft.width(),tft.height())/25; + const lgfx::rgb888_t colors888[4] = { {0x00,0xff,0x00}, {0xff,0xff,0x00}, {0xff,0x80,0x00}, {0xff,0x00,0x00} }; + const lgfx::colors_t gradient888 = tft.createGradient( colors888 ); +}; + + +// some random values based on display width/height +struct randomValues_t +{ + constValues_t constValues; + const uint32_t x0 = random()%tft.width(); + const uint32_t y0 = random()%tft.height(); + const uint32_t x1 = random()%tft.width(); + const uint32_t y1 = random()%tft.height(); + const uint32_t thickness0 = (random()%constValues.max_thickness)+2; + const uint32_t thickness1 = (random()%constValues.max_thickness)+2; + const RGBColor colorstart = RGBColor( uint8_t(rand() % 0xff), uint8_t(rand() % 0xff), uint8_t(rand() % 0xff) ); + const RGBColor colorend = RGBColor( uint8_t(rand() % 0xff), uint8_t(rand() % 0xff), uint8_t(rand() % 0xff) ); + const lgfx::rgb888_t color24start = rand()%0x1000000u; + const lgfx::rgb888_t color24end = rand()%0x1000000u; + const lgfx::rgb565_t color16start = rand()%0x10000; + const lgfx::rgb565_t color16end = rand()%0x10000; + const lgfx::rgb332_t color8start = rand()%256; + const lgfx::rgb332_t color8end = rand()%256; + const lgfx::rgb888_t colors888[2] = { color24start, color24end }; + const lgfx::colors_t gradient888 = tft.createGradient( colors888 ); +}; + + + +void drawGrid() +{ + randomValues_t v; + auto cv = v.constValues; + + float theta = ( M_PI / 180.0f ) * 22.5; // angle + float sin0 = sinf(theta); + float cos0 = cosf(theta); + float sin1 = sinf(M_PI-theta); + float cos1 = cosf(M_PI-theta); + + for( int32_t y=-tft.height()*2; y=0 && last_y>=0 && (i/15)%2==1 ) { + lgfx::rgb888_t colorsRGB[] = { last_color, color }; + auto gradientRGB = tft.createGradient( colorsRGB ); + tft.drawWedgeLine( last_x, last_y, x2, y2, cv.thick1, cv.thick3, gradientRGB ); + } + last_color = color; + last_x = x2; + last_y = y2; + } +} + + +void setup() +{ + tft.init(); + tft.fillScreen(TFT_WHITE); +} + +void loop() +{ + static bool toggler = true; + toggler = !toggler; + if( toggler ) { + runRandomLinesDemo(); + vTaskDelay(1000); + } else { + runGradientDemo(); + vTaskDelay(5000); + } +} + diff --git a/src/lgfx/v1/LGFXBase.cpp b/src/lgfx/v1/LGFXBase.cpp index a672cd9a..0624258e 100644 --- a/src/lgfx/v1/LGFXBase.cpp +++ b/src/lgfx/v1/LGFXBase.cpp @@ -825,6 +825,71 @@ namespace lgfx endWrite(); } + + constexpr float LoAlphaTheshold = 1.0f / 32.0f; + constexpr float HiAlphaTheshold = 1.0f - LoAlphaTheshold; + + +//---------------------------------------------------------------------------- + + // helper function for radial gradients + // calculates distance between two sets of coordinates + float pixelDistance( double x0, double y0, double x1, double y1 ) + { + return sqrtf((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) );; + } + + // Helper function for draw_gradient_wedgeline, inspired by TFT_eSPI + // Returns distance of px,py to closest part of a to b wedge + float wedgeLineDistance(float xpax, float ypay, float bax, float bay, float dr=0.0f) + { + float d = (xpax * bax + ypay * bay) / (bax * bax + bay * bay); + float h = d<0.0f ? 0.0f : d>1.0f ? 1.0f : d; // constrain( d, 0.0f, 1.0f ); + float dx = xpax - bax * h, dy = ypay - bay * h; + return sqrtf(dx * dx + dy * dy) + h * dr; + } + + // Helper function for draw_gradient_wedgeline() + // Constrains coordinates top-left{xlo,ylo}:bottom-right{xhi,yhi} to gfx writable area + bool LGFXBase::clampArea(int32_t *xlo, int32_t *ylo, int32_t *xhi, int32_t *yhi) + { + if ((*xlo >= width()) || (*ylo >= height())) return false; // lowest coords are outside (higher) of viewport + if ((*xhi < 0) || (*yhi < 0)) return false; // highest coords are outside (lower) of viewport + // Adjust to lowest bounds + if (*xlo < 0) *xlo = 0; + if (*ylo < 0) *ylo = 0; + // Adjust to highest bounds + if (*xhi > width()) *xhi = width() - 1; + if (*yhi > height()) *yhi = height() - 1; + return true; // Coords are adjusted and area is fully writable + } + + rgb888_t LGFXBase::map_gradient( double value, double start, double end, const rgb888_t *colors, uint32_t colors_count ) + { + if(!colors) return rgb888_t(0,0,0); + if(colors_count<=1) return colors[0]; // there's no point mapping to a single value, also avoid divide by zero + float indexFloat = float(value-start) / float(end-start) * float(colors_count-1); + int32_t paletteIndex = int32_t(indexFloat/1); + float distance = indexFloat - float(paletteIndex); + const float min_precision = 0.00000011920928955078125; // std::numeric_limits::epsilon() + if( distance < min_precision ) { + return colors[paletteIndex]; + } else { + rgb888_t color0 = colors[paletteIndex]; + rgb888_t color1 = colors[paletteIndex+1]; + uint8_t r1 = color0.R8(), g1 = color0.G8(), b1 = color0.B8(); + uint8_t r2 = color1.R8(), g2 = color1.G8(), b2 = color1.B8(); + return rgb888_t( r1 + distance*float(r2-r1), g1 + distance*float(g2-g1), b1 + distance*float(b2-b1) ); + } + } + + rgb888_t LGFXBase::map_gradient( double value, double start, double end, const colors_t gradient ) + { + if(!gradient.colors) return rgb888_t(0,0,0); + if(gradient.count<=1) return gradient.colors[0]; // there's no point mapping to a single value, also avoid divide by zero + return map_gradient( value, start, end, gradient.colors, gradient.count ); + } + void LGFXBase::draw_gradient_line( int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colorstart, uint32_t colorend ) { if ( colorstart == colorend || (x0 == x1 && y0 == y1)) { @@ -874,8 +939,216 @@ namespace lgfx endWrite(); } - constexpr float LoAlphaTheshold = 1.0f / 32.0f; - constexpr float HiAlphaTheshold = 1.0f - LoAlphaTheshold; + void LGFXBase::draw_gradient_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const colors_t gradient ) + { + if(!gradient.colors || gradient.count==0) return; + if ( (x0 == x1 && y0 == y1) || gradient.count == 1 ) { + setColor(color888(gradient.colors[0].r, gradient.colors[0].g, gradient.colors[0].b)); + drawLine( x0, y0, x1, y1 ); + return; + } + + bool steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { // swap axis + std::swap(x0, y0); + std::swap(x1, y1); + } + + bool swapped = false; + if (x0 > x1) { // swap points + std::swap(x0, x1); + std::swap(y0, y1); + swapped = true; + } + + int32_t dx = x1 - x0; + int32_t err = dx >> 1; + int32_t dy = abs(y1 - y0); + int32_t ystep = (y0 < y1) ? 1 : -1; + + startWrite(); + for (int32_t x = x0; x <= x1; x++) { + auto color = map_gradient( x, swapped?x1:x0, swapped?x0:x1, gradient ); + setColor(color888(color.r, color.g, color.b)); + writePixel( steep?y0:x, steep?x:y0 ); + err -= dy; + if (err < 0) { + err += dx; + y0 += ystep; + } + } + endWrite(); + } + + void LGFXBase::draw_gradient_wedgeline(float ax, float ay, float bx, float by, float ar, float br, const colors_t gradient ) + { + const bool is_circle = (ax==bx && ay==by /*&& ar==br*/ ); + if( !gradient.colors || gradient.count==0 ) return; // line needs at least one color + if ( (ar < 0.0) || (br < 0.0) ) return; // don't negociate with infinity + if ( (fabsf(ax - bx) < 0.01f) && (fabsf(ay - by) < 0.01f) ) bx += 0.01f; // Avoid divide by zero + // convert first gradient color to RGB + rgb888_t fg_color = gradient.colors[0]; + // Find line bounding box + int32_t x0 = (int32_t)floorf(fminf(ax-ar, bx-br)); + int32_t x1 = (int32_t) ceilf(fmaxf(ax+ar, bx+br)); + int32_t y0 = (int32_t)floorf(fminf(ay-ar, by-br)); + int32_t y1 = (int32_t) ceilf(fmaxf(ay+ar, by+br)); + // clamp coords to drawable area + if (!clampArea(&x0, &y0, &x1, &y1)) { + return; + } + + constexpr float PixelAlphaGain = 255.0f; + + setClipRect( x0, y0, x1, y1 ); + startWrite(); + + // Establish x start and y start + int32_t ys = ay; + if ((ax-ar)>(bx-br)) ys = by; + + float rdt = ar - br; // Radius delta + float alpha = 1.0f; // base alpha + ar += 0.5; // center pixel + // line distance including rounded edges + float linedist = is_circle? (ar + br)*.5f : pixelDistance(ax, ay, bx, by) + ar + br; + float xpax, ypay, bax = bx - ax, bay = by - ay; + + int32_t xs = x0; // Set x start to left side of box + // 1st pass: Scan bounding box from ys down, calculate pixel intensity from distance to line + for (int32_t yp = ys; yp <= y1; yp++) { + bool endX = false; // Flag to skip pixels + ypay = yp - ay; + for (int32_t xp = xs; xp <= x1; xp++) { + if (endX) if (alpha <= LoAlphaTheshold) break; // Skip right side + xpax = xp - ax; + alpha = ar - wedgeLineDistance(xpax, ypay, bax, bay, rdt); + if (alpha <= LoAlphaTheshold ) continue; + // handle gradient + if( gradient.count>1 ) fg_color = map_gradient( pixelDistance(ax, ay, xp, yp), 0.0f, linedist, gradient ); + // Track edge to minimise calculations + if (!endX) { endX = true; xs = xp; } + if (alpha > HiAlphaTheshold) { + setColor(color888(fg_color.r, fg_color.g, fg_color.b)); + drawPixel(xp, yp); + continue; + } + fillRectAlpha(xp, yp, 1, 1, (uint8_t)(alpha * PixelAlphaGain), fg_color); + } + } + + xs = x0; // Reset x start to left side of box + // 2nd pass: Scan bounding box from ys-1 up, calculate pixel intensity from distance to line + for (int32_t yp = ys-1; yp >= y0; yp--) { + bool endX = false; // Flag to skip pixels + ypay = yp - ay; + for (int32_t xp = xs; xp <= x1; xp++) { + if (endX) if (alpha <= LoAlphaTheshold) break; // Skip right side of drawn line + xpax = xp - ax; + alpha = ar - wedgeLineDistance(xpax, ypay, bax, bay, rdt); + if (alpha <= LoAlphaTheshold ) continue; + // handle gradient + if( gradient.count>1 ) fg_color = map_gradient( pixelDistance(ax, ay, xp, yp), 0.0f, linedist, gradient ); + // Track line boundary + if (!endX) { endX = true; xs = xp; } + if (alpha > HiAlphaTheshold) { + setColor(color888(fg_color.r, fg_color.g, fg_color.b)); + drawPixel(xp, yp); + continue; + } + fillRectAlpha(xp, yp, 1, 1, (uint8_t)(alpha * PixelAlphaGain), fg_color); + } + } + + endWrite(); + clearClipRect(); + } + + void LGFXBase::draw_wedgeline(float ax, float ay, float bx, float by, float ar, float br, const uint32_t fg_color) + { + const rgb888_t color[1] = { fg_color }; // create a colors array with single color + auto gradient = createGradient( color ); // create single color gradient + draw_gradient_wedgeline(ax, ay, bx, by, ar, br, gradient ); // dispatch + } + + void LGFXBase::fill_rect_radial_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t gradient) + { + if( w<=1 || h<=1 || !gradient.colors || gradient.count==0 ) return; + if( gradient.count == 1 ) { + setColor(color888(gradient.colors[0].r, gradient.colors[0].g, gradient.colors[0].b)); + fillRect(x, y, w, h); + return; + } + float major_side = std::max(w,h); + float midx = (w-1)/2.0f; + float midy = (h-1)/2.0f; + float vratio = h/major_side; + float hratio = w/major_side; + float fmidx = midx*vratio; + float fmidy = midy*hratio; + float hyp0 = pixelDistance( midx, midy, 0, 0 ); + + rgb888_t scanline[w]; + + startWrite(); + for( int _y=0;_y + const colors_t createGradient( const rgb888_t(&colors)[N] ) { const colors_t ret = { colors, N }; return ret; } + const colors_t createGradient( const rgb888_t* colors, const uint32_t count ) { const colors_t ret = { colors, count }; return ret; } + template + auto mapGradient( double val, double min, double max, const colors_t gr ) { rgb888_t c=map_gradient(val, min, max, gr); return T(c.r, c.g, c.b); } + template + auto mapGradient( double val, double min, double max, const rgb888_t *colors, uint32_t count ) { rgb888_t c=map_gradient(val, min, max, colors, count); return T(c.r, c.g, c.b); } + + LGFX_INLINE_T void drawSmoothLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, const T& color ) { drawWideLine( x0, y0, x1, y1, 0.5f, color); } + void drawGradientLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, const colors_t colors ) { draw_gradient_line(x0, y0, x1, y1, colors); } + LGFX_INLINE_T void drawWideLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, float r, const T& color) { draw_wedgeline(x0, y0, x1, y1, r, r, convert_to_rgb888(color)); } + void drawWideLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, float r, const colors_t colors ) { draw_gradient_wedgeline(x0, y0, x1, y1, r, r, colors); } + LGFX_INLINE_T void drawWedgeLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, float r0, float r1, const T& color ) { draw_wedgeline(x0, y0, x1, y1, r0, r1, convert_to_rgb888(color)); } + void drawWedgeLine ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, float r0, float r1, const colors_t colors ) { draw_gradient_wedgeline(x0, y0, x1, y1, r0, r1, colors); } + LGFX_INLINE_T void drawSpot ( int32_t x, int32_t y, float r, const T& color ) { draw_wedgeline(x, y, x, y, r, r, convert_to_rgb888(color)); } + void drawGradientSpot ( int32_t x, int32_t y, float r, const colors_t gr ) { draw_gradient_wedgeline(x, y, x, y, r, r, gr); } + void drawGradientHLine( int32_t x, int32_t y, uint32_t w, const colors_t colors ) { draw_gradient_line(x, y, x+w, y, colors); } + void drawGradientVLine( int32_t x, int32_t y, uint32_t h, const colors_t colors ) { draw_gradient_line(x, y, x, y+h, colors); } + void fillGradientRect ( int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t colors, fill_style_t style=RADIAL) { fill_rect_gradient(x, y, w, h, colors, style); } + LGFX_INLINE_T void fillGradientRect ( int32_t x, int32_t y, uint32_t w, uint32_t h, const T& start, const T& end, fill_style_t style=RADIAL) { fill_rect_gradient(x, y, w, h, convert_to_rgb888(start), convert_to_rgb888(end), style); } + +//---------------------------------------------------------------------------- + + LGFX_INLINE_T void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, const T& color) { setColor(color); fillSmoothRoundRect(x, y, w, h, r); } void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r); @@ -944,7 +971,7 @@ namespace lgfx int32_t _sx = 0, _sy = 0, _sw = 0, _sh = 0; // for scroll zone int32_t _clip_l = 0, _clip_r = -1, _clip_t = 0, _clip_b = -1; // clip rect - uint32_t _base_rgb888 = 0; // gap fill colour for clear and scroll zone + uint32_t _base_rgb888 = 0; // gap fill colour for clear and scroll zone raw_color_t _color = 0xFFFFFFU; color_conv_t _write_conv; @@ -1261,7 +1288,28 @@ namespace lgfx static void make_rotation_matrix(float* result, float dst_x, float dst_y, float src_x, float src_y, float angle, float zoom_x, float zoom_y); void read_rect(int32_t x, int32_t y, int32_t w, int32_t h, void* dst, pixelcopy_t* param); + +//---------------------------------------------------------------------------- + + bool clampArea(int32_t *xlo, int32_t *ylo, int32_t *xhi, int32_t *yhi); + + rgb888_t map_gradient( double value, double start, double end, const rgb888_t *colors, uint32_t colors_count ); + rgb888_t map_gradient( double value, double start, double end, const colors_t gradient ); + void draw_gradient_line( int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colorstart, uint32_t colorend ); + void draw_gradient_line( int32_t x0, int32_t y0, int32_t x1, int32_t y1, const colors_t gradient ); + + void draw_wedgeline (float x0, float y0, float x1, float y1, float r0, float r1, const uint32_t fg_color); + void draw_gradient_wedgeline(float x0, float y0, float x1, float y1, float r0, float r1, const colors_t gradient ); + + void fill_rect_radial_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t gradient); + void fill_rect_radial_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint32_t colorstart, const uint32_t colorend ); + void fill_rect_linear_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t gradient, fill_style_t style=VLINEAR ); + void fill_rect_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const colors_t gradient, fill_style_t style=RADIAL ); + void fill_rect_gradient(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint32_t colorstart, const uint32_t colorend, fill_style_t style=RADIAL ); + +//---------------------------------------------------------------------------- + void fill_arc_helper(int32_t cx, int32_t cy, int32_t oradius_x, int32_t iradius_x, int32_t oradius_y, int32_t iradius_y, float start, float end); void draw_bezier_helper(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2); void draw_bitmap(int32_t x, int32_t y, const uint8_t *bitmap, int32_t w, int32_t h, uint32_t fg_rawcolor, uint32_t bg_rawcolor = ~0u); diff --git a/src/lgfx/v1/misc/colortype.hpp b/src/lgfx/v1/misc/colortype.hpp index c3d7786f..17e72b1c 100644 --- a/src/lgfx/v1/misc/colortype.hpp +++ b/src/lgfx/v1/misc/colortype.hpp @@ -936,10 +936,18 @@ namespace lgfx uint_fast16_t _b8a; }; + + struct colors_t + { + const rgb888_t *colors; + const uint32_t count; + }; + + //---------------------------------------------------------------------------- #undef LGFX_INLINE } } -using RGBColor = lgfx::bgr888_t; \ No newline at end of file +using RGBColor = lgfx::bgr888_t; diff --git a/src/lgfx/v1/misc/enum.hpp b/src/lgfx/v1/misc/enum.hpp index f02bf24b..64677ef6 100644 --- a/src/lgfx/v1/misc/enum.hpp +++ b/src/lgfx/v1/misc/enum.hpp @@ -112,6 +112,22 @@ namespace lgfx static constexpr int TFT_TRANSPARENT = 0x0120; } +//---------------------------------------------------------------------------- + + namespace gradient_fill_styles + { + enum fill_style_t + { + horizontal_linear = 0, + vertical_linear = 1, + radial_center = 2 + }; + static constexpr const fill_style_t HLINEAR = fill_style_t::horizontal_linear; + static constexpr const fill_style_t VLINEAR = fill_style_t::vertical_linear; + static constexpr const fill_style_t RADIAL = fill_style_t::radial_center; + } + using namespace gradient_fill_styles; + //---------------------------------------------------------------------------- namespace textdatum