50 Commits

Author SHA1 Message Date
221d5a5db5 important Bugfix. Flipping direction in LaTeX renderer fixed 2018-06-12 18:33:13 +02:00
a531da26d3 Merge branch 'master' of git.shimatta.de:mhu/gds-render 2018-06-11 15:18:02 +02:00
f913976a44 replaced date parser by shorter but more complicated code 2018-06-11 15:16:40 +02:00
da19037211 Activate -Wall compile flag, Fix code not to throw warnings 2018-06-05 22:51:50 +02:00
3ed83c1146 open GDS File in binary mode 2018-06-04 12:26:31 +02:00
9d10b17d7d add 0x prefix for hex number 2018-06-04 12:05:53 +02:00
ea53890cd0 Move delete-event signal connect from glade to C-File 2018-06-04 11:41:35 +02:00
88815bc007 Fix implicit function declaration 2018-06-04 11:37:36 +02:00
288965af7b move example alyouts+rendered outputs into subfolders 2018-06-02 02:58:56 +02:00
690c1cb5ae Implement full path support with correct line caps (rounded|flat|squared) 2018-06-02 02:54:38 +02:00
0f4de608a2 Enabled parser to detect path-types, fix indentation 2018-06-02 02:25:01 +02:00
d1a1cb762a update eymaples 2018-06-01 21:48:10 +02:00
223a2c6e71 add support for paths 2018-06-01 21:47:54 +02:00
27cb06afe2 Add example GDS file, mapping file, and output files generated 2018-05-31 02:18:05 +02:00
1c4ccd9153 Support for standalone rendering 2018-05-31 02:16:37 +02:00
dc208c6ad3 fix bug in parser 2018-05-31 02:16:12 +02:00
8455491c11 fix syntax error in exported LaTeX code 2018-05-31 00:08:02 +02:00
58c7f571f4 fix type cast warning 2018-05-31 00:06:00 +02:00
0290a6c9d3 Layer support added 2018-05-31 00:04:14 +02:00
9b7073604b Merge branch 'master' of git.shimatta.de:mhu/gds-render 2018-05-30 23:57:00 +02:00
f2c58e4520 LaTeX Layer support started 2018-05-30 23:56:38 +02:00
c1a7dce0a3 Add directory for rendering example 2018-05-27 16:53:02 +02:00
37a561115a fix: gtk_widget_destroy: assertion 'GTK_IS_WIDGET (widget)' failed 2018-05-24 00:36:55 +02:00
1ffe677804 Fix 2nd segfault 2018-05-24 00:23:39 +02:00
2c3c7a9a80 fix Segfault 2018-05-24 00:15:39 +02:00
da34256b83 Remove lonely 'Foo' 2018-05-23 14:22:02 +02:00
93b726a05f TeX output works
* A lot is missing (paths...)
* Dimension limit of TeX is a problem.
2018-05-23 13:17:10 +02:00
6c24cebaf7 Drag and drop layer arrangement. Major Feature 2018-05-23 01:03:16 +02:00
084c6999c7 Add option to specify layer order, wrote tex output for layer order 2018-05-22 18:45:23 +02:00
a261f61c5c fix commit 2018-05-22 16:18:28 +02:00
29f66951d1 Completely restructudred code
* Subfolders for different modules
* LaTeX output module started
* Convert button sensitivity impemented
2018-05-22 16:17:14 +02:00
9a6aee1410 Make only Cells selectable 2018-05-22 13:00:50 +02:00
4987459337 restructured code 2018-05-22 12:59:28 +02:00
1db0ac1d17 Optimized Layout in Header Bar 2018-05-22 12:47:44 +02:00
35d10a5a24 Custom Library/Cell Renderer for tree view
This allows direct storing of library/cell structures instead of only names
2018-05-22 00:00:19 +02:00
46cc20e878 Colorized Save/Load Layer mapping buttons 2018-05-19 20:37:09 +02:00
17b5848335 Implement Date/Time Field Support. Change Text Color for cell names 2018-05-19 20:26:33 +02:00
f47c2e52ff Merge branch 'master' of git.shimatta.de:mhu/gds-render 2018-05-19 18:31:34 +02:00
dc748504ad edited for Gnome builder 2018-05-19 18:31:18 +02:00
89b34b1326 Remove unecessary lines from CMake config 2018-05-18 23:21:36 +02:00
e8fbe25bcb Improved Layer Selection
* Removed Slider for opacity. Use Color Dialog instead
* Implement Layer loading
* remove Spinner from header bar
2018-05-18 22:47:39 +02:00
302a0d1da7 move glade files into resources inside the binary 2018-05-18 18:47:19 +02:00
f42a4c40fb fix widget 2018-05-17 22:36:09 +02:00
035f6889eb removed printf 2018-05-17 21:53:17 +02:00
9eb861f6d8 layer mapping save function implemented 2018-05-17 21:46:14 +02:00
d7d8e6b2dc Library deletion completed 2018-05-17 20:31:25 +02:00
f5f381b37a add spinner, remove debug messages 2018-05-16 20:07:41 +02:00
7aa593fdf9 make list scrollable 2018-05-16 16:36:36 +02:00
f49f32a83e Corrected License string 2018-05-16 16:29:34 +02:00
d52f5afb93 add GPL license 2018-05-16 16:27:38 +02:00
31 changed files with 17900 additions and 458 deletions

10
.buildconfig Normal file
View File

@@ -0,0 +1,10 @@
[default]
name=Default
runtime=host
config-opts=
run-opts=
prefix=/home/mari/.cache/gnome-builder/install/gds-render/host
app-id=
postbuild=
prebuild=
default=true

View File

@@ -1,15 +1,36 @@
cmake_minimum_required(VERSION 2.8)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
project(gds-render)
add_subdirectory(glade)
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS})
configure_file(glade/main.glade glade/main.glade COPYONLY)
configure_file(glade/layer-widget.glade glade/layer-widget.glade COPYONLY)
add_definitions(${GLIB2_CFLAGS_OTHER})
project(gds-render)
add_executable(${PROJECT_NAME} "main.c" "gdsparse.c" "layer-element.c" "layer-selector.c")
aux_source_directory("layer-widget" LAYER_SOURCES)
aux_source_directory("tree-renderer" RENDERER_SOURCES)
aux_source_directory("gds-parser" PARSER_SOURCES)
aux_source_directory("latex-output" LATEX_SOURCES)
set(SOURCE "main.c" "layer-selector.c")
set(SOURCE
${SOURCE}
${LAYER_SOURCES}
${RENDERER_SOURCES}
${PARSER_SOURCES}
${LATEX_SOURCES}
)
add_compile_options(-Wall)
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
add_dependencies(${PROJECT_NAME} glib-resources)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} m)

View File

