diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp b/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp index eef66b2d1..4ed1b2c97 100755 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp @@ -331,7 +331,97 @@ void BitmapBuffer::drawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat } } -void BitmapBuffer::drawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat, LcdFlags flags) +// +// Liang-barsky clipping algo +// +static float lb_max(float arr[], int n) +{ + float m = 0; + for (int i = 0; i < n; ++i) + if (m < arr[i]) m = arr[i]; + return m; +} + +// this function gives the minimum +static float lb_min(float arr[], int n) +{ + float m = 1; + for (int i = 0; i < n; ++i) + if (m > arr[i]) m = arr[i]; + return m; +} + +bool BitmapBuffer::liangBarskyClipper(coord_t& x1, coord_t& y1, coord_t& x2, coord_t& y2) +{ + // defining variables + float p1 = -(x2 - x1); + float p2 = -p1; + float p3 = -(y2 - y1); + float p4 = -p3; + + float q1 = x1 - xmin; + float q2 = xmax - x1; + float q3 = y1 - ymin; + float q4 = ymax - y1; + + float posarr[5], negarr[5]; + int posind = 1, negind = 1; + posarr[0] = 1; + negarr[0] = 0; + + if ((p1 == 0 && q1 < 0) || (p2 == 0 && q2 < 0) || (p3 == 0 && q3 < 0) || + (p4 == 0 && q4 < 0)) { + return false; + } + + if (p1 != 0) { + float r1 = q1 / p1; + float r2 = q2 / p2; + if (p1 < 0) { + negarr[negind++] = r1; // for negative p1, add it to negative array + posarr[posind++] = r2; // and add p2 to positive array + } else { + negarr[negind++] = r2; + posarr[posind++] = r1; + } + } + if (p3 != 0) { + float r3 = q3 / p3; + float r4 = q4 / p4; + if (p3 < 0) { + negarr[negind++] = r3; + posarr[posind++] = r4; + } else { + negarr[negind++] = r4; + posarr[posind++] = r3; + } + } + + float xn1, yn1, xn2, yn2; + float rn1, rn2; + rn1 = lb_max(negarr, negind); // maximum of negative array + rn2 = lb_min(posarr, posind); // minimum of positive array + + if (rn1 > rn2) { // reject + return false; + } + + xn1 = x1 + p2 * rn1; + yn1 = y1 + p4 * rn1; // computing new points + + xn2 = x1 + p2 * rn2; + yn2 = y1 + p4 * rn2; + + x1 = coord_t(xn1); + y1 = coord_t(yn1); + x2 = coord_t(xn2); + y2 = coord_t(yn2); + + return true; +} + +void BitmapBuffer::drawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, + uint8_t pat, LcdFlags flags) { // Offsets x1 += offsetX; @@ -339,6 +429,9 @@ void BitmapBuffer::drawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint x2 += offsetX; y2 += offsetY; + if (!liangBarskyClipper(x1, y1, x2, y2)) + return; + // No 'opacity' here, only 'color' pixel_t color = COLOR_VAL(flags); diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h index e5b9b5299..6d661ff16 100755 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h @@ -426,6 +426,8 @@ class BitmapBuffer: public BitmapBufferBase } void drawHorizontalLineAbs(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags flags, uint8_t opacity); + + bool liangBarskyClipper(coord_t& x1, coord_t& y1, coord_t& x2, coord_t& y2); }; extern BitmapBuffer * lcd;