9 Commits

Author SHA1 Message Date
199833d603 Updated code for cell size calculation 2018-12-29 01:13:33 +01:00
b0acbda6e3 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.
2018-12-22 21:30:16 +01:00
7e4b915961 Remove useless empty lines 2018-12-22 21:06:52 +01:00
1fe70422db Update size labels when size is set 2018-12-22 21:04:34 +01:00
b5087769ee Add cell size preview to dialog 2018-12-22 20:54:02 +01:00
4f9e5ca0b4 Add drawing area for size demonstartion 2018-12-22 19:37:57 +01:00
a2b83c37a9 Edit trigonometric functions 2018-12-22 19:31:36 +01:00
15ff68ea74 Fix invalid conversion 2018-12-22 19:13:33 +01:00
6bb05890b9 Add database unit parsing 2018-12-22 19:11:09 +01:00
12 changed files with 377 additions and 31 deletions

View File

@@ -48,6 +48,12 @@
#include <math.h>
#include <cairo.h>
/**
* @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, &current_lib->mod_time, &current_lib->access_time);

View File

@@ -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 */;
};

View File

@@ -4,7 +4,7 @@
<requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">1</property>
<property name="upper">3000</property>
<property name="upper">4000</property>
<property name="value">1000</property>
<property name="step_increment">10</property>
<property name="page_increment">1000</property>
@@ -51,7 +51,6 @@
<property name="label" translatable="yes">Render SVG using Cairographics (too buggy at the moment)</property>
<property name="use_action_appearance">True</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
@@ -69,6 +68,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="fill_level">4000</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
</object>
@@ -106,5 +106,50 @@
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkDrawingArea" id="shape-drawer">
<property name="height_request">200</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="x-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="y-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">7</property>
</packing>
</child>
</object>
</interface>

View File

@@ -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
@@ -202,8 +203,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;
@@ -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));
@@ -242,8 +247,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"),

5
main.c
View File

@@ -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;
}

View File

@@ -135,10 +135,29 @@ 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);
}
void bounding_box_apply_transform(double scale, double rotation, union bounding_box *box)
{
}

View File

@@ -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_ */

View File

@@ -0,0 +1,104 @@
/*
* GDSII-Converter
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file cell-trigonometrics.c
* @brief Calculation of gds_cell trigonometrics
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#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(&current_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,
&current_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, &current_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! */
}
}
/** @} */

View File

@@ -0,0 +1,47 @@
/*
* GDSII-Converter
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file cell-trigonometrics.h
* @brief Calculation of gds_cell trigonometrics
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @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_ */
/** @} */

View File

@@ -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)

View File

@@ -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,13 +76,69 @@ 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_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;
dialog = &(self->parent);
builder = gtk_builder_new_from_resource("/dialog.glade");
@@ -89,12 +149,22 @@ 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;
renderer_settings_dialog_update_labels(self);
g_object_unref(builder);
}
@@ -155,9 +225,37 @@ 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;
renderer_settings_dialog_update_labels(dialog);
}
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;
renderer_settings_dialog_update_labels(dialog);
}
/** @} */

View File

@@ -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__ */
/** @} */