26 Commits

Author SHA1 Message Date
a5d794461a Add license 2018-07-23 15:26:51 +02:00
6fb4d39fc8 Add application menu and about dialog 2018-07-23 15:10:40 +02:00
d0e1383861 reconstructed code to use g_application 2018-07-23 13:10:34 +02:00
6296627ac2 Merge branch 'master' of git.shimatta.de:mhu/gds-render 2018-07-23 09:59:26 +02:00
f79bab102b Remove Bounding box calculations from parser. They're not needed 2018-07-23 09:58:14 +02:00
e5300e60aa Color of Load layer mapping button changed to blue 2018-07-22 16:55:20 +02:00
4c5784c3a4 finished first version of Cairo export 2018-07-22 16:38:26 +02:00
f765e27ce8 fix rendering of box in cairo renderer 2018-07-20 23:29:27 +02:00
40760725b8 Merge branch 'master' into cairo-dev 2018-07-20 23:26:50 +02:00
dac834aef2 auto detect glade files 2018-07-20 23:22:47 +02:00
d4f2d6798e Merge branch 'master' into cairo-dev 2018-07-20 22:41:16 +02:00
f8cbf7e066 use enum name instead of pure integer value 2018-07-20 22:36:54 +02:00
59ec0c5a10 cairo layer renderer 2018-07-20 22:32:23 +02:00
2a615367d7 Add advanced export settings for LaTeX export 2018-07-19 22:09:58 +02:00
3167da4648 cairo output started 2018-07-19 18:45:37 +02:00
b72466957c Added variable scaling factor for Tex output 2018-07-19 17:54:05 +02:00
d9f0f3cdd5 settings dialog fully implemented 2018-07-19 17:49:33 +02:00
4c04ce3614 further implementation of settings dialog 2018-07-19 16:38:52 +02:00
a2bc980c64 dialog implementation 2018-07-19 15:47:57 +02:00
73ea4d6838 re-organized folder structure 2018-07-19 15:11:18 +02:00
526785cffd add dialog to compile resources 2018-07-19 15:07:20 +02:00
6a8b359f3d add dialog for conversion options 2018-07-19 15:05:44 +02:00
bbd731401d add support for boxes 2018-07-17 00:02:30 +02:00
7734467ea9 Use cairo for path bounding box 2018-07-11 12:24:15 +02:00
7d66ca1280 Support for magnification, bounding boxes fully implemented 2018-07-04 21:46:39 +02:00
542737622f smaller fixes, started boundary box scanner. Rotation, scaling and flipping is not handled correctly yet 2018-07-04 09:49:04 +02:00
20 changed files with 1079 additions and 306 deletions

View File

@@ -2,22 +2,23 @@ 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)
pkg_check_modules(CAIRO REQUIRED cairo)
project(gds-render)
add_subdirectory(glade)
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS})
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
add_definitions(${GLIB2_CFLAGS_OTHER})
aux_source_directory("layer-widget" LAYER_SOURCES)
aux_source_directory("widgets" 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")
aux_source_directory("cairo-output" CAIRO_SOURCES)
set(SOURCE "main.c" "layer-selector.c" "main-window.c")
set(SOURCE
${SOURCE}
@@ -25,6 +26,7 @@ set(SOURCE
${RENDERER_SOURCES}
${PARSER_SOURCES}
${LATEX_SOURCES}
${CAIRO_SOURCES}
)
add_compile_options(-Wall)
@@ -32,5 +34,5 @@ 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)
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m)

248
cairo-output/cairo-output.c Normal file
View File

@@ -0,0 +1,248 @@
/*
* 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 "cairo-output.h"
#include <math.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-pdf.h>
struct cairo_layer {
cairo_t *cr;
cairo_surface_t *rec;
struct layer_info *linfo;
};
static void revert_inherited_transform(struct cairo_layer *layers)
{
int i;
for (i = 0; i < MAX_LAYERS; i++) {
if (layers[i].cr == NULL)
continue;
cairo_restore(layers[i].cr);
}
}
static void apply_inherited_transform_to_all_layers(struct cairo_layer *layers,
const struct gds_point *origin,
double magnification,
gboolean flipping,
double rotation,
double scale)
{
int i;
cairo_t *temp_layer_cr;
for (i = 0; i < MAX_LAYERS; i++) {
temp_layer_cr = layers[i].cr;
if (temp_layer_cr == NULL)
continue;
/* Save the state and apply transformation */
cairo_save(temp_layer_cr);
cairo_translate(temp_layer_cr, (double)origin->x/scale, (double)origin->y/scale);
cairo_rotate(temp_layer_cr, M_PI*rotation/180.0);
cairo_scale(temp_layer_cr, magnification,
(flipping == TRUE ? -magnification : magnification));
}
}
static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, double scale)
{
GList *instance_list;
struct gds_cell *temp_cell;
struct gds_cell_instance *cell_instance;
GList *gfx_list;
struct gds_graphics *gfx;
GList *vertex_list;
struct gds_point *vertex;
cairo_t *cr;
/* Render child cells */
for (instance_list = cell->child_cells; instance_list != NULL; instance_list = instance_list->next) {
cell_instance = (struct gds_cell_instance *)instance_list->data;
if ((temp_cell = cell_instance->cell_ref) != NULL) {
apply_inherited_transform_to_all_layers(layers,
&cell_instance->origin,
cell_instance->magnification,
cell_instance->flipped,
cell_instance->angle,
scale);
render_cell(temp_cell, layers, scale);
revert_inherited_transform(layers);
}
}
/* Render graphics */
for (gfx_list = cell->graphic_objs; gfx_list != NULL; gfx_list = gfx_list->next) {
gfx = (struct gds_graphics *)gfx_list->data;
/* Get layer renderer */
if (gfx->layer >= MAX_LAYERS)
continue;
if ((cr = layers[gfx->layer].cr) == NULL)
continue;
/* Apply settings */
cairo_set_line_width(cr, (gfx->width_absolute ? gfx->width_absolute/scale : 1));
switch (gfx->path_render_type) {
case PATH_FLUSH:
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
break;
case PATH_ROUNDED:
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
break;
case PATH_SQUARED:
cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
break;
}
/* Add vertices */
for (vertex_list = gfx->vertices; vertex_list != NULL; vertex_list = vertex_list->next) {
vertex = (struct gds_point *)vertex_list->data;
/* If first point -> move to, else line to */
if (vertex_list->prev == NULL)
cairo_move_to(cr, vertex->x/scale, vertex->y/scale);
else
cairo_line_to(cr, vertex->x/scale, vertex->y/scale);
}
/* Create graphics object */
switch (gfx->gfx_type) {
case GRAPHIC_PATH:
cairo_stroke(cr);
break;
case GRAPHIC_BOX:
case GRAPHIC_POLYGON:
cairo_set_line_width(cr, 0.1/scale);
cairo_close_path(cr);
cairo_stroke_preserve(cr); // Prevent graphic glitches
cairo_fill(cr);
break;
}
}
}
void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale)
{
cairo_surface_t *pdf_surface;
cairo_t *pdf_cr;
struct layer_info *linfo;
struct cairo_layer *layers;
struct cairo_layer *lay;
GList *info_list;
int i;
double rec_x0, rec_y0, rec_width, rec_height;
double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN;
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
/* Clear layers */
for (i = 0; i < MAX_LAYERS; i++) {
layers[i].cr = NULL;
layers[i].rec = NULL;
}
/* Create recording surface for each layer */
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data;
if (linfo->layer < MAX_LAYERS) {
lay = &(layers[(unsigned int)linfo->layer]);
lay->linfo = linfo;
lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,
NULL);
lay->cr = cairo_create(layers[(unsigned int)linfo->layer].rec);
cairo_scale(lay->cr, 1, -1); // Fix coordinate system
cairo_set_source_rgb(lay->cr, linfo->color.red, linfo->color.green, linfo->color.blue);
} else {
printf("Layer number (%d) too high!\n", linfo->layer);
goto ret_clear_layers;
}
}
render_cell(cell, layers, scale);
/* get size of image and top left coordinate */
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data;
if (linfo->layer >= MAX_LAYERS) {
printf("Layer outside of Spec.\n");
continue;
}
/* Print size */
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
&rec_width, &rec_height);
printf("Size of layer %d: %lf -- %lf\n", linfo->layer,
rec_width, rec_height);
/* update bounding box */
xmin = MIN(xmin, rec_x0);
xmax = MAX(xmax, rec_x0);
ymin = MIN(ymin, rec_y0);
ymax = MAX(ymax, rec_y0);
xmin = MIN(xmin, rec_x0+rec_width);
xmax = MAX(xmax, rec_x0+rec_width);
ymin = MIN(ymin, rec_y0+rec_height);
ymax = MAX(ymax, rec_y0+rec_height);
}
printf("Bounding box: (%lf,%lf) -- (%lf,%lf)\n", xmin, ymin, xmax, ymax);
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
pdf_cr = cairo_create(pdf_surface);
/* Write layers to PDF */
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data;
if (linfo->layer >= MAX_LAYERS) {
printf("Layer outside of Spec.\n");
continue;
}
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
}
cairo_show_page(pdf_cr);
cairo_destroy(pdf_cr);
cairo_surface_destroy(pdf_surface);
ret_clear_layers:
for (i = 0; i < MAX_LAYERS; i++) {
lay = &layers[i];
if(lay->cr) {
cairo_destroy(lay->cr);
cairo_surface_destroy(lay->rec);
}
}
free(layers);
printf("cairo export finished. It might still be buggy!\n");
}

View File

@@ -0,0 +1,30 @@
/*
* 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 __CAIRO_OUTPUT_H__
#define __CAIRO_OUTPUT_H__
#include "../layer-selector.h"
#include "../gds-parser/gds-types.h"
#define MAX_LAYERS (300)
void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale);
#endif /* __CAIRO_OUTPUT_H__ */

View File

@@ -33,6 +33,7 @@
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include <cairo.h>
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
@@ -302,7 +303,7 @@ static int name_cell(struct gds_cell *cell, unsigned int bytes,
}
void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
{
struct gds_cell_instance *inst = (struct gds_cell_instance *)gcell_ref;
struct gds_library *lib = (struct gds_library *)glibrary;
@@ -328,7 +329,7 @@ void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
GDS_WARN("referenced cell could not be found in library");
}
void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
static void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
{
struct gds_cell *cell = (struct gds_cell *)gcell;
@@ -339,7 +340,7 @@ void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
}
void scan_library_references(gpointer library_list_item, gpointer user)
static void scan_library_references(gpointer library_list_item, gpointer user)
{
struct gds_library *lib = (struct gds_library *)library_list_item;
@@ -347,7 +348,7 @@ 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)
static 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;
@@ -507,21 +508,22 @@ int parse_gds_from_file(const char *filename, GList **library_list)
current_cell = NULL;
printf("Leaving Cell\n");
break;
//case BOX:
case BOX:
case BOUNDARY:
if (current_cell == NULL) {
GDS_ERROR("Boundary outside of cell");
GDS_ERROR("Boundary/Box outside of cell");
run = -3;
break;
}
current_cell->graphic_objs = append_graphics(current_cell->graphic_objs,
GRAPHIC_POLYGON, &current_graphics);
(rec_type == BOUNDARY ? GRAPHIC_POLYGON : GRAPHIC_BOX),
&current_graphics);
if (current_cell->graphic_objs == NULL) {
GDS_ERROR("Memory allocation failed");
run = -4;
break;
}
printf("\tEntering boundary\n");
printf("\tEntering boundary/Box\n");
break;
case SREF:
if (current_cell == NULL) {
@@ -575,6 +577,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
}
break;
case MAG:
break;
case ANGLE:
@@ -729,6 +732,9 @@ int parse_gds_from_file(const char *filename, GList **library_list)
g_list_foreach(lib_list, scan_library_references, NULL);
}
*library_list = lib_list;
free(workbuff);

View File

