Gradients: mostly done

This commit is contained in:
o9000 2016-10-03 20:25:35 +02:00
parent 822b149419
commit b4c2b3e6af
18 changed files with 400 additions and 280 deletions

View file

@ -194,7 +194,7 @@ endif( ENABLE_TINT2CONF )
if( ENABLE_ASAN )
SET(ASAN_C_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -Wshadow")
SET(ASAN_L_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic ")
SET(ASAN_L_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -fuse-ld=gold ")
else()
SET(ASAN_C_FLAGS "")
SET(ASAN_L_FLAGS "")

View file

@ -164,6 +164,7 @@ void init_battery_panel(void *p)
battery->area.has_mouse_press_effect = battery->area.has_mouse_over_effect;
if (battery_tooltip_enabled)
battery->area._get_tooltip_text = battery_get_tooltip;
init_area_gradients(&battery->area);
}
void battery_init_fonts()

View file

@ -196,6 +196,7 @@ void init_clock_panel(void *p)
clock->area.resize_needed = 1;
clock->area.on_screen = TRUE;
init_area_gradients(&clock->area);
if (time_tooltip_format) {
clock->area._get_tooltip_text = clock_get_tooltip;

View file

@ -71,8 +71,6 @@ char *snapshot_path;
// detect if it's an old config file (==1)
static gboolean new_config_file;
static gboolean read_bg_color2;
static gboolean read_bg_gradient;
static gboolean read_bg_color_hover;
static gboolean read_border_color_hover;
static gboolean read_bg_color_press;
@ -244,12 +242,10 @@ void add_entry(char *key, char *value)
init_background(&bg);
bg.border.radius = atoi(value);
g_array_append_val(backgrounds, bg);
read_bg_color2 = 0;
read_bg_gradient = 0;
read_bg_color_hover = 0;
read_border_color_hover = 0;
read_bg_color_press = 0;
read_border_color_press = 0;
read_bg_color_hover = FALSE;
read_border_color_hover = FALSE;
read_bg_color_press = FALSE;
read_border_color_press = FALSE;
} else if (strcmp(key, "border_width") == 0) {
g_array_index(backgrounds, Background, backgrounds->len - 1).border.width = atoi(value);
} else if (strcmp(key, "border_sides") == 0) {
@ -345,27 +341,13 @@ void add_entry(char *key, char *value)
GradientClass *g = &g_array_index(gradients, GradientClass, gradients->len - 1);
extract_values(value, &value1, &value2, &value3);
ColorStop *color_stop = (ColorStop *) calloc(1, sizeof(ColorStop));
color_stop->offset = atof(value1);
color_stop->offset = atof(value1) / 100.0;
get_color(value2, color_stop->color.rgb);
if (value3)
color_stop->color.alpha = (atoi(value2) / 100.0);
color_stop->color.alpha = (atoi(value3) / 100.0);
else
color_stop->color.alpha = 0.5;
g->extra_color_stops = g_list_append(g->extra_color_stops, color_stop);
} else if (strcmp(key, "from_origin") == 0) {
GradientClass *g = &g_array_index(gradients, GradientClass, gradients->len - 1);
if (g->type == GRADIENT_HORIZONTAL || g->type == GRADIENT_VERTICAL || g->type == GRADIENT_CENTERED) {
fprintf(stderr, RED "Control points can only be specified for linear and radial gradients: line %s = %s" RESET "\n", key, value);
} else {
g->from.origin = origin_from_string(value);
}
} else if (strcmp(key, "to_origin") == 0) {
GradientClass *g = &g_array_index(gradients, GradientClass, gradients->len - 1);
if (g->type == GRADIENT_HORIZONTAL || g->type == GRADIENT_VERTICAL || g->type == GRADIENT_CENTERED) {
fprintf(stderr, RED "Control points can only be specified for linear and radial gradients: line %s = %s" RESET "\n", key, value);
} else {
g->to.origin = origin_from_string(value);
}
} else if (strcmp(key, "from_offset_x") == 0) {
GradientClass *g = &g_array_index(gradients, GradientClass, gradients->len - 1);
if (g->type == GRADIENT_HORIZONTAL || g->type == GRADIENT_VERTICAL || g->type == GRADIENT_CENTERED) {
@ -554,7 +536,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
panel_config.area.gradients = g_list_append(panel_config.area.gradients, &g_array_index(backgrounds, Background, id));
panel_config.area.gradients = g_list_append(panel_config.area.gradients, &g_array_index(gradients, GradientClass, id));
} else if (strcmp(key, "wm_menu") == 0)
wm_menu = atoi(value);
else if (strcmp(key, "panel_dock") == 0)
@ -663,7 +645,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
panel_config.battery.area.gradients = g_list_append(panel_config.battery.area.gradients, &g_array_index(backgrounds, Background, id));
panel_config.battery.area.gradients = g_list_append(panel_config.battery.area.gradients, &g_array_index(gradients, GradientClass, id));
#endif
} else if (strcmp(key, "battery_hide") == 0) {
#ifdef ENABLE_BATTERY
@ -690,7 +672,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
separator->area.gradients = g_list_append(separator->area.gradients, &g_array_index(backgrounds, Background, id));
separator->area.gradients = g_list_append(separator->area.gradients, &g_array_index(gradients, GradientClass, id));
} else if (strcmp(key, "separator_color") == 0) {
Separator *separator = get_or_create_last_separator();
extract_values(value, &value1, &value2, &value3);
@ -788,7 +770,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
execp->area.gradients = g_list_append(execp->area.gradients, &g_array_index(backgrounds, Background, id));
execp->area.gradients = g_list_append(execp->area.gradients, &g_array_index(gradients, GradientClass, id));
} else if (strcmp(key, "execp_centered") == 0) {
Execp *execp = get_or_create_last_execp();
execp->backend->centered = atoi(value);
@ -889,7 +871,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
panel_config.clock.area.gradients = g_list_append(panel_config.clock.area.gradients, &g_array_index(backgrounds, Background, id));
panel_config.clock.area.gradients = g_list_append(panel_config.clock.area.gradients, &g_array_index(gradients, GradientClass, id));
} else if (strcmp(key, "clock_tooltip") == 0) {
if (strlen(value) > 0)
time_tooltip_format = strdup(value);
@ -1175,7 +1157,7 @@ void add_entry(char *key, char *value)
int id = atoi(value);
id = (id < gradients->len && id >= 0) ? id : -1;
if (id >= 0)
launcher_icon_gradient = &g_array_index(gradients, GradientClass, id);
launcher_icon_gradients = g_list_append(launcher_icon_gradients, &g_array_index(gradients, GradientClass, id));
} else if (strcmp(key, "launcher_icon_size") == 0) {
launcher_max_icon_size = atoi(value);
} else if (strcmp(key, "launcher_item_app") == 0) {

View file

@ -182,6 +182,7 @@ void init_execp_panel(void *p)
execp->area.resize_needed = TRUE;
execp->area.on_screen = TRUE;
init_area_gradients(&execp->area);
if (!execp->backend->timer)
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);

View file

@ -53,7 +53,7 @@ char *icon_theme_name_xsettings;
int launcher_icon_theme_override;
int startup_notifications;
Background *launcher_icon_bg;
GradientClass *launcher_icon_gradient;
GList *launcher_icon_gradients;
Imlib_Image scale_icon(Imlib_Image original, int icon_size);
void free_icon(Imlib_Image icon);
@ -76,6 +76,7 @@ void default_launcher()
launcher_icon_theme_override = 0;
startup_notifications = 0;
launcher_icon_bg = NULL;
launcher_icon_gradients = NULL;
}
void init_launcher()
@ -107,6 +108,7 @@ void init_launcher_panel(void *p)
launcher->area.on_screen = TRUE;
panel_refresh = TRUE;
init_area_gradients(&launcher->area);
launcher_load_themes(launcher);
launcher_load_icons(launcher);
@ -422,16 +424,20 @@ void launcher_load_icons(Launcher *launcher)
{
// Load apps (.desktop style launcher items)
GSList *app = launcher->list_apps;
int index = 0;
while (app != NULL) {
LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon));
index++;
LauncherIcon *launcherIcon = (LauncherIcon *)calloc(1, sizeof(LauncherIcon));
launcherIcon->area.panel = launcher->area.panel;
launcherIcon->area._draw_foreground = draw_launcher_icon;
launcherIcon->area.size_mode = LAYOUT_FIXED;
launcherIcon->area._resize = NULL;
sprintf(launcherIcon->area.name, "LauncherIcon %d", index);
launcherIcon->area.resize_needed = 0;
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
launcherIcon->area.bg = launcher_icon_bg;
launcherIcon->area.gradients = launcher_icon_gradients;
launcherIcon->area.on_screen = TRUE;
launcherIcon->area._on_change_layout = launcher_icon_on_change_layout;
launcherIcon->area._dump_geometry = launcher_icon_dump_geometry;
@ -444,6 +450,7 @@ void launcher_load_icons(Launcher *launcher)
add_area(&launcherIcon->area, (Area *)launcher);
launcher->list_icons = g_slist_append(launcher->list_icons, launcherIcon);
launcher_reload_icon(launcher, launcherIcon);
init_area_gradients(&launcherIcon->area);
app = g_slist_next(app);
}
}

View file

@ -46,7 +46,7 @@ extern char *icon_theme_name_config;
extern int launcher_icon_theme_override;
extern int startup_notifications;
extern Background *launcher_icon_bg;
extern GradientClass *launcher_icon_gradient;
extern GList *launcher_icon_gradients;
// default global data
void default_launcher();

View file

@ -56,6 +56,7 @@ gboolean panel_refresh;
gboolean task_dragged;
char *panel_window_name = NULL;
gboolean debug_geometry;
gboolean debug_gradients;
gboolean panel_autohide;
int panel_autohide_show_timeout;
@ -115,6 +116,9 @@ void default_panel()
Background transparent_bg;
init_background(&transparent_bg);
g_array_append_val(backgrounds, transparent_bg);
GradientClass transparent_gradient;
init_gradient(&transparent_gradient, GRADIENT_VERTICAL);
g_array_append_val(gradients, transparent_gradient);
}
void cleanup_panel()
@ -215,6 +219,7 @@ void init_panel()
p->area._clear = panel_clear_background;
p->separator_list = NULL;
init_panel_size_and_position(p);
init_area_gradients(&p->area);
// add children according to panel_items
for (int k = 0; k < strlen(panel_items_order); k++) {
if (panel_items_order[k] == 'L')

View file

@ -84,6 +84,7 @@ void init_separator_panel(void *p)
separator->area.on_screen = TRUE;
separator->area._resize = resize_separator;
separator->area._draw_foreground = draw_separator;
init_area_gradients(&separator->area);
}
}

View file

