Merge branch 'color-palette-feature' into dev

This commit is contained in:
Mario Hüttel 2019-06-13 22:25:54 +02:00
commit f5f8509b91
4 changed files with 192 additions and 3 deletions

View File

@ -61,6 +61,7 @@ struct _GdsRenderGui {
GList *gds_libraries; GList *gds_libraries;
ActivityBar *activity_status_bar; ActivityBar *activity_status_bar;
struct render_settings render_dialog_settings; struct render_settings render_dialog_settings;
ColorPalette *palette;
}; };
G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT) G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
@ -239,6 +240,20 @@ end_destroy:
gtk_widget_destroy(open_dialog); gtk_widget_destroy(open_dialog);
} }
/**
* @brief Callback for auto coloring button
* @param button
* @param user
*/
static void on_auto_color_clicked(gpointer button, gpointer user)
{
GdsRenderGui *self;
(void)button;
self = RENDERER_GUI(user);
layer_selector_auto_color_layers(self->layer_selector, self->palette, 1.0);
}
/** /**
* @brief Convert button callback * @brief Convert button callback
* @param button * @param button
@ -445,6 +460,7 @@ static void gds_render_gui_dispose(GObject *gobject)
g_clear_object(&self->cell_tree_store); g_clear_object(&self->cell_tree_store);
g_clear_object(&self->cell_search_entry); g_clear_object(&self->cell_search_entry);
g_clear_object(&self->activity_status_bar); g_clear_object(&self->activity_status_bar);
g_clear_object(&self->palette);
if (self->main_window) { if (self->main_window) {
g_signal_handlers_destroy(self->main_window); g_signal_handlers_destroy(self->main_window);
@ -488,6 +504,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
GtkWidget *sort_up_button; GtkWidget *sort_up_button;
GtkWidget *sort_down_button; GtkWidget *sort_down_button;
GtkWidget *activity_bar_box; GtkWidget *activity_bar_box;
GtkWidget *auto_color_button;
main_builder = gtk_builder_new_from_resource("/gui/main.glade"); main_builder = gtk_builder_new_from_resource("/gui/main.glade");
@ -538,19 +555,24 @@ static void gds_render_gui_init(GdsRenderGui *self)
g_signal_connect(GTK_WIDGET(self->main_window), "delete-event", g_signal_connect(GTK_WIDGET(self->main_window), "delete-event",
G_CALLBACK(on_window_close), self); G_CALLBACK(on_window_close), self);
g_object_unref(main_builder);
/* Create and apply ActivityBar */ /* Create and apply ActivityBar */
self->activity_status_bar = activity_bar_new(); self->activity_status_bar = activity_bar_new();
gtk_container_add(GTK_CONTAINER(activity_bar_box), GTK_WIDGET(self->activity_status_bar)); gtk_container_add(GTK_CONTAINER(activity_bar_box), GTK_WIDGET(self->activity_status_bar));
gtk_widget_show(GTK_WIDGET(self->activity_status_bar)); gtk_widget_show(GTK_WIDGET(self->activity_status_bar));
/* Create color palette */
self->palette = color_palette_new_from_resource("/data/color-palette.txt");
auto_color_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "auto-color-button"));
g_signal_connect(auto_color_button, "clicked", G_CALLBACK(on_auto_color_clicked), self);
/* Set default conversion/rendering settings */ /* Set default conversion/rendering settings */
self->render_dialog_settings.scale = 1000; self->render_dialog_settings.scale = 1000;
self->render_dialog_settings.renderer = RENDERER_LATEX_TIKZ; self->render_dialog_settings.renderer = RENDERER_LATEX_TIKZ;
self->render_dialog_settings.tex_pdf_layers = FALSE; self->render_dialog_settings.tex_pdf_layers = FALSE;
self->render_dialog_settings.tex_standalone = FALSE; self->render_dialog_settings.tex_standalone = FALSE;
g_object_unref(main_builder);
/* Reference all objects referenced by this object */ /* Reference all objects referenced by this object */
g_object_ref(self->activity_status_bar); g_object_ref(self->activity_status_bar);
@ -560,6 +582,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
g_object_ref(self->layer_selector); g_object_ref(self->layer_selector);
g_object_ref(self->cell_tree_store); g_object_ref(self->cell_tree_store);
g_object_ref(self->cell_search_entry); g_object_ref(self->cell_search_entry);
g_object_ref(self->palette);
} }
GdsRenderGui *gds_render_gui_new() GdsRenderGui *gds_render_gui_new()

View File

@ -33,6 +33,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <glib.h> #include <glib.h>
#include <gds-render/layer/color-palette.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -90,6 +91,14 @@ GList *layer_selector_export_rendered_layer_info(LayerSelector *selector);
*/ */
void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function); void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function);
/**
* @brief Apply colors from palette to all layers. Aditionally set alpha
* @param layer_selector LayerSelector object
* @param palette Color palette to use
* @param global_alpha Additional alpha value that is applied to all layers
*/
void layer_selector_auto_color_layers(LayerSelector *layer_selector, ColorPalette *palette, double global_alpha);
G_END_DECLS G_END_DECLS
#endif /* __LAYER_SELECTOR_H__ */ #endif /* __LAYER_SELECTOR_H__ */

View File