@@ -5,57 +5,59 @@
#include <glib.h>
#define CELL_NAME_MAX (100)
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1};
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1, GRAPHIC_BOX};
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_point {
int x;
int y;
struct gds_time_field {
uint16_t year;
uint16_t month;
uint16_t day;
uint16_t hour;
uint16_t minute;
uint16_t second;
};
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;
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

@@ -1,8 +1,6 @@
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
${CMAKE_CURRENT_SOURCE_DIR}/*.glade
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/resources.c
COMMAND

43
glade/about.glade Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkAboutDialog" id="about-dialog">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<property name="program_name">GDS-Render Tool </property>
<property name="comments" translatable="yes">Tool for rendering GDS(II) layout files into LaTeX/TikZ code or directly into a PDF file</property>
<property name="website">https://git.shimatta.de/mhu/gds-render</property>
<property name="website_label" translatable="yes">Git Repository</property>
<property name="authors">Mario Hüttel &lt;mario.huettel@gmx.net&gt;</property>
<property name="logo_icon_name">applications-graphics</property>
<property name="license_type">gpl-2-0-only</property>
<child>
<placeholder/>
</child>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>

90
glade/dialog.glade Normal file
View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">1</property>
<property name="upper">3000</property>
<property name="value">1000</property>
<property name="step_increment">10</property>
<property name="page_increment">1000</property>
</object>
<object class="GtkBox" id="dialog-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="latex-radio">
<property name="label" translatable="yes">Generate LaTeX/TikZ output</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="cairo-radio">
<property name="label" translatable="yes">Render PDF using Cairographics</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">latex-radio</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScale" id="dialog-scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="standalone-check">
<property name="label" translatable="yes">Configure LaTeX as standalone document</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="layer-check">
<property name="label" translatable="yes">Generate PDF Layers</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</interface>

View File

@@ -4,7 +4,6 @@
<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>
<child type="titlebar">
<object class="GtkHeaderBar">
@@ -35,7 +34,7 @@
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<style>
<class name="destructive-action"/>
<class name="suggested-action"/>
</style>
</object>
<packing>

View File

@@ -2,7 +2,9 @@
<gresources>
<gresource prefix="/">
<file compressed="true">main.glade</file>
<file compressed="true">about.glade</file>
<file>layer-widget.glade</file>
<file>dialog.glade</file>
</gresource>
</gresources>

View File

@@ -81,7 +81,7 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
}
static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GString *buffer)
static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GString *buffer, double scale)
{
GList *temp;
GList *temp_vertex;
@@ -95,19 +95,19 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
if (write_layer_env(tex_file, &color, (int)gfx->layer, linfo, buffer) == TRUE) {
/* Layer is defined => create graphics */
if (gfx->gfx_type == GRAPHIC_POLYGON) {
if (gfx->gfx_type == GRAPHIC_POLYGON || gfx->gfx_type == GRAPHIC_BOX ) {
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);
g_string_printf(buffer, "(%lf pt, %lf pt) -- ", ((double)pt->x)/scale, ((double)pt->y)/scale);
WRITEOUT_BUFFER(buffer);
}
g_string_printf(buffer, "cycle;\n");
WRITEOUT_BUFFER(buffer);
} else if(gfx->gfx_type == GRAPHIC_PATH) {
} else if (gfx->gfx_type == GRAPHIC_PATH) {
if (g_list_length(gfx->vertices) < 2) {
printf("Cannot write path with less than 2 points\n");
@@ -116,11 +116,11 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
if (gfx->path_render_type < 0 || gfx->path_render_type > 2) {
printf("Path type unrecognized. Setting to 'flushed'\n");
gfx->path_render_type = 0;
gfx->path_render_type = PATH_FLUSH;
}
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,
gfx->width_absolute/scale, gfx->layer, color.alpha,
line_caps[gfx->path_render_type]);
WRITEOUT_BUFFER(buffer);
@@ -128,8 +128,8 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
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,
((double)pt->x)/scale,
((double)pt->y)/scale,
(temp_vertex->next ? " -- " : ""));
WRITEOUT_BUFFER(buffer);
}
@@ -145,31 +145,36 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
}
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer)
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale)
{
GList *list_child;
struct gds_cell_instance *inst;
/* Draw polygons of current cell */
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer);
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer, scale);
/* 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;
/* Abort if cell has no reference */
if (!inst->cell_ref)
continue;
/* 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);
((double)inst->origin.x)/scale,((double)inst->origin.y)/scale);
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"));
g_string_printf(buffer, "\\begin{scope}[yscale=%lf, xscale=%lf]\n", (inst->flipped ? -1*inst->magnification : inst->magnification),
inst->magnification);
WRITEOUT_BUFFER(buffer);
if (inst->cell_ref)
render_cell(inst->cell_ref, layer_infos, tex_file, buffer);
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale);
g_string_printf(buffer, "\\end{scope}\n");
WRITEOUT_BUFFER(buffer);
@@ -183,7 +188,8 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
}
void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file)
void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
gboolean create_pdf_layers, gboolean standalone_document)
{
GString *working_line;
@@ -195,9 +201,11 @@ void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_fi
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");
g_string_printf(working_line, "\\newif\\iftestmode\n\\testmode%s\n",
(standalone_document ? "true" : "false"));
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\newif\\ifcreatepdflayers\n\\createpdflayersfalse %% Change to true for Embedded layers in PDF output\n");
g_string_printf(working_line, "\\newif\\ifcreatepdflayers\n\\createpdflayers%s\n",
(create_pdf_layers ? "true" : "false"));
WRITEOUT_BUFFER(working_line);
g_string_printf(working_line, "\\iftestmode\n");
WRITEOUT_BUFFER(working_line);
@@ -214,7 +222,7 @@ void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_fi
WRITEOUT_BUFFER(working_line);
/* Generate graphics output */
render_cell(cell, layer_infos, tex_file, working_line);
render_cell(cell, layer_infos, tex_file, working_line, scale);
g_string_printf(working_line, "\\end{tikzpicture}\n");

View File

@@ -27,6 +27,7 @@
#define LATEX_LINE_BUFFER_KB (10)
void render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file);
void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
gboolean create_pdf_layers, gboolean standalone_document);
#endif /* __LATEX_OUTPUT_H__ */

View File

@@ -19,7 +19,7 @@
#include "layer-selector.h"
#include "gds-parser/gds-parser.h"
#include "layer-widget/layer-element.h"
#include "widgets/layer-element.h"
#include <glib.h>
#include <string.h>
#include <stdio.h>

316
main-window.c Normal file
View File

@@ -0,0 +1,316 @@
/*
* 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 "main-window.h"
#include <stdio.h>
#include "gds-parser/gds-parser.h"
#include <gtk/gtk.h>
#include "layer-selector.h"
#include "tree-renderer/tree-store.h"
#include "latex-output/latex-output.h"
#include "widgets/conv-settings-dialog.h"
#include "cairo-output/cairo-output.h"
struct open_button_data {
GtkWindow *main_window;
GList **list_ptr;
GtkTreeStore *cell_store;
GtkListBox *layer_box;
};
struct convert_button_data {
GtkTreeView *tree_view;
GtkWindow *main_window;
};
static gboolean on_window_close(gpointer window, gpointer user)
{
gtk_widget_destroy(GTK_WIDGET(window));
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;
}
static void on_load_gds(gpointer button, gpointer user)
{
GList *cell;
GtkTreeIter libiter;
GtkTreeIter celliter;
GList *lib;
struct gds_library *gds_lib;
struct gds_cell *gds_c;
struct open_button_data *ptr = (struct open_button_data *)user;
GtkTreeStore *store = ptr->cell_store;
GtkWidget *open_dialog;
GtkFileChooser *file_chooser;
GtkFileFilter *filter;
GtkStyleContext *button_style;
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);
file_chooser = GTK_FILE_CHOOSER(open_dialog);
/* Add GDS II Filter */
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.gds");
gtk_file_filter_set_name(filter, "GDSII-Files");
gtk_file_chooser_add_filter(file_chooser, filter);
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
if (dialog_result == GTK_RESPONSE_ACCEPT) {
/* Get File name */
filename = gtk_file_chooser_get_filename(file_chooser);
gtk_tree_store_clear(store);
clear_lib_list(ptr->list_ptr);
/* Parse new GDSII file */
gds_result = parse_gds_from_file(filename, ptr->list_ptr);
/* Delete file name afterwards */
g_free(filename);
if (gds_result)
goto end_destroy;
/* remove suggested action from Open button */
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
gtk_style_context_remove_class(button_style, "suggested-action");
for (lib = *(ptr->list_ptr); lib != NULL; lib = lib->next) {
gds_lib = (struct gds_library *)lib->data;
/* Create top level iter */
gtk_tree_store_append (store, &libiter, NULL);
/* 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);
/* 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);
}
}
/* Create Layers in Layer Box */
generate_layer_widgets(ptr->layer_box, *(ptr->list_ptr));
}
end_destroy:
/* Destroy dialog and filter */
gtk_widget_destroy(open_dialog);
}
static void on_convert_clicked(gpointer button, gpointer user)
{
static struct render_settings sett = {
.scale = 1000.0f,
.renderer = RENDERER_LATEX_TIKZ,
};
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 *output_file;
GtkWidget *dialog;
RendererSettingsDialog *settings;
GtkFileFilter *filter;
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();
settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window));
renderer_settings_dialog_set_settings(settings, &sett);
res = gtk_dialog_run(GTK_DIALOG(settings));
if (res == GTK_RESPONSE_OK) {
renderer_settings_dialog_get_settings(settings, &sett);
gtk_widget_destroy(GTK_WIDGET(settings));
} else {
gtk_widget_destroy(GTK_WIDGET(settings));
goto ret_layer_destroy;
}
/* save file dialog */
dialog = gtk_file_chooser_dialog_new((sett.renderer == RENDERER_LATEX_TIKZ
? "Save LaTeX File" : "Save PDF"),
GTK_WINDOW(data->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
/* Set file filter according to settings */
filter = gtk_file_filter_new();
if (sett.renderer == RENDERER_LATEX_TIKZ) {
gtk_file_filter_add_pattern(filter, "*.tex");
gtk_file_filter_set_name(filter, "LaTeX-Files");
} else {
gtk_file_filter_add_pattern(filter, "*.pdf");
gtk_file_filter_set_name(filter, "PDF-Files");
}
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
gtk_widget_destroy(dialog);
switch (sett.renderer) {
case RENDERER_LATEX_TIKZ:
output_file = fopen(file_name, "w");
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett.scale,
sett.tex_pdf_layers, sett.tex_standalone);
fclose(output_file);
break;
case RENDERER_CAIROGRAPHICS:
cairo_render_cell_to_pdf(cell_to_render, layer_list, file_name, sett.scale);
break;
}
g_free(file_name);
} else {
gtk_widget_destroy(dialog);
}
ret_layer_destroy:
g_list_free_full(layer_list, (GDestroyNotify)delete_layer_info_struct);
}
/* 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)
{
GtkTreeModel *model = NULL;
GtkTreeIter iter;
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);
}
}
GtkWindow *create_main_window()
{
GtkBuilder *main_builder;
GtkTreeView *cell_tree;
GtkTreeStore *cell_store;
GtkWidget *listbox;
GtkWidget *conv_button;
static GList *gds_libs;
static struct open_button_data open_data;
static struct convert_button_data conv_data;
main_builder = gtk_builder_new_from_resource("/main.glade");
gtk_builder_connect_signals(main_builder, NULL);
cell_tree = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree"));
cell_store = setup_cell_selector(cell_tree);
open_data.cell_store = cell_store;
open_data.list_ptr = &gds_libs;
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 */
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);
/* 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);
return (conv_data.main_window);
}

27
main-window.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* 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 _MAIN_WINDOW_H_
#define _MAIN_WINDOW_H_
#include <gtk/gtk.h>
GtkWindow *create_main_window();
#endif /* _MAIN_WINDOW_H_ */

