Gradients: mostly done
This commit is contained in:
286
src/util/area.c
286
src/util/area.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user