From 6bb05890b95ba258e4b9c05221afce4f6eb128ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 19:11:09 +0100 Subject: [PATCH 01/18] Add database unit parsing --- gds-parser/gds-parser.c | 27 ++++++++++++++++++++++++--- gds-parser/gds-types.h | 2 +- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/gds-parser/gds-parser.c b/gds-parser/gds-parser.c index 8553b69..acdcea0 100644 --- a/gds-parser/gds-parser.c +++ b/gds-parser/gds-parser.c @@ -48,6 +48,12 @@ #include #include +/** + * @brief Default units assumed for library. + * @note This value is usually overwritten with the value defined in the library. + */ +#define GDS_DEFAULT_UNITS (10E-9) + #define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS error*/ #define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */ @@ -221,7 +227,7 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr) if (lib) { lib->cells = NULL; lib->name[0] = 0; - lib->unit_to_meters = 1; // Default. Will be overwritten + lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten lib->cell_names = NULL; } else return NULL; @@ -383,7 +389,7 @@ static int name_cell(struct gds_cell *cell, unsigned int bytes, return -1; } data[bytes] = 0; // Append '0' - len = strlen(data); + len = (int)strlen(data); if (len > CELL_NAME_MAX-1) { GDS_ERROR("Cell name '%s' too long: %d\n", data, len); return -1; @@ -710,6 +716,8 @@ int parse_gds_from_file(const char *filename, GList **library_list) break; case PATHTYPE: break; + case UNITS: + break; default: //GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length); break; @@ -731,7 +739,6 @@ int parse_gds_from_file(const char *filename, GList **library_list) switch (rec_type) { case HEADER: - case UNITS: case ENDLIB: case ENDSTR: case BOUNDARY: @@ -742,6 +749,20 @@ int parse_gds_from_file(const char *filename, GList **library_list) case INVALID: break; + case UNITS: + if (!current_lib) { + GDS_WARN("Units defined outside of library!\n"); + break; + } + + if (rec_data_length != 16) { + GDS_WARN("Unit define incomplete. Will assume database unit of %E meters\n", current_lib->unit_in_meters); + break; + } + + current_lib->unit_in_meters = gds_convert_double(&workbuff[8]); + GDS_INF("Length of database unit: %E meters\n", current_lib->unit_in_meters); + break; case BGNLIB: /* Parse date record */ gds_parse_date(workbuff, read, ¤t_lib->mod_time, ¤t_lib->access_time); diff --git a/gds-parser/gds-types.h b/gds-parser/gds-types.h index 88cad12..1fce5b8 100644 --- a/gds-parser/gds-types.h +++ b/gds-parser/gds-types.h @@ -113,7 +113,7 @@ struct gds_library { char name[CELL_NAME_MAX]; struct gds_time_field mod_time; struct gds_time_field access_time; - double unit_to_meters; /**< @warning not yet implemented */ + double unit_in_meters; /**< Length of a database unit in meters */ GList *cells; /**< List of #gds_cell that contains all cells in this library*/ GList *cell_names /**< List of strings that contains all cell names */; }; From 15ff68ea741dd8e1bd64a5ddff48569c082ddf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 19:13:33 +0100 Subject: [PATCH 02/18] Fix invalid conversion --- main-window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main-window.c b/main-window.c index d687875..b9e2ba8 100644 --- a/main-window.c +++ b/main-window.c @@ -202,8 +202,8 @@ end_destroy: static void on_convert_clicked(gpointer button, gpointer user) { static struct render_settings sett = { - .scale = 1000.0f, - .renderer = RENDERER_LATEX_TIKZ, + .scale = 1000.0, + .renderer = RENDERER_LATEX_TIKZ, }; struct convert_button_data *data = (struct convert_button_data *)user; GtkTreeSelection *selection; From a2b83c37a969ca7f8a2c46282bae3872302ed6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 19:31:36 +0100 Subject: [PATCH 03/18] Edit trigonometric functions --- main-window.c | 2 -- trigonometric/bounding-box.c | 16 +++++++++++++++- trigonometric/vector-operations.c | 19 +++++++++---------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/main-window.c b/main-window.c index b9e2ba8..564fa52 100644 --- a/main-window.c +++ b/main-window.c @@ -242,8 +242,6 @@ static void on_convert_clicked(gpointer button, gpointer user) goto ret_layer_destroy; } - - /* save file dialog */ dialog = gtk_file_chooser_dialog_new((sett.renderer == RENDERER_LATEX_TIKZ ? "Save LaTeX File" : "Save PDF"), diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index 3499ce4..648ac1b 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -135,12 +135,26 @@ static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b void bounding_box_calculate_path_box(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box) { - + printf("Error! Function bounding_box_calculate_path_box not yet implemented!\n"); } void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt) { + struct vector_2d point; + if (!destination || !pt) { + return; + } + + if (!conv_func) + conv_func(pt, &point); + else + (void)vector_2d_copy(&point, (struct vector_2d *)pt); + + destination->vectors.lower_left.x = MIN(destination->vectors.lower_left.x, point.x); + destination->vectors.lower_left.y = MIN(destination->vectors.lower_left.y, point.y); + destination->vectors.upper_right.x = MAX(destination->vectors.upper_right.x, point.x); + destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y); } /** @} */ diff --git a/trigonometric/vector-operations.c b/trigonometric/vector-operations.c index 4cdbca4..0666056 100644 --- a/trigonometric/vector-operations.c +++ b/trigonometric/vector-operations.c @@ -76,18 +76,17 @@ struct vector_2d *vector_2d_copy(struct vector_2d *opt_res, struct vector_2d *ve if (!vec) return NULL; - if (opt_res) { - opt_res->x = vec->x; - opt_res->y = vec->y; - return opt_res; - } else { + + if (opt_res) + res = opt_res; + else res = vector_2d_alloc(); - if (res) { - res->x = vec->x; - res->y = vec->y; - } - return res; + + if (res) { + res->x = vec->x; + res->y = vec->y; } + return res; } struct vector_2d *vector_2d_alloc(void) From 4f9e5ca0b4a6def63ef3cb52a35df778036f1b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 19:37:57 +0100 Subject: [PATCH 04/18] Add drawing area for size demonstartion --- glade/dialog.glade | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/glade/dialog.glade b/glade/dialog.glade index 90b1ea5..f5aeed0 100644 --- a/glade/dialog.glade +++ b/glade/dialog.glade @@ -106,5 +106,17 @@ 5 + + + 100 + True + False + + + False + True + 6 + + From b5087769eedffafecf850876fd7ec4a2eddb3a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 20:54:02 +0100 Subject: [PATCH 05/18] Add cell size preview to dialog --- glade/dialog.glade | 38 ++++++++++++- widgets/conv-settings-dialog.c | 100 +++++++++++++++++++++++++++++++-- widgets/conv-settings-dialog.h | 14 +++++ 3 files changed, 146 insertions(+), 6 deletions(-) diff --git a/glade/dialog.glade b/glade/dialog.glade index f5aeed0..527d0ad 100644 --- a/glade/dialog.glade +++ b/glade/dialog.glade @@ -4,7 +4,7 @@ 1 - 3000 + 4000 1000 10 1000 @@ -69,6 +69,7 @@ True True adjustment1 + 4000 0 0 @@ -108,7 +109,7 @@ - 100 + 200 True False @@ -118,5 +119,38 @@ 6 + + + True + False + + + True + False + + + True + True + 0 + + + + + True + False + + + True + True + 1 + + + + + False + True + 7 + + diff --git a/widgets/conv-settings-dialog.c b/widgets/conv-settings-dialog.c index e4280e1..14c8922 100644 --- a/widgets/conv-settings-dialog.c +++ b/widgets/conv-settings-dialog.c @@ -39,12 +39,16 @@ struct _RendererSettingsDialog { GtkWidget *scale; GtkWidget *layer_check; GtkWidget *standalone_check; + GtkDrawingArea *shape_drawing; + GtkLabel *x_label; + GtkLabel *y_label; + + double cell_height; + double cell_width; }; G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG) - - static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass) { /* No special code needed. Child cells are destroyed automatically due to reference counter */ @@ -72,11 +76,59 @@ static void latex_render_callback(GtkToggleButton *radio, RendererSettingsDialog hide_tex_options(dialog); } +static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gpointer data) +{ + int width; + int height; + GtkStyleContext *style_context; + GdkRGBA foreground_color; + RendererSettingsDialog *dialog = (RendererSettingsDialog *)data; + double usable_width; + double usable_height; + double height_scale; + double width_scale; + double final_scale_value; + + style_context = gtk_widget_get_style_context(widget); + width = gtk_widget_get_allocated_width(widget); + height = gtk_widget_get_allocated_height(widget); + + gtk_render_background(style_context, cr, 0, 0, width, height); + + gtk_style_context_get_color(style_context, gtk_style_context_get_state(style_context), + &foreground_color); + + gdk_cairo_set_source_rgba(cr, &foreground_color); + + cairo_save(cr); + + /* Tranform coordiante system */ + cairo_scale(cr, 1, -1); + cairo_translate(cr, (double)width/2.0, -(double)height/2.0); + + /* Define usable drawing area */ + usable_width = (0.95*(double)width) - 15.0; + usable_height = (0.95*(double)height) - 15.0; + + width_scale = usable_width/dialog->cell_width; + height_scale = usable_height/dialog->cell_height; + + final_scale_value = (width_scale < height_scale ? width_scale : height_scale); + + cairo_rectangle(cr, -dialog->cell_width*final_scale_value/2, -dialog->cell_height*final_scale_value/2, + dialog->cell_width*final_scale_value, dialog->cell_height*final_scale_value); + cairo_stroke(cr); + cairo_restore(cr); + + return FALSE; +} + static void renderer_settings_dialog_init(RendererSettingsDialog *self) { GtkBuilder *builder; GtkWidget *box; GtkDialog *dialog; + char default_buff[100]; dialog = &(self->parent); @@ -89,12 +141,26 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self) 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")); + self->shape_drawing = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "shape-drawer")); + self->x_label = GTK_LABEL(gtk_builder_get_object(builder, "x-label")); + self->y_label = GTK_LABEL(gtk_builder_get_object(builder, "y-label")); gtk_dialog_add_buttons(dialog, "Cancel", GTK_RESPONSE_CANCEL, "OK", GTK_RESPONSE_OK, NULL); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), box); gtk_window_set_title(GTK_WINDOW(self), "Renderer Settings"); g_signal_connect(self->radio_latex, "toggled", G_CALLBACK(latex_render_callback), (gpointer)self); + g_signal_connect(G_OBJECT(self->shape_drawing), + "draw", G_CALLBACK(shape_drawer_drawing_callback), (gpointer)self); + + /* Default values */ + self->cell_width = 1E-6; + self->cell_height = 1E-6; + + snprintf(default_buff, sizeof(default_buff), "Width: %E", self->cell_width); + gtk_label_set_text(self->x_label, default_buff); + snprintf(default_buff, sizeof(default_buff), "Height: %E", self->cell_height); + gtk_label_set_text(self->y_label, default_buff); g_object_unref(builder); } @@ -155,9 +221,35 @@ void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struc hide_tex_options(dialog); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg), TRUE); break; - - } } +void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, double width) +{ + if (!dialog) + return; + + if (width == 0.0) + width = 1E-6; + + if (width < 0.0) + width = -width; + + dialog->cell_width = width; +} + +void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, double height) +{ + if (!dialog) + return; + + if (height == 0.0) + height = 1E-6; + + if (height < 0.0) + height = -height; + + dialog->cell_height = height; +} + /** @} */ diff --git a/widgets/conv-settings-dialog.h b/widgets/conv-settings-dialog.h index 909ceaa..3680c04 100644 --- a/widgets/conv-settings-dialog.h +++ b/widgets/conv-settings-dialog.h @@ -75,6 +75,20 @@ void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struc */ void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings); +/** + * @brief renderer_settings_dialog_set_cell_width Set width for rendered cell + * @param dialog + * @param width Width in meters + */ +void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, double width); + +/** + * @brief renderer_settings_dialog_set_cell_height Set height for rendered cell + * @param dialog + * @param height Height in meters + */ +void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, double height); + #endif /* __CONV_SETTINGS_DIALOG_H__ */ /** @} */ From 1fe70422db47bf87e3e559a0f1ffdf3c040df0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 21:04:34 +0100 Subject: [PATCH 06/18] Update size labels when size is set --- widgets/conv-settings-dialog.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/widgets/conv-settings-dialog.c b/widgets/conv-settings-dialog.c index 14c8922..a10e1a5 100644 --- a/widgets/conv-settings-dialog.c +++ b/widgets/conv-settings-dialog.c @@ -123,13 +123,21 @@ static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gp return FALSE; } +static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self) +{ + char default_buff[100]; + + snprintf(default_buff, sizeof(default_buff), "Width: %E", self->cell_width); + gtk_label_set_text(self->x_label, default_buff); + snprintf(default_buff, sizeof(default_buff), "Height: %E", self->cell_height); + gtk_label_set_text(self->y_label, default_buff); +} + static void renderer_settings_dialog_init(RendererSettingsDialog *self) { GtkBuilder *builder; GtkWidget *box; GtkDialog *dialog; - char default_buff[100]; - dialog = &(self->parent); @@ -156,11 +164,7 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self) /* Default values */ self->cell_width = 1E-6; self->cell_height = 1E-6; - - snprintf(default_buff, sizeof(default_buff), "Width: %E", self->cell_width); - gtk_label_set_text(self->x_label, default_buff); - snprintf(default_buff, sizeof(default_buff), "Height: %E", self->cell_height); - gtk_label_set_text(self->y_label, default_buff); + renderer_settings_dialog_update_labels(self); g_object_unref(builder); } @@ -236,6 +240,7 @@ void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, dou width = -width; dialog->cell_width = width; + renderer_settings_dialog_update_labels(dialog); } void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, double height) @@ -250,6 +255,7 @@ void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, do height = -height; dialog->cell_height = height; + renderer_settings_dialog_update_labels(dialog); } /** @} */ From 7e4b91596113ce51c7f141b6a00c3589fce7966b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 21:06:52 +0100 Subject: [PATCH 07/18] Remove useless empty lines --- main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/main.c b/main.c index 5309c4d..10d19a1 100644 --- a/main.c +++ b/main.c @@ -85,8 +85,6 @@ static int start_gui(int argc, char **argv) g_application_register(G_APPLICATION(gapp), NULL, NULL); g_signal_connect(gapp, "activate", G_CALLBACK(gapp_activate), &appdata); - - menu = g_menu_new(); m_quit = g_menu_new(); m_about = g_menu_new(); @@ -102,7 +100,6 @@ static int start_gui(int argc, char **argv) g_object_unref(m_about); g_object_unref(menu); - app_status = g_application_run(G_APPLICATION(gapp), argc, argv); g_object_unref(gapp); @@ -122,7 +119,6 @@ int main(int argc, char **argv) int scale = 1000; int app_status; - GOptionEntry entries[] = { {"tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL }, {"pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL }, @@ -192,6 +188,5 @@ int main(int argc, char **argv) app_status = start_gui(argc, argv); } - return app_status; } From b0acbda6e32c8f5fa9b57e4b22a868ae7baf5426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 Dec 2018 21:30:11 +0100 Subject: [PATCH 08/18] Temporarily re-enabled SVG output (from GUI only) * Cairo version: 1.16.0-1 * SVG output doens't seem as broken as before with the current cairo version * Transparency doesn't work. Transparent layers aren't rendered at all. --- glade/dialog.glade | 1 - 1 file changed, 1 deletion(-) diff --git a/glade/dialog.glade b/glade/dialog.glade index 527d0ad..c60e085 100644 --- a/glade/dialog.glade +++ b/glade/dialog.glade @@ -51,7 +51,6 @@ Render SVG using Cairographics (too buggy at the moment) True True - False True False True From 199833d603de8372099eaeee81fad58f9341b4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 29 Dec 2018 01:13:33 +0100 Subject: [PATCH 09/18] Updated code for cell size calculation --- main-window.c | 5 ++ trigonometric/bounding-box.c | 5 ++ trigonometric/bounding-box.h | 1 + trigonometric/cell-trigonometrics.c | 104 ++++++++++++++++++++++++++++ trigonometric/cell-trigonometrics.h | 47 +++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 trigonometric/cell-trigonometrics.c create mode 100644 trigonometric/cell-trigonometrics.h diff --git a/main-window.c b/main-window.c index 564fa52..b67f733 100644 --- a/main-window.c +++ b/main-window.c @@ -36,6 +36,7 @@ #include "latex-output/latex-output.h" #include "widgets/conv-settings-dialog.h" #include "cairo-output/cairo-output.h" +#include "trigonometric/cell-trigonometrics.h" /** * @brief User data supplied to callback function of the open button @@ -217,6 +218,7 @@ static void on_convert_clicked(gpointer button, gpointer user) GtkFileFilter *filter; gint res; char *file_name; + union bounding_box *cell_box; /* Get selected cell */ selection = gtk_tree_view_get_selection(data->tree_view); @@ -231,6 +233,9 @@ static void on_convert_clicked(gpointer button, gpointer user) /* Get layers that are rendered */ layer_list = export_rendered_layer_info(); + /* Calculate cell size in DB units */ + + /* Show settings dialog */ settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window)); renderer_settings_dialog_set_settings(settings, &sett); res = gtk_dialog_run(GTK_DIALOG(settings)); diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index 648ac1b..db13baa 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -157,4 +157,9 @@ void bounding_box_update_point(union bounding_box *destination, conv_generic_to_ destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y); } +void bounding_box_apply_transform(double scale, double rotation, union bounding_box *box) +{ + +} + /** @} */ diff --git a/trigonometric/bounding-box.h b/trigonometric/bounding-box.h index aa9e1a1..e1f733d 100644 --- a/trigonometric/bounding-box.h +++ b/trigonometric/bounding-box.h @@ -48,6 +48,7 @@ void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t void bounding_box_update_box(union bounding_box *destination, union bounding_box *update); void bounding_box_prepare_empty(union bounding_box *box); void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt); +void bounding_box_apply_transform(double scale, double rotation, union bounding_box *box); #endif /* _BOUNDING_BOX_H_ */ diff --git a/trigonometric/cell-trigonometrics.c b/trigonometric/cell-trigonometrics.c new file mode 100644 index 0000000..5ca584d --- /dev/null +++ b/trigonometric/cell-trigonometrics.c @@ -0,0 +1,104 @@ +/* + * GDSII-Converter + * Copyright (C) 2018 Mario Hüttel + * + * 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 . + */ + +/** + * @file cell-trigonometrics.c + * @brief Calculation of gds_cell trigonometrics + * @author Mario Hüttel + */ + +#include "cell-trigonometrics.h" + +/** + * @addtogroup trigonometric + * @{ + */ + +static void convert_gds_point_to_2d_vector(struct gds_point *pt, struct vector_2d *vector) +{ + vector->x = pt->x; + vector->y = pt->y; +} + +/** + * @brief update_box_with_gfx + * @param box + * @param gfx_list + */ +static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gfx) +{ + union bounding_box current_box; + + bounding_box_prepare_empty(¤t_box); + + switch (gfx->gfx_type) { + case GRAPHIC_BOX: + case GRAPHIC_POLYGON: + bounding_box_calculate_polygon(gfx->vertices, + (conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector, + ¤t_box); + break; + case GRAPHIC_PATH: + /* + * This is not implemented correctly. + * Please be aware if paths are the oputpost elements of your cell. + * You might end up with a completely wrong calculated cell size. + */ + /* Okay.. You're right. It is not implemented at all. ;P */ + break; + default: + /* Unknown graphics object. */ + /* Print error? Nah.. */ + break; + } + + /* Update box with results */ + bounding_box_update_box(box, ¤t_box); +} + +void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell) +{ + GList *gfx_list; + struct gds_graphics *gfx; + GList *sub_cell_list; + struct gds_cell_instance *sub_cell; + union bounding_box temp_box; + + if (!box || !cell) + return; + + /* Update box with graphic elements */ + for (gfx_list = cell->graphic_objs; gfx_list != NULL; gfx_list = gfx_list->next) { + gfx = (struct gds_graphics *)gfx_list->data; + update_box_with_gfx(box, gfx); + } + + /* Update bounding box with boxes of subcells */ + for (sub_cell_list = cell->child_cells; sub_cell_list != NULL; sub_cell_list = sub_cell_list->next) { + sub_cell = (struct gds_cell_instance *)sub_cell_list->data; + bounding_box_prepare_empty(&temp_box); + /* Recursion Woohoo!! This dies if your GDS is faulty and contains a reference loop */ + calculate_cell_bounding_box(&temp_box, sub_cell->cell_ref); + + /* TODO: Apply transformations! */ + + } +} + +/** @} */ diff --git a/trigonometric/cell-trigonometrics.h b/trigonometric/cell-trigonometrics.h new file mode 100644 index 0000000..2a4ba5d --- /dev/null +++ b/trigonometric/cell-trigonometrics.h @@ -0,0 +1,47 @@ +/* + * GDSII-Converter + * Copyright (C) 2018 Mario Hüttel + * + * 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 . + */ + +/** + * @file cell-trigonometrics.h + * @brief Calculation of gds_cell trigonometrics + * @author Mario Hüttel + */ + +/** + * @addtogroup trigonometric + * @{ + */ + +#ifndef _CELL_TRIGONOMETRICS_H_ +#define _CELL_TRIGONOMETRICS_H_ + +#include "bounding-box.h" +#include "../gds-parser/gds-types.h" + +/** + * @brief calculate_cell_bounding_box Calculate bounding box of gds cell + * @param box Resulting boundig box. Will be uüdated and not overwritten + * @param cell toplevel cell + * @warning Path handling not yet implemented correctly + */ +void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell); + +#endif /* _CELL_TRIGONOMETRICS_H_ */ + +/** @} */ From 7124c9a5cc9d94d1923f0192c14a010bf2ec1507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 27 Feb 2019 20:27:01 +0100 Subject: [PATCH 10/18] Add fallthrough mark, correct Typo --- gds-parser/gds-parser.c | 1 + trigonometric/cell-trigonometrics.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gds-parser/gds-parser.c b/gds-parser/gds-parser.c index acdcea0..5183a0e 100644 --- a/gds-parser/gds-parser.c +++ b/gds-parser/gds-parser.c @@ -464,6 +464,7 @@ static void scan_cell_reference_dependencies(gpointer gcell, gpointer library) static void scan_library_references(gpointer library_list_item, gpointer user) { struct gds_library *lib = (struct gds_library *)library_list_item; + (void)user; GDS_INF("Scanning Library: %s\n", lib->name); g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib); diff --git a/trigonometric/cell-trigonometrics.c b/trigonometric/cell-trigonometrics.c index 5ca584d..4254b43 100644 --- a/trigonometric/cell-trigonometrics.c +++ b/trigonometric/cell-trigonometrics.c @@ -49,6 +49,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf switch (gfx->gfx_type) { case GRAPHIC_BOX: + /* Expected fallthrough */ case GRAPHIC_POLYGON: bounding_box_calculate_polygon(gfx->vertices, (conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector, @@ -57,7 +58,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf case GRAPHIC_PATH: /* * This is not implemented correctly. - * Please be aware if paths are the oputpost elements of your cell. + * Please be aware if paths are the outmost elements of your cell. * You might end up with a completely wrong calculated cell size. */ /* Okay.. You're right. It is not implemented at all. ;P */ From 5573ceb46b4e1174f3ec7defcb6159f677189680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 27 Feb 2019 20:28:06 +0100 Subject: [PATCH 11/18] Fix formatting in GDS-Parser --- gds-parser/gds-parser.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gds-parser/gds-parser.c b/gds-parser/gds-parser.c index 5183a0e..0c56ddb 100644 --- a/gds-parser/gds-parser.c +++ b/gds-parser/gds-parser.c @@ -870,15 +870,11 @@ int parse_gds_from_file(const char *filename, GList **library_list) fclose(gds_file); - if (!run) { /* Iterate and find references to cells */ g_list_foreach(lib_list, scan_library_references, NULL); } - - - *library_list = lib_list; free(workbuff); From bce47f11fc9f7c9efb1621b38d1d406c0756395d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 27 Feb 2019 20:28:53 +0100 Subject: [PATCH 12/18] Fix formatting --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 10d19a1..1eea1f7 100644 --- a/main.c +++ b/main.c @@ -56,8 +56,8 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_ } const static GActionEntry app_actions[] = { - { "quit", app_quit }, - { "about", app_about } + {"quit", app_quit}, + {"about", app_about} }; static void gapp_activate(GApplication *app, gpointer user_data) From 2e1cf456c7969f2e83db390a39435b46de18d46c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 27 Feb 2019 21:30:41 +0100 Subject: [PATCH 13/18] Add pointer to parent library to cells, implement first draft of cell size/shape preview --- gds-parser/gds-parser.c | 13 +++++++-- gds-parser/gds-types.h | 1 + main-window.c | 12 +++++++- trigonometric/bounding-box.c | 44 +++++++++++++++++++++++++++-- trigonometric/bounding-box.h | 4 ++- trigonometric/cell-trigonometrics.c | 16 +++++++++-- 6 files changed, 81 insertions(+), 9 deletions(-) diff --git a/gds-parser/gds-parser.c b/gds-parser/gds-parser.c index 0c56ddb..e6ef61b 100644 --- a/gds-parser/gds-parser.c +++ b/gds-parser/gds-parser.c @@ -58,7 +58,7 @@ #define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */ #if GDS_PRINT_DEBUG_INFOS - #define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__) /**< @brief standard printf. But cna be disabled in code */ + #define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__) /**< @brief standard printf. But can be disabled in code */ #else #define GDS_INF(fmt, ...) #endif @@ -303,6 +303,7 @@ static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr) cell->child_cells = NULL; cell->graphic_objs = NULL; cell->name[0] = 0; + cell->parent_library = NULL; } else return NULL; /* return cell */ @@ -614,12 +615,20 @@ int parse_gds_from_file(const char *filename, GList **library_list) GDS_INF("Leaving Library\n"); break; case BGNSTR: + if (current_lib == NULL) { + GDS_ERROR("Defining Cell outside of library!\n"); + run = -4; + break; + } current_lib->cells = append_cell(current_lib->cells, ¤t_cell); if (current_lib->cells == NULL) { GDS_ERROR("Allocating memory failed"); run = -3; break; } + + current_cell->parent_library = current_lib; + GDS_INF("Entering Cell\n"); break; case ENDSTR: @@ -726,7 +735,7 @@ int parse_gds_from_file(const char *filename, GList **library_list) /* No Data -> No Processing, go back to top */ - if (!rec_data_length) continue; + if (!rec_data_length || run != 1) continue; read = fread(workbuff, sizeof(char), rec_data_length, gds_file); diff --git a/gds-parser/gds-types.h b/gds-parser/gds-types.h index 1fce5b8..80e2acc 100644 --- a/gds-parser/gds-types.h +++ b/gds-parser/gds-types.h @@ -104,6 +104,7 @@ struct gds_cell { struct gds_time_field access_time; GList *child_cells; /**< @brief List of #gds_cell_instance elements */ GList *graphic_objs; /**< @brief List of #gds_graphics */ + struct gds_library *parent_library; /**< @brief Pointer to parent library */ }; /** diff --git a/main-window.c b/main-window.c index 6874daf..a5328bf 100644 --- a/main-window.c +++ b/main-window.c @@ -230,7 +230,8 @@ static void on_convert_clicked(gpointer button, gpointer user) GtkFileFilter *filter; gint res; char *file_name; - union bounding_box *cell_box; + union bounding_box cell_box; + double height, width; /* Get selected cell */ selection = gtk_tree_view_get_selection(data->tree_view); @@ -246,10 +247,19 @@ static void on_convert_clicked(gpointer button, gpointer user) layer_list = export_rendered_layer_info(); /* Calculate cell size in DB units */ + bounding_box_prepare_empty(&cell_box); + calculate_cell_bounding_box(&cell_box, cell_to_render); + + /* Calculate size in meters */ + height = (cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y) * cell_to_render->parent_library->unit_in_meters; + width = (cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x) * cell_to_render->parent_library->unit_in_meters; /* Show settings dialog */ settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window)); renderer_settings_dialog_set_settings(settings, &sett); + renderer_settings_dialog_set_cell_height(settings, height); + renderer_settings_dialog_set_cell_width(settings, width); + res = gtk_dialog_run(GTK_DIALOG(settings)); if (res == GTK_RESPONSE_OK) { renderer_settings_dialog_get_settings(settings, &sett); diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index db13baa..80811dd 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -133,9 +133,32 @@ static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b vector_2d_subtract(m2, m2, &v_vec); } -void bounding_box_calculate_path_box(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box) +void bounding_box_calculate_path_box(GList *vertices, double thickness, + conv_generic_to_vector_2d_t conv_func, union bounding_box *box) { - printf("Error! Function bounding_box_calculate_path_box not yet implemented!\n"); + GList *vertex_iterator; + struct vector_2d pt; + + printf("Warning! Function bounding_box_calculate_path_box not yet implemented correctly!\n"); + + if (!vertices || !box) + return; + + for (vertex_iterator = vertices; vertex_iterator != NULL; vertex_iterator = g_list_next(vertex_iterator)) { + + if (conv_func != NULL) + conv_func(vertex_iterator->data, &pt); + else + (void)vector_2d_copy(&pt, (struct vector_2d *)vertex_iterator->data); + + /* These are approximations. + * Used as long as miter point calculation is not fully implemented + */ + box->vectors.lower_left.x = MIN(box->vectors.lower_left.x, pt.x - thickness/2); + box->vectors.lower_left.y = MIN(box->vectors.lower_left.y, pt.y - thickness/2); + box->vectors.upper_right.x = MAX(box->vectors.upper_right.x, pt.x + thickness/2); + box->vectors.upper_right.y = MAX(box->vectors.upper_right.y, pt.y + thickness/2); + } } void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt) @@ -157,9 +180,24 @@ void bounding_box_update_point(union bounding_box *destination, conv_generic_to_ destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y); } -void bounding_box_apply_transform(double scale, double rotation, union bounding_box *box) +/** + * @brief bounding_box_apply_transform + * @param scale scaling factor + * @param rotation roation of bounding box around the origin in degrees (counterclockwise) + * @param box bounding box the operations should be applied to + */ +void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box) { + int i; + /* Due to linearity, the order of the operations does not matter. + * flip must be applied before rotation as defined by the GDS format + */ + for (i = 0; i < 2; i++) { + box->vector_array[i].y *= (flip_at_x ? -1 : 1); + vector_2d_rotate(&box->vector_array[i], rotation_deg * M_PI / 180); + vector_2d_scale(&box->vector_array[i], scale); + } } /** @} */ diff --git a/trigonometric/bounding-box.h b/trigonometric/bounding-box.h index e1f733d..12f883d 100644 --- a/trigonometric/bounding-box.h +++ b/trigonometric/bounding-box.h @@ -32,6 +32,7 @@ #define _BOUNDING_BOX_H_ #include #include "vector-operations.h" +#include union bounding_box { /** Coordinate System is (y up | x right) */ @@ -48,7 +49,8 @@ void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t void bounding_box_update_box(union bounding_box *destination, union bounding_box *update); void bounding_box_prepare_empty(union bounding_box *box); void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt); -void bounding_box_apply_transform(double scale, double rotation, union bounding_box *box); +void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box); +void bounding_box_calculate_path_box(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box); #endif /* _BOUNDING_BOX_H_ */ diff --git a/trigonometric/cell-trigonometrics.c b/trigonometric/cell-trigonometrics.c index 4254b43..4466bc7 100644 --- a/trigonometric/cell-trigonometrics.c +++ b/trigonometric/cell-trigonometrics.c @@ -24,6 +24,7 @@ */ #include "cell-trigonometrics.h" +#include /** * @addtogroup trigonometric @@ -61,7 +62,9 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf * Please be aware if paths are the outmost elements of your cell. * You might end up with a completely wrong calculated cell size. */ - /* Okay.. You're right. It is not implemented at all. ;P */ + bounding_box_calculate_path_box(gfx->vertices, gfx->width_absolute, + (conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector, + ¤t_box); break; default: /* Unknown graphics object. */ @@ -97,8 +100,17 @@ void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell) /* Recursion Woohoo!! This dies if your GDS is faulty and contains a reference loop */ calculate_cell_bounding_box(&temp_box, sub_cell->cell_ref); - /* TODO: Apply transformations! */ + /* Apply transformations */ + bounding_box_apply_transform(ABS(sub_cell->magnification), sub_cell->angle, sub_cell->flipped, &temp_box); + /* Move bounding box to origin */ + temp_box.vectors.lower_left.x += sub_cell->origin.x; + temp_box.vectors.lower_left.x += sub_cell->origin.x; + temp_box.vectors.upper_right.y += sub_cell->origin.y; + temp_box.vectors.upper_right.y += sub_cell->origin.y; + + /* update the parent's box */ + bounding_box_update_box(box, &temp_box); } } From 531634b55a6fb2816d96aeaa4193fb2674bcb11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 27 Feb 2019 21:42:54 +0100 Subject: [PATCH 14/18] Fix bug in bounding box 2d translation --- trigonometric/cell-trigonometrics.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trigonometric/cell-trigonometrics.c b/trigonometric/cell-trigonometrics.c index 4466bc7..823a531 100644 --- a/trigonometric/cell-trigonometrics.c +++ b/trigonometric/cell-trigonometrics.c @@ -105,8 +105,8 @@ void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell) /* Move bounding box to origin */ temp_box.vectors.lower_left.x += sub_cell->origin.x; - temp_box.vectors.lower_left.x += sub_cell->origin.x; - temp_box.vectors.upper_right.y += sub_cell->origin.y; + temp_box.vectors.upper_right.x += sub_cell->origin.x; + temp_box.vectors.lower_left.y += sub_cell->origin.y; temp_box.vectors.upper_right.y += sub_cell->origin.y; /* update the parent's box */ From 845da756b72ffeec10497f2a164551ed1c7684be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Thu, 28 Feb 2019 21:17:54 +0100 Subject: [PATCH 15/18] Fix bug of wrong bounding box calculation: Replace DBL_MIN with -DBL_MAX --- trigonometric/bounding-box.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index 80811dd..4dc0225 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -38,7 +38,7 @@ void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box) { - double xmin = DBL_MAX, xmax = DBL_MIN, ymin = DBL_MAX, ymax = DBL_MIN; + double xmin = DBL_MAX, xmax = -DBL_MAX, ymin = DBL_MAX, ymax = -DBL_MAX; struct vector_2d temp_vec; GList *list_item; @@ -86,8 +86,8 @@ void bounding_box_prepare_empty(union bounding_box *box) { box->vectors.lower_left.x = DBL_MAX; box->vectors.lower_left.y = DBL_MAX; - box->vectors.upper_right.x = DBL_MIN; - box->vectors.upper_right.y = DBL_MIN; + box->vectors.upper_right.x = -DBL_MAX; + box->vectors.upper_right.y = -DBL_MAX; } static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b, struct vector_2d *c, From f74e2d5cf5ecba4d19231adaf25a81e7ca63e6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 4 Mar 2019 19:35:04 +0100 Subject: [PATCH 16/18] Fix bug --- trigonometric/bounding-box.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index 4dc0225..ac51cac 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -169,7 +169,7 @@ void bounding_box_update_point(union bounding_box *destination, conv_generic_to_ return; } - if (!conv_func) + if (conv_func) conv_func(pt, &point); else (void)vector_2d_copy(&point, (struct vector_2d *)pt); From 91a3e8f9833ca6d7dde5bc979d691e2705c21e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 4 Mar 2019 19:35:25 +0100 Subject: [PATCH 17/18] Fix style --- trigonometric/bounding-box.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/trigonometric/bounding-box.c b/trigonometric/bounding-box.c index ac51cac..9d3b26d 100644 --- a/trigonometric/bounding-box.c +++ b/trigonometric/bounding-box.c @@ -165,9 +165,8 @@ void bounding_box_update_point(union bounding_box *destination, conv_generic_to_ { struct vector_2d point; - if (!destination || !pt) { + if (!destination || !pt) return; - } if (conv_func) conv_func(pt, &point); From 68e7d52cd8d0e32f0697ac7f81524a31a59b1282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 4 Mar 2019 20:14:21 +0100 Subject: [PATCH 18/18] Changed settings dialog api to use database units. Implement render output size preview --- glade/dialog.glade | 35 ++++++++++++++- main-window.c | 7 +-- widgets/conv-settings-dialog.c | 78 +++++++++++++++++++++++++--------- widgets/conv-settings-dialog.h | 15 +++++-- 4 files changed, 106 insertions(+), 29 deletions(-) diff --git a/glade/dialog.glade b/glade/dialog.glade index c60e085..792d1ca 100644 --- a/glade/dialog.glade +++ b/glade/dialog.glade @@ -113,7 +113,7 @@ False - False + True True 6 @@ -151,5 +151,38 @@ 7 + + + True + False + + + True + False + + + True + True + 0 + + + + + True + False + + + True + True + 1 + + + + + False + True + 8 + + diff --git a/main-window.c b/main-window.c index a5328bf..600bf0a 100644 --- a/main-window.c +++ b/main-window.c @@ -250,13 +250,14 @@ static void on_convert_clicked(gpointer button, gpointer user) bounding_box_prepare_empty(&cell_box); calculate_cell_bounding_box(&cell_box, cell_to_render); - /* Calculate size in meters */ - height = (cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y) * cell_to_render->parent_library->unit_in_meters; - width = (cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x) * cell_to_render->parent_library->unit_in_meters; + /* Calculate size in meters database units */ + height = (cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y); + width = (cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x); /* Show settings dialog */ settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window)); renderer_settings_dialog_set_settings(settings, &sett); + renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters); renderer_settings_dialog_set_cell_height(settings, height); renderer_settings_dialog_set_cell_width(settings, width); diff --git a/widgets/conv-settings-dialog.c b/widgets/conv-settings-dialog.c index a10e1a5..7460dfb 100644 --- a/widgets/conv-settings-dialog.c +++ b/widgets/conv-settings-dialog.c @@ -43,8 +43,12 @@ struct _RendererSettingsDialog { GtkLabel *x_label; GtkLabel *y_label; - double cell_height; - double cell_width; + GtkLabel *x_output_label; + GtkLabel *y_output_label; + + unsigned int cell_height; + unsigned int cell_width; + double unit_in_meters; }; G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG) @@ -110,13 +114,13 @@ static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gp usable_width = (0.95*(double)width) - 15.0; usable_height = (0.95*(double)height) - 15.0; - width_scale = usable_width/dialog->cell_width; - height_scale = usable_height/dialog->cell_height; + width_scale = usable_width/(double)dialog->cell_width; + height_scale = usable_height/(double)dialog->cell_height; final_scale_value = (width_scale < height_scale ? width_scale : height_scale); - cairo_rectangle(cr, -dialog->cell_width*final_scale_value/2, -dialog->cell_height*final_scale_value/2, - dialog->cell_width*final_scale_value, dialog->cell_height*final_scale_value); + cairo_rectangle(cr, -(double)dialog->cell_width*final_scale_value/2.0, -(double)dialog->cell_height*final_scale_value/2.0, + (double)dialog->cell_width*final_scale_value, (double)dialog->cell_height*final_scale_value); cairo_stroke(cr); cairo_restore(cr); @@ -126,11 +130,31 @@ static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gp static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self) { char default_buff[100]; + double scale; - snprintf(default_buff, sizeof(default_buff), "Width: %E", self->cell_width); + if (!self) + return; + + snprintf(default_buff, sizeof(default_buff), "Width: %E", self->cell_width * self->unit_in_meters); gtk_label_set_text(self->x_label, default_buff); - snprintf(default_buff, sizeof(default_buff), "Height: %E", self->cell_height); + snprintf(default_buff, sizeof(default_buff), "Height: %E", self->cell_height * self->unit_in_meters); gtk_label_set_text(self->y_label, default_buff); + + scale = gtk_range_get_value(GTK_RANGE(self->scale)); + + snprintf(default_buff, sizeof(default_buff), "Output Width: %u px", (unsigned int)((double)self->cell_width / scale)); + gtk_label_set_text(self->x_output_label, default_buff); + snprintf(default_buff, sizeof(default_buff), "Output Height: %u px", (unsigned int)((double)self->cell_height / scale)); + gtk_label_set_text(self->y_output_label, default_buff); +} + +static void scale_value_changed(GtkRange *range, gpointer user_data) +{ + (void)range; + RendererSettingsDialog *dialog; + + dialog = RENDERER_SETTINGS_DIALOG(user_data); + renderer_settings_dialog_update_labels(dialog); } static void renderer_settings_dialog_init(RendererSettingsDialog *self) @@ -152,6 +176,8 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self) self->shape_drawing = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "shape-drawer")); self->x_label = GTK_LABEL(gtk_builder_get_object(builder, "x-label")); self->y_label = GTK_LABEL(gtk_builder_get_object(builder, "y-label")); + self->x_output_label = GTK_LABEL(gtk_builder_get_object(builder, "x-output-label")); + self->y_output_label = GTK_LABEL(gtk_builder_get_object(builder, "y-output-label")); gtk_dialog_add_buttons(dialog, "Cancel", GTK_RESPONSE_CANCEL, "OK", GTK_RESPONSE_OK, NULL); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), box); @@ -161,9 +187,12 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self) g_signal_connect(G_OBJECT(self->shape_drawing), "draw", G_CALLBACK(shape_drawer_drawing_callback), (gpointer)self); + g_signal_connect(self->scale, "value-changed", G_CALLBACK(scale_value_changed), (gpointer)self); + /* Default values */ - self->cell_width = 1E-6; - self->cell_height = 1E-6; + self->cell_width = 1; + self->cell_height = 1; + self->unit_in_meters = 1E-6; renderer_settings_dialog_update_labels(self); g_object_unref(builder); @@ -228,34 +257,41 @@ void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struc } } -void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, double width) +void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width) { if (!dialog) return; - if (width == 0.0) - width = 1E-6; + if (width == 0) + width = 1; - if (width < 0.0) - width = -width; dialog->cell_width = width; renderer_settings_dialog_update_labels(dialog); } -void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, double height) +void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height) { if (!dialog) return; - if (height == 0.0) - height = 1E-6; - - if (height < 0.0) - height = -height; + if (height == 0) + height = 1; dialog->cell_height = height; renderer_settings_dialog_update_labels(dialog); } +void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters) +{ + if (!dialog) + return; + + if (unit_in_meters < 0) + unit_in_meters *= -1; + + dialog->unit_in_meters = unit_in_meters; + renderer_settings_dialog_update_labels(dialog); +} + /** @} */ diff --git a/widgets/conv-settings-dialog.h b/widgets/conv-settings-dialog.h index 3680c04..562a114 100644 --- a/widgets/conv-settings-dialog.h +++ b/widgets/conv-settings-dialog.h @@ -78,16 +78,23 @@ void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struc /** * @brief renderer_settings_dialog_set_cell_width Set width for rendered cell * @param dialog - * @param width Width in meters + * @param width Width in database units */ -void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, double width); +void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width); /** * @brief renderer_settings_dialog_set_cell_height Set height for rendered cell * @param dialog - * @param height Height in meters + * @param height Height in database units */ -void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, double height); +void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height); + +/** + * @brief renderer_settings_dialog_set_database_unit_scale Set database scale + * @param dialog dialog element + * @param unit_in_meters Database unit in meters + */ +void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters); #endif /* __CONV_SETTINGS_DIALOG_H__ */