Compare commits
65 Commits
89b34b1326
...
v1.0-rc2
Author | SHA1 | Date | |
---|---|---|---|
a5d794461a | |||
6fb4d39fc8 | |||
d0e1383861 | |||
6296627ac2 | |||
f79bab102b | |||
e5300e60aa | |||
4c5784c3a4 | |||
f765e27ce8 | |||
40760725b8 | |||
dac834aef2 | |||
d4f2d6798e | |||
f8cbf7e066 | |||
59ec0c5a10 | |||
2a615367d7 | |||
3167da4648 | |||
b72466957c | |||
d9f0f3cdd5 | |||
4c04ce3614 | |||
a2bc980c64 | |||
73ea4d6838 | |||
526785cffd | |||
6a8b359f3d | |||
bbd731401d | |||
7734467ea9 | |||
7d66ca1280 | |||
542737622f | |||
221d5a5db5 | |||
a531da26d3 | |||
f913976a44 | |||
da19037211 | |||
3ed83c1146 | |||
9d10b17d7d | |||
ea53890cd0 | |||
88815bc007 | |||
288965af7b | |||
690c1cb5ae | |||
0f4de608a2 | |||
d1a1cb762a | |||
223a2c6e71 | |||
27cb06afe2 | |||
1c4ccd9153 | |||
dc208c6ad3 | |||
8455491c11 | |||
58c7f571f4 | |||
0290a6c9d3 | |||
9b7073604b | |||
f2c58e4520 | |||
c1a7dce0a3 | |||
37a561115a | |||
1ffe677804 | |||
2c3c7a9a80 | |||
da34256b83 | |||
93b726a05f | |||
6c24cebaf7 | |||
084c6999c7 | |||
a261f61c5c | |||
29f66951d1 | |||
9a6aee1410 | |||
4987459337 | |||
1db0ac1d17 | |||
35d10a5a24 | |||
46cc20e878 | |||
17b5848335 | |||
f47c2e52ff | |||
dc748504ad |
10
.buildconfig
Normal file
10
.buildconfig
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[default]
|
||||||
|
name=Default
|
||||||
|
runtime=host
|
||||||
|
config-opts=
|
||||||
|
run-opts=
|
||||||
|
prefix=/home/mari/.cache/gnome-builder/install/gds-render/host
|
||||||
|
app-id=
|
||||||
|
postbuild=
|
||||||
|
prebuild=
|
||||||
|
default=true
|
@@ -2,28 +2,37 @@ cmake_minimum_required(VERSION 2.8)
|
|||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||||
|
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||||
|
|
||||||
project(gds-render)
|
project(gds-render)
|
||||||
|
|
||||||
add_subdirectory(glade)
|
add_subdirectory(glade)
|
||||||
|
|
||||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} "layer-widget")
|
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
|
||||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS})
|
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||||
|
|
||||||
|
|
||||||
aux_source_directory("layer-widget" SUB_SOURCES)
|
aux_source_directory("widgets" LAYER_SOURCES)
|
||||||
set(SOURCE "main.c" "gdsparse.c" "layer-selector.c")
|
aux_source_directory("tree-renderer" RENDERER_SOURCES)
|
||||||
|
aux_source_directory("gds-parser" PARSER_SOURCES)
|
||||||
|
aux_source_directory("latex-output" LATEX_SOURCES)
|
||||||
|
aux_source_directory("cairo-output" CAIRO_SOURCES)
|
||||||
|
set(SOURCE "main.c" "layer-selector.c" "main-window.c")
|
||||||
|
|
||||||
set(SOURCE
|
set(SOURCE
|
||||||
${SOURCE}
|
${SOURCE}
|
||||||
${SUB_SOURCES}
|
${LAYER_SOURCES}
|
||||||
|
${RENDERER_SOURCES}
|
||||||
|
${PARSER_SOURCES}
|
||||||
|
${LATEX_SOURCES}
|
||||||
|
${CAIRO_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_compile_options(-Wall)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
|
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
|
||||||
add_dependencies(${PROJECT_NAME} glib-resources)
|
add_dependencies(${PROJECT_NAME} glib-resources)
|
||||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
|
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
248
cairo-output/cairo-output.c
Normal 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");
|
||||||
|
}
|
30
cairo-output/cairo-output.h
Normal file
30
cairo-output/cairo-output.h
Normal 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__ */
|
@@ -27,12 +27,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "gdsparse.h"
|
#include "gds-parser.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
|
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||||
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
|
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||||
@@ -58,6 +59,8 @@ enum record {
|
|||||||
STRANS = 0x1A01,
|
STRANS = 0x1A01,
|
||||||
BOX = 0x2D00,
|
BOX = 0x2D00,
|
||||||
LAYER = 0x0D02,
|
LAYER = 0x0D02,
|
||||||
|
WIDTH = 0x0F03,
|
||||||
|
PATHTYPE = 0x2102
|
||||||
};
|
};
|
||||||
|
|
||||||
static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
||||||
@@ -83,7 +86,7 @@ static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double gds_convert_double(char *data)
|
static double gds_convert_double(const char *data)
|
||||||
{
|
{
|
||||||
bool sign_bit;
|
bool sign_bit;
|
||||||
int i;
|
int i;
|
||||||
@@ -123,7 +126,7 @@ static double gds_convert_double(char *data)
|
|||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static signed int gds_convert_signed_int(char *data)
|
static signed int gds_convert_signed_int(const char *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -139,7 +142,7 @@ static signed int gds_convert_signed_int(char *data)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int16_t gds_convert_signed_int16(char *data)
|
static int16_t gds_convert_signed_int16(const char *data)
|
||||||
{
|
{
|
||||||
if (!data) {
|
if (!data) {
|
||||||
GDS_ERROR("This should not happen");
|
GDS_ERROR("This should not happen");
|
||||||
@@ -149,7 +152,17 @@ static int16_t gds_convert_signed_int16(char *data)
|
|||||||
(((int16_t)(data[1]) & 0xFF) << 0));
|
(((int16_t)(data[1]) & 0xFF) << 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *append_library(GList *curr_list)
|
static uint16_t gds_convert_unsigend_int16(const char *data)
|
||||||
|
{
|
||||||
|
if (!data) {
|
||||||
|
GDS_ERROR("This should not happen");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (uint16_t)((((uint16_t)(data[0]) & 0xFF) << 8) |
|
||||||
|
(((uint16_t)(data[1]) & 0xFF) << 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||||
{
|
{
|
||||||
struct gds_library *lib;
|
struct gds_library *lib;
|
||||||
|
|
||||||
@@ -161,6 +174,9 @@ static GList *append_library(GList *curr_list)
|
|||||||
lib->cell_names = NULL;
|
lib->cell_names = NULL;
|
||||||
} else
|
} else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (library_ptr)
|
||||||
|
*library_ptr = lib;
|
||||||
|
|
||||||
return g_list_append(curr_list, lib);
|
return g_list_append(curr_list, lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +191,8 @@ static GList *append_graphics(GList *curr_list, enum graphics_type type,
|
|||||||
gfx->layer = 0;
|
gfx->layer = 0;
|
||||||
gfx->vertices = NULL;
|
gfx->vertices = NULL;
|
||||||
gfx->width_absolute = 0;
|
gfx->width_absolute = 0;
|
||||||
gfx->type = type;
|
gfx->gfx_type = type;
|
||||||
|
gfx->path_render_type = PATH_FLUSH;
|
||||||
} else
|
} else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -286,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_cell_instance *inst = (struct gds_cell_instance *)gcell_ref;
|
||||||
struct gds_library *lib = (struct gds_library *)glibrary;
|
struct gds_library *lib = (struct gds_library *)glibrary;
|
||||||
@@ -312,7 +329,7 @@ void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
|
|||||||
GDS_WARN("referenced cell could not be found in library");
|
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;
|
struct gds_cell *cell = (struct gds_cell *)gcell;
|
||||||
|
|
||||||
@@ -323,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;
|
struct gds_library *lib = (struct gds_library *)library_list_item;
|
||||||
|
|
||||||
@@ -331,9 +348,43 @@ void scan_library_references(gpointer library_list_item, gpointer user)
|
|||||||
g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib);
|
g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!access_date || !mod_date) {
|
||||||
|
GDS_WARN("Date structures invalid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length != (2*6*2)) {
|
||||||
|
GDS_WARN("Could not parse date field! Not the specified length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (temp_date = mod_date; 1; temp_date = access_date) {
|
||||||
|
temp_date->year = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
temp_date->month = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
temp_date->day = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
temp_date->hour = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
temp_date->minute = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
temp_date->second = gds_convert_unsigend_int16(buffer);
|
||||||
|
buffer += 2;
|
||||||
|
|
||||||
|
if (temp_date == access_date)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int parse_gds_from_file(const char *filename, GList **library_list)
|
int parse_gds_from_file(const char *filename, GList **library_list)
|
||||||
{
|
{
|
||||||
char workbuff[1024];
|
char *workbuff;
|
||||||
int read;
|
int read;
|
||||||
int i;
|
int i;
|
||||||
int run = 1;
|
int run = 1;
|
||||||
@@ -350,8 +401,14 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
|
|
||||||
lib_list = *library_list;
|
lib_list = *library_list;
|
||||||
|
|
||||||
|
/* Allocate working buffer */
|
||||||
|
workbuff = (char *)malloc(sizeof(char)*128*1024);
|
||||||
|
|
||||||
|
if(!workbuff)
|
||||||
|
return -100;
|
||||||
|
|
||||||
/* open File */
|
/* open File */
|
||||||
gds_file = fopen(filename, "r");
|
gds_file = fopen(filename, "rb");
|
||||||
if (gds_file == NULL) {
|
if (gds_file == NULL) {
|
||||||
GDS_ERROR("Could not open File %s", filename);
|
GDS_ERROR("Could not open File %s", filename);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -374,8 +431,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec_data_length = (uint16_t)((((uint16_t)(workbuff[0])) << 8) |
|
rec_data_length = gds_convert_unsigend_int16(workbuff);
|
||||||
(uint16_t)(workbuff[1]));
|
|
||||||
|
|
||||||
if (rec_data_length < 4) {
|
if (rec_data_length < 4) {
|
||||||
/* Possible Zero-Padding: */
|
/* Possible Zero-Padding: */
|
||||||
@@ -398,13 +454,12 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
GDS_ERROR("Unexpected end of file");
|
GDS_ERROR("Unexpected end of file");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rec_type = (uint16_t)((((uint16_t)(workbuff[0])) << 8) |
|
rec_type = gds_convert_unsigend_int16(workbuff);
|
||||||
(uint16_t)(workbuff[1]));
|
|
||||||
|
|
||||||
/* if begin: Allocate structures */
|
/* if begin: Allocate structures */
|
||||||
switch (rec_type) {
|
switch (rec_type) {
|
||||||
case BGNLIB:
|
case BGNLIB:
|
||||||
lib_list = append_library(lib_list);
|
lib_list = append_library(lib_list, ¤t_lib);
|
||||||
if (lib_list == NULL) {
|
if (lib_list == NULL) {
|
||||||
GDS_ERROR("Allocating memory failed");
|
GDS_ERROR("Allocating memory failed");
|
||||||
run = -3;
|
run = -3;
|
||||||
@@ -412,8 +467,6 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
|
|
||||||
}
|
}
|
||||||
printf("Entering Lib\n");
|
printf("Entering Lib\n");
|
||||||
current_lib = (struct gds_library *)
|
|
||||||
g_list_last(lib_list)->data;
|
|
||||||
break;
|
break;
|
||||||
case ENDLIB:
|
case ENDLIB:
|
||||||
if (current_lib == NULL) {
|
if (current_lib == NULL) {
|
||||||
@@ -455,21 +508,22 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
current_cell = NULL;
|
current_cell = NULL;
|
||||||
printf("Leaving Cell\n");
|
printf("Leaving Cell\n");
|
||||||
break;
|
break;
|
||||||
//case BOX:
|
case BOX:
|
||||||
case BOUNDARY:
|
case BOUNDARY:
|
||||||
if (current_cell == NULL) {
|
if (current_cell == NULL) {
|
||||||
GDS_ERROR("Boundary outside of cell");
|
GDS_ERROR("Boundary/Box outside of cell");
|
||||||
run = -3;
|
run = -3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
current_cell->graphic_objs = append_graphics(current_cell->graphic_objs,
|
current_cell->graphic_objs = append_graphics(current_cell->graphic_objs,
|
||||||
GRAPHIC_POLYGON, ¤t_graphics);
|
(rec_type == BOUNDARY ? GRAPHIC_POLYGON : GRAPHIC_BOX),
|
||||||
|
¤t_graphics);
|
||||||
if (current_cell->graphic_objs == NULL) {
|
if (current_cell->graphic_objs == NULL) {
|
||||||
GDS_ERROR("Memory allocation failed");
|
GDS_ERROR("Memory allocation failed");
|
||||||
run = -4;
|
run = -4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\tEntering boundary\n");
|
printf("\tEntering boundary/Box\n");
|
||||||
break;
|
break;
|
||||||
case SREF:
|
case SREF:
|
||||||
if (current_cell == NULL) {
|
if (current_cell == NULL) {
|
||||||
@@ -505,7 +559,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
case ENDEL:
|
case ENDEL:
|
||||||
if (current_graphics != NULL) {
|
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;
|
current_graphics = NULL;
|
||||||
}
|
}
|
||||||
if (current_s_reference != NULL) {
|
if (current_s_reference != NULL) {
|
||||||
@@ -523,12 +577,17 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MAG:
|
case MAG:
|
||||||
break;
|
break;
|
||||||
case ANGLE:
|
case ANGLE:
|
||||||
break;
|
break;
|
||||||
case STRANS:
|
case STRANS:
|
||||||
break;
|
break;
|
||||||
|
case WIDTH:
|
||||||
|
break;
|
||||||
|
case PATHTYPE:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
|
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
|
||||||
break;
|
break;
|
||||||
@@ -541,12 +600,33 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
read = fread(workbuff, sizeof(char), rec_data_length, gds_file);
|
read = fread(workbuff, sizeof(char), rec_data_length, gds_file);
|
||||||
|
|
||||||
if (read != rec_data_length) {
|
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;
|
run = -5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rec_type) {
|
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, ¤t_lib->mod_time, ¤t_lib->access_time);
|
||||||
|
break;
|
||||||
|
case BGNSTR:
|
||||||
|
gds_parse_date(workbuff, read, ¤t_cell->mod_time, ¤t_cell->access_time);
|
||||||
|
break;
|
||||||
case LIBNAME:
|
case LIBNAME:
|
||||||
name_library(current_lib, read, workbuff);
|
name_library(current_lib, read, workbuff);
|
||||||
break;
|
break;
|
||||||
@@ -582,6 +662,12 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
case SNAME:
|
case SNAME:
|
||||||
name_cell_ref(current_s_reference, read, workbuff);
|
name_cell_ref(current_s_reference, read, workbuff);
|
||||||
break;
|
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:
|
case LAYER:
|
||||||
if (!current_graphics) {
|
if (!current_graphics) {
|
||||||
GDS_WARN("Layer has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
|
GDS_WARN("Layer has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
|
||||||
@@ -621,6 +707,18 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
printf("\t\tAngle defined: %lf\n", current_s_reference->angle);
|
printf("\t\tAngle defined: %lf\n", current_s_reference->angle);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PATHTYPE:
|
||||||
|
if (current_graphics == NULL) {
|
||||||
|
GDS_WARN("Path type defined outside of path. Ignoring");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (current_graphics->gfx_type == GRAPHIC_PATH) {
|
||||||
|
current_graphics->path_render_type = (int)gds_convert_signed_int16(workbuff);
|
||||||
|
printf("\t\tPathtype: %d\n", current_graphics->path_render_type);
|
||||||
|
} else {
|
||||||
|
GDS_WARN("Path type defined inside non-path graphics object. Ignoring");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,10 +727,18 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
|||||||
fclose(gds_file);
|
fclose(gds_file);
|
||||||
|
|
||||||
|
|
||||||
/* Iterate and find references to cells */
|
if (!run) {
|
||||||
g_list_foreach(lib_list, scan_library_references, NULL);
|
/* Iterate and find references to cells */
|
||||||
|
g_list_foreach(lib_list, scan_library_references, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*library_list = lib_list;
|
*library_list = lib_list;
|
||||||
|
|
||||||
|
free(workbuff);
|
||||||
|
|
||||||
return run;
|
return run;
|
||||||
}
|
}
|
||||||
|
|
@@ -20,60 +20,8 @@
|
|||||||
#ifndef __GDSPARSE_H__
|
#ifndef __GDSPARSE_H__
|
||||||
#define __GDSPARSE_H__
|
#define __GDSPARSE_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include "gds-types.h"
|
||||||
#define CELL_NAME_MAX (100)
|
|
||||||
|
|
||||||
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1};
|
|
||||||
|
|
||||||
struct gds_time_field {
|
|
||||||
uint16_t year;
|
|
||||||
uint16_t month;
|
|
||||||
uint16_t day;
|
|
||||||
uint16_t hour;
|
|
||||||
uint16_t minute;
|
|
||||||
uint16_t second;
|
|
||||||
};
|
|
||||||
struct gds_point {
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gds_graphics {
|
|
||||||
enum graphics_type type;
|
|
||||||
GList *vertices;
|
|
||||||
unsigned int path_width;
|
|
||||||
int width_absolute;
|
|
||||||
int16_t layer;
|
|
||||||
uint16_t datatype;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gds_cell_instance {
|
|
||||||
char ref_name[CELL_NAME_MAX];
|
|
||||||
struct gds_cell *cell_ref;
|
|
||||||
struct gds_point origin;
|
|
||||||
int flipped;
|
|
||||||
double angle;
|
|
||||||
double magnification;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gds_cell {
|
|
||||||
char name[CELL_NAME_MAX];
|
|
||||||
struct gds_time_field mod_time;
|
|
||||||
struct gds_time_field access_time;
|
|
||||||
GList *child_cells;
|
|
||||||
GList *graphic_objs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gds_library {
|
|
||||||
char name[CELL_NAME_MAX];
|
|
||||||
struct gds_time_field time;
|
|
||||||
double unit_to_meters;
|
|
||||||
GList *cells;
|
|
||||||
GList *cell_names;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int parse_gds_from_file(const char *filename, GList **library_array);
|
int parse_gds_from_file(const char *filename, GList **library_array);
|
||||||
int clear_lib_list(GList **library_list);
|
int clear_lib_list(GList **library_list);
|
63
gds-parser/gds-types.h
Normal file
63
gds-parser/gds-types.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef __GDS_TYPES_H__
|
||||||
|
#define __GDS_TYPES_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#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, GRAPHIC_BOX};
|
||||||
|
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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__ */
|
@@ -1,8 +1,6 @@
|
|||||||
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
|
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
|
||||||
add_custom_command(DEPENDS
|
add_custom_command(DEPENDS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources.xml
|
${CMAKE_CURRENT_SOURCE_DIR}/*.glade
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/main.glade
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/layer-widget.glade
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/resources.c
|
${CMAKE_CURRENT_BINARY_DIR}/resources.c
|
||||||
COMMAND
|
COMMAND
|
||||||
|
43
glade/about.glade
Normal file
43
glade/about.glade
Normal 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 <mario.huettel@gmx.net></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
90
glade/dialog.glade
Normal 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>
|
@@ -12,6 +12,24 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="spacing">3</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>
|
<child>
|
||||||
<object class="GtkLabel" id="layer">
|
<object class="GtkLabel" id="layer">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -21,7 +39,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">0</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -36,7 +54,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">1</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -50,7 +68,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">2</property>
|
<property name="position">3</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -61,7 +79,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">3</property>
|
<property name="position">4</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
162
glade/main.glade
162
glade/main.glade
@@ -3,9 +3,8 @@
|
|||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.20"/>
|
<requires lib="gtk+" version="3.20"/>
|
||||||
<object class="GtkWindow" id="main-window">
|
<object class="GtkWindow" id="main-window">
|
||||||
<property name="visible">True</property>
|
<property name="height_request">250</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<signal name="delete-event" handler="on_window_close" swapped="no"/>
|
|
||||||
<child type="titlebar">
|
<child type="titlebar">
|
||||||
<object class="GtkHeaderBar">
|
<object class="GtkHeaderBar">
|
||||||
<property name="name">header</property>
|
<property name="name">header</property>
|
||||||
@@ -15,57 +14,66 @@
|
|||||||
<property name="subtitle" translatable="yes">GDSII to PDF Converter</property>
|
<property name="subtitle" translatable="yes">GDSII to PDF Converter</property>
|
||||||
<property name="show_close_button">True</property>
|
<property name="show_close_button">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkButton" id="button-load-gds">
|
||||||
|
<property name="label">gtk-open</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">True</property>
|
||||||
<child>
|
<property name="receives_default">True</property>
|
||||||
<object class="GtkButton" id="button-load-gds">
|
<property name="use_stock">True</property>
|
||||||
<property name="label">gtk-open</property>
|
<property name="always_show_image">True</property>
|
||||||
<property name="visible">True</property>
|
<style>
|
||||||
<property name="can_focus">True</property>
|
<class name="suggested-action"/>
|
||||||
<property name="receives_default">True</property>
|
</style>
|
||||||
<property name="use_stock">True</property>
|
|
||||||
<property name="always_show_image">True</property>
|
|
||||||
<style>
|
|
||||||
<class name="suggested-action"/>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="button-load-mapping">
|
|
||||||
<property name="label" translatable="yes">Load Mapping</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="sensitive">False</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">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>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">3</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</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="suggested-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>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -73,15 +81,23 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkTreeView" id="cell-tree">
|
<object class="GtkScrolledWindow">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<child internal-child="selection">
|
<property name="hscrollbar_policy">never</property>
|
||||||
<object class="GtkTreeSelection"/>
|
<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>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">True</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
@@ -90,6 +106,7 @@
|
|||||||
<object class="GtkScrolledWindow">
|
<object class="GtkScrolledWindow">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hscrollbar_policy">never</property>
|
||||||
<property name="shadow_type">in</property>
|
<property name="shadow_type">in</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkViewport">
|
<object class="GtkViewport">
|
||||||
@@ -111,43 +128,6 @@
|
|||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</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>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@@ -2,7 +2,9 @@
|
|||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/">
|
<gresource prefix="/">
|
||||||
<file compressed="true">main.glade</file>
|
<file compressed="true">main.glade</file>
|
||||||
|
<file compressed="true">about.glade</file>
|
||||||
<file>layer-widget.glade</file>
|
<file>layer-widget.glade</file>
|
||||||
|
<file>dialog.glade</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|
||||||
|
240
latex-output/latex-output.c
Normal file
240
latex-output/latex-output.c
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* 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, double scale)
|
||||||
|
{
|
||||||
|
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 || 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)/scale, ((double)pt->y)/scale);
|
||||||
|
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 = PATH_FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_printf(buffer, "\\draw[line width=%lf pt, draw={c%d}, opacity={%lf}, cap=%s] ",
|
||||||
|
gfx->width_absolute/scale, 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)/scale,
|
||||||
|
((double)pt->y)/scale,
|
||||||
|
(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, 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, 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)/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=%lf, xscale=%lf]\n", (inst->flipped ? -1*inst->magnification : inst->magnification),
|
||||||
|
inst->magnification);
|
||||||
|
WRITEOUT_BUFFER(buffer);
|
||||||
|
|
||||||
|
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale);
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
|
||||||
|
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\\testmode%s\n",
|
||||||
|
(standalone_document ? "true" : "false"));
|
||||||
|
WRITEOUT_BUFFER(working_line);
|
||||||
|
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);
|
||||||
|
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, scale);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
33
latex-output/latex-output.h
Normal file
33
latex-output/latex-output.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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 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__ */
|
185
layer-selector.c
185
layer-selector.c
@@ -18,71 +18,95 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "layer-selector.h"
|
#include "layer-selector.h"
|
||||||
#include "gdsparse.h"
|
#include "gds-parser/gds-parser.h"
|
||||||
|
#include "widgets/layer-element.h"
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static GList *layer_widgets = NULL;
|
static GtkWidget *global_load_button;
|
||||||
static GtkWidget *load_button;
|
static GtkWidget *global_save_button;
|
||||||
static GtkWidget *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)
|
if (info)
|
||||||
free(inf);
|
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 */
|
row_list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
|
||||||
if (*info_list != NULL) {
|
|
||||||
g_list_free_full(*info_list, (GDestroyNotify)layer_list_remove_element);
|
/* Iterate through widgets and add layers that shall be exported */
|
||||||
*info_list = NULL;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return info_list;
|
||||||
|
|
||||||
*info_list = local_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void delete_layer_widget(GtkWidget *widget)
|
|
||||||
{
|
|
||||||
|
|
||||||
gtk_widget_destroy(widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_list_box_widgets(GtkListBox *box)
|
void clear_list_box_widgets(GtkListBox *box)
|
||||||
{
|
{
|
||||||
GList *list;
|
GList *list;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
list = gtk_container_get_children(GTK_CONTAINER(box));
|
list = gtk_container_get_children(GTK_CONTAINER(box));
|
||||||
for (;list != NULL; list = list->next) {
|
for (temp = list; temp != NULL; temp = temp->next) {
|
||||||
gtk_container_remove(GTK_CONTAINER(box), GTK_WIDGET(list->data));
|
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 */
|
/* 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 */
|
/* Deactivate buttons */
|
||||||
gtk_widget_set_sensitive(load_button, FALSE);
|
gtk_widget_set_sensitive(global_load_button, FALSE);
|
||||||
gtk_widget_set_sensitive(save_button, FALSE);
|
gtk_widget_set_sensitive(global_save_button, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean check_if_layer_widget_exists(int layer) {
|
static gboolean check_if_layer_widget_exists(int layer) {
|
||||||
GList *list;
|
GList *list;
|
||||||
|
GList *temp;
|
||||||
LayerElement *widget;
|
LayerElement *widget;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
for (list = layer_widgets; list != NULL; list = list->next) {
|
list = gtk_container_get_children(GTK_CONTAINER(global_list_box));
|
||||||
widget = (LayerElement *)list->data;
|
|
||||||
|
for (temp = list; temp != NULL; temp = temp->next) {
|
||||||
|
widget = LAYER_ELEMENT(temp->data);
|
||||||
if (layer_element_get_layer(widget) == layer) {
|
if (layer_element_get_layer(widget) == layer) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_list_free(list);
|
||||||
|
|
||||||
return ret;
|
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);
|
layer_element_set_layer(LAYER_ELEMENT(le), layer);
|
||||||
gtk_list_box_insert(listbox, le, -1);
|
gtk_list_box_insert(listbox, le, -1);
|
||||||
gtk_widget_show(le);
|
gtk_widget_show(le);
|
||||||
layer_widgets = g_list_append(layer_widgets, le);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
||||||
{
|
{
|
||||||
GList *children1, *children2;
|
|
||||||
LayerElement *le1, *le2;
|
LayerElement *le1, *le2;
|
||||||
gint ret;
|
gint ret;
|
||||||
|
|
||||||
children1 = gtk_container_get_children(GTK_CONTAINER(row1));
|
le1 = LAYER_ELEMENT(row1);
|
||||||
children2 = gtk_container_get_children(GTK_CONTAINER(row2));
|
le2 = LAYER_ELEMENT(row2);
|
||||||
le1 = LAYER_ELEMENT(children1->data);
|
|
||||||
le2 = LAYER_ELEMENT(children2->data);
|
|
||||||
|
|
||||||
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
|
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
|
||||||
|
|
||||||
g_list_free(children1);
|
|
||||||
g_list_free(children2);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,8 +146,10 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
|||||||
{
|
{
|
||||||
GList *cell_list = NULL;
|
GList *cell_list = NULL;
|
||||||
struct gds_library *lib;
|
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);
|
gtk_list_box_set_sort_func(listbox, sort_func, NULL, NULL);
|
||||||
|
|
||||||
for (; libs != NULL; libs = libs->next) {
|
for (; libs != NULL; libs = libs->next) {
|
||||||
@@ -144,9 +162,12 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
|||||||
/* Force sort */
|
/* Force sort */
|
||||||
gtk_list_box_invalidate_sort(listbox);
|
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 */
|
/* Activate Buttons */
|
||||||
gtk_widget_set_sensitive(load_button, TRUE);
|
gtk_widget_set_sensitive(global_load_button, TRUE);
|
||||||
gtk_widget_set_sensitive(save_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)) {
|
if (g_match_info_matches(mi)) {
|
||||||
/* Line is valid */
|
/* Line is valid */
|
||||||
match = g_match_info_fetch_named(mi, "layer");
|
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);
|
g_free(match);
|
||||||
match = g_match_info_fetch_named(mi, "r");
|
match = g_match_info_fetch_named(mi, "r");
|
||||||
color->red = g_ascii_strtod(match, NULL);
|
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;
|
LayerElement *ret = NULL;
|
||||||
|
for (; el_list != NULL; el_list = el_list->next) {
|
||||||
for (le_found = NULL; list != NULL; list = list->next) {
|
if (layer_element_get_layer(LAYER_ELEMENT(el_list->data)) == layer) {
|
||||||
temp = LAYER_ELEMENT(list->data);
|
ret = LAYER_ELEMENT(el_list->data);
|
||||||
if (layer_element_get_layer(temp) == layer) {
|
|
||||||
le_found = temp;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
return le_found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void load_layer_mapping_from_file(gchar *file_name)
|
static void load_layer_mapping_from_file(gchar *file_name)
|
||||||
{
|
{
|
||||||
GFile *file;
|
GFile *file;
|
||||||
GFileInputStream *stream;
|
GFileInputStream *stream;
|
||||||
GDataInputStream *dstream;
|
GDataInputStream *dstream;
|
||||||
|
|
||||||
LayerElement *le;
|
LayerElement *le;
|
||||||
char *name;
|
char *name;
|
||||||
gboolean export;
|
gboolean export;
|
||||||
int layer;
|
int layer;
|
||||||
GdkRGBA color;
|
GdkRGBA color;
|
||||||
int result;
|
int result;
|
||||||
|
GList *rows;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
file = g_file_new_for_path(file_name);
|
file = g_file_new_for_path(file_name);
|
||||||
stream = g_file_read(file, NULL, NULL);
|
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));
|
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) {
|
while((result = load_csv_line(dstream, &export, &name, &layer, &color)) >= 0) {
|
||||||
/* skip broken line */
|
/* skip broken line */
|
||||||
if (result == 1)
|
if (result == 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* search for layer widget */
|
/* Add rows in the same order as in file */
|
||||||
if (le = find_layer_in_list(layer_widgets, layer)) {
|
if ((le = find_layer_element_in_list(rows, layer))) {
|
||||||
layer_element_set_name(le, name);
|
gtk_list_box_insert(global_list_box, GTK_WIDGET(le), -1);
|
||||||
|
|
||||||
layer_element_set_color(le, &color);
|
layer_element_set_color(le, &color);
|
||||||
layer_element_set_export(le, export);
|
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 */
|
/* read line */
|
||||||
g_object_unref(dstream);
|
g_object_unref(dstream);
|
||||||
g_object_unref(stream);
|
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);
|
layer_element_get_color(layer_element, &color);
|
||||||
|
|
||||||
/* print values to line */
|
/* 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);
|
color.blue, color.alpha, (export == TRUE ? 1 : 0), name);
|
||||||
|
|
||||||
if (string->len > (max_len-1)) {
|
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);
|
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;
|
FILE *file;
|
||||||
char workbuff[512];
|
char workbuff[512];
|
||||||
GList *le_list;
|
GList *le_list;
|
||||||
|
GList *temp;
|
||||||
|
|
||||||
/* Overwrite existing file */
|
/* Overwrite existing file */
|
||||||
file = fopen((const char *)file_name, "w");
|
file = fopen((const char *)file_name, "w");
|
||||||
|
|
||||||
/* File format is CSV: <Layer>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
|
le_list = gtk_container_get_children(GTK_CONTAINER(list_box));
|
||||||
for (le_list = layer_widgets; le_list != NULL; le_list = le_list->next) {
|
|
||||||
|
/* 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 */
|
/* To be sure it is a valid string */
|
||||||
workbuff[0] = 0;
|
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);
|
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_list_free(le_list);
|
||||||
|
|
||||||
/* Save File */
|
/* Save File */
|
||||||
fflush(file);
|
fflush(file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -364,7 +415,7 @@ static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
|
|||||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
if (res == GTK_RESPONSE_ACCEPT) {
|
if (res == GTK_RESPONSE_ACCEPT) {
|
||||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
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);
|
g_free(file_name);
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(dialog);
|
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)
|
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
||||||
{
|
{
|
||||||
g_object_ref(G_OBJECT(button));
|
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);
|
g_signal_connect(button, "clicked", G_CALLBACK(load_mapping_clicked), main_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
||||||
{
|
{
|
||||||
g_object_ref(G_OBJECT(button));
|
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);
|
g_signal_connect(button, "clicked", G_CALLBACK(save_mapping_clicked), main_window);
|
||||||
}
|
}
|
||||||
|
@@ -22,21 +22,19 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <layer-element.h>
|
|
||||||
|
|
||||||
struct layer_info {
|
struct layer_info
|
||||||
int id;
|
{
|
||||||
/* This contains both: opacity and Color */
|
int layer;
|
||||||
GdkRGBA color;
|
char *name;
|
||||||
|
int stacked_position; ///< Lower is bottom, higher is top
|
||||||
|
GdkRGBA color;
|
||||||
};
|
};
|
||||||
|
|
||||||
void generate_layer_widgets(GtkListBox *listbox, GList *libs);
|
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_load_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||||
|
GList *export_rendered_layer_info();
|
||||||
void get_layer_info(GList **info_list, GtkListBox *box);
|
void delete_layer_info_struct(struct layer_info *info);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __LAYER_SELECTOR_H__ */
|
#endif /* __LAYER_SELECTOR_H__ */
|
||||||
|
@@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* GDSII-Converter
|
|
||||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
|
||||||
*
|
|
||||||
* This file is part of GDSII-Converter.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "layer-element.h"
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_BOX)
|
|
||||||
|
|
||||||
|
|
||||||
static void layer_element_dispose(GObject *obj)
|
|
||||||
{
|
|
||||||
/* destroy parent container. This destroys all widgets inside */
|
|
||||||
G_OBJECT_CLASS(layer_element_parent_class)->dispose(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void layer_element_class_init(LayerElementClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
|
||||||
oclass->dispose = layer_element_dispose;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* 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"));
|
|
||||||
|
|
||||||
/* Connect signals */
|
|
||||||
/* None */
|
|
||||||
|
|
||||||
g_object_unref(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *layer_element_new(void)
|
|
||||||
{
|
|
||||||
return GTK_WIDGET(g_object_new(layer_element_get_type(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *layer_element_get_name(LayerElement *elem)
|
|
||||||
{
|
|
||||||
return gtk_entry_get_text(elem->priv.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_element_set_name(LayerElement *elem, const char* name)
|
|
||||||
{
|
|
||||||
gtk_entry_set_text(elem->priv.name, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_element_set_layer(LayerElement *elem, int layer)
|
|
||||||
{
|
|
||||||
GString *string;
|
|
||||||
|
|
||||||
string = g_string_new_len(NULL, 100);
|
|
||||||
g_string_printf(string, "Layer: %3d", layer);
|
|
||||||
gtk_label_set_text(elem->priv.layer, (const gchar *)string->str);
|
|
||||||
elem->priv.layer_num = layer;
|
|
||||||
g_string_free(string, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int layer_element_get_layer(LayerElement *elem)
|
|
||||||
{
|
|
||||||
return elem->priv.layer_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_element_set_export(LayerElement *elem, gboolean export)
|
|
||||||
{
|
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->priv.export), export);
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean layer_element_get_export(LayerElement *elem)
|
|
||||||
{
|
|
||||||
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->priv.export));
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
|
|
||||||
{
|
|
||||||
if (!rgba)
|
|
||||||
return;
|
|
||||||
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
|
||||||
}
|
|
||||||
|
|
||||||
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
|
|
||||||
{
|
|
||||||
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
|
||||||
}
|
|
316
main-window.c
Normal file
316
main-window.c
Normal 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
27
main-window.h
Normal 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_ */
|
200
main.c
200
main.c
@@ -18,175 +18,85 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "gdsparse.h"
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <layer-element.h>
|
#include "main-window.h"
|
||||||
#include "layer-selector.h"
|
|
||||||
|
|
||||||
|
struct application_data {
|
||||||
enum cell_store_columns {
|
GtkApplication *app;
|
||||||
LIBRARY,
|
|
||||||
CELL,
|
|
||||||
STORE_COLUMN
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct open_button_data {
|
|
||||||
GtkWindow *main_window;
|
GtkWindow *main_window;
|
||||||
GList **list_ptr;
|
|
||||||
GtkTreeStore *cell_store;
|
|
||||||
GtkListBox *layer_box;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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));
|
struct application_data *appdata = (struct application_data *)user_data;
|
||||||
gtk_main_quit();
|
gtk_widget_destroy(GTK_WIDGET(appdata->main_window));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||||
|
|
||||||
void on_load_gds(gpointer button, gpointer user)
|
|
||||||
{
|
{
|
||||||
GList *cell;
|
GtkBuilder *builder;
|
||||||
GtkTreeIter libiter;
|
GtkDialog *dialog;
|
||||||
GtkTreeIter celliter;
|
struct application_data *appdata = (struct application_data *)user_data;
|
||||||
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;
|
|
||||||
|
|
||||||
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", ptr->main_window, GTK_FILE_CHOOSER_ACTION_OPEN,
|
builder = gtk_builder_new_from_resource("/about.glade");
|
||||||
"Cancel", GTK_RESPONSE_CANCEL, "Open GDSII", GTK_RESPONSE_ACCEPT, NULL);
|
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
|
||||||
file_chooser = GTK_FILE_CHOOSER(open_dialog);
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), appdata->main_window);
|
||||||
/* Add GDS II Filter */
|
gtk_dialog_run(dialog);
|
||||||
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));
|
gtk_widget_destroy(dialog);
|
||||||
|
g_object_unref(builder);
|
||||||
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);
|
|
||||||
gtk_tree_store_set (store, &libiter, LIBRARY, gds_lib->name, -1);
|
|
||||||
for (cell = gds_lib->cells; cell != NULL; cell = cell->next) {
|
|
||||||
gds_c = (struct gds_cell *)cell->data;
|
|
||||||
gtk_tree_store_append (store, &celliter, &libiter);
|
|
||||||
gtk_tree_store_set (store, &celliter, CELL, gds_c->name, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_convert_clicked(gpointer button, gpointer user)
|
const GActionEntry app_actions[] = {
|
||||||
|
{ "quit", app_quit },
|
||||||
|
{ "about", app_about }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gapp_activate(GApplication *app, gpointer user_data)
|
||||||
{
|
{
|
||||||
printf("convert\n");
|
GtkWindow *main_window;
|
||||||
}
|
struct application_data *appdata = (struct application_data *)user_data;
|
||||||
|
|
||||||
static GtkTreeStore * setup_cell_selector(GtkTreeView* view)
|
main_window = create_main_window();
|
||||||
{
|
appdata->main_window = main_window;
|
||||||
GtkTreeStore *cell_store;
|
gtk_application_add_window(GTK_APPLICATION(app), main_window);
|
||||||
|
gtk_widget_show(GTK_WIDGET(main_window));
|
||||||
GtkCellRenderer *render;
|
|
||||||
GtkTreeViewColumn *column;
|
|
||||||
|
|
||||||
cell_store = gtk_tree_store_new(STORE_COLUMN, G_TYPE_STRING, G_TYPE_STRING);
|
|
||||||
gtk_tree_view_set_model(view, GTK_TREE_MODEL(cell_store));
|
|
||||||
|
|
||||||
render = gtk_cell_renderer_text_new();
|
|
||||||
column = gtk_tree_view_column_new_with_attributes("Library", render, "text", LIBRARY, NULL);
|
|
||||||
gtk_tree_view_append_column(view, column);
|
|
||||||
|
|
||||||
column = gtk_tree_view_column_new_with_attributes("Cell", render, "text", CELL, NULL);
|
|
||||||
gtk_tree_view_append_column(view, column);
|
|
||||||
|
|
||||||
return cell_store;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
GtkBuilder *main_builder;
|
GtkApplication *gapp;
|
||||||
GList *gds_libs = NULL;
|
int app_status;
|
||||||
GtkTreeView *cell_tree;
|
struct application_data appdata;
|
||||||
GtkTreeStore *cell_store;
|
GMenu *menu;
|
||||||
GtkWidget *widget_generic;
|
GMenu *m_quit;
|
||||||
GtkWidget *layer;
|
GMenu *m_about;
|
||||||
GtkWidget *listbox;
|
|
||||||
|
|
||||||
struct open_button_data open_data;
|
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
|
||||||
|
g_application_register(G_APPLICATION(gapp), NULL, NULL);
|
||||||
gtk_init(&argc, &argv);
|
//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);
|
||||||
main_builder = gtk_builder_new_from_resource("/main.glade");
|
|
||||||
gtk_builder_connect_signals(main_builder, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cell_tree = (GtkTreeView *)gtk_builder_get_object(main_builder, "cell-tree");
|
menu = g_menu_new();
|
||||||
cell_store = setup_cell_selector(cell_tree);
|
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;
|
app_status = g_application_run (G_APPLICATION(gapp), argc, argv);
|
||||||
open_data.list_ptr = &gds_libs;
|
g_object_unref (gapp);
|
||||||
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);
|
|
||||||
|
|
||||||
|
return app_status;
|
||||||
/* 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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
gtk_main();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
2
test-data/.gitignore
vendored
Normal file
2
test-data/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.log
|
||||||
|
*.aux
|
2
test-data/polygon+path/layer-mapping.map
Normal file
2
test-data/polygon+path/layer-mapping.map
Normal 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
|
BIN
test-data/polygon+path/path.gds
Normal file
BIN
test-data/polygon+path/path.gds
Normal file
Binary file not shown.
BIN
test-data/polygon+path/path.pdf
Normal file
BIN
test-data/polygon+path/path.pdf
Normal file
Binary file not shown.
56
test-data/polygon+path/path.tex
Normal file
56
test-data/polygon+path/path.tex
Normal 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
|
2
test-data/polygon-only/layer-mapping.map
Normal file
2
test-data/polygon-only/layer-mapping.map
Normal 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
|
BIN
test-data/polygon-only/test.gds
Normal file
BIN
test-data/polygon-only/test.gds
Normal file
Binary file not shown.
BIN
test-data/polygon-only/test.pdf
Normal file
BIN
test-data/polygon-only/test.pdf
Normal file
Binary file not shown.
16229
test-data/polygon-only/test.tex
Normal file
16229
test-data/polygon-only/test.tex
Normal file
File diff suppressed because one or more lines are too long
99
tree-renderer/lib-cell-renderer.c
Normal file
99
tree-renderer/lib-cell-renderer.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib-cell-renderer.h"
|
||||||
|
#include "../gds-parser/gds-types.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_LIB = 1,
|
||||||
|
PROP_CELL,
|
||||||
|
PROP_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
void lib_cell_renderer_init(LibCellRenderer *self)
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lib_cell_renderer_constructed(GObject *obj)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS(lib_cell_renderer_parent_class)->constructed(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lib_cell_renderer_set_property(GObject *object,
|
||||||
|
guint param_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GValue val = G_VALUE_INIT;
|
||||||
|
|
||||||
|
g_value_init(&val, G_TYPE_STRING);
|
||||||
|
|
||||||
|
switch (param_id) {
|
||||||
|
case PROP_LIB:
|
||||||
|
g_value_set_string(&val, ((struct gds_library *)g_value_get_pointer(value))->name);
|
||||||
|
g_object_set_property(object, "text", &val);
|
||||||
|
break;
|
||||||
|
case PROP_CELL:
|
||||||
|
g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name);
|
||||||
|
g_object_set_property(object, "text", &val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lib_cell_renderer_get_property(GObject *object,
|
||||||
|
guint param_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (param_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GParamSpec *properties [PROP_COUNT];
|
||||||
|
|
||||||
|
void lib_cell_renderer_class_init(LibCellRendererClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
|
oclass->constructed = lib_cell_renderer_constructed;
|
||||||
|
oclass->set_property = lib_cell_renderer_set_property;
|
||||||
|
oclass->get_property = lib_cell_renderer_get_property;
|
||||||
|
|
||||||
|
properties[PROP_LIB] = g_param_spec_pointer("gds-lib", "gds-lib",
|
||||||
|
"Library reference to be displayed",
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
properties[PROP_CELL] = g_param_spec_pointer("gds-cell", "gds-cell",
|
||||||
|
"Cell reference to be displayed",
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
|
||||||
|
g_object_class_install_properties(oclass, PROP_COUNT, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkCellRenderer *lib_cell_renderer_new()
|
||||||
|
{
|
||||||
|
return GTK_CELL_RENDERER(g_object_new(TYPE_LIB_CELL_RENDERER, NULL));
|
||||||
|
}
|
41
tree-renderer/lib-cell-renderer.h
Normal file
41
tree-renderer/lib-cell-renderer.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIB_CELL_RENDERER_H__
|
||||||
|
#define __LIB_CELL_RENDERER_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE(LibCellRenderer, lib_cell_renderer, LIB_CELL, RENDERER, GtkCellRendererText)
|
||||||
|
#define TYPE_LIB_CELL_RENDERER (lib_cell_renderer_get_type())
|
||||||
|
|
||||||
|
typedef struct _LibCellRenderer {
|
||||||
|
/* Inheritance */
|
||||||
|
GtkCellRendererText super;
|
||||||
|
/* Custom Elements */
|
||||||
|
} LibCellRenderer;
|
||||||
|
|
||||||
|
GType lib_cell_renderer_get_type(void);
|
||||||
|
GtkCellRenderer *lib_cell_renderer_new(void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __LIB_CELL_RENDERER_H__ */
|
79
tree-renderer/tree-store.c
Normal file
79
tree-renderer/tree-store.c
Normal 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;
|
||||||
|
}
|
16
tree-renderer/tree-store.h
Normal file
16
tree-renderer/tree-store.h
Normal 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__ */
|
128
widgets/conv-settings-dialog.c
Normal file
128
widgets/conv-settings-dialog.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
48
widgets/conv-settings-dialog.h
Normal file
48
widgets/conv-settings-dialog.h
Normal 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__ */
|
189
widgets/layer-element.c
Normal file
189
widgets/layer-element.c
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* GDSII-Converter
|
||||||
|
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of GDSII-Converter.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "layer-element.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
|
||||||
|
|
||||||
|
static void layer_element_dispose(GObject *obj)
|
||||||
|
{
|
||||||
|
/* destroy parent container. This destroys all widgets inside */
|
||||||
|
G_OBJECT_CLASS(layer_element_parent_class)->dispose(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_element_constructed(GObject *obj)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS(layer_element_parent_class)->constructed(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_element_class_init(LayerElementClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||||
|
oclass->dispose = layer_element_dispose;
|
||||||
|
oclass->constructed = layer_element_constructed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkTargetEntry entries[] = {
|
||||||
|
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void layer_element_drag_begin(GtkWidget *widget,
|
||||||
|
GdkDragContext *context,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *row;
|
||||||
|
GtkAllocation alloc;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
|
||||||
|
gtk_widget_get_allocation (row, &alloc);
|
||||||
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
|
||||||
|
cr = cairo_create (surface);
|
||||||
|
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (row), "drag-icon");
|
||||||
|
gtk_widget_draw (row, cr);
|
||||||
|
gtk_style_context_remove_class (gtk_widget_get_style_context (row), "drag-icon");
|
||||||
|
|
||||||
|
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
|
||||||
|
cairo_surface_set_device_offset (surface, -x, -y);
|
||||||
|
gtk_drag_set_icon_surface (context, surface);
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_element_drag_data_get(GtkWidget *widget,
|
||||||
|
GdkDragContext *context,
|
||||||
|
GtkSelectionData *selection_data,
|
||||||
|
guint info,
|
||||||
|
guint time,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
gtk_selection_data_set(selection_data, gdk_atom_intern_static_string("GTK_LIST_BOX_ROW"),
|
||||||
|
32, (const guchar *)&widget, sizeof(gpointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_element_drag_data_received(GtkWidget *widget,
|
||||||
|
GdkDragContext *context,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
GtkSelectionData *selection_data,
|
||||||
|
guint info,
|
||||||
|
guint32 time,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *target;
|
||||||
|
GtkWidget *row;
|
||||||
|
GtkWidget *source;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
target = widget;
|
||||||
|
|
||||||
|
pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (target));
|
||||||
|
row = (gpointer) *(gpointer *)gtk_selection_data_get_data (selection_data);
|
||||||
|
source = gtk_widget_get_ancestor (row, GTK_TYPE_LIST_BOX_ROW);
|
||||||
|
|
||||||
|
if (source == target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_ref (source);
|
||||||
|
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (source)), source);
|
||||||
|
gtk_list_box_insert (GTK_LIST_BOX (gtk_widget_get_parent (target)), source, pos);
|
||||||
|
g_object_unref (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_element_init(LayerElement *self)
|
||||||
|
{
|
||||||
|
GtkBuilder *builder;
|
||||||
|
GtkWidget *glade_box;
|
||||||
|
builder = gtk_builder_new_from_resource("/layer-widget.glade");
|
||||||
|
glade_box = GTK_WIDGET(gtk_builder_get_object(builder, "box"));
|
||||||
|
gtk_container_add(GTK_CONTAINER(self), glade_box);
|
||||||
|
|
||||||
|
/* Get Elements */
|
||||||
|
self->priv.color = GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "color"));
|
||||||
|
self->priv.export = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "export"));
|
||||||
|
self->priv.layer = GTK_LABEL(gtk_builder_get_object(builder, "layer"));
|
||||||
|
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
|
||||||
|
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
|
||||||
|
|
||||||
|
/* Setup drag and drop */
|
||||||
|
gtk_drag_source_set(GTK_WIDGET(self->priv.event_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
|
||||||
|
g_signal_connect(self->priv.event_handle, "drag-begin", G_CALLBACK(layer_element_drag_begin), NULL);
|
||||||
|
g_signal_connect(self->priv.event_handle, "drag-data-get", G_CALLBACK(layer_element_drag_data_get), NULL);
|
||||||
|
gtk_drag_dest_set(GTK_WIDGET(self), GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_MOVE);
|
||||||
|
g_signal_connect(GTK_WIDGET(self), "drag-data-received", G_CALLBACK(layer_element_drag_data_received), NULL);
|
||||||
|
|
||||||
|
g_object_unref(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *layer_element_new(void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET(g_object_new(TYPE_LAYER_ELEMENT, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *layer_element_get_name(LayerElement *elem)
|
||||||
|
{
|
||||||
|
return gtk_entry_get_text(elem->priv.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_element_set_name(LayerElement *elem, const char* name)
|
||||||
|
{
|
||||||
|
gtk_entry_set_text(elem->priv.name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_element_set_layer(LayerElement *elem, int layer)
|
||||||
|
{
|
||||||
|
GString *string;
|
||||||
|
|
||||||
|
string = g_string_new_len(NULL, 100);
|
||||||
|
g_string_printf(string, "Layer: %d", layer);
|
||||||
|
gtk_label_set_text(elem->priv.layer, (const gchar *)string->str);
|
||||||
|
elem->priv.layer_num = layer;
|
||||||
|
g_string_free(string, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int layer_element_get_layer(LayerElement *elem)
|
||||||
|
{
|
||||||
|
return elem->priv.layer_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_element_set_export(LayerElement *elem, gboolean export)
|
||||||
|
{
|
||||||
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->priv.export), export);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean layer_element_get_export(LayerElement *elem)
|
||||||
|
{
|
||||||
|
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(elem->priv.export));
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
|
||||||
|
{
|
||||||
|
if (!rgba)
|
||||||
|
return;
|
||||||
|
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
|
||||||
|
{
|
||||||
|
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
||||||
|
}
|
@@ -21,33 +21,30 @@
|
|||||||
#define __LAYER_ELEMENT_H__
|
#define __LAYER_ELEMENT_H__
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
// #include <gdk/gdk.h>
|
|
||||||
|
|
||||||
#define LAYER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, layer_element_get_type(), LayerElement)
|
G_BEGIN_DECLS
|
||||||
#define LAYER_ELEMENT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, layer_element_get_type(), LayerElementClass)
|
|
||||||
#define IS_LAYE_RELEMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, layer_element_get_type())
|
/* 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 {
|
typedef struct _LayerElementPriv {
|
||||||
GtkEntry *name;
|
GtkEntry *name;
|
||||||
GtkLabel *layer;
|
GtkLabel *layer;
|
||||||
int layer_num;
|
int layer_num;
|
||||||
|
GtkEventBox *event_handle;
|
||||||
GtkColorButton *color;
|
GtkColorButton *color;
|
||||||
GtkCheckButton *export;
|
GtkCheckButton *export;
|
||||||
} LayerElementPriv;
|
} LayerElementPriv;
|
||||||
|
|
||||||
typedef struct _LayerElement {
|
struct _LayerElement {
|
||||||
/* Inheritance */
|
/* Inheritance */
|
||||||
GtkBox hbox;
|
GtkListBoxRow parent;
|
||||||
/* Custom Elements */
|
/* Custom Elements */
|
||||||
LayerElementPriv priv;
|
LayerElementPriv priv;
|
||||||
} LayerElement;
|
};
|
||||||
|
|
||||||
typedef struct _LayerElementClass {
|
|
||||||
GtkBoxClass parent_class;
|
|
||||||
} LayerElementClass;
|
|
||||||
|
|
||||||
|
|
||||||
GType layer_element_get_type(void);
|
|
||||||
GtkWidget *layer_element_new(void);
|
GtkWidget *layer_element_new(void);
|
||||||
|
|
||||||
const char *layer_element_get_name(LayerElement *elem);
|
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_get_color(LayerElement *elem, GdkRGBA *rgba);
|
||||||
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
|
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __LAYER_ELEMENT_H__ */
|
#endif /* __LAYER_ELEMENT_H__ */
|
Reference in New Issue
Block a user