Merge branch 'multithread-dev' into color-palette-feature

Get newest changes
This commit is contained in:
Mario Hüttel 2019-06-07 19:35:02 +02:00
commit e847e691bd
9 changed files with 236 additions and 9 deletions

View File

@ -33,6 +33,8 @@
#include <cairo-svg.h> #include <cairo-svg.h>
#include <gds-render/cairo-renderer/cairo-output.h> #include <gds-render/cairo-renderer/cairo-output.h>
#include <sys/wait.h>
#include <unistd.h>
/** /**
* @brief The cairo_layer struct * @brief The cairo_layer struct
@ -181,8 +183,8 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale) void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale)
{ {
cairo_surface_t *pdf_surface, *svg_surface; cairo_surface_t *pdf_surface = NULL, *svg_surface = NULL;
cairo_t *pdf_cr, *svg_cr; cairo_t *pdf_cr = NULL, *svg_cr = NULL;
struct layer_info *linfo; struct layer_info *linfo;
struct cairo_layer *layers; struct cairo_layer *layers;
struct cairo_layer *lay; struct cairo_layer *lay;
@ -190,12 +192,26 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
int i; int i;
double rec_x0, rec_y0, rec_width, rec_height; double rec_x0, rec_y0, rec_width, rec_height;
double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN; double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN;
pid_t process_id;
if (pdf_file == NULL && svg_file == NULL) { if (pdf_file == NULL && svg_file == NULL) {
/* No output specified */ /* No output specified */
return; return;
} }
/* Fork to a new child process. This ensures the memory leaks (see issue #16) in Cairo don't
* brick everything.
*
* And by the way: This now bricks all Windows compatibility. Deal with it.
*/
process_id = fork();
if (process_id < 0) {
/* Well... shit... We have to run it in our process. */
} else if (process_id > 0) {
/* Woohoo... Successfully dumped the shitty code to an unknowing victim */
goto ret_parent;
}
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer)); layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
/* Clear layers */ /* Clear layers */
@ -276,16 +292,15 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
continue; continue;
} }
if (pdf_file) { if (pdf_file && pdf_cr) {
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin); cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha); cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
} }
if (svg_file) { if (svg_file && svg_cr) {
cairo_set_source_surface(svg_cr, layers[linfo->layer].rec, -xmin, -ymin); cairo_set_source_surface(svg_cr, layers[linfo->layer].rec, -xmin, -ymin);
cairo_paint_with_alpha(svg_cr, linfo->color.alpha); cairo_paint_with_alpha(svg_cr, linfo->color.alpha);
} }
} }
if (pdf_file) { if (pdf_file) {
@ -310,7 +325,17 @@ ret_clear_layers:
} }
free(layers); free(layers);
printf("cairo export finished. It might still be buggy!\n"); printf("Cairo export finished. It might still be buggy!\n");
/* If forked, suspend process */
if (process_id == 0)
exit(0);
/* Fork didn't work. Just return here */
return;
ret_parent:
waitpid(process_id, NULL, 0);
return;
} }
/** @} */ /** @} */

6
doxygen/activity-bar.dox Normal file
View File

@ -0,0 +1,6 @@
/**
* @defgroup ActivityBar
* @ingroup Widgets
*
* Activity Status Bar
*/

View File

@ -31,6 +31,6 @@ In tabular form: *v1.0-rc4-41-gaa41373-dirty*
| 1.0-rc4 | 41 | aa41373 | yes | | 1.0-rc4 | 41 | aa41373 | yes |
This git-based version number is automatically put into the application and this doxumentation during the application's compilation / the documentation's generation. For this *git* is needed. Therefore, it is highly recommended to have 'git' installed for compilation although it is no build dependency. In case of a missing git installation, the string "! version not set !" is compiled into the application. This git-based version number is automatically put into the application and this documentation during the application's compilation / the documentation's generation. For this *git* is needed. Therefore, it is highly recommended to have 'git' installed for compilation although it is no build dependency. In case of a missing git installation, the string "! version not set !" is compiled into the application.
**/ **/

View File

