[Widget] Add scaling option to background-image.

This commit is contained in:
Dave Davenport 2021-06-15 17:18:34 +02:00
parent f72bae02bb
commit 4c1a74e15e
8 changed files with 120 additions and 11 deletions

View File

@ -366,6 +366,8 @@ dynamic: false;
.IP \(bu 2
Format: url("path to image");
.IP \(bu 2
Format: url("path to image", scale);
.IP \(bu 2
Format: linear\-gradient(stop color,stop1, color, stop2 color, ...);
.IP \(bu 2
Format: linear\-gradient(to direction, stop color,stop1, color, stop2 color, ...);
@ -375,7 +377,16 @@ Format: linear\-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
.PP
Where the path is a string, and stop color is of type color.
Where the \fB\fCpath\fR is a string, and \fB\fCstop\fR color is of type color.
The \fB\fCscale\fR property can be:
.IP \(bu 2
none
.IP \(bu 2
both
.IP \(bu 2
width
.IP \(bu 2
height
.SH Color
.PP

View File

@ -255,13 +255,20 @@ dynamic: false;
**rofi** support a very limited set of image formats.
* Format: url("path to image");
* Format: url("path to image", scale);
* Format: linear-gradient(stop color,stop1, color, stop2 color, ...);
* Format: linear-gradient(to direction, stop color,stop1, color, stop2 color, ...);
where direction is: top,left,right,bottom.
* Format: linear-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
Where the path is a string, and stop color is of type color.
Where the `path` is a string, and `stop` color is of type color.
The `scale` property can be:
* none
* both
* width
* height
## Color

View File

@ -35,6 +35,7 @@ void rofi_icon_fetcher_destroy ( void );
* @returns the uid identifying the request.
*/
uint32_t rofi_icon_fetcher_query ( const char *name, const int size );
uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize );
/**
* @param uid The unique id representing the matching request.

View File

@ -188,11 +188,22 @@ typedef enum
ROFI_DIRECTION_ANGLE,
} RofiDirection;
typedef enum
{
ROFI_SCALE_BOTH,
ROFI_SCALE_HEIGHT,
ROFI_SCALE_WIDTH,
ROFI_SCALE_NONE,
} RofiScaleType;
typedef struct
{
RofiImageType type;
char *url;
RofiScaleType scaling;
int wsize;
int hsize;
RofiDirection dir;
double angle;

View File

@ -242,6 +242,11 @@ HSL (?i:hsl[a]?)
/* Image type */
URL (?i:url?)
LINEAR_GRADIENT (?i:linear-gradient?)
WIDTH (?i:width?)
HEIGHT (?i:height?)
BOTH (?i:both?)
TO (?i:to?)
RIGHT (?i:right?)
@ -564,6 +569,9 @@ if ( queue == NULL ){
}
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{URL} { return T_URL; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LINEAR_GRADIENT} { return T_LINEAR_GRADIENT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{WIDTH} { return T_WIDTH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{HEIGHT} { return T_HEIGHT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{BOTH} { return T_BOTH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{TO} { return T_TO; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LEFT} { return T_LEFT; }

View File

@ -210,6 +210,9 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_COL_CMYK "cmyk colorscheme"
%token T_URL "an URL"
%token T_WIDTH "an WIDTH"
%token T_HEIGHT "an HEIGHT"
%token T_BOTH "an BOTH"
%token T_TO "an TO"
%token T_LEFT "an LEFT"
%token T_RIGHT "an RIGHT"
@ -217,6 +220,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_BOTTOM "an BOTTOM"
%type <ival> t_property_direction
%type <ival> t_property_scale_type
%token T_LINEAR_GRADIENT "a linear gradient"
%token T_PARENT_LEFT "Parent left ('(')"
@ -561,6 +565,12 @@ t_property_element
$$->value.image.type = ROFI_IMAGE_URL;
$$->value.image.url = $3;
}
| T_URL T_PARENT_LEFT T_STRING T_COMMA t_property_scale_type T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_URL;
$$->value.image.url = $3;
$$->value.image.scaling = $5;
}
| T_LINEAR_GRADIENT T_PARENT_LEFT t_color_list T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_LINEAR_GRADIENT;
@ -589,6 +599,12 @@ t_property_direction
| T_TOP { $$ = ROFI_DIRECTION_TOP; }
| T_BOTTOM { $$ = ROFI_DIRECTION_BOTTOM; }
;
t_property_scale_type
: T_BOTH { $$ = ROFI_SCALE_BOTH; }
| T_WIDTH { $$ = ROFI_SCALE_WIDTH; }
| T_HEIGHT { $$ = ROFI_SCALE_HEIGHT; }
| T_NONE { $$ = ROFI_SCALE_NONE; }
;
t_color_list
: t_property_color {

View File

@ -77,7 +77,8 @@ typedef struct
unsigned int *acount;
uint32_t uid;
int size;
int wsize;
int hsize;
cairo_surface_t *surface;
IconFetcherNameEntry *entry;
@ -301,13 +302,13 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
icon_path = sentry->entry->name;
}
else {
icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, sentry->size, 1, TRUE );
icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, MIN(sentry->wsize,sentry->hsize), 1, TRUE );
if ( icon_path_ == NULL ) {
g_debug ( "failed to get icon %s(%d): n/a", sentry->entry->name, sentry->size );
g_debug ( "failed to get icon %s(%dx%d): n/a", sentry->entry->name, sentry->wsize, sentry->hsize );
return;
}
else{
g_debug ( "found icon %s(%d): %s", sentry->entry->name, sentry->size, icon_path );
g_debug ( "found icon %s(%dx%d): %s", sentry->entry->name, sentry->wsize, sentry->hsize, icon_path );
}
}
cairo_surface_t *icon_surf = NULL;
@ -318,7 +319,7 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
}
GError *error = NULL;
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->size, sentry->size, TRUE, &error );
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->wsize, sentry->hsize, TRUE, &error );
if ( error != NULL ) {
g_warning ( "Failed to load image: %s", error->message );
g_error_free ( error );
@ -336,6 +337,40 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
rofi_view_reload ();
}
uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize )
{
g_debug ( "Query: %s(%dx%d)", name, wsize, hsize );
IconFetcherNameEntry *entry = g_hash_table_lookup ( rofi_icon_fetcher_data->icon_cache, name );
if ( entry == NULL ) {
entry = g_new0 ( IconFetcherNameEntry, 1 );
entry->name = g_strdup ( name );
g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache, entry->name, entry );
}
IconFetcherEntry *sentry;
for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
sentry = iter->data;
if ( sentry->wsize == wsize && sentry->hsize == hsize ) {
return sentry->uid;
}
}
// Not found.
sentry = g_new0 ( IconFetcherEntry, 1 );
sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
sentry->wsize = wsize;
sentry->hsize = hsize;
sentry->entry = entry;
sentry->surface = NULL;
entry->sizes = g_list_prepend ( entry->sizes, sentry );
g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache_uid, GINT_TO_POINTER ( sentry->uid ), sentry );
// Push into fetching queue.
sentry->state.callback = rofi_icon_fetcher_worker;
g_thread_pool_push ( tpool, sentry, NULL );
return sentry->uid;
}
uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
{
g_debug ( "Query: %s(%d)", name, size );
@ -348,7 +383,7 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
IconFetcherEntry *sentry;
for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
sentry = iter->data;
if ( sentry->size == size ) {
if ( sentry->wsize == size && sentry->hsize == size ) {
return sentry->uid;
}
}
@ -356,7 +391,8 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
// Not found.
sentry = g_new0 ( IconFetcherEntry, 1 );
sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
sentry->size = size;
sentry->wsize = size;
sentry->hsize = size;
sentry->entry = entry;
sentry->surface = NULL;

View File

@ -996,8 +996,27 @@ gboolean rofi_theme_get_image ( const widget *widget, const char *property, cair
return FALSE;
}
if ( p->value.image.type == ROFI_IMAGE_URL ) {
if ( p->value.image.surface_id == 0 ) {
p->value.image.surface_id = rofi_icon_fetcher_query ( p->value.image.url, -1 );
int wsize = -1;
int hsize = -1;
switch ( p->value.image.scaling ) {
case ROFI_SCALE_BOTH:
wsize = widget->w;
hsize = widget->h;
break;
case ROFI_SCALE_WIDTH:
wsize = widget->w;
break;
case ROFI_SCALE_HEIGHT:
hsize = widget->h;
break;
case ROFI_SCALE_NONE:
default:
break;
}
if ( p->value.image.surface_id == 0 || p->value.image.wsize != wsize || p->value.image.hsize != hsize) {
p->value.image.surface_id = rofi_icon_fetcher_query_advanced ( p->value.image.url, wsize, hsize );
p->value.image.wsize = wsize;
p->value.image.hsize = hsize;
}
cairo_surface_t *img = rofi_icon_fetcher_get ( p->value.image.surface_id );