@@ -5,8 +5,8 @@
* 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 as published by
* the Free Software Foundation, either version 2 of the License.
* 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
@@ -27,7 +27,7 @@
*/
#include "gdsparse.h"
#include "gds-parser.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -58,6 +58,8 @@ enum record {
STRANS = 0x1A01,
BOX = 0x2D00,
LAYER = 0x0D02,
WIDTH = 0x0F03,
PATHTYPE = 0x2102
};
static int name_cell_ref(struct gds_cell_instance *cell_inst,
@@ -83,7 +85,7 @@ static int name_cell_ref(struct gds_cell_instance *cell_inst,
return 0;
}
static double gds_convert_double(char *data)
static double gds_convert_double(const char *data)
{
bool sign_bit;
int i;
@@ -123,7 +125,7 @@ static double gds_convert_double(char *data)
return ret_val;
}
static signed int gds_convert_signed_int(char *data)
static signed int gds_convert_signed_int(const char *data)
{
int ret;
@@ -139,7 +141,7 @@ static signed int gds_convert_signed_int(char *data)
return ret;
}
static int16_t gds_convert_signed_int16(char *data)
static int16_t gds_convert_signed_int16(const char *data)
{
if (!data) {
GDS_ERROR("This should not happen");
@@ -149,7 +151,17 @@ static int16_t gds_convert_signed_int16(char *data)
(((int16_t)(data[1]) & 0xFF) << 0));
}
static GList *append_library(GList *curr_list)
static uint16_t gds_convert_unsigend_int16(const char *data)
{
if (!data) {
GDS_ERROR("This should not happen");
return 0;
}
return (uint16_t)((((uint16_t)(data[0]) & 0xFF) << 8) |
(((uint16_t)(data[1]) & 0xFF) << 0));
}
static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
{
struct gds_library *lib;
@@ -161,6 +173,9 @@ static GList *append_library(GList *curr_list)
lib->cell_names = NULL;
} else
return NULL;
if (library_ptr)
*library_ptr = lib;
return g_list_append(curr_list, lib);
}
@@ -175,7 +190,8 @@ static GList *append_graphics(GList *curr_list, enum graphics_type type,
gfx->layer = 0;
gfx->vertices = NULL;
gfx->width_absolute = 0;
gfx->type = type;
gfx->gfx_type = type;
gfx->path_render_type = PATH_FLUSH;
} else
return NULL;
@@ -331,9 +347,43 @@ void scan_library_references(gpointer library_list_item, gpointer user)
g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib);
}
void gds_parse_date(const char *buffer, int length, struct gds_time_field *mod_date, struct gds_time_field *access_date)
{
struct gds_time_field *temp_date;
if (!access_date || !mod_date) {
GDS_WARN("Date structures invalid");
return;
}
if (length != (2*6*2)) {
GDS_WARN("Could not parse date field! Not the specified length");
return;
}
for (temp_date = mod_date; 1; temp_date = access_date) {
temp_date->year = gds_convert_unsigend_int16(buffer);
buffer += 2;
temp_date->month = gds_convert_unsigend_int16(buffer);
buffer += 2;
temp_date->day = gds_convert_unsigend_int16(buffer);
buffer += 2;
temp_date->hour = gds_convert_unsigend_int16(buffer);
buffer += 2;
temp_date->minute = gds_convert_unsigend_int16(buffer);
buffer += 2;
temp_date->second = gds_convert_unsigend_int16(buffer);
buffer += 2;
if (temp_date == access_date)
break;
}
}
int parse_gds_from_file(const char *filename, GList **library_list)
{
char workbuff[1024];
char *workbuff;
int read;
int i;
int run = 1;
@@ -350,8 +400,14 @@ int parse_gds_from_file(const char *filename, GList **library_list)
lib_list = *library_list;
/* Allocate working buffer */
workbuff = (char *)malloc(sizeof(char)*128*1024);
if(!workbuff)
return -100;
/* open File */
gds_file = fopen(filename, "r");
gds_file = fopen(filename, "rb");
if (gds_file == NULL) {
GDS_ERROR("Could not open File %s", filename);
return -1;
@@ -374,8 +430,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
break;
}
rec_data_length = (uint16_t)((((uint16_t)(workbuff[0])) << 8) |
(uint16_t)(workbuff[1]));
rec_data_length = gds_convert_unsigend_int16(workbuff);
if (rec_data_length < 4) {
/* Possible Zero-Padding: */
@@ -398,13 +453,12 @@ int parse_gds_from_file(const char *filename, GList **library_list)
GDS_ERROR("Unexpected end of file");
break;
}
rec_type = (uint16_t)((((uint16_t)(workbuff[0])) << 8) |
(uint16_t)(workbuff[1]));
rec_type = gds_convert_unsigend_int16(workbuff);
/* if begin: Allocate structures */
switch (rec_type) {
case BGNLIB:
lib_list = append_library(lib_list);
lib_list = append_library(lib_list, &current_lib);
if (lib_list == NULL) {
GDS_ERROR("Allocating memory failed");
run = -3;
@@ -412,8 +466,6 @@ int parse_gds_from_file(const char *filename, GList **library_list)
}
printf("Entering Lib\n");
current_lib = (struct gds_library *)
g_list_last(lib_list)->data;
break;
case ENDLIB:
if (current_lib == NULL) {
@@ -505,7 +557,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
case ENDEL:
if (current_graphics != NULL) {
printf("\tLeaving %s\n", (current_graphics->type == GRAPHIC_POLYGON ? "boundary" : "path"));
printf("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary" : "path"));
current_graphics = NULL;
}
if (current_s_reference != NULL) {
@@ -529,6 +581,10 @@ int parse_gds_from_file(const char *filename, GList **library_list)
break;
case STRANS:
break;
case WIDTH:
break;
case PATHTYPE:
break;
default:
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
break;
@@ -541,12 +597,33 @@ int parse_gds_from_file(const char *filename, GList **library_list)
read = fread(workbuff, sizeof(char), rec_data_length, gds_file);
if (read != rec_data_length) {
GDS_ERROR("Could not read enough data");
GDS_ERROR("Could not read enough data: requested: %u, read: %u | Type: 0x%04x\n",
(unsigned int)rec_data_length, (unsigned int)read, (unsigned int)rec_type);
run = -5;
break;
}
switch (rec_type) {
case HEADER:
case UNITS:
case ENDLIB:
case ENDSTR:
case BOUNDARY:
case PATH:
case SREF:
case ENDEL:
case BOX:
case INVALID:
break;
case BGNLIB:
/* Parse date record */
gds_parse_date(workbuff, read, &current_lib->mod_time, &current_lib->access_time);
break;
case BGNSTR:
gds_parse_date(workbuff, read, &current_cell->mod_time, &current_cell->access_time);
break;
case LIBNAME:
name_library(current_lib, read, workbuff);
break;
@@ -582,6 +659,12 @@ int parse_gds_from_file(const char *filename, GList **library_list)
case SNAME:
name_cell_ref(current_s_reference, read, workbuff);
break;
case WIDTH:
if (!current_graphics) {
GDS_WARN("Width defined outside of path element");
}
current_graphics->width_absolute = gds_convert_signed_int(workbuff);
break;
case LAYER:
if (!current_graphics) {
GDS_WARN("Layer has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
@@ -621,6 +704,18 @@ int parse_gds_from_file(const char *filename, GList **library_list)
printf("\t\tAngle defined: %lf\n", current_s_reference->angle);
}
break;
case PATHTYPE:
if (current_graphics == NULL) {
GDS_WARN("Path type defined outside of path. Ignoring");
break;
}
if (current_graphics->gfx_type == GRAPHIC_PATH) {
current_graphics->path_render_type = (int)gds_convert_signed_int16(workbuff);
printf("\t\tPathtype: %d\n", current_graphics->path_render_type);
} else {
GDS_WARN("Path type defined inside non-path graphics object. Ignoring");
}
break;
}
@@ -629,10 +724,15 @@ int parse_gds_from_file(const char *filename, GList **library_list)
fclose(gds_file);
/* Iterate and find references to cells */
g_list_foreach(lib_list, scan_library_references, NULL);
if (!run) {
/* Iterate and find references to cells */
g_list_foreach(lib_list, scan_library_references, NULL);
}
*library_list = lib_list;
free(workbuff);
return run;
}
@@ -641,9 +741,21 @@ static void delete_cell_inst_element(struct gds_cell_instance *cell_inst)
free(cell_inst);
}
static void delete_vertex(struct gds_point *vertex)
{
free(vertex);
}
static void delete_graphics_obj(struct gds_graphics *gfx)
{
g_list_free_full(gfx->vertices, (GDestroyNotify)delete_vertex);
free(gfx);
}
static void delete_cell_element(struct gds_cell *cell)
{
g_list_free_full(cell->child_cells, (GDestroyNotify)delete_cell_inst_element);
g_list_free_full(cell->graphic_objs, (GDestroyNotify)delete_graphics_obj);
free(cell);
}
@@ -656,7 +768,8 @@ static void delete_library_element(struct gds_library *lib)
int clear_lib_list(GList **library_list)
{
if (*library_list == NULL) return 0;
if (*library_list == NULL)
return 0;
g_list_free_full(*library_list, (GDestroyNotify)delete_library_element);
*library_list = NULL;
return 0;

29
gds-parser/gds-parser.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* 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/>.
*/
#ifndef __GDSPARSE_H__
#define __GDSPARSE_H__
#include <glib.h>
#include "gds-types.h"
int parse_gds_from_file(const char *filename, GList **library_array);
int clear_lib_list(GList **library_list);
#endif /* __GDSPARSE_H__ */

61
gds-parser/gds-types.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef __GDS_TYPES_H__
#define __GDS_TYPES_H__
#include <stdint.h>
#include <glib.h>
#define CELL_NAME_MAX (100)
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1};
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2};
struct gds_time_field {
uint16_t year;
uint16_t month;
uint16_t day;
uint16_t hour;
uint16_t minute;
uint16_t second;
};
struct gds_point {
int x;
int y;
};
struct gds_graphics {
enum graphics_type gfx_type;
GList *vertices;
enum path_type path_render_type;
int width_absolute;
int16_t layer;
uint16_t datatype;
};
struct gds_cell_instance {
char ref_name[CELL_NAME_MAX];
struct gds_cell *cell_ref;
struct gds_point origin;
int flipped;
double angle;
double magnification;
};
struct gds_cell {
char name[CELL_NAME_MAX];
struct gds_time_field mod_time;
struct gds_time_field access_time;
GList *child_cells;
GList *graphic_objs;
};
struct gds_library {
char name[CELL_NAME_MAX];
struct gds_time_field mod_time;
struct gds_time_field access_time;
double unit_to_meters;
GList *cells;
GList *cell_names;
};
#endif /* __GDS_TYPES_H__ */

View File

@@ -1,81 +0,0 @@
/*
* 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 as published by
* the Free Software Foundation, either version 2 of the License.
*
* 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/>.
*/
#ifndef __GDSPARSE_H__
#define __GDSPARSE_H__
#include <stdint.h>
#include <glib.h>
#define CELL_NAME_MAX (100)
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1};
struct gds_time_field {
uint16_t year;
uint16_t month;
uint16_t day;
uint16_t hour;
uint16_t minute;
uint16_t second;
};
struct gds_point {
int x;
int y;
};
struct gds_graphics {
enum graphics_type type;
GList *vertices;
unsigned int path_width;
int width_absolute;
int16_t layer;
uint16_t datatype;
};
struct gds_cell_instance {
char ref_name[CELL_NAME_MAX];
struct gds_cell *cell_ref;
struct gds_point origin;
int flipped;
double angle;
double magnification;
};
struct gds_cell {
char name[CELL_NAME_MAX];
struct gds_time_field mod_time;
struct gds_time_field access_time;
GList *child_cells;
GList *graphic_objs;
};
struct gds_library {
char name[CELL_NAME_MAX];
struct gds_time_field time;
double unit_to_meters;
GList *cells;
GList *cell_names;
};
int parse_gds_from_file(const char *filename, GList **library_array);
int clear_lib_list(GList **library_list);
#endif /* __GDSPARSE_H__ */

