34 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
27 changed files with 17195 additions and 380 deletions

View File

@@ -7,22 +7,27 @@ project(gds-render)
add_subdirectory(glade)
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} "layer-widget")
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS})
add_definitions(${GLIB2_CFLAGS_OTHER})
aux_source_directory("layer-widget" SUB_SOURCES)
aux_source_directory("layer-widget" LAYER_SOURCES)
aux_source_directory("tree-renderer" RENDERER_SOURCES)
set(SOURCE "main.c" "gdsparse.c" "layer-selector.c")
aux_source_directory("gds-parser" PARSER_SOURCES)
aux_source_directory("latex-output" LATEX_SOURCES)
set(SOURCE "main.c" "layer-selector.c")
set(SOURCE
${SOURCE}
${SUB_SOURCES}
${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)

View File

@@ -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,
@@ -188,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;
@@ -346,6 +349,9 @@ void scan_library_references(gpointer library_list_item, gpointer user)
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;
@@ -356,37 +362,28 @@ void gds_parse_date(const char *buffer, int length, struct gds_time_field *mod_d
return;
}
mod_date->year = gds_convert_unsigend_int16(buffer);
buffer += 2;
mod_date->month = gds_convert_unsigend_int16(buffer);
buffer += 2;
mod_date->day = gds_convert_unsigend_int16(buffer);
buffer += 2;
mod_date->hour = gds_convert_unsigend_int16(buffer);
buffer += 2;
mod_date->minute = gds_convert_unsigend_int16(buffer);
buffer += 2;
mod_date->second = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->year = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->month = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->day = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->hour = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->minute = gds_convert_unsigend_int16(buffer);
buffer += 2;
access_date->second = gds_convert_unsigend_int16(buffer);
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;
@@ -403,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;
@@ -427,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: */
@@ -451,8 +453,7 @@ 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) {
@@ -556,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) {
@@ -580,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;
@@ -592,12 +597,26 @@ 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);
@@ -640,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!");
@@ -679,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;
}
@@ -687,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;
}

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,59 +0,0 @@
#ifndef __GDS_TYPES_H__
#define __GDS_TYPES_H__
#include <stdint.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 mod_time;
struct gds_time_field access_time;
double unit_to_meters;
GList *cells;
GList *cell_names;
};
#endif /* __GDS_TYPES_H__ */

View File

@@ -12,6 +12,24 @@
<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>
@@ -21,7 +39,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -36,7 +54,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@@ -50,7 +68,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
@@ -61,7 +79,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
</object>

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,63 +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>
<style>
<class name="destructive-action"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</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="expand">False</property>
<property name="fill">True</property>
<property name="position">3</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>
@@ -79,15 +82,23 @@
<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>
<property name="expand">False</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
@@ -96,6 +107,7 @@
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
@@ -117,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>

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

