13 #include <sys/ioctl.h>
15 #include <sys/unistd.h>
25 double p = V * (1 - S);
26 double q = V * (1 - S * f);
27 double t = V * (1 - S * (1 - f));
45 double f = fabs(
constrain(Factor, -1.0, 1.0));
46 double w = Factor > 0 ? f * 0xFF : 0;
47 return (Color & 0xFF000000) |
48 (
min(0xFF,
int((1 - f) * ((Color >> 16) & 0xFF) + w + 0.5)) << 16) |
49 (
min(0xFF,
int((1 - f) * ((Color >> 8) & 0xFF) + w + 0.5)) << 8) |
50 (
min(0xFF,
int((1 - f) * ( Color & 0xFF) + w + 0.5)) );
65 for (
int alphaA = 0; alphaA < 255; alphaA++) {
66 int range = (alphaA == 255 ? 255 : 254);
67 for (
int alphaB = 0; alphaB < 256; alphaB++) {
68 int alphaO_x_range = 255 * alphaA + alphaB * (range - alphaA);
71 int factorA = (256 * 255 * alphaA + alphaO_x_range / 2) / alphaO_x_range;
72 int factorB = (256 * alphaB * (range - alphaA) + alphaO_x_range / 2) / alphaO_x_range;
83 tColor Alpha = (ColorFg & 0xFF000000) >> 24;
86 uint16_t *lut = &
AlphaLutFactors[Alpha][(ColorBg & 0xFF000000) >> 24][0];
88 | (((((ColorFg & 0x00FF00FF) * lut[0] + (ColorBg & 0x00FF00FF) * lut[1])) & 0xFF00FF00)
89 | ((((ColorFg & 0x0000FF00) * lut[0] + (ColorBg & 0x0000FF00) * lut[1])) & 0x00FF0000)) >> 8);
97 tColor RB = (Color & 0x00FF00FF) * Alpha;
98 RB = ((RB + ((RB >> 8) & 0x00FF00FF) + 0x00800080) >> 8) & 0x00FF00FF;
99 tColor AG = ((Color >> 8) & 0x00FF00FF) * Alpha;
100 AG = ((AG + ((AG >> 8) & 0x00FF00FF) + 0x00800080)) & 0xFF00FF00;
106 tColor Alpha = (ColorFg & 0xFF000000) >> 24;
109 Alpha = ((Alpha + ((Alpha >> 8) & 0x000000FF) + 0x00000080) >> 8) & 0x000000FF;
111 return Multiply(ColorFg, Alpha) + Multiply(ColorBg, 255 - Alpha);
133 int ColorsPerBlend = ColorsForBlending / BlendColors + 2;
193 for (
int i = 0; i < Palette.
numColors; i++) {
195 if (ColorFg || ColorBg) {
197 case 0:
Color = ColorBg;
break;
198 case 1:
Color = ColorFg;
break;
210 for (
int i = 0; i < Palette.
numColors; i++)
220 int Af = (ColorFg & 0xFF000000) >> 24;
221 int Rf = (ColorFg & 0x00FF0000) >> 16;
222 int Gf = (ColorFg & 0x0000FF00) >> 8;
223 int Bf = (ColorFg & 0x000000FF);
224 int Ab = (ColorBg & 0xFF000000) >> 24;
225 int Rb = (ColorBg & 0x00FF0000) >> 16;
226 int Gb = (ColorBg & 0x0000FF00) >> 8;
227 int Bb = (ColorBg & 0x000000FF);
228 int A = (Ab + (Af - Ab) * Level / 0xFF) & 0xFF;
229 int R = (Rb + (Rf - Rb) * Level / 0xFF) & 0xFF;
230 int G = (Gb + (Gf - Gb) * Level / 0xFF) & 0xFF;
231 int B = (Bb + (Bf - Bb) * Level / 0xFF) & 0xFF;
232 return (A << 24) | (R << 16) | (G << 8) | B;
239 int A1 = (
Color & 0xFF000000) >> 24;
240 int R1 = (
Color & 0x00FF0000) >> 16;
241 int G1 = (
Color & 0x0000FF00) >> 8;
242 int B1 = (
Color & 0x000000FF);
243 for (
int i = 0; i < numColors && d > 0; i++) {
244 int A2 = (
color[i] & 0xFF000000) >> 24;
245 int R2 = (
color[i] & 0x00FF0000) >> 16;
246 int G2 = (
color[i] & 0x0000FF00) >> 8;
247 int B2 = (
color[i] & 0x000000FF);
250 diff = (abs(A1 - A2) << 1) + (abs(R1 - R2) << 1) + (abs(G1 - G2) << 1) + (abs(B1 - B2) << 1);
256 return d <= MaxDiff ? n : -1;
311 esyslog(
"ERROR: can't allocate bitmap!");
321 return 0 <= x && x <
width && 0 <= y && y <
height;
330 return x1 <= 0 && y1 <= 0 && x2 >=
width - 1 && y2 >=
height - 1;
339 return !(x2 < 0 || x1 >=
width || y2 < 0 || y1 >=
height);
365 FILE *f = fopen(FileName,
"r");
373 while ((s = ReadLine.
Read(f)) != NULL) {
376 if (strcmp(s,
"/* XPM */") != 0) {
377 esyslog(
"ERROR: invalid header in XPM file '%s'", FileName);
382 else if (*s++ ==
'"') {
385 if (4 != sscanf(s,
"%d %d %d %d", &w, &h, &n, &c)) {
386 esyslog(
"ERROR: faulty 'values' line in XPM file '%s'", FileName);
391 Xpm =
MALLOC(
char *, lines);
392 memset(Xpm, 0, lines *
sizeof(
char*));
394 char *q = strchr(s,
'"');
396 esyslog(
"ERROR: missing quotes in XPM file '%s'", FileName);
402 Xpm[index++] = strdup(s);
404 esyslog(
"ERROR: too many lines in XPM file '%s'", FileName);
414 esyslog(
"ERROR: too few lines in XPM file '%s'", FileName);
417 for (
int i = 0; i < index; i++)
424 esyslog(
"ERROR: can't open XPM file '%s'", FileName);
432 const char *
const *p = Xpm;
434 if (4 != sscanf(*p,
"%d %d %d %d", &w, &h, &n, &c)) {
435 esyslog(
"ERROR: faulty 'values' line in XPM: '%s'", *p);
439 esyslog(
"ERROR: too many colors in XPM: %d", n);
443 while (1 << (1 << b) < (IgnoreNone ? n - 1 : n))
448 for (
int i = 0; i < n; i++) {
449 const char *s = *++p;
450 if (
int(strlen(s)) < c) {
451 esyslog(
"ERROR: faulty 'colors' line in XPM: '%s'", s);
456 esyslog(
"ERROR: unknown color key in XPM: '%c'", *s);
460 if (strcasecmp(s,
"none") == 0) {
467 esyslog(
"ERROR: unknown color code in XPM: '%c'", *s);
470 tColor color = strtoul(++s, NULL, 16) | 0xFF000000;
471 SetColor((IgnoreNone && i > NoneColorIndex) ? i - 1 : i,
color);
473 for (
int y = 0; y < h; y++) {
474 const char *s = *++p;
475 if (
int(strlen(s)) != w * c) {
476 esyslog(
"ERROR: faulty pixel line in XPM: %d '%s'", y, s);
479 for (
int x = 0; x < w; x++) {
480 for (
int i = 0; i <= n; i++) {
482 esyslog(
"ERROR: undefined pixel color in XPM: %d %d '%s'", x, y, s);
485 if (strncmp(Xpm[i + 1], s, c) == 0) {
486 if (i == NoneColorIndex)
488 SetIndex(x, y, (IgnoreNone && i > NoneColorIndex) ? i - 1 : i);
542 for (
int ix = 0; ix < Bitmap.
width; ix++) {
543 for (
int iy = 0; iy < Bitmap.
height; iy++) {
544 if (!Overlay || Bitmap.
bitmap[Bitmap.
width * iy + ix] != 0)
551 Take(Bitmap, &Indexes, ColorFg, ColorBg);
552 for (
int ix = 0; ix < Bitmap.
width; ix++) {
553 for (
int iy = 0; iy < Bitmap.
height; iy++) {
554 if (!Overlay || Bitmap.
bitmap[Bitmap.
width * iy + ix] != 0)
570 if (!
Intersects(x, y, x + cw - 1, y + ch - 1))
577 if ((Alignment &
taLeft) != 0) {
581 else if ((Alignment &
taRight) != 0) {
589 x += (
Width - w) / 2;
593 if ((Alignment &
taTop) != 0)
595 else if ((Alignment &
taBottom) != 0) {
614 if (
Covers(x1, y1, x2, y2))
625 for (
int y = y1; y <= y2; y++) {
626 for (
int x = x1; x <= x2; x++)
639 int cx = (x1 + x2) / 2;
640 int cy = (y1 + y2) / 2;
641 switch (abs(Quadrants)) {
642 case 0: rx /= 2; ry /= 2;
break;
643 case 1: cx = x1; cy = y2;
break;
644 case 2: cx = x2; cy = y2;
break;
645 case 3: cx = x2; cy = y1;
break;
646 case 4: cx = x1; cy = y1;
break;
647 case 5: cx = x1; ry /= 2;
break;
648 case 6: cy = y2; rx /= 2;
break;
649 case 7: cx = x2; ry /= 2;
break;
650 case 8: cy = y1; rx /= 2;
break;
653 int TwoASquare =
max(1, 2 * rx * rx);
654 int TwoBSquare =
max(1, 2 * ry * ry);
657 int XChange = ry * ry * (1 - 2 * rx);
658 int YChange = rx * rx;
659 int EllipseError = 0;
660 int StoppingX = TwoBSquare * rx;
662 while (StoppingX >= StoppingY) {
671 case 6:
DrawRectangle(cx - x, cy - y, cx + x, cy - y,
Color);
if (Quadrants == 6)
break;
680 StoppingY += TwoASquare;
681 EllipseError += YChange;
682 YChange += TwoASquare;
683 if (2 * EllipseError + XChange > 0) {
685 StoppingX -= TwoBSquare;
686 EllipseError += XChange;
687 XChange += TwoBSquare;
693 YChange = rx * rx * (1 - 2 * ry);
696 StoppingY = TwoASquare * ry;
697 while (StoppingX <= StoppingY) {
706 case 6:
DrawRectangle(cx - x, cy - y, cx + x, cy - y,
Color);
if (Quadrants == 6)
break;
715 StoppingX += TwoBSquare;
716 EllipseError += XChange;
717 XChange += TwoBSquare;
718 if (2 * EllipseError + YChange > 0) {
720 StoppingY -= TwoASquare;
721 EllipseError += YChange;
722 YChange += TwoASquare;
731 bool upper = Type & 0x01;
732 bool falling = Type & 0x02;
733 bool vertical = Type & 0x04;
735 for (
int y = y1; y <= y2; y++) {
736 double c = cos((y - y1) * M_PI / (y2 - y1 + 1));
739 int x = int((x2 - x1 + 1) * c / 2);
740 if (upper && !falling || !upper && falling)
747 for (
int x = x1; x <= x2; x++) {
748 double c = cos((x - x1) * M_PI / (x2 - x1 + 1));
751 int y = int((y2 - y1 + 1) * c / 2);
767 int NewBpp = Palette.
Bpp();
768 if (
Bpp() == 4 && NewBpp == 2) {
771 bitmap[i] = (p >> 2) | ((p & 0x03) != 0);
774 else if (
Bpp() == 8) {
778 bitmap[i] = (p >> 6) | ((p & 0x30) != 0);
781 else if (NewBpp == 4) {
806 int MaxNewColors = (NewBpp == 4) ? 16 : 4;
808 for (
int i = 0; i < MaxNewColors; i++) {
811 for (
int n = 0; n < NumOldColors; n++) {
826 for (
int n = 0; n < NumOldColors; n++) {
842 int w =
max(1,
int(round(
Width() * FactorX)));
843 int h =
max(1,
int(round(
Height() * FactorY)));
847 if (!AntiAlias || FactorX <= 1.0 && FactorY <= 1.0) {
852 for (
int y = 0; y < b->
Height(); y++) {
856 for (
int x = 0; x < b->
Width(); x++) {
857 *Dest++ = SourceRow[SourceX >> 16];
861 DestRow += b->
Width();
869 for (
int y = 0; y < b->
Height(); y++) {
871 int sy =
min(SourceY >> 16,
Height() - 2);
872 uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF);
873 for (
int x = 0; x < b->
Width(); x++) {
874 int sx =
min(SourceX >> 16,
Width() - 2);
875 uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF);
1037 else if (
Layer >= 0) {
1151 :
cPixmap(Layer, ViewPort, DrawPort)
1199 Source.
Shift(Delta);
1202 if (Pixmap->
Layer() == 0)
1203 Copy(Pixmap, Source, Dest);
1205 Render(Pixmap, Source, Dest);
1222 if (Pixmap->
Layer() == 0)
1223 Copy(Pixmap, Source, Dest);
1225 Render(Pixmap, Source, Dest);
1240 ps -= Point.
Y() * ws;
1244 for (
int y = r.
Height(); y-- > 0; ) {
1265 if (
DrawPort().Size().Contains(Point)) {
1279 if (
DrawPort().Size().Contains(Point)) {
1283 data[p] = (
data[p] & 0x00FFFFFF) | ((((
data[p] >> 24) * (255 -
Alpha)) << 16) & 0xFF000000);
1299 bool UseColors = ColorFg || ColorBg;
1302 for (
int y = r.
Top(); y <= r.
Bottom(); y++) {
1304 for (
int x = r.
Left(); x <= r.
Right(); x++) {
1305 tIndex Index = *Bitmap.
Data(x - Point.
X(), y - Point.
Y());
1306 if (Index || !Overlay) {
1308 *cd = Index ? ColorFg : ColorBg;
1310 *cd = Bitmap.
Color(Index);
1329 int cw = Width ? Width : w;
1330 int ch = Height ? Height : h;
1331 cRect r(x, y, cw, ch);
1334 if (Width || Height) {
1337 if ((Alignment &
taLeft) != 0) {
1341 else if ((Alignment &
taRight) != 0) {
1349 x += (Width - w) / 2;
1353 if ((Alignment &
taTop) != 0)
1355 else if ((Alignment &
taBottom) != 0) {
1361 y += (Height - h) / 2;
1365 Font->
DrawText(
this, x, y, s, ColorFg, ColorBg, limit);
1379 for (
int y = r.
Height(); y-- > 0; ) {
1385 for (
int x = r.
Width(); x-- > 0; ) {
1401 int x1 = Rect.
Left();
1402 int y1 = Rect.
Top();
1403 int x2 = Rect.
Right();
1409 int cx = (x1 + x2) / 2;
1410 int cy = (y1 + y2) / 2;
1411 switch (abs(Quadrants)) {
1412 case 0: rx /= 2; ry /= 2;
break;
1413 case 1: cx = x1; cy = y2;
break;
1414 case 2: cx = x2; cy = y2;
break;
1415 case 3: cx = x2; cy = y1;
break;
1416 case 4: cx = x1; cy = y1;
break;
1417 case 5: cx = x1; ry /= 2;
break;
1418 case 6: cy = y2; rx /= 2;
break;
1419 case 7: cx = x2; ry /= 2;
break;
1420 case 8: cy = y1; rx /= 2;
break;
1423 int TwoASquare =
max(1, 2 * rx * rx);
1424 int TwoBSquare =
max(1, 2 * ry * ry);
1427 int XChange = ry * ry * (1 - 2 * rx);
1428 int YChange = rx * rx;
1429 int EllipseError = 0;
1430 int StoppingX = TwoBSquare * rx;
1434 while (StoppingX >= StoppingY) {
1436 switch (Quadrants) {
1444 case 6:
DrawRectangle(
cRect(cx - x, cy - y, 2 * x + ax + 1, 1), Color);
if (Quadrants == 6)
break;
1454 uint8_t intensity = abs(255 * (
long int)EllipseError / XChange);
1455 if (EllipseError >= 0) {
1456 intensity = 255 - intensity;
1461 switch (Quadrants) {
1468 case 7:
DrawRectangle(
cRect( cx - x + 1 - Delta, cy + ay + y, x + Delta, 1), Color);
1481 case 6:
DrawRectangle(
cRect( cx - x - Delta + 1, cy - y, 2 * (x + Delta) + ax - 1, 1), Color);
1486 case 8:
DrawRectangle(
cRect( cx - x - Delta + 1, cy + y, 2 * (x + Delta) + ax - 1 , 1), Color);
1490 case -1:
DrawRectangle(
cRect( cx + x + 1 + Delta, cy - y, rx - (x + Delta), 1), Color);
1499 case -4:
DrawRectangle(
cRect( cx + x + 1 + Delta, cy + y, rx - x - Delta, 1), Color);
1506 StoppingY += TwoASquare;
1507 EllipseError += YChange;
1508 YChange += TwoASquare;
1509 if (2 * EllipseError + XChange > 0) {
1511 StoppingX -= TwoBSquare;
1512 EllipseError += XChange;
1513 XChange += TwoBSquare;
1520 YChange = rx * rx * (1 - 2 * ry);
1523 StoppingY = TwoASquare * ry;
1524 while (StoppingX <= StoppingY) {
1526 switch (Quadrants) {
1534 case 6:
DrawRectangle(
cRect(cx - x, cy - y, 2 * x + ax + 1, 1), Color);
if (Quadrants == 6)
break;
1544 uint8_t intensity = abs(255 * (
long int)EllipseError / YChange);
1545 if (EllipseError >= 0) {
1546 intensity = 255 - intensity;
1551 switch (Quadrants) {
1552 case 5:
DrawRectangle(
cRect( cx + x, cy + ay + 1 + ymax, 1, y - ymax - Delta), Color);
1558 case 7:
DrawRectangle(
cRect( cx - x, cy + ay + 1 + ymax, 1, y - ymax - Delta), Color);
1571 case 6:
DrawRectangle(
cRect( cx + x + ax, cy - y + Delta, 1, y - ymax - Delta), Color);
1588 case -3:
DrawRectangle(
cRect( cx - x, cy + y + 2 - Delta, 1, ry - y - 1 + Delta), Color);
1591 case -4:
DrawRectangle(
cRect( cx + x, cy + y + 2 - Delta, 1, ry - y - 1 + Delta), Color);
1598 StoppingX += TwoBSquare;
1599 EllipseError += XChange;
1600 XChange += TwoBSquare;
1601 if (2 * EllipseError + YChange > 0) {
1603 StoppingY -= TwoASquare;
1604 EllipseError += YChange;
1605 YChange += TwoASquare;
1608 if (AntiAliased && Quadrants < 0 ) {
1609 switch (Quadrants) {
1625 bool upper = Type & 0x01;
1626 bool falling = Type & 0x02;
1627 bool vertical = Type & 0x04;
1628 int x1 = Rect.
Left();
1629 int y1 = Rect.
Top();
1630 int x2 = Rect.
Right();
1632 int w = Rect.
Width();
1635 uint8_t intensity = 0;
1642 for (
int y = 1; y <= (y2 - y1) / 2; y++) {
1643 double c = cos(y * M_PI / (y2 - y1));
1645 double wc = (w * c + (w & 1)) / 2;
1646 intensity = 255 * fabs(wc - floor(wc));
1650 int x = (x1 + x2 + w * c + 1) / 2;
1651 if (upper && !falling || !upper && falling) {
1678 if ((upper && !falling) || (!upper && falling))
1682 for (
int x = 1; x <= (x2 - x1) / 2; x++) {
1683 double c = cos(x * M_PI / (x2 - x1));
1685 double hc = (h * c + (h & 1)) / 2;
1686 intensity = 255 * fabs(hc - floor(hc));
1690 int y = (y1 + y2 + h * c + 1) / 2;
1732 int a = pm->Alpha();
1733 int ws = pm->DrawPort().
Width();
1737 for (
int y = d.
Height(); y-- > 0; ) {
1740 for (
int x = d.
Width(); x-- > 0; ) {
1766 int ws = pm->DrawPort().
Width();
1771 for (
int y = d.
Height(); y-- > 0; ) {
1802 for (
int y = d.
Height(); y-- > 0; ) {
1832 "bpp not supported",
1860 for (
int i = 0; i <
Osds.
Size(); i++) {
1878 for (
int i = 0; i <
Osds.
Size(); i++) {
1879 if (
Osds[i] ==
this) {
1882 Osds[0]->SetActive(
true);
1932 if (Pixmap->
Layer() >= 0)
1939 esyslog(
"ERROR: attempt to destroy an unregistered pixmap");
1965 if (!pm->DirtyViewPort().IsEmpty()) {
1967 d.
Combine(pm->DirtyViewPort());
1976 static cRect OldDirty;
1979 OldDirty = NewDirty;
1988 if (pm->Layer() == Layer)
1995 static tColor DirtyIndicatorColors[] = { 0x7FFFFF00, 0x7F00FFFF };
1996 static int DirtyIndicatorIndex = 0;
1997 DirtyIndicator.
Fill(DirtyIndicatorColors[DirtyIndicatorIndex]);
1998 DirtyIndicatorIndex = 1 - DirtyIndicatorIndex;
2012 for (
int i = 0; i < NumAreas; i++) {
2013 if (Areas[i].x1 > Areas[i].x2 || Areas[i].y1 > Areas[i].y2 || Areas[i].x1 < 0 || Areas[i].y1 < 0)
2015 for (
int j = i + 1; j < NumAreas; j++) {
2016 if (Areas[i].Intersects(Areas[j])) {
2021 if (Areas[i].bpp == 32) {
2032 if (Result ==
oeOk) {
2052 for (
int i = 0; i < NumAreas; i++) {
2068 cRect r(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
2112 pixmaps[0]->DrawImage(Point, Image);
2118 pixmaps[0]->DrawImage(Point, ImageHandle);
2134 pixmaps[0]->DrawBitmap(
cPoint(x, y), Bitmap, ColorFg, ColorBg, Overlay);
2137 bitmaps[i]->
DrawBitmap(x, y, Bitmap, ColorFg, ColorBg, ReplacePalette, Overlay);
2145 b = b->
Scaled(FactorX, FactorY, AntiAlias);
2164 pixmaps[0]->DrawRectangle(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color);
2174 pixmaps[0]->DrawEllipse(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color, Quadrants);
2184 pixmaps[0]->DrawSlope(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color, Type);
2219 esyslog(
"ERROR: attempt to open OSD while it is already open - using dummy OSD!");
2231 esyslog(
"ERROR: no OSD provider available - using dummy OSD!");
2232 return new cOsd(Left, Top, 999);
2257 dsyslog(
"OSD size changed to %dx%d @ %g", Width, Height, Aspect);
2276 esyslog(
"ERROR: no OSD provider available in call to SupportsTrueColor()");
2296 delete images[ImageHandle];
2297 images[ImageHandle] = NULL;
2305 return images[ImageHandle];
2371 for (
int i = 0; i <
shown; i++)