@ -123,6 +123,7 @@ void init_systray_panel(void *p)
show(&systray.area);
schedule_redraw(&systray.area);
refresh_systray = TRUE;
init_area_gradients(&systray.area);
}
gboolean resize_systray(void *obj)
@ -1500,9 +1501,9 @@ void refresh_systray_icons()
}
}
gboolean systray_on_monitor(int i_monitor, int num_panels)
gboolean systray_on_monitor(int i_monitor, int n_panels)
{
return (i_monitor == systray_monitor) || (i_monitor == 0 && (systray_monitor >= num_panels || systray_monitor < 0));
return (i_monitor == systray_monitor) || (i_monitor == 0 && (systray_monitor >= n_panels || systray_monitor < 0));
}
TrayWindow *systray_find_icon(Window win)

View file

@ -595,6 +595,9 @@ void set_task_state(Task *task, TaskState state)
Task *task1 = g_ptr_array_index(task_buttons, i);
task1->current_state = state;
task1->area.bg = panels[0].g_task.background[state];
free_area_gradients(&task1->area);
task1->area.gradients = panels[0].g_task.gradient[state];
init_area_gradients(&task1->area);
schedule_redraw(&task1->area);
if (state == TASK_ACTIVE && g_slist_find(urgent_list, task1))
del_urgent(task1);

View file

@ -304,10 +304,18 @@ void init_taskbar_panel(void *p)
taskbar = &panel->taskbar[j];
memcpy(&taskbar->area, &panel->g_taskbar.area, sizeof(Area));
taskbar->desktop = j;
if (j == server.desktop)
if (j == server.desktop) {
taskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
else
free_area_gradients(&taskbar->area);
taskbar->area.gradients = panel->g_taskbar.gradient[TASKBAR_ACTIVE];
init_area_gradients(&taskbar->area);
} else {
taskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
free_area_gradients(&taskbar->area);
taskbar->area.gradients = panel->g_taskbar.gradient[TASKBAR_NORMAL];
init_area_gradients(&taskbar->area);
}
}
init_taskbarname_panel(panel);
}
@ -478,8 +486,15 @@ void update_all_taskbars_visibility()
void set_taskbar_state(Taskbar *taskbar, TaskbarState state)
{
taskbar->area.bg = panels[0].g_taskbar.background[state];
free_area_gradients(&taskbar->area);
taskbar->area.gradients = panels[0].g_taskbar.gradient[state];
init_area_gradients(&taskbar->area);
if (taskbarname_enabled) {
taskbar->bar_name.area.bg = panels[0].g_taskbar.background_name[state];
free_area_gradients(&taskbar->bar_name.area);
taskbar->bar_name.area.gradients = panels[0].g_taskbar.gradient_name[state];
init_area_gradients(&taskbar->bar_name.area);
}
update_taskbar_visibility(taskbar);

View file

@ -60,10 +60,13 @@ void init_taskbarname_panel(void *p)
taskbar->bar_name.area.parent = taskbar;
taskbar->bar_name.area.has_mouse_over_effect = panel_config.mouse_effects;
taskbar->bar_name.area.has_mouse_press_effect = panel_config.mouse_effects;
if (j == server.desktop)
if (j == server.desktop) {
taskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_ACTIVE];
else
taskbar->bar_name.area.gradients = panel->g_taskbar.gradient_name[TASKBAR_ACTIVE];
} else {
taskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_NORMAL];
taskbar->bar_name.area.gradients = panel->g_taskbar.gradient_name[TASKBAR_NORMAL];
}
// use desktop number if name is missing
if (l) {
@ -75,6 +78,7 @@ void init_taskbarname_panel(void *p)
// append the name at the beginning of taskbar
taskbar->area.children = g_list_append(taskbar->area.children, &taskbar->bar_name);
init_area_gradients(&taskbar->bar_name.area);
}
for (l = list; l; l = l->next)

View file

@ -375,6 +375,7 @@ void init(int argc, char *argv[])
#endif
debug_geometry = getenv("DEBUG_GEOMETRY") != NULL;
debug_gradients = getenv("DEBUG_GRADIENTS") != NULL;
}
static int sigchild_pipe_valid = FALSE;

View file

