Issue #19: Add LayerSettings Class
* Remove Command line and GUI rendering code * Add LayerSettings Class with all options * Prepare to remove mapping parser. Is now integrated in LayerSettings * Adopt all renderers to check if the supplied layer_info struct has to be rendered. Further todos: * Implement correct command line parsing. * Implement Layerselector and GUI to use new LayerSettings class
This commit is contained in:
parent
f5bc8de86e
commit
3ffd63115f
@ -55,8 +55,17 @@ static void delete_layer_info_with_name(struct layer_info *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void command_line_convert_gds(const char *gds_name, const char *cell_name, const char *output_file_name, const char *layer_file, const char *so_path,
|
static void check_renderers_and_output_files()
|
||||||
enum command_line_renderer renderer, enum cmd_options options, double scale)
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_line_convert_gds(const char *gds_name,
|
||||||
|
const char *cell_name,
|
||||||
|
const char * const *renderers,
|
||||||
|
const char * const *output_file_names,
|
||||||
|
const char *layer_file,
|
||||||
|
const char *so_path)
|
||||||
{
|
{
|
||||||
GList *libs = NULL;
|
GList *libs = NULL;
|
||||||
int res;
|
int res;
|
||||||
@ -77,11 +86,13 @@ void command_line_convert_gds(const char *gds_name, const char *cell_name, const
|
|||||||
gboolean tex_layers = FALSE, tex_standalone = FALSE;
|
gboolean tex_layers = FALSE, tex_standalone = FALSE;
|
||||||
|
|
||||||
/* Check if parameters are valid */
|
/* Check if parameters are valid */
|
||||||
if (!gds_name || !cell_name || !output_file_name || !layer_file) {
|
if (!gds_name || !cell_name || !output_file_names || !layer_file || !renderers) {
|
||||||
printf("Probably missing argument. Check --help option\n");
|
printf("Probably missing argument. Check --help option\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Load GDS */
|
/* Load GDS */
|
||||||
clear_lib_list(&libs);
|
clear_lib_list(&libs);
|
||||||
res = parse_gds_from_file(gds_name, &libs);
|
res = parse_gds_from_file(gds_name, &libs);
|
||||||
@ -167,39 +178,8 @@ void command_line_convert_gds(const char *gds_name, const char *cell_name, const
|
|||||||
|
|
||||||
/* Render */
|
/* Render */
|
||||||
|
|
||||||
if (options & CMD_OPT_LATEX_LAYERS)
|
|
||||||
tex_layers = TRUE;
|
|
||||||
if (options & CMD_OPT_LATEX_STANDALONE)
|
|
||||||
tex_standalone = TRUE;
|
|
||||||
|
|
||||||
switch (renderer) {
|
|
||||||
case CMD_CAIRO_SVG:
|
|
||||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_svg());
|
|
||||||
break;
|
|
||||||
case CMD_LATEX:
|
|
||||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(latex_renderer_new_with_options(tex_layers, tex_standalone));
|
|
||||||
break;
|
|
||||||
case CMD_CAIRO_PDF:
|
|
||||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_pdf());
|
|
||||||
break;
|
|
||||||
case CMD_EXTERNAL:
|
|
||||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(external_renderer_new_with_so(so_path));
|
|
||||||
break;
|
|
||||||
case CMD_NONE:
|
|
||||||
/* Do nothing */
|
|
||||||
output_renderer = NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
output_renderer = NULL;
|
|
||||||
fprintf(stderr, "Invalid renderer supplied");
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output_renderer) {
|
|
||||||
gds_output_renderer_render_output(output_renderer, toplevel_cell, layer_info_list, output_file_name, scale);
|
|
||||||
g_object_unref(output_renderer);
|
|
||||||
}
|
|
||||||
/* Render end */
|
/* Render end */
|
||||||
ret_clear_layer_list:
|
ret_clear_layer_list:
|
||||||
g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name);
|
g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name);
|
||||||
|
@ -37,8 +37,8 @@
|
|||||||
#include <gds-render/widgets/activity-bar.h>
|
#include <gds-render/widgets/activity-bar.h>
|
||||||
#include <gds-render/cell-selector/tree-store.h>
|
#include <gds-render/cell-selector/tree-store.h>
|
||||||
#include <gds-render/cell-selector/lib-cell-renderer.h>
|
#include <gds-render/cell-selector/lib-cell-renderer.h>
|
||||||
#include <gds-render/output-renderers/latex-output.h>
|
//#include <gds-render/output-renderers/latex-output.h>
|
||||||
#include <gds-render/output-renderers/cairo-output.h>
|
//#include <gds-render/output-renderers/cairo-output.h>
|
||||||
#include <gds-render/widgets/conv-settings-dialog.h>
|
#include <gds-render/widgets/conv-settings-dialog.h>
|
||||||
#include <gds-render/geometric/cell-geometrics.h>
|
#include <gds-render/geometric/cell-geometrics.h>
|
||||||
#include <gds-render/version.h>
|
#include <gds-render/version.h>
|
||||||
@ -296,7 +296,7 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Get layers that are rendered */
|
/* Get layers that are rendered */
|
||||||
layer_list = layer_selector_export_rendered_layer_info(self->layer_selector);
|
//layer_list = layer_selector_export_rendered_layer_info(self->layer_selector);
|
||||||
|
|
||||||
/* Calculate cell size in DB units */
|
/* Calculate cell size in DB units */
|
||||||
bounding_box_prepare_empty(&cell_box);
|
bounding_box_prepare_empty(&cell_box);
|
||||||
@ -360,13 +360,13 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
|||||||
switch (sett->renderer) {
|
switch (sett->renderer) {
|
||||||
case RENDERER_LATEX_TIKZ:
|
case RENDERER_LATEX_TIKZ:
|
||||||
output_file = fopen(file_name, "w");
|
output_file = fopen(file_name, "w");
|
||||||
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett->scale,
|
/*latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett->scale,
|
||||||
sett->tex_pdf_layers, sett->tex_standalone);
|
sett->tex_pdf_layers, sett->tex_standalone);
|
||||||
fclose(output_file);
|
*/fclose(output_file);
|
||||||
break;
|
break;
|
||||||
case RENDERER_CAIROGRAPHICS_SVG:
|
case RENDERER_CAIROGRAPHICS_SVG:
|
||||||
case RENDERER_CAIROGRAPHICS_PDF:
|
case RENDERER_CAIROGRAPHICS_PDF:
|
||||||
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
/*cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
||||||
(sett->renderer == RENDERER_CAIROGRAPHICS_PDF
|
(sett->renderer == RENDERER_CAIROGRAPHICS_PDF
|
||||||
? file_name
|
? file_name
|
||||||
: NULL),
|
: NULL),
|
||||||
@ -374,7 +374,7 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
|||||||
? file_name
|
? file_name
|
||||||
: NULL),
|
: NULL),
|
||||||
sett->scale);
|
sett->scale);
|
||||||
break;
|
*/break;
|
||||||
}
|
}
|
||||||
g_free(file_name);
|
g_free(file_name);
|
||||||
|
|
||||||
@ -382,7 +382,8 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
|||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
ret_layer_destroy:
|
ret_layer_destroy:
|
||||||
g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
|
;
|
||||||
|
// g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,32 +33,21 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
enum command_line_renderer {
|
|
||||||
CMD_NONE = 0,
|
|
||||||
CMD_EXTERNAL,
|
|
||||||
CMD_CAIRO_SVG,
|
|
||||||
CMD_CAIRO_PDF,
|
|
||||||
CMD_LATEX,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum cmd_options {
|
|
||||||
CMD_OPT_NONE = 0U,
|
|
||||||
CMD_OPT_LATEX_STANDALONE = (1U<<0),
|
|
||||||
CMD_OPT_LATEX_LAYERS = (1U<<1),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief render output file according to command line parameters
|
* @brief Convert GDS according to command line parameters
|
||||||
* @param gds_name Name of GDS file
|
* @param gds_name Path to GDS File
|
||||||
* @param cell_name Name of cell to render
|
* @param cell_name Cell name
|
||||||
* @param output_file_name Output file name
|
* @param renderers Renderer ids
|
||||||
* @param so_file Shared object file to search external rendering function
|
* @param output_file_names Output file names
|
||||||
* @param renderer Type of output renderer
|
* @param layer_file Layer mapping file
|
||||||
* @param options Additional options for output renderer
|
* @param so_path Shared object path
|
||||||
* @param scale Scale value
|
|
||||||
*/
|
*/
|
||||||
void command_line_convert_gds(const char *gds_name, const char *cell_name, const char *output_file_name, const char *layer_file,
|
void command_line_convert_gds(const char *gds_name,
|
||||||
const char *so_file, enum command_line_renderer renderer, enum cmd_options options, double scale);
|
const char *cell_name,
|
||||||
|
const char * const *renderers,
|
||||||
|
const char * const *output_file_names,
|
||||||
|
const char *layer_file,
|
||||||
|
const char *so_path);
|
||||||
|
|
||||||
#endif /* _COMMAND_LINE_H_ */
|
#endif /* _COMMAND_LINE_H_ */
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file layer-info.h
|
* @file layer-info.h
|
||||||
* @brief Helper functions and definition of layer info struct
|
* @brief LayerSettings class heade file
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -28,24 +28,92 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Layer information.
|
* @brief Layer information.
|
||||||
*
|
*
|
||||||
* This structs contains information on how to render a layer
|
* This structs contains information on how to render a layer
|
||||||
|
* @note You probably don't want to use this struct standalone but in combination
|
||||||
|
* with a LayerSettings object.
|
||||||
*/
|
*/
|
||||||
struct layer_info
|
struct layer_info
|
||||||
{
|
{
|
||||||
int layer; /**< @brief Layer number */
|
int layer; /**< @brief Layer number */
|
||||||
char *name; /**< @brief Layer name */
|
char *name; /**< @brief Layer name. */
|
||||||
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
||||||
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
||||||
|
int render; /**< @brief true: Render to output */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(LayerSettings, layer_settings, GDS_RENDER, LAYER_SETTINGS, GObject)
|
||||||
|
|
||||||
|
#define GDS_RENDER_TYPE_LAYER_SETTINGS (layer_settings_get_type())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete a layer_info struct
|
* @brief Maximum length of a layer mapping CSV line
|
||||||
* @param info Struct to be deleted.
|
|
||||||
* @note The layer_info::name Element has to be freed manually
|
|
||||||
*/
|
*/
|
||||||
void layer_info_delete_struct(struct layer_info *info);
|
#define CSV_LINE_MAX_LEN (1024)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief New LayerSettings object
|
||||||
|
* @return New object
|
||||||
|
*/
|
||||||
|
LayerSettings *layer_settings_new();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief layer_settings_append_layer_info
|
||||||
|
* @param settings LayerSettings object.
|
||||||
|
* @param info Info to append
|
||||||
|
* @return Error code. 0 if successful
|
||||||
|
* @note \p info is copied internally. You can free this struct afterwards.
|
||||||
|
*/
|
||||||
|
int layer_settings_append_layer_info(LayerSettings *settings, struct layer_info *info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear all layers in this settings object
|
||||||
|
* @param settings LayerSettings object
|
||||||
|
*/
|
||||||
|
void layer_settings_clear(LayerSettings *settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a specific layer number from the layer settings.
|
||||||
|
* @param settings LayerSettings object
|
||||||
|
* @param layer Layer number
|
||||||
|
* @return Error code. 0 if successful
|
||||||
|
*/
|
||||||
|
int layer_settings_remove_layer(LayerSettings *settings, int layer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a GList with layer_info structs
|
||||||
|
*
|
||||||
|
* This function returns a GList with all layer_info structs in rendering order
|
||||||
|
* (bottom to top) that shall be rendered.
|
||||||
|
*
|
||||||
|
* @param settings LayerSettings object
|
||||||
|
* @return GList with struct layer_info elements.
|
||||||
|
*/
|
||||||
|
GList *layer_settings_get_layer_info_list(LayerSettings *settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write layer settings to a CSV file
|
||||||
|
* @param path
|
||||||
|
* @return 0 if successful
|
||||||
|
*/
|
||||||
|
int layer_settings_to_csv(LayerSettings *settings, const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load new layer Settings from CSV
|
||||||
|
*
|
||||||
|
* This function loads the layer information from a CSV file.
|
||||||
|
* All data inside the \p settings is cleared beforehand.
|
||||||
|
*
|
||||||
|
* @param settings Settings to write to.
|
||||||
|
* @param path CSV file path
|
||||||
|
* @return 0 if successful
|
||||||
|
*/
|
||||||
|
int layer_settings_load_from_csv(LayerSettings *settings, const char *path);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
#endif // _LAYER_INFO_H_
|
#endif // _LAYER_INFO_H_
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include <gds-render/widgets/layer-element.h>
|
#include <gds-render/widgets/layer-element.h>
|
||||||
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load a line from \p stream and parse try to parse it as layer information
|
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <gds-render/gds-utils/gds-types.h>
|
#include <gds-render/gds-utils/gds-types.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -53,8 +54,6 @@ struct _GdsOutputRendererClass {
|
|||||||
*/
|
*/
|
||||||
int (*render_output)(GdsOutputRenderer *renderer,
|
int (*render_output)(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale);
|
double scale);
|
||||||
gpointer padding[4];
|
gpointer padding[4];
|
||||||
};
|
};
|
||||||
@ -70,21 +69,64 @@ enum {
|
|||||||
*/
|
*/
|
||||||
GdsOutputRenderer *gds_output_renderer_new();
|
GdsOutputRenderer *gds_output_renderer_new();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new GdsOutputRenderer GObject with its properties
|
||||||
|
* @param output_file Output file of the renderer
|
||||||
|
* @param layer_settings Layer settings object
|
||||||
|
* @return New object
|
||||||
|
*/
|
||||||
|
GdsOutputRenderer *gds_output_renderer_new_with_props(const char *output_file, LayerSettings *layer_settings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gds_output_renderer_render_output
|
* @brief gds_output_renderer_render_output
|
||||||
* @param renderer Renderer object
|
* @param renderer Renderer object
|
||||||
* @param cell Cell to render
|
* @param cell Cell to render
|
||||||
* @param layer_infos List of Layer information (@ref layer_info)
|
|
||||||
* @param output_file Output file name
|
|
||||||
* @param scale scale value. The output is scaled *down* by this value
|
* @param scale scale value. The output is scaled *down* by this value
|
||||||
* @return 0 if successful
|
* @return 0 if successful
|
||||||
*/
|
*/
|
||||||
int gds_output_renderer_render_output(GdsOutputRenderer *renderer,
|
int gds_output_renderer_render_output(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale);
|
double scale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenience function for setting the "output-file" property
|
||||||
|
* @param renderer Renderer object
|
||||||
|
* @param file_name Output file path
|
||||||
|
*/
|
||||||
|
void gds_output_renderer_set_output_file(GdsOutputRenderer *renderer, const gchar *file_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenience function for getting the "output-file" property
|
||||||
|
* @param renderer
|
||||||
|
* @return Output file path. This must not be freed
|
||||||
|
*/
|
||||||
|
const char *gds_output_renderer_get_output_file(GdsOutputRenderer *renderer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get layer settings
|
||||||
|
*
|
||||||
|
* This is a convenience function for getting the
|
||||||
|
* "layer-settings" property
|
||||||
|
*
|
||||||
|
* @param renderer Renderer
|
||||||
|
* @return Layer settings object
|
||||||
|
*/
|
||||||
|
LayerSettings *gds_output_renderer_get_layer_settings(GdsOutputRenderer *renderer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set layer settings
|
||||||
|
*
|
||||||
|
* This is a convenience function for setting the
|
||||||
|
* "layer-settings" property.
|
||||||
|
*
|
||||||
|
* If another Layer settings has previously been supplied,
|
||||||
|
* it is unref'd.
|
||||||
|
*
|
||||||
|
* @param renderer Renderer
|
||||||
|
* @param settings LayerSettings object
|
||||||
|
*/
|
||||||
|
void gds_output_renderer_set_layer_settings(GdsOutputRenderer *renderer, LayerSettings *settings);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _GDS_OUTPUT_RENDERER_H_ */
|
#endif /* _GDS_OUTPUT_RENDERER_H_ */
|
||||||
|
@ -19,15 +19,313 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file layer-info.c
|
* @file layer-info.c
|
||||||
* @brief Helper functions for layer info struct
|
* @brief Implementation of the LayerSettings class
|
||||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gds-render/layer/layer-info.h>
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
void layer_info_delete_struct(struct layer_info *info)
|
struct _LayerSettings {
|
||||||
|
GObject parent;
|
||||||
|
GList *layer_infos;
|
||||||
|
gpointer padding[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(LayerSettings, layer_settings, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void layer_settings_init(LayerSettings *self)
|
||||||
{
|
{
|
||||||
if (info)
|
self->layer_infos = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_settings_class_init(LayerSettingsClass *klass)
|
||||||
|
{
|
||||||
|
(void)klass;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy layer_info struct
|
||||||
|
*
|
||||||
|
* This function copies a layer info struct.
|
||||||
|
* Be aware, that it does not only copy the pointer to the
|
||||||
|
* layer name, but instead duplicates the string.
|
||||||
|
*
|
||||||
|
* @param info Info to copy
|
||||||
|
* @return new layer_info struct
|
||||||
|
*/
|
||||||
|
static struct layer_info *layer_info_copy(const struct layer_info * const info)
|
||||||
|
{
|
||||||
|
struct layer_info *copy;
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
copy = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||||
|
if (!copy)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Copy data */
|
||||||
|
memcpy(copy, info, sizeof(struct layer_info));
|
||||||
|
/* Duplicate string */
|
||||||
|
if (info->name)
|
||||||
|
copy->name = strdup(info->name);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_info_delete_with_name(struct layer_info *const info)
|
||||||
|
{
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (info->name)
|
||||||
|
free(info->name);
|
||||||
free(info);
|
free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LayerSettings *layer_settings_new()
|
||||||
|
{
|
||||||
|
return g_object_new(GDS_RENDER_TYPE_LAYER_SETTINGS, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int layer_settings_append_layer_info(LayerSettings *settings, struct layer_info *info)
|
||||||
|
{
|
||||||
|
struct layer_info *info_copy;
|
||||||
|
|
||||||
|
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), -1);
|
||||||
|
if (!info)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
/* Copy layer info */
|
||||||
|
info_copy = layer_info_copy(info);
|
||||||
|
|
||||||
|
/* Append to list */
|
||||||
|
settings->layer_infos = g_list_append(settings->layer_infos, info_copy);
|
||||||
|
|
||||||
|
return (settings->layer_infos ? 0 : -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_settings_clear(LayerSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings));
|
||||||
|
|
||||||
|
/* Clear list and delete layer_info structs including the name field */
|
||||||
|
g_list_free_full(settings->layer_infos, (GDestroyNotify)layer_info_delete_with_name);
|
||||||
|
settings->layer_infos = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int layer_settings_remove_layer(LayerSettings *settings, int layer)
|
||||||
|
{
|
||||||
|
GList *list_iter;
|
||||||
|
GList *found = NULL;
|
||||||
|
struct layer_info *inf;
|
||||||
|
|
||||||
|
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), -1);
|
||||||
|
|
||||||
|
/* Find in list */
|
||||||
|
for (list_iter = settings->layer_infos; list_iter; list_iter = list_iter->next) {
|
||||||
|
inf = (struct layer_info *)list_iter->data;
|
||||||
|
|
||||||
|
if (!inf)
|
||||||
|
continue;
|
||||||
|
if (inf->layer == layer)
|
||||||
|
found = list_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
/* Free the layer_info struct */
|
||||||
|
layer_info_delete_with_name((struct layer_info *)found->data);
|
||||||
|
/* Delete the list element */
|
||||||
|
settings->layer_infos = g_list_delete_link(settings->layer_infos, found);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *layer_settings_get_layer_info_list(LayerSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), NULL);
|
||||||
|
return settings->layer_infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate a layer mapping CSV line for a given layer_info struct
|
||||||
|
* @param string Buffer to write to
|
||||||
|
* @param linfo Layer information
|
||||||
|
*/
|
||||||
|
static void layer_settings_gen_csv_line(GString *string, struct layer_info *linfo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
g_string_printf(string, "%d:%lf:%lf:%lf:%lf:%d:%s\n",
|
||||||
|
linfo->layer, linfo->color.red, linfo->color.green,
|
||||||
|
linfo->color.blue, linfo->color.alpha, (linfo->render ? 1 : 0), linfo->name);
|
||||||
|
/* Fix broken locale settings */
|
||||||
|
for (i = 0; string->str[i]; i++) {
|
||||||
|
if (string->str[i] == ',')
|
||||||
|
string->str[i] = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; string->str[i]; i++) {
|
||||||
|
if (string->str[i] == ':')
|
||||||
|
string->str[i] = ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int layer_settings_to_csv(LayerSettings *settings, const char *path)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
int i;
|
||||||
|
GOutputStream *w_fstream;
|
||||||
|
GString *string;
|
||||||
|
GList *info_iter;
|
||||||
|
struct layer_info *linfo;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
file = g_file_new_for_path(path);
|
||||||
|
w_fstream = G_OUTPUT_STREAM(g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
|
||||||
|
if (!w_fstream) {
|
||||||
|
ret = -1;
|
||||||
|
goto ret_unref_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate new working buffer string. A size bigger than 200 is unexpected, but possible
|
||||||
|
* 200 is a tradeoff between memory usage and preventing the necessity of realloc'ing the string
|
||||||
|
*/
|
||||||
|
string = g_string_new_len(NULL, 200);
|
||||||
|
if (!string) {
|
||||||
|
ret = -2;
|
||||||
|
goto ret_close_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over layers and write CSV lines */
|
||||||
|
for (info_iter = settings->layer_infos; info_iter; info_iter = info_iter->next) {
|
||||||
|
linfo = (struct layer_info *)info_iter->data;
|
||||||
|
|
||||||
|
layer_settings_gen_csv_line(string, linfo);
|
||||||
|
g_output_stream_write(w_fstream, string->str, sizeof(gchar), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete string */
|
||||||
|
g_string_free(string, TRUE);
|
||||||
|
ret_close_file:
|
||||||
|
g_output_stream_flush(w_fstream, NULL, NULL);
|
||||||
|
g_output_stream_close(w_fstream, NULL, NULL);
|
||||||
|
g_object_unref(w_fstream);
|
||||||
|
ret_unref_file:
|
||||||
|
g_object_unref(file);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||||
|
* @param stream Input data stream
|
||||||
|
* @param linfo Layer info struct to fill
|
||||||
|
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
||||||
|
*/
|
||||||
|
static int layer_settings_load_csv_line_from_stream(GDataInputStream *stream, struct layer_info *linfo)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
gsize len;
|
||||||
|
gchar *line;
|
||||||
|
GRegex *regex;
|
||||||
|
GMatchInfo *mi;
|
||||||
|
char *match;
|
||||||
|
|
||||||
|
if (!linfo) {
|
||||||
|
ret = 1;
|
||||||
|
goto ret_direct;
|
||||||
|
}
|
||||||
|
|
||||||
|
regex = g_regex_new("^(?<layer>[0-9]+),(?<r>[0-9\\.]+),(?<g>[0-9\\.]+),(?<b>[0-9\\.]+),(?<a>[0-9\\.]+),(?<export>[01]),(?<name>.*)$", 0, 0, NULL);
|
||||||
|
|
||||||
|
line = g_data_input_stream_read_line(stream, &len, NULL, NULL);
|
||||||
|
if (!line) {
|
||||||
|
ret = -1;
|
||||||
|
goto destroy_regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match line in CSV */
|
||||||
|
g_regex_match(regex, line, 0, &mi);
|
||||||
|
if (g_match_info_matches(mi)) {
|
||||||
|
/* Line is valid */
|
||||||
|
match = g_match_info_fetch_named(mi, "layer");
|
||||||
|
linfo->layer = (int)g_ascii_strtoll(match, NULL, 10);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "r");
|
||||||
|
linfo->color.red = g_ascii_strtod(match, NULL);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "g");
|
||||||
|
linfo->color.green = g_ascii_strtod(match, NULL);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "b");
|
||||||
|
linfo->color.blue = g_ascii_strtod(match, NULL);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "a");
|
||||||
|
linfo->color.alpha = g_ascii_strtod(match, NULL);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "export");
|
||||||
|
linfo->render = ((!strcmp(match, "1")) ? 1 : 0);
|
||||||
|
g_free(match);
|
||||||
|
match = g_match_info_fetch_named(mi, "name");
|
||||||
|
linfo->name = match;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
/* Line is malformatted */
|
||||||
|
printf("Could not recognize line in CSV as valid entry: %s\n", line);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_match_info_free(mi);
|
||||||
|
g_free(line);
|
||||||
|
destroy_regex:
|
||||||
|
g_regex_unref(regex);
|
||||||
|
ret_direct:
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int layer_settings_load_from_csv(LayerSettings *settings, const char *path)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
int ret = 0;
|
||||||
|
GInputStream *in_stream;
|
||||||
|
GDataInputStream *data_stream;
|
||||||
|
int parser_ret;
|
||||||
|
struct layer_info linfo;
|
||||||
|
|
||||||
|
file = g_file_new_for_path(path);
|
||||||
|
in_stream = G_INPUT_STREAM(g_file_read(file, NULL, NULL));
|
||||||
|
if (!in_stream) {
|
||||||
|
ret = -1;
|
||||||
|
goto ret_destroy_file;
|
||||||
|
}
|
||||||
|
/* Delete old settings */
|
||||||
|
layer_settings_clear(settings);
|
||||||
|
|
||||||
|
data_stream = g_data_input_stream_new(in_stream);
|
||||||
|
|
||||||
|
while ((parser_ret = layer_settings_load_csv_line_from_stream(data_stream, &linfo)) >= 0) {
|
||||||
|
/* Line broken */
|
||||||
|
if (parser_ret == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
layer_settings_append_layer_info(settings, &linfo);
|
||||||
|
/* Clear name to prevent memory leak */
|
||||||
|
if (linfo.name)
|
||||||
|
g_free(linfo.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref(data_stream);
|
||||||
|
g_object_unref(in_stream);
|
||||||
|
ret_destroy_file:
|
||||||
|
g_object_unref(file);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -395,7 +395,6 @@ GList *layer_selector_export_rendered_layer_info(LayerSelector *selector)
|
|||||||
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
|
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||||
layer_element_get_color(le, &linfo->color);
|
layer_element_get_color(le, &linfo->color);
|
||||||
linfo->layer = layer_element_get_layer(le);
|
linfo->layer = layer_element_get_layer(le);
|
||||||
linfo->stacked_position = i;
|
|
||||||
linfo->name = (char *)layer_element_get_name(le);
|
linfo->name = (char *)layer_element_get_name(le);
|
||||||
|
|
||||||
/* Append to list */
|
/* Append to list */
|
||||||
|
70
main.c
70
main.c
@ -241,20 +241,20 @@ int main(int argc, char **argv)
|
|||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
gchar *gds_name;
|
gchar *gds_name;
|
||||||
gchar *basename;
|
gchar *basename;
|
||||||
gchar *output_path = NULL, *mappingname = NULL, *cellname = NULL;
|
gchar **output_paths = NULL;
|
||||||
gchar *renderer_arg = NULL;
|
gchar *mappingname = NULL;
|
||||||
|
gchar *cellname = NULL;
|
||||||
|
gchar **renderer_args = NULL;
|
||||||
gboolean version = FALSE, pdf_standalone = FALSE, pdf_layers = FALSE;
|
gboolean version = FALSE, pdf_standalone = FALSE, pdf_layers = FALSE;
|
||||||
gchar *custom_library_path = NULL;
|
gchar *custom_library_path = NULL;
|
||||||
int scale = 1000;
|
int scale = 1000;
|
||||||
int app_status = 0;
|
int app_status = 0;
|
||||||
enum command_line_renderer renderer = CMD_NONE;
|
|
||||||
enum cmd_options opt = CMD_OPT_NONE;
|
|
||||||
|
|
||||||
GOptionEntry entries[] = {
|
GOptionEntry entries[] = {
|
||||||
{"version", 'v', 0, G_OPTION_ARG_NONE, &version, "Print version", NULL},
|
{"version", 'v', 0, G_OPTION_ARG_NONE, &version, "Print version", NULL},
|
||||||
{"renderer", 'r', 0, G_OPTION_ARG_STRING, &renderer_arg, "Renderer to use", "pdf|svg|tikz|ext"},
|
{"renderer", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &renderer_args, "Renderer to use. Can be used multiple times.", "pdf|svg|tikz|ext"},
|
||||||
{"scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" },
|
{"scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" },
|
||||||
{"output-file", 'o', 0, G_OPTION_ARG_FILENAME, &output_path, "Output file path", "PATH" },
|
{"output-file", 'o', 0, G_OPTION_ARG_FILENAME_ARRAY, &output_paths, "Output file path. Can be used multiple times.", "PATH" },
|
||||||
{"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" },
|
{"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" },
|
||||||
{"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" },
|
{"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" },
|
||||||
{"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL },
|
{"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL },
|
||||||
@ -292,57 +292,25 @@ int main(int argc, char **argv)
|
|||||||
printf("Ignored argument: %s", argv[i]);
|
printf("Ignored argument: %s", argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if PDF/TeX names are supplied. if not generate */
|
|
||||||
basename = g_path_get_basename(gds_name);
|
|
||||||
|
|
||||||
if (!strcmp(renderer_arg, "pdf")) {
|
|
||||||
renderer = CMD_CAIRO_PDF;
|
|
||||||
if (!output_path)
|
|
||||||
output_path = g_strdup_printf("./%s.pdf", basename);
|
|
||||||
}
|
|
||||||
else if (!strcmp(renderer_arg, "svg")) {
|
|
||||||
renderer = CMD_NONE; // To buggy atm CMD_CAIRO_SVG;
|
|
||||||
if (!output_path)
|
|
||||||
output_path = g_strdup_printf("./%s.svg", basename);
|
|
||||||
} else if (!strcmp(renderer_arg, "tikz")) {
|
|
||||||
renderer = CMD_LATEX;
|
|
||||||
if (pdf_layers)
|
|
||||||
opt |= CMD_OPT_LATEX_LAYERS;
|
|
||||||
if (pdf_standalone)
|
|
||||||
opt |= CMD_OPT_LATEX_STANDALONE;
|
|
||||||
if (!output_path)
|
|
||||||
output_path = g_strdup_printf("./%s.tex", basename);
|
|
||||||
} else if (!strcmp(renderer_arg, "ext")) {
|
|
||||||
renderer = CMD_EXTERNAL;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "No valid renderer specified\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basename)
|
|
||||||
g_free(basename);
|
|
||||||
|
|
||||||
if (!output_path || strlen(output_path) == 0) {
|
|
||||||
app_status = -2;
|
|
||||||
goto ret_free_renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
command_line_convert_gds(gds_name, cellname, output_path, mappingname, custom_library_path, renderer, opt, scale);
|
|
||||||
/* Clean up */
|
|
||||||
app_status = 0;
|
|
||||||
|
|
||||||
ret_free_renderer:
|
|
||||||
if (output_path)
|
|
||||||
g_free(output_path);
|
|
||||||
if (renderer_arg)
|
|
||||||
g_free(renderer_arg);
|
|
||||||
if (mappingname)
|
|
||||||
g_free(mappingname);
|
|
||||||
if (cellname)
|
|
||||||
g_free(cellname);
|
|
||||||
} else {
|
} else {
|
||||||
app_status = start_gui(argc, argv);
|
app_status = start_gui(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_status:
|
ret_status:
|
||||||
|
|
||||||
|
/* If necessary, free command line parameters */
|
||||||
|
if (output_paths)
|
||||||
|
g_strfreev(output_paths);
|
||||||
|
if (renderer_args)
|
||||||
|
g_strfreev(renderer_args);
|
||||||
|
if (mappingname)
|
||||||
|
g_free(mappingname);
|
||||||
|
if (cellname)
|
||||||
|
free(cellname);
|
||||||
|
if (custom_library_path);
|
||||||
|
free(custom_library_path);
|
||||||
|
|
||||||
return app_status;
|
return app_status;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ static int cairo_renderer_render_cell_to_vector_file(struct gds_cell *cell, GLis
|
|||||||
/* Create recording surface for each layer */
|
/* Create recording surface for each layer */
|
||||||
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
|
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
|
||||||
linfo = (struct layer_info *)info_list->data;
|
linfo = (struct layer_info *)info_list->data;
|
||||||
if (linfo->layer < MAX_LAYERS) {
|
if (linfo->layer < MAX_LAYERS && linfo->render) {
|
||||||
lay = &(layers[(unsigned int)linfo->layer]);
|
lay = &(layers[(unsigned int)linfo->layer]);
|
||||||
lay->linfo = linfo;
|
lay->linfo = linfo;
|
||||||
lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,
|
lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,
|
||||||
@ -266,6 +266,9 @@ static int cairo_renderer_render_cell_to_vector_file(struct gds_cell *cell, GLis
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!linfo->render)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Print size */
|
/* Print size */
|
||||||
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
|
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
|
||||||
&rec_width, &rec_height);
|
&rec_width, &rec_height);
|
||||||
@ -309,6 +312,9 @@ static int cairo_renderer_render_cell_to_vector_file(struct gds_cell *cell, GLis
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!linfo->render)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (pdf_file && pdf_cr) {
|
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);
|
||||||
@ -363,17 +369,25 @@ static void cairo_renderer_init(CairoRenderer *self)
|
|||||||
|
|
||||||
static int cairo_renderer_render_output(GdsOutputRenderer *renderer,
|
static int cairo_renderer_render_output(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
CairoRenderer *c_renderer = GDS_RENDER_CAIRO_RENDERER(renderer);
|
CairoRenderer *c_renderer = GDS_RENDER_CAIRO_RENDERER(renderer);
|
||||||
const char *pdf_file = NULL;
|
const char *pdf_file = NULL;
|
||||||
const char *svg_file = NULL;
|
const char *svg_file = NULL;
|
||||||
|
LayerSettings *settings;
|
||||||
|
GList *layer_infos = NULL;
|
||||||
|
const char *output_file;
|
||||||
|
|
||||||
if (!c_renderer)
|
if (!c_renderer)
|
||||||
return -2000;
|
return -2000;
|
||||||
|
|
||||||
|
output_file = gds_output_renderer_get_output_file(renderer);
|
||||||
|
settings = gds_output_renderer_get_layer_settings(renderer);
|
||||||
|
|
||||||
|
/* Set layer info list. In case of failure it remains NULL */
|
||||||
|
if (settings)
|
||||||
|
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||||
|
|
||||||
if (c_renderer->svg == TRUE)
|
if (c_renderer->svg == TRUE)
|
||||||
svg_file = output_file;
|
svg_file = output_file;
|
||||||
else
|
else
|
||||||
|
@ -99,11 +99,19 @@ ret_close_so_handle:
|
|||||||
|
|
||||||
static int external_renderer_render_output(GdsOutputRenderer *renderer,
|
static int external_renderer_render_output(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
ExternalRenderer *ext_renderer = GDS_RENDER_EXTERNAL_RENDERER(renderer);
|
ExternalRenderer *ext_renderer = GDS_RENDER_EXTERNAL_RENDERER(renderer);
|
||||||
|
LayerSettings *settings;
|
||||||
|
GList *layer_infos = NULL;
|
||||||
|
const char *output_file;
|
||||||
|
|
||||||
|
output_file = gds_output_renderer_get_output_file(renderer);
|
||||||
|
settings = gds_output_renderer_get_layer_settings(renderer);
|
||||||
|
|
||||||
|
/* Set layer info list. In case of failure it remains NULL */
|
||||||
|
if (settings)
|
||||||
|
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||||
|
|
||||||
return external_renderer_render_cell(cell, layer_infos, output_file, scale, ext_renderer->shared_object_path);
|
return external_renderer_render_cell(cell, layer_infos, output_file, scale, ext_renderer->shared_object_path);
|
||||||
}
|
}
|
||||||
@ -151,7 +159,7 @@ static void external_renderer_dispose(GObject *self_obj)
|
|||||||
self->shared_object_path = NULL;
|
self->shared_object_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS(external_renderer_parent_class)->dispose(G_OBJECT(self));
|
G_OBJECT_CLASS(external_renderer_parent_class)->dispose(self_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GParamSpec *external_renderer_properties[N_PROPERTIES] = {NULL};
|
static GParamSpec *external_renderer_properties[N_PROPERTIES] = {NULL};
|
||||||
|
@ -31,38 +31,123 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gds-render/output-renderers/gds-output-renderer.h>
|
#include <gds-render/output-renderers/gds-output-renderer.h>
|
||||||
|
#include <gds-render/layer/layer-info.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gpointer padding[12];
|
gchar *output_file;
|
||||||
|
LayerSettings *layer_settings;
|
||||||
|
gpointer padding[11];
|
||||||
} GdsOutputRendererPrivate;
|
} GdsOutputRendererPrivate;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_OUTPUT_FILE = 1,
|
||||||
|
PROP_LAYER_SETTINGS,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE(GdsOutputRenderer, gds_output_renderer, G_TYPE_OBJECT)
|
G_DEFINE_TYPE_WITH_PRIVATE(GdsOutputRenderer, gds_output_renderer, G_TYPE_OBJECT)
|
||||||
|
|
||||||
static int gds_output_renderer_render_dummy(GdsOutputRenderer *renderer,
|
static int gds_output_renderer_render_dummy(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
(void)renderer;
|
(void)renderer;
|
||||||
(void)cell;
|
(void)cell;
|
||||||
(void)layer_infos;
|
|
||||||
(void)output_file;
|
|
||||||
(void)scale;
|
(void)scale;
|
||||||
|
|
||||||
g_warning("Output renderer does not define a render_output function!");
|
g_warning("Output renderer does not define a render_output function!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gds_output_renderer_dispose(GObject *self_obj)
|
||||||
|
{
|
||||||
|
GdsOutputRenderer *renderer = GDS_RENDER_OUTPUT_RENDERER(self_obj);
|
||||||
|
GdsOutputRendererPrivate *priv;
|
||||||
|
|
||||||
|
priv = gds_output_renderer_get_instance_private(renderer);
|
||||||
|
if (priv->output_file)
|
||||||
|
g_free(priv->output_file);
|
||||||
|
|
||||||
|
g_clear_object(&priv->layer_settings);
|
||||||
|
|
||||||
|
/* Chain up to parent class */
|
||||||
|
G_OBJECT_CLASS(gds_output_renderer_parent_class)->dispose(self_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gds_output_renderer_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdsOutputRenderer *self = GDS_RENDER_OUTPUT_RENDERER(obj);
|
||||||
|
GdsOutputRendererPrivate *priv;
|
||||||
|
|
||||||
|
priv = gds_output_renderer_get_instance_private(self);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_OUTPUT_FILE:
|
||||||
|
g_value_set_string(value, priv->output_file);
|
||||||
|
break;
|
||||||
|
case PROP_LAYER_SETTINGS:
|
||||||
|
g_value_set_object(value, priv->layer_settings);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gds_output_renderer_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdsOutputRenderer *self = GDS_RENDER_OUTPUT_RENDERER(obj);
|
||||||
|
GdsOutputRendererPrivate *priv;
|
||||||
|
|
||||||
|
priv = gds_output_renderer_get_instance_private(self);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_OUTPUT_FILE:
|
||||||
|
if (priv->output_file)
|
||||||
|
g_free(priv->output_file);
|
||||||
|
priv->output_file = g_strdup(g_value_get_string(value));
|
||||||
|
break;
|
||||||
|
case PROP_LAYER_SETTINGS:
|
||||||
|
g_clear_object(&priv->layer_settings);
|
||||||
|
priv->layer_settings = g_value_get_object(value);
|
||||||
|
g_object_ref(priv->layer_settings);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
klass->render_output = gds_output_renderer_render_dummy;
|
klass->render_output = gds_output_renderer_render_dummy;
|
||||||
|
|
||||||
|
oclass->dispose = gds_output_renderer_dispose;
|
||||||
|
oclass->set_property = gds_output_renderer_set_property;
|
||||||
|
oclass->get_property = gds_output_renderer_get_property;
|
||||||
|
|
||||||
|
/* Setup properties */
|
||||||
|
gds_output_renderer_properties[PROP_OUTPUT_FILE] =
|
||||||
|
g_param_spec_string("output-file", "output file", "Output file for renderer",
|
||||||
|
NULL, G_PARAM_READWRITE);
|
||||||
|
gds_output_renderer_properties[PROP_LAYER_SETTINGS] =
|
||||||
|
g_param_spec_object("layer-settings", "Layer Settings object",
|
||||||
|
"Object containing the layer rendering information",
|
||||||
|
GDS_RENDER_TYPE_LAYER_SETTINGS, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_properties(oclass, N_PROPERTIES, gds_output_renderer_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gds_output_renderer_init(GdsOutputRenderer *self)
|
void gds_output_renderer_init(GdsOutputRenderer *self)
|
||||||
{
|
{
|
||||||
(void)self;
|
GdsOutputRendererPrivate *priv;
|
||||||
|
|
||||||
|
priv = gds_output_renderer_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->output_file = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,17 +156,69 @@ GdsOutputRenderer *gds_output_renderer_new()
|
|||||||
return GDS_RENDER_OUTPUT_RENDERER(g_object_new(GDS_RENDER_TYPE_OUTPUT_RENDERER, NULL));
|
return GDS_RENDER_OUTPUT_RENDERER(g_object_new(GDS_RENDER_TYPE_OUTPUT_RENDERER, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
int gds_output_renderer_render_output(GdsOutputRenderer *renderer, struct gds_cell *cell, GList *layer_infos, const char *output_file, double scale)
|
GdsOutputRenderer *gds_output_renderer_new_with_props(const char *output_file, LayerSettings *layer_settings)
|
||||||
|
{
|
||||||
|
return GDS_RENDER_OUTPUT_RENDERER(g_object_new(GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
||||||
|
"layer-settings", layer_settings,
|
||||||
|
"output-file", output_file,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void gds_output_renderer_set_output_file(GdsOutputRenderer *renderer, const gchar *file_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail(GDS_RENDER_IS_OUTPUT_RENDERER(renderer));
|
||||||
|
|
||||||
|
/* Check if the filename is actually filled */
|
||||||
|
if (!file_name || !file_name[0])
|
||||||
|
return;
|
||||||
|
g_object_set(renderer, "output-file", file_name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *gds_output_renderer_get_output_file(GdsOutputRenderer *renderer)
|
||||||
|
{
|
||||||
|
const char *file = NULL;
|
||||||
|
|
||||||
|
g_object_get(renderer, "output-file", &file, NULL);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerSettings *gds_output_renderer_get_layer_settings(GdsOutputRenderer *renderer)
|
||||||
|
{
|
||||||
|
LayerSettings *ret = NULL;
|
||||||
|
|
||||||
|
g_object_get(renderer, "layer-settings", &ret, NULL);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gds_output_renderer_set_layer_settings(GdsOutputRenderer *renderer, LayerSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings));
|
||||||
|
|
||||||
|
g_object_set(renderer, "layer_settings", settings, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gds_output_renderer_render_output(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale)
|
||||||
{
|
{
|
||||||
GdsOutputRendererClass *klass;
|
GdsOutputRendererClass *klass;
|
||||||
|
GdsOutputRendererPrivate *priv = gds_output_renderer_get_instance_private(renderer);
|
||||||
|
|
||||||
if (GDS_RENDER_IS_OUTPUT_RENDERER(renderer) == FALSE) {
|
if (GDS_RENDER_IS_OUTPUT_RENDERER(renderer) == FALSE) {
|
||||||
g_error("Output Renderer not valid.");
|
g_error("Output Renderer not valid.");
|
||||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cell || !layer_infos || !output_file) {
|
if (!priv->output_file || !priv->output_file[0]) {
|
||||||
g_error("Output renderer called with insufficient parameters.");
|
g_error("No/invalid output file set.");
|
||||||
|
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->layer_settings) {
|
||||||
|
g_error("No layer specification supplied.");
|
||||||
|
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cell) {
|
||||||
|
g_error("Output renderer called without cell to render.");
|
||||||
return GDS_OUTPUT_RENDERER_PARAM_ERR;
|
return GDS_OUTPUT_RENDERER_PARAM_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +228,7 @@ int gds_output_renderer_render_output(GdsOutputRenderer *renderer, struct gds_ce
|
|||||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return klass->render_output(renderer, cell, layer_infos, output_file, scale);
|
return klass->render_output(renderer, cell, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,10 +69,13 @@ static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString
|
|||||||
{
|
{
|
||||||
GList *list;
|
GList *list;
|
||||||
struct layer_info *lifo;
|
struct layer_info *lifo;
|
||||||
char *end_str;
|
|
||||||
|
|
||||||
for (list = layer_infos; list != NULL; list = list->next) {
|
for (list = layer_infos; list != NULL; list = list->next) {
|
||||||
lifo = (struct layer_info *)list->data;
|
lifo = (struct layer_info *)list->data;
|
||||||
|
|
||||||
|
if (!lifo->render)
|
||||||
|
continue;
|
||||||
|
|
||||||
g_string_printf(buffer, "\\pgfdeclarelayer{l%d}\n\\definecolor{c%d}{rgb}{%lf,%lf,%lf}\n",
|
g_string_printf(buffer, "\\pgfdeclarelayer{l%d}\n\\definecolor{c%d}{rgb}{%lf,%lf,%lf}\n",
|
||||||
lifo->layer, lifo->layer,
|
lifo->layer, lifo->layer,
|
||||||
lifo->color.red, lifo->color.green, lifo->color.blue);
|
lifo->color.red, lifo->color.green, lifo->color.blue);
|
||||||
@ -85,14 +88,13 @@ static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString
|
|||||||
for (list = layer_infos; list != NULL; list = list->next) {
|
for (list = layer_infos; list != NULL; list = list->next) {
|
||||||
lifo = (struct layer_info *)list->data;
|
lifo = (struct layer_info *)list->data;
|
||||||
|
|
||||||
if (list->next == NULL)
|
if (!lifo->render)
|
||||||
end_str = ",main}";
|
continue;
|
||||||
else
|
|
||||||
end_str = ",";
|
g_string_printf(buffer, "l%d,", lifo->layer);
|
||||||
g_string_printf(buffer, "l%d%s", lifo->layer, end_str);
|
|
||||||
WRITEOUT_BUFFER(buffer);
|
WRITEOUT_BUFFER(buffer);
|
||||||
}
|
}
|
||||||
fwrite("\n", sizeof(char), 1, tex_file);
|
fwrite("main}\n", sizeof(char), 1, tex_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,7 +130,7 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
|
|||||||
|
|
||||||
for (temp = linfo; temp != NULL; temp = temp->next) {
|
for (temp = linfo; temp != NULL; temp = temp->next) {
|
||||||
inf = (struct layer_info *)temp->data;
|
inf = (struct layer_info *)temp->data;
|
||||||
if (inf->layer == layer) {
|
if (inf->layer == layer && inf->render) {
|
||||||
color->alpha = inf->color.alpha;
|
color->alpha = inf->color.alpha;
|
||||||
color->red = inf->color.red;
|
color->red = inf->color.red;
|
||||||
color->green = inf->color.green;
|
color->green = inf->color.green;
|
||||||
@ -322,19 +324,29 @@ static int latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos,
|
|||||||
|
|
||||||
static int latex_renderer_render_output(GdsOutputRenderer *renderer,
|
static int latex_renderer_render_output(GdsOutputRenderer *renderer,
|
||||||
struct gds_cell *cell,
|
struct gds_cell *cell,
|
||||||
GList *layer_infos,
|
|
||||||
const char *output_file,
|
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
LatexRenderer *l_renderer = GDS_RENDER_LATEX_RENDERER(renderer);
|
LatexRenderer *l_renderer = GDS_RENDER_LATEX_RENDERER(renderer);
|
||||||
FILE *tex_file;
|
FILE *tex_file;
|
||||||
int ret = -2;
|
int ret = -2;
|
||||||
|
LayerSettings *settings;
|
||||||
|
GList *layer_infos = NULL;
|
||||||
|
const char *output_file;
|
||||||
|
|
||||||
|
output_file = gds_output_renderer_get_output_file(renderer);
|
||||||
|
settings = gds_output_renderer_get_layer_settings(renderer);
|
||||||
|
|
||||||
|
/* Set layer info list. In case of failure it remains NULL */
|
||||||
|
if (settings)
|
||||||
|
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||||
|
|
||||||
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);
|
||||||
fclose(tex_file);
|
fclose(tex_file);
|
||||||
|
} else {
|
||||||
|
g_error("Could not open LaTeX outpur file");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user