19 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
18 changed files with 16462 additions and 95 deletions

View File

@@ -27,6 +27,7 @@ set(SOURCE
${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

@@ -59,6 +59,7 @@ enum record {
BOX = 0x2D00,
LAYER = 0x0D02,
WIDTH = 0x0F03,
PATHTYPE = 0x2102
};
static int name_cell_ref(struct gds_cell_instance *cell_inst,
@@ -189,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;
@@ -347,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;
@@ -357,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;
@@ -404,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;
@@ -428,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: */
@@ -452,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) {
@@ -557,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) {
@@ -583,6 +583,8 @@ int parse_gds_from_file(const char *filename, GList **library_list)
break;
case WIDTH:
break;
case PATHTYPE:
break;
default:
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
break;
@@ -595,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);
@@ -688,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;
}
@@ -696,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;
}

View File

@@ -7,54 +7,55 @@
#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;
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;
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;
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;
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;
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;
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

@@ -6,7 +6,6 @@
<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>

View File

@@ -18,6 +18,7 @@
*/
#include "latex-output.h"
#include <math.h>
#define WRITEOUT_BUFFER(buff) fwrite((buff)->str, sizeof(char), (buff)->len, tex_file)
@@ -70,7 +71,8 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
color->red = inf->color.red;
color->green = inf->color.green;
color->blue = inf->color.blue;
g_string_printf(buffer, "\\begin{pgfonlayer}{l%d}\n\\begin{scope}[ocg={ref=%d, status=visible,name=%d}]\n", layer, layer, layer);
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;
}
@@ -86,17 +88,14 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
struct gds_graphics *gfx;
struct gds_point *pt;
GdkRGBA color;
int width;
gchar *red, *green, *blue, *opacity;
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->type == GRAPHIC_POLYGON) {
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);
@@ -108,9 +107,37 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
}
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, "\\end{scope}\n\\end{pgfonlayer}\n");
g_string_printf(buffer, "\\ifcreatepdflayers\n\\end{scope}\n\\fi\n\\end{pgfonlayer}\n");
WRITEOUT_BUFFER(buffer);
}
@@ -131,13 +158,14 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
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)}, rotate=%lf]\n",
((double)inst->origin.x)/1000.0,((double)inst->origin.y)/1000.0,
inst->angle);
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}[xscale=%s]\n",
(inst->flipped ? "-1" : "1"));
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)
@@ -148,6 +176,9 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
}
}
@@ -163,6 +194,18 @@ void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_fi
/* 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);
@@ -177,6 +220,13 @@ void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_fi
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

@@ -23,18 +23,12 @@
#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 delete_layer_widget(GtkWidget *widget)
{
gtk_widget_destroy(widget);
}
void delete_layer_info_struct(struct layer_info *info)
{
if (info)
@@ -67,6 +61,7 @@ GList *export_rendered_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);
@@ -269,7 +264,6 @@ static void load_layer_mapping_from_file(gchar *file_name)
char *name;
gboolean export;
int layer;
int target_layer;
GdkRGBA color;
int result;
GList *rows;
@@ -293,15 +287,13 @@ static void load_layer_mapping_from_file(gchar *file_name)
gtk_container_remove(GTK_CONTAINER(global_list_box), GTK_WIDGET(le));
}
target_layer = 0;
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)) {
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);

View File

@@ -26,6 +26,7 @@
struct layer_info
{
int layer;
char *name;
int stacked_position; ///< Lower is bottom, higher is top
GdkRGBA color;
};

3
main.c
View File

@@ -246,6 +246,9 @@ 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 */

View File

@@ -1,2 +1,2 @@
layout.tex
toplevel.pdf
*.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

@@ -8,10 +8,8 @@ static gboolean tree_sel_func(GtkTreeSelection *selection,
gboolean path_currently_selected,
gpointer data)
{
static int cnt = 0;
GtkTreeIter iter;
struct gds_cell *cell;
gchar *p;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, -1);