1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Implemented anti-aliasing for cPixmap::DrawEllipse()

This commit is contained in:
Klaus Schmidinger 2020-10-12 13:54:44 +02:00
parent bbd36d0610
commit fc7ca12edd
3 changed files with 167 additions and 41 deletions

View File

@ -2441,7 +2441,7 @@ Christoph Haubrich <christoph1.haubrich@arcor.de>
for suggesting to add a confirmation before renaming a recording to its folder name 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 reporting a problem with data loss in case renaming a recording fails
for adding support for HEVC-video and AC-4-audio for adding support for HEVC-video and AC-4-audio
for implementing anti-aliasing for cPixmap::DrawSlope() for implementing anti-aliasing for cPixmap::DrawSlope() and cPixmap::DrawEllipse()
Pekka Mauno <pekka.mauno@iki.fi> Pekka Mauno <pekka.mauno@iki.fi>
for fixing cSchedule::GetFollowingEvent() in case there is currently no present for fixing cSchedule::GetFollowingEvent() in case there is currently no present

View File

@ -9513,7 +9513,7 @@ Video Disk Recorder Revision History
with the main menu open. with the main menu open.
- Official release. - Official release.
2020-09-29: Version 2.4.5 2020-10-12: Version 2.4.5
- Updated the Italian OSD texts (thanks to Diego Pierotto). - Updated the Italian OSD texts (thanks to Diego Pierotto).
- Fixed handling newline characters in ci.c's CopyString() (reported by Winfried Köhler). - Fixed handling newline characters in ci.c's CopyString() (reported by Winfried Köhler).
@ -9521,6 +9521,7 @@ Video Disk Recorder Revision History
by Winfried Köhler). by Winfried Köhler).
- Fixed a possible invalid lock sequence in cMenuTimers::OnOff(). - Fixed a possible invalid lock sequence in cMenuTimers::OnOff().
- Fixed several typos (reported by Jens Schleusener). - Fixed several typos (reported by Jens Schleusener).
- Implemented anti-aliasing for cPixmap::DrawSlope() (thanks to Christoph Haubrich). - Implemented anti-aliasing for cPixmap::DrawSlope() and cPixmap::DrawEllipse() (thanks
to Christoph Haubrich).
The version numbers (both VDRVERSNUM and APIVERSNUM) have been bumped to 2.4.5 to The version numbers (both VDRVERSNUM and APIVERSNUM) have been bumped to 2.4.5 to
indicate this change. indicate this change.

