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;
148 if (
color[i] == Color)
159 return numColors - 1;
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;
202 int n =
Index(Color);
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);
531 for (
int ix = 0; ix < Bitmap.
width; ix++) {
532 for (
int iy = 0; iy < Bitmap.
height; iy++) {
533 if (!Overlay || Bitmap.
bitmap[Bitmap.
width * iy + ix] != 0)
540 Take(Bitmap, &Indexes, ColorFg, ColorBg);
541 for (
int ix = 0; ix < Bitmap.
width; ix++) {
542 for (
int iy = 0; iy < Bitmap.
height; iy++) {
543 if (!Overlay || Bitmap.
bitmap[Bitmap.
width * iy + ix] != 0)
554 int w = Font->
Width(s);
557 int cw = Width ? Width : w;
558 int ch = Height ? Height : h;
559 if (!
Intersects(x, y, x + cw - 1, y + ch - 1))
563 if (Width || Height) {
566 if ((Alignment &
taLeft) != 0) {
570 else if ((Alignment &
taRight) != 0) {
578 x += (Width - w) / 2;
582 if ((Alignment &
taTop) != 0)
584 else if ((Alignment &
taBottom) != 0) {
590 y += (Height - h) / 2;
596 Font->
DrawText(
this, x, y, s, ColorFg, ColorBg, limit);
603 if (
Covers(x1, y1, x2, y2))
614 for (
int y = y1; y <= y2; y++) {
615 for (
int x = x1; x <= x2; x++)
628 int cx = (x1 + x2) / 2;
629 int cy = (y1 + y2) / 2;
630 switch (abs(Quadrants)) {
631 case 0: rx /= 2; ry /= 2;
break;
632 case 1: cx = x1; cy = y2;
break;
633 case 2: cx = x2; cy = y2;
break;
634 case 3: cx = x2; cy = y1;
break;
635 case 4: cx = x1; cy = y1;
break;
636 case 5: cx = x1; ry /= 2;
break;
637 case 6: cy = y2; rx /= 2;
break;
638 case 7: cx = x2; ry /= 2;
break;
639 case 8: cy = y1; rx /= 2;
break;
642 int TwoASquare =
max(1, 2 * rx * rx);
643 int TwoBSquare =
max(1, 2 * ry * ry);
646 int XChange = ry * ry * (1 - 2 * rx);
647 int YChange = rx * rx;
648 int EllipseError = 0;
649 int StoppingX = TwoBSquare * rx;
651 while (StoppingX >= StoppingY) {
654 case 1:
DrawRectangle(cx, cy - y, cx + x, cy - y, Color);
break;
656 case 2:
DrawRectangle(cx - x, cy - y, cx, cy - y, Color);
break;
657 case 3:
DrawRectangle(cx - x, cy + y, cx, cy + y, Color);
break;
658 case 4:
DrawRectangle(cx, cy + y, cx + x, cy + y, Color);
break;
660 case 6:
DrawRectangle(cx - x, cy - y, cx + x, cy - y, Color);
if (Quadrants == 6)
break;
661 case 8:
DrawRectangle(cx - x, cy + y, cx + x, cy + y, Color);
break;
662 case -1:
DrawRectangle(cx + x, cy - y, x2, cy - y, Color);
break;
663 case -2:
DrawRectangle(x1, cy - y, cx - x, cy - y, Color);
break;
664 case -3:
DrawRectangle(x1, cy + y, cx - x, cy + y, Color);
break;
665 case -4:
DrawRectangle(cx + x, cy + y, x2, cy + y, Color);
break;
669 StoppingY += TwoASquare;
670 EllipseError += YChange;
671 YChange += TwoASquare;
672 if (2 * EllipseError + XChange > 0) {
674 StoppingX -= TwoBSquare;
675 EllipseError += XChange;
676 XChange += TwoBSquare;
682 YChange = rx * rx * (1 - 2 * ry);
685 StoppingY = TwoASquare * ry;
686 while (StoppingX <= StoppingY) {
689 case 1:
DrawRectangle(cx, cy - y, cx + x, cy - y, Color);
break;
691 case 2:
DrawRectangle(cx - x, cy - y, cx, cy - y, Color);
break;
692 case 3:
DrawRectangle(cx - x, cy + y, cx, cy + y, Color);
break;
693 case 4:
DrawRectangle(cx, cy + y, cx + x, cy + y, Color);
break;
695 case 6:
DrawRectangle(cx - x, cy - y, cx + x, cy - y, Color);
if (Quadrants == 6)
break;
696 case 8:
DrawRectangle(cx - x, cy + y, cx + x, cy + y, Color);
break;
697 case -1:
DrawRectangle(cx + x, cy - y, x2, cy - y, Color);
break;
698 case -2:
DrawRectangle(x1, cy - y, cx - x, cy - y, Color);
break;
699 case -3:
DrawRectangle(x1, cy + y, cx - x, cy + y, Color);
break;
700 case -4:
DrawRectangle(cx + x, cy + y, x2, cy + y, Color);
break;
704 StoppingX += TwoBSquare;
705 EllipseError += XChange;
706 XChange += TwoBSquare;
707 if (2 * EllipseError + YChange > 0) {
709 StoppingY -= TwoASquare;
710 EllipseError += YChange;
711 YChange += TwoASquare;
720 bool upper = Type & 0x01;
721 bool falling = Type & 0x02;
722 bool vertical = Type & 0x04;
724 for (
int y = y1; y <= y2; y++) {
725 double c = cos((y - y1) * M_PI / (y2 - y1 + 1));
728 int x = int((x2 - x1 + 1) * c / 2);
729 if (upper && !falling || !upper && falling)
736 for (
int x = x1; x <= x2; x++) {
737 double c = cos((x - x1) * M_PI / (x2 - x1 + 1));
740 int y = int((y2 - y1 + 1) * c / 2);
756 int NewBpp = Palette.
Bpp();
757 if (
Bpp() == 4 && NewBpp == 2) {
760 bitmap[i] = (p >> 2) | ((p & 0x03) != 0);
763 else if (
Bpp() == 8) {
767 bitmap[i] = (p >> 6) | ((p & 0x30) != 0);
770 else if (NewBpp == 4) {
795 int MaxNewColors = (NewBpp == 4) ? 16 : 4;
797 for (
int i = 0; i < MaxNewColors; i++) {
800 for (
int n = 0; n < NumOldColors; n++) {
809 NewPalette.
SetColor(i, Colors[Index]);
815 for (
int n = 0; n < NumOldColors; n++) {
817 Map[n] = NewPalette.
Index(Colors[n]);
834 if (!AntiAlias || FactorX <= 1.0 && FactorY <= 1.0) {
839 for (
int y = 0; y < b->
Height(); y++) {
843 for (
int x = 0; x < b->
Width(); x++) {
844 *Dest++ = SourceRow[SourceX >> 16];
848 DestRow += b->
Width();
856 for (
int y = 0; y < b->
Height(); y++) {
858 int sy =
min(SourceY >> 16,
Height() - 2);
859 uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF);
860 for (
int x = 0; x < b->
Width(); x++) {
861 int sx =
min(SourceX >> 16,
Width() - 2);
862 uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF);
887 return Left() <= Point.
X() &&
888 Top() <= Point.
Y() &&
937 Set(Point.
X(), Point.
Y(), 1, 1);
961 esyslog(
"ERROR: pixmap layer %d limited to %d", Layer,
layer);
1017 if (Layer !=
layer) {
1018 if (Layer > 0 ||
layer > 0)
1029 if (Alpha !=
alpha) {
1102 memcpy(
data, Data, l);
1130 :
cPixmap(Layer, ViewPort, DrawPort)
1177 Source.
Shift(Delta);
1180 if (Pixmap->
Layer() == 0)
1181 Copy(Pixmap, Source, Dest);
1183 Render(Pixmap, Source, Dest);
1200 if (Pixmap->
Layer() == 0)
1201 Copy(Pixmap, Source, Dest);
1203 Render(Pixmap, Source, Dest);
1218 ps -= Point.
Y() * ws;
1222 for (
int y = r.
Height(); y-- > 0; ) {
1243 if (
DrawPort().Size().Contains(Point)) {
1259 bool UseColors = ColorFg || ColorBg;
1262 for (
int y = r.
Top(); y <= r.
Bottom(); y++) {
1264 for (
int x = r.
Left(); x <= r.
Right(); x++) {
1265 tIndex Index = *Bitmap.
Data(x - Point.
X(), y - Point.
Y());
1266 if (Index || !Overlay) {
1268 *cd = Index ? ColorFg : ColorBg;
1270 *cd = Bitmap.
Color(Index);
1286 int w = Font->
Width(s);
1289 int cw = Width ? Width : w;
1290 int ch = Height ? Height : h;
1291 cRect r(x, y, cw, ch);
1294 if (Width || Height) {
1297 if ((Alignment &
taLeft) != 0) {
1301 else if ((Alignment &
taRight) != 0) {
1309 x += (Width - w) / 2;
1313 if ((Alignment &
taTop) != 0)
1315 else if ((Alignment &
taBottom) != 0) {
1321 y += (Height - h) / 2;
1325 Font->
DrawText(
this, x, y, s, ColorFg, ColorBg, limit);
1339 for (
int y = r.
Height(); y-- > 0; ) {
1345 for (
int x = r.
Width(); x-- > 0; ) {
1363 int x1 = Rect.
Left();
1364 int y1 = Rect.
Top();
1365 int x2 = Rect.
Right();
1369 int cx = (x1 + x2) / 2;
1370 int cy = (y1 + y2) / 2;
1371 switch (abs(Quadrants)) {
1372 case 0: rx /= 2; ry /= 2;
break;
1373 case 1: cx = x1; cy = y2;
break;
1374 case 2: cx = x2; cy = y2;
break;
1375 case 3: cx = x2; cy = y1;
break;
1376 case 4: cx = x1; cy = y1;
break;
1377 case 5: cx = x1; ry /= 2;
break;
1378 case 6: cy = y2; rx /= 2;
break;
1379 case 7: cx = x2; ry /= 2;
break;
1380 case 8: cy = y1; rx /= 2;
break;
1383 int TwoASquare =
max(1, 2 * rx * rx);
1384 int TwoBSquare =
max(1, 2 * ry * ry);
1387 int XChange = ry * ry * (1 - 2 * rx);
1388 int YChange = rx * rx;
1389 int EllipseError = 0;
1390 int StoppingX = TwoBSquare * rx;
1392 while (StoppingX >= StoppingY) {
1393 switch (Quadrants) {
1401 case 6:
DrawRectangle(
cRect(cx - x, cy - y, 2 * x + 1, 1), Color);
if (Quadrants == 6)
break;
1410 StoppingY += TwoASquare;
1411 EllipseError += YChange;
1412 YChange += TwoASquare;
1413 if (2 * EllipseError + XChange > 0) {
1415 StoppingX -= TwoBSquare;
1416 EllipseError += XChange;
1417 XChange += TwoBSquare;
1423 YChange = rx * rx * (1 - 2 * ry);
1426 StoppingY = TwoASquare * ry;
1427 while (StoppingX <= StoppingY) {
1428 switch (Quadrants) {
1436 case 6:
DrawRectangle(
cRect(cx - x, cy - y, 2 * x + 1, 1), Color);
if (Quadrants == 6)
break;
1445 StoppingX += TwoBSquare;
1446 EllipseError += XChange;
1447 XChange += TwoBSquare;
1448 if (2 * EllipseError + YChange > 0) {
1450 StoppingY -= TwoASquare;
1451 EllipseError += YChange;
1452 YChange += TwoASquare;
1464 bool upper = Type & 0x01;
1465 bool falling = Type & 0x02;
1466 bool vertical = Type & 0x04;
1467 int x1 = Rect.
Left();
1468 int y1 = Rect.
Top();
1469 int x2 = Rect.
Right();
1471 int w = Rect.
Width();
1474 for (
int y = y1; y <= y2; y++) {
1475 double c = cos((y - y1) * M_PI / h);
1478 int x = (x1 + x2) / 2 +
int(w * c / 2);
1479 if (upper && !falling || !upper && falling)
1486 for (
int x = x1; x <= x2; x++) {
1487 double c = cos((x - x1) * M_PI / w);
1490 int y = (y1 + y2) / 2 +
int(h * c / 2);
1505 if (
const cPixmapMemory *pm = dynamic_cast<const cPixmapMemory *>(Pixmap)) {
1512 int a = pm->Alpha();
1513 int ws = pm->DrawPort().
Width();
1517 for (
int y = d.
Height(); y-- > 0; ) {
1520 for (
int x = d.
Width(); x-- > 0; ) {
1539 if (
const cPixmapMemory *pm = dynamic_cast<const cPixmapMemory *>(Pixmap)) {
1546 int ws = pm->DrawPort().
Width();
1551 for (
int y = d.
Height(); y-- > 0; ) {
1567 if (&Source == &cRect::Null)
1582 for (
int y = d.
Height(); y-- > 0; ) {
1612 "bpp not supported",
1639 for (
int i = 0; i <
Osds.
Size(); i++) {
1657 for (
int i = 0; i <
Osds.
Size(); i++) {
1658 if (
Osds[i] ==
this) {
1712 esyslog(
"ERROR: attempt to destroy an unregistered pixmap");
1738 if (!pm->DirtyViewPort().IsEmpty()) {
1740 d.
Combine(pm->DirtyViewPort());
1749 static cRect OldDirty;
1752 OldDirty = NewDirty;
1760 if (pm->Layer() == Layer)
1767 static tColor DirtyIndicatorColors[] = { 0x7FFFFF00, 0x7F00FFFF };
1768 static int DirtyIndicatorIndex = 0;
1769 DirtyIndicator.
Fill(DirtyIndicatorColors[DirtyIndicatorIndex]);
1770 DirtyIndicatorIndex = 1 - DirtyIndicatorIndex;
1783 for (
int i = 0; i < NumAreas; i++) {
1784 if (Areas[i].x1 > Areas[i].x2 || Areas[i].y1 > Areas[i].y2 || Areas[i].x1 < 0 || Areas[i].y1 < 0)
1786 for (
int j = i + 1; j < NumAreas; j++) {
1787 if (Areas[i].Intersects(Areas[j])) {
1792 if (Areas[i].bpp == 32) {
1803 if (Result ==
oeOk) {
1820 for (
int i = 0; i < NumAreas; i++) {
1836 cRect r(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
1880 pixmaps[0]->DrawImage(Point, Image);
1886 pixmaps[0]->DrawImage(Point, ImageHandle);
1902 pixmaps[0]->DrawBitmap(
cPoint(x, y), Bitmap, ColorFg, ColorBg, Overlay);
1905 bitmaps[i]->
DrawBitmap(x, y, Bitmap, ColorFg, ColorBg, ReplacePalette, Overlay);
1912 pixmaps[0]->DrawText(
cPoint(x, y), s, ColorFg, ColorBg, Font, Width, Height, Alignment);
1915 bitmaps[i]->
DrawText(x, y, s, ColorFg, ColorBg, Font, Width, Height, Alignment);
1922 pixmaps[0]->DrawRectangle(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color);
1932 pixmaps[0]->DrawEllipse(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color, Quadrants);
1942 pixmaps[0]->DrawSlope(
cRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), Color, Type);
1976 esyslog(
"ERROR: attempt to open OSD while it is already open - using dummy OSD!");
1978 cOsd *ActiveOsd = cOsd::Osds.
Size() ? cOsd::Osds[0] : NULL;
1980 if (Osd == cOsd::Osds[0]) {
1988 esyslog(
"ERROR: no OSD provider available - using dummy OSD!");
1989 return new cOsd(Left, Top, 999);
2013 dsyslog(
"OSD size changed to %dx%d @ %g", Width, Height, Aspect);
2023 esyslog(
"ERROR: no OSD provider available in call to SupportsTrueColor()");
2043 delete images[ImageHandle];
2044 images[ImageHandle] = NULL;
2052 return images[ImageHandle];
2090 Set(Osd, Left, Top, Width, Height, Text, Font, ColorFg, ColorBg);
2118 for (
int i = 0; i <
shown; i++)