10
glade/CMakeLists.txt Normal file
View File

@@ -0,0 +1,10 @@
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
add_custom_command(DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/resources.xml
${CMAKE_CURRENT_SOURCE_DIR}/main.glade
${CMAKE_CURRENT_SOURCE_DIR}/layer-widget.glade
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/resources.c
COMMAND
glib-compile-resources --target="${CMAKE_CURRENT_BINARY_DIR}/resources.c" --sourcedir="${CMAKE_CURRENT_SOURCE_DIR}" --generate-source "${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
)

View File

@@ -3,15 +3,33 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="upper">100</property>
<property name="value">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
<property name="upper">1</property>
<property name="value">1</property>
<property name="step_increment">0.01</property>
<property name="page_increment">0.10000000000000001</property>
</object>
<object class="GtkBox" id="box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">3</property>
<child>
<object class="GtkEventBox" id="event-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-justify-fill</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="layer">
<property name="visible">True</property>
@@ -19,9 +37,9 @@
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">True</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -29,27 +47,12 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_alpha">True</property>
<property name="title" translatable="yes">Select Layer Color and Opacity</property>
<property name="rgba">rgb(0,0,0)</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScale" id="opacity">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="restrict_to_fill_level">False</property>
<property name="fill_level">100</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
<property name="value_pos">right</property>
</object>
<packing>
<property name="expand">True</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
@@ -63,7 +66,7 @@
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>

View File

@@ -3,9 +3,9 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="main-window">
<property name="height_request">250</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="delete-event" handler="on_window_close" swapped="no"/>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="name">header</property>
@@ -15,57 +15,66 @@
<property name="subtitle" translatable="yes">GDSII to PDF Converter</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkBox">
<object class="GtkButton" id="button-load-gds">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button-load-gds">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-load-mapping">
<property name="label" translatable="yes">Load Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-save-mapping">
<property name="label" translatable="yes">Save Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="button-load-mapping">
<property name="label" translatable="yes">Load Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<style>
<class name="destructive-action"/>
</style>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-save-mapping">
<property name="label" translatable="yes">Save Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="convert-button">
<property name="label">gtk-convert</property>
<property name="name">button-convert</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
<child>
@@ -73,11 +82,19 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="cell-tree">
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="cell-tree">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
@@ -87,10 +104,24 @@
</packing>
</child>
<child>
<object class="GtkListBox" id="layer-list">
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkListBox" id="layer-list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
@@ -98,43 +129,6 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="button-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="convert-button">
<property name="label">gtk-convert</property>
<property name="name">button-convert</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>

9
glade/resources.xml Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/">
<file compressed="true">main.glade</file>
<file>layer-widget.glade</file>
</gresource>
</gresources>