@ -21,6 +21,7 @@
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -481,21 +482,19 @@ void draw_background(Area *a, cairo_t *c)
a->bg->border.radius - a->bg->border.width / 1.571);
cairo_fill(c);
/*
cairo_pattern_t *cairo_gradient_pattern;
if (area_has_gradient_fill(a)) {
cairo_gradient_pattern = cairo_pattern_create_linear(0.0, 0.0, 0.0, a->height - top_bottom_border_width(a));
cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.1, a->bg->fill_color.rgb[0],
a->bg->fill_color.rgb[1], a->bg->fill_color.rgb[2], a->bg->fill_color.alpha);
cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.9, a->bg->fill_color2.rgb[0],
a->bg->fill_color2.rgb[1], a->bg->fill_color2.rgb[2], a->bg->fill_color2.alpha);
cairo_set_source(c, cairo_gradient_pattern);
} else
if (area_has_gradient_fill(a))
cairo_pattern_destroy(cairo_gradient_pattern);
*/
}
for (GList *l = a->gradient_instances; l; l = l->next) {
GradientInstance *gi = (GradientInstance *)l->data;
if (!gi->pattern)
update_gradient(gi);
cairo_set_source(c, gi->pattern);
draw_rect(c,
left_border_width(a),
top_border_width(a),
a->width - left_right_border_width(a),
a->height - top_bottom_border_width(a),
a->bg->border.radius - a->bg->border.width / 1.571);
cairo_fill(c);
}
if (a->bg->border.width > 0) {
@ -537,6 +536,8 @@ void remove_area(Area *a)
Area *area = (Area *)a;
Area *parent = (Area *)area->parent;
free_area_gradients(a);
if (parent) {
parent->children = g_list_remove(parent->children, area);
parent->resize_needed = TRUE;
@ -560,7 +561,6 @@ void add_area(Area *a, Area *parent)
schedule_redraw(parent);
panel_refresh = TRUE;
}
init_area_gradients(a);
}
void free_area(Area *a)
@ -846,86 +846,80 @@ void area_dump_geometry(Area *area, int indent)
}
}
void instantiate_gradient_offsets(Area *area, GradientInstance *gi, GList *offsets, GList **offset_instances)
Area *compute_element_area(Area *area, Element element)
{
if (element == ELEMENT_SELF)
return area;
if (element == ELEMENT_PARENT)
return (Area *)area->parent;
if (element == ELEMENT_PANEL)
return (Area *)area->panel;
g_assert_not_reached();
return area;
}
void instantiate_gradient_offsets(GradientInstance *gi, GList *offsets)
{
for (GList *l = offsets; l; l = l->next) {
Offset *offset = (Offset *)l->data;
OffsetInstance *offset_instance = (OffsetInstance *)calloc(1, sizeof(OffsetInstance));
offset_instance->constant = offset->constant;
if (offset_instance->constant) {
offset_instance->constant_value = offset->constant_value;
} else {
offset_instance->variable = offset->variable;
offset_instance->multiplier = offset->multiplier;
if (offset->variable_element == ORIGIN_ELEMENT)
offset_instance->variable_element = area;
else if (offset->variable_element == ORIGIN_PARENT)
offset_instance->variable_element = area->parent ? (Area *)area->parent : area;
else if (offset->variable_element == ORIGIN_PANEL)
offset_instance->variable_element = (Area *)area->panel;
else if (offset->variable_element == ORIGIN_SCREEN)
// TODO
offset_instance->variable_element = (Area *)area->panel;
else if (offset->variable_element == ORIGIN_DESKTOP)
// TODO
offset_instance->variable_element = (Area *)area->panel;
else
g_assert_not_reached();
*offset_instances = g_list_append(*offset_instances, offset_instance);
offset_instance->variable_element->dependent_gradients =
g_list_append(offset_instance->variable_element->dependent_gradients, gi);
gi->gradient_dependencies = g_list_append(gi->gradient_dependencies, offset_instance->variable_element);
if (!offset->constant) {
Area *element_area = compute_element_area(gi->area, offset->element);
element_area->dependent_gradients = g_list_append(element_area->dependent_gradients, gi);
}
}
}
void free_gradient_offsets(GradientInstance *gi, GList **offset_instances)
void free_gradient_offsets(GradientInstance *gi, GList **offsets)
{
for (GList *l = *offset_instances; l; l = l->next) {
OffsetInstance *offset_instance = (OffsetInstance *)l->data;
if (!offset_instance->constant) {
offset_instance->variable_element->dependent_gradients =
g_list_remove_all(offset_instance->variable_element->dependent_gradients, gi);
gi->gradient_dependencies = g_list_remove_all(gi->gradient_dependencies, offset_instance->variable_element);
for (GList *l = *offsets; l; l = l->next) {
Offset *offset = (Offset *)l->data;
if (!offset->constant) {
Area *element_area = compute_element_area(gi->area, offset->element);
element_area->dependent_gradients = g_list_remove_all(element_area->dependent_gradients, gi);
}
}
g_list_free_full(*offset_instances, free);
}
void instantiate_gradient_point(Area *area,
GradientInstance *gi,
ControlPoint *control,
ControlPointInstance *control_instance)
void instantiate_gradient_point(GradientInstance *gi, ControlPoint *control)
{
instantiate_gradient_offsets(area, gi, control->offsets_x, &control_instance->offsets_x);
instantiate_gradient_offsets(area, gi, control->offsets_y, &control_instance->offsets_y);
instantiate_gradient_offsets(area, gi, control->offsets_r, &control_instance->offsets_r);
instantiate_gradient_offsets(gi, control->offsets_x);
instantiate_gradient_offsets(gi, control->offsets_y);
instantiate_gradient_offsets(gi, control->offsets_r);
}
void free_gradient_point(GradientInstance *gi, ControlPointInstance *control_instance)
void free_gradient_point(GradientInstance *gi, ControlPoint *control)
{
free_gradient_offsets(gi, &control_instance->offsets_x);
free_gradient_offsets(gi, &control_instance->offsets_y);
free_gradient_offsets(gi, &control_instance->offsets_r);
free_gradient_offsets(gi, &control->offsets_x);
free_gradient_offsets(gi, &control->offsets_y);
free_gradient_offsets(gi, &control->offsets_r);
}
void instantiate_gradient(Area *area, GradientClass *g, GradientInstance *gi)
{
gi->gradient_class = g;
g_assert_nonnull(area);
g_assert_nonnull(g);
gi->area = area;
gi->from.origin = area;
instantiate_gradient_point(area, gi, &g->from, &gi->from);
instantiate_gradient_point(area, gi, &g->to, &gi->to);
gi->gradient_class = g;
instantiate_gradient_point(gi, &g->from);
instantiate_gradient_point(gi, &g->to);
}
void free_gradient(GradientInstance *gi)
{
free_gradient_point(gi, &gi->from);
free_gradient_point(gi, &gi->to);
if (gi->pattern) {
cairo_pattern_destroy(gi->pattern);
gi->pattern = NULL;
}
free_gradient_point(gi, &gi->gradient_class->from);
free_gradient_point(gi, &gi->gradient_class->to);
gi->gradient_class = NULL;
}
void init_area_gradients(Area *area)
{
g_assert_null(area->gradient_instances);
if (debug_gradients)
fprintf(stderr, "Initializing gradients for area %s\n", area->name);
for (GList *l = area->gradients; l; l = l->next) {
GradientClass *g = (GradientClass *)l->data;
GradientInstance *gi = (GradientInstance *)calloc(1, sizeof(GradientInstance));
@ -936,14 +930,170 @@ void init_area_gradients(Area *area)
void free_area_gradients(Area *area)
{
if (debug_gradients)
fprintf(stderr, "Freeing gradients for area %s\n", area->name);
for (GList *l = area->gradient_instances; l; l = l->next) {
GradientInstance *gi = (GradientInstance *)l->data;
free_gradient(gi);
}
g_list_free_full(area->gradient_instances, free);
area->gradient_instances = NULL;
g_assert_null(area->dependent_gradients);
}
double compute_control_point_offset(Area *area, Offset *offset)
{
if (offset->constant)
return offset->constant_value;
Area *element_area = compute_element_area(area, offset->element);
Area *parent_area = ((Area *)area->parent);
g_assert_nonnull(element_area);
g_assert_nonnull(parent_area);
double width = element_area->width;
double height = element_area->height;
double radius = sqrt(element_area->width * element_area->width + element_area->height * element_area->height) / 2.0;
double left, top;
if (offset->element == ELEMENT_SELF) {
left = 0;
top = 0;
} else if (offset->element == ELEMENT_PARENT) {
left = parent_area->posx - area->posx;
top = parent_area->posy - area->posy;
} else if (offset->element == ELEMENT_PANEL) {
left = 0 - area->posx;
top = 0 - area->posy;
}
double right = left + width;
double bottom = top + height;
double center_x = left + 0.5 * width;
double center_y = top + 0.5 * height;
if (offset->variable == SIZE_WIDTH)
return width * offset->multiplier;
if (offset->variable == SIZE_HEIGHT)
return height * offset->multiplier;
if (offset->variable == SIZE_RADIUS)
return radius * offset->multiplier;
if (offset->variable == SIZE_LEFT)
return left * offset->multiplier;
if (offset->variable == SIZE_RIGHT)
return right * offset->multiplier;
if (offset->variable == SIZE_TOP)
return top * offset->multiplier;
if (offset->variable == SIZE_BOTTOM)
return bottom * offset->multiplier;
if (offset->variable == SIZE_CENTERX)
return center_x * offset->multiplier;
if (offset->variable == SIZE_CENTERY)
return center_y * offset->multiplier;
g_assert_not_reached();
return 0;
}
double compute_control_point_offsets(GradientInstance *gi, GList *offsets)
{
double result = 0;
for (GList *l = offsets; l; l = l->next) {
Offset *offset = (Offset *)l->data;
result += compute_control_point_offset(gi->area, offset);
}
return result;
}
void compute_control_point(GradientInstance *gi, ControlPoint *control, double *x, double *y, double *r)
{
*x = compute_control_point_offsets(gi, control->offsets_x);
*y = compute_control_point_offsets(gi, control->offsets_y);
*r = compute_control_point_offsets(gi, control->offsets_r);
}
void update_gradient(GradientInstance *gi)
{
// TODO
if (gi->pattern) {
return;
cairo_pattern_destroy(gi->pattern);
gi->pattern = NULL;
}
schedule_redraw(gi->area);
double from_x, from_y, from_r;
compute_control_point(gi, &gi->gradient_class->from, &from_x, &from_y, &from_r);
double to_x, to_y, to_r;
compute_control_point(gi, &gi->gradient_class->to, &to_x, &to_y, &to_r);
if (gi->gradient_class->type == GRADIENT_VERTICAL || gi->gradient_class->type == GRADIENT_HORIZONTAL ||
gi->gradient_class->type == GRADIENT_LINEAR) {
gi->pattern = cairo_pattern_create_linear(from_x, from_y, to_x, to_y);
if (debug_gradients)
fprintf(stderr,
"Creating linear gradient for area %s: %f %f, %f %f\n",
gi->area->name,
from_x,
from_y,
to_x,
to_y);
} else if (gi->gradient_class->type == GRADIENT_CENTERED || gi->gradient_class->type == GRADIENT_RADIAL) {
gi->pattern = cairo_pattern_create_radial(from_x, from_y, from_r, to_x, to_y, to_r);
if (debug_gradients)
fprintf(stderr,
"Creating radial gradient for area %s: %f %f %f, %f %f %f\n",
gi->area->name,
from_x,
from_y,
from_r,
to_x,
to_y,
to_r);
} else {
g_assert_not_reached();
}
if (debug_gradients)
fprintf(stderr,
"Adding color stop at offset %f: %f %f %f %f\n",
0.0,
gi->gradient_class->start_color.rgb[0],
gi->gradient_class->start_color.rgb[1],
gi->gradient_class->start_color.rgb[2],
gi->gradient_class->start_color.alpha);
cairo_pattern_add_color_stop_rgba(gi->pattern,
0,
gi->gradient_class->start_color.rgb[0],
gi->gradient_class->start_color.rgb[1],
gi->gradient_class->start_color.rgb[2],
gi->gradient_class->start_color.alpha);
for (GList *l = gi->gradient_class->extra_color_stops; l; l = l->next) {
ColorStop *color_stop = (ColorStop *)l->data;
if (debug_gradients)
fprintf(stderr,
"Adding color stop at offset %f: %f %f %f %f\n",
color_stop->offset,
color_stop->color.rgb[0],
color_stop->color.rgb[1],
color_stop->color.rgb[2],
color_stop->color.alpha);
cairo_pattern_add_color_stop_rgba(gi->pattern,
color_stop->offset,
color_stop->color.rgb[0],
color_stop->color.rgb[1],
color_stop->color.rgb[2],
color_stop->color.alpha);
}
if (debug_gradients)
fprintf(stderr,
"Adding color stop at offset %f: %f %f %f %f\n",
1.0,
gi->gradient_class->end_color.rgb[0],
gi->gradient_class->end_color.rgb[1],
gi->gradient_class->end_color.rgb[2],
gi->gradient_class->end_color.alpha);
cairo_pattern_add_color_stop_rgba(gi->pattern,
1.0,
gi->gradient_class->end_color.rgb[0],
gi->gradient_class->end_color.rgb[1],
gi->gradient_class->end_color.rgb[2],
gi->gradient_class->end_color.alpha);
schedule_redraw(gi->area);
}

View file

@ -199,101 +199,44 @@ void get_color(char *hex, double *rgb)
rgb[2] = (b / 255.0);
}
void extract_values(const char *value, char **value1, char **value2, char **value3)
void extract_values(const char *str, char **value1, char **value2, char **value3)
{
char *value0 = strdup(value);
char *b = 0, *c = 0;
if (*value1)
free(*value1);
if (*value2)
free(*value2);
if (*value3)
free(*value3);
if ((b = strchr(value0, ' '))) {
b[0] = '\0';
b++;
} else {
*value2 = 0;
*value3 = 0;
}
*value1 = strdup(value0);
g_strstrip(*value1);
if (b) {
if ((c = strchr(b, ' '))) {
c[0] = '\0';
c++;
} else {
c = 0;
*value3 = 0;
*value1 = NULL;
*value2 = NULL;
*value3 = NULL;
char **tokens = g_strsplit(str, " ", 3);
if (tokens[0]) {
*value1 = strdup(tokens[0]);
if (tokens[1]) {
*value2 = strdup(tokens[1]);
if (tokens[2]) {
*value3 = strdup(tokens[2]);
}
}
*value2 = strdup(b);
g_strstrip(*value2);
}
if (c) {
*value3 = strdup(c);
g_strstrip(*value3);
}
free(value0);
g_strfreev(tokens);
}
void extract_values_4(const char *value, char **value1, char **value2, char **value3, char **value4)
void extract_values_4(const char *str, char **value1, char **value2, char **value3, char **value4)
{
char *value0 = strdup(value);
char *b = 0, *c = 0, *d;
if (*value1)
free(*value1);
if (*value2)
free(*value2);
if (*value3)
free(*value3);
if (*value4)
free(*value4);
if ((b = strchr(value0, ' '))) {
b[0] = '\0';
b++;
} else {
*value2 = 0;
*value3 = 0;
*value4 = 0;
}
*value1 = strdup(value0);
g_strstrip(*value1);
if (b) {
if ((c = strchr(b, ' '))) {
c[0] = '\0';
c++;
} else {
c = 0;
*value3 = 0;
*value4 = 0;
*value1 = NULL;
*value2 = NULL;
*value3 = NULL;
*value4 = NULL;
char **tokens = g_strsplit(str, " ", 4);
if (tokens[0]) {
*value1 = strdup(tokens[0]);
if (tokens[1]) {
*value2 = strdup(tokens[1]);
if (tokens[2]) {
*value3 = strdup(tokens[2]);
if (tokens[3]) {
*value4 = strdup(tokens[3]);
}
}
}
*value2 = strdup(b);
g_strstrip(*value2);
}
if (c) {
if ((d = strchr(c, ' '))) {
d[0] = '\0';
d++;
} else {
d = 0;
*value4 = 0;
}
*value3 = strdup(c);
g_strstrip(*value3);
*value4 = strdup(d);
g_strstrip(*value4);
}
free(value0);
g_strfreev(tokens);
}
void adjust_asb(DATA32 *data, int w, int h, float alpha_adjust, float satur_adjust, float bright_adjust)

View file

@ -48,38 +48,30 @@ GradientType gradient_type_from_string(const char *str)
return GRADIENT_VERTICAL;
}
gboolean read_origin_from_string(const char *str, Origin *element)
gboolean read_element_from_string(const char *str, Element *element)
{
if (g_str_equal(str, "element")) {
*element = ORIGIN_ELEMENT;
if (g_str_equal(str, "self")) {
*element = ELEMENT_SELF;
return TRUE;
}
if (g_str_equal(str, "parent")) {
*element = ORIGIN_PARENT;
*element = ELEMENT_PARENT;
return TRUE;
}
if (g_str_equal(str, "panel")) {
*element = ORIGIN_PANEL;
return TRUE;
}
if (g_str_equal(str, "screen")) {
*element = ORIGIN_SCREEN;
return TRUE;
}
if (g_str_equal(str, "desktop")) {
*element = ORIGIN_DESKTOP;
*element = ELEMENT_PANEL;
return TRUE;
}
return FALSE;
}
Origin origin_from_string(const char *str)
Element element_from_string(const char *str)
{
Origin result;
if (read_origin_from_string(str, &result))
Element result;
if (read_element_from_string(str, &result))
return result;
fprintf(stderr, RED "Invalid origin type: %s" RESET "\n", str);
return ORIGIN_ELEMENT;
return ELEMENT_SELF;
}
gboolean read_size_from_string(const char *str, SizeVariable *variable)
@ -92,6 +84,10 @@ gboolean read_size_from_string(const char *str, SizeVariable *variable)
*variable = SIZE_HEIGHT;
return TRUE;
}
if (g_str_equal(str, "radius")) {
*variable = SIZE_RADIUS;
return TRUE;
}
if (g_str_equal(str, "left")) {
*variable = SIZE_LEFT;
return TRUE;
@ -108,24 +104,24 @@ gboolean read_size_from_string(const char *str, SizeVariable *variable)
*variable = SIZE_BOTTOM;
return TRUE;
}
if (g_str_equal(str, "center")) {
*variable = SIZE_CENTER;
if (g_str_equal(str, "centerx")) {
*variable = SIZE_CENTERX;
return TRUE;
}
if (g_str_equal(str, "radius")) {
*variable = SIZE_RADIUS;
if (g_str_equal(str, "centery")) {
*variable = SIZE_CENTERY;
return TRUE;
}
return FALSE;
}
gboolean read_size_variable_from_string(const char *str,
Origin *variable_element,
Element *variable_element,
SizeVariable *variable,
double *multiplier)
{
if (read_size_from_string(str, variable)) {
*variable_element = ORIGIN_ELEMENT;
*variable_element = ELEMENT_SELF;
*multiplier = 1;
return TRUE;
}
@ -133,8 +129,8 @@ gboolean read_size_variable_from_string(const char *str,
char *value1 = 0, *value2 = 0, *value3 = 0, *value4 = 0;
extract_values_4(str, &value1, &value2, &value3, &value4);
if (value1 && value2 && !value3) {
if (read_origin_from_string(value1, variable_element) && read_size_from_string(value2, variable)) {
if (value1 && !value2) {
if (read_size_from_string(value1, variable)) {
*multiplier = 1;
if (value1)
free(value1);
@ -148,8 +144,38 @@ gboolean read_size_variable_from_string(const char *str,
}
}
if (value1 && value2 && !value3) {
if (read_element_from_string(value1, variable_element) && read_size_from_string(value2, variable)) {
*multiplier = 1;
if (value1)
free(value1);
if (value2)
free(value2);
if (value3)
free(value3);
if (value4)
free(value4);
return TRUE;
}
}
if (value1 && value2 && value3 && !value4) {
if (read_size_from_string(value1, variable) && g_str_equal(value2, "*") &&
read_double_with_percent(value3, multiplier)) {
if (value1)
free(value1);
if (value2)
free(value2);
if (value3)
free(value3);
if (value4)
free(value4);
return TRUE;
}
}
if (value1 && value2 && value3 && value4) {
if (read_origin_from_string(value1, variable_element) && read_size_from_string(value2, variable) &&
if (read_element_from_string(value1, variable_element) && read_size_from_string(value2, variable) &&
g_str_equal(value3, "*") && read_double_with_percent(value4, multiplier)) {
if (value1)
free(value1);
@ -178,18 +204,21 @@ gboolean read_size_variable_from_string(const char *str,
Offset *offset_from_string(const char *str)
{
Offset *offset = (Offset *)calloc(1, sizeof(Offset));
// number ?
if (read_double(str, &offset->constant_value)) {
offset->constant = TRUE;
return offset;
}
// SIZE ?
offset->constant = FALSE;
if (read_size_variable_from_string(str, &offset->variable_element, &offset->variable, &offset->multiplier)) {
if (read_size_variable_from_string(str, &offset->element, &offset->variable, &offset->multiplier)) {
if (debug_gradients)
fprintf(stderr,
"Read offset '%s' as: %d %d %f\n",
str,
offset->element,
offset->variable,
offset->multiplier);
return offset;
}
free(offset);
return NULL;
}
@ -199,63 +228,61 @@ void init_gradient(GradientClass *g, GradientType type)
memset(g, 0, sizeof(*g));
g->type = type;
if (g->type == GRADIENT_VERTICAL) {
g->from.origin = ORIGIN_ELEMENT;
Offset *offset_top = (Offset *)calloc(1, sizeof(Offset));
offset_top->constant = TRUE;
offset_top->constant_value = 0;
g->from.offsets_y = g_list_append(g->from.offsets_y, offset_top);
Offset *offset_bottom = (Offset *)calloc(1, sizeof(Offset));
offset_bottom->constant = FALSE;
offset_bottom->variable_element = ORIGIN_ELEMENT;
offset_bottom->element = ELEMENT_SELF;
offset_bottom->variable = SIZE_HEIGHT;
offset_bottom->multiplier = 1.0;
g->from.offsets_y = g_list_append(g->from.offsets_y, offset_bottom);
g->to.offsets_y = g_list_append(g->to.offsets_y, offset_bottom);
} else if (g->type == GRADIENT_HORIZONTAL) {
g->from.origin = ORIGIN_ELEMENT;
Offset *offset_left = (Offset *)calloc(1, sizeof(Offset));
offset_left->constant = TRUE;
offset_left->constant_value = 0;
g->from.offsets_x = g_list_append(g->from.offsets_x, offset_left);
Offset *offset_right = (Offset *)calloc(1, sizeof(Offset));
offset_right->constant = FALSE;
offset_right->variable_element = ORIGIN_ELEMENT;
offset_right->element = ELEMENT_SELF;
offset_right->variable = SIZE_WIDTH;
offset_right->multiplier = 1.0;
g->from.offsets_x = g_list_append(g->from.offsets_x, offset_right);
g->to.offsets_x = g_list_append(g->to.offsets_x, offset_right);
} else if (g->type == GRADIENT_CENTERED) {
g->from.origin = ORIGIN_ELEMENT;
// from
Offset *offset_center_x = (Offset *)calloc(1, sizeof(Offset));
offset_center_x->constant = FALSE;
offset_center_x->variable_element = ORIGIN_ELEMENT;
offset_center_x->variable = SIZE_CENTER;
offset_center_x->element = ELEMENT_SELF;
offset_center_x->variable = SIZE_CENTERX;
offset_center_x->multiplier = 1.0;
g->from.offsets_x = g_list_append(g->from.offsets_x, offset_center_x);
Offset *offset_center_y = (Offset *)calloc(1, sizeof(Offset));
offset_center_y->constant = FALSE;
offset_center_y->variable_element = ORIGIN_ELEMENT;
offset_center_y->variable = SIZE_CENTER;
offset_center_y->element = ELEMENT_SELF;
offset_center_y->variable = SIZE_CENTERY;
offset_center_y->multiplier = 1.0;
g->from.offsets_y = g_list_append(g->from.offsets_y, offset_center_y);
Offset *offset_center_r = (Offset *)calloc(1, sizeof(Offset));
offset_center_x->constant = TRUE;
offset_center_x->constant_value = 0;
offset_center_r->constant = TRUE;
offset_center_r->constant_value = 0;
g->from.offsets_r = g_list_append(g->from.offsets_r, offset_center_r);
g->to.origin = ORIGIN_ELEMENT;
// to
offset_center_x = (Offset *)calloc(1, sizeof(Offset));
offset_center_x->constant = FALSE;
offset_center_x->variable_element = ORIGIN_ELEMENT;
offset_center_x->variable = SIZE_CENTER;
offset_center_x->element = ELEMENT_SELF;
offset_center_x->variable = SIZE_CENTERX;
offset_center_x->multiplier = 1.0;
g->to.offsets_x = g_list_append(g->to.offsets_x, offset_center_x);
offset_center_y = (Offset *)calloc(1, sizeof(Offset));
offset_center_y->constant = FALSE;
offset_center_y->variable_element = ORIGIN_ELEMENT;
offset_center_y->variable = SIZE_CENTER;
offset_center_y->element = ELEMENT_SELF;
offset_center_y->variable = SIZE_CENTERY;
offset_center_y->multiplier = 1.0;
g->to.offsets_y = g_list_append(g->to.offsets_y, offset_center_y);
offset_center_r = (Offset *)calloc(1, sizeof(Offset));
offset_center_r->constant = FALSE;
offset_center_r->variable_element = ORIGIN_ELEMENT;
offset_center_r->element = ELEMENT_SELF;
offset_center_r->variable = SIZE_RADIUS;
offset_center_r->multiplier = 1.0;
g->to.offsets_r = g_list_append(g->to.offsets_r, offset_center_r);
@ -275,4 +302,5 @@ void cleanup_gradient(GradientClass *g)
g_list_free_full(g->to.offsets_x, free);
g_list_free_full(g->to.offsets_y, free);
g_list_free_full(g->to.offsets_r, free);
bzero(g, sizeof(*g));
}

View file

@ -23,23 +23,22 @@ typedef struct ColorStop {
double offset;
} ColorStop;
typedef enum Origin {
ORIGIN_ELEMENT = 0,
ORIGIN_PARENT,
ORIGIN_PANEL,
ORIGIN_SCREEN,
ORIGIN_DESKTOP
} Origin;
typedef enum Element {
ELEMENT_SELF = 0,
ELEMENT_PARENT,
ELEMENT_PANEL
} Element;
typedef enum SizeVariable {
SIZE_WIDTH = 0,
SIZE_HEIGHT,
SIZE_RADIUS,
SIZE_LEFT,
SIZE_RIGHT,
SIZE_TOP,
SIZE_BOTTOM,
SIZE_CENTER,
SIZE_RADIUS
SIZE_CENTERX,
SIZE_CENTERY
} SizeVariable;
typedef struct Offset {
@ -47,13 +46,12 @@ typedef struct Offset {
// if constant == true
double constant_value;
// else
Origin variable_element;
Element element;
SizeVariable variable;
double multiplier;
} Offset;
typedef struct ControlPoint {
Origin origin;
// Each element is an Offset
GList *offsets_x;
GList *offsets_y;
@ -72,7 +70,7 @@ typedef struct GradientClass {
} GradientClass;
GradientType gradient_type_from_string(const char *str);
Origin origin_from_string(const char *str);
Element element_from_string(const char *str);
Offset *offset_from_string(const char *str);
void init_gradient(GradientClass *g, GradientType type);
void cleanup_gradient(GradientClass *g);
@ -83,33 +81,12 @@ void cleanup_gradient(GradientClass *g);
struct Area;
typedef struct Area Area;
typedef struct OffsetInstance {
gboolean constant;
// if constant == true
double constant_value;
// else
Area *variable_element;
SizeVariable variable;
double multiplier;
} OffsetInstance;
typedef struct ControlPointInstance {
Area *origin;
// Each element is an OffsetInstance
GList *offsets_x;
GList *offsets_y;
GList *offsets_r;
} ControlPointInstance;
typedef struct GradientInstance {
GradientClass *gradient_class;
Area *area;
ControlPointInstance from;
ControlPointInstance to;
cairo_pattern_t *pattern;
// Each element is an Area whose geometry is used to compute this gradient
// TODO why do we need it?
GList *gradient_dependencies;
} GradientInstance;
extern gboolean debug_gradients;
#endif // GRADIENT_H