@ -40,6 +40,40 @@ struct _ColorPalette {
G_DEFINE_TYPE(ColorPalette, color_palette, G_TYPE_OBJECT) G_DEFINE_TYPE(ColorPalette, color_palette, G_TYPE_OBJECT)
/**
* @brief Return the number of non empty lines in array
*
* This function returns the number of non empty lines in an
* array. The scanning is either terminated by the given length
* or if a \0 terminator is found.
*
* @param[in] data Array to count lines in
* @param[in] length Length of \p data
* @return < 0: Error, >=0: Lines
*/
static int count_non_empty_lines_in_array(const char *data, size_t length)
{
unsigned int idx;
int non_empty_lines;
char last_char = '\n';
if (!data)
return -1;
/* Count each '\n' as a new line if it is not directly preceded by another '\n' */
for (idx = 0; idx < length && data[idx]; idx++) {
if (data[idx] == '\n' && last_char != '\n')
non_empty_lines++;
last_char = data[idx];
}
/* Count the last line in case the data does not end with a '\n' */
if (data[idx-1] != '\n')
non_empty_lines++;
return non_empty_lines;
}
/** /**
* @brief color_palette_fill_with_resource * @brief color_palette_fill_with_resource
* @param palette * @param palette
@ -49,7 +83,16 @@ G_DEFINE_TYPE(ColorPalette, color_palette, G_TYPE_OBJECT)
static int color_palette_fill_with_resource(ColorPalette *palette, char *resource_name) static int color_palette_fill_with_resource(ColorPalette *palette, char *resource_name)
{ {
GBytes *data; GBytes *data;
char *char_array; char line[10];
int line_idx;
unsigned int color_idx;
int idx;
const char *char_array;
gsize byte_count;
int lines;
GRegex *regex;
GMatchInfo *mi;
char *match;
if (!palette || !resource_name) if (!palette || !resource_name)
return -1; return -1;
@ -59,7 +102,81 @@ static int color_palette_fill_with_resource(ColorPalette *palette, char *resourc
if (!data) if (!data)
return -2; return -2;
char_array = (const char *)g_bytes_get_data(data, &byte_count);
if (!char_array || !byte_count)
goto ret_unref;
/* Get maximum lenght of color palette, assuming all entries are valid */
lines = count_non_empty_lines_in_array(char_array, byte_count);
if (lines <= 0)
goto ret_unref;
palette->color_array = (GdkRGBA *)malloc(sizeof(GdkRGBA) * (unsigned int)lines);
/* Setup regex for hexadecimal RGB colors like 'A0CB3F' */
regex = g_regex_new("^(?<red>[0-9A-Fa-f][0-9A-Fa-f])(?<green>[0-9A-Fa-f][0-9A-Fa-f])(?<blue>[0-9A-Fa-f][0-9A-Fa-f])$", 0, 0, NULL);
/* Reset line */
line_idx = 0;
line[0] = '\0';
/* Set color index */
color_idx = 0;
/* interate over lines and match */
for (idx = 0 ; idx < byte_count; idx++) {
/* Fillup line. */
line[line_idx] = char_array[idx];
/* If end of line/string is reached, process */
if (line[line_idx] == '\n' || line[line_idx] == '\0') {
line[line_idx] = '\0';
/* Match the line */
g_regex_match(regex, line, 0, &mi);
if (g_match_info_matches(mi) && color_idx < lines) {
match = g_match_info_fetch_named(mi, "red");
palette->color_array[color_idx].red = (double)g_ascii_strtoll(match, NULL, 16) / 255.0;
g_free(match);
match = g_match_info_fetch_named(mi, "green");
palette->color_array[color_idx].green = (double)g_ascii_strtoll(match, NULL, 16) / 255.0;
g_free(match);
match = g_match_info_fetch_named(mi, "blue");
palette->color_array[color_idx].blue = (double)g_ascii_strtoll(match, NULL, 16) / 255.0;
g_free(match);
/* Only RGB supported so far. Fix alpha channel to 1.0 */
palette->color_array[color_idx].alpha = 1.0;
color_idx++;
}
g_match_info_free(mi);
/* End of string */
if (char_array[idx] == '\0')
break;
line_idx = 0;
continue;
}
/* increment line index. If end is reached write all bytes to the line end
* line is longer than required for parsing. This ensures, that everything works as expected
*/
line_idx += (line_idx < sizeof(line)-1 ? 1 : 0);
}
/* Data read; Shrink array in case of invalid lines */
palette->color_array = realloc(palette->color_array, (size_t)color_idx * sizeof(GdkRGBA));
palette->color_array_length = color_idx;
g_regex_unref(regex);
ret_unref:
g_bytes_unref(data); g_bytes_unref(data);
return 0; return 0;

View File

@ -781,4 +781,44 @@ void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort
gtk_list_box_set_sort_func(box, NULL, NULL, NULL); gtk_list_box_set_sort_func(box, NULL, NULL, NULL);
} }
void layer_selector_auto_color_layers(LayerSelector *layer_selector, ColorPalette *palette, double global_alpha)
{
GList *le_list;
GList *le_list_ptr;
LayerElement *le;
unsigned int color_index = 0;
unsigned int color_count;
GdkRGBA color;
if (GDS_RENDER_IS_COLOR_PALETTE(palette) == FALSE || LAYER_IS_SELECTOR(layer_selector) == FALSE)
return;
if (global_alpha <= 0)
return;
if (GTK_IS_LIST_BOX(layer_selector->list_box) == FALSE)
return;
le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
/* iterate over layer elements and fill colors */
color_index = 0;
color_count = color_palette_get_color_count(palette);
if (color_count == 0)
goto ret_free_le_list;
for (le_list_ptr = le_list; le_list_ptr != NULL; le_list_ptr = le_list_ptr->next) {
le = LAYER_ELEMENT(le_list_ptr->data);
if (le) {
color_palette_get_color(palette, &color, color_index++);
color.alpha *= global_alpha;
layer_element_set_color(le, &color);
if (color_index >= color_count)
color_index = 0;
}
}
ret_free_le_list:
g_list_free(le_list);
}
/** @} */ /** @} */