232
latex-output/latex-output.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* 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/>.
*/
#include "latex-output.h"
#include <math.h>
#define WRITEOUT_BUFFER(buff) fwrite((buff)->str, sizeof(char), (buff)->len, tex_file)
static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString *buffer)
{
GList *list;
struct layer_info *lifo;
char *end_str;
for (list = layer_infos; list != NULL; list = list->next) {
lifo = (struct layer_info *)list->data;
g_string_printf(buffer, "\\pgfdeclarelayer{l%d}\n\\definecolor{c%d}{rgb}{%lf,%lf,%lf}\n",
lifo->layer, lifo->layer,
lifo->color.red, lifo->color.green, lifo->color.blue);
WRITEOUT_BUFFER(buffer);
}
g_string_printf(buffer, "\\pgfsetlayers{");
WRITEOUT_BUFFER(buffer);
for (list = layer_infos; list != NULL; list = list->next) {
lifo = (struct layer_info *)list->data;
if (list->next == NULL)
end_str = ",main}";
else
end_str = ",";
g_string_printf(buffer, "l%d%s", lifo->layer, end_str);
WRITEOUT_BUFFER(buffer);
}
fwrite("\n", sizeof(char), 1, tex_file);
}
/**
* @brief write_layer_env
* @param tex_file
* @param layer
* @param buffer
* @return TRUE if layer is placeable
*/
static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList *linfo, GString *buffer)
{
GList *temp;
struct layer_info *inf;
for (temp = linfo; temp != NULL; temp = temp->next) {
inf = (struct layer_info *)temp->data;
if (inf->layer == layer) {
color->alpha = inf->color.alpha;
color->red = inf->color.red;
color->green = inf->color.green;
color->blue = inf->color.blue;
g_string_printf(buffer, "\\begin{pgfonlayer}{l%d}\n\\ifcreatepdflayers\n\\begin{scope}[ocg={ref=%d, status=visible,name={%s}}]\n\\fi]\n",
layer, layer, inf->name);
WRITEOUT_BUFFER(buffer);
return TRUE;
}
}
return FALSE;
}
static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GString *buffer)
{
GList *temp;
GList *temp_vertex;
struct gds_graphics *gfx;
struct gds_point *pt;
GdkRGBA color;
static const char *line_caps[] = {"butt", "round", "rect"};
for (temp = graphics; temp != NULL; temp = temp->next) {
gfx = (struct gds_graphics *)temp->data;
if (write_layer_env(tex_file, &color, (int)gfx->layer, linfo, buffer) == TRUE) {
/* Layer is defined => create graphics */
if (gfx->gfx_type == GRAPHIC_POLYGON) {
g_string_printf(buffer, "\\draw[line width=0.00001 pt, draw={c%d}, fill={c%d}, fill opacity={%lf}] ",
gfx->layer, gfx->layer, color.alpha);
WRITEOUT_BUFFER(buffer);
/* Append vertices */
for (temp_vertex = gfx->vertices; temp_vertex != NULL; temp_vertex = temp_vertex->next) {
pt = (struct gds_point *)temp_vertex->data;
g_string_printf(buffer, "(%lf pt, %lf pt) -- ", ((double)pt->x)/1000.0, ((double)pt->y)/1000.0);
WRITEOUT_BUFFER(buffer);
}
g_string_printf(buffer, "cycle;\n");
WRITEOUT_BUFFER(buffer);
} else if(gfx->gfx_type == GRAPHIC_PATH) {
if (g_list_length(gfx->vertices) < 2) {
printf("Cannot write path with less than 2 points\n");
break;
}
if (gfx->path_render_type < 0 || gfx->path_render_type > 2) {
printf("Path type unrecognized. Setting to 'flushed'\n");
gfx->path_render_type = 0;
}
g_string_printf(buffer, "\\draw[line width=%lf pt, draw={c%d}, opacity={%lf}, cap=%s] ",
gfx->width_absolute/1000.0, gfx->layer, color.alpha,
line_caps[gfx->path_render_type]);
WRITEOUT_BUFFER(buffer);
/* Append vertices */
for (temp_vertex = gfx->vertices; temp_vertex != NULL; temp_vertex = temp_vertex->next) {
pt = (struct gds_point *)temp_vertex->data;
g_string_printf(buffer, "(%lf pt, %lf pt)%s",
((double)pt->x)/1000.0,
((double)pt->y)/1000.0,
(temp_vertex->next ? " -- " : ""));
WRITEOUT_BUFFER(buffer);
}
g_string_printf(buffer, ";\n");
WRITEOUT_BUFFER(buffer);
}
g_string_printf(buffer, "\\ifcreatepdflayers\n\\end{scope}\n\\fi\n\\end{pgfonlayer}\n");
WRITEOUT_BUFFER(buffer);
}
} /* For graphics */
}
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer)
{
GList *list_child;
struct gds_cell_instance *inst;
/* Draw polygons of current cell */
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer);
/* Draw polygons of childs */
for (list_child = cell->child_cells; list_child != NULL; list_child = list_child->next) {
inst = (struct gds_cell_instance *)list_child->data;
/* generate translation scope */
g_string_printf(buffer, "\\begin{scope}[shift={(%lf pt,%lf pt)}]\n",
((double)inst->origin.x)/1000.0,((double)inst->origin.y)/1000.0);
WRITEOUT_BUFFER(buffer);
g_string_printf(buffer, "\\begin{scope}[rotate=%lf]\n", inst->angle);
WRITEOUT_BUFFER(buffer);
g_string_printf(buffer, "\\begin{scope}[yscale=%s]\n", (inst->flipped ? "-1" : "1"));
WRITEOUT_BUFFER(buffer);
if (inst->cell_ref)
render_cell(inst->cell_ref, layer_infos, tex_file, buffer);
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
}
}
void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file)
{
GString *working_line;
if (!tex_file || !layer_infos || !cell)
return;
/* 10 kB Line working buffer should be enough */
working_line = g_string_new_len(NULL, LATEX_LINE_BUFFER_KB*1024);
/* standalone foo */
g_string_printf(working_line, "\\newif\\iftestmode\n\\testmodefalse %% Change to true for standalone rendering\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\newif\\ifcreatepdflayers\n\\createpdflayersfalse %% Change to true for Embedded layers in PDF output\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\iftestmode\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\documentclass[tikz]{standalone}\n\\usepackage{xcolor}\n\\usetikzlibrary{ocgx}\n\\begin{document}\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\fi\n");
WRITEOUT_BUFFER(working_line);
/* Write layer definitions */
write_layer_definitions(tex_file, layer_infos, working_line);
/* Open tikz Pictute */
g_string_printf(working_line, "\\begin{tikzpicture}\n");
WRITEOUT_BUFFER(working_line);
/* Generate graphics output */
render_cell(cell, layer_infos, tex_file, working_line);
g_string_printf(working_line, "\\end{tikzpicture}\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\iftestmode\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\end{document}\n");
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\fi\n");
WRITEOUT_BUFFER(working_line);
fflush(tex_file);
g_string_free(working_line, TRUE);
}

View File

@@ -0,0 +1,32 @@
/*
* 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/>.
*/
#ifndef __LATEX_OUTPUT_H__
#define __LATEX_OUTPUT_H__
#include "../gds-parser/gds-types.h"
#include <glib.h>
#include <stdio.h>
#include "../layer-selector.h"
#define LATEX_LINE_BUFFER_KB (10)
void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file);
#endif /* __LATEX_OUTPUT_H__ */

View File

@@ -1,122 +0,0 @@
/*
* 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 as published by
* the Free Software Foundation, either version 2 of the License.
*
* 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/>.
*/
#include "layer-element.h"
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_BOX)
static void layer_element_dispose(GObject *obj)
{
/* destroy parent container. This destroys all widgets inside */
G_OBJECT_CLASS(layer_element_parent_class)->dispose(obj);
}
static void layer_element_class_init(LayerElementClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->dispose = layer_element_dispose;
return;
}
static void layer_element_init(LayerElement *self)
{
GtkBuilder *builder;
GtkWidget *glade_box;
builder = gtk_builder_new_from_file("glade/layer-widget.glade");
glade_box = GTK_WIDGET(gtk_builder_get_object(builder, "box"));
gtk_box_pack_start(GTK_BOX(self), glade_box, TRUE, TRUE, 0);
/* Get Elements */
self->priv.color = GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "color"));
self->priv.export = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "export"));
self->priv.layer = GTK_LABEL(gtk_builder_get_object(builder, "layer"));
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
self->priv.opacity = GTK_SCALE(gtk_builder_get_object(builder, "opacity"));
/* Connect signals */
/* None */
g_object_unref(builder);
}
GtkWidget *layer_element_new(void)
{
return GTK_WIDGET(g_object_new(layer_element_get_type(), NULL));
}
const char *layer_element_get_name(LayerElement *elem)
{
return gtk_entry_get_text(elem->priv.name);
}
void layer_element_set_name(LayerElement *elem, const char* name)
{
gtk_entry_set_text(elem->priv.name, name);
}
void layer_element_set_layer(LayerElement *elem, int layer)
{
GString *string;
string = g_string_new_len(NULL, 100);
g_string_printf(string, "Layer: %d", layer);
gtk_label_set_text(elem->priv.layer, (const gchar *)string->str);
elem->priv.layer_num = layer;
g_string_free(string, TRUE);
}
int layer_element_get_layer(LayerElement *elem)
{
return elem->priv.layer_num;
}
void layer_element_set_opacity(LayerElement *elem, int opacity)
{
if (opacity > 100 || opacity < 0)
return;
gtk_range_set_value(GTK_RANGE(elem->priv.opacity), (gdouble)opacity);
}
int layer_element_get_opacity(LayerElement *elem)
{
return (int)gtk_range_get_value(GTK_RANGE(elem->priv.opacity));
}
void layer_element_set_export(LayerElement *elem, gboolean export)
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->priv.export), export);
}
gboolean layer_element_get_export(LayerElement *elem)
{
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->priv.export));
}
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
{
if (!rgba)
return;
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
{
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}

View File

@@ -1,61 +1,112 @@
/*
* 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/>.
*/
#include "layer-selector.h"
#include "gdsparse.h"
#include "gds-parser/gds-parser.h"
#include "layer-widget/layer-element.h"
#include <glib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static GtkWidget *global_load_button;
static GtkWidget *global_save_button;
static GtkListBox *global_list_box;
static void layer_list_remove_element(struct layer_info *inf)
void delete_layer_info_struct(struct layer_info *info)
{
if (inf)
free(inf);
if (info)
free(info);
}
void get_layer_info(GList **info_list, GtkListBox *box)
/**
* @brief export_rendered_layer_info
* @return new list with all info elements needed to render cells
*/
GList *export_rendered_layer_info()
{
GList *local_list = NULL;
GList *info_list = NULL;
LayerElement *le;
struct layer_info *linfo;
GList *row_list;
GList *temp;
int i;
/* Clear info Glist */
if (*info_list != NULL) {
g_list_free_full(*info_list, (GDestroyNotify)layer_list_remove_element);
*info_list = NULL;
row_list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
/* Iterate through widgets and add layers that shall be exported */
for (i = 0, temp = row_list; temp != NULL; temp = temp->next, i++) {
le = LAYER_ELEMENT(temp->data);
if (layer_element_get_export(le) == TRUE) {
/* Allocate new info and fill with info */
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
layer_element_get_color(le, &linfo->color);
linfo->layer = layer_element_get_layer(le);
linfo->stacked_position = i;
linfo->name = (char *)layer_element_get_name(le);
/* Append to list */
info_list = g_list_append(info_list, (gpointer)linfo);
}
}
*info_list = local_list;
}
static GList *layer_widgets = NULL;
static void delete_layer_widget(GtkWidget *widget)
{
gtk_widget_destroy(widget);
return info_list;
}
void clear_list_box_widgets(GtkListBox *box)
{
GList *list;
GList *temp;
list = gtk_container_get_children(GTK_CONTAINER(box));
for (;list != NULL; list = list->next) {
gtk_container_remove(GTK_CONTAINER(box), GTK_WIDGET(list->data));
for (temp = list; temp != NULL; temp = temp->next) {
gtk_container_remove(GTK_CONTAINER(box), GTK_WIDGET(temp->data));
}
/* Widgets are already destroyed when removed from box */
g_list_free(layer_widgets);
layer_widgets = NULL;
/* Widgets are already destroyed when removed from box because they are only referenced inside the container */
g_list_free(list);
/* Deactivate buttons */
gtk_widget_set_sensitive(global_load_button, FALSE);
gtk_widget_set_sensitive(global_save_button, FALSE);
}
static gboolean check_if_layer_widget_exists(int layer) {
GList *list;
GList *temp;
LayerElement *widget;
gboolean ret = FALSE;
for (list = layer_widgets; list != NULL; list = list->next) {
widget = (LayerElement *)list->data;
list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
for (temp = list; temp != NULL; temp = temp->next) {
widget = LAYER_ELEMENT(temp->data);
if (layer_element_get_layer(widget) == layer) {
ret = TRUE;
break;
}
}
g_list_free(list);
return ret;
}
@@ -74,29 +125,20 @@ static void analyze_cell_layers(GtkListBox *listbox, struct gds_cell *cell)
layer_element_set_layer(LAYER_ELEMENT(le), layer);
gtk_list_box_insert(listbox, le, -1);
gtk_widget_show(le);
layer_widgets = g_list_append(layer_widgets, le);
printf("added new layer\n");
}
}
}
gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
{
GList *children1, *children2;
LayerElement *le1, *le2;
gint ret;
children1 = gtk_container_get_children(GTK_CONTAINER(row1));
children2 = gtk_container_get_children(GTK_CONTAINER(row2));
le1 = LAYER_ELEMENT(children1->data);
le2 = LAYER_ELEMENT(children2->data);
le1 = LAYER_ELEMENT(row1);
le2 = LAYER_ELEMENT(row2);
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
g_list_free(children1);
g_list_free(children2);
return ret;
}
@@ -104,11 +146,11 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
{
GList *cell_list = NULL;
struct gds_library *lib;
printf("foo?\n");
clear_list_box_widgets(listbox);
global_list_box = listbox;
clear_list_box_widgets(listbox);
gtk_list_box_set_sort_func(listbox, sort_func, NULL, NULL);
printf("layers deleted\n");
for (; libs != NULL; libs = libs->next) {
lib = (struct gds_library *)libs->data;
@@ -119,4 +161,276 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
/* Force sort */
gtk_list_box_invalidate_sort(listbox);
/* Disable sort, so user can sort layers */
gtk_list_box_set_sort_func(listbox, NULL, NULL, NULL);
/* Activate Buttons */
gtk_widget_set_sensitive(global_load_button, TRUE);
gtk_widget_set_sensitive(global_save_button, TRUE);
}
/**
* @brief load_csv_line
* @param file
* @param export
* @param name
* @param layer
* @param color
* @param opacity
* @return 0 if succesfull, 1 if line was malformatted or parameters are broken, -1 if file end
*/
static int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
{
int ret;
gsize len;
gchar *line;
GRegex *regex;
GMatchInfo *mi;
char *match;
if ((!export) || (!name) || (!layer) || (!color)) {
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");
*layer = (int)g_ascii_strtoll(match, NULL, 10);
g_free(match);
match = g_match_info_fetch_named(mi, "r");
color->red = g_ascii_strtod(match, NULL);
g_free(match);
match = g_match_info_fetch_named(mi, "g");
color->green = g_ascii_strtod(match, NULL);
g_free(match);
match = g_match_info_fetch_named(mi, "b");
color->blue = g_ascii_strtod(match, NULL);
g_free(match);
match = g_match_info_fetch_named(mi, "a");
color->alpha = g_ascii_strtod(match, NULL);
g_free(match);
match = g_match_info_fetch_named(mi, "export");
*export = ((!strcmp(match, "1")) ? TRUE : FALSE);
g_free(match);
match = g_match_info_fetch_named(mi, "name");
*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;
}
static LayerElement *find_layer_element_in_list(GList *el_list, int layer)
{
LayerElement *ret = NULL;
for (; el_list != NULL; el_list = el_list->next) {
if (layer_element_get_layer(LAYER_ELEMENT(el_list->data)) == layer) {
ret = LAYER_ELEMENT(el_list->data);
break;
}
}
return ret;
}
static void load_layer_mapping_from_file(gchar *file_name)
{
GFile *file;
GFileInputStream *stream;
GDataInputStream *dstream;
LayerElement *le;
char *name;
gboolean export;
int layer;
GdkRGBA color;
int result;
GList *rows;
GList *temp;
file = g_file_new_for_path(file_name);
stream = g_file_read(file, NULL, NULL);
if (!stream)
goto destroy_file;
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
rows = gtk_container_get_children(GTK_CONTAINER(global_list_box));
/* Reference and remove all rows from box */
for (temp = rows; temp != NULL; temp = temp->next) {
le = LAYER_ELEMENT(temp->data);
/* Referencing protets the widget from being deleted when removed */
g_object_ref(G_OBJECT(le));
gtk_container_remove(GTK_CONTAINER(global_list_box), GTK_WIDGET(le));
}
while((result = load_csv_line(dstream, &export, &name, &layer, &color)) >= 0) {
/* skip broken line */
if (result == 1)
continue;
/* Add rows in the same order as in file */
if ((le = find_layer_element_in_list(rows, layer))) {
gtk_list_box_insert(global_list_box, GTK_WIDGET(le), -1);
layer_element_set_color(le, &color);
layer_element_set_export(le, export);
layer_element_set_name(le, name);
g_free(name);
/* Dereference and remove from list */
g_object_unref(G_OBJECT(le));
rows = g_list_remove(rows, le);
}
}
/* Add remaining elements */
for (temp = rows; temp != NULL; temp = temp->next) {
le = LAYER_ELEMENT(temp->data);
/* Referencing protets the widget from being deleted when removed */
gtk_list_box_insert(global_list_box, GTK_WIDGET(le), -1);
g_object_unref(G_OBJECT(le));
}
/* Delete list */
g_list_free(rows);
/* read line */
g_object_unref(dstream);
g_object_unref(stream);
destroy_file:
g_object_unref(file);
}
static void load_mapping_clicked(GtkWidget *button, gpointer user_data)
{
GtkWidget *dialog;
gint res;
gchar *file_name;
dialog = gtk_file_chooser_dialog_new("Load Mapping File", GTK_WINDOW(user_data), GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL, "Load Mapping", GTK_RESPONSE_ACCEPT, NULL);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
load_layer_mapping_from_file(file_name);
g_free(file_name);
}
gtk_widget_destroy(dialog);
}
static void create_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
{
GString *string;
gboolean export;
const gchar *name;
int layer;
GdkRGBA color;
string = g_string_new_len(NULL, max_len-1);
/* Extract values */
export = layer_element_get_export(layer_element);
name = (const gchar*)layer_element_get_name(layer_element);
layer = layer_element_get_layer(layer_element);
layer_element_get_color(layer_element, &color);
/* print values to line */
g_string_printf(string, "%d,%lf,%lf,%lf,%lf,%d,%s\n",
layer, color.red, color.green,
color.blue, color.alpha, (export == TRUE ? 1 : 0), name);
if (string->len > (max_len-1)) {
printf("Layer Definition too long. Please shorten Layer Name!!\n");
line_buffer[0] = 0x0;
return;
}
/* copy max_len bytes of string */
strncpy(line_buffer, (char *)string->str, max_len-1);
line_buffer[max_len-1] = 0;
/* Completely remove string */
g_string_free(string, TRUE);
}
static void save_layer_mapping_data(const gchar *file_name, GtkListBox *list_box)
{
FILE *file;
char workbuff[512];
GList *le_list;
GList *temp;
/* Overwrite existing file */
file = fopen((const char *)file_name, "w");
le_list = gtk_container_get_children(GTK_CONTAINER(list_box));
/* File format is CSV: <Layer>,<target_pos>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
for (temp = le_list; temp != NULL; temp = temp->next) {
/* To be sure it is a valid string */
workbuff[0] = 0;
create_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
}
g_list_free(le_list);
/* Save File */
fflush(file);
fclose(file);
}
static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
{
GtkWidget *dialog;
gint res;
gchar *file_name;
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(user_data), GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "Save Mapping", GTK_RESPONSE_ACCEPT, NULL);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
save_layer_mapping_data(file_name, global_list_box);
g_free(file_name);
}
gtk_widget_destroy(dialog);
}
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window)
{
g_object_ref(G_OBJECT(button));
global_load_button = button;
g_signal_connect(button, "clicked", G_CALLBACK(load_mapping_clicked), main_window);
}
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window)
{
g_object_ref(G_OBJECT(button));
global_save_button = button;
g_signal_connect(button, "clicked", G_CALLBACK(save_mapping_clicked), main_window);
}

View File

@@ -1,23 +1,40 @@
/*
* 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/>.
*/
#ifndef __LAYER_SELECTOR_H__
#define __LAYER_SELECTOR_H__
#include <gtk/gtk.h>
#include <glib.h>
#include "layer-element.h"
struct layer_info {
int id;
/* This contains both: opacity and Color */
GdkRGBA color;
struct layer_info
{
int layer;
char *name;
int stacked_position; ///< Lower is bottom, higher is top
GdkRGBA color;
};
void generate_layer_widgets(GtkListBox *listbox, GList *libs);
void clear_list_box_widgets();
void setup_load_mapping_callback(GtkWidget *button);
void setup_save_mapping_callback(GtkWidget *button);
void get_layer_info(GList **info_list, GtkListBox *box);
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window);
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
GList *export_rendered_layer_info();
void delete_layer_info_struct(struct layer_info *info);
#endif /* __LAYER_SELECTOR_H__ */

View File

@@ -0,0 +1,189 @@
/*
* 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/>.
*/
#include "layer-element.h"
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
static void layer_element_dispose(GObject *obj)
{
/* destroy parent container. This destroys all widgets inside */
G_OBJECT_CLASS(layer_element_parent_class)->dispose(obj);
}
static void layer_element_constructed(GObject *obj)
{
G_OBJECT_CLASS(layer_element_parent_class)->constructed(obj);
}
static void layer_element_class_init(LayerElementClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->dispose = layer_element_dispose;
oclass->constructed = layer_element_constructed;
}
static GtkTargetEntry entries[] = {
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
};
static void layer_element_drag_begin(GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
GtkWidget *row;
GtkAllocation alloc;
cairo_surface_t *surface;
cairo_t *cr;
int x, y;
row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
gtk_widget_get_allocation (row, &alloc);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
cr = cairo_create (surface);
gtk_style_context_add_class (gtk_widget_get_style_context (row), "drag-icon");
gtk_widget_draw (row, cr);
gtk_style_context_remove_class (gtk_widget_get_style_context (row), "drag-icon");
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
cairo_surface_set_device_offset (surface, -x, -y);
gtk_drag_set_icon_surface (context, surface);
cairo_destroy (cr);
cairo_surface_destroy (surface);
}
static void layer_element_drag_data_get(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
gtk_selection_data_set(selection_data, gdk_atom_intern_static_string("GTK_LIST_BOX_ROW"),
32, (const guchar *)&widget, sizeof(gpointer));
}
static void layer_element_drag_data_received(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint32 time,
gpointer data)
{
GtkWidget *target;
GtkWidget *row;
GtkWidget *source;
int pos;
target = widget;
pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (target));
row = (gpointer) *(gpointer *)gtk_selection_data_get_data (selection_data);
source = gtk_widget_get_ancestor (row, GTK_TYPE_LIST_BOX_ROW);
if (source == target)
return;
g_object_ref (source);
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (source)), source);
gtk_list_box_insert (GTK_LIST_BOX (gtk_widget_get_parent (target)), source, pos);
g_object_unref (source);
}
static void layer_element_init(LayerElement *self)
{
GtkBuilder *builder;
GtkWidget *glade_box;
builder = gtk_builder_new_from_resource("/layer-widget.glade");
glade_box = GTK_WIDGET(gtk_builder_get_object(builder, "box"));
gtk_container_add(GTK_CONTAINER(self), glade_box);
/* Get Elements */
self->priv.color = GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "color"));
self->priv.export = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "export"));
self->priv.layer = GTK_LABEL(gtk_builder_get_object(builder, "layer"));
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
/* Setup drag and drop */
gtk_drag_source_set(GTK_WIDGET(self->priv.event_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
g_signal_connect(self->priv.event_handle, "drag-begin", G_CALLBACK(layer_element_drag_begin), NULL);
g_signal_connect(self->priv.event_handle, "drag-data-get", G_CALLBACK(layer_element_drag_data_get), NULL);
gtk_drag_dest_set(GTK_WIDGET(self), GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_MOVE);
g_signal_connect(GTK_WIDGET(self), "drag-data-received", G_CALLBACK(layer_element_drag_data_received), NULL);
g_object_unref(builder);
}
GtkWidget *layer_element_new(void)
{
return GTK_WIDGET(g_object_new(TYPE_LAYER_ELEMENT, NULL));
}
const char *layer_element_get_name(LayerElement *elem)
{
return gtk_entry_get_text(elem->priv.name);
}
void layer_element_set_name(LayerElement *elem, const char* name)
{
gtk_entry_set_text(elem->priv.name, name);
}
void layer_element_set_layer(LayerElement *elem, int layer)
{
GString *string;
string = g_string_new_len(NULL, 100);
g_string_printf(string, "Layer: %d", layer);
gtk_label_set_text(elem->priv.layer, (const gchar *)string->str);
elem->priv.layer_num = layer;
g_string_free(string, TRUE);
}
int layer_element_get_layer(LayerElement *elem)
{
return elem->priv.layer_num;
}
void layer_element_set_export(LayerElement *elem, gboolean export)
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->priv.export), export);
}
gboolean layer_element_get_export(LayerElement *elem)
{
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->priv.export));
}
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
{
if (!rgba)
return;
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
{
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}

View File

@@ -5,8 +5,8 @@
* 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 as published by
* the Free Software Foundation, either version 2 of the License.
* 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
@@ -21,45 +21,41 @@
#define __LAYER_ELEMENT_H__
#include <gtk/gtk.h>
// #include <gdk/gdk.h>
#define LAYER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, layer_element_get_type(), LayerElement)
#define LAYER_ELEMENT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, layer_element_get_type(), LayerElementClass)
#define IS_LAYE_RELEMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, layer_element_get_type())
G_BEGIN_DECLS
/* Creates Class structure etc */
G_DECLARE_FINAL_TYPE(LayerElement, layer_element, LAYER, ELEMENT, GtkListBoxRow)
#define TYPE_LAYER_ELEMENT (layer_element_get_type())
typedef struct _LayerElementPriv {
GtkEntry *name;
GtkLabel *layer;
int layer_num;
GtkEventBox *event_handle;
GtkColorButton *color;
GtkScale *opacity;
GtkCheckButton *export;
} LayerElementPriv;
typedef struct _LayerElement {
/* Inheritance */
GtkBox hbox;
GtkListBoxRow parent;
/* Custom Elements */
LayerElementPriv priv;
} LayerElement;
typedef struct _LayerElementClass {
GtkBoxClass parent_class;
} LayerElementClass;
GType layer_element_get_type(void);
GtkWidget *layer_element_new(void);
const char *layer_element_get_name(LayerElement *elem);
void layer_element_set_name(LayerElement *elem, const char* name);
void layer_element_set_layer(LayerElement *elem, int layer);
int layer_element_get_layer(LayerElement *elem);
void layer_element_set_opacity(LayerElement *elem, int opacity);
int layer_element_get_opacity(LayerElement *elem);
void layer_element_set_export(LayerElement *elem, gboolean export);
gboolean layer_element_get_export(LayerElement *elem);
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba);
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
G_END_DECLS
#endif /* __LAYER_ELEMENT_H__ */

169
main.c
View File

@@ -5,8 +5,8 @@
* 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 as published by
* the Free Software Foundation, either version 2 of the License.
* 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
@@ -18,18 +18,12 @@
*/
#include <stdio.h>
#include "gdsparse.h"
#include "gds-parser/gds-parser.h"
#include <gtk/gtk.h>
#include "layer-element.h"
#include "layer-widget/layer-element.h"
#include "layer-selector.h"
enum cell_store_columns {
LIBRARY,
CELL,
STORE_COLUMN
};
#include "tree-renderer/tree-store.h"
#include "latex-output/latex-output.h"
struct open_button_data {
GtkWindow *main_window;
@@ -38,8 +32,10 @@ struct open_button_data {
GtkListBox *layer_box;
};
struct convert_button_data {
GtkTreeView *tree_view;
GtkWindow *main_window;
};
gboolean on_window_close(gpointer window, gpointer user)
{
@@ -48,7 +44,19 @@ gboolean on_window_close(gpointer window, gpointer user)
return TRUE;
}
static GString *generate_string_from_date(struct gds_time_field *date)
{
GString *str;
str = g_string_new_len(NULL, 50);
g_string_printf(str, "%02u.%02u.%u - %02u:%02u",
(unsigned int)date->day,
(unsigned int)date->month,
(unsigned int)date->year,
(unsigned int)date->hour,
(unsigned int)date->minute);
return str;
}
void on_load_gds(gpointer button, gpointer user)
{
@@ -67,6 +75,8 @@ void on_load_gds(gpointer button, gpointer user)
gint dialog_result;
int gds_result;
char *filename;
GString *mod_date;
GString *acc_date;
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", ptr->main_window, GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL, "Open GDSII", GTK_RESPONSE_ACCEPT, NULL);
@@ -103,11 +113,40 @@ void on_load_gds(gpointer button, gpointer user)
gds_lib = (struct gds_library *)lib->data;
/* Create top level iter */
gtk_tree_store_append (store, &libiter, NULL);
gtk_tree_store_set (store, &libiter, LIBRARY, gds_lib->name, -1);
/* Convert dates to String */
mod_date = generate_string_from_date(&gds_lib->mod_time);
acc_date = generate_string_from_date(&gds_lib->access_time);
gtk_tree_store_set (store, &libiter,
CELL_SEL_LIBRARY, gds_lib,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
-1);
/* Delete GStrings including string data. */
/* Cell store copies String type data items */
g_string_free(mod_date, TRUE);
g_string_free(acc_date, TRUE);
for (cell = gds_lib->cells; cell != NULL; cell = cell->next) {
gds_c = (struct gds_cell *)cell->data;
gtk_tree_store_append (store, &celliter, &libiter);
gtk_tree_store_set (store, &celliter, CELL, gds_c->name, -1);
/* Convert dates to String */
mod_date = generate_string_from_date(&gds_c->mod_time);
acc_date = generate_string_from_date(&gds_c->access_time);
gtk_tree_store_set (store, &celliter,
CELL_SEL_CELL, gds_c,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
-1);
/* Delete GStrings including string data. */
/* Cell store copies String type data items */
g_string_free(mod_date, TRUE);
g_string_free(acc_date, TRUE);
}
}
@@ -116,32 +155,67 @@ void on_load_gds(gpointer button, gpointer user)
}
end_destroy:
/* Destroy dialog and filter */
gtk_widget_destroy(open_dialog);
}
void on_convert_clicked(gpointer button, gpointer user)
static void on_convert_clicked(gpointer button, gpointer user)
{
printf("convert\n");
struct convert_button_data *data = (struct convert_button_data *)user;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
GList *layer_list;
struct gds_cell *cell_to_render;
FILE *tex_file;
GtkWidget *dialog;
gint res;
char *file_name;
/* Get selected cell */
selection = gtk_tree_view_get_selection(data->tree_view);
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
return;
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell_to_render, -1);
if (!cell_to_render)
return;
/* Get layers that are rendered */
layer_list = export_rendered_layer_info();
/* save file dialog */
dialog = gtk_file_chooser_dialog_new("Save TeX File", GTK_WINDOW(data->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
tex_file = fopen(file_name, "w");
g_free(file_name);
gtk_widget_destroy(dialog);
render_cell_to_code(cell_to_render, layer_list, tex_file);
fclose(tex_file);
} else {
gtk_widget_destroy(dialog);
}
g_list_free_full(layer_list, (GDestroyNotify)delete_layer_info_struct);
}
static GtkTreeStore * setup_cell_selector(GtkTreeView* view)
/* This function activates/deactivates the convert button depending on whether
* a cell is selected for conversion or not */
static void cell_selection_changed(GtkTreeSelection *sel, GtkWidget *convert_button)
{
GtkTreeStore *cell_store;
GtkTreeModel *model = NULL;
GtkTreeIter iter;
GtkCellRenderer *render;
GtkTreeViewColumn *column;
cell_store = gtk_tree_store_new(STORE_COLUMN, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_view_set_model(view, GTK_TREE_MODEL(cell_store));
render = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Library", render, "text", LIBRARY, NULL);
gtk_tree_view_append_column(view, column);
column = gtk_tree_view_column_new_with_attributes("Cell", render, "text", CELL, NULL);
gtk_tree_view_append_column(view, column);
return cell_store;
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
/* Node selected. Show button */
gtk_widget_set_sensitive(convert_button, TRUE);
} else {
gtk_widget_set_sensitive(convert_button, FALSE);
}
}
int main(int argc, char **argv)
@@ -150,15 +224,15 @@ int main(int argc, char **argv)
GList *gds_libs = NULL;
GtkTreeView *cell_tree;
GtkTreeStore *cell_store;
GtkWidget *widget_generic;
GtkWidget *layer;
GtkWidget *conv_button;
GtkWidget *listbox;
struct open_button_data open_data;
struct convert_button_data conv_data;
gtk_init(&argc, &argv);
main_builder = gtk_builder_new_from_file("glade/main.glade");
main_builder = gtk_builder_new_from_resource("/main.glade");
gtk_builder_connect_signals(main_builder, NULL);
@@ -172,16 +246,31 @@ int main(int argc, char **argv)
open_data.main_window = GTK_WINDOW(gtk_builder_get_object(main_builder, "main-window"));
g_signal_connect(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds")),
"clicked", G_CALLBACK(on_load_gds), (gpointer)&open_data);
/* Connect delete-event */
g_signal_connect(GTK_WIDGET(open_data.main_window), "delete-event", G_CALLBACK(on_window_close), NULL);
/* Connect Convert button */
widget_generic = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
g_signal_connect(widget_generic, "clicked", G_CALLBACK(on_convert_clicked), layer);
conv_data.tree_view = cell_tree;
conv_data.main_window = open_data.main_window;
conv_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
g_signal_connect(conv_button, "clicked", G_CALLBACK(on_convert_clicked), &conv_data);
/* test widget list */
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
open_data.layer_box = GTK_LIST_BOX(listbox);
/* Set buttons fpr layer mapping GUI */
setup_load_mapping_callback(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping")),
open_data.main_window);
setup_save_mapping_callback(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping")),
open_data.main_window);
/* Callback for selection change of cell selector */
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(cell_tree)), "changed",
G_CALLBACK(cell_selection_changed), conv_button);
gtk_main();
return 0;

2
test-data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.log
*.aux

View File

