wl_backend: implement all background image fill modes
- tpixmap (Tiled): repeat image across screen - spixmap (Scaled): stretch to exact screen dimensions - cpixmap (Centered): place at center with background color fill - mpixmap (Maximized): scale preserving aspect ratio, letterbox - fpixmap (Filled): scale preserving aspect ratio, crop to fill All modes now use RSmoothScaleImage for quality, respect the background color (3rd texture argument) for uncovered areas, and handle transparent images via RCombineImageWithColor.
This commit is contained in:
parent
07022840ac
commit
94054aeec8
|
|
@ -7775,28 +7775,99 @@ static void wl_set_desktop_background(WScreen *scr, const char *texture_desc)
|
|||
strcasecmp(type, "spixmap") == 0 ||
|
||||
strcasecmp(type, "mpixmap") == 0 ||
|
||||
strcasecmp(type, "cpixmap") == 0 ||
|
||||
strcasecmp(type, "fpixmap") == 0 ||
|
||||
strcasecmp(type, "tpixmap") == 0) &&
|
||||
WMGetPropListItemCount(texpl) >= 2) {
|
||||
const char *path = WMGetFromPLString(WMGetFromPLArray(texpl, 1));
|
||||
/* Background color (3rd argument, optional) */
|
||||
RColor bgcolor = {0, 0, 0, 255};
|
||||
if (WMGetPropListItemCount(texpl) >= 3) {
|
||||
const char *cstr = WMGetFromPLString(WMGetFromPLArray(texpl, 2));
|
||||
if (cstr) parse_color_to_rcolor(scr, cstr, &bgcolor);
|
||||
}
|
||||
if (path) {
|
||||
RImage *img = RLoadImage(rc, path, 0);
|
||||
if (img) {
|
||||
if (type[0] == 's' || type[0] == 'S') {
|
||||
/* Scale to fill */
|
||||
bg = RScaleImage(img, width, height);
|
||||
} else if (type[0] == 'c' || type[0] == 'C') {
|
||||
/* Center */
|
||||
/* Combine with background color if image has alpha */
|
||||
if (img->format == RRGBAFormat)
|
||||
RCombineImageWithColor(img, &bgcolor);
|
||||
|
||||
char mode = (type[0] >= 'a' && type[0] <= 'z') ? type[0] - 32 : type[0];
|
||||
if (mode == 'S') {
|
||||
/* Scaled: stretch to exact screen size */
|
||||
bg = RSmoothScaleImage(img, width, height);
|
||||
} else if (mode == 'F') {
|
||||
/* Filled: scale preserving aspect, fill screen (crop) */
|
||||
int w, h;
|
||||
if (img->width * height > img->height * width) {
|
||||
w = (height * img->width) / img->height;
|
||||
h = height;
|
||||
} else {
|
||||
w = width;
|
||||
h = (width * img->height) / img->width;
|
||||
}
|
||||
RImage *scaled = RSmoothScaleImage(img, w, h);
|
||||
if (scaled) {
|
||||
bg = RCreateImage(width, height, 0);
|
||||
if (bg) {
|
||||
RClearImage(bg, &bgcolor);
|
||||
int sx = (scaled->width - width) / 2;
|
||||
int sy = (scaled->height - height) / 2;
|
||||
RCopyArea(bg, scaled, sx, sy, width, height, 0, 0);
|
||||
}
|
||||
RReleaseImage(scaled);
|
||||
}
|
||||
} else if (mode == 'M') {
|
||||
/* Maximized: scale preserving aspect, fit inside (letterbox) */
|
||||
int w, h;
|
||||
if (img->width * height > img->height * width) {
|
||||
w = width;
|
||||
h = (width * img->height) / img->width;
|
||||
} else {
|
||||
w = (height * img->width) / img->height;
|
||||
h = height;
|
||||
}
|
||||
RImage *scaled = RSmoothScaleImage(img, w, h);
|
||||
if (scaled) {
|
||||
bg = RCreateImage(width, height, 0);
|
||||
if (bg) {
|
||||
RClearImage(bg, &bgcolor);
|
||||
int dx = (width - scaled->width) / 2;
|
||||
int dy = (height - scaled->height) / 2;
|
||||
RCombineArea(bg, scaled, 0, 0, scaled->width, scaled->height, dx, dy);
|
||||
}
|
||||
RReleaseImage(scaled);
|
||||
}
|
||||
} else if (mode == 'C') {
|
||||
/* Centered: place at center, no scaling */
|
||||
bg = RCreateImage(width, height, 0);
|
||||
if (bg) {
|
||||
RColor black = {0, 0, 0, 255};
|
||||
RClearImage(bg, &black);
|
||||
int x = (width - img->width) / 2;
|
||||
int y = (height - img->height) / 2;
|
||||
RCombineArea(bg, img, 0, 0, img->width, img->height, x, y);
|
||||
RClearImage(bg, &bgcolor);
|
||||
int dx = (width - img->width) / 2;
|
||||
int dy = (height - img->height) / 2;
|
||||
/* Handle images larger than screen */
|
||||
int sx = 0, sy = 0, cw = img->width, ch = img->height;
|
||||
if (dx < 0) { sx = -dx; dx = 0; cw = width; }
|
||||
if (dy < 0) { sy = -dy; dy = 0; ch = height; }
|
||||
RCombineArea(bg, img, sx, sy, cw, ch, dx, dy);
|
||||
}
|
||||
} else if (mode == 'T') {
|
||||
/* Tiled: repeat the image */
|
||||
bg = RCreateImage(width, height, 0);
|
||||
if (bg) {
|
||||
for (int ty = 0; ty < height; ty += img->height) {
|
||||
for (int tx = 0; tx < width; tx += img->width) {
|
||||
int cw = img->width;
|
||||
int ch = img->height;
|
||||
if (tx + cw > width) cw = width - tx;
|
||||
if (ty + ch > height) ch = height - ty;
|
||||
RCombineArea(bg, img, 0, 0, cw, ch, tx, ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Default: scale to fill */
|
||||
bg = RScaleImage(img, width, height);
|
||||
/* Default (plain "pixmap"): scale to fill */
|
||||
bg = RSmoothScaleImage(img, width, height);
|
||||
}
|
||||
RReleaseImage(img);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue