Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
33deba8ca4 | |||
b0c25a4bcf | |||
899c8daf81 | |||
a9c7b9f61f | |||
55fd080796 | |||
178ef2d5b2 | |||
6a78e0df15 | |||
1e6d0bd1b9 | |||
658e681c38 | |||
e24b4a8367 | |||
960a773ed1 | |||
ab23be1cfc | |||
72d5352b09 | |||
3f198f870a | |||
2a204640bd | |||
a237a89ecf | |||
1ec0f9b297 | |||
2f2eb90b69 | |||
bbf08a4d6e | |||
34a19fa11d | |||
b4ae8eee37 | |||
6e1b7d3f61 | |||
d1e6e7b05a | |||
187ae2a74b | |||
eeae61ad47 | |||
3146ca801f | |||
43fdab4533 | |||
59835018af | |||
d81c6d1037 | |||
ba53a1151e | |||
fdf2c9a42b | |||
34c113517b | |||
5291b682c7 | |||
e76f2cbb9d | |||
586339cac1 | |||
3882f3944e | |||
00b47d7ded | |||
e9b67fe1bc | |||
976bdd9854 | |||
73e4806e65 | |||
0b17c25ecc | |||
0ef6d2f40f | |||
58bb74b905 | |||
cd9030a24e | |||
546332a9c2 | |||
68e7d52cd8 | |||
91a3e8f983 | |||
f74e2d5cf5 | |||
8ffb1d42b6 | |||
845da756b7 | |||
531634b55a | |||
2e1cf456c7 | |||
bce47f11fc | |||
5573ceb46b | |||
7124c9a5cc | |||
d5997ab5f2 | |||
e692129477 | |||
c28da2ab71 | |||
6937d24699 | |||
1d67424bc9 | |||
c7ffcf68ed | |||
8306c34292 | |||
af031acc38 | |||
9f2544ee94 | |||
1f281119df | |||
bdb06c4d6e | |||
1fa2d75abd | |||
199833d603 | |||
b0acbda6e3 | |||
7e4b915961 | |||
1fe70422db | |||
b5087769ee | |||
4f9e5ca0b4 | |||
a2b83c37a9 | |||
15ff68ea74 | |||
6bb05890b9 | |||
a3be13bc7c | |||
4cc519a661 | |||
f3968bee48 | |||
f54ff7ded6 | |||
f025a0233d | |||
bbdc6c9049 | |||
03a5aea335 | |||
3e1a4c7d92 | |||
fc6756b1fb | |||
d7293de1dc | |||
37c21ced04 | |||
179dfa0724 | |||
3c1f4f9c97 | |||
d4ba826474 | |||
8b1626c111 | |||
2a860ab949 | |||
eaf692e046 | |||
2fe6358815 | |||
e8b7bd65ac | |||
d69082a676 | |||
b6ea48ba47 | |||
cf7e4ccad0 | |||
1a6fdf59ab | |||
299d65aa6c | |||
54d5148c9d | |||
6a01d67594 | |||
01367af99c | |||
f04418376c | |||
74783f312a | |||
d4517aa493 | |||
13676deb34 | |||
f204d4c2e8 | |||
7047315892 | |||
a56bec272b | |||
8f9531d63f | |||
5aaa4d85b8 | |||
6f9b23301e | |||
7c47d7207f | |||
c502b65297 | |||
5526e403a3 | |||
5c3b299eb0 | |||
6f7feb7aa9 | |||
13aa2c8609 | |||
942df1d971 | |||
bb13993e34 | |||
b25f147707 | |||
c60afedd6c |
10
.buildconfig
10
.buildconfig
@@ -1,10 +0,0 @@
|
||||
[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
.gitignore
vendored
2
.gitignore
vendored
@@ -72,3 +72,5 @@ Thumbs.db
|
||||
*.exe
|
||||
|
||||
*.user
|
||||
*.user*
|
||||
*.buildconfig
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "c-style-checker"]
|
||||
path = c-style-checker
|
||||
url = https://git.shimatta.de/mhu/c-style-checker
|
37
AUR/PKGBUILD
Normal file
37
AUR/PKGBUILD
Normal file
@@ -0,0 +1,37 @@
|
||||
# Maintainer: Mario Hüttel <mario (dot) huettel (!) gmx (dot) net>
|
||||
|
||||
pkgname=gds-render
|
||||
pkgver=20180725.001
|
||||
pkgrel=1
|
||||
pkgdesc="Conversion tool for converting GDS layout files into TikZ Code and PDF"
|
||||
arch=('i686' 'x86_64')
|
||||
url="https://git.shimatta.de/mhu/gds-render"
|
||||
licence=('GPLv2')
|
||||
depends=('glib2' 'gtk3' 'cairo')
|
||||
makedepends=('cmake' 'git')
|
||||
privides=('gds-render')
|
||||
source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/gds-render.git")
|
||||
sha1sums=('SKIP')
|
||||
|
||||
pkgver () {
|
||||
_date=`date +"%Y%m%d"`
|
||||
cd "${srcdir}/${pkgname}-git"
|
||||
echo "$_date.$(git rev-list --count master).$(git rev-parse --short master)"
|
||||
}
|
||||
|
||||
build () {
|
||||
cd "$srcdir/$pkgname-git"
|
||||
cmake .
|
||||
make
|
||||
}
|
||||
|
||||
package () {
|
||||
cd "$srcdir/$pkgname-git"
|
||||
make DESTDIR="${pkgdir}" install
|
||||
install -D -m664 "$srcdir/$pkgname-git/AUR/gds-render.desktop" \
|
||||
"$pkgdir/usr/share/applications/gds-render.desktop"
|
||||
install -D -m664 "$srcdir/$pkgname-git/icon/gds-render.svg" \
|
||||
"$pkgdir/usr/share/icons/hicolor/scalable/apps/gds-render.svg"
|
||||
install -D -m664 "$srcdir/$pkgname-git/icon/128x128/gds-render.png" \
|
||||
"$pkgdir/usr/share/icons/hicolor/128x128/apps/gds-render.png"
|
||||
}
|
9
AUR/gds-render.desktop
Normal file
9
AUR/gds-render.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=GDS-Render
|
||||
Comment=Converter for GDS layout files
|
||||
Icon=gds-render
|
||||
Exec=gds-render
|
||||
Categories=Graphics
|
||||
|
@@ -1,24 +1,27 @@
|
||||
project(gds-render)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||
|
||||
project(gds-render)
|
||||
|
||||
add_subdirectory(glade)
|
||||
add_subdirectory(doxygen)
|
||||
add_subdirectory(version)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
|
||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||
|
||||
|
||||
aux_source_directory("widgets" LAYER_SOURCES)
|
||||
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")
|
||||
aux_source_directory("trigonometric" TRIG_SOURCES)
|
||||
aux_source_directory("layer-selector" LAYER_SELECTOR_SOURCES)
|
||||
set(SOURCE "main.c" "mapping-parser.c" "command-line.c" "main-window.c" "external-renderer.c")
|
||||
|
||||
set(SOURCE
|
||||
${SOURCE}
|
||||
@@ -27,12 +30,17 @@ set(SOURCE
|
||||
${PARSER_SOURCES}
|
||||
${LATEX_SOURCES}
|
||||
${CAIRO_SOURCES}
|
||||
${TRIG_SOURCES}
|
||||
${LAYER_SELECTOR_SOURCES}
|
||||
)
|
||||
|
||||
add_compile_options(-Wall)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
|
||||
add_dependencies(${PROJECT_NAME} glib-resources)
|
||||
add_dependencies(${PROJECT_NAME} version)
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS})
|
||||
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
|
||||
|
||||
add_custom_target(documentation DEPENDS doxygen)
|
||||
|
21
README.MD
Normal file
21
README.MD
Normal file
@@ -0,0 +1,21 @@
|
||||
# GDS-Render
|
||||
|
||||
This software is a rendering programm for GDS2 layout files.
|
||||
The GDS2 format is mainly used in integrated circuit development.
|
||||
This program allows the conversion of a GDS file to a vector graphics file.
|
||||
|
||||
## Output Formats
|
||||
* Export GDS Layout to LaTeX (using TikZ).
|
||||
* Export to PDF (Cairographics).
|
||||
|
||||
# Features
|
||||
Note: Due to various size limitations of both TikZ and the PDF export, the layout might not render correctly. In this case adjust the scale value. A higher scale value scales down your design.
|
||||
|
||||
* Configurable layer stack-up.
|
||||
* Layer colors configurable as ARGB color values.
|
||||
* Command line interface.
|
||||
* ~~Awesome~~ Somehow usable GUI.
|
||||
|
||||
# License and Other Stuff
|
||||
* Free software (GPLv2 _only_)
|
||||
* Coded in plain C using GTK+3.0, Glib2, and Cairographics
|
1
c-style-checker
Submodule
1
c-style-checker
Submodule
Submodule c-style-checker added at 3a58e3dd1c
@@ -16,19 +16,37 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file cairo-output.c
|
||||
* @brief Output renderer for Cairo PDF export
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/** @addtogroup Cairo-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "cairo-output.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-pdf.h>
|
||||
#include <cairo-svg.h>
|
||||
|
||||
/**
|
||||
* @brief The cairo_layer struct
|
||||
* Each rendered layer is represented by this struct.
|
||||
*/
|
||||
struct cairo_layer {
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *rec;
|
||||
struct layer_info *linfo;
|
||||
cairo_t *cr; /**< @brief cairo context for layer*/
|
||||
cairo_surface_t *rec; /**< @brief Recording surface to hold the layer */
|
||||
struct layer_info *linfo; /**< @brief Reference to layer information */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Revert the last transformation on all layers
|
||||
* @param layers Pointer to #cairo_layer structures
|
||||
*/
|
||||
static void revert_inherited_transform(struct cairo_layer *layers)
|
||||
{
|
||||
int i;
|
||||
@@ -40,6 +58,15 @@ static void revert_inherited_transform(struct cairo_layer *layers)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies transformation to all layers
|
||||
* @param layers Array of layers
|
||||
* @param origin Origin translation
|
||||
* @param magnification Scaling
|
||||
* @param flipping Mirror image on x-axis before rotating
|
||||
* @param rotation Rotattion in degrees
|
||||
* @param scale Scale the image down by. Only used for sclaing origin coordinates. Not applied to layer.
|
||||
*/
|
||||
static void apply_inherited_transform_to_all_layers(struct cairo_layer *layers,
|
||||
const struct gds_point *origin,
|
||||
double magnification,
|
||||
@@ -64,6 +91,12 @@ static void apply_inherited_transform_to_all_layers(struct cairo_layer *layers,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief render_cell Render a cell with its sub-cells
|
||||
* @param cell Cell to render
|
||||
* @param layers Cell will be rendered into these layers
|
||||
* @param scale sclae image down by this factor
|
||||
*/
|
||||
static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, double scale)
|
||||
{
|
||||
GList *instance_list;
|
||||
@@ -145,10 +178,10 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
|
||||
}
|
||||
|
||||
void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale)
|
||||
void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale)
|
||||
{
|
||||
cairo_surface_t *pdf_surface;
|
||||
cairo_t *pdf_cr;
|
||||
cairo_surface_t *pdf_surface, *svg_surface;
|
||||
cairo_t *pdf_cr, *svg_cr;
|
||||
struct layer_info *linfo;
|
||||
struct cairo_layer *layers;
|
||||
struct cairo_layer *lay;
|
||||
@@ -157,6 +190,11 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p
|
||||
double rec_x0, rec_y0, rec_width, rec_height;
|
||||
double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN;
|
||||
|
||||
if (pdf_file == NULL && svg_file == NULL) {
|
||||
/* No output specified */
|
||||
return;
|
||||
}
|
||||
|
||||
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
|
||||
|
||||
/* Clear layers */
|
||||
@@ -214,8 +252,15 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p
|
||||
|
||||
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);
|
||||
if (pdf_file) {
|
||||
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
|
||||
pdf_cr = cairo_create(pdf_surface);
|
||||
}
|
||||
|
||||
if (svg_file) {
|
||||
svg_surface = cairo_svg_surface_create(svg_file, xmax-xmin, ymax-ymin);
|
||||
svg_cr = cairo_create(svg_surface);
|
||||
}
|
||||
|
||||
/* Write layers to PDF */
|
||||
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
|
||||
@@ -226,13 +271,29 @@ void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *p
|
||||
continue;
|
||||
}
|
||||
|
||||
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
|
||||
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
|
||||
if (pdf_file) {
|
||||
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
|
||||
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
|
||||
}
|
||||
|
||||
if (svg_file) {
|
||||
cairo_set_source_surface(svg_cr, layers[linfo->layer].rec, -xmin, -ymin);
|
||||
cairo_paint_with_alpha(svg_cr, linfo->color.alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cairo_show_page(pdf_cr);
|
||||
cairo_destroy(pdf_cr);
|
||||
cairo_surface_destroy(pdf_surface);
|
||||
if (pdf_file) {
|
||||
cairo_show_page(pdf_cr);
|
||||
cairo_destroy(pdf_cr);
|
||||
cairo_surface_destroy(pdf_surface);
|
||||
}
|
||||
|
||||
if (svg_file) {
|
||||
cairo_show_page(svg_cr);
|
||||
cairo_destroy(svg_cr);
|
||||
cairo_surface_destroy(svg_surface);
|
||||
}
|
||||
|
||||
ret_clear_layers:
|
||||
for (i = 0; i < MAX_LAYERS; i++) {
|
||||
@@ -246,3 +307,5 @@ ret_clear_layers:
|
||||
|
||||
printf("cairo export finished. It might still be buggy!\n");
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -16,15 +16,33 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cairo-output.h
|
||||
* @brief Header File for Cairo output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
#ifndef __CAIRO_OUTPUT_H__
|
||||
#define __CAIRO_OUTPUT_H__
|
||||
|
||||
#include "../layer-selector.h"
|
||||
#include "../layer-selector/layer-selector.h"
|
||||
#include "../gds-parser/gds-types.h"
|
||||
|
||||
#define MAX_LAYERS (300)
|
||||
/** @addtogroup Cairo-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
void cairo_render_cell_to_pdf(struct gds_cell *cell, GList *layer_infos, char *pdf_file, double scale);
|
||||
#define MAX_LAYERS (300) /**< \brief Maximum layer count the output renderer can process. Typically GDS only specifies up to 255 layers.*/
|
||||
|
||||
/**
|
||||
* @brief Render \p cell to a PDF file specified by \p pdf_file
|
||||
* @param cell Toplevel cell to @ref Cairo-Renderer
|
||||
* @param layer_infos List of layer information. Specifies color and layer stacking
|
||||
* @param pdf_file PDF output file. Set to NULL if no PDF file has to be generated
|
||||
* @param svg_file SVG output file. Set to NULL if no SVG file has to be generated
|
||||
* @param scale Scale the output image down by \p scale
|
||||
*/
|
||||
void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __CAIRO_OUTPUT_H__ */
|
||||
|
202
command-line.c
Normal file
202
command-line.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file command-line.c
|
||||
* @brief Function to render according to command line parameters
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "command-line.h"
|
||||
#include "gds-parser/gds-parser.h"
|
||||
#include "mapping-parser.h"
|
||||
#include "cairo-output/cairo-output.h"
|
||||
#include "latex-output/latex-output.h"
|
||||
#include "external-renderer.h"
|
||||
#include "gds-parser/gds-tree-checker.h"
|
||||
|
||||
/**
|
||||
* @brief Delete layer_info and free nem element.
|
||||
*
|
||||
* Like delete_layer_info_struct() but also frees layer_info::name
|
||||
* @param info
|
||||
* @warning This function must not be used if the layer_info::name field references the internal storage strings if e.g. an entry field
|
||||
*/
|
||||
static void delete_layer_info_with_name(struct layer_info *info)
|
||||
{
|
||||
if (info) {
|
||||
if (info->name)
|
||||
g_free(info->name);
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
|
||||
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
||||
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
||||
gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file)
|
||||
{
|
||||
GList *libs = NULL;
|
||||
FILE *tex_file;
|
||||
int res;
|
||||
GFile *file;
|
||||
int i;
|
||||
GFileInputStream *stream;
|
||||
GDataInputStream *dstream;
|
||||
gboolean layer_export;
|
||||
GdkRGBA layer_color;
|
||||
int layer;
|
||||
char *layer_name;
|
||||
GList *layer_info_list = NULL;
|
||||
GList *cell_list;
|
||||
struct layer_info *linfo_temp;
|
||||
struct gds_library *first_lib;
|
||||
struct gds_cell *toplevel_cell = NULL, *temp_cell;
|
||||
|
||||
|
||||
/* Check if parameters are valid */
|
||||
if (!gds_name || (!pdf_name && pdf) || (!tex_name && tex) || !layer_file || !cell_name) {
|
||||
printf("Probably missing argument. Check --help option\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load GDS */
|
||||
clear_lib_list(&libs);
|
||||
res = parse_gds_from_file(gds_name, &libs);
|
||||
if (res)
|
||||
goto ret_destroy_library_list;
|
||||
|
||||
file = g_file_new_for_path(layer_file);
|
||||
stream = g_file_read(file, NULL, NULL);
|
||||
|
||||
if (!stream) {
|
||||
printf("Layer mapping not readable!\n");
|
||||
goto ret_destroy_file;
|
||||
}
|
||||
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
||||
i = 0;
|
||||
do {
|
||||
res = load_csv_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
|
||||
if (res == 0) {
|
||||
if (!layer_export)
|
||||
continue;
|
||||
linfo_temp = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||
if (!linfo_temp) {
|
||||
printf("Out of memory\n");
|
||||
goto ret_clear_layer_list;
|
||||
}
|
||||
linfo_temp->color.alpha = layer_color.alpha;
|
||||
linfo_temp->color.red = layer_color.red;
|
||||
linfo_temp->color.green = layer_color.green;
|
||||
linfo_temp->color.blue = layer_color.blue;
|
||||
linfo_temp->name = layer_name;
|
||||
linfo_temp->stacked_position = i++;
|
||||
linfo_temp->layer = layer;
|
||||
layer_info_list = g_list_append(layer_info_list, (gpointer)linfo_temp);
|
||||
}
|
||||
} while(res >= 0);
|
||||
|
||||
|
||||
/* find_cell in first library. */
|
||||
if (!libs)
|
||||
goto ret_clear_layer_list;
|
||||
|
||||
first_lib = (struct gds_library *)libs->data;
|
||||
if (!first_lib) {
|
||||
fprintf(stderr, "No library in library list. This should not happen.\n");
|
||||
goto ret_clear_layer_list;
|
||||
}
|
||||
|
||||
for (cell_list = first_lib->cells; cell_list != NULL; cell_list = g_list_next(cell_list)) {
|
||||
temp_cell = (struct gds_cell *)cell_list->data;
|
||||
if (!strcmp(temp_cell->name, cell_name)) {
|
||||
toplevel_cell = temp_cell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!toplevel_cell) {
|
||||
printf("Couldn't find cell in first library!\n");
|
||||
goto ret_clear_layer_list;
|
||||
}
|
||||
|
||||
/* Check if cell passes vital checks */
|
||||
res = gds_tree_check_reference_loops(toplevel_cell->parent_library);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Checking library %s failed.\n", first_lib->name);
|
||||
goto ret_clear_layer_list;
|
||||
} else if (res > 0) {
|
||||
fprintf(stderr, "%d reference loops found.\n", res);
|
||||
|
||||
/* do further checking if the specified cell and/or its subcells are affected */
|
||||
if (toplevel_cell->checks.affected_by_reference_loop == 1) {
|
||||
fprintf(stderr, "Cell is affected by reference loop. Abort!\n");
|
||||
goto ret_clear_layer_list;
|
||||
}
|
||||
}
|
||||
|
||||
if (toplevel_cell->checks.affected_by_reference_loop == GDS_CELL_CHECK_NOT_RUN)
|
||||
fprintf(stderr, "Cell was not checked. This should not happen. Please report this issue. Will continue either way.\n");
|
||||
|
||||
/* Note: unresolved references are not an abort condition.
|
||||
* Deal with it.
|
||||
*/
|
||||
|
||||
/* Render outputs */
|
||||
if (pdf == TRUE || svg == TRUE) {
|
||||
cairo_render_cell_to_vector_file(toplevel_cell, layer_info_list, (pdf == TRUE ? pdf_name : NULL),
|
||||
(svg == TRUE ? svg_name : NULL), scale);
|
||||
}
|
||||
|
||||
if (tex == TRUE) {
|
||||
tex_file = fopen(tex_name, "w");
|
||||
if (!tex_file)
|
||||
goto ret_clear_layer_list;
|
||||
latex_render_cell_to_code(toplevel_cell, layer_info_list, tex_file, scale, pdf_layers, pdf_standalone);
|
||||
fclose(tex_file);
|
||||
}
|
||||
|
||||
if (so_name && so_out_file) {
|
||||
if (strlen(so_name) == 0 || strlen(so_out_file) == 0)
|
||||
goto ret_clear_layer_list;
|
||||
|
||||
/* Render output using external renderer */
|
||||
printf("Invoking external renderer!\n");
|
||||
external_renderer_render_cell(toplevel_cell, layer_info_list, so_out_file, so_name);
|
||||
printf("External renderer finished!\n");
|
||||
}
|
||||
|
||||
ret_clear_layer_list:
|
||||
g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name);
|
||||
|
||||
g_object_unref(dstream);
|
||||
g_object_unref(stream);
|
||||
ret_destroy_file:
|
||||
g_object_unref(file);
|
||||
/* Delete all allocated libraries */
|
||||
ret_destroy_library_list:
|
||||
clear_lib_list(&libs);
|
||||
}
|
||||
|
||||
/** @} */
|
58
command-line.h
Normal file
58
command-line.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file command-line.h
|
||||
* @brief Render according to command line parameters
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _COMMAND_LINE_H_
|
||||
#define _COMMAND_LINE_H_
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Convert GDS according to supplied parameters
|
||||
* @param gds_name GDS File path
|
||||
* @param pdf_name Cairo-PDF path
|
||||
* @param tex_name TeX/TikZ path
|
||||
* @param pdf Render Cairo
|
||||
* @param tex Render LaTeX
|
||||
* @param layer_file Layer mapping file
|
||||
* @param cell_name Cell name to render
|
||||
* @param scale Scale image down by this value
|
||||
* @param pdf_layers TikZ creates OCG layers
|
||||
* @param pdf_standalone LaTeX document is standalone7
|
||||
* @param svg Render to SVG file
|
||||
* @param so_name Path to shared object of custom renderer
|
||||
* @param so_out_file Output file path for custom renderer
|
||||
* @param svg_name SVG file name
|
||||
*/
|
||||
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
||||
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
||||
gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file);
|
||||
|
||||
#endif /* _COMMAND_LINE_H_ */
|
||||
|
||||
/** @} */
|
10
doxygen/CMakeLists.txt
Normal file
10
doxygen/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
find_package(Doxygen)
|
||||
|
||||
if (DOXYGEN_FOUND)
|
||||
add_custom_target(doxygen
|
||||
COMMAND ./build-doxygen.sh "${PROJECT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating documentation with Doxygen")
|
||||
else (DOXYGEN_FOUND)
|
||||
message("Doxygen need to be installed to generate the doxygen documentation")
|
||||
endif (DOXYGEN_FOUND)
|
2535
doxygen/Doxyconfig
Normal file
2535
doxygen/Doxyconfig
Normal file
File diff suppressed because it is too large
Load Diff
20
doxygen/build-doxygen.sh
Executable file
20
doxygen/build-doxygen.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
cd "$DIR"
|
||||
|
||||
export PROJECT_NUMBER=`git describe --tags`
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
export OUTPUT_DIRECTORY="./output"
|
||||
else
|
||||
export OUTPUT_DIRECTORY="$1"
|
||||
fi
|
||||
|
||||
doxygen Doxyconfig
|
BIN
doxygen/images/gui.pdf
Normal file
BIN
doxygen/images/gui.pdf
Normal file
Binary file not shown.
2036
doxygen/images/gui.svg
Normal file
2036
doxygen/images/gui.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 114 KiB |
34
doxygen/lmf-spec.dox
Normal file
34
doxygen/lmf-spec.dox
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
@page lmf-spec Layer Mapping File Specification
|
||||
|
||||
File Format
|
||||
-----------
|
||||
|
||||
The layer mapping file contains information on how to render the layers.
|
||||
The information is stored in CSV format -- *True CSV*; not that rubbish with semicolons that Excel calls CSV.
|
||||
|
||||
Each line representing a layer consists of following fields:
|
||||
|
||||
> layer,r,g,b,a,export,name
|
||||
|
||||
- **layer**: Layer number identifiying this layer.
|
||||
- **r**,**b**,**g**,**a**: RGBA color value uning double precision float values in the range from 0 to 1.
|
||||
- **export**: Either '1' or '0'. Defining whether to render this layer into the output file.
|
||||
- **name**: The name of the layer.
|
||||
|
||||
the order of the layers inside the layer mapping file defines the layer stack in the rendered output.
|
||||
The first layer is at the bottom, the last at the top.
|
||||
|
||||
|
||||
Handling Inside the GUI
|
||||
-----------------------
|
||||
|
||||
The layer mapping file can be imported and exported inside the GUI.
|
||||
|
||||
### Export
|
||||
During export, all layer configurations are written to the mapping file
|
||||
|
||||
### Import
|
||||
During import, all layer configurations are loaded from the mapping file. This overwrites any configuration done to that layer. Layers that are not present in the layer mapping file are appended at the end of the list. This means, they are rendered on top of the other layers. Because the layer mapping file does not contain any information on these layers, their configuration is not reset during import.
|
||||
|
||||
*/
|
6
doxygen/main-application.dox
Normal file
6
doxygen/main-application.dox
Normal file
@@ -0,0 +1,6 @@
|
||||
/* This file only contains help information for doxygen */
|
||||
|
||||
/**
|
||||
* @defgroup MainApplication Main Application
|
||||
*
|
||||
*/
|
26
doxygen/main-page.dox
Normal file
26
doxygen/main-page.dox
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
|
||||
@mainpage
|
||||
This programm converts GDS layout files to
|
||||
|
||||
- PDF Files using the @ref Cairo-Renderer
|
||||
- Latex code (TikZ) using the @ref LaTeX-Renderer
|
||||
|
||||
See the @subpage usage page for details
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
3
doxygen/output/.gitignore
vendored
Normal file
3
doxygen/output/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*
|
||||
*/
|
||||
!.gitignore
|
8
doxygen/trigonometric.dox
Normal file
8
doxygen/trigonometric.dox
Normal file
@@ -0,0 +1,8 @@
|
||||
/* This file only contains help information for doxygen */
|
||||
|
||||
/**
|
||||
* @defgroup trigonometric Trigonometric Helper Functions
|
||||
*
|
||||
* The trigonometric helper function are used to calculate bounding boxes
|
||||
* @warning Code is incomplete. Please double check for functionality!
|
||||
*/
|
30
doxygen/usage.dox
Normal file
30
doxygen/usage.dox
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
@page usage Usage
|
||||
@section cmd Command Line Interface
|
||||
To use the application on the command line check 'gds-render --help'.
|
||||
|
||||
Application Options:
|
||||
- -t, --tikz Output TikZ code
|
||||
- -p, --pdf Output PDF document
|
||||
- -s, --scale=SCALE Divide output coordinates by SCALE
|
||||
- -o, --tex-output=PATH Optional path for TeX file
|
||||
- -O, --pdf-output=PATH Optional path for PDF file
|
||||
- -m, --mapping=PATH Path for Layer Mapping File
|
||||
- -c, --cell=NAME Cell to render
|
||||
- -a, --tex-standalone Create standalone PDF
|
||||
- -l, --tex-layers Create PDF Layers (OCG)
|
||||
- -P, --custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
|
||||
- -e, --external-lib-output=PATH Output path for external render library
|
||||
- --display=DISPLAY X display to use
|
||||
|
||||
|
||||
@section gui Graphical User Interface
|
||||
|
||||
The graphical user interface (GUI) can be used to open GDS Files, configure the layer rendering (colors, order, transparency etc.), and convert cells.
|
||||
|
||||
It is possible to export the layer configurations so they can be used later on. Even in the @ref cmd
|
||||
|
||||
@image html gui.svg
|
||||
@image latex gui.pdf
|
||||
|
||||
*/
|
6
doxygen/widgets.dox
Normal file
6
doxygen/widgets.dox
Normal file
@@ -0,0 +1,6 @@
|
||||
/* This file only contains help information for doxygen */
|
||||
|
||||
/**
|
||||
* @defgroup Widgets Custom GTK Widgets
|
||||
*
|
||||
*/
|
71
external-renderer.c
Normal file
71
external-renderer.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file external-renderer.c
|
||||
* @brief This file implements the dynamic library loading for the external rendering feature
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "external-renderer.h"
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list,
|
||||
char *output_file, char *so_path)
|
||||
{
|
||||
int (*so_render_func)(struct gds_cell *, GList *, char *) = NULL;
|
||||
void *so_handle = NULL;
|
||||
char *error_msg;
|
||||
int ret = 0;
|
||||
|
||||
/* Check parameter sanity */
|
||||
if (!output_file || !so_path || !toplevel_cell || !layer_info_list)
|
||||
return -3000;
|
||||
|
||||
/* Load shared object */
|
||||
so_handle = dlopen(so_path, RTLD_LAZY);
|
||||
if (!so_handle) {
|
||||
printf("Could not load external library '%s'\nDetailed error is:\n%s\n", so_path, dlerror());
|
||||
return -2000;
|
||||
}
|
||||
|
||||
/* Load symbol from library */
|
||||
so_render_func = (int (*)(struct gds_cell *, GList *, char *))dlsym(so_handle, EXTERNAL_LIBRARY_FUNCTION);
|
||||
error_msg = dlerror();
|
||||
if (error_msg != NULL) {
|
||||
printf("Rendering function not found in library:\n%s\n", error_msg);
|
||||
goto ret_close_so_handle;
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
if (so_render_func)
|
||||
so_render_func(toplevel_cell, layer_info_list, output_file);
|
||||
|
||||
ret_close_so_handle:
|
||||
dlclose(so_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} */
|
59
external-renderer.h
Normal file
59
external-renderer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file external-renderer.h
|
||||
* @brief Render according to command line parameters
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _EXTERNAL_RENDERER_H_
|
||||
#define _EXTERNAL_RENDERER_H_
|
||||
|
||||
#include "gds-parser/gds-types.h"
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief function name expected to be found in external library.
|
||||
*
|
||||
* The function has to be defined as follows:
|
||||
* @code
|
||||
* int function_name(gds_cell *toplevel, GList *layer_info_list, char *output_file_name)
|
||||
* @endcode
|
||||
*/
|
||||
#define EXTERNAL_LIBRARY_FUNCTION "render_cell_to_file"
|
||||
|
||||
/**
|
||||
* @brief external_renderer_render_cell
|
||||
* @param toplevel_cell The toplevel cell to render
|
||||
* @param layer_info_list The layer information. Contains #layer_info elements
|
||||
* @param output_file Output file
|
||||
* @param so_path Path to the shared object file containing #EXTERNAL_LIBRARY_FUNCTION
|
||||
* @return 0 on success
|
||||
*/
|
||||
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list, char *output_file, char *so_path);
|
||||
|
||||
#endif /* _EXTERNAL_RENDERER_H_ */
|
||||
|
||||
/** @} */
|
@@ -17,15 +17,23 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @file gds-parser.c
|
||||
* @brief Implementation of the GDS-Parser
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* What's missing? - A lot:
|
||||
* Support for Boxes
|
||||
* Support for 4 Byte real
|
||||
* Support for pathtypes
|
||||
* Support for datatypes (only layer so far)
|
||||
* etc...
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#include "gds-parser.h"
|
||||
#include <stdlib.h>
|
||||
@@ -35,10 +43,21 @@
|
||||
#include <math.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||
/**
|
||||
* @brief Default units assumed for library.
|
||||
* @note This value is usually overwritten with the value defined in the library.
|
||||
*/
|
||||
#define GDS_DEFAULT_UNITS (10E-9)
|
||||
|
||||
enum record {
|
||||
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS error*/
|
||||
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */
|
||||
|
||||
#if GDS_PRINT_DEBUG_INFOS
|
||||
#define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__) /**< @brief standard printf. But can be disabled in code */
|
||||
#else
|
||||
#define GDS_INF(fmt, ...)
|
||||
#endif
|
||||
enum gds_record {
|
||||
INVALID = 0x0000,
|
||||
HEADER = 0x0002,
|
||||
BGNLIB = 0x0102,
|
||||
@@ -63,6 +82,13 @@ enum record {
|
||||
PATHTYPE = 0x2102
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Name cell reference
|
||||
* @param cell_inst Cell reference
|
||||
* @param bytes Length of name
|
||||
* @param data Name
|
||||
* @return 0 if successful
|
||||
*/
|
||||
static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
||||
unsigned int bytes, char *data)
|
||||
{
|
||||
@@ -73,7 +99,7 @@ static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
||||
return -1;
|
||||
}
|
||||
data[bytes] = 0; // Append '0'
|
||||
len = strlen(data);
|
||||
len = (int)strlen(data);
|
||||
if (len > CELL_NAME_MAX-1) {
|
||||
GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
|
||||
return -1;
|
||||
@@ -81,11 +107,16 @@ static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
||||
|
||||
/* else: */
|
||||
strcpy(cell_inst->ref_name, data);
|
||||
printf("\tCell referenced: %s\n", cell_inst->ref_name);
|
||||
GDS_INF("\tCell referenced: %s\n", cell_inst->ref_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert GDS 8-byte real to double
|
||||
* @param data 8 Byte GDS real
|
||||
* @return result
|
||||
*/
|
||||
static double gds_convert_double(const char *data)
|
||||
{
|
||||
bool sign_bit;
|
||||
@@ -126,6 +157,11 @@ static double gds_convert_double(const char *data)
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert GDS INT32 to int
|
||||
* @param data Buffer containing the int
|
||||
* @return result
|
||||
*/
|
||||
static signed int gds_convert_signed_int(const char *data)
|
||||
{
|
||||
int ret;
|
||||
@@ -142,6 +178,11 @@ static signed int gds_convert_signed_int(const char *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert GDS INT16 to int16
|
||||
* @param data Buffer containing the INT16
|
||||
* @return result
|
||||
*/
|
||||
static int16_t gds_convert_signed_int16(const char *data)
|
||||
{
|
||||
if (!data) {
|
||||
@@ -152,6 +193,11 @@ static int16_t gds_convert_signed_int16(const char *data)
|
||||
(((int16_t)(data[1]) & 0xFF) << 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert GDS UINT16 String to uint16
|
||||
* @param data Buffer containing the uint16
|
||||
* @return result
|
||||
*/
|
||||
static uint16_t gds_convert_unsigend_int16(const char *data)
|
||||
{
|
||||
if (!data) {
|
||||
@@ -162,6 +208,12 @@ static uint16_t gds_convert_unsigend_int16(const char *data)
|
||||
(((uint16_t)(data[1]) & 0xFF) << 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append library to list
|
||||
* @param curr_list List containing gds_library elements. May be NULL.
|
||||
* @param library_ptr Return of newly created library.
|
||||
* @return Newly created list pointer
|
||||
*/
|
||||
static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
{
|
||||
struct gds_library *lib;
|
||||
@@ -170,7 +222,7 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
if (lib) {
|
||||
lib->cells = NULL;
|
||||
lib->name[0] = 0;
|
||||
lib->unit_to_meters = 1; // Default. Will be overwritten
|
||||
lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten
|
||||
lib->cell_names = NULL;
|
||||
} else
|
||||
return NULL;
|
||||
@@ -180,6 +232,13 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
return g_list_append(curr_list, lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append graphics to list
|
||||
* @param curr_list List containing gds_graphics elements. May be NULL
|
||||
* @param type Type of graphics
|
||||
* @param graphics_ptr newly created graphic is written here
|
||||
* @return new list pointer
|
||||
*/
|
||||
static GList *append_graphics(GList *curr_list, enum graphics_type type,
|
||||
struct gds_graphics **graphics_ptr)
|
||||
{
|
||||
@@ -202,6 +261,13 @@ static GList *append_graphics(GList *curr_list, enum graphics_type type,
|
||||
return g_list_append(curr_list, gfx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Appends vertext List
|
||||
* @param curr_list List containing gds_point elements. May be NULL.
|
||||
* @param x x-coordinate of new point
|
||||
* @param y y-coordinate of new point
|
||||
* @return new Pointer to List.
|
||||
*/
|
||||
static GList *append_vertex(GList *curr_list, int x, int y)
|
||||
{
|
||||
struct gds_point *vertex;
|
||||
@@ -215,6 +281,14 @@ static GList *append_vertex(GList *curr_list, int x, int y)
|
||||
return g_list_append(curr_list, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief append_cell Append a gds_cell to a list
|
||||
*
|
||||
* Usage similar to append_cell_ref().
|
||||
* @param curr_list List containing gds_cell elements. May be NULL
|
||||
* @param cell_ptr newly created cell
|
||||
* @return new pointer to list
|
||||
*/
|
||||
static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
|
||||
{
|
||||
struct gds_cell *cell;
|
||||
@@ -224,6 +298,9 @@ static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
|
||||
cell->child_cells = NULL;
|
||||
cell->graphic_objs = NULL;
|
||||
cell->name[0] = 0;
|
||||
cell->parent_library = NULL;
|
||||
cell->checks.unresolved_child_count = GDS_CELL_CHECK_NOT_RUN;
|
||||
cell->checks.affected_by_reference_loop = GDS_CELL_CHECK_NOT_RUN;
|
||||
} else
|
||||
return NULL;
|
||||
/* return cell */
|
||||
@@ -233,6 +310,14 @@ static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
|
||||
return g_list_append(curr_list, cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append a cell reference to the reference GList.
|
||||
*
|
||||
* Appends a new gds_cell_instance to \p curr_list and returns the new element via \p instance_ptr
|
||||
* @param curr_list List of gds_cell_instance elements. May be NULL
|
||||
* @param instance_ptr newly created element
|
||||
* @return new GList pointer
|
||||
*/
|
||||
static GList *append_cell_ref(GList *curr_list, struct gds_cell_instance **instance_ptr)
|
||||
{
|
||||
struct gds_cell_instance *inst;
|
||||
@@ -254,6 +339,13 @@ static GList *append_cell_ref(GList *curr_list, struct gds_cell_instance **insta
|
||||
return g_list_append(curr_list, inst);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Name a gds_library
|
||||
* @param current_library Library to name
|
||||
* @param bytes Lenght of name
|
||||
* @param data Name
|
||||
* @return 0 if successful
|
||||
*/
|
||||
static int name_library(struct gds_library *current_library,
|
||||
unsigned int bytes, char *data)
|
||||
{
|
||||
@@ -265,18 +357,26 @@ static int name_library(struct gds_library *current_library,
|
||||
}
|
||||
|
||||
data[bytes] = 0; // Append '0'
|
||||
len = strlen(data);
|
||||
len = (int)strlen(data);
|
||||
if (len > CELL_NAME_MAX-1) {
|
||||
GDS_ERROR("Library name '%s' too long: %d\n", data, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(current_library->name, data);
|
||||
printf("Named library: %s\n", current_library->name);
|
||||
GDS_INF("Named library: %s\n", current_library->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Names a gds_cell
|
||||
* @param cell Cell to name
|
||||
* @param bytes Length of name
|
||||
* @param data Name
|
||||
* @param lib Library in which \p cell is located
|
||||
* @return 0 id successful
|
||||
*/
|
||||
static int name_cell(struct gds_cell *cell, unsigned int bytes,
|
||||
char *data, struct gds_library *lib)
|
||||
{
|
||||
@@ -287,14 +387,14 @@ static int name_cell(struct gds_cell *cell, unsigned int bytes,
|
||||
return -1;
|
||||
}
|
||||
data[bytes] = 0; // Append '0'
|
||||
len = strlen(data);
|
||||
len = (int)strlen(data);
|
||||
if (len > CELL_NAME_MAX-1) {
|
||||
GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(cell->name, data);
|
||||
printf("Named cell: %s\n", cell->name);
|
||||
GDS_INF("Named cell: %s\n", cell->name);
|
||||
|
||||
/* Append cell name to lib's list of names */
|
||||
lib->cell_names = g_list_append(lib->cell_names, cell->name);
|
||||
@@ -302,7 +402,13 @@ static int name_cell(struct gds_cell *cell, unsigned int bytes,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Search for cell reference \p gcell_ref in \p glibrary
|
||||
*
|
||||
* Search cell referenced by \p gcell_ref inside \p glibrary and update gds_cell_instance::cell_ref with found #gds_cell
|
||||
* @param gcell_ref gpointer cast of struct gds_cell_instance *
|
||||
* @param glibrary gpointer cast of struct gds_library *
|
||||
*/
|
||||
static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
|
||||
{
|
||||
struct gds_cell_instance *inst = (struct gds_cell_instance *)gcell_ref;
|
||||
@@ -310,7 +416,7 @@ static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
|
||||
GList *cell_item;
|
||||
struct gds_cell *cell;
|
||||
|
||||
printf("\t\t\tReference: %s: ", inst->ref_name);
|
||||
GDS_INF("\t\t\tReference: %s: ", inst->ref_name);
|
||||
/* Find cell */
|
||||
for (cell_item = lib->cells; cell_item != NULL;
|
||||
cell_item = cell_item->next) {
|
||||
@@ -318,36 +424,57 @@ static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
|
||||
cell = (struct gds_cell *)cell_item->data;
|
||||
/* Check if cell is found */
|
||||
if (!strcmp(cell->name, inst->ref_name)) {
|
||||
printf("found\n");
|
||||
GDS_INF("found\n");
|
||||
/* update reference link */
|
||||
inst->cell_ref = cell;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("MISSING!\n");
|
||||
GDS_INF("MISSING!\n");
|
||||
GDS_WARN("referenced cell could not be found in library");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scans cell references inside cell
|
||||
This function searches all the references in \p gcell and updates the gds_cell_instance::cell_ref field in each instance
|
||||
* @param gcell pointer cast of #gds_cell *
|
||||
* @param library Library where the cell references are searched in
|
||||
*/
|
||||
static void scan_cell_reference_dependencies(gpointer gcell, gpointer library)
|
||||
{
|
||||
struct gds_cell *cell = (struct gds_cell *)gcell;
|
||||
|
||||
printf("\tScanning cell: %s\n", cell->name);
|
||||
GDS_INF("\tScanning cell: %s\n", cell->name);
|
||||
|
||||
/* Scan all library references */
|
||||
g_list_foreach(cell->child_cells, parse_reference_list, library);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scans library's cell references
|
||||
*
|
||||
* This function searches all the references between cells and updates the gds_cell_instance::cell_ref field in each instance
|
||||
* @param library_list_item List containing #gds_library elements
|
||||
* @param user not used
|
||||
*/
|
||||
static void scan_library_references(gpointer library_list_item, gpointer user)
|
||||
{
|
||||
struct gds_library *lib = (struct gds_library *)library_list_item;
|
||||
(void)user;
|
||||
|
||||
printf("Scanning Library: %s\n", lib->name);
|
||||
GDS_INF("Scanning Library: %s\n", lib->name);
|
||||
g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gds_parse_date
|
||||
* @param buffer Buffer that contains the GDS Date field
|
||||
* @param length Length of \p buffer
|
||||
* @param mod_date Modification Date
|
||||
* @param access_date Last Access Date
|
||||
*/
|
||||
static void gds_parse_date(const char *buffer, int length, struct gds_time_field *mod_date, struct gds_time_field *access_date)
|
||||
{
|
||||
|
||||
@@ -390,7 +517,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
int run = 1;
|
||||
FILE *gds_file = NULL;
|
||||
uint16_t rec_data_length;
|
||||
enum record rec_type;
|
||||
enum gds_record rec_type;
|
||||
struct gds_library *current_lib = NULL;
|
||||
struct gds_cell *current_cell = NULL;
|
||||
struct gds_graphics *current_graphics = NULL;
|
||||
@@ -466,7 +593,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
|
||||
}
|
||||
printf("Entering Lib\n");
|
||||
GDS_INF("Entering Lib\n");
|
||||
break;
|
||||
case ENDLIB:
|
||||
if (current_lib == NULL) {
|
||||
@@ -482,16 +609,24 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
}
|
||||
current_lib = NULL;
|
||||
printf("Leaving Library\n");
|
||||
GDS_INF("Leaving Library\n");
|
||||
break;
|
||||
case BGNSTR:
|
||||
if (current_lib == NULL) {
|
||||
GDS_ERROR("Defining Cell outside of library!\n");
|
||||
run = -4;
|
||||
break;
|
||||
}
|
||||
current_lib->cells = append_cell(current_lib->cells, ¤t_cell);
|
||||
if (current_lib->cells == NULL) {
|
||||
GDS_ERROR("Allocating memory failed");
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
printf("Entering Cell\n");
|
||||
|
||||
current_cell->parent_library = current_lib;
|
||||
|
||||
GDS_INF("Entering Cell\n");
|
||||
break;
|
||||
case ENDSTR:
|
||||
if (current_cell == NULL) {
|
||||
@@ -506,7 +641,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
}
|
||||
current_cell = NULL;
|
||||
printf("Leaving Cell\n");
|
||||
GDS_INF("Leaving Cell\n");
|
||||
break;
|
||||
case BOX:
|
||||
case BOUNDARY:
|
||||
@@ -523,11 +658,11 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
run = -4;
|
||||
break;
|
||||
}
|
||||
printf("\tEntering boundary/Box\n");
|
||||
GDS_INF("\tEntering boundary/Box\n");
|
||||
break;
|
||||
case SREF:
|
||||
if (current_cell == NULL) {
|
||||
GDS_ERROR("Path outside of cell");
|
||||
GDS_ERROR("Cell Reference outside of cell");
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
@@ -539,7 +674,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\tEntering reference\n");
|
||||
GDS_INF("\tEntering reference\n");
|
||||
break;
|
||||
case PATH:
|
||||
if (current_cell == NULL) {
|
||||
@@ -554,16 +689,16 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
run = -4;
|
||||
break;
|
||||
}
|
||||
printf("\tEntering Path\n");
|
||||
GDS_INF("\tEntering Path\n");
|
||||
break;
|
||||
case ENDEL:
|
||||
if (current_graphics != NULL) {
|
||||
|
||||
printf("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary" : "path"));
|
||||
GDS_INF("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary" : "path"));
|
||||
current_graphics = NULL;
|
||||
}
|
||||
if (current_s_reference != NULL) {
|
||||
printf("\tLeaving Reference\n");
|
||||
GDS_INF("\tLeaving Reference\n");
|
||||
current_s_reference = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -588,6 +723,8 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
case PATHTYPE:
|
||||
break;
|
||||
case UNITS:
|
||||
break;
|
||||
default:
|
||||
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
|
||||
break;
|
||||
@@ -595,7 +732,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
|
||||
|
||||
/* No Data -> No Processing, go back to top */
|
||||
if (!rec_data_length) continue;
|
||||
if (!rec_data_length || run != 1) continue;
|
||||
|
||||
read = fread(workbuff, sizeof(char), rec_data_length, gds_file);
|
||||
|
||||
@@ -609,7 +746,6 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
switch (rec_type) {
|
||||
|
||||
case HEADER:
|
||||
case UNITS:
|
||||
case ENDLIB:
|
||||
case ENDSTR:
|
||||
case BOUNDARY:
|
||||
@@ -620,6 +756,20 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
case INVALID:
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
if (!current_lib) {
|
||||
GDS_WARN("Units defined outside of library!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (rec_data_length != 16) {
|
||||
GDS_WARN("Unit define incomplete. Will assume database unit of %E meters\n", current_lib->unit_in_meters);
|
||||
break;
|
||||
}
|
||||
|
||||
current_lib->unit_in_meters = gds_convert_double(&workbuff[8]);
|
||||
GDS_INF("Length of database unit: %E meters\n", current_lib->unit_in_meters);
|
||||
break;
|
||||
case BGNLIB:
|
||||
/* Parse date record */
|
||||
gds_parse_date(workbuff, read, ¤t_lib->mod_time, ¤t_lib->access_time);
|
||||
@@ -628,17 +778,17 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
gds_parse_date(workbuff, read, ¤t_cell->mod_time, ¤t_cell->access_time);
|
||||
break;
|
||||
case LIBNAME:
|
||||
name_library(current_lib, read, workbuff);
|
||||
name_library(current_lib, (unsigned int)read, workbuff);
|
||||
break;
|
||||
case STRNAME:
|
||||
name_cell(current_cell, read, workbuff, current_lib);
|
||||
name_cell(current_cell, (unsigned int)read, workbuff, current_lib);
|
||||
break;
|
||||
case XY:
|
||||
if (current_s_reference) {
|
||||
/* Get origin of reference */
|
||||
current_s_reference->origin.x = gds_convert_signed_int(workbuff);
|
||||
current_s_reference->origin.y = gds_convert_signed_int(&workbuff[4]);
|
||||
printf("\t\tSet origin to: %d/%d\n", current_s_reference->origin.x,
|
||||
GDS_INF("\t\tSet origin to: %d/%d\n", current_s_reference->origin.x,
|
||||
current_s_reference->origin.y);
|
||||
} else if (current_graphics) {
|
||||
for (i = 0; i < read/8; i++) {
|
||||
@@ -646,7 +796,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
y = gds_convert_signed_int(&workbuff[i*8+4]);
|
||||
current_graphics->vertices =
|
||||
append_vertex(current_graphics->vertices, x, y);
|
||||
printf("\t\tSet coordinate: %d/%d\n", x, y);
|
||||
GDS_INF("\t\tSet coordinate: %d/%d\n", x, y);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -660,7 +810,11 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
|
||||
case SNAME:
|
||||
name_cell_ref(current_s_reference, read, workbuff);
|
||||
if (current_s_reference) {
|
||||
name_cell_ref(current_s_reference, (unsigned int)read, workbuff);
|
||||
} else {
|
||||
GDS_ERROR("reference name set outside of cell reference.\n");
|
||||
}
|
||||
break;
|
||||
case WIDTH:
|
||||
if (!current_graphics) {
|
||||
@@ -677,7 +831,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
if (current_graphics->layer < 0) {
|
||||
GDS_WARN("Layer negative!\n");
|
||||
}
|
||||
printf("\t\tAdded layer %d\n", (int)current_graphics->layer);
|
||||
GDS_INF("\t\tAdded layer %d\n", (int)current_graphics->layer);
|
||||
break;
|
||||
case MAG:
|
||||
if (rec_data_length != 8) {
|
||||
@@ -690,7 +844,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
}
|
||||
if (current_s_reference != NULL) {
|
||||
current_s_reference->magnification = gds_convert_double(workbuff);
|
||||
printf("\t\tMagnification defined: %lf\n", current_s_reference->magnification);
|
||||
GDS_INF("\t\tMagnification defined: %lf\n", current_s_reference->magnification);
|
||||
}
|
||||
break;
|
||||
case ANGLE:
|
||||
@@ -704,7 +858,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
}
|
||||
if (current_s_reference != NULL) {
|
||||
current_s_reference->angle = gds_convert_double(workbuff);
|
||||
printf("\t\tAngle defined: %lf\n", current_s_reference->angle);
|
||||
GDS_INF("\t\tAngle defined: %lf\n", current_s_reference->angle);
|
||||
}
|
||||
break;
|
||||
case PATHTYPE:
|
||||
@@ -713,8 +867,8 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
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);
|
||||
current_graphics->path_render_type = (enum path_type)gds_convert_signed_int16(workbuff);
|
||||
GDS_INF("\t\tPathtype: %d\n", current_graphics->path_render_type);
|
||||
} else {
|
||||
GDS_WARN("Path type defined inside non-path graphics object. Ignoring");
|
||||
}
|
||||
@@ -726,15 +880,11 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
|
||||
fclose(gds_file);
|
||||
|
||||
|
||||
if (!run) {
|
||||
/* Iterate and find references to cells */
|
||||
g_list_foreach(lib_list, scan_library_references, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
*library_list = lib_list;
|
||||
|
||||
free(workbuff);
|
||||
@@ -742,31 +892,62 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
return run;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete_cell_inst_element
|
||||
* @param cell_inst
|
||||
*/
|
||||
static void delete_cell_inst_element(struct gds_cell_instance *cell_inst)
|
||||
{
|
||||
free(cell_inst);
|
||||
if (cell_inst)
|
||||
free(cell_inst);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete_vertex
|
||||
* @param vertex
|
||||
*/
|
||||
static void delete_vertex(struct gds_point *vertex)
|
||||
{
|
||||
free(vertex);
|
||||
if (vertex)
|
||||
free(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete_graphics_obj
|
||||
* @param gfx
|
||||
*/
|
||||
static void delete_graphics_obj(struct gds_graphics *gfx)
|
||||
{
|
||||
if (!gfx)
|
||||
return;
|
||||
|
||||
g_list_free_full(gfx->vertices, (GDestroyNotify)delete_vertex);
|
||||
free(gfx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete_cell_element
|
||||
* @param cell
|
||||
*/
|
||||
static void delete_cell_element(struct gds_cell *cell)
|
||||
{
|
||||
if (!cell)
|
||||
return;
|
||||
|
||||
g_list_free_full(cell->child_cells, (GDestroyNotify)delete_cell_inst_element);
|
||||
g_list_free_full(cell->graphic_objs, (GDestroyNotify)delete_graphics_obj);
|
||||
free(cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief delete_library_element
|
||||
* @param lib
|
||||
*/
|
||||
static void delete_library_element(struct gds_library *lib)
|
||||
{
|
||||
if (!lib)
|
||||
return;
|
||||
|
||||
g_list_free(lib->cell_names);
|
||||
g_list_free_full(lib->cells, (GDestroyNotify)delete_cell_element);
|
||||
free(lib);
|
||||
@@ -774,9 +955,15 @@ static void delete_library_element(struct gds_library *lib)
|
||||
|
||||
int clear_lib_list(GList **library_list)
|
||||
{
|
||||
if (!library_list)
|
||||
return 0;
|
||||
|
||||
if (*library_list == NULL)
|
||||
return 0;
|
||||
|
||||
g_list_free_full(*library_list, (GDestroyNotify)delete_library_element);
|
||||
*library_list = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,13 +17,33 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gds-parser.h
|
||||
* @brief Header file for the GDS-Parser
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __GDSPARSE_H__
|
||||
#define __GDSPARSE_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include "gds-types.h"
|
||||
|
||||
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
|
||||
|
||||
int parse_gds_from_file(const char *filename, GList **library_array);
|
||||
/**
|
||||
* @brief Deletes all libraries including cells, references etc.
|
||||
* @param library_list Pointer to a list of #gds_library. Is set to NULL after completion.
|
||||
* @return 0
|
||||
*/
|
||||
int clear_lib_list(GList **library_list);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __GDSPARSE_H__ */
|
||||
|
200
gds-parser/gds-tree-checker.c
Normal file
200
gds-parser/gds-tree-checker.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gds-tree-checker.c
|
||||
* @brief Checking functions of a cell tree
|
||||
*
|
||||
* This file contains cehcking functions for the GDS cell tree.
|
||||
* These functions include checks if all child references could be resolved,
|
||||
* and if the cell tree contains loops.
|
||||
*
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "gds-tree-checker.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int gds_tree_check_cell_references(struct gds_library *lib)
|
||||
{
|
||||
GList *cell_iter;
|
||||
struct gds_cell *cell;
|
||||
GList *instance_iter;
|
||||
struct gds_cell_instance *cell_inst;
|
||||
int total_unresolved_count = 0;
|
||||
|
||||
if (!lib)
|
||||
return -1;
|
||||
|
||||
/* Iterate over all cells in library */
|
||||
for (cell_iter = lib->cells; cell_iter != NULL; cell_iter = g_list_next(cell_iter)) {
|
||||
cell = (struct gds_cell *)cell_iter->data;
|
||||
|
||||
/* Check if this list element is broken. This should never happen */
|
||||
if (!cell) {
|
||||
fprintf(stderr, "Broken cell list item found. Will continue.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Reset the unresolved cell reference counter to 0 */
|
||||
cell->checks.unresolved_child_count = 0;
|
||||
|
||||
/* Iterate through all child cell references and check if the references are set */
|
||||
for (instance_iter = cell->child_cells; instance_iter != NULL;
|
||||
instance_iter = g_list_next(instance_iter)) {
|
||||
cell_inst = (struct gds_cell_instance *)instance_iter->data;
|
||||
|
||||
/* Check if broken. This should not happen */
|
||||
if (!cell_inst) {
|
||||
fprintf(stderr, "Broken cell list item found in cell %s. Will continue.\n",
|
||||
cell->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if instance is valid; else increment "error" counter of cell */
|
||||
if (!cell_inst->cell_ref) {
|
||||
total_unresolved_count++;
|
||||
cell->checks.unresolved_child_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total_unresolved_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if list contains a cell
|
||||
* @param list GList to check. May be a null pointer
|
||||
* @param cell Cell to check for
|
||||
* @return 0 if cell is not in list. 1 if cell is in list
|
||||
*/
|
||||
static int gds_tree_check_list_contains_cell(GList *list, struct gds_cell *cell) {
|
||||
GList *iter;
|
||||
|
||||
for (iter = list; iter != NULL; iter = g_list_next(iter)) {
|
||||
if ((struct gds_cell *)iter->data == cell)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function follows down the reference list of a cell and marks each visited subcell and detects loops
|
||||
* @param cell_to_check The cell to check for reference loops
|
||||
* @param visited_cells Pointer to list head. May be zero.
|
||||
* @return 0 if no loops exist; error in processing: <0; loop found: >0
|
||||
*/
|
||||
static int gds_tree_check_iterate_ref_and_check(struct gds_cell *cell_to_check, GList **visited_cells)
|
||||
{
|
||||
GList *ref_iter;
|
||||
struct gds_cell_instance *ref;
|
||||
struct gds_cell *sub_cell;
|
||||
int res;
|
||||
|
||||
if (!cell_to_check)
|
||||
return -1;
|
||||
|
||||
/* Check if this cell is already contained in visited cells. This indicates a loop */
|
||||
if (gds_tree_check_list_contains_cell(*visited_cells, cell_to_check))
|
||||
return 1;
|
||||
|
||||
/* Add cell to visited cell list */
|
||||
*visited_cells = g_list_append(*visited_cells, (gpointer)cell_to_check);
|
||||
|
||||
/* Mark references and process sub cells */
|
||||
for (ref_iter = cell_to_check->child_cells; ref_iter != NULL; ref_iter = g_list_next(ref_iter)) {
|
||||
ref = (struct gds_cell_instance *)ref_iter->data;
|
||||
|
||||
if (!ref)
|
||||
return -1;
|
||||
|
||||
sub_cell = ref->cell_ref;
|
||||
|
||||
/* If cell is not resolved, ignore. No harm there */
|
||||
if (!sub_cell)
|
||||
continue;
|
||||
|
||||
res = gds_tree_check_iterate_ref_and_check(sub_cell, visited_cells);
|
||||
if (res < 0) {
|
||||
/* Error. return. */
|
||||
return -3;
|
||||
} else if (res > 0) {
|
||||
/* Loop in subcell found. Propagate to top */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove cell from visted cells */
|
||||
*visited_cells = g_list_remove(*visited_cells, cell_to_check);
|
||||
|
||||
/* No error found in this chain */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gds_tree_check_reference_loops(struct gds_library *lib)
|
||||
{
|
||||
int res;
|
||||
int loop_count = 0;
|
||||
GList *cell_iter;
|
||||
struct gds_cell *cell_to_check;
|
||||
GList *visited_cells = NULL;
|
||||
|
||||
|
||||
if (!lib)
|
||||
return -1;
|
||||
|
||||
for (cell_iter = lib->cells; cell_iter != NULL; cell_iter = g_list_next(cell_iter)) {
|
||||
cell_to_check = (struct gds_cell *)cell_iter->data;
|
||||
|
||||
/* A broken cell reference will be counted fatal in this case */
|
||||
if (!cell_to_check)
|
||||
return -2;
|
||||
|
||||
/* iterate through references and check if loop exists */
|
||||
res = gds_tree_check_iterate_ref_and_check(cell_to_check, &visited_cells);
|
||||
|
||||
if (res < 0) {
|
||||
/* Error */
|
||||
return res;
|
||||
} else if (res > 0) {
|
||||
/* Loop found: increment loop count and flag cell */
|
||||
cell_to_check->checks.affected_by_reference_loop = 1;
|
||||
loop_count++;
|
||||
} else if (res == 0) {
|
||||
/* No error found for this cell */
|
||||
cell_to_check->checks.affected_by_reference_loop = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (visited_cells) {
|
||||
fprintf(stderr, "Visited cell list should be empty. This is a bug. Please report this.\n");
|
||||
g_list_free(visited_cells);
|
||||
}
|
||||
|
||||
return loop_count;
|
||||
}
|
||||
|
||||
/** @} */
|
61
gds-parser/gds-tree-checker.h
Normal file
61
gds-parser/gds-tree-checker.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gds-tree-checker.h
|
||||
* @brief Checking functions of a cell tree (Header)
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GDS_TREE_CHECKER_H_
|
||||
#define _GDS_TREE_CHECKER_H_
|
||||
|
||||
#include "gds-types.h"
|
||||
|
||||
/**
|
||||
* @brief gds_tree_check_cell_references checks if all child cell references can be resolved in the given library
|
||||
*
|
||||
* This function will only mark cells that
|
||||
* directly contain unresolved references.
|
||||
*
|
||||
* If a cell contains a reference to a cell with unresolved references, it is not flagged.
|
||||
*
|
||||
* @param lib The GDS library to check
|
||||
* @return less than 0 if an error occured during processing; 0 if all child cells could be resolved;
|
||||
* greater than zero if the processing was successful but not all cell references could be resolved.
|
||||
* In this case the number of unresolved references is returned
|
||||
*/
|
||||
int gds_tree_check_cell_references(struct gds_library *lib);
|
||||
|
||||
/**
|
||||
* @brief gds_tree_check_reference_loops checks if the given library contains reference loops
|
||||
* @param lib GDS library
|
||||
* @return negative if an error occured, zero if there are no reference loops, else a positive number representing the number
|
||||
* of affected cells
|
||||
*/
|
||||
int gds_tree_check_reference_loops(struct gds_library *lib);
|
||||
|
||||
#endif /* _GDS_TREE_CHECKER_H_ */
|
||||
|
||||
/** @} */
|
@@ -1,21 +1,88 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gds-types.h
|
||||
* @brief Defines types and macros used by the GDS-Parser
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#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))
|
||||
#define CELL_NAME_MAX (100) /**< @brief Maximum length of a gds_cell::name or a gds_library::name */
|
||||
|
||||
enum graphics_type {GRAPHIC_PATH = 0, GRAPHIC_POLYGON = 1, GRAPHIC_BOX};
|
||||
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2};
|
||||
/* Maybe use the macros that ship with the compiler? */
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
||||
|
||||
/** @brief Defintion of check counter default value
|
||||
* that indicates that the corresponding check has not yet been executed */
|
||||
enum {GDS_CELL_CHECK_NOT_RUN = -1};
|
||||
|
||||
/** @brief Types of graphic objects */
|
||||
enum graphics_type
|
||||
{
|
||||
GRAPHIC_PATH = 0, /**< @brief Path. Esentially a line */
|
||||
GRAPHIC_POLYGON = 1, /**< @brief An arbitrary polygon */
|
||||
GRAPHIC_BOX = 2 /**< @brief A rectangle. @warning Implementation in renderers might be buggy!*/
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Defines the line caps of a path
|
||||
*/
|
||||
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2}; /**< Path line caps */
|
||||
|
||||
/**
|
||||
* @brief A point in the 2D plane. Sometimes references as vertex
|
||||
*/
|
||||
struct gds_point {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stores the result of the cell checks.
|
||||
*/
|
||||
struct gds_cell_checks {
|
||||
int unresolved_child_count; /**< @brief Number of unresolved cell instances inside this cell. Default: GDS_CELL_CHECK_NOT_RUN */
|
||||
int affected_by_reference_loop; /**< @brief 1 if the cell is affected by a reference loop and therefore not renderable. Default: GDS_CELL_CHECK_NOT_RUN*/
|
||||
/**
|
||||
* @brief For the internal use of the checker.
|
||||
* @warning Do not use this structure and its contents!
|
||||
*/
|
||||
struct _check_internals {
|
||||
int marker;
|
||||
} _internal;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Date information for cells and libraries
|
||||
*/
|
||||
struct gds_time_field {
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
@@ -25,39 +92,55 @@ struct gds_time_field {
|
||||
uint16_t second;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A GDS graphics object
|
||||
*/
|
||||
struct gds_graphics {
|
||||
enum graphics_type gfx_type;
|
||||
GList *vertices;
|
||||
enum path_type path_render_type;
|
||||
int width_absolute;
|
||||
int16_t layer;
|
||||
enum graphics_type gfx_type; /**< \brief Type of graphic */
|
||||
GList *vertices; /**< @brief List of #gds_point */
|
||||
enum path_type path_render_type; /**< @brief Line cap */
|
||||
int width_absolute; /**< @brief Width. Not used for objects other than paths */
|
||||
int16_t layer; /**< @brief Layer the graphic object is on */
|
||||
uint16_t datatype;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This represents an instanc of a cell inside another cell
|
||||
*/
|
||||
struct gds_cell_instance {
|
||||
char ref_name[CELL_NAME_MAX];
|
||||
struct gds_cell *cell_ref;
|
||||
struct gds_point origin;
|
||||
int flipped;
|
||||
double angle;
|
||||
double magnification;
|
||||
char ref_name[CELL_NAME_MAX]; /**< @brief Name of referenced cell */
|
||||
struct gds_cell *cell_ref; /**< @brief Referenced gds_cell structure */
|
||||
struct gds_point origin; /**< @brief Origin */
|
||||
int flipped; /**< @brief Mirrored on x-axis before rotation */
|
||||
double angle; /**< @brief Angle of rotation (counter clockwise) in degrees */
|
||||
double magnification; /**< @brief magnification */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A Cell inside a gds_library
|
||||
*/
|
||||
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;
|
||||
GList *child_cells; /**< @brief List of #gds_cell_instance elements */
|
||||
GList *graphic_objs; /**< @brief List of #gds_graphics */
|
||||
struct gds_library *parent_library; /**< @brief Pointer to parent library */
|
||||
struct gds_cell_checks checks; /**< @brief Checking results */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GDS Toplevel library
|
||||
*/
|
||||
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;
|
||||
double unit_in_meters; /**< Length of a database unit in meters */
|
||||
GList *cells; /**< List of #gds_cell that contains all cells in this library*/
|
||||
GList *cell_names /**< List of strings that contains all cell names */;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __GDS_TYPES_H__ */
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<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="logo_icon_name">gds-render</property>
|
||||
<property name="license_type">gpl-2-0-only</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">3000</property>
|
||||
<property name="upper">4000</property>
|
||||
<property name="value">1000</property>
|
||||
<property name="step_increment">10</property>
|
||||
<property name="page_increment">1000</property>
|
||||
@@ -16,6 +16,7 @@
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="latex-radio">
|
||||
<property name="label" translatable="yes">Generate LaTeX/TikZ output</property>
|
||||
<property name="use_action_appearance">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
@@ -29,8 +30,9 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="cairo-radio">
|
||||
<object class="GtkRadioButton" id="cairo-pdf-radio">
|
||||
<property name="label" translatable="yes">Render PDF using Cairographics</property>
|
||||
<property name="use_action_appearance">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
@@ -44,18 +46,36 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="cairo-svg-radio">
|
||||
<property name="label" translatable="yes">Render SVG using Cairographics (too buggy at the moment)</property>
|
||||
<property name="use_action_appearance">True</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">2</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="fill_level">4000</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>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -69,7 +89,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -83,7 +103,85 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="shape-drawer">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="x-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="y-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="x-output-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="y-output-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
122
glade/main.glade
122
glade/main.glade
@@ -2,16 +2,26 @@
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-up</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-down</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="main-window">
|
||||
<property name="height_request">250</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">gds-render</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<object class="GtkHeaderBar" id="header-bar">
|
||||
<property name="name">header</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">GDS Renderer</property>
|
||||
<property name="subtitle" translatable="yes">GDSII to PDF Converter</property>
|
||||
<property name="show_close_button">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-load-gds">
|
||||
@@ -81,19 +91,48 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="cell-tree">
|
||||
<object class="GtkSearchEntry" id="cell-search">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
<property name="primary_icon_name">edit-find-symbolic</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="cell-tree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="enable_search">False</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -103,23 +142,74 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="layer-list">
|
||||
<object class="GtkButton" id="button-up-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">image1</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</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-down-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">image2</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="layer-list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="selection_mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
BIN
icon/128x128/gds-render.png
Normal file
BIN
icon/128x128/gds-render.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
479
icon/gds-render.svg
Normal file
479
icon/gds-render.svg
Normal file
@@ -0,0 +1,479 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30.000001 29.999999"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="gds-render.svg"
|
||||
inkscape:export-filename="/home/mari/projects/cpp/gds-render/icon/22x22/gds-render.png"
|
||||
inkscape:export-xdpi="18.62639"
|
||||
inkscape:export-ydpi="18.62639">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="123.37499"
|
||||
inkscape:cy="62.837322"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
inkscape:window-width="2880"
|
||||
inkscape:window-height="1508"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="38"
|
||||
inkscape:window-maximized="1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4825-0">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4821" />
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop4823" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
osb:paint="solid"
|
||||
id="linearGradient4788">
|
||||
<stop
|
||||
id="stop4786"
|
||||
offset="0"
|
||||
style="stop-color:#c4a000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="298.01938"
|
||||
x2="29.850964"
|
||||
y1="268.53937"
|
||||
x1="1.6864967"
|
||||
id="linearGradient4806"
|
||||
xlink:href="#linearGradient4825-0"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="261.9151"
|
||||
x2="7.7163501"
|
||||
y1="298.01938"
|
||||
x1="29.850964"
|
||||
id="linearGradient4833"
|
||||
xlink:href="#linearGradient4825-0"
|
||||
inkscape:collect="always" />
|
||||
<g
|
||||
id="g4922">
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-0"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4892"
|
||||
d=""
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-1"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4895"
|
||||
d="m 7.78125,-2.359375 c 0,-0.46875 0.046875,-0.53125 0.8125,-0.53125 v -0.34375 c -0.3125,0.015625 -1.140625,0.015625 -1.5,0.015625 -0.375,0 -1.421875,0 -1.734375,-0.015625 v 0.34375 H 5.71875 c 1.0625,0 1.09375,0.140625 1.09375,0.578125 v 0.765625 c 0,1.359375 -1.5625,1.453125 -1.875,1.453125 -0.9375,0 -3.1875,-0.578125 -3.1875,-4 0,-3.453125 2.265625,-3.96875 3.109375,-3.96875 1.03125,0 2.28125,0.75 2.59375,2.859375 0.015625,0.140625 0.015625,0.171875 0.15625,0.171875 0.171875,0 0.171875,-0.03125 0.171875,-0.28125 v -2.828125 c 0,-0.21875 0,-0.28125 -0.125,-0.28125 -0.0625,0 -0.078125,0.03125 -0.15625,0.15625 l -0.578125,0.9375 C 6.578125,-7.75 5.84375,-8.421875 4.703125,-8.421875 c -2.15625,0 -4.0625,1.890625 -4.0625,4.328125 0,2.484375 1.90625,4.34375 4.078125,4.34375 0.84375,0 1.8125,-0.28125 2.265625,-1.03125 0.21875,0.375 0.609375,0.765625 0.703125,0.765625 0.09375,0 0.09375,-0.0625 0.09375,-0.265625 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-2"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4898"
|
||||
d="m 0.5,-8.15625 v 0.34375 h 0.234375 c 0.875,0 0.90625,0.109375 0.90625,0.5625 v 6.34375 c 0,0.4375 -0.03125,0.5625 -0.90625,0.5625 H 0.5 V 0 h 4.1875 c 2,0 3.59375,-1.796875 3.59375,-4 0,-2.3125 -1.609375,-4.15625 -3.59375,-4.15625 z m 2.625,7.8125 c -0.515625,0 -0.546875,-0.09375 -0.546875,-0.484375 V -7.34375 c 0,-0.390625 0.03125,-0.46875 0.546875,-0.46875 h 1.265625 c 0.984375,0 1.78125,0.46875 2.265625,1.265625 0.546875,0.84375 0.546875,2.046875 0.546875,2.53125 0,0.671875 -0.015625,1.796875 -0.703125,2.671875 -0.390625,0.5 -1.109375,1 -2.109375,1 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-3"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4901"
|
||||
d="M 2.484375,-4.984375 C 1.875,-5.140625 1.34375,-5.734375 1.34375,-6.5 c 0,-0.84375 0.671875,-1.59375 1.59375,-1.59375 1.96875,0 2.21875,1.9375 2.296875,2.453125 0.03125,0.140625 0.03125,0.1875 0.140625,0.1875 0.140625,0 0.140625,-0.0625 0.140625,-0.265625 v -2.421875 c 0,-0.21875 0,-0.28125 -0.125,-0.28125 -0.03125,0 -0.078125,0 -0.171875,0.15625 L 4.828125,-7.53125 C 4.25,-8.265625 3.46875,-8.421875 2.9375,-8.421875 c -1.328125,0 -2.296875,1.078125 -2.296875,2.296875 0,0.5625 0.203125,1.09375 0.65625,1.578125 0.40625,0.453125 0.828125,0.5625 1.671875,0.78125 0.421875,0.09375 1.078125,0.265625 1.25,0.328125 0.5625,0.28125 0.9375,0.921875 0.9375,1.59375 0,0.90625 -0.640625,1.75 -1.625,1.75 -0.546875,0 -1.28125,-0.140625 -1.875,-0.640625 -0.6875,-0.625 -0.734375,-1.484375 -0.75,-1.890625 -0.015625,-0.09375 -0.109375,-0.09375 -0.125,-0.09375 -0.140625,0 -0.140625,0.0625 -0.140625,0.28125 v 2.40625 c 0,0.21875 0,0.28125 0.125,0.28125 C 0.84375,0.25 0.84375,0.234375 0.9375,0.078125 0.984375,-0.015625 1.234375,-0.453125 1.328125,-0.640625 1.75,-0.15625 2.515625,0.25 3.53125,0.25 4.875,0.25 5.84375,-0.890625 5.84375,-2.203125 5.84375,-2.921875 5.5625,-3.46875 5.25,-3.859375 4.8125,-4.40625 4.265625,-4.53125 3.796875,-4.65625 Z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-4"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4904"
|
||||
d="M 3.234375,-2.265625 V -2.90625 H 0.125 v 0.640625 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-5"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4907"
|
||||
d="m 5.046875,-4.0625 c 1.1875,-0.28125 2.09375,-1.03125 2.09375,-1.953125 0,-1.15625 -1.34375,-2.140625 -3.0625,-2.140625 H 0.5 v 0.34375 h 0.234375 c 0.875,0 0.90625,0.109375 0.90625,0.5625 v 6.34375 c 0,0.4375 -0.03125,0.5625 -0.90625,0.5625 H 0.5 V 0 c 0.28125,-0.03125 1.25,-0.03125 1.609375,-0.03125 0.34375,0 1.328125,0 1.609375,0.03125 V -0.34375 H 3.484375 c -0.859375,0 -0.90625,-0.125 -0.90625,-0.5625 v -3.0625 H 3.96875 c 0.46875,0 0.90625,0.125 1.234375,0.46875 0.40625,0.453125 0.40625,0.703125 0.40625,1.53125 0,0.9375 0,1.25 0.515625,1.765625 C 6.3125,-0.03125 6.8125,0.25 7.484375,0.25 c 0.9375,0 1.09375,-1.03125 1.09375,-1.296875 0,-0.0625 0,-0.171875 -0.140625,-0.171875 -0.125,0 -0.125,0.078125 -0.125,0.1875 C 8.25,-0.3125 7.90625,0.015625 7.515625,0.015625 6.96875,0.015625 6.84375,-0.546875 6.75,-1.1875 6.734375,-1.265625 6.671875,-1.78125 6.640625,-2.078125 6.546875,-2.671875 6.5,-3.0625 6.140625,-3.4375 c -0.125,-0.125 -0.4375,-0.453125 -1.09375,-0.625 z m -1.125,-0.140625 H 2.578125 V -7.34375 c 0,-0.265625 0,-0.40625 0.25,-0.46875 0.109375,0 0.46875,0 0.703125,0 0.96875,0 2.5,0 2.5,1.796875 0,1.046875 -0.5625,1.8125 -2.109375,1.8125 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-6"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4910"
|
||||
d="m 4.578125,-2.765625 c 0.265625,0 0.28125,0 0.28125,-0.234375 0,-1.203125 -0.640625,-2.328125 -2.09375,-2.328125 -1.359375,0 -2.40625,1.234375 -2.40625,2.703125 0,1.578125 1.21875,2.75 2.546875,2.75 1.421875,0 1.953125,-1.296875 1.953125,-1.546875 0,-0.078125 -0.046875,-0.125 -0.125,-0.125 -0.09375,0 -0.125,0.0625 -0.140625,0.125 -0.3125,1 -1.109375,1.28125 -1.625,1.28125 -0.5,0 -1.703125,-0.34375 -1.703125,-2.40625 v -0.21875 z M 1.28125,-3 c 0.09375,-1.875 1.140625,-2.09375 1.484375,-2.09375 1.28125,0 1.34375,1.6875 1.359375,2.09375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-7"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4913"
|
||||
d="m 5.3125,-2.90625 c 0,-1.109375 0,-1.4375 -0.265625,-1.828125 -0.34375,-0.46875 -0.90625,-0.53125 -1.3125,-0.53125 -1.171875,0 -1.625,0.984375 -1.71875,1.21875 v -1.21875 l -1.640625,0.125 v 0.34375 c 0.8125,0 0.921875,0.09375 0.921875,0.671875 v 3.234375 c 0,0.546875 -0.140625,0.546875 -0.921875,0.546875 V 0 c 0.3125,-0.03125 0.96875,-0.03125 1.296875,-0.03125 0.34375,0 1,0 1.296875,0.03125 v -0.34375 c -0.75,0 -0.90625,0 -0.90625,-0.546875 v -2.21875 c 0,-1.25 0.828125,-1.921875 1.578125,-1.921875 0.734375,0 0.90625,0.609375 0.90625,1.34375 v 2.796875 c 0,0.546875 -0.140625,0.546875 -0.90625,0.546875 V 0 c 0.296875,-0.03125 0.953125,-0.03125 1.28125,-0.03125 0.34375,0 1,0 1.3125,0.03125 v -0.34375 c -0.609375,0 -0.90625,0 -0.921875,-0.359375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-8"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4916"
|
||||
d="M 3.578125,-8.15625 V -7.8125 C 4.40625,-7.8125 4.5,-7.734375 4.5,-7.140625 V -4.5 C 4.25,-4.859375 3.734375,-5.265625 3,-5.265625 c -1.390625,0 -2.578125,1.171875 -2.578125,2.703125 0,1.515625 1.125,2.6875 2.453125,2.6875 0.90625,0 1.421875,-0.609375 1.59375,-0.828125 V 0.125 L 6.15625,0 V -0.34375 C 5.34375,-0.34375 5.25,-0.4375 5.25,-1.015625 v -7.28125 z m 0.890625,6.75 c 0,0.21875 0,0.265625 -0.171875,0.515625 -0.28125,0.421875 -0.765625,0.765625 -1.375,0.765625 -0.296875,0 -1.59375,-0.109375 -1.59375,-2.4375 0,-0.859375 0.140625,-1.328125 0.40625,-1.734375 0.234375,-0.359375 0.71875,-0.734375 1.3125,-0.734375 0.75,0 1.15625,0.53125 1.28125,0.734375 0.140625,0.203125 0.140625,0.21875 0.140625,0.4375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="lx-text4864-glyph0-9"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4919"
|
||||
d="m 2,-2.78125 c 0,-1.15625 0.46875,-2.25 1.390625,-2.25 0.09375,0 0.125,0 0.171875,0.015625 -0.09375,0.046875 -0.28125,0.109375 -0.28125,0.4375 0,0.34375 0.265625,0.484375 0.453125,0.484375 0.25,0 0.484375,-0.15625 0.484375,-0.484375 0,-0.359375 -0.328125,-0.6875 -0.84375,-0.6875 -1.015625,0 -1.359375,1.09375 -1.421875,1.328125 H 1.9375 v -1.328125 l -1.609375,0.125 v 0.34375 c 0.8125,0 0.921875,0.09375 0.921875,0.671875 v 3.234375 c 0,0.546875 -0.140625,0.546875 -0.921875,0.546875 V 0 c 0.34375,-0.03125 1,-0.03125 1.359375,-0.03125 0.328125,0 1.171875,0 1.4375,0.03125 V -0.34375 H 2.890625 C 2.015625,-0.34375 2,-0.484375 2,-0.90625 Z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
</g>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
sodipodi:insensitive="true"
|
||||
style="display:inline"
|
||||
transform="translate(0,-267.00004)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
ry="4.8109269"
|
||||
y="267.27731"
|
||||
x="0.27727795"
|
||||
height="29.445444"
|
||||
width="29.445444"
|
||||
id="rect863"
|
||||
style="fill:url(#linearGradient4833);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4806);stroke-width:0.55500001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
inkscape:label="GDS"
|
||||
id="layer2"
|
||||
inkscape:groupmode="layer"
|
||||
sodipodi:insensitive="true">
|
||||
<g
|
||||
transform="matrix(1.1803494,0,0,1.1803494,-3.0934521,2.5343859)"
|
||||
id="g4860">
|
||||
<rect
|
||||
style="fill:#5c3566;fill-opacity:1;fill-rule:nonzero;stroke:#5c3566;stroke-width:0.03089017;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4722-9"
|
||||
width="7.315506"
|
||||
height="2.6185424"
|
||||
x="17.855755"
|
||||
y="2.8206506" />
|
||||
<rect
|
||||
style="fill:#5c3566;fill-opacity:1;fill-rule:nonzero;stroke:#5c3566;stroke-width:0.03089017;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4722"
|
||||
width="7.315506"
|
||||
height="2.6185424"
|
||||
x="5.0017018"
|
||||
y="2.8206506" />
|
||||
<rect
|
||||
style="fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.18781857;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4647"
|
||||
width="21.451309"
|
||||
height="5.3823962"
|
||||
x="4.4756289"
|
||||
y="5.5161438"
|
||||
ry="0.57490903" />
|
||||
<path
|
||||
style="fill:#5c3566;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.4249042;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10.647111,2.1885173 c 1.371044,1.5346563 7.602828,2.1172607 8.900202,0 V 5.445367 h -8.900202 z"
|
||||
id="rect4673"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:0.09766429;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10.743177,2.1889465 v 1.1220392 l 1.692999,1.126e-4 0.846062,1.2390311 h 1.693 2.051725 l 0.826813,-1.2343732 h 1.693537 V 2.1885173 H 17.515176 L 16.669114,3.4240551 H 14.975238 13.620839 L 12.7949,2.1885173 Z"
|
||||
id="path4655"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccc" />
|
||||
<path
|
||||
style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:0.12909999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10.444636,4.7267469 9.7322177,4.2143924 8.4348855,4.2137428 7.1896962,2.1729032 H 4.4609914 v 1.1220392 h 1.6548333 l 0.8269886,2.1548987 h 1.6548343 l 1.8914814,0.011475 z"
|
||||
id="path4655-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<rect
|
||||
style="fill:#cc0000;fill-opacity:1;fill-rule:nonzero;stroke:#cc0000;stroke-width:0.03570647;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4703"
|
||||
width="2.6473525"
|
||||
height="0.67746186"
|
||||
x="13.879735"
|
||||
y="4.5986104"
|
||||
ry="0" />
|
||||
<path
|
||||
style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:0.13003762;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 19.828607,4.7038749 0.722805,-0.5123545 1.316244,-6.495e-4 1.263343,-2.0408398 h 2.768485 v 1.1220392 h -1.678958 l -0.839046,2.154899 h -1.678958 l -1.919057,0.011474 z"
|
||||
id="path4655-6-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
style="fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#73d216;stroke-width:0.06713366;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 6.5082658,5.4557442 v 1.4172746 1.225227 l 0.038859,0.1943268 v 0 c 0.128985,0.3512949 0.5947729,0.6114739 1.1565142,0.6114739 h 5.351728 c 0.561743,0 1.063373,-0.2021525 1.192356,-0.5534475 l 0.0031,-0.058026 V 8.0982458 6.8730188 5.4557442 Z"
|
||||
id="rect4739"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccsscccccc" />
|
||||
<path
|
||||
style="fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#73d216;stroke-width:0.0674862;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 16.02714,5.4330487 v 1.4171297 1.2251018 l 0.03927,0.1943069 v 0 c 0.13036,0.3512589 0.601098,0.6114113 1.168812,0.6114113 h 5.408637 c 0.567714,0 1.074679,-0.2021319 1.205035,-0.5533908 l 0.0031,-0.05802 V 8.0752802 6.8501784 5.4330487 Z"
|
||||
id="rect4739-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccsscccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="lx-text4864"
|
||||
transform="matrix(0.38106292,0,0,0.38106292,2.3851025,22.428875)">
|
||||
<defs
|
||||
id="defs4924">
|
||||
<g
|
||||
id="g5236">
|
||||
<symbol
|
||||
id="symbol5198"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5196"
|
||||
d=""
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5202"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5200"
|
||||
d="m 7.78125,-2.359375 c 0,-0.46875 0.046875,-0.53125 0.8125,-0.53125 v -0.34375 c -0.3125,0.015625 -1.140625,0.015625 -1.5,0.015625 -0.375,0 -1.421875,0 -1.734375,-0.015625 v 0.34375 H 5.71875 c 1.0625,0 1.09375,0.140625 1.09375,0.578125 v 0.765625 c 0,1.359375 -1.5625,1.453125 -1.875,1.453125 -0.9375,0 -3.1875,-0.578125 -3.1875,-4 0,-3.453125 2.265625,-3.96875 3.109375,-3.96875 1.03125,0 2.28125,0.75 2.59375,2.859375 0.015625,0.140625 0.015625,0.171875 0.15625,0.171875 0.171875,0 0.171875,-0.03125 0.171875,-0.28125 v -2.828125 c 0,-0.21875 0,-0.28125 -0.125,-0.28125 -0.0625,0 -0.078125,0.03125 -0.15625,0.15625 l -0.578125,0.9375 C 6.578125,-7.75 5.84375,-8.421875 4.703125,-8.421875 c -2.15625,0 -4.0625,1.890625 -4.0625,4.328125 0,2.484375 1.90625,4.34375 4.078125,4.34375 0.84375,0 1.8125,-0.28125 2.265625,-1.03125 0.21875,0.375 0.609375,0.765625 0.703125,0.765625 0.09375,0 0.09375,-0.0625 0.09375,-0.265625 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5206"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5204"
|
||||
d="m 0.5,-8.15625 v 0.34375 h 0.234375 c 0.875,0 0.90625,0.109375 0.90625,0.5625 v 6.34375 c 0,0.4375 -0.03125,0.5625 -0.90625,0.5625 H 0.5 V 0 h 4.1875 c 2,0 3.59375,-1.796875 3.59375,-4 0,-2.3125 -1.609375,-4.15625 -3.59375,-4.15625 z m 2.625,7.8125 c -0.515625,0 -0.546875,-0.09375 -0.546875,-0.484375 V -7.34375 c 0,-0.390625 0.03125,-0.46875 0.546875,-0.46875 h 1.265625 c 0.984375,0 1.78125,0.46875 2.265625,1.265625 0.546875,0.84375 0.546875,2.046875 0.546875,2.53125 0,0.671875 -0.015625,1.796875 -0.703125,2.671875 -0.390625,0.5 -1.109375,1 -2.109375,1 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5210"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5208"
|
||||
d="M 2.484375,-4.984375 C 1.875,-5.140625 1.34375,-5.734375 1.34375,-6.5 c 0,-0.84375 0.671875,-1.59375 1.59375,-1.59375 1.96875,0 2.21875,1.9375 2.296875,2.453125 0.03125,0.140625 0.03125,0.1875 0.140625,0.1875 0.140625,0 0.140625,-0.0625 0.140625,-0.265625 v -2.421875 c 0,-0.21875 0,-0.28125 -0.125,-0.28125 -0.03125,0 -0.078125,0 -0.171875,0.15625 L 4.828125,-7.53125 C 4.25,-8.265625 3.46875,-8.421875 2.9375,-8.421875 c -1.328125,0 -2.296875,1.078125 -2.296875,2.296875 0,0.5625 0.203125,1.09375 0.65625,1.578125 0.40625,0.453125 0.828125,0.5625 1.671875,0.78125 0.421875,0.09375 1.078125,0.265625 1.25,0.328125 0.5625,0.28125 0.9375,0.921875 0.9375,1.59375 0,0.90625 -0.640625,1.75 -1.625,1.75 -0.546875,0 -1.28125,-0.140625 -1.875,-0.640625 -0.6875,-0.625 -0.734375,-1.484375 -0.75,-1.890625 -0.015625,-0.09375 -0.109375,-0.09375 -0.125,-0.09375 -0.140625,0 -0.140625,0.0625 -0.140625,0.28125 v 2.40625 c 0,0.21875 0,0.28125 0.125,0.28125 C 0.84375,0.25 0.84375,0.234375 0.9375,0.078125 0.984375,-0.015625 1.234375,-0.453125 1.328125,-0.640625 1.75,-0.15625 2.515625,0.25 3.53125,0.25 4.875,0.25 5.84375,-0.890625 5.84375,-2.203125 5.84375,-2.921875 5.5625,-3.46875 5.25,-3.859375 4.8125,-4.40625 4.265625,-4.53125 3.796875,-4.65625 Z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5214"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5212"
|
||||
d="M 3.234375,-2.265625 V -2.90625 H 0.125 v 0.640625 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5218"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5216"
|
||||
d="m 5.046875,-4.0625 c 1.1875,-0.28125 2.09375,-1.03125 2.09375,-1.953125 0,-1.15625 -1.34375,-2.140625 -3.0625,-2.140625 H 0.5 v 0.34375 h 0.234375 c 0.875,0 0.90625,0.109375 0.90625,0.5625 v 6.34375 c 0,0.4375 -0.03125,0.5625 -0.90625,0.5625 H 0.5 V 0 c 0.28125,-0.03125 1.25,-0.03125 1.609375,-0.03125 0.34375,0 1.328125,0 1.609375,0.03125 V -0.34375 H 3.484375 c -0.859375,0 -0.90625,-0.125 -0.90625,-0.5625 v -3.0625 H 3.96875 c 0.46875,0 0.90625,0.125 1.234375,0.46875 0.40625,0.453125 0.40625,0.703125 0.40625,1.53125 0,0.9375 0,1.25 0.515625,1.765625 C 6.3125,-0.03125 6.8125,0.25 7.484375,0.25 c 0.9375,0 1.09375,-1.03125 1.09375,-1.296875 0,-0.0625 0,-0.171875 -0.140625,-0.171875 -0.125,0 -0.125,0.078125 -0.125,0.1875 C 8.25,-0.3125 7.90625,0.015625 7.515625,0.015625 6.96875,0.015625 6.84375,-0.546875 6.75,-1.1875 6.734375,-1.265625 6.671875,-1.78125 6.640625,-2.078125 6.546875,-2.671875 6.5,-3.0625 6.140625,-3.4375 c -0.125,-0.125 -0.4375,-0.453125 -1.09375,-0.625 z m -1.125,-0.140625 H 2.578125 V -7.34375 c 0,-0.265625 0,-0.40625 0.25,-0.46875 0.109375,0 0.46875,0 0.703125,0 0.96875,0 2.5,0 2.5,1.796875 0,1.046875 -0.5625,1.8125 -2.109375,1.8125 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5222"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5220"
|
||||
d="m 4.578125,-2.765625 c 0.265625,0 0.28125,0 0.28125,-0.234375 0,-1.203125 -0.640625,-2.328125 -2.09375,-2.328125 -1.359375,0 -2.40625,1.234375 -2.40625,2.703125 0,1.578125 1.21875,2.75 2.546875,2.75 1.421875,0 1.953125,-1.296875 1.953125,-1.546875 0,-0.078125 -0.046875,-0.125 -0.125,-0.125 -0.09375,0 -0.125,0.0625 -0.140625,0.125 -0.3125,1 -1.109375,1.28125 -1.625,1.28125 -0.5,0 -1.703125,-0.34375 -1.703125,-2.40625 v -0.21875 z M 1.28125,-3 c 0.09375,-1.875 1.140625,-2.09375 1.484375,-2.09375 1.28125,0 1.34375,1.6875 1.359375,2.09375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5226"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5224"
|
||||
d="m 5.3125,-2.90625 c 0,-1.109375 0,-1.4375 -0.265625,-1.828125 -0.34375,-0.46875 -0.90625,-0.53125 -1.3125,-0.53125 -1.171875,0 -1.625,0.984375 -1.71875,1.21875 v -1.21875 l -1.640625,0.125 v 0.34375 c 0.8125,0 0.921875,0.09375 0.921875,0.671875 v 3.234375 c 0,0.546875 -0.140625,0.546875 -0.921875,0.546875 V 0 c 0.3125,-0.03125 0.96875,-0.03125 1.296875,-0.03125 0.34375,0 1,0 1.296875,0.03125 v -0.34375 c -0.75,0 -0.90625,0 -0.90625,-0.546875 v -2.21875 c 0,-1.25 0.828125,-1.921875 1.578125,-1.921875 0.734375,0 0.90625,0.609375 0.90625,1.34375 v 2.796875 c 0,0.546875 -0.140625,0.546875 -0.90625,0.546875 V 0 c 0.296875,-0.03125 0.953125,-0.03125 1.28125,-0.03125 0.34375,0 1,0 1.3125,0.03125 v -0.34375 c -0.609375,0 -0.90625,0 -0.921875,-0.359375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5230"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5228"
|
||||
d="M 3.578125,-8.15625 V -7.8125 C 4.40625,-7.8125 4.5,-7.734375 4.5,-7.140625 V -4.5 C 4.25,-4.859375 3.734375,-5.265625 3,-5.265625 c -1.390625,0 -2.578125,1.171875 -2.578125,2.703125 0,1.515625 1.125,2.6875 2.453125,2.6875 0.90625,0 1.421875,-0.609375 1.59375,-0.828125 V 0.125 L 6.15625,0 V -0.34375 C 5.34375,-0.34375 5.25,-0.4375 5.25,-1.015625 v -7.28125 z m 0.890625,6.75 c 0,0.21875 0,0.265625 -0.171875,0.515625 -0.28125,0.421875 -0.765625,0.765625 -1.375,0.765625 -0.296875,0 -1.59375,-0.109375 -1.59375,-2.4375 0,-0.859375 0.140625,-1.328125 0.40625,-1.734375 0.234375,-0.359375 0.71875,-0.734375 1.3125,-0.734375 0.75,0 1.15625,0.53125 1.28125,0.734375 0.140625,0.203125 0.140625,0.21875 0.140625,0.4375 z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="symbol5234"
|
||||
overflow="visible"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5232"
|
||||
d="m 2,-2.78125 c 0,-1.15625 0.46875,-2.25 1.390625,-2.25 0.09375,0 0.125,0 0.171875,0.015625 -0.09375,0.046875 -0.28125,0.109375 -0.28125,0.4375 0,0.34375 0.265625,0.484375 0.453125,0.484375 0.25,0 0.484375,-0.15625 0.484375,-0.484375 0,-0.359375 -0.328125,-0.6875 -0.84375,-0.6875 -1.015625,0 -1.359375,1.09375 -1.421875,1.328125 H 1.9375 v -1.328125 l -1.609375,0.125 v 0.34375 c 0.8125,0 0.921875,0.09375 0.921875,0.671875 v 3.234375 c 0,0.546875 -0.140625,0.546875 -0.921875,0.546875 V 0 c 0.34375,-0.03125 1,-0.03125 1.359375,-0.03125 0.328125,0 1.171875,0 1.4375,0.03125 V -0.34375 H 2.890625 C 2.015625,-0.34375 2,-0.484375 2,-0.90625 Z m 0,0"
|
||||
style="stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
</g>
|
||||
</defs>
|
||||
<g
|
||||
id="lx-text4864-surface1">
|
||||
<g
|
||||
id="g4946"
|
||||
style="fill:#000000;fill-opacity:1">
|
||||
<use
|
||||
id="use4926"
|
||||
y="0"
|
||||
x="0"
|
||||
xlink:href="#lx-text4864-glyph0-1"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4928"
|
||||
y="0"
|
||||
x="9.1851797"
|
||||
xlink:href="#lx-text4864-glyph0-2"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4930"
|
||||
y="0"
|
||||
x="18.125278"
|
||||
xlink:href="#lx-text4864-glyph0-3"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4932"
|
||||
y="0"
|
||||
x="24.628908"
|
||||
xlink:href="#lx-text4864-glyph0-4"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4934"
|
||||
y="0"
|
||||
x="28.531084"
|
||||
xlink:href="#lx-text4864-glyph0-5"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4936"
|
||||
y="0"
|
||||
x="37.146004"
|
||||
xlink:href="#lx-text4864-glyph0-6"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4938"
|
||||
y="0"
|
||||
x="42.348904"
|
||||
xlink:href="#lx-text4864-glyph0-7"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4940"
|
||||
y="0"
|
||||
x="48.852535"
|
||||
xlink:href="#lx-text4864-glyph0-8"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4942"
|
||||
y="0"
|
||||
x="55.356163"
|
||||
xlink:href="#lx-text4864-glyph0-6"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4944"
|
||||
y="0"
|
||||
x="60.559067"
|
||||
xlink:href="#lx-text4864-glyph0-9"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 29 KiB |
@@ -17,11 +17,35 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file latex-output.c
|
||||
* @brief LaTeX output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include "latex-output.h"
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @addtogroup LaTeX-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Writes a GString \p buffer to the fixed file tex_file */
|
||||
#define WRITEOUT_BUFFER(buff) fwrite((buff)->str, sizeof(char), (buff)->len, tex_file)
|
||||
|
||||
/**
|
||||
* @brief Write the layer declarration to TeX file
|
||||
*
|
||||
* This writes the declaration of the layers and the mapping in which order
|
||||
* the layers shall be rendered by TikZ. Layers are written in the order they are
|
||||
* positioned inside the \p layer_infos list.
|
||||
*
|
||||
* @param tex_file TeX-File to write to
|
||||
* @param layer_infos List containing layer_info structs.
|
||||
* @param buffer
|
||||
* @note The field layer_info::stacked_position is ignored. Stack depends on list order.
|
||||
*/
|
||||
static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString *buffer)
|
||||
{
|
||||
GList *list;
|
||||
@@ -53,11 +77,30 @@ static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write_layer_env
|
||||
* @param tex_file
|
||||
* @param layer
|
||||
* @param buffer
|
||||
* @return TRUE if layer is placeable
|
||||
* @brief Write layer Envirmonment
|
||||
*
|
||||
* If the requested layer shall be rendered, this code writes the necessary code
|
||||
* to open the layer. It also returns the color the layer shall be rendered in.
|
||||
*
|
||||
* The followingenvironments are generated:
|
||||
*
|
||||
* @code{.tex}
|
||||
* \begin{pgfonlayer}{<layer>}
|
||||
* % If pdf layers shall be used also this is enabled:
|
||||
* \begin{scope}[ocg={ref=<layer>, status=visible,name={<Layer Name>}}]
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* If the layer shall not be rendered, FALSE is returned and the color is not filled in and
|
||||
* the cod eis not written to the file.
|
||||
*
|
||||
* @param tex_file TeX file to write to
|
||||
* @param color Return of the layer's color
|
||||
* @param layer Requested layer number
|
||||
* @param linfo Layer information list containing layer_info structs
|
||||
* @param buffer Some working buffer
|
||||
* @return TRUE, if the layer shall be rendered.
|
||||
* @note The opened environments have to be closed afterwards
|
||||
*/
|
||||
static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList *linfo, GString *buffer)
|
||||
{
|
||||
@@ -71,7 +114,7 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
|
||||
color->red = inf->color.red;
|
||||
color->green = inf->color.green;
|
||||
color->blue = inf->color.blue;
|
||||
g_string_printf(buffer, "\\begin{pgfonlayer}{l%d}\n\\ifcreatepdflayers\n\\begin{scope}[ocg={ref=%d, status=visible,name={%s}}]\n\\fi]\n",
|
||||
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;
|
||||
@@ -80,7 +123,17 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Writes a graphics object to the specified tex_file
|
||||
*
|
||||
* This function opens the layer, writes a graphics object and closes the layer
|
||||
*
|
||||
* @param tex_file File to write to
|
||||
* @param graphics Object to render
|
||||
* @param linfo Layer information
|
||||
* @param buffer Working buffer
|
||||
* @param scale Scale abject down by this value
|
||||
*/
|
||||
static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GString *buffer, double scale)
|
||||
{
|
||||
GList *temp;
|
||||
@@ -144,7 +197,14 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
|
||||
} /* For graphics */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Render cell to file
|
||||
* @param cell Cell to render
|
||||
* @param layer_infos Layer information
|
||||
* @param tex_file File to write to
|
||||
* @param buffer Working buffer
|
||||
* @param scale Scale output down by this value
|
||||
*/
|
||||
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale)
|
||||
{
|
||||
|
||||
@@ -238,3 +298,5 @@ void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *
|
||||
fflush(tex_file);
|
||||
g_string_free(working_line, TRUE);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,17 +17,39 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file latex-output.h
|
||||
* @brief LaTeX output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef __LATEX_OUTPUT_H__
|
||||
#define __LATEX_OUTPUT_H__
|
||||
|
||||
/**
|
||||
* @addtogroup LaTeX-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "../gds-parser/gds-types.h"
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include "../layer-selector.h"
|
||||
#include "../mapping-parser.h"
|
||||
|
||||
#define LATEX_LINE_BUFFER_KB (10)
|
||||
#define LATEX_LINE_BUFFER_KB (10) /**< @brief Buffer for LaTeX Code line in KiB */
|
||||
|
||||
/**
|
||||
* @brief Render \p cell to LateX/TikZ code
|
||||
* @param cell Cell to render
|
||||
* @param layer_infos Layer information
|
||||
* @param tex_file Already opened file to write data in
|
||||
* @param scale Scale image down by this value
|
||||
* @param create_pdf_layers Optional content groups used
|
||||
* @param standalone_document document can be compiled standalone
|
||||
*/
|
||||
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__ */
|
||||
|
231
layer-selector/layer-selector-dnd.c
Normal file
231
layer-selector/layer-selector-dnd.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original Drag and Drop Code taken from:
|
||||
* https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/tests/testlist3.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-selector-dnd.c
|
||||
* @brief This file implements the drag and drop functions regarding the list box containing the layer elements
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include "layer-selector-dnd.h"
|
||||
|
||||
static GtkTargetEntry entries[] = {
|
||||
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
|
||||
};
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
|
||||
{
|
||||
int i;
|
||||
GtkListBoxRow *row;
|
||||
|
||||
row = NULL;
|
||||
for (i = 0; ; i++) {
|
||||
GtkListBoxRow *tmp;
|
||||
tmp = gtk_list_box_get_row_at_index(list, i);
|
||||
if (tmp == NULL)
|
||||
break;
|
||||
row = tmp;
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_row_before (GtkListBox *list, GtkListBoxRow *row)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = gtk_list_box_row_get_index (row);
|
||||
return gtk_list_box_get_row_at_index (list, pos - 1);
|
||||
}
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_row_after (GtkListBox *list, GtkListBoxRow *row)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = gtk_list_box_row_get_index(row);
|
||||
return gtk_list_box_get_row_at_index(list, pos + 1);
|
||||
}
|
||||
|
||||
static void layer_selector_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
||||
GtkSelectionData *selection_data, guint info, guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *row_before, *row_after;
|
||||
GtkWidget *row;
|
||||
GtkWidget *source;
|
||||
int pos;
|
||||
|
||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||
|
||||
g_object_set_data(G_OBJECT(widget), "row-before", NULL);
|
||||
g_object_set_data(G_OBJECT(widget), "row-after", NULL);
|
||||
|
||||
if (row_before)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||
if (row_after)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||
|
||||
row = (gpointer) *((gpointer *)gtk_selection_data_get_data(selection_data));
|
||||
source = gtk_widget_get_ancestor(row, GTK_TYPE_LIST_BOX_ROW);
|
||||
|
||||
if (source == row_after)
|
||||
return;
|
||||
|
||||
g_object_ref(source);
|
||||
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(source)), source);
|
||||
|
||||
if (row_after)
|
||||
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_after));
|
||||
else
|
||||
pos = gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row_before)) + 1;
|
||||
|
||||
gtk_list_box_insert(GTK_LIST_BOX(widget), source, pos);
|
||||
g_object_unref(source);
|
||||
}
|
||||
|
||||
static gboolean layer_selector_drag_motion(GtkWidget *widget, GdkDragContext *context, int x, int y, guint time)
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
GtkWidget *row;
|
||||
int hover_row_y;
|
||||
int hover_row_height;
|
||||
GtkWidget *drag_row;
|
||||
GtkWidget *row_before;
|
||||
GtkWidget *row_after;
|
||||
|
||||
row = GTK_WIDGET(gtk_list_box_get_row_at_y(GTK_LIST_BOX(widget), y));
|
||||
|
||||
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||
if (row_before)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||
if (row_after)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||
|
||||
if (row) {
|
||||
gtk_widget_get_allocation(row, &alloc);
|
||||
hover_row_y = alloc.y;
|
||||
hover_row_height = alloc.height;
|
||||
|
||||
if (y < hover_row_y + hover_row_height/2) {
|
||||
row_after = row;
|
||||
row_before = GTK_WIDGET(layer_selector_get_row_before(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
|
||||
} else {
|
||||
row_before = row;
|
||||
row_after = GTK_WIDGET(layer_selector_get_row_after(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
|
||||
}
|
||||
} else {
|
||||
row_before = GTK_WIDGET(layer_selector_get_last_row(GTK_LIST_BOX(widget)));
|
||||
row_after = NULL;
|
||||
}
|
||||
|
||||
g_object_set_data(G_OBJECT(widget), "row-before", row_before);
|
||||
g_object_set_data(G_OBJECT(widget), "row-after", row_after);
|
||||
|
||||
if (drag_row == row_before || drag_row == row_after) {
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (row_before)
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||
if (row_after)
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void layer_selector_drag_leave(GtkWidget *widget, GdkDragContext *context, guint time)
|
||||
{
|
||||
GtkWidget *drag_row;
|
||||
GtkWidget *row_before;
|
||||
GtkWidget *row_after;
|
||||
|
||||
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(drag_row), "drag-hover");
|
||||
if (row_before)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_before), "drag-hover-bottom");
|
||||
if (row_after)
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row_after), "drag-hover-top");
|
||||
|
||||
}
|
||||
|
||||
static const char *dnd_additional_css =
|
||||
".row:not(:first-child) { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:first-child { "
|
||||
" border-top: 1px solid transparent; "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:last-child { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid alpha(gray,0.5); "
|
||||
"}"
|
||||
".row.drag-icon { "
|
||||
" background: #282828; "
|
||||
" border: 1px solid blue; "
|
||||
"}"
|
||||
".row.drag-row { "
|
||||
" color: gray; "
|
||||
" background: alpha(gray,0.2); "
|
||||
"}"
|
||||
".row.drag-row.drag-hover { "
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover image, "
|
||||
".row.drag-hover label { "
|
||||
" color: #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-top {"
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-bottom {"
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}";
|
||||
|
||||
void layer_selector_list_box_setup_dnd(GtkListBox *box)
|
||||
{
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, dnd_additional_css, -1, NULL);
|
||||
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (provider), 800);
|
||||
|
||||
gtk_drag_dest_set(GTK_WIDGET(box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, entries, 1, GDK_ACTION_MOVE);
|
||||
g_signal_connect(box, "drag-data-received", G_CALLBACK(layer_selector_drag_data_received), NULL);
|
||||
g_signal_connect(box, "drag-motion", G_CALLBACK(layer_selector_drag_motion), NULL);
|
||||
g_signal_connect(box, "drag-leave", G_CALLBACK(layer_selector_drag_leave), NULL);
|
||||
|
||||
}
|
33
layer-selector/layer-selector-dnd.h
Normal file
33
layer-selector/layer-selector-dnd.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-selector-dnd.h
|
||||
* @brief Header for drag and drop of layer selector
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _LAYER_SELECTOR_DND_H_
|
||||
#define _LAYER_SELECTOR_DND_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
void layer_selector_list_box_setup_dnd(GtkListBox *box);
|
||||
|
||||
#endif /* _LAYER_SELECTOR_DND_H_ */
|
@@ -17,9 +17,20 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-selector.c
|
||||
* @brief Implementation of the layer selector
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "layer-selector.h"
|
||||
#include "gds-parser/gds-parser.h"
|
||||
#include "widgets/layer-element.h"
|
||||
#include "../gds-parser/gds-parser.h"
|
||||
#include "../widgets/layer-element.h"
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -89,6 +100,11 @@ void clear_list_box_widgets(GtkListBox *box)
|
||||
gtk_widget_set_sensitive(global_save_button, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if specific layer number is present in list box
|
||||
* @param layer Layer nu,ber
|
||||
* @return TRUE if present
|
||||
*/
|
||||
static gboolean check_if_layer_widget_exists(int layer) {
|
||||
GList *list;
|
||||
GList *temp;
|
||||
@@ -110,6 +126,11 @@ static gboolean check_if_layer_widget_exists(int layer) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Analyze \p cell and append used layers to list box
|
||||
* @param listbox listbox to add layer
|
||||
* @param cell Cell to analyze
|
||||
*/
|
||||
static void analyze_cell_layers(GtkListBox *listbox, struct gds_cell *cell)
|
||||
{
|
||||
GList *graphics;
|
||||
@@ -129,16 +150,35 @@ static void analyze_cell_layers(GtkListBox *listbox, struct gds_cell *cell)
|
||||
}
|
||||
}
|
||||
|
||||
gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
||||
/**
|
||||
* @brief sort_func Sort callback for list box
|
||||
* @param row1
|
||||
* @param row2
|
||||
* @param unused
|
||||
* @note Do not use this function. This is an internal callback
|
||||
* @return See sort function documentation of GTK+
|
||||
*/
|
||||
static gint sort_func(GtkListBoxRow *row1, GtkListBoxRow *row2, gpointer unused)
|
||||
{
|
||||
LayerElement *le1, *le2;
|
||||
gint ret;
|
||||
static const enum layer_selector_sort_algo default_sort = LAYER_SELECTOR_SORT_DOWN;
|
||||
const enum layer_selector_sort_algo *algo = (const enum layer_selector_sort_algo *)unused;
|
||||
|
||||
/* Assume downward sorting */
|
||||
/* TODO: This is nasty. Find a better way */
|
||||
if (!algo)
|
||||
algo = &default_sort;
|
||||
|
||||
le1 = LAYER_ELEMENT(row1);
|
||||
le2 = LAYER_ELEMENT(row2);
|
||||
|
||||
/* Determine sort fow downward sort */
|
||||
ret = layer_element_get_layer(le1) - layer_element_get_layer(le2);
|
||||
|
||||
/* Change order if upward sort is requested */
|
||||
ret *= (*algo == LAYER_SELECTOR_SORT_DOWN ? 1 : -1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -150,7 +190,6 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
||||
global_list_box = listbox;
|
||||
|
||||
clear_list_box_widgets(listbox);
|
||||
gtk_list_box_set_sort_func(listbox, sort_func, NULL, NULL);
|
||||
|
||||
for (; libs != NULL; libs = libs->next) {
|
||||
lib = (struct gds_library *)libs->data;
|
||||
@@ -159,11 +198,8 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
||||
} /* For Cell List */
|
||||
} /* For libs */
|
||||
|
||||
/* Force sort */
|
||||
gtk_list_box_invalidate_sort(listbox);
|
||||
|
||||
/* Disable sort, so user can sort layers */
|
||||
gtk_list_box_set_sort_func(listbox, NULL, NULL, NULL);
|
||||
/* Sort the layers */
|
||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_DOWN);
|
||||
|
||||
/* Activate Buttons */
|
||||
gtk_widget_set_sensitive(global_load_button, TRUE);
|
||||
@@ -171,78 +207,11 @@ void generate_layer_widgets(GtkListBox *listbox, GList *libs)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load_csv_line
|
||||
* @param file
|
||||
* @param export
|
||||
* @param name
|
||||
* @param layer
|
||||
* @param color
|
||||
* @param opacity
|
||||
* @return 0 if succesfull, 1 if line was malformatted or parameters are broken, -1 if file end
|
||||
* @brief Find LayerElement in list with specified layer number
|
||||
* @param el_list List with elements of type LayerElement
|
||||
* @param layer Layer number
|
||||
* @return Found LayerElement. If nothing is found, NULL.
|
||||
*/
|
||||
static int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
|
||||
{
|
||||
int ret;
|
||||
gsize len;
|
||||
gchar *line;
|
||||
GRegex *regex;
|
||||
GMatchInfo *mi;
|
||||
char *match;
|
||||
|
||||
if ((!export) || (!name) || (!layer) || (!color)) {
|
||||
ret = 1;
|
||||
goto ret_direct;
|
||||
}
|
||||
|
||||
regex = g_regex_new("^(?<layer>[0-9]+),(?<r>[0-9\\.]+),(?<g>[0-9\\.]+),(?<b>[0-9\\.]+),(?<a>[0-9\\.]+),(?<export>[01]),(?<name>.*)$", 0, 0, NULL);
|
||||
|
||||
line = g_data_input_stream_read_line(stream, &len, NULL, NULL);
|
||||
if (!line) {
|
||||
ret = -1;
|
||||
goto destroy_regex;
|
||||
}
|
||||
|
||||
/* Match line in CSV */
|
||||
g_regex_match(regex, line, 0, &mi);
|
||||
if (g_match_info_matches(mi)) {
|
||||
/* Line is valid */
|
||||
match = g_match_info_fetch_named(mi, "layer");
|
||||
*layer = (int)g_ascii_strtoll(match, NULL, 10);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "r");
|
||||
color->red = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "g");
|
||||
color->green = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "b");
|
||||
color->blue = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "a");
|
||||
color->alpha = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "export");
|
||||
*export = ((!strcmp(match, "1")) ? TRUE : FALSE);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "name");
|
||||
*name = match;
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Line is malformatted */
|
||||
printf("Could not recognize line in CSV as valid entry: %s\n", line);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
g_match_info_free(mi);
|
||||
g_free(line);
|
||||
destroy_regex:
|
||||
g_regex_unref(regex);
|
||||
ret_direct:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static LayerElement *find_layer_element_in_list(GList *el_list, int layer)
|
||||
{
|
||||
LayerElement *ret = NULL;
|
||||
@@ -255,6 +224,10 @@ static LayerElement *find_layer_element_in_list(GList *el_list, int layer)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load file and apply layer definitions to listbox
|
||||
* @param file_name CSV Layer Mapping File
|
||||
*/
|
||||
static void load_layer_mapping_from_file(gchar *file_name)
|
||||
{
|
||||
GFile *file;
|
||||
@@ -325,6 +298,11 @@ destroy_file:
|
||||
g_object_unref(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for Load Mapping Button
|
||||
* @param button
|
||||
* @param user_data
|
||||
*/
|
||||
static void load_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
@@ -342,8 +320,15 @@ static void load_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create Line for LayerMapping file with supplied information
|
||||
* @param layer_element information
|
||||
* @param line_buffer buffer to write to
|
||||
* @param max_len Maximum length that cna be used in \p line_buffer
|
||||
*/
|
||||
static void create_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
|
||||
{
|
||||
int i;
|
||||
GString *string;
|
||||
gboolean export;
|
||||
const gchar *name;
|
||||
@@ -359,9 +344,19 @@ static void create_csv_line(LayerElement *layer_element, char *line_buffer, size
|
||||
layer_element_get_color(layer_element, &color);
|
||||
|
||||
/* print values to line */
|
||||
g_string_printf(string, "%d,%lf,%lf,%lf,%lf,%d,%s\n",
|
||||
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);
|
||||
/* Fix broken locale settings */
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ',')
|
||||
string->str[i] = '.';
|
||||
}
|
||||
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ':')
|
||||
string->str[i] = ',';
|
||||
}
|
||||
|
||||
if (string->len > (max_len-1)) {
|
||||
printf("Layer Definition too long. Please shorten Layer Name!!\n");
|
||||
@@ -377,6 +372,11 @@ static void create_csv_line(LayerElement *layer_element, char *line_buffer, size
|
||||
g_string_free(string, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Save layer mapping of whole list box into file
|
||||
* @param file_name layer mapping file
|
||||
* @param list_box listbox
|
||||
*/
|
||||
static void save_layer_mapping_data(const gchar *file_name, GtkListBox *list_box)
|
||||
{
|
||||
FILE *file;
|
||||
@@ -404,6 +404,11 @@ static void save_layer_mapping_data(const gchar *file_name, GtkListBox *list_box
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for Save Layer Mapping Button
|
||||
* @param button
|
||||
* @param user_data
|
||||
*/
|
||||
static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
@@ -412,6 +417,8 @@ static void save_mapping_clicked(GtkWidget *button, gpointer user_data)
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(user_data), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"Cancel", GTK_RESPONSE_CANCEL, "Save Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
if (res == GTK_RESPONSE_ACCEPT) {
|
||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
@@ -434,3 +441,16 @@ void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window)
|
||||
global_save_button = button;
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(save_mapping_clicked), main_window);
|
||||
}
|
||||
|
||||
void layer_selector_force_sort(enum layer_selector_sort_algo sort_function)
|
||||
{
|
||||
if (!global_list_box)
|
||||
return;
|
||||
|
||||
/* Set dorting function, sort, and disable sorting function */
|
||||
gtk_list_box_set_sort_func(global_list_box, sort_func, (gpointer)&sort_function, NULL);
|
||||
gtk_list_box_invalidate_sort(global_list_box);
|
||||
gtk_list_box_set_sort_func(global_list_box, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/** @} */
|
82
layer-selector/layer-selector.h
Normal file
82
layer-selector/layer-selector.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-selector.h
|
||||
* @brief Implementation of the Layer selection list
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef __LAYER_SELECTOR_H__
|
||||
#define __LAYER_SELECTOR_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include "../mapping-parser.h"
|
||||
|
||||
/**
|
||||
* @brief Defines how to sort the layer selector list box.
|
||||
*/
|
||||
enum layer_selector_sort_algo {LAYER_SELECTOR_SORT_DOWN = 0, LAYER_SELECTOR_SORT_UP};
|
||||
|
||||
/**
|
||||
* @brief Generate layer widgets in \p listbox
|
||||
* @note This clears all previously inserted elements
|
||||
* @param listbox
|
||||
* @param libs The library to add
|
||||
*/
|
||||
void generate_layer_widgets(GtkListBox *listbox, GList *libs);
|
||||
|
||||
/**
|
||||
* @brief Supply button for loading the layer mapping
|
||||
* @param button
|
||||
* @param main_window Parent window for dialogs
|
||||
*/
|
||||
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||
|
||||
/**
|
||||
* @brief Supply button for saving the layer mapping
|
||||
* @param button
|
||||
* @param main_window
|
||||
*/
|
||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||
|
||||
/**
|
||||
* @brief get the layer information present in the listbox of the selector
|
||||
* @return List with layer_info elements
|
||||
*/
|
||||
GList *export_rendered_layer_info();
|
||||
|
||||
/**
|
||||
* @brief Delete a layer_info struct
|
||||
* @param info Struct to be deleted.
|
||||
* @note The layer_info::name Element has to be freed manually
|
||||
*/
|
||||
void delete_layer_info_struct(struct layer_info *info);
|
||||
|
||||
/**
|
||||
* @brief Force sorting of the layer selector in a specified way
|
||||
*
|
||||
* If the layer selector is not yet set up, this function has no effect.
|
||||
*
|
||||
* @param sort_function Sorting direction
|
||||
*/
|
||||
void layer_selector_force_sort(enum layer_selector_sort_algo sort_function);
|
||||
|
||||
#endif /* __LAYER_SELECTOR_H__ */
|
228
main-window.c
228
main-window.c
@@ -17,34 +17,68 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file main-window.c
|
||||
* @brief Handling of GUI
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/** @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "main-window.h"
|
||||
#include <stdio.h>
|
||||
#include "gds-parser/gds-parser.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include "layer-selector.h"
|
||||
#include "layer-selector/layer-selector.h"
|
||||
#include "layer-selector/layer-selector-dnd.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"
|
||||
|
||||
#include "trigonometric/cell-trigonometrics.h"
|
||||
#include "version/version.h"
|
||||
#include "tree-renderer/lib-cell-renderer.h"
|
||||
#include "gds-parser/gds-tree-checker.h"
|
||||
/**
|
||||
* @brief User data supplied to callback function of the open button
|
||||
*/
|
||||
struct open_button_data {
|
||||
GtkWindow *main_window;
|
||||
GList **list_ptr;
|
||||
GtkTreeStore *cell_store;
|
||||
GtkListBox *layer_box;
|
||||
GtkSearchEntry *search_entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief User data supplied to callback function of the convert button
|
||||
*/
|
||||
struct convert_button_data {
|
||||
GtkTreeView *tree_view;
|
||||
GtkWindow *main_window;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Window close event of main window
|
||||
*
|
||||
* Closes the main window. This leads to the termination of the whole application
|
||||
* @param window main window
|
||||
* @param user not used
|
||||
* @return TRUE. This indicates that the event has been fully handled
|
||||
*/
|
||||
static gboolean on_window_close(gpointer window, gpointer user)
|
||||
{
|
||||
gtk_widget_destroy(GTK_WIDGET(window));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generate string from gds_time_field
|
||||
* @param date Date to convert
|
||||
* @return String with date
|
||||
*/
|
||||
static GString *generate_string_from_date(struct gds_time_field *date)
|
||||
{
|
||||
GString *str;
|
||||
@@ -59,7 +93,11 @@ static GString *generate_string_from_date(struct gds_time_field *date)
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function of Load GDS button
|
||||
* @param button
|
||||
* @param user Necessary Data
|
||||
*/
|
||||
static void on_load_gds(gpointer button, gpointer user)
|
||||
{
|
||||
GList *cell;
|
||||
@@ -79,9 +117,13 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
char *filename;
|
||||
GString *mod_date;
|
||||
GString *acc_date;
|
||||
unsigned int cell_error_level;
|
||||
|
||||
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);
|
||||
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();
|
||||
@@ -114,17 +156,21 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
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_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);
|
||||
gtk_tree_store_set(store, &libiter,
|
||||
CELL_SEL_LIBRARY, gds_lib,
|
||||
CELL_SEL_MODDATE, mod_date->str,
|
||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||
-1);
|
||||
|
||||
/* Check this library. This might take a while */
|
||||
(void)gds_tree_check_cell_references(gds_lib);
|
||||
(void)gds_tree_check_reference_loops(gds_lib);
|
||||
|
||||
/* Delete GStrings including string data. */
|
||||
/* Cell store copies String type data items */
|
||||
@@ -133,17 +179,28 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
|
||||
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_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);
|
||||
/* Get the checking results for this cell */
|
||||
cell_error_level = 0;
|
||||
if (gds_c->checks.unresolved_child_count)
|
||||
cell_error_level |= LIB_CELL_RENDERER_ERROR_WARN;
|
||||
|
||||
/* Check if it is completely b0rken */
|
||||
if (gds_c->checks.affected_by_reference_loop)
|
||||
cell_error_level |= LIB_CELL_RENDERER_ERROR_ERR;
|
||||
|
||||
/* Add cell to tree store model */
|
||||
gtk_tree_store_set(store, &celliter,
|
||||
CELL_SEL_CELL, gds_c,
|
||||
CELL_SEL_MODDATE, mod_date->str,
|
||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||
CELL_SEL_CELL_ERROR_STATE, cell_error_level,
|
||||
-1);
|
||||
|
||||
/* Delete GStrings including string data. */
|
||||
/* Cell store copies String type data items */
|
||||
@@ -161,11 +218,17 @@ end_destroy:
|
||||
gtk_widget_destroy(open_dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert button callback
|
||||
* @param button
|
||||
* @param user
|
||||
*/
|
||||
static void on_convert_clicked(gpointer button, gpointer user)
|
||||
{
|
||||
(void)button;
|
||||
static struct render_settings sett = {
|
||||
.scale = 1000.0f,
|
||||
.renderer = RENDERER_LATEX_TIKZ,
|
||||
.scale = 1000.0,
|
||||
.renderer = RENDERER_LATEX_TIKZ,
|
||||
};
|
||||
struct convert_button_data *data = (struct convert_button_data *)user;
|
||||
GtkTreeSelection *selection;
|
||||
@@ -179,6 +242,11 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
GtkFileFilter *filter;
|
||||
gint res;
|
||||
char *file_name;
|
||||
union bounding_box cell_box;
|
||||
unsigned int height, width;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
/* Get selected cell */
|
||||
selection = gtk_tree_view_get_selection(data->tree_view);
|
||||
@@ -193,8 +261,24 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
/* Get layers that are rendered */
|
||||
layer_list = export_rendered_layer_info();
|
||||
|
||||
/* Calculate cell size in DB units */
|
||||
bounding_box_prepare_empty(&cell_box);
|
||||
calculate_cell_bounding_box(&cell_box, cell_to_render);
|
||||
|
||||
/* Calculate size in database units
|
||||
* Note that the results are bound to be positive,
|
||||
* so casting them to unsigned int is asbsolutely valid
|
||||
*/
|
||||
height = (unsigned int)(cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y);
|
||||
width = (unsigned int)(cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x);
|
||||
|
||||
/* Show settings dialog */
|
||||
settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window));
|
||||
renderer_settings_dialog_set_settings(settings, &sett);
|
||||
renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters);
|
||||
renderer_settings_dialog_set_cell_height(settings, height);
|
||||
renderer_settings_dialog_set_cell_width(settings, width);
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(settings));
|
||||
if (res == GTK_RESPONSE_OK) {
|
||||
renderer_settings_dialog_get_settings(settings, &sett);
|
||||
@@ -204,8 +288,6 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
goto ret_layer_destroy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* save file dialog */
|
||||
dialog = gtk_file_chooser_dialog_new((sett.renderer == RENDERER_LATEX_TIKZ
|
||||
? "Save LaTeX File" : "Save PDF"),
|
||||
@@ -213,15 +295,25 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
"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) {
|
||||
switch (sett.renderer) {
|
||||
case RENDERER_LATEX_TIKZ:
|
||||
gtk_file_filter_add_pattern(filter, "*.tex");
|
||||
gtk_file_filter_set_name(filter, "LaTeX-Files");
|
||||
} else {
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS_PDF:
|
||||
gtk_file_filter_add_pattern(filter, "*.pdf");
|
||||
gtk_file_filter_set_name(filter, "PDF-Files");
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS_SVG:
|
||||
gtk_file_filter_add_pattern(filter, "*.svg");
|
||||
gtk_file_filter_set_name(filter, "SVG-Files");
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
if (res == GTK_RESPONSE_ACCEPT) {
|
||||
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
@@ -234,8 +326,16 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
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);
|
||||
case RENDERER_CAIROGRAPHICS_SVG:
|
||||
case RENDERER_CAIROGRAPHICS_PDF:
|
||||
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
||||
(sett.renderer == RENDERER_CAIROGRAPHICS_PDF
|
||||
? file_name
|
||||
: NULL),
|
||||
(sett.renderer == RENDERER_CAIROGRAPHICS_SVG
|
||||
? file_name
|
||||
: NULL),
|
||||
sett.scale);
|
||||
break;
|
||||
}
|
||||
g_free(file_name);
|
||||
@@ -247,8 +347,30 @@ 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 */
|
||||
/**
|
||||
* @brief cell_tree_view_activated
|
||||
* @param tree_view Not used
|
||||
* @param user convert button data
|
||||
*/
|
||||
static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
|
||||
GtkTreeViewColumn *column, gpointer user)
|
||||
{
|
||||
(void)tree_view;
|
||||
(void)path;
|
||||
(void)column;
|
||||
|
||||
on_convert_clicked(NULL, user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback for cell-selection change event
|
||||
*
|
||||
* This function activates/deactivates the convert button depending on whether
|
||||
* a cell is selected for conversion or not
|
||||
* @param sel
|
||||
* @param convert_button
|
||||
*/
|
||||
static void cell_selection_changed(GtkTreeSelection *sel, GtkWidget *convert_button)
|
||||
{
|
||||
GtkTreeModel *model = NULL;
|
||||
@@ -262,27 +384,46 @@ static void cell_selection_changed(GtkTreeSelection *sel, GtkWidget *convert_but
|
||||
}
|
||||
}
|
||||
|
||||
static void sort_up_callback(GtkWidget *widget, gpointer user)
|
||||
{
|
||||
(void)widget;
|
||||
(void)user;
|
||||
|
||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_UP);
|
||||
}
|
||||
|
||||
static void sort_down_callback(GtkWidget *widget, gpointer user)
|
||||
{
|
||||
(void)widget;
|
||||
(void)user;
|
||||
|
||||
layer_selector_force_sort(LAYER_SELECTOR_SORT_DOWN);
|
||||
}
|
||||
|
||||
GtkWindow *create_main_window()
|
||||
{
|
||||
GtkBuilder *main_builder;
|
||||
GtkTreeView *cell_tree;
|
||||
GtkTreeStore *cell_store;
|
||||
GtkWidget *listbox;
|
||||
GtkWidget *conv_button;
|
||||
GtkWidget *search_entry;
|
||||
GtkHeaderBar *header_bar;
|
||||
static GList *gds_libs;
|
||||
static struct open_button_data open_data;
|
||||
static struct convert_button_data conv_data;
|
||||
struct tree_stores *cell_selector_stores;
|
||||
GtkWidget *sort_up_button;
|
||||
GtkWidget *sort_down_button;
|
||||
|
||||
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);
|
||||
search_entry = GTK_WIDGET(gtk_builder_get_object(main_builder, "cell-search"));
|
||||
open_data.search_entry = GTK_SEARCH_ENTRY(search_entry);
|
||||
cell_selector_stores = setup_cell_selector(cell_tree, GTK_ENTRY(search_entry));
|
||||
|
||||
|
||||
open_data.cell_store = cell_store;
|
||||
open_data.cell_store = cell_selector_stores->base_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")),
|
||||
@@ -300,6 +441,9 @@ GtkWindow *create_main_window()
|
||||
g_signal_connect(conv_button, "clicked", G_CALLBACK(on_convert_clicked), &conv_data);
|
||||
|
||||
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
|
||||
/* Set up the list box sided callbacks for drag and drop */
|
||||
layer_selector_list_box_setup_dnd(GTK_LIST_BOX(listbox));
|
||||
|
||||
open_data.layer_box = GTK_LIST_BOX(listbox);
|
||||
|
||||
/* Set buttons fpr layer mapping GUI */
|
||||
@@ -311,6 +455,22 @@ GtkWindow *create_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);
|
||||
g_signal_connect(cell_tree, "row-activated", G_CALLBACK(cell_tree_view_activated), &conv_data);
|
||||
|
||||
return (conv_data.main_window);
|
||||
/* Set version in main window subtitle */
|
||||
header_bar = GTK_HEADER_BAR(gtk_builder_get_object(main_builder, "header-bar"));
|
||||
gtk_header_bar_set_subtitle(header_bar, _app_version_string);
|
||||
|
||||
/* Get layer sorting buttons and set callbacks */
|
||||
sort_up_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-up-sort"));
|
||||
sort_down_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-down-sort"));
|
||||
|
||||
g_signal_connect(sort_up_button, "clicked", G_CALLBACK(sort_up_callback), NULL);
|
||||
g_signal_connect(sort_down_button, "clicked", G_CALLBACK(sort_down_callback), NULL);
|
||||
|
||||
g_object_unref(main_builder);
|
||||
|
||||
return conv_data.main_window;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,11 +17,30 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file main-window.h
|
||||
* @brief Header for main-window
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _MAIN_WINDOW_H_
|
||||
#define _MAIN_WINDOW_H_
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* @brief Create main window
|
||||
*
|
||||
* This function creates the main window and sets the necessary callback routines.
|
||||
* @return
|
||||
*/
|
||||
GtkWindow *create_main_window();
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _MAIN_WINDOW_H_ */
|
||||
|
148
main.c
148
main.c
@@ -19,17 +19,23 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include "main-window.h"
|
||||
#include "command-line.h"
|
||||
#include "external-renderer.h"
|
||||
#include "version/version.h"
|
||||
|
||||
struct application_data {
|
||||
GtkApplication *app;
|
||||
GtkWindow *main_window;
|
||||
GtkApplication *app;
|
||||
GtkWindow *main_window;
|
||||
};
|
||||
|
||||
|
||||
static void app_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||
{
|
||||
struct application_data *appdata = (struct application_data *)user_data;
|
||||
const struct application_data * const appdata = (const struct application_data *)user_data;
|
||||
(void)action;
|
||||
(void)parameter;
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(appdata->main_window));
|
||||
}
|
||||
|
||||
@@ -37,26 +43,29 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkDialog *dialog;
|
||||
struct application_data *appdata = (struct application_data *)user_data;
|
||||
const struct application_data * const appdata = (const struct application_data *)user_data;
|
||||
(void)action;
|
||||
(void)parameter;
|
||||
|
||||
builder = gtk_builder_new_from_resource("/about.glade");
|
||||
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
|
||||
gtk_window_set_transient_for(GTK_WINDOW(dialog), appdata->main_window);
|
||||
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), _app_version_string);
|
||||
gtk_dialog_run(dialog);
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
gtk_widget_destroy(GTK_WIDGET(dialog));
|
||||
g_object_unref(builder);
|
||||
}
|
||||
|
||||
const GActionEntry app_actions[] = {
|
||||
{ "quit", app_quit },
|
||||
{ "about", app_about }
|
||||
const static GActionEntry app_actions[] = {
|
||||
{"quit", app_quit, NULL, NULL, NULL, {0}},
|
||||
{"about", app_about, NULL, NULL, NULL, {0}}
|
||||
};
|
||||
|
||||
static void gapp_activate(GApplication *app, gpointer user_data)
|
||||
{
|
||||
GtkWindow *main_window;
|
||||
struct application_data *appdata = (struct application_data *)user_data;
|
||||
struct application_data * const appdata = (struct application_data *)user_data;
|
||||
|
||||
main_window = create_main_window();
|
||||
appdata->main_window = main_window;
|
||||
@@ -64,21 +73,19 @@ static void gapp_activate(GApplication *app, gpointer user_data)
|
||||
gtk_widget_show(GTK_WIDGET(main_window));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
static int start_gui(int argc, char **argv)
|
||||
{
|
||||
|
||||
GtkApplication *gapp;
|
||||
int app_status;
|
||||
struct application_data appdata;
|
||||
static struct application_data appdata;
|
||||
GMenu *menu;
|
||||
GMenu *m_quit;
|
||||
GMenu *m_about;
|
||||
|
||||
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
|
||||
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_NON_UNIQUE);
|
||||
g_application_register(G_APPLICATION(gapp), NULL, NULL);
|
||||
//g_action_map_add_action_entries(G_ACTION_MAP(gapp), app_actions, G_N_ELEMENTS(app_actions), &appdata);
|
||||
g_signal_connect (gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
|
||||
|
||||
|
||||
g_signal_connect(gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
|
||||
|
||||
menu = g_menu_new();
|
||||
m_quit = g_menu_new();
|
||||
@@ -87,16 +94,115 @@ int main(int argc, char **argv)
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
app_status = g_application_run (G_APPLICATION(gapp), argc, argv);
|
||||
g_object_unref (gapp);
|
||||
app_status = g_application_run(G_APPLICATION(gapp), argc, argv);
|
||||
g_object_unref(gapp);
|
||||
|
||||
return app_status;
|
||||
}
|
||||
|
||||
static void print_version()
|
||||
{
|
||||
printf("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n",
|
||||
_app_version_string);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
gchar *gds_name;
|
||||
gchar *basename;
|
||||
gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL, *svgname = NULL;
|
||||
gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE, svg = FALSE;
|
||||
gboolean version = FALSE;
|
||||
gchar *custom_library_path = NULL;
|
||||
gchar *custom_library_file_name = NULL;
|
||||
int scale = 1000;
|
||||
int app_status = 0;
|
||||
|
||||
GOptionEntry entries[] = {
|
||||
{"version", 'v', 0, G_OPTION_ARG_NONE, &version, "Print version", NULL},
|
||||
{"tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL },
|
||||
{"pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL },
|
||||
//{"svg", 'S', 0, G_OPTION_ARG_NONE, &svg, "Output SVG image", NULL },
|
||||
{"scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" },
|
||||
{"tex-output", 'o', 0, G_OPTION_ARG_FILENAME, &texname, "Optional path for TeX file", "PATH" },
|
||||
{"pdf-output", 'O', 0, G_OPTION_ARG_FILENAME, &pdfname, "Optional path for PDF file", "PATH" },
|
||||
//{"svg-output", 0, 0, G_OPTION_ARG_FILENAME, &svgname, "Optional path for PDF file", "PATH"},
|
||||
{"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" },
|
||||
{"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" },
|
||||
{"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL },
|
||||
{"tex-layers", 'l', 0, G_OPTION_ARG_NONE, &pdf_layers, "Create PDF Layers (OCG)", NULL },
|
||||
{"custom-render-lib", 'P', 0, G_OPTION_ARG_FILENAME, &custom_library_path, "Path to a custom shared object, that implements the " EXTERNAL_LIBRARY_FUNCTION " function", "PATH"},
|
||||
{"external-lib-output", 'e', 0, G_OPTION_ARG_FILENAME, &custom_library_file_name, "Output path for external render library", "PATH"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
context = g_option_context_new(" FILE - Convert GDS file <FILE> to graphic");
|
||||
g_option_context_add_main_entries(context, entries, NULL);
|
||||
g_option_context_add_group(context, gtk_get_option_group(TRUE));
|
||||
|
||||
if (!g_option_context_parse(context, &argc, &argv, &error)) {
|
||||
g_print("Option parsing failed: %s\n", error->message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (version) {
|
||||
print_version();
|
||||
goto ret_status;
|
||||
}
|
||||
|
||||
if (argc >= 2) {
|
||||
if (scale < 1) {
|
||||
printf("Scale < 1 not allowed. Setting to 1\n");
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
/* No format selected */
|
||||
if (!(tikz || pdf || svg))
|
||||
tikz = TRUE;
|
||||
|
||||
/* Get gds name */
|
||||
gds_name = argv[1];
|
||||
|
||||
/* Check if PDF/TeX names are supplied. if not generate */
|
||||
basename = g_path_get_basename(gds_name);
|
||||
|
||||
if (!texname)
|
||||
texname = g_strdup_printf("./%s.tex", basename);
|
||||
|
||||
if (!pdfname)
|
||||
pdfname = g_strdup_printf("./%s.pdf", basename);
|
||||
|
||||
if (!svgname)
|
||||
svgname = g_strdup_printf("./%s.svg", basename);
|
||||
|
||||
command_line_convert_gds(gds_name, pdfname, texname, pdf, tikz,
|
||||
mappingname, cellname, (double)scale,
|
||||
pdf_layers, pdf_standalone, svg, svgname,
|
||||
custom_library_path, custom_library_file_name);
|
||||
/* Clean up */
|
||||
g_free(pdfname);
|
||||
g_free(texname);
|
||||
g_free(svgname);
|
||||
g_free(basename);
|
||||
if (mappingname)
|
||||
g_free(mappingname);
|
||||
if (cellname)
|
||||
g_free(cellname);
|
||||
app_status = 0;
|
||||
} else {
|
||||
app_status = start_gui(argc, argv);
|
||||
}
|
||||
|
||||
ret_status:
|
||||
return app_status;
|
||||
}
|
||||
|
98
mapping-parser.c
Normal file
98
mapping-parser.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mapping-parser.c
|
||||
* @brief Function to read a mapping file line and parse it.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "mapping-parser.h"
|
||||
|
||||
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
|
||||
{
|
||||
int ret;
|
||||
gsize len;
|
||||
gchar *line;
|
||||
GRegex *regex;
|
||||
GMatchInfo *mi;
|
||||
char *match;
|
||||
|
||||
if ((!export) || (!name) || (!layer) || (!color)) {
|
||||
ret = 1;
|
||||
goto ret_direct;
|
||||
}
|
||||
|
||||
regex = g_regex_new("^(?<layer>[0-9]+),(?<r>[0-9\\.]+),(?<g>[0-9\\.]+),(?<b>[0-9\\.]+),(?<a>[0-9\\.]+),(?<export>[01]),(?<name>.*)$", 0, 0, NULL);
|
||||
|
||||
line = g_data_input_stream_read_line(stream, &len, NULL, NULL);
|
||||
if (!line) {
|
||||
ret = -1;
|
||||
goto destroy_regex;
|
||||
}
|
||||
|
||||
/* Match line in CSV */
|
||||
g_regex_match(regex, line, 0, &mi);
|
||||
if (g_match_info_matches(mi)) {
|
||||
/* Line is valid */
|
||||
match = g_match_info_fetch_named(mi, "layer");
|
||||
*layer = (int)g_ascii_strtoll(match, NULL, 10);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "r");
|
||||
color->red = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "g");
|
||||
color->green = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "b");
|
||||
color->blue = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "a");
|
||||
color->alpha = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "export");
|
||||
*export = ((!strcmp(match, "1")) ? TRUE : FALSE);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "name");
|
||||
*name = match;
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Line is malformatted */
|
||||
printf("Could not recognize line in CSV as valid entry: %s\n", line);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
g_match_info_free(mi);
|
||||
g_free(line);
|
||||
destroy_regex:
|
||||
g_regex_unref(regex);
|
||||
ret_direct:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
62
mapping-parser.h
Normal file
62
mapping-parser.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mapping-parser.h
|
||||
* @brief Function to read a mapping file line and parse it.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef __MAPPING_PARSER_H__
|
||||
#define __MAPPING_PARSER_H__
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* @brief Layer information.
|
||||
*
|
||||
* This structs contains information on how to render a layer
|
||||
*/
|
||||
struct layer_info
|
||||
{
|
||||
int layer; /**< @brief Layer number */
|
||||
char *name; /**< @brief Layer name */
|
||||
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
||||
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||
* @param stream Input data stream
|
||||
* @param export Layer shall be exported
|
||||
* @param name Layer name. Free returned pointer after using.
|
||||
* @param layer Layer number
|
||||
* @param color RGBA color.
|
||||
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
||||
*/
|
||||
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __MAPPING_PARSER_H__ */
|
@@ -25,6 +25,7 @@ G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
|
||||
enum {
|
||||
PROP_LIB = 1,
|
||||
PROP_CELL,
|
||||
PROP_ERROR_LEVEL,
|
||||
PROP_COUNT
|
||||
};
|
||||
|
||||
@@ -38,24 +39,56 @@ static void lib_cell_renderer_constructed(GObject *obj)
|
||||
G_OBJECT_CLASS(lib_cell_renderer_parent_class)->constructed(obj);
|
||||
}
|
||||
|
||||
static void convert_error_level_to_color(GdkRGBA *color, unsigned int error_level)
|
||||
{
|
||||
|
||||
/* Always use no transparency */
|
||||
color->alpha = 1.0;
|
||||
|
||||
if (error_level & LIB_CELL_RENDERER_ERROR_ERR) {
|
||||
/* Error set. Color cell red */
|
||||
color->red = 1.0;
|
||||
color->blue = 0.0;
|
||||
color->green = 0.0;
|
||||
} else if (error_level & LIB_CELL_RENDERER_ERROR_WARN) {
|
||||
/* Only warning set; orange color */
|
||||
color->red = 1.0;
|
||||
color->blue = 0.0;
|
||||
color->green = 0.6;
|
||||
} else {
|
||||
/* Everything okay; green color */
|
||||
color->red = (double)61.0/(double)255.0;
|
||||
color->green = (double)152.0/(double)255.0;
|
||||
color->blue = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
GdkRGBA color;
|
||||
|
||||
switch (param_id) {
|
||||
case PROP_LIB:
|
||||
g_value_init(&val, G_TYPE_STRING);
|
||||
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_init(&val, G_TYPE_STRING);
|
||||
g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name);
|
||||
g_object_set_property(object, "text", &val);
|
||||
break;
|
||||
case PROP_ERROR_LEVEL:
|
||||
/* Set cell color according to error level */
|
||||
g_value_init(&val, GDK_TYPE_RGBA);
|
||||
convert_error_level_to_color(&color, g_value_get_uint(value));
|
||||
g_value_set_boxed(&val, &color);
|
||||
g_object_set_property(object, "foreground-rgba", &val);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
|
||||
break;
|
||||
@@ -89,6 +122,8 @@ void lib_cell_renderer_class_init(LibCellRendererClass *klass)
|
||||
properties[PROP_CELL] = g_param_spec_pointer("gds-cell", "gds-cell",
|
||||
"Cell reference to be displayed",
|
||||
G_PARAM_WRITABLE);
|
||||
properties[PROP_ERROR_LEVEL] = g_param_spec_uint("error-level", "error-level",
|
||||
"Error level of this cell", 0, 255, 0, G_PARAM_WRITABLE);
|
||||
|
||||
g_object_class_install_properties(oclass, PROP_COUNT, properties);
|
||||
}
|
||||
|
@@ -27,6 +27,9 @@ 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())
|
||||
|
||||
#define LIB_CELL_RENDERER_ERROR_WARN (1U<<0)
|
||||
#define LIB_CELL_RENDERER_ERROR_ERR (1U<<1)
|
||||
|
||||
typedef struct _LibCellRenderer {
|
||||
/* Inheritance */
|
||||
GtkCellRendererText super;
|
||||
|
@@ -1,7 +1,46 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tree-store.h
|
||||
* @brief Tree store implementation
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "tree-store.h"
|
||||
#include "lib-cell-renderer.h"
|
||||
#include "../gds-parser/gds-types.h"
|
||||
|
||||
/**
|
||||
* @brief this function olny allows cells to be selected
|
||||
* @param selection
|
||||
* @param model
|
||||
* @param path
|
||||
* @param path_currently_selected
|
||||
* @param data
|
||||
* @return TRUE if element is selectable, FALSE if not
|
||||
*/
|
||||
static gboolean tree_sel_func(GtkTreeSelection *selection,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
@@ -10,59 +49,111 @@ static gboolean tree_sel_func(GtkTreeSelection *selection,
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
struct gds_cell *cell;
|
||||
unsigned int error_level;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, -1);
|
||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, CELL_SEL_CELL_ERROR_STATE, &error_level, -1);
|
||||
|
||||
/* Allow only rows with valid cell to be selected */
|
||||
if (cell)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
/* Allow only rows with _valid_ cell to be selected */
|
||||
if (cell) {
|
||||
/* Cell available. Check if it passed the critical checks */
|
||||
if (!(error_level & LIB_CELL_RENDERER_ERROR_ERR))
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GtkTreeStore *setup_cell_selector(GtkTreeView* view)
|
||||
/**
|
||||
* @brief cell_store_filter_visible_func Decides whether an element of the tree model @p model is visible.
|
||||
* @param model Tree model
|
||||
* @param iter Current element / iter in Model to check
|
||||
* @param data Data. Set to static stores variable
|
||||
* @return TRUE if visible, else FALSE
|
||||
* @note TODO: Maybe implement Damerau-Levenshtein distance matching
|
||||
*/
|
||||
static gboolean cell_store_filter_visible_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
GtkTreeStore *cell_store;
|
||||
struct tree_stores *stores = (struct tree_stores *)data;
|
||||
struct gds_cell *cell;
|
||||
struct gds_library *lib;
|
||||
gboolean result = FALSE;
|
||||
const char *search_string;
|
||||
|
||||
if (!model || !iter || !stores)
|
||||
goto exit_filter;
|
||||
|
||||
gtk_tree_model_get(model, iter, CELL_SEL_CELL, &cell, CELL_SEL_LIBRARY, &lib, -1);
|
||||
|
||||
if (lib) {
|
||||
result = TRUE;
|
||||
goto exit_filter;
|
||||
}
|
||||
|
||||
if (!cell)
|
||||
goto exit_filter;
|
||||
|
||||
search_string = gtk_entry_get_text(stores->search_entry);
|
||||
|
||||
/* Show all, if field is empty */
|
||||
if (!strlen(search_string))
|
||||
result = TRUE;
|
||||
|
||||
if (strstr(cell->name, search_string))
|
||||
result = TRUE;
|
||||
|
||||
gtk_tree_view_expand_all(stores->base_tree_view);
|
||||
|
||||
exit_filter:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void change_filter(GtkWidget *entry, gpointer data)
|
||||
{
|
||||
struct tree_stores *stores = (struct tree_stores *)data;
|
||||
gtk_tree_model_filter_refilter(stores->filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup a GtkTreeView with the necessary columns
|
||||
* @param view Tree view to set up
|
||||
* @param search_entry Entry field for search
|
||||
* @return Tree stores for storing data inside the GtkTreeView
|
||||
*/
|
||||
struct tree_stores *setup_cell_selector(GtkTreeView* view, GtkEntry *search_entry)
|
||||
{
|
||||
static struct tree_stores stores;
|
||||
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));
|
||||
stores.base_tree_view = view;
|
||||
stores.search_entry = search_entry;
|
||||
|
||||
stores.base_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
/* Searching */
|
||||
if (search_entry) {
|
||||
stores.filter = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(GTK_TREE_MODEL(stores.base_store), NULL));
|
||||
gtk_tree_model_filter_set_visible_func (stores.filter,
|
||||
(GtkTreeModelFilterVisibleFunc)cell_store_filter_visible_func,
|
||||
&stores, NULL);
|
||||
g_signal_connect(GTK_SEARCH_ENTRY(search_entry), "search-changed", G_CALLBACK(change_filter), &stores);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_model(view, GTK_TREE_MODEL(stores.filter));
|
||||
|
||||
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);
|
||||
column = gtk_tree_view_column_new_with_attributes("Cell", render_cell, "gds-cell", CELL_SEL_CELL,
|
||||
"error-level", CELL_SEL_CELL_ERROR_STATE, 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);
|
||||
@@ -75,5 +166,6 @@ GtkTreeStore *setup_cell_selector(GtkTreeView* view)
|
||||
* 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;
|
||||
return &stores;
|
||||
}
|
||||
/** @} */
|
||||
|
@@ -1,16 +1,57 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tree-store.h
|
||||
* @brief Header file for Tree store implementation
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __TREE_STORE_H__
|
||||
#define __TREE_STORE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/** @brief Columns of selection tree view */
|
||||
enum cell_store_columns {
|
||||
CELL_SEL_LIBRARY = 0,
|
||||
CELL_SEL_CELL,
|
||||
CELL_SEL_CELL_ERROR_STATE, /**< Used for cell color and selectability */
|
||||
CELL_SEL_MODDATE,
|
||||
CELL_SEL_ACCESSDATE,
|
||||
CELL_SEL_COLUMN_COUNT
|
||||
CELL_SEL_COLUMN_COUNT /**< @brief Not a column. Used to determine count of columns */
|
||||
};
|
||||
|
||||
GtkTreeStore *setup_cell_selector(GtkTreeView* view);
|
||||
struct tree_stores {
|
||||
GtkTreeView *base_tree_view;
|
||||
GtkTreeStore *base_store;
|
||||
GtkTreeModelFilter *filter;
|
||||
GtkEntry *search_entry;
|
||||
};
|
||||
|
||||
struct tree_stores *setup_cell_selector(GtkTreeView* view, GtkEntry *search_entry);
|
||||
|
||||
#endif /* __TREE_STORE_H__ */
|
||||
|
||||
/** @} */
|
||||
|
203
trigonometric/bounding-box.c
Normal file
203
trigonometric/bounding-box.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bounding-box.c
|
||||
* @brief Calculation of bounding boxes
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bounding-box.h"
|
||||
#include <math.h>
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
||||
|
||||
void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
|
||||
{
|
||||
double xmin = DBL_MAX, xmax = -DBL_MAX, ymin = DBL_MAX, ymax = -DBL_MAX;
|
||||
struct vector_2d temp_vec;
|
||||
GList *list_item;
|
||||
|
||||
/* Check for errors */
|
||||
if (!conv_func || !box || !vertices)
|
||||
return;
|
||||
|
||||
for (list_item = vertices; list_item != NULL; list_item = g_list_next(list_item)) {
|
||||
/* Convert generic vertex to vector_2d */
|
||||
if (conv_func)
|
||||
conv_func((void *)list_item->data, &temp_vec);
|
||||
else
|
||||
vector_2d_copy(&temp_vec, (struct vector_2d *)list_item->data);
|
||||
|
||||
/* Update bounding coordinates with vertex */
|
||||
xmin = MIN(xmin, temp_vec.x);
|
||||
xmax = MAX(xmax, temp_vec.x);
|
||||
ymin = MIN(ymin, temp_vec.y);
|
||||
ymax = MAX(ymax, temp_vec.y);
|
||||
}
|
||||
|
||||
/* Fill bounding box with results */
|
||||
box->vectors.lower_left.x = xmin;
|
||||
box->vectors.lower_left.y = ymin;
|
||||
box->vectors.upper_right.x = xmax;
|
||||
box->vectors.upper_right.y = ymax;
|
||||
}
|
||||
|
||||
void bounding_box_update_box(union bounding_box *destination, union bounding_box *update)
|
||||
{
|
||||
if (!destination || !update)
|
||||
return;
|
||||
|
||||
destination->vectors.lower_left.x = MIN(destination->vectors.lower_left.x,
|
||||
update->vectors.lower_left.x);
|
||||
destination->vectors.lower_left.y = MIN(destination->vectors.lower_left.y,
|
||||
update->vectors.lower_left.y);
|
||||
destination->vectors.upper_right.x = MAX(destination->vectors.upper_right.x,
|
||||
update->vectors.upper_right.x);
|
||||
destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y,
|
||||
update->vectors.upper_right.y);
|
||||
}
|
||||
|
||||
void bounding_box_prepare_empty(union bounding_box *box)
|
||||
{
|
||||
box->vectors.lower_left.x = DBL_MAX;
|
||||
box->vectors.lower_left.y = DBL_MAX;
|
||||
box->vectors.upper_right.x = -DBL_MAX;
|
||||
box->vectors.upper_right.y = -DBL_MAX;
|
||||
}
|
||||
|
||||
static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b, struct vector_2d *c,
|
||||
struct vector_2d *m1, struct vector_2d *m2, double width)
|
||||
{
|
||||
double angle, angle_sin, u;
|
||||
struct vector_2d ba, bc, u_vec, v_vec, ba_norm;
|
||||
|
||||
if (!a || !b || !c || !m1 || !m2)
|
||||
return;
|
||||
|
||||
vector_2d_subtract(&ba, a, b);
|
||||
vector_2d_subtract(&bc, c, b);
|
||||
|
||||
angle = vector_2d_calculate_angle_between(&ba, &bc);
|
||||
|
||||
if (ABS_DBL(angle) < 0.05 || ABS_DBL(angle - M_PI) < 0.1) {
|
||||
/* Specail cases Don*/
|
||||
vector_2d_copy(&ba_norm, &ba);
|
||||
vector_2d_rotate(&ba_norm, DEG2RAD(90));
|
||||
vector_2d_normalize(&ba_norm);
|
||||
vector_2d_scale(&ba_norm, width/2.0);
|
||||
vector_2d_add(m1, b, &ba_norm);
|
||||
vector_2d_subtract(m2, b, &ba_norm);
|
||||
return;
|
||||
}
|
||||
angle_sin = sin(angle);
|
||||
u = width/(2*angle_sin);
|
||||
|
||||
vector_2d_copy(&u_vec, &ba);
|
||||
vector_2d_copy(&v_vec, &bc);
|
||||
vector_2d_normalize(&u_vec);
|
||||
vector_2d_normalize(&v_vec);
|
||||
vector_2d_scale(&u_vec, u);
|
||||
vector_2d_scale(&v_vec, u);
|
||||
|
||||
vector_2d_copy(m1, b);
|
||||
vector_2d_add(m1, m1, &u_vec);
|
||||
vector_2d_add(m1, m1, &v_vec);
|
||||
|
||||
vector_2d_copy(m2, b);
|
||||
vector_2d_subtract(m2, m2, &u_vec);
|
||||
vector_2d_subtract(m2, m2, &v_vec);
|
||||
}
|
||||
|
||||
void bounding_box_calculate_path_box(GList *vertices, double thickness,
|
||||
conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
|
||||
{
|
||||
GList *vertex_iterator;
|
||||
struct vector_2d pt;
|
||||
|
||||
printf("Warning! Function bounding_box_calculate_path_box not yet implemented correctly!\n");
|
||||
|
||||
if (!vertices || !box)
|
||||
return;
|
||||
|
||||
for (vertex_iterator = vertices; vertex_iterator != NULL; vertex_iterator = g_list_next(vertex_iterator)) {
|
||||
|
||||
if (conv_func != NULL)
|
||||
conv_func(vertex_iterator->data, &pt);
|
||||
else
|
||||
(void)vector_2d_copy(&pt, (struct vector_2d *)vertex_iterator->data);
|
||||
|
||||
/* These are approximations.
|
||||
* Used as long as miter point calculation is not fully implemented
|
||||
*/
|
||||
box->vectors.lower_left.x = MIN(box->vectors.lower_left.x, pt.x - thickness/2);
|
||||
box->vectors.lower_left.y = MIN(box->vectors.lower_left.y, pt.y - thickness/2);
|
||||
box->vectors.upper_right.x = MAX(box->vectors.upper_right.x, pt.x + thickness/2);
|
||||
box->vectors.upper_right.y = MAX(box->vectors.upper_right.y, pt.y + thickness/2);
|
||||
}
|
||||
}
|
||||
|
||||
void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt)
|
||||
{
|
||||
struct vector_2d point;
|
||||
|
||||
if (!destination || !pt)
|
||||
return;
|
||||
|
||||
if (conv_func)
|
||||
conv_func(pt, &point);
|
||||
else
|
||||
(void)vector_2d_copy(&point, (struct vector_2d *)pt);
|
||||
|
||||
destination->vectors.lower_left.x = MIN(destination->vectors.lower_left.x, point.x);
|
||||
destination->vectors.lower_left.y = MIN(destination->vectors.lower_left.y, point.y);
|
||||
destination->vectors.upper_right.x = MAX(destination->vectors.upper_right.x, point.x);
|
||||
destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply transformations onto bounding box.
|
||||
* @param scale Scaling factor
|
||||
* @param rotation_deg Roation of bounding box around the origin in degrees (counterclockwise)
|
||||
* @param flip_at_x Flip the boundig box on the x axis before rotating.
|
||||
* @param box Bounding box the operations should be applied to.
|
||||
*/
|
||||
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Due to linearity, the order of the operations does not matter.
|
||||
* flip must be applied before rotation as defined by the GDS format
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
box->vector_array[i].y *= (flip_at_x ? -1 : 1);
|
||||
vector_2d_rotate(&box->vector_array[i], rotation_deg * M_PI / 180);
|
||||
vector_2d_scale(&box->vector_array[i], scale);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
57
trigonometric/bounding-box.h
Normal file
57
trigonometric/bounding-box.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bounding-box.h
|
||||
* @brief Header for calculation of bounding boxes
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _BOUNDING_BOX_H_
|
||||
#define _BOUNDING_BOX_H_
|
||||
#include <glib.h>
|
||||
#include "vector-operations.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
union bounding_box {
|
||||
/** Coordinate System is (y up | x right) */
|
||||
struct _vectors {
|
||||
struct vector_2d lower_left;
|
||||
struct vector_2d upper_right;
|
||||
} vectors;
|
||||
struct vector_2d vector_array[2];
|
||||
};
|
||||
|
||||
typedef void (*conv_generic_to_vector_2d_t)(void *, struct vector_2d *);
|
||||
|
||||
void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);
|
||||
void bounding_box_update_box(union bounding_box *destination, union bounding_box *update);
|
||||
void bounding_box_prepare_empty(union bounding_box *box);
|
||||
void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt);
|
||||
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box);
|
||||
void bounding_box_calculate_path_box(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);
|
||||
|
||||
#endif /* _BOUNDING_BOX_H_ */
|
||||
|
||||
/** @} */
|
119
trigonometric/cell-trigonometrics.c
Normal file
119
trigonometric/cell-trigonometrics.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cell-trigonometrics.c
|
||||
* @brief Calculation of gds_cell trigonometrics
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include "cell-trigonometrics.h"
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
static void convert_gds_point_to_2d_vector(struct gds_point *pt, struct vector_2d *vector)
|
||||
{
|
||||
vector->x = pt->x;
|
||||
vector->y = pt->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the given bounding box with the bounding box of a graphics element.
|
||||
* @param box box to update
|
||||
* @param gfx Graphics element
|
||||
*/
|
||||
static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gfx)
|
||||
{
|
||||
union bounding_box current_box;
|
||||
|
||||
bounding_box_prepare_empty(¤t_box);
|
||||
|
||||
switch (gfx->gfx_type) {
|
||||
case GRAPHIC_BOX:
|
||||
/* Expected fallthrough */
|
||||
case GRAPHIC_POLYGON:
|
||||
bounding_box_calculate_polygon(gfx->vertices,
|
||||
(conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector,
|
||||
¤t_box);
|
||||
break;
|
||||
case GRAPHIC_PATH:
|
||||
/*
|
||||
* This is not implemented correctly.
|
||||
* Please be aware if paths are the outmost elements of your cell.
|
||||
* You might end up with a completely wrong calculated cell size.
|
||||
*/
|
||||
bounding_box_calculate_path_box(gfx->vertices, gfx->width_absolute,
|
||||
(conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector,
|
||||
¤t_box);
|
||||
break;
|
||||
default:
|
||||
/* Unknown graphics object. */
|
||||
/* Print error? Nah.. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update box with results */
|
||||
bounding_box_update_box(box, ¤t_box);
|
||||
}
|
||||
|
||||
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell)
|
||||
{
|
||||
GList *gfx_list;
|
||||
struct gds_graphics *gfx;
|
||||
GList *sub_cell_list;
|
||||
struct gds_cell_instance *sub_cell;
|
||||
union bounding_box temp_box;
|
||||
|
||||
if (!box || !cell)
|
||||
return;
|
||||
|
||||
/* Update box with graphic elements */
|
||||
for (gfx_list = cell->graphic_objs; gfx_list != NULL; gfx_list = gfx_list->next) {
|
||||
gfx = (struct gds_graphics *)gfx_list->data;
|
||||
update_box_with_gfx(box, gfx);
|
||||
}
|
||||
|
||||
/* Update bounding box with boxes of subcells */
|
||||
for (sub_cell_list = cell->child_cells; sub_cell_list != NULL;
|
||||
sub_cell_list = sub_cell_list->next) {
|
||||
sub_cell = (struct gds_cell_instance *)sub_cell_list->data;
|
||||
bounding_box_prepare_empty(&temp_box);
|
||||
/* Recursion Woohoo!! This dies if your GDS is faulty and contains a reference loop */
|
||||
calculate_cell_bounding_box(&temp_box, sub_cell->cell_ref);
|
||||
|
||||
/* Apply transformations */
|
||||
bounding_box_apply_transform(ABS(sub_cell->magnification), sub_cell->angle,
|
||||
sub_cell->flipped, &temp_box);
|
||||
|
||||
/* Move bounding box to origin */
|
||||
temp_box.vectors.lower_left.x += sub_cell->origin.x;
|
||||
temp_box.vectors.upper_right.x += sub_cell->origin.x;
|
||||
temp_box.vectors.lower_left.y += sub_cell->origin.y;
|
||||
temp_box.vectors.upper_right.y += sub_cell->origin.y;
|
||||
|
||||
/* update the parent's box */
|
||||
bounding_box_update_box(box, &temp_box);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
47
trigonometric/cell-trigonometrics.h
Normal file
47
trigonometric/cell-trigonometrics.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cell-trigonometrics.h
|
||||
* @brief Calculation of gds_cell trigonometrics
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CELL_TRIGONOMETRICS_H_
|
||||
#define _CELL_TRIGONOMETRICS_H_
|
||||
|
||||
#include "bounding-box.h"
|
||||
#include "../gds-parser/gds-types.h"
|
||||
|
||||
/**
|
||||
* @brief calculate_cell_bounding_box Calculate bounding box of gds cell
|
||||
* @param box Resulting boundig box. Will be uüdated and not overwritten
|
||||
* @param cell toplevel cell
|
||||
* @warning Path handling not yet implemented correctly
|
||||
*/
|
||||
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell);
|
||||
|
||||
#endif /* _CELL_TRIGONOMETRICS_H_ */
|
||||
|
||||
/** @} */
|
149
trigonometric/vector-operations.c
Normal file
149
trigonometric/vector-operations.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vector-operations.c
|
||||
* @brief 2D Vector operations
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "vector-operations.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
||||
|
||||
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
if (a && b)
|
||||
return (a->x * b->x) + (a->y * b->y);
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void vector_2d_normalize(struct vector_2d *vec)
|
||||
{
|
||||
double len;
|
||||
if (!vec)
|
||||
return;
|
||||
len = sqrt(pow(vec->x,2)+pow(vec->y,2));
|
||||
vec->x = vec->x/len;
|
||||
vec->y = vec->y/len;
|
||||
}
|
||||
|
||||
void vector_2d_rotate(struct vector_2d *vec, double angle)
|
||||
{
|
||||
double sin_val, cos_val;
|
||||
struct vector_2d temp;
|
||||
|
||||
if (!vec)
|
||||
return;
|
||||
|
||||
sin_val = sin(angle);
|
||||
cos_val = cos(angle);
|
||||
|
||||
vector_2d_copy(&temp, vec);
|
||||
|
||||
/* Apply rotation matrix */
|
||||
vec->x = (cos_val * temp.x) - (sin_val * temp.y);
|
||||
vec->y = (sin_val * temp.x) + (cos_val * temp.y);
|
||||
}
|
||||
|
||||
struct vector_2d *vector_2d_copy(struct vector_2d *opt_res, struct vector_2d *vec)
|
||||
{
|
||||
struct vector_2d *res;
|
||||
|
||||
if (!vec)
|
||||
return NULL;
|
||||
|
||||
if (opt_res)
|
||||
res = opt_res;
|
||||
else
|
||||
res = vector_2d_alloc();
|
||||
|
||||
if (res) {
|
||||
res->x = vec->x;
|
||||
res->y = vec->y;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct vector_2d *vector_2d_alloc(void)
|
||||
{
|
||||
return (struct vector_2d *)malloc(sizeof(struct vector_2d));
|
||||
}
|
||||
|
||||
void vector_2d_free(struct vector_2d *vec)
|
||||
{
|
||||
if (vec) {
|
||||
free(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void vector_2d_scale(struct vector_2d *vec, double scale)
|
||||
{
|
||||
if (!vec)
|
||||
return;
|
||||
|
||||
vec->x *= scale;
|
||||
vec->y *= scale;
|
||||
}
|
||||
|
||||
double vector_2d_abs(struct vector_2d *vec)
|
||||
{
|
||||
double len = 0.0;
|
||||
if (vec) {
|
||||
len = sqrt(pow(vec->x,2)+pow(vec->y,2));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
double vector_2d_calculate_angle_between(struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
double cos_angle;
|
||||
|
||||
if (!a || !b)
|
||||
return 0.0;
|
||||
|
||||
cos_angle = ABS_DBL(vector_2d_scalar_multipy(a, b)) / (vector_2d_abs(a) * vector_2d_abs(b));
|
||||
return acos(cos_angle);
|
||||
}
|
||||
|
||||
void vector_2d_subtract(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
if (res && a && b) {
|
||||
res->x = a->x - b->x;
|
||||
res->y = a->y - b->y;
|
||||
}
|
||||
}
|
||||
|
||||
void vector_2d_add(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
if (res && a && b) {
|
||||
res->x = a->x +b->x;
|
||||
res->y = a->y + b->y;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
58
trigonometric/vector-operations.h
Normal file
58
trigonometric/vector-operations.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file vector-operations.h
|
||||
* @brief Header for 2D Vector operations
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup trigonometric
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _VECTOR_OPERATIONS_H_
|
||||
#define _VECTOR_OPERATIONS_H_
|
||||
|
||||
#include <math.h>
|
||||
|
||||
struct vector_2d {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
#define DEG2RAD(a) ((a)*M_PI/180.0)
|
||||
|
||||
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b);
|
||||
void vector_2d_normalize(struct vector_2d *vec);
|
||||
void vector_2d_rotate(struct vector_2d *vec, double angle);
|
||||
struct vector_2d *vector_2d_copy(struct vector_2d *opt_res, struct vector_2d *vec);
|
||||
struct vector_2d *vector_2d_alloc(void);
|
||||
void vector_2d_free(struct vector_2d *vec);
|
||||
void vector_2d_scale(struct vector_2d *vec, double scale);
|
||||
double vector_2d_abs(struct vector_2d *vec);
|
||||
double vector_2d_calculate_angle_between(struct vector_2d *a, struct vector_2d *b);
|
||||
void vector_2d_subtract(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b);
|
||||
void vector_2d_add(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b);
|
||||
|
||||
#endif /* _VECTOR_OPERATIONS_H_ */
|
||||
|
||||
/** @} */
|
5
version/CMakeLists.txt
Normal file
5
version/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_library(version STATIC "version.c")
|
||||
execute_process(COMMAND bash ./generate-version-string.sh
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_VER)
|
||||
target_compile_definitions(version PUBLIC PROJECT_GIT_VERSION=${GIT_VER})
|
1
version/generate-version-string.sh
Executable file
1
version/generate-version-string.sh
Executable file
@@ -0,0 +1 @@
|
||||
git describe --tags
|
@@ -17,24 +17,18 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __LAYER_SELECTOR_H__
|
||||
#define __LAYER_SELECTOR_H__
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#ifdef PROJECT_GIT_VERSION
|
||||
|
||||
struct layer_info
|
||||
{
|
||||
int layer;
|
||||
char *name;
|
||||
int stacked_position; ///< Lower is bottom, higher is top
|
||||
GdkRGBA color;
|
||||
};
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
const char *_app_version_string = xstr(PROJECT_GIT_VERSION);
|
||||
#else
|
||||
const char *_app_version_string = "! version not set !";
|
||||
#endif
|
||||
|
||||
void generate_layer_widgets(GtkListBox *listbox, GList *libs);
|
||||
void setup_load_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||
void setup_save_mapping_callback(GtkWidget *button, GtkWindow *main_window);
|
||||
GList *export_rendered_layer_info();
|
||||
void delete_layer_info_struct(struct layer_info *info);
|
||||
|
||||
#endif /* __LAYER_SELECTOR_H__ */
|
||||
/** @} */
|
28
version/version.h
Normal file
28
version/version.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup MainApplication
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief This string holds the 'git describe' version of the app */
|
||||
extern char *_app_version_string;
|
||||
|
||||
/** @} */
|
@@ -17,22 +17,42 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file conv-settings-dialog.c
|
||||
* @brief Implementation of the setting dialog
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "conv-settings-dialog.h"
|
||||
|
||||
struct _RendererSettingsDialog {
|
||||
GtkDialog parent;
|
||||
/* Private loot */
|
||||
GtkWidget *radio_latex;
|
||||
GtkWidget *radio_cairo;
|
||||
GtkWidget *radio_cairo_pdf;
|
||||
GtkWidget *radio_cairo_svg;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *layer_check;
|
||||
GtkWidget *standalone_check;
|
||||
GtkDrawingArea *shape_drawing;
|
||||
GtkLabel *x_label;
|
||||
GtkLabel *y_label;
|
||||
|
||||
GtkLabel *x_output_label;
|
||||
GtkLabel *y_output_label;
|
||||
|
||||
unsigned int cell_height;
|
||||
unsigned int cell_width;
|
||||
double unit_in_meters;
|
||||
};
|
||||
|
||||
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 */
|
||||
@@ -60,28 +80,169 @@ static void latex_render_callback(GtkToggleButton *radio, RendererSettingsDialog
|
||||
hide_tex_options(dialog);
|
||||
}
|
||||
|
||||
static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
GtkStyleContext *style_context;
|
||||
GdkRGBA foreground_color;
|
||||
RendererSettingsDialog *dialog = (RendererSettingsDialog *)data;
|
||||
double usable_width;
|
||||
double usable_height;
|
||||
double height_scale;
|
||||
double width_scale;
|
||||
double final_scale_value;
|
||||
|
||||
style_context = gtk_widget_get_style_context(widget);
|
||||
width = gtk_widget_get_allocated_width(widget);
|
||||
height = gtk_widget_get_allocated_height(widget);
|
||||
|
||||
gtk_render_background(style_context, cr, 0, 0, width, height);
|
||||
|
||||
gtk_style_context_get_color(style_context, gtk_style_context_get_state(style_context),
|
||||
&foreground_color);
|
||||
|
||||
gdk_cairo_set_source_rgba(cr, &foreground_color);
|
||||
|
||||
cairo_save(cr);
|
||||
|
||||
/* Tranform coordiante system */
|
||||
cairo_scale(cr, 1, -1);
|
||||
cairo_translate(cr, (double)width/2.0, -(double)height/2.0);
|
||||
|
||||
/* Define usable drawing area */
|
||||
usable_width = (0.95*(double)width) - 15.0;
|
||||
usable_height = (0.95*(double)height) - 15.0;
|
||||
|
||||
width_scale = usable_width/(double)dialog->cell_width;
|
||||
height_scale = usable_height/(double)dialog->cell_height;
|
||||
|
||||
final_scale_value = (width_scale < height_scale ? width_scale : height_scale);
|
||||
|
||||
cairo_rectangle(cr, -(double)dialog->cell_width*final_scale_value/2.0, -(double)dialog->cell_height*final_scale_value/2.0,
|
||||
(double)dialog->cell_width*final_scale_value, (double)dialog->cell_height*final_scale_value);
|
||||
cairo_stroke(cr);
|
||||
cairo_restore(cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static double convert_number_to_engineering(double input, const char **out_prefix)
|
||||
{
|
||||
const char *selected_prefix = NULL;
|
||||
double return_val = 0.0;
|
||||
int idx;
|
||||
const static char * prefixes[] = {"y", "z", "a", "f", "p", "n", "u", "m", "c", "d", /* < 1 */
|
||||
"", /* 1 */
|
||||
"h", "k", "M", "G", "T", "P", "E", "Z", "Y"}; /* > 1 */
|
||||
const static double scale[] = {1E-24, 1E-21, 1E-18, 1E-15, 1E-12, 1E-9, 1E-6, 1E-3, 1E-2, 1E-1,
|
||||
1,
|
||||
1E2, 1E3, 1E6, 1E9, 1E12, 1E15, 1E18, 1E21, 1E24};
|
||||
const int prefix_count = (int)(sizeof(prefixes)/sizeof(char *));
|
||||
|
||||
for (idx = 1; idx < prefix_count; idx++) {
|
||||
if (input < scale[idx]) {
|
||||
/* This prefix is bigger than the number. Take the previous one */
|
||||
selected_prefix = prefixes[idx-1];
|
||||
return_val = input / scale[idx-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if prefix was set by loop. Else take the largest in the list */
|
||||
if (selected_prefix == NULL) {
|
||||
selected_prefix = prefixes[prefix_count-1];
|
||||
return_val = input / scale[prefix_count-1];
|
||||
}
|
||||
|
||||
if (out_prefix)
|
||||
*out_prefix = selected_prefix;
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self)
|
||||
{
|
||||
char default_buff[100];
|
||||
double scale;
|
||||
double width_meters;
|
||||
double height_meters;
|
||||
double width_engineering;
|
||||
const char *width_prefix;
|
||||
double height_engineering;
|
||||
const char *height_prefix;
|
||||
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
width_meters = (double)self->cell_width * self->unit_in_meters;
|
||||
height_meters = (double)self->cell_height * self->unit_in_meters;
|
||||
|
||||
width_engineering = convert_number_to_engineering(width_meters, &width_prefix);
|
||||
height_engineering = convert_number_to_engineering(height_meters, &height_prefix);
|
||||
|
||||
snprintf(default_buff, sizeof(default_buff), "Width: %.3lf %sm", width_engineering, width_prefix);
|
||||
gtk_label_set_text(self->x_label, default_buff);
|
||||
snprintf(default_buff, sizeof(default_buff), "Height: %.3lf %sm", height_engineering, height_prefix);
|
||||
gtk_label_set_text(self->y_label, default_buff);
|
||||
|
||||
scale = gtk_range_get_value(GTK_RANGE(self->scale));
|
||||
|
||||
/* Set the pixel sizes */
|
||||
snprintf(default_buff, sizeof(default_buff), "Output Width: %u px",
|
||||
(unsigned int)((double)self->cell_width / scale));
|
||||
gtk_label_set_text(self->x_output_label, default_buff);
|
||||
snprintf(default_buff, sizeof(default_buff), "Output Height: %u px",
|
||||
(unsigned int)((double)self->cell_height / scale));
|
||||
gtk_label_set_text(self->y_output_label, default_buff);
|
||||
}
|
||||
|
||||
static void scale_value_changed(GtkRange *range, gpointer user_data)
|
||||
{
|
||||
(void)range;
|
||||
RendererSettingsDialog *dialog;
|
||||
|
||||
dialog = RENDERER_SETTINGS_DIALOG(user_data);
|
||||
renderer_settings_dialog_update_labels(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->radio_cairo_pdf = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-pdf-radio"));
|
||||
self->radio_cairo_svg = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-svg-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"));
|
||||
self->shape_drawing = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "shape-drawer"));
|
||||
self->x_label = GTK_LABEL(gtk_builder_get_object(builder, "x-label"));
|
||||
self->y_label = GTK_LABEL(gtk_builder_get_object(builder, "y-label"));
|
||||
self->x_output_label = GTK_LABEL(gtk_builder_get_object(builder, "x-output-label"));
|
||||
self->y_output_label = GTK_LABEL(gtk_builder_get_object(builder, "y-output-label"));
|
||||
|
||||
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_signal_connect(G_OBJECT(self->shape_drawing),
|
||||
"draw", G_CALLBACK(shape_drawer_drawing_callback), (gpointer)self);
|
||||
|
||||
g_signal_connect(self->scale, "value-changed", G_CALLBACK(scale_value_changed), (gpointer)self);
|
||||
|
||||
/* Default values */
|
||||
self->cell_width = 1;
|
||||
self->cell_height = 1;
|
||||
self->unit_in_meters = 1E-6;
|
||||
renderer_settings_dialog_update_labels(self);
|
||||
|
||||
g_object_unref(builder);
|
||||
}
|
||||
@@ -99,13 +260,27 @@ RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
|
||||
|
||||
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
|
||||
{
|
||||
/*GList *radio_buttons;
|
||||
*GList *temp_button_list;
|
||||
*GtkToggleButton *temp_button = NULL;
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Get active radio button selection */
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE) {
|
||||
settings->renderer = RENDERER_LATEX_TIKZ;
|
||||
} else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf)) == TRUE) {
|
||||
settings->renderer = RENDERER_CAIROGRAPHICS_PDF;
|
||||
} else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg)) == TRUE) {
|
||||
settings->renderer = RENDERER_CAIROGRAPHICS_SVG;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -120,9 +295,51 @@ void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struc
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_latex), TRUE);
|
||||
show_tex_options(dialog);
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS:
|
||||
case RENDERER_CAIROGRAPHICS_PDF:
|
||||
hide_tex_options(dialog);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo), TRUE);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf), TRUE);
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS_SVG:
|
||||
hide_tex_options(dialog);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg), TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width)
|
||||
{
|
||||
if (!dialog)
|
||||
return;
|
||||
|
||||
if (width == 0)
|
||||
width = 1;
|
||||
|
||||
dialog->cell_width = width;
|
||||
renderer_settings_dialog_update_labels(dialog);
|
||||
}
|
||||
|
||||
void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height)
|
||||
{
|
||||
if (!dialog)
|
||||
return;
|
||||
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
dialog->cell_height = height;
|
||||
renderer_settings_dialog_update_labels(dialog);
|
||||
}
|
||||
|
||||
void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters)
|
||||
{
|
||||
if (!dialog)
|
||||
return;
|
||||
|
||||
if (unit_in_meters < 0)
|
||||
unit_in_meters *= -1;
|
||||
|
||||
dialog->unit_in_meters = unit_in_meters;
|
||||
renderer_settings_dialog_update_labels(dialog);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,6 +17,17 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file conv-settings-dialog.h
|
||||
* @brief Header file for the Conversion Settings Dialog
|
||||
* @author Mario.Huettel@gmx.net <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __CONV_SETTINGS_DIALOG_H__
|
||||
#define __CONV_SETTINGS_DIALOG_H__
|
||||
|
||||
@@ -24,25 +35,67 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
enum output_renderer {RENDERER_LATEX_TIKZ, RENDERER_CAIROGRAPHICS};
|
||||
/** @brief return type of the RedererSettingsDialog */
|
||||
enum output_renderer {RENDERER_LATEX_TIKZ, RENDERER_CAIROGRAPHICS_PDF, RENDERER_CAIROGRAPHICS_SVG};
|
||||
|
||||
G_DECLARE_FINAL_TYPE(RendererSettingsDialog, renderer_settings_dialog, RENDERER, SETTINGS_DIALOG, GtkDialog)
|
||||
|
||||
/**
|
||||
* @brief Create a new RedererSettingsDialog GObject
|
||||
* @param parent Parent window
|
||||
* @return Created dialog object
|
||||
*/
|
||||
RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent);
|
||||
|
||||
#define RENDERER_TYPE_SETTINGS_DIALOG (renderer_settings_dialog_get_type())
|
||||
|
||||
/**
|
||||
* @brief This struct holds the renderer configuration
|
||||
*/
|
||||
struct render_settings {
|
||||
double scale;
|
||||
enum output_renderer renderer;
|
||||
gboolean tex_pdf_layers;
|
||||
gboolean tex_standalone;
|
||||
double scale; /**< @brief Scale image down by this factor. @note Used to keep image in bound of maximum coordinate limit */
|
||||
enum output_renderer renderer; /**< The renderer to use */
|
||||
gboolean tex_pdf_layers; /**< Create OCG layers when rendering with TikZ */
|
||||
gboolean tex_standalone; /**< Create a standalone compile TeX file */
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* @brief Apply settings to dialog
|
||||
* @param dialog
|
||||
* @param settings
|
||||
*/
|
||||
void renderer_settings_dialog_set_settings(RendererSettingsDialog *dialog, struct render_settings *settings);
|
||||
|
||||
/**
|
||||
* @brief Get the settings configured in the dialog
|
||||
* @param dialog
|
||||
* @param settings
|
||||
*/
|
||||
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings);
|
||||
|
||||
/**
|
||||
* @brief renderer_settings_dialog_set_cell_width Set width for rendered cell
|
||||
* @param dialog
|
||||
* @param width Width in database units
|
||||
*/
|
||||
void renderer_settings_dialog_set_cell_width(RendererSettingsDialog *dialog, unsigned int width);
|
||||
|
||||
/**
|
||||
* @brief renderer_settings_dialog_set_cell_height Set height for rendered cell
|
||||
* @param dialog
|
||||
* @param height Height in database units
|
||||
*/
|
||||
void renderer_settings_dialog_set_cell_height(RendererSettingsDialog *dialog, unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief renderer_settings_dialog_set_database_unit_scale Set database scale
|
||||
* @param dialog dialog element
|
||||
* @param unit_in_meters Database unit in meters
|
||||
*/
|
||||
void renderer_settings_dialog_set_database_unit_scale(RendererSettingsDialog *dialog, double unit_in_meters);
|
||||
|
||||
#endif /* __CONV_SETTINGS_DIALOG_H__ */
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,6 +17,24 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The drag and drop implementation is adapted from
|
||||
* https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/tests/testlist3.c
|
||||
*
|
||||
* Thanks to the GTK3 people for creating these examples.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-element.c
|
||||
* @brief Implementation of the layer element used for configuring layer colors etc.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "layer-element.h"
|
||||
|
||||
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
|
||||
@@ -52,15 +70,16 @@ static void layer_element_drag_begin(GtkWidget *widget,
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
(void)data;
|
||||
|
||||
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);
|
||||
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_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_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);
|
||||
@@ -68,48 +87,35 @@ static void layer_element_drag_begin(GtkWidget *widget,
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
|
||||
}
|
||||
|
||||
static void layer_element_drag_data_get(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
static void layer_element_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
|
||||
{
|
||||
GtkWidget *row;
|
||||
(void)context;
|
||||
(void)data;
|
||||
|
||||
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
|
||||
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL);
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-row");
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-hover");
|
||||
}
|
||||
|
||||
static void layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
guint info, guint time, gpointer data)
|
||||
{
|
||||
(void)context;
|
||||
(void)info;
|
||||
(void)time;
|
||||
(void)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;
|
||||
@@ -126,11 +132,11 @@ static void layer_element_init(LayerElement *self)
|
||||
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
|
||||
|
||||
/* Setup drag and drop */
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context(GTK_WIDGET(self)), "row");
|
||||
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_signal_connect(self->priv.event_handle, "drag-end", G_CALLBACK(layer_element_drag_end), NULL);
|
||||
|
||||
g_object_unref(builder);
|
||||
}
|
||||
@@ -187,3 +193,5 @@ void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
|
||||
{
|
||||
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@@ -17,6 +17,17 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-element.h
|
||||
* @brief Omplementation of the layer element used for configuring layer colors etc.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __LAYER_ELEMENT_H__
|
||||
#define __LAYER_ELEMENT_H__
|
||||
|
||||
@@ -45,17 +56,70 @@ struct _LayerElement {
|
||||
LayerElementPriv priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create new layer element object
|
||||
* @return new object
|
||||
*/
|
||||
GtkWidget *layer_element_new(void);
|
||||
|
||||
/**
|
||||
* @brief get name of the layer
|
||||
* @param elem Layer element
|
||||
* @return Name. Must not be changed, freed or anything else.
|
||||
*/
|
||||
const char *layer_element_get_name(LayerElement *elem);
|
||||
|
||||
/**
|
||||
* @brief layer_element_set_name
|
||||
* @param elem set the name of the layer
|
||||
* @param name Name. Can be freed after call to this function
|
||||
*/
|
||||
void layer_element_set_name(LayerElement *elem, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Set layer number for this layer
|
||||
* @param elem Layer element
|
||||
* @param layer Layer number
|
||||
*/
|
||||
void layer_element_set_layer(LayerElement *elem, int layer);
|
||||
|
||||
/**
|
||||
* @brief Get layer number
|
||||
* @param elem Layer Element
|
||||
* @return Number of this layer
|
||||
*/
|
||||
int layer_element_get_layer(LayerElement *elem);
|
||||
|
||||
/**
|
||||
* @brief Set export flag for this layer
|
||||
* @param elem Layer Element
|
||||
* @param export flag
|
||||
*/
|
||||
void layer_element_set_export(LayerElement *elem, gboolean export);
|
||||
|
||||
/**
|
||||
* @brief Get export flag of layer
|
||||
* @param elem Layer Element
|
||||
* @return
|
||||
*/
|
||||
gboolean layer_element_get_export(LayerElement *elem);
|
||||
|
||||
/**
|
||||
* @brief Get color of layer
|
||||
* @param elem Layer Element
|
||||
* @param rgba RGBA color
|
||||
*/
|
||||
void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba);
|
||||
|
||||
/**
|
||||
* @brief Set color of layer
|
||||
* @param elem Layer Element
|
||||
* @param rgba RGBA color
|
||||
*/
|
||||
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __LAYER_ELEMENT_H__ */
|
||||
|
||||
/** @} */
|
||||
|
Reference in New Issue
Block a user