Compare commits

...

8 Commits

Author SHA1 Message Date
f5f8509b91 Merge branch 'color-palette-feature' into dev 2019-06-13 22:25:54 +02:00
61f607ac94 Add autocoloring to layer selector. Auto coloring feature now fully implemented. Fix #14 2019-06-13 22:22:59 +02:00
ee1b55120f Gui: Add button callback for auto color button 2019-06-13 22:21:35 +02:00
b04788b7d4 Layer selector: Add prototype and empty function body for function that
fills all layers with colors from a given color palette.
2019-06-13 22:21:35 +02:00
3c05b50bc7 Gui: Add color palette object to gui. Will be used in button callback to
fill layer colors automatically.
2019-06-13 22:21:35 +02:00
dfadaa241e Color palette: Finish implementation
Color palette can now be loaded from a resource containing hexadecimal
RGB values.
2019-06-13 22:21:28 +02:00
e847e691bd Merge branch 'multithread-dev' into color-palette-feature
Get newest changes
2019-06-07 19:35:02 +02:00
6ae316f459 Edit color palette code 2019-05-28 20:05:13 +02:00
4 changed files with 192 additions and 3 deletions

View File

@ -61,6 +61,7 @@ struct _GdsRenderGui {
GList *gds_libraries;
ActivityBar *activity_status_bar;
struct render_settings render_dialog_settings;
ColorPalette *palette;
};
G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
@ -239,6 +240,20 @@ end_destroy:
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
* @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_search_entry);
g_clear_object(&self->activity_status_bar);
g_clear_object(&self->palette);
if (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_down_button;
GtkWidget *activity_bar_box;
GtkWidget *auto_color_button;
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_CALLBACK(on_window_close), self);
g_object_unref(main_builder);
/* Create and apply ActivityBar */
self->activity_status_bar = activity_bar_new();
gtk_container_add(GTK_CONTAINER(activity_bar_box), 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 */
self->render_dialog_settings.scale = 1000;
self->render_dialog_settings.renderer = RENDERER_LATEX_TIKZ;
self->render_dialog_settings.tex_pdf_layers = FALSE;
self->render_dialog_settings.tex_standalone = FALSE;
g_object_unref(main_builder);
/* Reference all objects referenced by this object */
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->cell_tree_store);
g_object_ref(self->cell_search_entry);
g_object_ref(self->palette);
}
GdsRenderGui *gds_render_gui_new()

View File

@ -33,6 +33,7 @@
#include <gtk/gtk.h>
#include <glib.h>
#include <gds-render/layer/color-palette.h>
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);
/**
* @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
#endif /* __LAYER_SELECTOR_H__ */

View File

@ -40,6 +40,40 @@ struct _ColorPalette {
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
* @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)
{
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)
return -1;
@ -59,7 +102,81 @@ static int color_palette_fill_with_resource(ColorPalette *palette, char *resourc
if (!data)
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);
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);
}
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);
}
/** @} */