mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Merge branch 'work/jinliu/cursor-scaling' into 'main'
cursor: scale cursors to the requested size on env var "XCURSOR_RESIZED=true" See merge request wayland/wayland!440
This commit is contained in:
commit
72a32cc5f2
1 changed files with 85 additions and 4 deletions
|
|
@ -29,6 +29,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -438,8 +439,45 @@ xcursor_read_image(FILE *file,
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct xcursor_image *
|
||||||
|
xcursor_resize_image (struct xcursor_image *src, int size)
|
||||||
|
{
|
||||||
|
uint32_t dest_y, dest_x;
|
||||||
|
double scale = (double) size / src->size;
|
||||||
|
struct xcursor_image *dest;
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
return NULL;
|
||||||
|
if (size > XCURSOR_IMAGE_MAX_SIZE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dest = xcursor_image_create((int) (src->width * scale),
|
||||||
|
(int) (src->height * scale));
|
||||||
|
if (!dest)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dest->size = (uint32_t) size;
|
||||||
|
dest->xhot = (uint32_t) (src->xhot * scale);
|
||||||
|
dest->yhot = (uint32_t) (src->yhot * scale);
|
||||||
|
dest->delay = src->delay;
|
||||||
|
|
||||||
|
for (dest_y = 0; dest_y < dest->height; dest_y++)
|
||||||
|
{
|
||||||
|
uint32_t src_y = (uint32_t) (dest_y / scale);
|
||||||
|
uint32_t *src_row = src->pixels + (src_y * src->width);
|
||||||
|
uint32_t *dest_row = dest->pixels + (dest_y * dest->width);
|
||||||
|
for (dest_x = 0; dest_x < dest->width; dest_x++)
|
||||||
|
{
|
||||||
|
uint32_t src_x = (uint32_t) (dest_x / scale);
|
||||||
|
dest_row[dest_x] = src_row[src_x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
static struct xcursor_images *
|
static struct xcursor_images *
|
||||||
xcursor_xc_file_load_images(FILE *file, int size)
|
xcursor_xc_file_load_images(FILE *file, int size, bool resize)
|
||||||
{
|
{
|
||||||
struct xcursor_file_header *file_header;
|
struct xcursor_file_header *file_header;
|
||||||
uint32_t best_size;
|
uint32_t best_size;
|
||||||
|
|
@ -467,8 +505,15 @@ xcursor_xc_file_load_images(FILE *file, int size)
|
||||||
toc = xcursor_find_image_toc(file_header, best_size, n);
|
toc = xcursor_find_image_toc(file_header, best_size, n);
|
||||||
if (toc < 0)
|
if (toc < 0)
|
||||||
break;
|
break;
|
||||||
images->images[images->nimage] = xcursor_read_image(file, file_header,
|
struct xcursor_image *image = xcursor_read_image(file, file_header, toc);
|
||||||
toc);
|
if (!image)
|
||||||
|
break;
|
||||||
|
if (resize && image->size != (uint32_t) size) {
|
||||||
|
struct xcursor_image *resized_image = xcursor_resize_image(image, size);
|
||||||
|
xcursor_image_destroy(image);
|
||||||
|
image = resized_image;
|
||||||
|
}
|
||||||
|
images->images[images->nimage] = image;
|
||||||
if (!images->images[images->nimage])
|
if (!images->images[images->nimage])
|
||||||
break;
|
break;
|
||||||
images->nimage++;
|
images->nimage++;
|
||||||
|
|
@ -682,6 +727,40 @@ xcursor_theme_inherits(const char *full)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xcursor_default_parse_bool(const char *v)
|
||||||
|
{
|
||||||
|
char c0;
|
||||||
|
|
||||||
|
c0 = *v;
|
||||||
|
if (isupper ((int)c0))
|
||||||
|
c0 = (char) tolower (c0);
|
||||||
|
if (c0 == 't' || c0 == 'y' || c0 == '1')
|
||||||
|
return 1;
|
||||||
|
if (c0 == 'f' || c0 == 'n' || c0 == '0')
|
||||||
|
return 0;
|
||||||
|
if (c0 == 'o')
|
||||||
|
{
|
||||||
|
char c1 = v[1];
|
||||||
|
if (isupper ((int)c1))
|
||||||
|
c1 = (char) tolower (c1);
|
||||||
|
if (c1 == 'n')
|
||||||
|
return 1;
|
||||||
|
if (c1 == 'f')
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
xcursor_get_resizable(void)
|
||||||
|
{
|
||||||
|
const char *v = getenv("XCURSOR_RESIZED");
|
||||||
|
if (!v)
|
||||||
|
return false;
|
||||||
|
return xcursor_default_parse_bool(v) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_all_cursors_from_dir(const char *path, int size,
|
load_all_cursors_from_dir(const char *path, int size,
|
||||||
void (*load_callback)(struct xcursor_images *, void *),
|
void (*load_callback)(struct xcursor_images *, void *),
|
||||||
|
|
@ -700,6 +779,8 @@ load_all_cursors_from_dir(const char *path, int size,
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const bool resize = xcursor_get_resizable();
|
||||||
|
|
||||||
for (ent = readdir(dir); ent; ent = readdir(dir)) {
|
for (ent = readdir(dir); ent; ent = readdir(dir)) {
|
||||||
#ifdef _DIRENT_HAVE_D_TYPE
|
#ifdef _DIRENT_HAVE_D_TYPE
|
||||||
if (ent->d_type != DT_UNKNOWN &&
|
if (ent->d_type != DT_UNKNOWN &&
|
||||||
|
|
@ -718,7 +799,7 @@ load_all_cursors_from_dir(const char *path, int size,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
images = xcursor_xc_file_load_images(f, size);
|
images = xcursor_xc_file_load_images(f, size, resize);
|
||||||
|
|
||||||
if (images) {
|
if (images) {
|
||||||
images->name = strdup(ent->d_name);
|
images->name = strdup(ent->d_name);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue