mirror of https://github.com/MLXXXp/Arduboy2.git
Make drawLine smarter on PIXEL_SAFE_MODE
The current drawLine leaves all the pixel-safety checks to drawPixel, which is not quite optimal for off-screen lines and partially off-screen lines. This commit changes its behavior by having it skip the draw when both ends are off-screen, and also skip when the "current pixel" goes from on-screen to off-screen. To achieve this end some API changes are done to drawPixel, since it after all does not tell whether a draw has been attempted. A (very internal; not in header) drawPixelMaybe function is now composed of drawPixel's checking part, and a drawPixelRaw for a complete absense of checks in other "safe" functions. The drawPixel signature is unchanged; it is hoped that drawPixelMaybe would be inlined, its returns stripped, exposing the drawPixelRaw call as a tail call.
This commit is contained in:
parent
0eae58c760
commit
ecf87428fd
|
@ -313,14 +313,26 @@ const uint8_t bitshift_left[] PROGMEM = {
|
|||
};
|
||||
|
||||
void Arduboy2Base::drawPixel(int16_t x, int16_t y, uint8_t color)
|
||||
{
|
||||
drawPixelMaybe(int16_t x, int16_t y, uint8_t color);
|
||||
}
|
||||
|
||||
// Draw a pixel, tell me whether it has been done.
|
||||
// The intent for inlining is to let drawPixel strip away the return part
|
||||
// and make drawPixelRaw a tail call.
|
||||
inline bool drawPixelMaybe(int16_t x, int16_t y, uint8_t color)
|
||||
{
|
||||
#ifdef PIXEL_SAFE_MODE
|
||||
if (x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1))
|
||||
if (!validPixel(x, y))
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
drawPixelRaw(x, y, color);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduboy2Base::drawPixelRaw(int16_t x, int16_t y, uint8_t color)
|
||||
uint16_t row_offset;
|
||||
uint8_t bit;
|
||||
|
||||
|
@ -501,6 +513,13 @@ void Arduboy2Base::fillCircleHelper
|
|||
void Arduboy2Base::drawLine
|
||||
(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color)
|
||||
{
|
||||
#ifdef PIXEL_SAFE_MODE
|
||||
// No need to draw
|
||||
if (!(validPixel(x0, y0) || validPixel(x1, y1))) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// bresenham's algorithm - thx wikpedia
|
||||
bool steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
|
@ -519,6 +538,9 @@ void Arduboy2Base::drawLine
|
|||
|
||||
int16_t err = dx / 2;
|
||||
int8_t ystep;
|
||||
|
||||
bool initial_validity = steep ? validPixel(y0, x0) : validPixel(x0, y0);
|
||||
bool valid;
|
||||
|
||||
if (y0 < y1)
|
||||
{
|
||||
|
@ -533,11 +555,16 @@ void Arduboy2Base::drawLine
|
|||
{
|
||||
if (steep)
|
||||
{
|
||||
drawPixel(y0, x0, color);
|
||||
valid = drawPixel(y0, x0, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawPixel(x0, y0, color);
|
||||
valid = drawPixel(x0, y0, color);
|
||||
}
|
||||
|
||||
// We have reached the end of valid pixels.
|
||||
if (initial_validity && !valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
err -= dy;
|
||||
|
@ -561,10 +588,14 @@ void Arduboy2Base::drawRect
|
|||
void Arduboy2Base::drawFastVLine
|
||||
(int16_t x, int16_t y, uint8_t h, uint8_t color)
|
||||
{
|
||||
// Do x bounds checks
|
||||
if (x < 0 || x >= WIDTH)
|
||||
return;
|
||||
|
||||
int end = y+h;
|
||||
for (int a = max(0,y); a < min(end,HEIGHT); a++)
|
||||
{
|
||||
drawPixel(x,a,color);
|
||||
drawPixelRaw(x,a,color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,20 @@ class Arduboy2Base : public Arduboy2Core
|
|||
*/
|
||||
void display(bool clear);
|
||||
|
||||
/** \brief
|
||||
* Tells whether a given coordinate points to a valid pixel.
|
||||
*
|
||||
* \param x The X coordinate of the pixel.
|
||||
* \param y The Y coordinate of the pixel.
|
||||
*
|
||||
* \details
|
||||
* This function returns true if x is in the interval [0, WIDTH) and y is in
|
||||
* the interval [0, HEIGHT).
|
||||
*/
|
||||
bool validPixel(int16_t x, int16_t y) {
|
||||
return !(x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1));
|
||||
}
|
||||
|
||||
/** \brief
|
||||
* Set a single pixel in the display buffer to the specified color.
|
||||
*
|
||||
|
@ -444,6 +458,10 @@ class Arduboy2Base : public Arduboy2Core
|
|||
*/
|
||||
void drawPixel(int16_t x, int16_t y, uint8_t color = WHITE);
|
||||
|
||||
// Draw a pixel without checking.
|
||||
// (Not officially part of the API)
|
||||
void drawPixelRaw(int16_t x, int16_t y, uint8_t color);
|
||||
|
||||
/** \brief
|
||||
* Returns the state of the given pixel in the screen buffer.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue