Compare commits
3 Commits
32b8c4ccd3
...
a10c09c674
Author | SHA1 | Date | |
---|---|---|---|
a10c09c674 | |||
a0d19bee39 | |||
4115fd97af |
@ -293,6 +293,15 @@ static void async_rendering_finished_callback(GdsOutputRenderer *renderer, gpoin
|
|||||||
g_object_unref(renderer);
|
g_object_unref(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void async_rendering_status_update_callback(GdsOutputRenderer *renderer, const char *status_message, gpointer data)
|
||||||
|
{
|
||||||
|
GdsRenderGui *gui;
|
||||||
|
(void)renderer;
|
||||||
|
|
||||||
|
gui = RENDERER_GUI(data);
|
||||||
|
activity_bar_set_busy(gui->activity_status_bar, status_message);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert button callback
|
* @brief Convert button callback
|
||||||
* @param button
|
* @param button
|
||||||
@ -426,6 +435,9 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
|||||||
|
|
||||||
activity_bar_set_busy(self->activity_status_bar, "Rendering cell...");
|
activity_bar_set_busy(self->activity_status_bar, "Rendering cell...");
|
||||||
/* TODO: Replace this with asynchronous rendering. However, this fixes issue #19 */
|
/* TODO: Replace this with asynchronous rendering. However, this fixes issue #19 */
|
||||||
|
|
||||||
|
g_signal_connect(render_engine, "progress-changed",
|
||||||
|
G_CALLBACK(async_rendering_status_update_callback), self);
|
||||||
gds_output_renderer_render_output_async(render_engine, cell_to_render, sett->scale);
|
gds_output_renderer_render_output_async(render_engine, cell_to_render, sett->scale);
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,6 +144,16 @@ void gds_output_renderer_set_layer_settings(GdsOutputRenderer *renderer, LayerSe
|
|||||||
*/
|
*/
|
||||||
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale);
|
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function emits the 'progress-changed' in the thread/context that triggered an asynchronous rendering
|
||||||
|
*
|
||||||
|
* If the rendering is not asynchronous, this function has no effect.
|
||||||
|
*
|
||||||
|
* @param renderer GdsOutputrenderer object
|
||||||
|
* @param status Status to supply to signal emission
|
||||||
|
*/
|
||||||
|
void gds_output_renderer_update_gui_status_from_async(GdsOutputRenderer *renderer, const char *status);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _GDS_OUTPUT_RENDERER_H_ */
|
#endif /* _GDS_OUTPUT_RENDERER_H_ */
|
||||||
|
@ -400,6 +400,7 @@ static int cairo_renderer_render_output(GdsOutputRenderer *renderer,
|
|||||||
else
|
else
|
||||||
pdf_file = output_file;
|
pdf_file = output_file;
|
||||||
|
|
||||||
|
gds_output_renderer_update_gui_status_from_async(renderer, "Rendering Cairo Output...");
|
||||||
ret = cairo_renderer_render_cell_to_vector_file(cell, layer_infos, pdf_file, svg_file, scale);
|
ret = cairo_renderer_render_cell_to_vector_file(cell, layer_infos, pdf_file, svg_file, scale);
|
||||||
|
|
||||||
if (settings)
|
if (settings)
|
||||||
|
@ -38,13 +38,20 @@ struct renderer_params {
|
|||||||
double scale;
|
double scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct idle_function_params {
|
||||||
|
GMutex message_lock;
|
||||||
|
char *status_message;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gchar *output_file;
|
gchar *output_file;
|
||||||
LayerSettings *layer_settings;
|
LayerSettings *layer_settings;
|
||||||
GMutex settings_lock;
|
GMutex settings_lock;
|
||||||
gboolean mutex_init_status;
|
gboolean mutex_init_status;
|
||||||
GTask *task;
|
GTask *task;
|
||||||
|
GMainContext *main_context;
|
||||||
struct renderer_params async_params;
|
struct renderer_params async_params;
|
||||||
|
struct idle_function_params idle_function_parameters;
|
||||||
gpointer padding[11];
|
gpointer padding[11];
|
||||||
} GdsOutputRendererPrivate;
|
} GdsOutputRendererPrivate;
|
||||||
|
|
||||||
@ -56,7 +63,7 @@ enum {
|
|||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE(GdsOutputRenderer, gds_output_renderer, G_TYPE_OBJECT)
|
G_DEFINE_TYPE_WITH_PRIVATE(GdsOutputRenderer, gds_output_renderer, G_TYPE_OBJECT)
|
||||||
|
|
||||||
enum gds_output_renderer_signal_ids {ASYNC_FINISHED = 0, ASYNC_PROGRESS_UPDATE, GDS_OUTPUT_RENDERER_SIGNAL_COUNT};
|
enum gds_output_renderer_signal_ids {ASYNC_FINISHED = 0, ASYNC_PROGRESS_CHANGED, GDS_OUTPUT_RENDERER_SIGNAL_COUNT};
|
||||||
static guint gds_output_renderer_signals[GDS_OUTPUT_RENDERER_SIGNAL_COUNT];
|
static guint gds_output_renderer_signals[GDS_OUTPUT_RENDERER_SIGNAL_COUNT];
|
||||||
|
|
||||||
static int gds_output_renderer_render_dummy(GdsOutputRenderer *renderer,
|
static int gds_output_renderer_render_dummy(GdsOutputRenderer *renderer,
|
||||||
@ -83,6 +90,11 @@ static void gds_output_renderer_dispose(GObject *self_obj)
|
|||||||
g_mutex_lock(&priv->settings_lock);
|
g_mutex_lock(&priv->settings_lock);
|
||||||
g_mutex_unlock(&priv->settings_lock);
|
g_mutex_unlock(&priv->settings_lock);
|
||||||
g_mutex_clear(&priv->settings_lock);
|
g_mutex_clear(&priv->settings_lock);
|
||||||
|
|
||||||
|
g_mutex_lock(&priv->idle_function_parameters.message_lock);
|
||||||
|
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||||
|
g_mutex_clear(&priv->idle_function_parameters.message_lock);
|
||||||
|
|
||||||
priv->mutex_init_status = FALSE;
|
priv->mutex_init_status = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +162,7 @@ static GParamSpec *gds_output_renderer_properties[N_PROPERTIES] = {NULL};
|
|||||||
static void gds_output_renderer_class_init(GdsOutputRendererClass *klass)
|
static void gds_output_renderer_class_init(GdsOutputRendererClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
|
GType progress_changed_param_types[1] = {G_TYPE_POINTER};
|
||||||
|
|
||||||
klass->render_output = gds_output_renderer_render_dummy;
|
klass->render_output = gds_output_renderer_render_dummy;
|
||||||
|
|
||||||
@ -157,6 +170,7 @@ static void gds_output_renderer_class_init(GdsOutputRendererClass *klass)
|
|||||||
oclass->set_property = gds_output_renderer_set_property;
|
oclass->set_property = gds_output_renderer_set_property;
|
||||||
oclass->get_property = gds_output_renderer_get_property;
|
oclass->get_property = gds_output_renderer_get_property;
|
||||||
|
|
||||||
|
|
||||||
/* Setup properties */
|
/* Setup properties */
|
||||||
gds_output_renderer_properties[PROP_OUTPUT_FILE] =
|
gds_output_renderer_properties[PROP_OUTPUT_FILE] =
|
||||||
g_param_spec_string("output-file", "output file", "Output file for renderer",
|
g_param_spec_string("output-file", "output file", "Output file for renderer",
|
||||||
@ -178,16 +192,16 @@ static void gds_output_renderer_class_init(GdsOutputRendererClass *klass)
|
|||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
gds_output_renderer_signals[ASYNC_PROGRESS_UPDATE] =
|
gds_output_renderer_signals[ASYNC_PROGRESS_CHANGED] =
|
||||||
g_signal_newv("progress-update", GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
g_signal_newv("progress-changed", GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
|
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0,
|
1,
|
||||||
NULL);
|
progress_changed_param_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gds_output_renderer_init(GdsOutputRenderer *self)
|
void gds_output_renderer_init(GdsOutputRenderer *self)
|
||||||
@ -200,7 +214,10 @@ void gds_output_renderer_init(GdsOutputRenderer *self)
|
|||||||
priv->output_file = NULL;
|
priv->output_file = NULL;
|
||||||
priv->task = NULL;
|
priv->task = NULL;
|
||||||
priv->mutex_init_status = TRUE;
|
priv->mutex_init_status = TRUE;
|
||||||
|
priv->main_context = NULL;
|
||||||
|
priv->idle_function_parameters.status_message = NULL;
|
||||||
g_mutex_init(&priv->settings_lock);
|
g_mutex_init(&priv->settings_lock);
|
||||||
|
g_mutex_init(&priv->idle_function_parameters.message_lock);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -334,8 +351,13 @@ static void gds_output_renderer_async_finished(GObject *src_obj, GAsyncResult *r
|
|||||||
|
|
||||||
priv = gds_output_renderer_get_instance_private(GDS_RENDER_OUTPUT_RENDERER(src_obj));
|
priv = gds_output_renderer_get_instance_private(GDS_RENDER_OUTPUT_RENDERER(src_obj));
|
||||||
|
|
||||||
|
priv->main_context = NULL;
|
||||||
|
|
||||||
g_signal_emit(src_obj, gds_output_renderer_signals[ASYNC_FINISHED], 0);
|
g_signal_emit(src_obj, gds_output_renderer_signals[ASYNC_FINISHED], 0);
|
||||||
g_clear_object(&priv->task);
|
g_clear_object(&priv->task);
|
||||||
|
|
||||||
|
/* Clear reference set in gds_output_renderer_render_output_async() */
|
||||||
|
g_object_unref(src_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale)
|
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale)
|
||||||
@ -353,11 +375,73 @@ int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct
|
|||||||
g_mutex_lock(&priv->settings_lock);
|
g_mutex_lock(&priv->settings_lock);
|
||||||
priv->async_params.cell = cell;
|
priv->async_params.cell = cell;
|
||||||
priv->async_params.scale = scale;
|
priv->async_params.scale = scale;
|
||||||
|
priv->main_context = g_main_context_default();
|
||||||
g_mutex_unlock(&priv->settings_lock);
|
g_mutex_unlock(&priv->settings_lock);
|
||||||
|
|
||||||
|
/* Self reference. This could end up being nasty... */
|
||||||
|
g_object_ref(renderer);
|
||||||
|
|
||||||
|
/* Do the magic */
|
||||||
g_task_run_in_thread(priv->task, gds_output_renderer_async_wrapper);
|
g_task_run_in_thread(priv->task, gds_output_renderer_async_wrapper);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean idle_event_processor_callback(gpointer user_data)
|
||||||
|
{
|
||||||
|
GdsOutputRenderer *renderer;
|
||||||
|
GdsOutputRendererPrivate *priv;
|
||||||
|
char *status_message;
|
||||||
|
|
||||||
|
/* If the rendering is finished before the mainloop gets to this point
|
||||||
|
* the renderer is already disposed. Catch this!
|
||||||
|
*/
|
||||||
|
if (!GDS_RENDER_IS_OUTPUT_RENDERER(user_data))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
renderer = GDS_RENDER_OUTPUT_RENDERER(user_data);
|
||||||
|
priv = gds_output_renderer_get_instance_private(renderer);
|
||||||
|
|
||||||
|
if (g_mutex_trylock(&priv->idle_function_parameters.message_lock)) {
|
||||||
|
status_message = priv->idle_function_parameters.status_message;
|
||||||
|
g_signal_emit(renderer, gds_output_renderer_signals[ASYNC_PROGRESS_CHANGED], 0, status_message);
|
||||||
|
g_free(priv->idle_function_parameters.status_message);
|
||||||
|
priv->idle_function_parameters.status_message = NULL;
|
||||||
|
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gds_output_renderer_update_gui_status_from_async(GdsOutputRenderer *renderer, const char *status)
|
||||||
|
{
|
||||||
|
GSource *idle_event_processor;
|
||||||
|
GdsOutputRendererPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail(GDS_RENDER_IS_OUTPUT_RENDERER(renderer));
|
||||||
|
if (!status)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv = gds_output_renderer_get_instance_private(renderer);
|
||||||
|
|
||||||
|
/* If rendering is not async */
|
||||||
|
if (!priv->main_context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_mutex_lock(&priv->idle_function_parameters.message_lock);
|
||||||
|
|
||||||
|
if (priv->idle_function_parameters.status_message)
|
||||||
|
g_free(priv->idle_function_parameters.status_message);
|
||||||
|
|
||||||
|
priv->idle_function_parameters.status_message = g_strdup(status);
|
||||||
|
|
||||||
|
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||||
|
|
||||||
|
idle_event_processor = g_idle_source_new();
|
||||||
|
g_source_set_callback(idle_event_processor, idle_event_processor_callback, (gpointer)renderer, NULL);
|
||||||
|
g_source_attach(idle_event_processor, priv->main_context);
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -227,12 +227,18 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
|
|||||||
* @param buffer Working buffer
|
* @param buffer Working buffer
|
||||||
* @param scale Scale output down by this value
|
* @param scale Scale output down by this value
|
||||||
*/
|
*/
|
||||||
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale)
|
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale,
|
||||||
|
GdsOutputRenderer *renderer)
|
||||||
{
|
{
|
||||||
|
GString *status;
|
||||||
GList *list_child;
|
GList *list_child;
|
||||||
struct gds_cell_instance *inst;
|
struct gds_cell_instance *inst;
|
||||||
|
|
||||||
|
status = g_string_new(NULL);
|
||||||
|
g_string_printf(status, "Generating cell %s", cell->name);
|
||||||
|
gds_output_renderer_update_gui_status_from_async(renderer, status->str);
|
||||||
|
g_string_free(status, TRUE);
|
||||||
|
|
||||||
/* Draw polygons of current cell */
|
/* Draw polygons of current cell */
|
||||||
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer, scale);
|
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer, scale);
|
||||||
|
|
||||||
@ -256,7 +262,7 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
|
|||||||
inst->magnification);
|
inst->magnification);
|
||||||
WRITEOUT_BUFFER(buffer);
|
WRITEOUT_BUFFER(buffer);
|
||||||
|
|
||||||
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale);
|
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale, renderer);
|
||||||
|
|
||||||
g_string_printf(buffer, "\\end{scope}\n");
|
g_string_printf(buffer, "\\end{scope}\n");
|
||||||
WRITEOUT_BUFFER(buffer);
|
WRITEOUT_BUFFER(buffer);
|
||||||
@ -271,7 +277,7 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
|
static int latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
|
||||||
gboolean create_pdf_layers, gboolean standalone_document)
|
gboolean create_pdf_layers, gboolean standalone_document, GdsOutputRenderer *renderer)
|
||||||
{
|
{
|
||||||
GString *working_line;
|
GString *working_line;
|
||||||
|
|
||||||
@ -304,7 +310,7 @@ static int latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos,
|
|||||||
WRITEOUT_BUFFER(working_line);
|
WRITEOUT_BUFFER(working_line);
|
||||||
|
|
||||||
/* Generate graphics output */
|
/* Generate graphics output */
|
||||||
render_cell(cell, layer_infos, tex_file, working_line, scale);
|
render_cell(cell, layer_infos, tex_file, working_line, scale, renderer);
|
||||||
|
|
||||||
|
|
||||||
g_string_printf(working_line, "\\end{tikzpicture}\n");
|
g_string_printf(working_line, "\\end{tikzpicture}\n");
|
||||||
@ -344,7 +350,7 @@ static int latex_renderer_render_output(GdsOutputRenderer *renderer,
|
|||||||
tex_file = fopen(output_file, "w");
|
tex_file = fopen(output_file, "w");
|
||||||
if (tex_file) {
|
if (tex_file) {
|
||||||
ret = latex_render_cell_to_code(cell, layer_infos, tex_file, scale,
|
ret = latex_render_cell_to_code(cell, layer_infos, tex_file, scale,
|
||||||
l_renderer->pdf_layers, l_renderer->tex_standalone);
|
l_renderer->pdf_layers, l_renderer->tex_standalone, renderer);
|
||||||
fclose(tex_file);
|
fclose(tex_file);
|
||||||
} else {
|
} else {
|
||||||
g_error("Could not open LaTeX output file");
|
g_error("Could not open LaTeX output file");
|
||||||
|
Loading…
Reference in New Issue
Block a user