@ -34,6 +34,7 @@
#include <gds-render/gds-utils/gds-parser.h> #include <gds-render/gds-utils/gds-parser.h>
#include <gds-render/gds-utils/gds-tree-checker.h> #include <gds-render/gds-utils/gds-tree-checker.h>
#include <gds-render/layer/layer-selector.h> #include <gds-render/layer/layer-selector.h>
#include <gds-render/widgets/activity-bar.h>
#include <gds-render/tree-renderer/tree-store.h> #include <gds-render/tree-renderer/tree-store.h>
#include <gds-render/tree-renderer/lib-cell-renderer.h> #include <gds-render/tree-renderer/lib-cell-renderer.h>
#include <gds-render/latex-renderer/latex-output.h> #include <gds-render/latex-renderer/latex-output.h>
@ -58,6 +59,7 @@ struct _GdsRenderGui {
LayerSelector *layer_selector; LayerSelector *layer_selector;
GtkTreeView *cell_tree_view; GtkTreeView *cell_tree_view;
GList *gds_libraries; GList *gds_libraries;
ActivityBar *activity_status_bar;
struct render_settings render_dialog_settings; struct render_settings render_dialog_settings;
}; };
@ -442,6 +444,7 @@ static void gds_render_gui_dispose(GObject *gobject)
g_clear_object(&self->layer_selector); g_clear_object(&self->layer_selector);
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);
if (self->main_window) { if (self->main_window) {
g_signal_handlers_destroy(self->main_window); g_signal_handlers_destroy(self->main_window);
@ -484,6 +487,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
struct tree_stores *cell_selector_stores; struct tree_stores *cell_selector_stores;
GtkWidget *sort_up_button; GtkWidget *sort_up_button;
GtkWidget *sort_down_button; GtkWidget *sort_down_button;
GtkWidget *activity_bar_box;
main_builder = gtk_builder_new_from_resource("/gui/main.glade"); main_builder = gtk_builder_new_from_resource("/gui/main.glade");
@ -505,6 +509,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
/* Create layer selector */ /* Create layer selector */
self->layer_selector = layer_selector_new(GTK_LIST_BOX(listbox)); self->layer_selector = layer_selector_new(GTK_LIST_BOX(listbox));
activity_bar_box = GTK_WIDGET(gtk_builder_get_object(main_builder, "activity-bar"));
/* Callback for selection change of cell selector */ /* Callback for selection change of cell selector */
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(self->cell_tree_view)), "changed", g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(self->cell_tree_view)), "changed",
@ -535,6 +540,11 @@ static void gds_render_gui_init(GdsRenderGui *self)
g_object_unref(main_builder); 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));
/* 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;
@ -543,6 +553,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
/* 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->main_window); g_object_ref(self->main_window);
g_object_ref(self->cell_tree_view); g_object_ref(self->cell_tree_view);
g_object_ref(self->convert_button); g_object_ref(self->convert_button);

View File

@ -53,7 +53,8 @@
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */ #define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */
#if GDS_PRINT_DEBUG_INFOS #if GDS_PRINT_DEBUG_INFOS
#define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__) /**< @brief standard printf. But can be disabled in code */ /**< @brief standard printf. But can be disabled in code. */
#define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else #else
#define GDS_INF(fmt, ...) #define GDS_INF(fmt, ...)
#endif #endif
@ -813,7 +814,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
if (current_s_reference) { if (current_s_reference) {
name_cell_ref(current_s_reference, (unsigned int)read, workbuff); name_cell_ref(current_s_reference, (unsigned int)read, workbuff);
} else { } else {
GDS_ERROR("reference name set outside of cell reference.\n"); GDS_ERROR("Reference name set outside of cell reference");
} }
break; break;
case WIDTH: case WIDTH:

View File