135
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.c 4.7 2020/09/29 14:09:26 kls Exp $ * $Id: osd.c 4.8 2020/10/12 13:54:44 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
@ -633,7 +633,7 @@ void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quad
{ {
if (!Intersects(x1, y1, x2, y2)) if (!Intersects(x1, y1, x2, y2))
return; return;
// Algorithm based on http://homepage.smc.edu/kennedy_john/BELIPSE.PDF // Algorithm based on https://dai.fmph.uniba.sk/upload/0/01/Ellipse.pdf
int rx = x2 - x1; int rx = x2 - x1;
int ry = y2 - y1; int ry = y2 - y1;
int cx = (x1 + x2) / 2; int cx = (x1 + x2) / 2;
@ -1278,8 +1278,12 @@ void cPixmapMemory::DrawBlendedPixel(const cPoint &Point, tColor Color, uint8_t
Lock(); Lock();
if (DrawPort().Size().Contains(Point)) { if (DrawPort().Size().Contains(Point)) {
int p = Point.Y() * DrawPort().Width() + Point.X(); int p = Point.Y() * DrawPort().Width() + Point.X();
if (Alpha != ALPHA_OPAQUE) if (Alpha != ALPHA_OPAQUE) {
if (Color == clrTransparent)
data[p] = (data[p] & 0x00FFFFFF) | ((((data[p] >> 24) * (255 - Alpha)) << 16) & 0xFF000000);
else
data[p] = AlphaBlend(Color, data[p], Alpha); data[p] = AlphaBlend(Color, data[p], Alpha);
}
else else
data[p] = Color; data[p] = Color;
MarkDrawPortDirty(Point); MarkDrawPortDirty(Point);
@ -1392,10 +1396,9 @@ void cPixmapMemory::DrawRectangle(const cRect &Rect, tColor Color)
void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants) void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
{ {
//TODO use anti-aliasing?
//TODO fix alignment //TODO fix alignment
Lock(); Lock();
// Algorithm based on http://homepage.smc.edu/kennedy_john/BELIPSE.PDF // Algorithm based on https://dai.fmph.uniba.sk/upload/0/01/Ellipse.pdf
int x1 = Rect.Left(); int x1 = Rect.Left();
int y1 = Rect.Top(); int y1 = Rect.Top();
int x2 = Rect.Right(); int x2 = Rect.Right();
@ -1425,7 +1428,10 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
int EllipseError = 0; int EllipseError = 0;
int StoppingX = TwoBSquare * rx; int StoppingX = TwoBSquare * rx;
int StoppingY = 0; int StoppingY = 0;
int Delta = 0;
bool AntiAliased = Setup.AntiAlias;
while (StoppingX >= StoppingY) { while (StoppingX >= StoppingY) {
if (!AntiAliased) {
switch (Quadrants) { switch (Quadrants) {
case 5: DrawRectangle(cRect(cx, cy + y, x + 1, 1), Color); // no break case 5: DrawRectangle(cRect(cx, cy + y, x + 1, 1), Color); // no break
case 1: DrawRectangle(cRect(cx, cy - y, x + 1, 1), Color); break; case 1: DrawRectangle(cRect(cx, cy - y, x + 1, 1), Color); break;
@ -1442,6 +1448,59 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break; case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break;
default: ; default: ;
} }
}
else {
uint8_t intensity = abs(255 * (long int)EllipseError / XChange);
if (EllipseError >= 0) {
intensity = 255 - intensity;
Delta = 0;
}
else
Delta = 1;
switch (Quadrants) {
case 5: DrawRectangle( cRect( cx, cy + y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx + x + Delta, cy + y), Color, intensity);
// no break
case 1: DrawRectangle( cRect( cx, cy - y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx + x + Delta, cy - y), Color, intensity);
break;
case 7: DrawRectangle( cRect( cx - x + 1 - Delta, cy + y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy + y), Color, intensity);
// no break
case 2: DrawRectangle( cRect( cx - x + 1 - Delta, cy - y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy - y), Color, intensity);
break;
case 3: DrawRectangle( cRect( cx - x + 1 - Delta, cy + y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy + y), Color, intensity);
break;
case 4: DrawRectangle( cRect( cx, cy + y, x + Delta, 1), Color);
DrawBlendedPixel(cPoint(cx + x + Delta, cy + y), Color, intensity);
break;
case 0:
case 6: DrawRectangle( cRect( cx - x + 1 - Delta, cy - y, 2 * (x + Delta) - 1, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy - y), Color, intensity);
DrawBlendedPixel(cPoint(cx + x + Delta, cy - y), Color, intensity);
if (Quadrants == 6)
break;
case 8: DrawRectangle( cRect( cx - x + 1 - Delta, cy + y, 2 * (x + Delta) - 1 , 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy + y), Color, intensity);
DrawBlendedPixel(cPoint(cx + x + Delta, cy + y), Color, intensity);
break;
case -1: DrawRectangle( cRect( cx + x + 1 + Delta, cy - y, rx - (x + Delta), 1), Color);
DrawBlendedPixel(cPoint(cx + x + Delta, cy - y), Color, 255-intensity);
break;
case -2: DrawRectangle( cRect( x1, cy - y, rx - x - Delta, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy - y), Color, 255-intensity);
break;
case -3: DrawRectangle( cRect( x1, cy + y, rx - x - Delta, 1), Color);
DrawBlendedPixel(cPoint(cx - x - Delta, cy + y), Color, 255-intensity);
break;
case -4: DrawRectangle( cRect( cx + x + 1 + Delta, cy + y, rx - x - Delta, 1), Color);
DrawBlendedPixel(cPoint(cx + x + Delta, cy + y), Color, 255-intensity);
break;
default: ;
}
}
y++; y++;
StoppingY += TwoASquare; StoppingY += TwoASquare;
EllipseError += YChange; EllipseError += YChange;
@ -1453,6 +1512,7 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
XChange += TwoBSquare; XChange += TwoBSquare;
} }
} }
int ymax = y - 1;
x = 0; x = 0;
y = ry; y = ry;
XChange = ry * ry; XChange = ry * ry;
@ -1461,6 +1521,7 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
StoppingX = 0; StoppingX = 0;
StoppingY = TwoASquare * ry; StoppingY = TwoASquare * ry;
while (StoppingX <= StoppingY) { while (StoppingX <= StoppingY) {
if (!AntiAliased) {
switch (Quadrants) { switch (Quadrants) {
case 5: DrawRectangle(cRect(cx, cy + y, x + 1, 1), Color); // no break case 5: DrawRectangle(cRect(cx, cy + y, x + 1, 1), Color); // no break
case 1: DrawRectangle(cRect(cx, cy - y, x + 1, 1), Color); break; case 1: DrawRectangle(cRect(cx, cy - y, x + 1, 1), Color); break;
@ -1477,6 +1538,61 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break; case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break;
default: ; default: ;
} }
}
else {
uint8_t intensity = abs(255 * (long int)EllipseError / YChange);
if (EllipseError >= 0) {
intensity = 255 - intensity;
Delta = 1;
}
else
Delta = 0;
switch (Quadrants) {
case 5: DrawRectangle( cRect( cx + x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx + x, cy + y + 1 - Delta), Color, intensity);
// no break
case 1: DrawRectangle( cRect( cx + x, cy - y + Delta, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx + x, cy - y - 1 + Delta), Color, intensity);
break;
case 7: DrawRectangle( cRect( cx - x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy + y + 1 - Delta), Color, intensity);
// no break
case 2: DrawRectangle( cRect( cx - x, cy - y + Delta, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy - y - 1 + Delta), Color, intensity);
break;
case 3: DrawRectangle( cRect( cx - x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy + y + 1 - Delta), Color, intensity);
break;
case 4: DrawRectangle( cRect( cx + x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx + x, cy + y + 1 - Delta), Color, intensity);
break;
case 0:
case 6: DrawRectangle( cRect( cx + x, cy - y + Delta, 1, y - ymax - Delta), Color);
DrawRectangle( cRect( cx - x, cy - y + Delta, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy - y - 1 + Delta), Color, intensity);
DrawBlendedPixel(cPoint(cx + x, cy - y - 1 + Delta), Color, intensity);
if (Quadrants == 6)
break;
case 8: DrawRectangle( cRect( cx - x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawRectangle( cRect( cx + x, cy + 1 + ymax, 1, y - ymax - Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy + y + 1 - Delta), Color, intensity);
DrawBlendedPixel(cPoint(cx + x, cy + y + 1 - Delta), Color, intensity);
break;
case -1: DrawRectangle( cRect( cx + x, cy - ry, 1, ry - y - 1 + Delta), Color);
DrawBlendedPixel(cPoint(cx + x, cy - y - 1 + Delta), Color, 255-intensity);
break;
case -2: DrawRectangle( cRect( cx - x, cy - ry, 1, ry - y - 1 + Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy - y - 1 + Delta), Color, 255-intensity);
break;
case -3: DrawRectangle( cRect( cx - x, cy + y + 2 - Delta, 1, ry - y - 1 + Delta), Color);
DrawBlendedPixel(cPoint(cx - x, cy + y + 1 - Delta), Color, 255-intensity);
break;
case -4: DrawRectangle( cRect( cx + x, cy + y + 2 - Delta, 1, ry - y - 1 + Delta), Color);
DrawBlendedPixel(cPoint(cx + x, cy + y + 1 - Delta), Color, 255-intensity);
break;
default: ;
}
}
x++; x++;
StoppingX += TwoBSquare; StoppingX += TwoBSquare;
EllipseError += XChange; EllipseError += XChange;
@ -1488,6 +1604,15 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants)
YChange += TwoASquare; YChange += TwoASquare;
} }
} }
if (AntiAliased && Quadrants < 0 ) {
switch (Quadrants) {
case -1: DrawRectangle(cRect(cx + x, cy - ry, rx - x + 1, ry - y), Color); break;
case -2: DrawRectangle(cRect(x1, cy - ry, rx - x + 1, ry - y), Color); break;
case -3: DrawRectangle(cRect(x1, cy + y + 1, rx - x + 1, ry - y), Color); break;
case -4: DrawRectangle(cRect(cx + x, cy + y + 1, rx - x + 1, ry - y), Color); break;
default: ;
}
}
MarkDrawPortDirty(Rect); MarkDrawPortDirty(Rect);
Unlock(); Unlock();
} }