@@ -0,0 +1,2 @@
2,0.203922,0.396078,0.643137,1.000000,1,BOTTOM-Layer
1,0.450980,0.823529,0.086275,1.000000,1,TOP-Layer

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,56 @@
\newif\iftestmode
\testmodetrue % Change to true for standalone rendering
\newif\ifcreatepdflayers
\createpdflayerstrue % Change to true for Embedded layers in PDF output
\iftestmode
\documentclass[tikz]{standalone}
\usepackage{xcolor}
\usetikzlibrary{ocgx}
\begin{document}
\fi
\pgfdeclarelayer{l2}
\definecolor{c2}{rgb}{0.203922,0.396078,0.643137}
\pgfdeclarelayer{l1}
\definecolor{c1}{rgb}{0.450980,0.823529,0.086275}
\pgfsetlayers{l2,l1,main}
\begin{tikzpicture}
\begin{pgfonlayer}{l1}
\ifcreatepdflayers
\begin{scope}[ocg={ref=1, status=visible,name={TOP-Layer}}]
\fi]
\draw[line width=0.300000 pt, draw={c1}, opacity={1.000000}, cap=rect] (-1.108000 pt, 0.589000 pt) -- (-0.498000 pt, 0.589000 pt) -- (-0.255000 pt, 0.343000 pt);
\ifcreatepdflayers
\end{scope}
\fi
\end{pgfonlayer}
\begin{pgfonlayer}{l1}
\ifcreatepdflayers
\begin{scope}[ocg={ref=1, status=visible,name={TOP-Layer}}]
\fi]
\draw[line width=0.300000 pt, draw={c1}, opacity={1.000000}, cap=butt] (-1.031000 pt, 0.326000 pt) -- (-1.028000 pt, 0.093000 pt) -- (-0.282000 pt, -0.019000 pt);
\ifcreatepdflayers
\end{scope}
\fi
\end{pgfonlayer}
\begin{pgfonlayer}{l1}
\ifcreatepdflayers
\begin{scope}[ocg={ref=1, status=visible,name={TOP-Layer}}]
\fi]
\draw[line width=0.300000 pt, draw={c1}, opacity={1.000000}, cap=round] (0.076000 pt, 0.059000 pt) -- (0.660000 pt, 0.027000 pt) -- (0.871000 pt, 0.599000 pt);
\ifcreatepdflayers
\end{scope}
\fi
\end{pgfonlayer}
\begin{pgfonlayer}{l2}
\ifcreatepdflayers
\begin{scope}[ocg={ref=2, status=visible,name={BOTTOM-Layer}}]
\fi]
\draw[line width=0.00001 pt, draw={c2}, fill={c2}, fill opacity={1.000000}] (-1.264000 pt, -0.471000 pt) -- (-1.264000 pt, 0.768000 pt) -- (1.047000 pt, 0.768000 pt) -- (1.047000 pt, -0.471000 pt) -- (-1.264000 pt, -0.471000 pt) -- cycle;
\ifcreatepdflayers
\end{scope}
\fi
\end{pgfonlayer}
\end{tikzpicture}
\iftestmode
\end{document}
\fi

View File

@@ -0,0 +1,2 @@
2,0.203922,0.396078,0.643137,1.000000,1,BOTTOM-Layer
1,0.450980,0.823529,0.086275,1.000000,1,TOP-Layer

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,99 @@
/*
* 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/>.
*/
#include "lib-cell-renderer.h"
#include "../gds-parser/gds-types.h"
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
enum {
PROP_LIB = 1,
PROP_CELL,
PROP_COUNT
};
void lib_cell_renderer_init(LibCellRenderer *self)
{
/* Nothing to do */
}
static void lib_cell_renderer_constructed(GObject *obj)
{
G_OBJECT_CLASS(lib_cell_renderer_parent_class)->constructed(obj);
}
static void lib_cell_renderer_set_property(GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
GValue val = G_VALUE_INIT;
g_value_init(&val, G_TYPE_STRING);
switch (param_id) {
case PROP_LIB:
g_value_set_string(&val, ((struct gds_library *)g_value_get_pointer(value))->name);
g_object_set_property(object, "text", &val);
break;
case PROP_CELL:
g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name);
g_object_set_property(object, "text", &val);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static void lib_cell_renderer_get_property(GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
switch (param_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static GParamSpec *properties [PROP_COUNT];
void lib_cell_renderer_class_init(LibCellRendererClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->constructed = lib_cell_renderer_constructed;
oclass->set_property = lib_cell_renderer_set_property;
oclass->get_property = lib_cell_renderer_get_property;
properties[PROP_LIB] = g_param_spec_pointer("gds-lib", "gds-lib",
"Library reference to be displayed",
G_PARAM_WRITABLE);
properties[PROP_CELL] = g_param_spec_pointer("gds-cell", "gds-cell",
"Cell reference to be displayed",
G_PARAM_WRITABLE);
g_object_class_install_properties(oclass, PROP_COUNT, properties);
}
GtkCellRenderer *lib_cell_renderer_new()
{
return GTK_CELL_RENDERER(g_object_new(TYPE_LIB_CELL_RENDERER, NULL));
}

View File

@@ -0,0 +1,41 @@
/*
* 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/>.
*/
#ifndef __LIB_CELL_RENDERER_H__
#define __LIB_CELL_RENDERER_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(LibCellRenderer, lib_cell_renderer, LIB_CELL, RENDERER, GtkCellRendererText)
#define TYPE_LIB_CELL_RENDERER (lib_cell_renderer_get_type())
typedef struct _LibCellRenderer {
/* Inheritance */
GtkCellRendererText super;
/* Custom Elements */
} LibCellRenderer;
GType lib_cell_renderer_get_type(void);
GtkCellRenderer *lib_cell_renderer_new(void);
G_END_DECLS
#endif /* __LIB_CELL_RENDERER_H__ */

View File

@@ -0,0 +1,79 @@
#include "tree-store.h"
#include "lib-cell-renderer.h"
#include "../gds-parser/gds-types.h"
static gboolean tree_sel_func(GtkTreeSelection *selection,
GtkTreeModel *model,
GtkTreePath *path,
gboolean path_currently_selected,
gpointer data)
{
GtkTreeIter iter;
struct gds_cell *cell;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, -1);
/* Allow only rows with valid cell to be selected */
if (cell)
return TRUE;
else
return FALSE;
}
GtkTreeStore *setup_cell_selector(GtkTreeView* view)
{
GtkTreeStore *cell_store;
GtkCellRenderer *render_dates;
GtkCellRenderer *render_cell;
GtkCellRenderer *render_lib;
GtkTreeViewColumn *column;
GdkRGBA cell_text_color;
GValue val = G_VALUE_INIT;
cell_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_view_set_model(view, GTK_TREE_MODEL(cell_store));
render_dates = gtk_cell_renderer_text_new();
render_cell = lib_cell_renderer_new();
render_lib = lib_cell_renderer_new();
/* Set foreground color for cell column */
cell_text_color.alpha = 1;
cell_text_color.red = (double)61.0/(double)255.0;
cell_text_color.green = (double)152.0/(double)255.0;
cell_text_color.blue = 0.0;
g_value_init(&val, G_TYPE_BOOLEAN);
g_value_set_boolean(&val, TRUE);
g_object_set_property(G_OBJECT(render_cell), "foreground-set", &val);
g_value_unset(&val);
g_value_init(&val, GDK_TYPE_RGBA);
g_value_set_boxed(&val, &cell_text_color);
g_object_set_property(G_OBJECT(render_cell), "foreground-rgba", &val);
g_value_unset(&val);
column = gtk_tree_view_column_new_with_attributes("Library", render_lib, "gds-lib", CELL_SEL_LIBRARY, NULL);
gtk_tree_view_append_column(view, column);
/* Cell color: #3D9801 */
column = gtk_tree_view_column_new_with_attributes("Cell", render_cell, "gds-cell", CELL_SEL_CELL, NULL);
gtk_tree_view_append_column(view, column);
column = gtk_tree_view_column_new_with_attributes("Mod. Date", render_dates, "text", CELL_SEL_MODDATE, NULL);
gtk_tree_view_append_column(view, column);
column = gtk_tree_view_column_new_with_attributes("Acc. Date", render_dates, "text", CELL_SEL_ACCESSDATE, NULL);
gtk_tree_view_append_column(view, column);
/* Callback for selection
* This prevents selecting a library */
gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(view), tree_sel_func, NULL, NULL);
return cell_store;
}

View File

@@ -0,0 +1,16 @@
#ifndef __TREE_STORE_H__
#define __TREE_STORE_H__
#include <gtk/gtk.h>
enum cell_store_columns {
CELL_SEL_LIBRARY = 0,
CELL_SEL_CELL,
CELL_SEL_MODDATE,
CELL_SEL_ACCESSDATE,
CELL_SEL_COLUMN_COUNT
};
GtkTreeStore *setup_cell_selector(GtkTreeView* view);
#endif /* __TREE_STORE_H__ */