@ -37,7 +37,21 @@
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */ #define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
/**
* @brief Parse a GDS file
*
* This function parses a GDS File and creates a list of libraries,
* which then contain the different cells.
*
* The function appends The detected libraries to the \p library_array list.
* The library array may be empty, meaning *library_list may be NULL.
*
* @param filename[in] Path to the GDS file
* @param library_array[in] GList Pointer.
* @return 0 if successful
*/
int parse_gds_from_file(const char *filename, GList **library_array); int parse_gds_from_file(const char *filename, GList **library_array);
/** /**
* @brief Deletes all libraries including cells, references etc. * @brief Deletes all libraries including cells, references etc.
* @param library_list Pointer to a list of #gds_library. Is set to NULL after completion. * @param library_list Pointer to a list of #gds_library. Is set to NULL after completion.

View File

@ -0,0 +1,60 @@
/*
* GDSII-Converter
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file activity-bar.h
* @brief Header file for activity bar widget
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup ActivityBar
* @ingroup Widgets
* @{
*/
#ifndef __LAYER_ELEMENT_H__
#define __LAYER_ELEMENT_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/* Creates Class structure etc */
G_DECLARE_FINAL_TYPE(ActivityBar, activity_bar, ACTIVITY, BAR, GtkBox)
#define TYPE_ACTIVITY_BAR (activity_bar_get_type())
/**
* @brief Create new Object ActivityBar
* @return New object. In case of error: NULL.
*/
ActivityBar *activity_bar_new();
/**
* @brief Deletes all applied tasks and sets bar to "Ready".
* @param[in] bar AcitivityBar object.
*/
void activity_bar_set_ready(ActivityBar *bar);
G_END_DECLS
#endif /* __LAYER_ELEMENT_H__ */
/** @} */

View File

@ -121,6 +121,7 @@ unsigned int color_palette_get_color_count(ColorPalette *palette)
static void color_palette_class_init(ColorPaletteClass *klass) static void color_palette_class_init(ColorPaletteClass *klass)
{ {
(void)klass;
/* Nothing to do for now */ /* Nothing to do for now */
return; return;
} }

109
widgets/activity-bar.c Normal file
View File

@ -0,0 +1,109 @@
/*
* GDSII-Converter
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* The drag and drop implementation is adapted from
* https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/tests/testlist3.c
*
* Thanks to the GTK3 people for creating these examples.
*/
/**
* @file activity-bar.c
* @brief Status bar indicating activity of the program
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup ActivityBar
* @ingroup Widgets
* @{
*/
#include <gds-render/widgets/activity-bar.h>
/** @brief Opaque ActivityBar object. Not viewable outside this source file. */
struct _ActivityBar {
GtkBox super;
/* Private stuff */
GtkWidget *spinner;
GtkWidget *label;
};
G_DEFINE_TYPE(ActivityBar, activity_bar, GTK_TYPE_BOX)
static void activity_bar_dispose(GObject *obj)
{
ActivityBar *bar;
bar = ACTIVITY_BAR(obj);
/* Clear references on owned objects */
g_clear_object(&bar->label);
g_clear_object(&bar->spinner);
/* Chain up */
G_OBJECT_CLASS(activity_bar_parent_class)->dispose(obj);
}
static void activity_bar_class_init(ActivityBarClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->dispose = activity_bar_dispose;
}
static void activity_bar_init(ActivityBar *self)
{
GtkContainer *box = GTK_CONTAINER(self);
/* Create Widgets */
self->label = gtk_label_new("");
self->spinner = gtk_spinner_new();
/* Add to this widget and show */
gtk_container_add(box, self->spinner);
gtk_container_add(box, self->label);
gtk_widget_show(self->label);
gtk_widget_show(self->spinner);
g_object_ref(self->spinner);
g_object_ref(self->label);
}
ActivityBar *activity_bar_new()
{
ActivityBar *bar;
bar = ACTIVITY_BAR(g_object_new(TYPE_ACTIVITY_BAR, "orientation", GTK_ORIENTATION_HORIZONTAL, NULL));
if (bar)
activity_bar_set_ready(bar);
return bar;
}
/* TODO: Complete this once the task list is fully implemented */
void activity_bar_set_ready(ActivityBar *bar)
{
gtk_label_set_text(GTK_LABEL(bar->label), "Ready");
gtk_spinner_stop(GTK_SPINNER(bar->spinner));
}
/** @} */