287
main.c
View File

@@ -18,260 +18,85 @@
*/
#include <stdio.h>
#include "gds-parser/gds-parser.h"
#include <gtk/gtk.h>
#include "layer-widget/layer-element.h"
#include "layer-selector.h"
#include "tree-renderer/tree-store.h"
#include "latex-output/latex-output.h"
#include "main-window.h"
struct open_button_data {
GtkWindow *main_window;
GList **list_ptr;
GtkTreeStore *cell_store;
GtkListBox *layer_box;
};
struct convert_button_data {
GtkTreeView *tree_view;
struct application_data {
GtkApplication *app;
GtkWindow *main_window;
};
gboolean on_window_close(gpointer window, gpointer user)
static void app_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
gtk_widget_destroy(GTK_WIDGET(window));
gtk_main_quit();
return TRUE;
struct application_data *appdata = (struct application_data *)user_data;
gtk_widget_destroy(GTK_WIDGET(appdata->main_window));
}
static GString *generate_string_from_date(struct gds_time_field *date)
static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
GString *str;
GtkBuilder *builder;
GtkDialog *dialog;
struct application_data *appdata = (struct application_data *)user_data;
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;
builder = gtk_builder_new_from_resource("/about.glade");
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
gtk_window_set_transient_for(GTK_WINDOW(dialog), appdata->main_window);
gtk_dialog_run(dialog);
gtk_widget_destroy(dialog);
g_object_unref(builder);
}
void on_load_gds(gpointer button, gpointer user)
const GActionEntry app_actions[] = {
{ "quit", app_quit },
{ "about", app_about }
};
static void gapp_activate(GApplication *app, gpointer user_data)
{
GList *cell;
GtkTreeIter libiter;
GtkTreeIter celliter;
GList *lib;
struct gds_library *gds_lib;
struct gds_cell *gds_c;
struct open_button_data *ptr = (struct open_button_data *)user;
GtkTreeStore *store = ptr->cell_store;
GtkWidget *open_dialog;
GtkFileChooser *file_chooser;
GtkFileFilter *filter;
GtkStyleContext *button_style;
gint dialog_result;
int gds_result;
char *filename;
GString *mod_date;
GString *acc_date;
GtkWindow *main_window;
struct application_data *appdata = (struct application_data *)user_data;
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);
file_chooser = GTK_FILE_CHOOSER(open_dialog);
/* Add GDS II Filter */
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.gds");
gtk_file_filter_set_name(filter, "GDSII-Files");
gtk_file_chooser_add_filter(file_chooser, filter);
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
if (dialog_result == GTK_RESPONSE_ACCEPT) {
/* Get File name */
filename = gtk_file_chooser_get_filename(file_chooser);
gtk_tree_store_clear(store);
clear_lib_list(ptr->list_ptr);
/* Parse new GDSII file */
gds_result = parse_gds_from_file(filename, ptr->list_ptr);
/* Delete file name afterwards */
g_free(filename);
if (gds_result)
goto end_destroy;
/* remove suggested action from Open button */
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
gtk_style_context_remove_class(button_style, "suggested-action");
for (lib = *(ptr->list_ptr); lib != NULL; lib = lib->next) {
gds_lib = (struct gds_library *)lib->data;
/* Create top level iter */
gtk_tree_store_append (store, &libiter, NULL);
/* 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);
/* 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);
}
}
/* Create Layers in Layer Box */
generate_layer_widgets(ptr->layer_box, *(ptr->list_ptr));
}
end_destroy:
/* Destroy dialog and filter */
gtk_widget_destroy(open_dialog);
}
static void on_convert_clicked(gpointer button, gpointer user)
{
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);
}
/* 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)
{
GtkTreeModel *model = NULL;
GtkTreeIter iter;
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);
}
main_window = create_main_window();
appdata->main_window = main_window;
gtk_application_add_window(GTK_APPLICATION(app), main_window);
gtk_widget_show(GTK_WIDGET(main_window));
}
int main(int argc, char **argv)
{
GtkBuilder *main_builder;
GList *gds_libs = NULL;
GtkTreeView *cell_tree;
GtkTreeStore *cell_store;
GtkWidget *conv_button;
GtkWidget *listbox;
GtkApplication *gapp;
int app_status;
struct application_data appdata;
GMenu *menu;
GMenu *m_quit;
GMenu *m_about;
struct open_button_data open_data;
struct convert_button_data conv_data;
gtk_init(&argc, &argv);
main_builder = gtk_builder_new_from_resource("/main.glade");
gtk_builder_connect_signals(main_builder, NULL);
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
g_application_register(G_APPLICATION(gapp), NULL, NULL);
//g_action_map_add_action_entries(G_ACTION_MAP(gapp), app_actions, G_N_ELEMENTS(app_actions), &appdata);
g_signal_connect (gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
cell_tree = (GtkTreeView *)gtk_builder_get_object(main_builder, "cell-tree");
cell_store = setup_cell_selector(cell_tree);
menu = g_menu_new();
m_quit = g_menu_new();
m_about = g_menu_new();
g_menu_append(m_quit, "Quit", "app.quit");
g_menu_append(m_about, "About", "app.about");
g_menu_append_section(menu, NULL, G_MENU_MODEL(m_about));
g_menu_append_section(menu, NULL, G_MENU_MODEL(m_quit));
g_action_map_add_action_entries(G_ACTION_MAP(gapp), app_actions, G_N_ELEMENTS(app_actions), &appdata);
gtk_application_set_app_menu(GTK_APPLICATION(gapp), G_MENU_MODEL(menu));
g_object_unref(m_quit);
g_object_unref(m_about);
g_object_unref(menu);
open_data.cell_store = cell_store;
open_data.list_ptr = &gds_libs;
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);
app_status = g_application_run (G_APPLICATION(gapp), argc, argv);
g_object_unref (gapp);
/* Connect delete-event */
g_signal_connect(GTK_WIDGET(open_data.main_window), "delete-event", G_CALLBACK(on_window_close), NULL);
/* Connect Convert button */
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);
/* 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;
return app_status;
}

View File

@@ -0,0 +1,128 @@
/*
* 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 "conv-settings-dialog.h"
struct _RendererSettingsDialog {
GtkDialog parent;
/* Private loot */
GtkWidget *radio_latex;
GtkWidget *radio_cairo;
GtkWidget *scale;
GtkWidget *layer_check;
GtkWidget *standalone_check;
};
G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG)
static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
{
/* No special code needed. Child cells are destroyed automatically due to reference counter */
return;
}
static void show_tex_options(RendererSettingsDialog *self)
{
gtk_widget_show(self->layer_check);
gtk_widget_show(self->standalone_check);
}
static void hide_tex_options(RendererSettingsDialog *self)
{
gtk_widget_hide(self->layer_check);
gtk_widget_hide(self->standalone_check);
}
static void latex_render_callback(GtkToggleButton *radio, RendererSettingsDialog *dialog)
{
if (gtk_toggle_button_get_active(radio))
show_tex_options(dialog);
else
hide_tex_options(dialog);
}
static void renderer_settings_dialog_init(RendererSettingsDialog *self)
{
GtkBuilder *builder;
GtkWidget *box;
GtkDialog *dialog;
dialog = &(self->parent);
builder = gtk_builder_new_from_resource("/dialog.glade");
box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
self->radio_latex = GTK_WIDGET(gtk_builder_get_object(builder, "latex-radio"));
self->radio_cairo = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-radio"));
self->scale = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-scale"));
self->standalone_check = GTK_WIDGET(gtk_builder_get_object(builder, "standalone-check"));
self->layer_check = GTK_WIDGET(gtk_builder_get_object(builder, "layer-check"));
gtk_dialog_add_buttons(dialog, "Cancel", GTK_RESPONSE_CANCEL, "OK", GTK_RESPONSE_OK, NULL);
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), box);
gtk_window_set_title(GTK_WINDOW(self), "Renderer Settings");
g_signal_connect(self->radio_latex, "toggled", G_CALLBACK(latex_render_callback), (gpointer)self);
g_object_unref(builder);
}
RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
{
RendererSettingsDialog *res;
res = RENDERER_SETTINGS_DIALOG(g_object_new(RENDERER_TYPE_SETTINGS_DIALOG, NULL));
if (res && parent) {
gtk_window_set_transient_for(GTK_WINDOW(res), parent);
}
return res;
}
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
{
if (!settings || !dialog)
return;
settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));
settings->renderer = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE ? RENDERER_LATEX_TIKZ : RENDERER_CAIROGRAPHICS);
settings->tex_pdf_layers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->layer_check));
settings->tex_standalone = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->standalone_check));
}
void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
{
if (!settings || !dialog)
return;
gtk_range_set_value(GTK_RANGE(dialog->scale), settings->scale);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->layer_check), settings->tex_pdf_layers);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->standalone_check), settings->tex_standalone);
switch (settings->renderer) {
case RENDERER_LATEX_TIKZ:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_latex), TRUE);
show_tex_options(dialog);
break;
case RENDERER_CAIROGRAPHICS:
hide_tex_options(dialog);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo), TRUE);
break;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 __CONV_SETTINGS_DIALOG_H__
#define __CONV_SETTINGS_DIALOG_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
enum output_renderer {RENDERER_LATEX_TIKZ, RENDERER_CAIROGRAPHICS};
G_DECLARE_FINAL_TYPE(RendererSettingsDialog, renderer_settings_dialog, RENDERER, SETTINGS_DIALOG, GtkDialog)
RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent);
#define RENDERER_TYPE_SETTINGS_DIALOG (renderer_settings_dialog_get_type())
struct render_settings {
double scale;
enum output_renderer renderer;
gboolean tex_pdf_layers;
gboolean tex_standalone;
};
G_END_DECLS
void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings);
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings);
#endif /* __CONV_SETTINGS_DIALOG_H__ */

View File

@@ -38,12 +38,12 @@ typedef struct _LayerElementPriv {
GtkCheckButton *export;
} LayerElementPriv;
typedef struct _LayerElement {
struct _LayerElement {
/* Inheritance */
GtkListBoxRow parent;
/* Custom Elements */
LayerElementPriv priv;
} LayerElement;
};
GtkWidget *layer_element_new(void);