diff --git a/CONTRIBUTORS b/CONTRIBUTORS index b9907e95..f3507096 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2441,6 +2441,7 @@ Christoph Haubrich for suggesting to add a confirmation before renaming a recording to its folder name for reporting a problem with data loss in case renaming a recording fails for adding support for HEVC-video and AC-4-audio + for implementing anti-aliasing for cPixmap::DrawSlope() Pekka Mauno for fixing cSchedule::GetFollowingEvent() in case there is currently no present diff --git a/HISTORY b/HISTORY index b764a911..e7e780ed 100644 --- a/HISTORY +++ b/HISTORY @@ -9513,7 +9513,7 @@ Video Disk Recorder Revision History with the main menu open. - Official release. -2020-09-16: +2020-09-29: Version 2.4.5 - Updated the Italian OSD texts (thanks to Diego Pierotto). - Fixed handling newline characters in ci.c's CopyString() (reported by Winfried Köhler). @@ -9521,3 +9521,6 @@ Video Disk Recorder Revision History by Winfried Köhler). - Fixed a possible invalid lock sequence in cMenuTimers::OnOff(). - Fixed several typos (reported by Jens Schleusener). +- Implemented anti-aliasing for cPixmap::DrawSlope() (thanks to Christoph Haubrich). + The version numbers (both VDRVERSNUM and APIVERSNUM) have been bumped to 2.4.5 to + indicate this change. diff --git a/config.h b/config.h index c9f3d3b1..f57aea73 100644 --- a/config.h +++ b/config.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 4.19 2020/07/15 15:13:08 kls Exp $ + * $Id: config.h 4.20 2020/09/29 14:09:26 kls Exp $ */ #ifndef __CONFIG_H @@ -22,13 +22,13 @@ // VDR's own version number: -#define VDRVERSION "2.4.4" -#define VDRVERSNUM 20404 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "2.4.5" +#define VDRVERSNUM 20405 // Version * 10000 + Major * 100 + Minor // The plugin API's version number: -#define APIVERSION "2.4.3" -#define APIVERSNUM 20403 // Version * 10000 + Major * 100 + Minor +#define APIVERSION "2.4.5" +#define APIVERSNUM 20405 // Version * 10000 + Major * 100 + Minor // When loading plugins, VDR searches them by their APIVERSION, which // may be smaller than VDRVERSION in case there have been no changes to diff --git a/osd.c b/osd.c index 8a3ce721..e8c7f857 100644 --- a/osd.c +++ b/osd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 4.6 2019/05/24 21:28:35 kls Exp $ + * $Id: osd.c 4.7 2020/09/29 14:09:26 kls Exp $ */ #include "osd.h" @@ -1273,6 +1273,20 @@ void cPixmapMemory::DrawPixel(const cPoint &Point, tColor Color) Unlock(); } +void cPixmapMemory::DrawBlendedPixel(const cPoint &Point, tColor Color, uint8_t Alpha) +{ + Lock(); + if (DrawPort().Size().Contains(Point)) { + int p = Point.Y() * DrawPort().Width() + Point.X(); + if (Alpha != ALPHA_OPAQUE) + data[p] = AlphaBlend(Color, data[p], Alpha); + else + data[p] = Color; + MarkDrawPortDirty(Point); + } + Unlock(); +} + void cPixmapMemory::DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool Overlay) { Lock(); @@ -1480,7 +1494,6 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants) void cPixmapMemory::DrawSlope(const cRect &Rect, tColor Color, int Type) { - //TODO anti-aliasing? //TODO also simplify cBitmap::DrawSlope() Lock(); bool upper = Type & 0x01; @@ -1492,28 +1505,87 @@ void cPixmapMemory::DrawSlope(const cRect &Rect, tColor Color, int Type) int y2 = Rect.Bottom(); int w = Rect.Width(); int h = Rect.Height(); + bool AntiAliased = Setup.AntiAlias; + uint8_t intensity = 0; + if (vertical) { - for (int y = y1; y <= y2; y++) { - double c = cos((y - y1) * M_PI / h); + if (upper) + DrawRectangle(cRect(x1, y1, w, 1), Color); + else + DrawRectangle(cRect(x1, y2, w, 1), Color); + for (int y = 1; y <= (y2 - y1) / 2; y++) { + double c = cos(y * M_PI / (y2 - y1)); + if (AntiAliased) { + double wc = (w * c + (w & 1)) / 2; + intensity = 255 * fabs(wc - floor(wc)); + } if (falling) c = -c; - int x = (x1 + x2) / 2 + int(w * c / 2); - if (upper && !falling || !upper && falling) - DrawRectangle(cRect(x1, y, x - x1 + 1, 1), Color); - else - DrawRectangle(cRect(x, y, x2 - x + 1, 1), Color); + int x = (x1 + x2 + w * c + 1) / 2; + if (upper && !falling || !upper && falling) { + if (AntiAliased) { + DrawRectangle(cRect(x1, y1 + y, x - x1, 1), Color); + DrawBlendedPixel(cPoint(x, y1 + y), Color, upper ? intensity : 255 - intensity); + DrawRectangle(cRect(x1, y2 - y, x2 - x, 1), Color); + DrawBlendedPixel(cPoint(x1 + x2 - x, y2 - y), Color, upper ? 255 - intensity : intensity); + } + else { + DrawRectangle(cRect(x1, y1 + y, x - x1 + 1, 1), Color); + DrawRectangle(cRect(x1, y2 - y, x2 - x + 1, 1), Color); + } + } + else { + if (AntiAliased) { + DrawRectangle(cRect(x + 1, y1 + y, x2 - x, 1), Color); + DrawBlendedPixel(cPoint(x, y1 + y), Color, falling ? intensity : 255 - intensity); + DrawRectangle(cRect(x1 + x2 - x + 1, y2 - y, x - x1, 1), Color); + DrawBlendedPixel(cPoint(x1 + x2 - x, y2 - y), Color, falling ? 255 - intensity : intensity); + } + else { + DrawRectangle(cRect(x, y1 + y, x2 - x + 1, 1), Color); + DrawRectangle(cRect(x1 + x2 - x, y2 - y, x - x1 + 1, 1), Color); + } + } } } else { - for (int x = x1; x <= x2; x++) { - double c = cos((x - x1) * M_PI / w); + if ((upper && !falling) || (!upper && falling)) + DrawRectangle(cRect(x1, y1, 1, h), Color); + else + DrawRectangle(cRect(x2, y1, 1, h), Color); + for (int x = 1; x <= (x2 - x1) / 2; x++) { + double c = cos(x * M_PI / (x2 - x1)); + if (AntiAliased) { + double hc = (h * c + (h & 1)) / 2; + intensity = 255 * fabs(hc - floor(hc)); + } if (falling) c = -c; - int y = (y1 + y2) / 2 + int(h * c / 2); - if (upper) - DrawRectangle(cRect(x, y1, 1, y - y1 + 1), Color); - else - DrawRectangle(cRect(x, y, 1, y2 - y + 1), Color); + int y = (y1 + y2 + h * c + 1) / 2; + if (upper) { + if (AntiAliased) { + DrawRectangle(cRect(x1 + x, y1, 1, y - y1), Color); + DrawBlendedPixel(cPoint(x1 + x, y), Color, falling ? 255 - intensity : intensity); + DrawRectangle(cRect(x2 - x, y1, 1, y2 - y), Color); + DrawBlendedPixel(cPoint(x2 - x, y1 + y2 - y), Color, falling ? intensity : 255 - intensity); + } + else { + DrawRectangle(cRect(x1 + x, y1, 1, y - y1 + 1), Color); + DrawRectangle(cRect(x2 - x, y1, 1, y2 - y + 1), Color); + } + } + else { + if (AntiAliased) { + DrawRectangle(cRect(x1 + x, y + 1, 1, y2 - y), Color); + DrawBlendedPixel(cPoint(x1 + x, y), Color, falling ? intensity : 255 - intensity); + DrawRectangle(cRect(x2 - x, y1 + y2 - y + 1, 1, y - y1), Color); + DrawBlendedPixel(cPoint(x2 - x, y1 + y2 - y), Color, falling ? 255 - intensity : intensity); + } + else { + DrawRectangle(cRect(x1 + x, y, 1, y2 - y + 1), Color); + DrawRectangle(cRect(x2 - x, y1 + y2 - y, 1, y - y1 + 1), Color); + } + } } } MarkDrawPortDirty(Rect); diff --git a/osd.h b/osd.h index 51b1adf9..eeb5496f 100644 --- a/osd.h +++ b/osd.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.h 4.6 2019/05/24 21:28:35 kls Exp $ + * $Id: osd.h 4.7 2020/09/29 14:09:26 kls Exp $ */ #ifndef __OSD_H @@ -607,6 +607,10 @@ public: ///< a full 32 bit ARGB value. If the alpha value of Color is not 0xFF ///< (fully opaque), and this is the background pixmap (layer 0), the pixel is ///< alpha blended with the existing color at the given position in this pixmap. + virtual void DrawBlendedPixel(const cPoint &Point, tColor Color, uint8_t AlphaLayer = ALPHA_OPAQUE) { DrawPixel(Point, Color); } + ///< Like DrawPixel(), but with an additional AlphaLayer, and works on any + ///< pixmap, not only the background. The default implementation just calls + ///< DrawPixel(), ignoring AlphaLayer. virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false) = 0; ///< Sets the pixels in the OSD with the data from the given ///< Bitmap, putting the upper left corner of the Bitmap at Point. @@ -697,6 +701,7 @@ public: virtual void DrawImage(const cPoint &Point, const cImage &Image); virtual void DrawImage(const cPoint &Point, int ImageHandle); virtual void DrawPixel(const cPoint &Point, tColor Color); + virtual void DrawBlendedPixel(const cPoint &Point, tColor Color, uint8_t AlphaLayer = ALPHA_OPAQUE); virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false); virtual void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); virtual void DrawRectangle(const cRect &Rect, tColor Color);