@@ -18,71 +18,95 @@
*/
#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 GList *layer_widgets = NULL;
static GtkWidget *load_button;
static GtkWidget *save_button;
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 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 because they are only referenced inside the container */
g_list_free(layer_widgets);
layer_widgets = NULL;
g_list_free(list);
/* Deactivate buttons */
gtk_widget_set_sensitive(load_button, FALSE);
gtk_widget_set_sensitive(save_button, FALSE);
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;
}
@@ -101,28 +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);
}
}
}
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;
}
@@ -130,8 +146,10 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
{
GList *cell_list = NULL;
struct gds_library *lib;
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);
for (; libs != NULL; libs = libs->next) {
@@ -144,9 +162,12 @@ 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(load_button, TRUE);
gtk_widget_set_sensitive(save_button, TRUE);
gtk_widget_set_sensitive(global_load_button, TRUE);
gtk_widget_set_sensitive(global_save_button, TRUE);
}
/**
@@ -186,7 +207,7 @@ static int load_csv_line(GDataInputStream *stream, gboolean *export, char **name
if (g_match_info_matches(mi)) {
/* Line is valid */
match = g_match_info_fetch_named(mi, "layer");
*layer = g_ascii_strtoll(match, NULL, 10);
*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);
@@ -222,34 +243,31 @@ ret_direct:
}
static LayerElement *find_layer_in_list(GList *list, int layer)
static LayerElement *find_layer_element_in_list(GList *el_list, int layer)
{
LayerElement *le_found, *temp;
for (le_found = NULL; list != NULL; list = list->next) {
temp = LAYER_ELEMENT(list->data);
if (layer_element_get_layer(temp) == layer) {
le_found = temp;
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 le_found;
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);
@@ -259,20 +277,47 @@ static void load_layer_mapping_from_file(gchar *file_name)
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;
/* search for layer widget */
if (le = find_layer_in_list(layer_widgets, layer)) {
layer_element_set_name(le, name);
/* 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);
}
g_free(name);
}
/* 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);
@@ -314,7 +359,8 @@ static void create_csv_line(LayerElement *layer_element, char *line_buffer, size
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,
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)) {
@@ -331,23 +377,28 @@ static void create_csv_line(LayerElement *layer_element, char *line_buffer, size
g_string_free(string, TRUE);
}
static void save_layer_mapping_data(const gchar *file_name)
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");
/* File format is CSV: <Layer>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
for (le_list = layer_widgets; le_list != NULL; le_list = le_list->next) {
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((LayerElement *)le_list->data, workbuff, sizeof(workbuff));
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);
@@ -364,7 +415,7 @@ static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
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);
save_layer_mapping_data(file_name, global_list_box);
g_free(file_name);
}
gtk_widget_destroy(dialog);
@@ -373,13 +424,13 @@ static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window)
{
g_object_ref(G_OBJECT(button));
load_button = 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));
save_button = button;
global_save_button = button;
g_signal_connect(button, "clicked", G_CALLBACK(save_mapping_clicked), main_window);
}

View File

@@ -22,21 +22,19 @@
#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, GtkWindow *main_window);
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
void get_layer_info(GList **info_list, GtkListBox *box);
GList *export_rendered_layer_info();
void delete_layer_info_struct(struct layer_info *info);
#endif /* __LAYER_SELECTOR_H__ */

View File

@@ -19,8 +19,7 @@
#include "layer-element.h"
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_BOX)
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
static void layer_element_dispose(GObject *obj)
{
@@ -40,29 +39,105 @@ static void layer_element_class_init(LayerElementClass *klass)
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_box_pack_start(GTK_BOX(self), glade_box, TRUE, TRUE, 0);
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"));
/* Connect signals */
/* None */
/* 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(layer_element_get_type(), NULL));
return GTK_WIDGET(g_object_new(TYPE_LAYER_ELEMENT, NULL));
}
const char *layer_element_get_name(LayerElement *elem)
@@ -80,7 +155,7 @@ void layer_element_set_layer(LayerElement *elem, int layer)
GString *string;
string = g_string_new_len(NULL, 100);
g_string_printf(string, "Layer: %3d", layer);
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);

View File

@@ -21,33 +21,30 @@
#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_LAYER_ELEMENT(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;
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);
@@ -59,4 +56,6 @@ 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__ */

154
main.c
View File

@@ -18,21 +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"
#include "tree-renderer/lib-cell-renderer.h"
enum cell_store_columns {
LIBRARY,
CELL,
MODDATE,
ACCESSDATE,
STORE_COLUMN_COUNT
};
#include "tree-renderer/tree-store.h"
#include "latex-output/latex-output.h"
struct open_button_data {
GtkWindow *main_window;
@@ -41,6 +32,11 @@ 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)
{
gtk_widget_destroy(GTK_WIDGET(window));
@@ -123,9 +119,9 @@ void on_load_gds(gpointer button, gpointer user)
acc_date = generate_string_from_date(&gds_lib->access_time);
gtk_tree_store_set (store, &libiter,
LIBRARY, gds_lib,
MODDATE, mod_date->str,
ACCESSDATE, acc_date->str,
CELL_SEL_LIBRARY, gds_lib,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
-1);
/* Delete GStrings including string data. */
@@ -142,9 +138,9 @@ void on_load_gds(gpointer button, gpointer user)
acc_date = generate_string_from_date(&gds_c->access_time);
gtk_tree_store_set (store, &celliter,
CELL, gds_c,
MODDATE, mod_date->str,
ACCESSDATE, acc_date->str,
CELL_SEL_CELL, gds_c,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
-1);
/* Delete GStrings including string data. */
@@ -163,62 +159,63 @@ end_destroy:
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_dates;
GtkCellRenderer *render_cell;
GtkCellRenderer *render_lib;
GtkTreeViewColumn *column;
GdkRGBA cell_text_color;
GValue val = G_VALUE_INIT;
cell_store = gtk_tree_store_new(STORE_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", 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, NULL);
gtk_tree_view_append_column(view, column);
column = gtk_tree_view_column_new_with_attributes("Mod. Date", render_dates, "text", MODDATE, NULL);
gtk_tree_view_append_column(view, column);
column = gtk_tree_view_column_new_with_attributes("Acc. Date", render_dates, "text", ACCESSDATE, 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)
@@ -227,11 +224,11 @@ 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);
@@ -249,11 +246,17 @@ 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);
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
open_data.layer_box = GTK_LIST_BOX(listbox);
@@ -264,6 +267,9 @@ int main(int argc, char **argv)
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();

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

@@ -18,7 +18,7 @@
*/
#include "lib-cell-renderer.h"
#include "../gds-types.h"
#include "../gds-parser/gds-types.h"
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)

View File

@@ -20,12 +20,11 @@
#ifndef __LIB_CELL_RENDERER_H__
#define __LIB_CELL_RENDERER_H__
#include <gtk/gtk.h>
#define LIB_CELL_RENDERER(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, lib_cell_renderer_get_type(), LibCellRenderer)
#define LIB_CELL_RENDERER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, lib_cell_renderer_get_type(), LibCellRendererClass)
#define IS_LIB_CELL_RENDERER(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, layer_element_get_type())
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 {
@@ -34,14 +33,9 @@ typedef struct _LibCellRenderer {
/* Custom Elements */
} LibCellRenderer;
typedef struct _LibCellRendererClass {
GtkCellRendererTextClass parent;
} LibCellRendererClass;
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__ */