{render,config}: allow specifying wallpaper anchor position
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Iee73e9d149e85d2c00eaba4be25d42bd6a6a6964
This commit is contained in:
parent
dd0252fe7b
commit
a82b986ac6
4 changed files with 189 additions and 29 deletions
19
include/chroma.h
vendored
19
include/chroma.h
vendored
|
|
@ -44,6 +44,19 @@ typedef enum {
|
||||||
CHROMA_SCALE_CENTER = 3 // center image at original size
|
CHROMA_SCALE_CENTER = 3 // center image at original size
|
||||||
} chroma_scale_mode_t;
|
} chroma_scale_mode_t;
|
||||||
|
|
||||||
|
// Anchor positions for wallpaper placement
|
||||||
|
typedef enum {
|
||||||
|
CHROMA_ANCHOR_CENTER = 0, // center of the output (default)
|
||||||
|
CHROMA_ANCHOR_TOP = 1, // top edge, centered horizontally
|
||||||
|
CHROMA_ANCHOR_BOTTOM = 2, // bottom edge, centered horizontally
|
||||||
|
CHROMA_ANCHOR_LEFT = 3, // left edge, centered vertically
|
||||||
|
CHROMA_ANCHOR_RIGHT = 4, // right edge, centered vertically
|
||||||
|
CHROMA_ANCHOR_TOP_LEFT = 5, // top-left corner
|
||||||
|
CHROMA_ANCHOR_TOP_RIGHT = 6, // top-right corner
|
||||||
|
CHROMA_ANCHOR_BOTTOM_LEFT = 7, // bottom-left corner
|
||||||
|
CHROMA_ANCHOR_BOTTOM_RIGHT = 8 // bottom-right corner
|
||||||
|
} chroma_anchor_t;
|
||||||
|
|
||||||
// Image filtering quality settings
|
// Image filtering quality settings
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CHROMA_FILTER_NEAREST = 0, // nearest neighbor filtering (pixelated)
|
CHROMA_FILTER_NEAREST = 0, // nearest neighbor filtering (pixelated)
|
||||||
|
|
@ -90,6 +103,7 @@ typedef struct {
|
||||||
// Configuration for this output
|
// Configuration for this output
|
||||||
chroma_scale_mode_t scale_mode;
|
chroma_scale_mode_t scale_mode;
|
||||||
chroma_filter_quality_t filter_quality;
|
chroma_filter_quality_t filter_quality;
|
||||||
|
chroma_anchor_t anchor;
|
||||||
bool config_loaded;
|
bool config_loaded;
|
||||||
|
|
||||||
// OpenGL resource cache
|
// OpenGL resource cache
|
||||||
|
|
@ -108,6 +122,7 @@ typedef struct {
|
||||||
char image_path[MAX_PATH_LEN];
|
char image_path[MAX_PATH_LEN];
|
||||||
chroma_scale_mode_t scale_mode;
|
chroma_scale_mode_t scale_mode;
|
||||||
chroma_filter_quality_t filter_quality;
|
chroma_filter_quality_t filter_quality;
|
||||||
|
chroma_anchor_t anchor;
|
||||||
} chroma_config_mapping_t;
|
} chroma_config_mapping_t;
|
||||||
|
|
||||||
// Application configuration
|
// Application configuration
|
||||||
|
|
@ -120,6 +135,7 @@ typedef struct {
|
||||||
// Global scaling and filtering settings (used as defaults)
|
// Global scaling and filtering settings (used as defaults)
|
||||||
chroma_scale_mode_t default_scale_mode;
|
chroma_scale_mode_t default_scale_mode;
|
||||||
chroma_filter_quality_t default_filter_quality;
|
chroma_filter_quality_t default_filter_quality;
|
||||||
|
chroma_anchor_t default_anchor;
|
||||||
|
|
||||||
// Image downsampling settings
|
// Image downsampling settings
|
||||||
bool enable_downsampling; // enable automatic downsampling
|
bool enable_downsampling; // enable automatic downsampling
|
||||||
|
|
@ -231,7 +247,8 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config,
|
||||||
const char *output_name);
|
const char *output_name);
|
||||||
int chroma_config_get_mapping_for_output(
|
int chroma_config_get_mapping_for_output(
|
||||||
chroma_config_t *config, const char *output_name,
|
chroma_config_t *config, const char *output_name,
|
||||||
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality);
|
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality,
|
||||||
|
chroma_anchor_t *anchor);
|
||||||
|
|
||||||
void chroma_config_print(const chroma_config_t *config);
|
void chroma_config_print(const chroma_config_t *config);
|
||||||
|
|
||||||
|
|
|
||||||
110
src/config.c
110
src/config.c
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
#include "../include/chroma.h"
|
#include "../include/chroma.h"
|
||||||
|
|
||||||
// Default configuration values
|
|
||||||
|
|
||||||
static char *trim_whitespace(char *str) {
|
static char *trim_whitespace(char *str) {
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
|
|
@ -122,11 +120,71 @@ static const char *filter_quality_to_string(chroma_filter_quality_t quality) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse anchor position from string
|
||||||
|
static chroma_anchor_t parse_anchor(const char *value) {
|
||||||
|
if (!value)
|
||||||
|
return CHROMA_ANCHOR_CENTER;
|
||||||
|
|
||||||
|
if (strcasecmp(value, "center") == 0) {
|
||||||
|
return CHROMA_ANCHOR_CENTER;
|
||||||
|
} else if (strcasecmp(value, "top") == 0) {
|
||||||
|
return CHROMA_ANCHOR_TOP;
|
||||||
|
} else if (strcasecmp(value, "bottom") == 0) {
|
||||||
|
return CHROMA_ANCHOR_BOTTOM;
|
||||||
|
} else if (strcasecmp(value, "left") == 0) {
|
||||||
|
return CHROMA_ANCHOR_LEFT;
|
||||||
|
} else if (strcasecmp(value, "right") == 0) {
|
||||||
|
return CHROMA_ANCHOR_RIGHT;
|
||||||
|
} else if (strcasecmp(value, "top-left") == 0 ||
|
||||||
|
strcasecmp(value, "topleft") == 0) {
|
||||||
|
return CHROMA_ANCHOR_TOP_LEFT;
|
||||||
|
} else if (strcasecmp(value, "top-right") == 0 ||
|
||||||
|
strcasecmp(value, "topright") == 0) {
|
||||||
|
return CHROMA_ANCHOR_TOP_RIGHT;
|
||||||
|
} else if (strcasecmp(value, "bottom-left") == 0 ||
|
||||||
|
strcasecmp(value, "bottomleft") == 0) {
|
||||||
|
return CHROMA_ANCHOR_BOTTOM_LEFT;
|
||||||
|
} else if (strcasecmp(value, "bottom-right") == 0 ||
|
||||||
|
strcasecmp(value, "bottomright") == 0) {
|
||||||
|
return CHROMA_ANCHOR_BOTTOM_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
chroma_log("WARN", "Unknown anchor: %s (using center)", value);
|
||||||
|
return CHROMA_ANCHOR_CENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get string representation of anchor position
|
||||||
|
static const char *anchor_to_string(chroma_anchor_t anchor) {
|
||||||
|
switch (anchor) {
|
||||||
|
case CHROMA_ANCHOR_CENTER:
|
||||||
|
return "center";
|
||||||
|
case CHROMA_ANCHOR_TOP:
|
||||||
|
return "top";
|
||||||
|
case CHROMA_ANCHOR_BOTTOM:
|
||||||
|
return "bottom";
|
||||||
|
case CHROMA_ANCHOR_LEFT:
|
||||||
|
return "left";
|
||||||
|
case CHROMA_ANCHOR_RIGHT:
|
||||||
|
return "right";
|
||||||
|
case CHROMA_ANCHOR_TOP_LEFT:
|
||||||
|
return "top-left";
|
||||||
|
case CHROMA_ANCHOR_TOP_RIGHT:
|
||||||
|
return "top-right";
|
||||||
|
case CHROMA_ANCHOR_BOTTOM_LEFT:
|
||||||
|
return "bottom-left";
|
||||||
|
case CHROMA_ANCHOR_BOTTOM_RIGHT:
|
||||||
|
return "bottom-right";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Output-to-image mapping
|
// Output-to-image mapping
|
||||||
static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
||||||
const char *image_path,
|
const char *image_path,
|
||||||
chroma_scale_mode_t scale_mode,
|
chroma_scale_mode_t scale_mode,
|
||||||
chroma_filter_quality_t filter_quality) {
|
chroma_filter_quality_t filter_quality,
|
||||||
|
chroma_anchor_t anchor) {
|
||||||
if (!config || !output_name || !image_path) {
|
if (!config || !output_name || !image_path) {
|
||||||
return CHROMA_ERROR_INIT;
|
return CHROMA_ERROR_INIT;
|
||||||
}
|
}
|
||||||
|
|
@ -159,12 +217,14 @@ static int add_output_mapping(chroma_config_t *config, const char *output_name,
|
||||||
strcpy(mapping->image_path, image_path);
|
strcpy(mapping->image_path, image_path);
|
||||||
mapping->scale_mode = scale_mode;
|
mapping->scale_mode = scale_mode;
|
||||||
mapping->filter_quality = filter_quality;
|
mapping->filter_quality = filter_quality;
|
||||||
|
mapping->anchor = anchor;
|
||||||
|
|
||||||
config->mapping_count++;
|
config->mapping_count++;
|
||||||
|
|
||||||
chroma_log("DEBUG", "Added mapping: %s -> %s (scale: %s, filter: %s)",
|
chroma_log(
|
||||||
output_name, image_path, scale_mode_to_string(scale_mode),
|
"DEBUG", "Added mapping: %s -> %s (scale: %s, filter: %s, anchor: %s)",
|
||||||
filter_quality_to_string(filter_quality));
|
output_name, image_path, scale_mode_to_string(scale_mode),
|
||||||
|
filter_quality_to_string(filter_quality), anchor_to_string(anchor));
|
||||||
chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)",
|
chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)",
|
||||||
config->mapping_count, output_name, image_path, path_len);
|
config->mapping_count, output_name, image_path, path_len);
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
|
|
@ -183,6 +243,7 @@ static void init_default_config(chroma_config_t *config) {
|
||||||
// Set default scaling and filtering
|
// Set default scaling and filtering
|
||||||
config->default_scale_mode = CHROMA_SCALE_FILL;
|
config->default_scale_mode = CHROMA_SCALE_FILL;
|
||||||
config->default_filter_quality = CHROMA_FILTER_LINEAR;
|
config->default_filter_quality = CHROMA_FILTER_LINEAR;
|
||||||
|
config->default_anchor = CHROMA_ANCHOR_CENTER;
|
||||||
|
|
||||||
// Set default downsampling settings
|
// Set default downsampling settings
|
||||||
config->enable_downsampling = true; // enable by default, performance etc.
|
config->enable_downsampling = true; // enable by default, performance etc.
|
||||||
|
|
@ -286,6 +347,10 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
config->enable_downsampling = parse_bool(value);
|
config->enable_downsampling = parse_bool(value);
|
||||||
chroma_log("DEBUG", "Set downsampling: %s",
|
chroma_log("DEBUG", "Set downsampling: %s",
|
||||||
config->enable_downsampling ? "enabled" : "disabled");
|
config->enable_downsampling ? "enabled" : "disabled");
|
||||||
|
} else if (strcasecmp(key, "anchor") == 0) {
|
||||||
|
config->default_anchor = parse_anchor(value);
|
||||||
|
chroma_log("DEBUG", "Set default anchor: %s",
|
||||||
|
anchor_to_string(config->default_anchor));
|
||||||
} else if (strcasecmp(key, "max_output_width") == 0) {
|
} else if (strcasecmp(key, "max_output_width") == 0) {
|
||||||
int width = atoi(value);
|
int width = atoi(value);
|
||||||
if (width > 0 && width <= 16384) { // Reasonable limits
|
if (width > 0 && width <= 16384) { // Reasonable limits
|
||||||
|
|
@ -351,6 +416,10 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
mapping->filter_quality = parse_filter_quality(value);
|
mapping->filter_quality = parse_filter_quality(value);
|
||||||
chroma_log("DEBUG", "Set filter quality for output %s: %s", output_name,
|
chroma_log("DEBUG", "Set filter quality for output %s: %s", output_name,
|
||||||
filter_quality_to_string(mapping->filter_quality));
|
filter_quality_to_string(mapping->filter_quality));
|
||||||
|
} else if (strcasecmp(property, "anchor") == 0) {
|
||||||
|
mapping->anchor = parse_anchor(value);
|
||||||
|
chroma_log("DEBUG", "Set anchor for output %s: %s", output_name,
|
||||||
|
anchor_to_string(mapping->anchor));
|
||||||
} else {
|
} else {
|
||||||
chroma_log("WARN", "Unknown output property: %s (line %d)", property,
|
chroma_log("WARN", "Unknown output property: %s (line %d)", property,
|
||||||
line_number);
|
line_number);
|
||||||
|
|
@ -375,7 +444,8 @@ static int parse_config_line(chroma_config_t *config, char *line,
|
||||||
|
|
||||||
if (add_output_mapping(config, output_name, path_to_validate,
|
if (add_output_mapping(config, output_name, path_to_validate,
|
||||||
config->default_scale_mode,
|
config->default_scale_mode,
|
||||||
config->default_filter_quality) != CHROMA_OK) {
|
config->default_filter_quality,
|
||||||
|
config->default_anchor) != CHROMA_OK) {
|
||||||
chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name,
|
chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name,
|
||||||
path_to_validate);
|
path_to_validate);
|
||||||
if (expanded_path) {
|
if (expanded_path) {
|
||||||
|
|
@ -518,12 +588,13 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get configuration mapping for output, including scale mode and filter
|
// Get configuration mapping for output, including scale mode, filter
|
||||||
// quality
|
// quality, and anchor
|
||||||
int chroma_config_get_mapping_for_output(
|
int chroma_config_get_mapping_for_output(
|
||||||
chroma_config_t *config, const char *output_name,
|
chroma_config_t *config, const char *output_name,
|
||||||
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality) {
|
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality,
|
||||||
if (!config || !output_name || !scale_mode || !filter_quality) {
|
chroma_anchor_t *anchor) {
|
||||||
|
if (!config || !output_name || !scale_mode || !filter_quality || !anchor) {
|
||||||
return CHROMA_ERROR_INIT;
|
return CHROMA_ERROR_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,10 +603,13 @@ int chroma_config_get_mapping_for_output(
|
||||||
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
|
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
|
||||||
*scale_mode = config->mappings[i].scale_mode;
|
*scale_mode = config->mappings[i].scale_mode;
|
||||||
*filter_quality = config->mappings[i].filter_quality;
|
*filter_quality = config->mappings[i].filter_quality;
|
||||||
|
*anchor = config->mappings[i].anchor;
|
||||||
chroma_log("DEBUG",
|
chroma_log("DEBUG",
|
||||||
"Found specific mapping for output %s: scale=%s, filter=%s",
|
"Found specific mapping for output %s: scale=%s, filter=%s, "
|
||||||
|
"anchor=%s",
|
||||||
output_name, scale_mode_to_string(*scale_mode),
|
output_name, scale_mode_to_string(*scale_mode),
|
||||||
filter_quality_to_string(*filter_quality));
|
filter_quality_to_string(*filter_quality),
|
||||||
|
anchor_to_string(*anchor));
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,14 +617,14 @@ int chroma_config_get_mapping_for_output(
|
||||||
// Return defaults if no specific mapping found
|
// Return defaults if no specific mapping found
|
||||||
*scale_mode = config->default_scale_mode;
|
*scale_mode = config->default_scale_mode;
|
||||||
*filter_quality = config->default_filter_quality;
|
*filter_quality = config->default_filter_quality;
|
||||||
chroma_log("DEBUG", "Using defaults for output %s: scale=%s, filter=%s",
|
*anchor = config->default_anchor;
|
||||||
output_name, scale_mode_to_string(*scale_mode),
|
chroma_log(
|
||||||
filter_quality_to_string(*filter_quality));
|
"DEBUG", "Using defaults for output %s: scale=%s, filter=%s, anchor=%s",
|
||||||
|
output_name, scale_mode_to_string(*scale_mode),
|
||||||
|
filter_quality_to_string(*filter_quality), anchor_to_string(*anchor));
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Print current configuration for debugging
|
// Print current configuration for debugging
|
||||||
void chroma_config_print(const chroma_config_t *config) {
|
void chroma_config_print(const chroma_config_t *config) {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
|
|
|
||||||
12
src/core.c
12
src/core.c
|
|
@ -112,19 +112,21 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
|
||||||
// Store old configuration values for comparison
|
// Store old configuration values for comparison
|
||||||
chroma_scale_mode_t old_scale_mode = output->scale_mode;
|
chroma_scale_mode_t old_scale_mode = output->scale_mode;
|
||||||
chroma_filter_quality_t old_filter_quality = output->filter_quality;
|
chroma_filter_quality_t old_filter_quality = output->filter_quality;
|
||||||
|
chroma_anchor_t old_anchor = output->anchor;
|
||||||
bool had_config = output->config_loaded;
|
bool had_config = output->config_loaded;
|
||||||
|
|
||||||
// Load configuration for this output (scale mode and filter quality)
|
// Load configuration for this output (scale mode, filter quality, anchor)
|
||||||
if (chroma_config_get_mapping_for_output(
|
if (chroma_config_get_mapping_for_output(
|
||||||
&state->config, output->name ? output->name : "unknown",
|
&state->config, output->name ? output->name : "unknown",
|
||||||
&output->scale_mode, &output->filter_quality) == CHROMA_OK) {
|
&output->scale_mode, &output->filter_quality, &output->anchor) == CHROMA_OK) {
|
||||||
output->config_loaded = true;
|
output->config_loaded = true;
|
||||||
chroma_log("DEBUG", "Loaded config for output %u: scale=%d, filter=%d",
|
chroma_log("DEBUG", "Loaded config for output %u: scale=%d, filter=%d, anchor=%d",
|
||||||
output->id, output->scale_mode, output->filter_quality);
|
output->id, output->scale_mode, output->filter_quality, output->anchor);
|
||||||
|
|
||||||
// Check if configuration changed and invalidate texture if needed
|
// Check if configuration changed and invalidate texture if needed
|
||||||
if (had_config && (old_scale_mode != output->scale_mode ||
|
if (had_config && (old_scale_mode != output->scale_mode ||
|
||||||
old_filter_quality != output->filter_quality)) {
|
old_filter_quality != output->filter_quality ||
|
||||||
|
old_anchor != output->anchor)) {
|
||||||
chroma_output_invalidate_texture(output);
|
chroma_output_invalidate_texture(output);
|
||||||
output->vbo_dirty = true; // VBO needs update for new scale mode
|
output->vbo_dirty = true; // VBO needs update for new scale mode
|
||||||
chroma_log("DEBUG",
|
chroma_log("DEBUG",
|
||||||
|
|
|
||||||
77
src/render.c
77
src/render.c
|
|
@ -41,8 +41,9 @@ static void get_gl_filter_params(chroma_filter_quality_t quality,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate texture coordinates based on scaling mode
|
// Calculate texture coordinates based on scaling mode and anchor position
|
||||||
static void calculate_texture_coords(chroma_scale_mode_t scale_mode,
|
static void calculate_texture_coords(chroma_scale_mode_t scale_mode,
|
||||||
|
chroma_anchor_t anchor,
|
||||||
int image_width, int image_height,
|
int image_width, int image_height,
|
||||||
int output_width, int output_height,
|
int output_width, int output_height,
|
||||||
float tex_coords[8]) {
|
float tex_coords[8]) {
|
||||||
|
|
@ -142,6 +143,72 @@ static void calculate_texture_coords(chroma_scale_mode_t scale_mode,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply anchor-based offset by shifting the visible crop region
|
||||||
|
// For fill: shift which part of image is shown
|
||||||
|
// For fit/center: shift where the image is positioned
|
||||||
|
//
|
||||||
|
// Positive shift reveals left/bottom portion
|
||||||
|
// Negative shift reveals right/top portion
|
||||||
|
float u_shift = 0.0f;
|
||||||
|
float v_shift = 0.0f;
|
||||||
|
|
||||||
|
switch (anchor) {
|
||||||
|
case CHROMA_ANCHOR_CENTER:
|
||||||
|
u_shift = 0.0f;
|
||||||
|
v_shift = 0.0f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_TOP:
|
||||||
|
u_shift = 0.0f;
|
||||||
|
v_shift = -0.5f; // shift up to show top of image
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_BOTTOM:
|
||||||
|
u_shift = 0.0f;
|
||||||
|
v_shift = 0.5f; // shift down to show bottom of image
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_LEFT:
|
||||||
|
u_shift = -0.5f; // shift left to show left of image
|
||||||
|
v_shift = 0.0f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_RIGHT:
|
||||||
|
u_shift = 0.5f; // shift right to show right of image
|
||||||
|
v_shift = 0.0f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_TOP_LEFT:
|
||||||
|
u_shift = -0.5f;
|
||||||
|
v_shift = -0.5f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_TOP_RIGHT:
|
||||||
|
u_shift = 0.5f;
|
||||||
|
v_shift = -0.5f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_BOTTOM_LEFT:
|
||||||
|
u_shift = -0.5f;
|
||||||
|
v_shift = 0.5f;
|
||||||
|
break;
|
||||||
|
case CHROMA_ANCHOR_BOTTOM_RIGHT:
|
||||||
|
u_shift = 0.5f;
|
||||||
|
v_shift = 0.5f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the shift amount based on crop/border space available
|
||||||
|
float u_crop = 1.0f - (u2 - u1);
|
||||||
|
float v_crop = 1.0f - (v2 - v1);
|
||||||
|
u1 += u_shift * u_crop;
|
||||||
|
u2 += u_shift * u_crop;
|
||||||
|
v1 += v_shift * v_crop;
|
||||||
|
v2 += v_shift * v_crop;
|
||||||
|
|
||||||
|
// Clamp to valid range [0, 1]
|
||||||
|
if (u1 < 0.0f)
|
||||||
|
u1 = 0.0f;
|
||||||
|
if (u2 > 1.0f)
|
||||||
|
u2 = 1.0f;
|
||||||
|
if (v1 < 0.0f)
|
||||||
|
v1 = 0.0f;
|
||||||
|
if (v2 > 1.0f)
|
||||||
|
v2 = 1.0f;
|
||||||
|
|
||||||
// Set texture coordinates for quad (bottom-left, bottom-right, top-right,
|
// Set texture coordinates for quad (bottom-left, bottom-right, top-right,
|
||||||
// top-left)
|
// top-left)
|
||||||
tex_coords[0] = u1;
|
tex_coords[0] = u1;
|
||||||
|
|
@ -688,11 +755,11 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
// Update VBO only if needed. E.g, image changed, scale mode changed, or first
|
// Update VBO only if needed. E.g, image changed, scale mode changed, or first
|
||||||
// render
|
// render
|
||||||
if (output->vbo_dirty) {
|
if (output->vbo_dirty) {
|
||||||
// Calculate texture coordinates based on scaling mode
|
// Calculate texture coordinates based on scaling mode and anchor
|
||||||
float tex_coords[8];
|
float tex_coords[8];
|
||||||
calculate_texture_coords(output->scale_mode, output->image->width,
|
calculate_texture_coords(output->scale_mode, output->anchor,
|
||||||
output->image->height, output->width,
|
output->image->width, output->image->height,
|
||||||
output->height, tex_coords);
|
output->width, output->height, tex_coords);
|
||||||
|
|
||||||
// Create dynamic vertex data with calculated texture coordinates
|
// Create dynamic vertex data with calculated texture coordinates
|
||||||
float dynamic_vertices[] = {
|
float dynamic_vertices[] = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue