From 59f160f21f5fbfeff95a8a8f8abc8d1aa5853fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Garci=CC=81a=20Hierro?= Date: Tue, 7 Jul 2020 21:09:53 +0100 Subject: [PATCH] [CANVAS] Fix leftover pixels when drawing the home direction arrow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the arrow is taller than the width of a grid slow, it overflows the slot a bit when it's rotated by 90ยบ. Also, simplify the algorithm for drawing it a bit so it transmits a bit less data per redrawing. --- src/main/io/osd.c | 2 +- src/main/io/osd_canvas.c | 33 +++++++++++++++++++++------------ src/main/io/osd_canvas.h | 2 +- src/main/io/osd_common.c | 7 ++----- src/main/io/osd_common.h | 2 +- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/main/io/osd.c b/src/main/io/osd.c index a340e0ecad..0d3b7d75d4 100755 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -1310,7 +1310,7 @@ static bool osdDrawSingleElement(uint8_t item) else { int homeDirection = GPS_directionToHome - DECIDEGREES_TO_DEGREES(osdGetHeading()); - osdDrawDirArrow(osdDisplayPort, osdGetDisplayPortCanvas(), OSD_DRAW_POINT_GRID(elemPosX, elemPosY), homeDirection, true); + osdDrawDirArrow(osdDisplayPort, osdGetDisplayPortCanvas(), OSD_DRAW_POINT_GRID(elemPosX, elemPosY), homeDirection); } } else { // No home or no fix or unknown heading, blink. diff --git a/src/main/io/osd_canvas.c b/src/main/io/osd_canvas.c index 801fb1703e..a649b10b5b 100644 --- a/src/main/io/osd_canvas.c +++ b/src/main/io/osd_canvas.c @@ -120,32 +120,41 @@ void osdCanvasDrawVario(displayPort_t *display, displayCanvas_t *canvas, const o prev = zvel; } -void osdCanvasDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees, bool eraseBefore) +void osdCanvasDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees) { UNUSED(display); + const int top = 6; + const int topInset = -2; + const int bottom = -6; + const int width = 5; + // Since grid slots are not square, when we rotate the arrow + // it overflows horizontally a bit. Making a square-ish arrow + // doesn't look good, so it's better to overstep the grid slot + // boundaries a bit and then clean after ourselves. + const int overflow = 3; + int px; int py; osdDrawPointGetPixels(&px, &py, display, canvas, p); - displayCanvasClipToRect(canvas, px, py, canvas->gridElementWidth, canvas->gridElementHeight); - - if (eraseBefore) { - displayCanvasSetFillColor(canvas, DISPLAY_CANVAS_COLOR_TRANSPARENT); - displayCanvasFillRect(canvas, px, py, canvas->gridElementWidth, canvas->gridElementHeight); - } + displayCanvasClearRect(canvas, px - overflow, py, canvas->gridElementWidth + overflow * 2, canvas->gridElementHeight); displayCanvasSetFillColor(canvas, DISPLAY_CANVAS_COLOR_WHITE); displayCanvasSetStrokeColor(canvas, DISPLAY_CANVAS_COLOR_BLACK); displayCanvasCtmRotate(canvas, -DEGREES_TO_RADIANS(180 + degrees)); displayCanvasCtmTranslate(canvas, px + canvas->gridElementWidth / 2, py + canvas->gridElementHeight / 2); - displayCanvasFillStrokeTriangle(canvas, 0, 6, 5, -6, -5, -6); + + // Main triangle + displayCanvasFillStrokeTriangle(canvas, 0, top, width, bottom, -width, bottom); + // Inset triangle displayCanvasSetFillColor(canvas, DISPLAY_CANVAS_COLOR_TRANSPARENT); - displayCanvasFillStrokeTriangle(canvas, 0, -2, 6, -7, -6, -7); - displayCanvasMoveToPoint(canvas, 6, -7); - displayCanvasSetStrokeColor(canvas, DISPLAY_CANVAS_COLOR_TRANSPARENT); - displayCanvasStrokeLineToPoint(canvas, -6, -7); + displayCanvasFillTriangle(canvas, 0, topInset, width + 1, bottom - 1, -width, bottom - 1); + // Draw bottom strokes of the triangle + displayCanvasMoveToPoint(canvas, -width, bottom - 1); + displayCanvasStrokeLineToPoint(canvas, 0, topInset); + displayCanvasStrokeLineToPoint(canvas, width, bottom - 1); } static void osdDrawArtificialHorizonLevelLine(displayCanvas_t *canvas, int width, int pos, int margin) diff --git a/src/main/io/osd_canvas.h b/src/main/io/osd_canvas.h index b6fc2722ce..6a8d013e80 100644 --- a/src/main/io/osd_canvas.h +++ b/src/main/io/osd_canvas.h @@ -33,7 +33,7 @@ typedef struct displayCanvas_s displayCanvas_t; typedef struct osdDrawPoint_s osdDrawPoint_t; void osdCanvasDrawVario(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float zvel); -void osdCanvasDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees, bool eraseBefore); +void osdCanvasDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees); void osdCanvasDrawArtificialHorizon(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float pitchAngle, float rollAngle); void osdCanvasDrawHeadingGraph(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, int heading); bool osdCanvasDrawSidebars(displayPort_t *display, displayCanvas_t *canvas); diff --git a/src/main/io/osd_common.c b/src/main/io/osd_common.c index 5dc53ea41d..f5453f4ec6 100644 --- a/src/main/io/osd_common.c +++ b/src/main/io/osd_common.c @@ -88,17 +88,14 @@ void osdDrawVario(displayPort_t *display, displayCanvas_t *canvas, const osdDraw #endif } -void osdDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees, bool eraseBefore) +void osdDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees) { -#if !defined(USE_CANVAS) - UNUSED(eraseBefore); -#endif uint8_t gx; uint8_t gy; #if defined(USE_CANVAS) if (canvas) { - osdCanvasDrawDirArrow(display, canvas, p, degrees, eraseBefore); + osdCanvasDrawDirArrow(display, canvas, p, degrees); } else { #endif osdDrawPointGetGrid(&gx, &gy, display, canvas, p); diff --git a/src/main/io/osd_common.h b/src/main/io/osd_common.h index a878c2f3d4..054f458a63 100644 --- a/src/main/io/osd_common.h +++ b/src/main/io/osd_common.h @@ -76,7 +76,7 @@ void osdDrawVario(displayPort_t *display, displayCanvas_t *canvas, const osdDraw // Draws an arrow at the given point, where 0 degrees points to the top of the viewport and // positive angles result in clockwise rotation. If eraseBefore is true, the rect surrouing // the arrow will be erased first (need for e.g. the home arrow, since it uses multiple symbols) -void osdDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees, bool eraseBefore); +void osdDrawDirArrow(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float degrees); void osdDrawArtificialHorizon(displayPort_t *display, displayCanvas_t *canvas, const osdDrawPoint_t *p, float rollAngle, float pitchAngle); // Draws a heading graph with heading given as 0.1 degree steps i.e. [0, 3600). It uses 9 horizontal // grid slots.