diff --git a/cairo-output/cairo-output.c b/cairo-output/cairo-output.c index 062c0fd..9db1b8e 100644 --- a/cairo-output/cairo-output.c +++ b/cairo-output/cairo-output.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with GDSII-Converter. If not, see . */ - /** +/** * @file cairo-output.c * @brief Output renderer for Cairo PDF export * @author Mario Hüttel @@ -31,15 +31,16 @@ #include #include #include +#include /** * @brief The cairo_layer struct * Each rendered layer is represented by this struct. */ struct cairo_layer { - cairo_t *cr; /**< @brief cairo context for layer*/ - cairo_surface_t *rec; /**< @brief Recording surface to hold the layer */ - struct layer_info *linfo; /**< @brief Reference to layer information */ + cairo_t *cr; /**< @brief cairo context for layer*/ + cairo_surface_t *rec; /**< @brief Recording surface to hold the layer */ + struct layer_info *linfo; /**< @brief Reference to layer information */ }; /** @@ -177,10 +178,10 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl } -void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_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; - cairo_t *pdf_cr; + cairo_surface_t *pdf_surface, *svg_surface; + cairo_t *pdf_cr, *svg_cr; struct layer_info *linfo; struct cairo_layer *layers; struct cairo_layer *lay; @@ -189,6 +190,11 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p double rec_x0, rec_y0, rec_width, rec_height; double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN; + if (pdf_file == NULL && svg_file == NULL) { + /* No output specified */ + return; + } + layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer)); /* Clear layers */ @@ -246,8 +252,15 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p printf("Bounding box: (%lf,%lf) -- (%lf,%lf)\n", xmin, ymin, xmax, ymax); - pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin); - pdf_cr = cairo_create(pdf_surface); + if (pdf_file) { + pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin); + pdf_cr = cairo_create(pdf_surface); + } + + if (svg_file) { + svg_surface = cairo_svg_surface_create(svg_file, xmax-xmin, ymax-ymin); + svg_cr = cairo_create(svg_surface); + } /* Write layers to PDF */ for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) { @@ -258,13 +271,29 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p continue; } - cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin); - cairo_paint_with_alpha(pdf_cr, linfo->color.alpha); + if (pdf_file) { + cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin); + cairo_paint_with_alpha(pdf_cr, linfo->color.alpha); + } + + if (svg_file) { + cairo_set_source_surface(svg_cr, layers[linfo->layer].rec, -xmin, -ymin); + cairo_paint_with_alpha(svg_cr, linfo->color.alpha); + } + } - cairo_show_page(pdf_cr); - cairo_destroy(pdf_cr); - cairo_surface_destroy(pdf_surface); + if (pdf_file) { + cairo_show_page(pdf_cr); + cairo_destroy(pdf_cr); + cairo_surface_destroy(pdf_surface); + } + + if (svg_file) { + cairo_show_page(svg_cr); + cairo_destroy(svg_cr); + cairo_surface_destroy(svg_surface); + } ret_clear_layers: for (i = 0; i < MAX_LAYERS; i++) { diff --git a/cairo-output/cairo-output.h b/cairo-output/cairo-output.h index 069372c..091b704 100644 --- a/cairo-output/cairo-output.h +++ b/cairo-output/cairo-output.h @@ -37,10 +37,11 @@ * @brief Render \p cell to a PDF file specified by \p pdf_file * @param cell Toplevel cell to render * @param layer_infos List of layer information. Specifies color and layer stacking - * @param pdf_file Output file + * @param pdf_file PDF output file. Set to NULL if no PDF file has to be generated + * @param svg_file SVG output file. Set to NULL if no SVG file has to be generated * @param scale Scale the output image down by \p scale */ -void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_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); /** @} */ diff --git a/command-line.c b/command-line.c index ceb90f6..dad5671 100644 --- a/command-line.c +++ b/command-line.c @@ -50,21 +50,9 @@ static void delete_layer_info_with_name(struct layer_info *info) } } -/** - * @brief Convert GDS according to supplied parameters - * @param gds_name GDS File path - * @param pdf_name Cairo-PDF path - * @param tex_name TeX/TikZ path - * @param pdf Render Cairo - * @param tex Render LaTeX - * @param layer_file Layer mapping file - * @param cell_name Cell name to render - * @param scale Scale image down by this value - * @param pdf_layers TikZ creates OCG layers - * @param pdf_standalone LaTeX document is standalone - */ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex, - char *layer_file, char *cell_name, double scale, gboolean pdf_layers, gboolean pdf_standalone) + char *layer_file, char *cell_name, double scale, gboolean pdf_layers, + gboolean pdf_standalone, gboolean svg, char *svg_name) { GList *libs = NULL; FILE *tex_file; @@ -143,8 +131,9 @@ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gb } /* Render outputs */ - if (pdf == TRUE) { - cairo_render_cell_to_pdf(toplevel_cell, layer_info_list, pdf_name, scale); + if (pdf == TRUE || svg == TRUE) { + cairo_render_cell_to_vector_file(toplevel_cell, layer_info_list, (pdf == TRUE ? pdf_name : NULL), + (svg == TRUE ? svg_name : NULL), scale); } if (tex == TRUE) { diff --git a/command-line.h b/command-line.h index eaa9de8..3c36360 100644 --- a/command-line.h +++ b/command-line.h @@ -32,8 +32,24 @@ #define _COMMAND_LINE_H_ #include +/** + * @brief Convert GDS according to supplied parameters + * @param gds_name GDS File path + * @param pdf_name Cairo-PDF path + * @param tex_name TeX/TikZ path + * @param pdf Render Cairo + * @param tex Render LaTeX + * @param layer_file Layer mapping file + * @param cell_name Cell name to render + * @param scale Scale image down by this value + * @param pdf_layers TikZ creates OCG layers + * @param pdf_standalone LaTeX document is standalone7 + * @param svg Render to SVG file + * @param svg_name SVG file name + */ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex, - char *layer_file, char *cell_name, double scale, gboolean pdf_layers, gboolean pdf_standalone); + char *layer_file, char *cell_name, double scale, gboolean pdf_layers, + gboolean pdf_standalone, gboolean svg, char *svg_name); #endif /* _COMMAND_LINE_H_ */ diff --git a/doxygen/Doxyconfig b/doxygen/Doxyconfig index d4eb6f7..28ecff4 100644 --- a/doxygen/Doxyconfig +++ b/doxygen/Doxyconfig @@ -51,7 +51,7 @@ PROJECT_BRIEF = # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = /home/mari/projects/cpp/gds-render/icon/gds-render.svg +PROJECT_LOGO = ../icon/gds-render.svg # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is diff --git a/glade/dialog.glade b/glade/dialog.glade index 7186456..90b1ea5 100644 --- a/glade/dialog.glade +++ b/glade/dialog.glade @@ -16,6 +16,7 @@ Generate LaTeX/TikZ output + True True True False @@ -29,8 +30,9 @@ - + Render PDF using Cairographics + True True True False @@ -44,6 +46,24 @@ 1 + + + Render SVG using Cairographics (too buggy at the moment) + True + True + False + True + False + True + True + latex-radio + + + False + True + 2 + + True @@ -55,7 +75,7 @@ False True - 2 + 3 @@ -69,7 +89,7 @@ False True - 3 + 4 @@ -83,7 +103,7 @@ False True - 4 + 5 diff --git a/main-window.c b/main-window.c index 931bac9..d687875 100644 --- a/main-window.c +++ b/main-window.c @@ -251,13 +251,21 @@ static void on_convert_clicked(gpointer button, gpointer user) "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL); /* Set file filter according to settings */ filter = gtk_file_filter_new(); - if (sett.renderer == RENDERER_LATEX_TIKZ) { + switch (sett.renderer) { + case RENDERER_LATEX_TIKZ: gtk_file_filter_add_pattern(filter, "*.tex"); gtk_file_filter_set_name(filter, "LaTeX-Files"); - } else { + break; + case RENDERER_CAIROGRAPHICS_PDF: gtk_file_filter_add_pattern(filter, "*.pdf"); gtk_file_filter_set_name(filter, "PDF-Files"); + break; + case RENDERER_CAIROGRAPHICS_SVG: + gtk_file_filter_add_pattern(filter, "*.svg"); + gtk_file_filter_set_name(filter, "SVG-Files"); + break; } + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); @@ -274,8 +282,12 @@ static void on_convert_clicked(gpointer button, gpointer user) sett.tex_pdf_layers, sett.tex_standalone); fclose(output_file); break; - case RENDERER_CAIROGRAPHICS: - cairo_render_cell_to_pdf(cell_to_render, layer_list, file_name, sett.scale); + case RENDERER_CAIROGRAPHICS_SVG: + case RENDERER_CAIROGRAPHICS_PDF: + cairo_render_cell_to_vector_file(cell_to_render, layer_list, + (sett.renderer == RENDERER_CAIROGRAPHICS_PDF ? file_name : NULL), + (sett.renderer == RENDERER_CAIROGRAPHICS_SVG ? file_name : NULL), + sett.scale); break; } g_free(file_name); diff --git a/main.c b/main.c index bdfe858..5a0e9b9 100644 --- a/main.c +++ b/main.c @@ -110,8 +110,8 @@ int main(int argc, char **argv) GOptionContext *context; gchar *gds_name; gchar *basename; - gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL; - gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE; + gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL, *svgname = NULL; + gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE, svg = FALSE; int scale = 1000; int app_status; @@ -120,9 +120,11 @@ int main(int argc, char **argv) { { "tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL }, { "pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL }, + //{ "svg", 'S', 0, G_OPTION_ARG_NONE, &svg, "Output SVG image", NULL }, { "scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by ", "" }, { "tex-output", 'o', 0, G_OPTION_ARG_FILENAME, &texname, "Optional path for TeX file", "PATH" }, { "pdf-output", 'O', 0, G_OPTION_ARG_FILENAME, &pdfname, "Optional path for PDF file", "PATH" }, + //{ "svg-output", 0, 0, G_OPTION_ARG_FILENAME, &svgname, "Optional path for PDF 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" }, { "tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL }, @@ -146,7 +148,7 @@ int main(int argc, char **argv) } /* No format selected */ - if (!(tikz || pdf)) { + if (!(tikz || pdf || svg)) { tikz = TRUE; } @@ -164,11 +166,18 @@ int main(int argc, char **argv) pdfname = g_strdup_printf("./%s.pdf", basename); } + if (!pdfname) { + pdfname = g_strdup_printf("./%s.svg", basename); + } + + command_line_convert_gds(gds_name, pdfname, texname, pdf, tikz, mappingname, cellname, - (double)scale, pdf_layers, pdf_standalone); + (double)scale, pdf_layers, pdf_standalone, svg, svgname); /* Clean up */ g_free(pdfname); g_free(texname); + g_free(svgname); + g_free(basename); if (mappingname) g_free(mappingname); if (cellname) diff --git a/trigonometric/vector-operations.c b/trigonometric/vector-operations.c index 6796687..bb741e5 100644 --- a/trigonometric/vector-operations.c +++ b/trigonometric/vector-operations.c @@ -52,6 +52,9 @@ void vector_2d_rotate(struct vector_2d *vec, double angle) double sin_val, cos_val; struct vector_2d temp; + if (!vec) + return; + sin_val = sin(angle); cos_val = cos(angle); diff --git a/widgets/conv-settings-dialog.c b/widgets/conv-settings-dialog.c index c553684..648d1b9 100644 --- a/widgets/conv-settings-dialog.c +++ b/widgets/conv-settings-dialog.c @@ -34,7 +34,8 @@ struct _RendererSettingsDialog { GtkDialog parent; /* Private loot */ GtkWidget *radio_latex; - GtkWidget *radio_cairo; + GtkWidget *radio_cairo_pdf; + GtkWidget *radio_cairo_svg; GtkWidget *scale; GtkWidget *layer_check; GtkWidget *standalone_check; @@ -83,7 +84,8 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self) builder = gtk_builder_new_from_resource("/dialog.glade"); box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box")); self->radio_latex = GTK_WIDGET(gtk_builder_get_object(builder, "latex-radio")); - self->radio_cairo = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-radio")); + self->radio_cairo_pdf = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-pdf-radio")); + self->radio_cairo_svg = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-svg-radio")); self->scale = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-scale")); self->standalone_check = GTK_WIDGET(gtk_builder_get_object(builder, "standalone-check")); self->layer_check = GTK_WIDGET(gtk_builder_get_object(builder, "layer-check")); @@ -110,13 +112,27 @@ RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent) void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings) { + GList *radio_buttons; + GList *temp_button_list; + GtkToggleButton *temp_button = NULL; + if (!settings || !dialog) return; settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale)); - settings->renderer = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE ? RENDERER_LATEX_TIKZ : RENDERER_CAIROGRAPHICS); + + /* Get active radio button selection */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE) { + settings->renderer = RENDERER_LATEX_TIKZ; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf)) == TRUE) { + settings->renderer = RENDERER_CAIROGRAPHICS_PDF; + } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg)) == TRUE) { + settings->renderer = RENDERER_CAIROGRAPHICS_SVG; + } + settings->tex_pdf_layers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->layer_check)); settings->tex_standalone = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->standalone_check)); } + void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings) { if (!settings || !dialog) @@ -131,10 +147,16 @@ void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struc gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_latex), TRUE); show_tex_options(dialog); break; - case RENDERER_CAIROGRAPHICS: + case RENDERER_CAIROGRAPHICS_PDF: hide_tex_options(dialog); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo), TRUE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf), TRUE); break; + case RENDERER_CAIROGRAPHICS_SVG: + hide_tex_options(dialog); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg), TRUE); + break; + + } } diff --git a/widgets/conv-settings-dialog.h b/widgets/conv-settings-dialog.h index ef5f6f0..909ceaa 100644 --- a/widgets/conv-settings-dialog.h +++ b/widgets/conv-settings-dialog.h @@ -36,7 +36,7 @@ G_BEGIN_DECLS /** @brief return type of the RedererSettingsDialog */ -enum output_renderer {RENDERER_LATEX_TIKZ, RENDERER_CAIROGRAPHICS}; +enum output_renderer {RENDERER_LATEX_TIKZ, RENDERER_CAIROGRAPHICS_PDF, RENDERER_CAIROGRAPHICS_SVG}; G_DECLARE_FINAL_TYPE(RendererSettingsDialog, renderer_settings_dialog, RENDERER, SETTINGS_DIALOG, GtkDialog)