Compare commits

..

69 Commits

Author SHA1 Message Date
504dc476b1 Fix recursive clone in github actions 2022-12-17 19:00:16 +01:00
8ff872cf36 Fix recursive clone in github actions 2022-12-17 18:57:19 +01:00
9c4dbd51c8 Merge branch 'dev' 2022-12-17 18:52:05 +01:00
2829143bbe Merge pull request 'Fix #49: Initialize variable' (#50) from fix-issue-49 into dev
Reviewed-on: #50
2022-12-17 18:43:56 +01:00
5185097075 Fix #49: Initialize variable 2022-12-17 18:43:10 +01:00
573cd59892 Merge branch 'dev' 2022-04-17 22:21:38 +02:00
8b1f667819 Merge pull request 'issue/47-add-vertex-count-to-gui' (#48) from issue/47-add-vertex-count-to-gui into dev
Reviewed-on: #48
2022-04-17 20:09:47 +02:00
c2ca2ff573 Rework the analysis cmd option to work with new statistics functions 2022-04-17 20:07:57 +02:00
c0ac6cc3c5 Move statistic calculation to parser. Show Vertex and GFX count in GUI. CLI -A param is now broken. Will implement in next commits. 2022-04-17 18:37:32 +02:00
22bc3a18d7 Issue #47: Add renderer for cell statistics and render dummy value 2022-04-17 17:40:18 +02:00
dbc9fcdf34 Issue #47: AddVertex count column to tree view 2022-04-17 16:54:57 +02:00
b39030aeaa Fix PKGBUILD 2022-04-17 00:47:41 +02:00
2f59a762cd Fix PKGBUILD 2022-04-17 00:46:51 +02:00
ab26f8a2af Fix PKGBUILD 2022-04-17 00:45:49 +02:00
9a43cd53f8 Update PKGBUILD 2022-04-17 00:38:50 +02:00
ba6b07c8a2 Implement cell statistics command line interface 2022-04-17 00:37:26 +02:00
1548c82542 Add libfort for pretty console tables 2022-04-16 16:13:22 +02:00
fb6d31c120 Fix stuck at -1 return value when executing command line interface 2022-04-16 16:00:50 +02:00
f6c65d9c7a Merge branch 'dev' 2022-04-10 15:35:14 +02:00
d43bec2cea Merge pull request 'issue/44-remove-duplicate-vertices' (#45) from issue/44-remove-duplicate-vertices into dev
Reviewed-on: #45
2022-04-10 15:33:41 +02:00
05a1ef9014 Disable debug output of parser. 2022-04-10 15:31:55 +02:00
a36b78b237 Add vertex simplification to parser
* Duplicate / Redundant vertices of polygons are now removed during parsing.
* Implications: Reduced output size of tex document, faster rendering.
2022-04-10 15:28:23 +02:00
ac87cafa37 Merge pull request 'Merge new features and minor fixes for v1.2.1 release' (#43) from dev into master
Reviewed-on: #43
2022-04-09 20:39:09 +02:00
091729841a Merge branch 'master' into dev 2022-04-09 20:39:07 +02:00
28368e8a32 Cairo Renderer: Only print notification that layer is rendered, if it is actually rendered 2022-04-09 20:36:49 +02:00
2b3cc8222a Merge pull request 'Change icons to new Adwaita icons' (#42) from update-icons into dev
Reviewed-on: #42
2022-04-09 20:15:26 +02:00
c23150b819 Merge branch 'dev' into update-icons 2022-04-09 20:15:01 +02:00
049e6c2a4c Merge pull request 'Improve some features' (#41) from improve-features into dev
Reviewed-on: #41
2022-04-09 20:13:47 +02:00
600e10e4d5 Increase layer count of Cairo renderer as this turned out to be too low for some semiconductor technologies 2022-04-09 20:10:11 +02:00
238f2cea82 Improve Autonaming in GUI
Autonaming now only asks for overwrite confirmation, if there
are layers with non empty names. Otherwise, the dialog is not shown.
2022-04-09 20:08:24 +02:00
91706ccf2e Change icons to new Adwaita icons 2022-04-09 19:40:39 +02:00
17e7239e54 Merge branch 'dev' 2022-02-11 21:57:10 +01:00
554b73c406 Fix hard crash in case of a unwritable Latex Output file. Print warnign instead of hard stop 2022-02-11 21:56:54 +01:00
4eebff04a4
Update README.MD
Add github status badge for CI
2021-10-01 23:46:32 +02:00
04525611fa
Update cmake.yml
Add gettext to dependencies
2021-10-01 23:43:37 +02:00
cb92d64ec3
Update cmake.yml 2021-10-01 23:41:40 +02:00
37ff2080f9
Create cmake.yml 2021-10-01 23:35:16 +02:00
e1b85d1a99 Merge branch 'issue/39-fix-search' of mhu/gds-render into dev 2020-11-26 23:08:55 +01:00
b0c9afdae5 Fix #39: Checking of pure library entry in cell selector was broken 2020-11-26 23:07:48 +01:00
f6abfada2c ColorPalette: Fix Dispose function
* Set freed pointer to NULL in dispose function because dispose cna be run multiple times. This fixes the case of freeing an already freed pointer.
2020-07-09 23:54:40 +02:00
f135b42d8a make clear we're not getting a return value from vector_2d_copy 2020-06-29 20:03:38 +02:00
058564326b Update library and compiler versions in doxygen 2020-04-24 01:17:20 +02:00
fd1eac7fda Merge branch 'master' into dev 2020-04-24 01:07:50 +02:00
2c91956b32 Doxygen: Update calculate_cell_bounding_box()
* Fix typo
* Extend description
2020-04-24 01:05:37 +02:00
232d025211 Doxygen: Update calculate_cell_bounding_box()
* Add note about problematic behaviour
* Fix typos
2020-04-24 01:02:10 +02:00
ceeb67355d Fix #38: Make parser store the datatype record of a graphics object 2020-04-19 02:58:34 +02:00
ba51a437a4 Fix definition of datatype in GDS graphics type 2020-04-19 02:57:15 +02:00
e461b0be1d Merge branch 'dev' 2020-04-19 00:52:42 +02:00
42f1636860 Make unit test reporting compact 2020-04-19 00:50:30 +02:00
d29109e516 Add unittests for calculation functions for vectors 2020-04-19 00:40:17 +02:00
b784f28d4c Change unit test output to include successful tests as well 2020-04-19 00:40:03 +02:00
94851570e9 Add preliminary working principle of unit tests 2020-04-18 03:23:15 +02:00
f4fa1bd4e5 Make tests link against libraries 2020-04-18 02:45:23 +02:00
2e7bb03c17 Add testing folder to doxygen's exclude list 2020-04-18 02:38:40 +02:00
39ff0dec1a Add test target to cmake 2020-04-18 02:32:11 +02:00
74f9663bde Add catch framework for testing 2020-04-18 02:21:23 +02:00
330285cc2f Merge branch 'master' into dev 2020-04-16 22:47:38 +02:00
24ae5e4d5b Fix #37: Introduce new versioning scheme for AUR PKGBUILD 2020-04-16 22:43:29 +02:00
f7d15c7267 Fix comment style from // to /**/ 2020-04-07 15:39:38 +02:00
00d02b8291 Issue #36: Fix possible memory leak of async status message, if rendering finishes, before message could be displayed 2020-04-03 20:53:32 +02:00
75e01b80c8 Issue #36: Fix memory leaks in set-property function of lib-cell-renderer 2020-04-03 20:32:05 +02:00
89f9a638c6 Add license header to file 2020-04-02 00:47:43 +02:00
7b1722661c Fix typo in documentation 2020-01-16 23:38:20 +01:00
5a43a8a4bf Rename functions of bounding box to be more consistent 2020-01-14 19:03:26 +01:00
f11e11e6a7 Doxygen: Add brief description for conv_generic_to_vector_2d_t 2020-01-14 19:02:50 +01:00
0c5dd3c8e7 Doxygen: Document union bounding_box 2020-01-14 18:52:03 +01:00
77a3a0da5a Doxygen: Fix typo 2020-01-14 18:52:03 +01:00
f8b0b63937 Doxygen: Remove warning from uncommented code printf and place it in doxygen @warning tag instead 2020-01-14 18:51:55 +01:00
2d389342fd cairo-renderer: Update coding style and add comment explaining how to use the inter process communication to update the GUI with rendering status updates 2020-01-14 14:09:24 +01:00
41 changed files with 18977 additions and 265 deletions

40
.github/workflows/cmake.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: CMake
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
with:
submodules: recursive
- name: Install system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get -y install libgtk-3-dev gettext
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

4
.gitmodules vendored
View File

@ -2,3 +2,7 @@
path = c-style-checker path = c-style-checker
url = https://git.shimatta.de/mhu/c-style-checker url = https://git.shimatta.de/mhu/c-style-checker
branch = master branch = master
[submodule "3rdparty/libfort"]
path = 3rdparty/libfort
url = https://git.shimatta.de/3rd-party/libfort
branch = develop

1
3rdparty/libfort vendored Submodule

@ -0,0 +1 @@
Subproject commit 41237162a9bd34a30a88069ee4e230584ae8d674

View File

@ -1,7 +1,7 @@
# Maintainer: Mario Hüttel <mario (dot) huettel (!) gmx (dot) net> # Maintainer: Mario Hüttel <mario (dot) huettel (!) gmx (dot) net>
pkgname=gds-render pkgname=gds-render
pkgver=20191020.403.448de30 pkgver=v1.2_10_g00d02b8
pkgrel=1 pkgrel=1
pkgdesc="Conversion tool for converting GDS layout files into TikZ Code and PDF" pkgdesc="Conversion tool for converting GDS layout files into TikZ Code and PDF"
arch=('i686' 'x86_64') arch=('i686' 'x86_64')
@ -10,13 +10,13 @@ licence=('GPLv2')
depends=('glib2' 'gtk3' 'cairo') depends=('glib2' 'gtk3' 'cairo')
makedepends=('cmake' 'git') makedepends=('cmake' 'git')
privides=('gds-render') privides=('gds-render')
source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/gds-render.git") source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/gds-render.git" "https://git.shimatta.de/3rd-party/libfort.git")
sha1sums=('SKIP') sha1sums=('SKIP' 'SKIP')
pkgver () { pkgver () {
_date=`date +"%Y%m%d"` _date=`date +"%Y%m%d"`
cd "${srcdir}/${pkgname}-git" cd "${srcdir}/${pkgname}-git/version"
echo "$_date.$(git rev-list --count master).$(git rev-parse --short master)" echo "$(echo "$(sh ./generate-version-string.sh)" | sed 's/-/_/g')"
} }
build () { build () {
@ -26,6 +26,13 @@ build () {
make make
} }
prepare () {
cd "${pkgname}-git"
git submodule init
git config submodule.libfort.url "$srcdir/libfort"
git submodule update
}
package () { package () {
cd "$srcdir/$pkgname-git/build" cd "$srcdir/$pkgname-git/build"
make DESTDIR="${pkgdir}" install make DESTDIR="${pkgdir}" install

View File

@ -1,4 +1,4 @@
project(gds-render) project(gds-render LANGUAGES C)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr/" CACHE PATH "..." FORCE) set(CMAKE_INSTALL_PREFIX "/usr/" CACHE PATH "..." FORCE)
@ -33,8 +33,6 @@ pkg_check_modules(CAIRO REQUIRED cairo)
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_subdirectory(plugins) add_subdirectory(plugins)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
IF(CMAKE_BUILD_TYPE STREQUAL "Debug") IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
message("${Yellow}Debug mode for translations used!${ColorReset}") message("${Yellow}Debug mode for translations used!${ColorReset}")
add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"${CMAKE_CURRENT_BINARY_DIR}/translations/output\") add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"${CMAKE_CURRENT_BINARY_DIR}/translations/output\")
@ -44,13 +42,7 @@ else(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"/usr/share\") add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"/usr/share\")
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(resources)
add_subdirectory(doxygen)
add_subdirectory(translations)
add_subdirectory(version)
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("widgets" LAYER_SOURCES)
aux_source_directory("cell-selector" CELL_SELECTOR_SOURCES) aux_source_directory("cell-selector" CELL_SELECTOR_SOURCES)
@ -74,15 +66,32 @@ set(SOURCE_GENERATED
${CMAKE_CURRENT_BINARY_DIR}/resources/resources.c ${CMAKE_CURRENT_BINARY_DIR}/resources/resources.c
) )
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
SET_SOURCE_FILES_PROPERTIES(${SOURCE_GENERATED} PROPERTIES GENERATED 1) SET_SOURCE_FILES_PROPERTIES(${SOURCE_GENERATED} PROPERTIES GENERATED 1)
add_subdirectory(test)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
add_subdirectory(resources)
add_subdirectory(doxygen)
add_subdirectory(translations)
add_subdirectory(version)
set(FORT_ENABLE_TESTING OFF CACHE INTERNAL "")
add_subdirectory(3rdparty/libfort)
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
add_definitions(${GLIB2_CFLAGS_OTHER})
add_executable(${PROJECT_NAME} ${SOURCE} ${SOURCE_GENERATED}) add_executable(${PROJECT_NAME} ${SOURCE} ${SOURCE_GENERATED})
add_dependencies(${PROJECT_NAME} glib-resources) add_dependencies(${PROJECT_NAME} glib-resources)
add_dependencies(${PROJECT_NAME} version) add_dependencies(${PROJECT_NAME} version)
add_dependencies(${PROJECT_NAME} translations) add_dependencies(${PROJECT_NAME} translations)
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS})
install (TARGETS ${PROJECT_NAME} install (TARGETS ${PROJECT_NAME}
RUNTIME RUNTIME
DESTINATION bin DESTINATION bin
) )
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS} fort)

View File

@ -1,5 +1,7 @@
# GDS-Render Readme # GDS-Render Readme
[![CMake](https://github.com/0mhu/gds-render/actions/workflows/cmake.yml/badge.svg?branch=master)](https://github.com/0mhu/gds-render/actions/workflows/cmake.yml)
This software is a rendering programm for GDS2 layout files. This software is a rendering programm for GDS2 layout files.
The GDS2 format is mainly used in integrated circuit development. The GDS2 format is mainly used in integrated circuit development.
This program allows the conversion of a GDS file to a vector graphics file. This program allows the conversion of a GDS file to a vector graphics file.

View File

@ -0,0 +1,106 @@
/*
* GDSII-Converter
* Copyright (C) 2022 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-statistics-renderer.c
* @brief CellStatisticsRenderer GObject Class
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup CellStatisticsRenderer
* @{
*/
#include <gds-render/cell-selector/cell-statistics-renderer.h>
G_DEFINE_TYPE(CellStatisticsRenderer, cell_statistics_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
enum {
PROP_CELL_STAT = 1,
PROP_COUNT
};
static void cell_statistics_renderer_set_property(GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
GValue val = G_VALUE_INIT;
GString *string;
const struct gds_cell_statistics *cell_stat;
switch (param_id) {
case PROP_CELL_STAT:
cell_stat = (const struct gds_cell_statistics *)g_value_get_pointer(value);
g_value_init(&val, G_TYPE_STRING);
string = g_string_new_len("", 5);
if (cell_stat)
g_string_printf(string, "%zu (%zu) | %zu (%zu)", cell_stat->total_vertex_count,
cell_stat->vertex_count, cell_stat->total_gfx_count, cell_stat->gfx_count);
g_value_set_string(&val, string->str);
g_object_set_property(object, "text", &val);
g_value_unset(&val);
g_string_free(string, TRUE);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static void cell_statistics_renderer_get_property(GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
(void)value;
switch (param_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static GParamSpec *properties[PROP_COUNT];
void cell_statistics_renderer_class_init(CellStatisticsRendererClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->set_property = cell_statistics_renderer_set_property;
oclass->get_property = cell_statistics_renderer_get_property;
properties[PROP_CELL_STAT] = g_param_spec_pointer("cell-stat", "cell-stat",
"Cell statistics", G_PARAM_WRITABLE);
g_object_class_install_properties(oclass, PROP_COUNT, properties);
}
void cell_statistics_renderer_init(CellStatisticsRenderer *self)
{
(void)self;
}
GtkCellRenderer *cell_statistics_renderer_new(void)
{
return GTK_CELL_RENDERER(g_object_new(TYPE_GDS_RENDER_CELL_STAT_RENDERER, NULL));
}
/** @} */

View File

@ -88,11 +88,13 @@ static void lib_cell_renderer_set_property(GObject *object,
g_value_init(&val, G_TYPE_STRING); g_value_init(&val, G_TYPE_STRING);
g_value_set_string(&val, ((struct gds_library *)g_value_get_pointer(value))->name); g_value_set_string(&val, ((struct gds_library *)g_value_get_pointer(value))->name);
g_object_set_property(object, "text", &val); g_object_set_property(object, "text", &val);
g_value_unset(&val);
break; break;
case PROP_CELL: case PROP_CELL:
g_value_init(&val, G_TYPE_STRING); g_value_init(&val, G_TYPE_STRING);
g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name); g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name);
g_object_set_property(object, "text", &val); g_object_set_property(object, "text", &val);
g_value_unset(&val);
break; break;
case PROP_ERROR_LEVEL: case PROP_ERROR_LEVEL:
/* Set cell color according to error level */ /* Set cell color according to error level */
@ -100,6 +102,7 @@ static void lib_cell_renderer_set_property(GObject *object,
convert_error_level_to_color(&color, g_value_get_uint(value)); convert_error_level_to_color(&color, g_value_get_uint(value));
g_value_set_boxed(&val, &color); g_value_set_boxed(&val, &color);
g_object_set_property(object, "foreground-rgba", &val); g_object_set_property(object, "foreground-rgba", &val);
g_value_unset(&val);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);

View File

@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <string.h>
#include <gds-render/command-line.h> #include <gds-render/command-line.h>
#include <gds-render/gds-utils/gds-parser.h> #include <gds-render/gds-utils/gds-parser.h>
@ -38,6 +39,41 @@
#include <gds-render/output-renderers/latex-renderer.h> #include <gds-render/output-renderers/latex-renderer.h>
#include <gds-render/output-renderers/external-renderer.h> #include <gds-render/output-renderers/external-renderer.h>
#include <gds-render/gds-utils/gds-tree-checker.h> #include <gds-render/gds-utils/gds-tree-checker.h>
#include <gds-render/gds-utils/gds-statistics.h>
#include <fort.h>
#ifndef COUNT_OF
#define COUNT_OF(x) (sizeof((x))/sizeof(0[(x)]))
#endif
enum analysis_format {
ANA_FORMAT_SIMPLE = 0,
ANA_FORMAT_CELLS_ONLY,
ANA_FORMAT_PRETTY,
};
struct analysis_format_cmdarg {
enum analysis_format format;
const char *argument;
};
static const struct analysis_format_cmdarg analysis_format_lookup[] = {
{
.format = ANA_FORMAT_SIMPLE,
.argument = "simple",
},
{
.format = ANA_FORMAT_PRETTY,
.argument = "pretty",
},
{
.format = ANA_FORMAT_CELLS_ONLY,
.argument = "cellsonly"
}
};
static int string_array_count(char **string_array) static int string_array_count(char **string_array)
{ {
@ -136,14 +172,14 @@ static struct gds_cell *find_gds_cell_in_lib(struct gds_library *lib, const char
} }
int command_line_convert_gds(const char *gds_name, int command_line_convert_gds(const char *gds_name,
const char *cell_name, const char *cell_name,
char **renderers, char **renderers,
char **output_file_names, char **output_file_names,
const char *layer_file, const char *layer_file,
struct external_renderer_params *ext_param, struct external_renderer_params *ext_param,
gboolean tex_standalone, gboolean tex_standalone,
gboolean tex_layers, gboolean tex_layers,
double scale) double scale)
{ {
int ret = -1; int ret = -1;
GList *libs = NULL; GList *libs = NULL;
@ -155,6 +191,10 @@ int command_line_convert_gds(const char *gds_name,
LayerSettings *layer_sett; LayerSettings *layer_sett;
GdsOutputRenderer *current_renderer; GdsOutputRenderer *current_renderer;
const struct gds_library_parsing_opts gds_parsing_options = {
.simplified_polygons = 1,
};
/* Check if parameters are valid */ /* Check if parameters are valid */
if (!gds_name || !cell_name || !output_file_names || !layer_file || !renderers) { if (!gds_name || !cell_name || !output_file_names || !layer_file || !renderers) {
printf(_("Probably missing argument. Check --help option\n")); printf(_("Probably missing argument. Check --help option\n"));
@ -173,7 +213,7 @@ int command_line_convert_gds(const char *gds_name,
/* Load GDS */ /* Load GDS */
clear_lib_list(&libs); clear_lib_list(&libs);
res = parse_gds_from_file(gds_name, &libs); res = parse_gds_from_file(gds_name, &libs, &gds_parsing_options);
if (res) if (res)
goto ret_destroy_library_list; goto ret_destroy_library_list;
@ -224,6 +264,8 @@ int command_line_convert_gds(const char *gds_name,
gds_output_renderer_render_output(current_renderer, toplevel_cell, scale); gds_output_renderer_render_output(current_renderer, toplevel_cell, scale);
} }
ret = 0;
ret_destroy_library_list: ret_destroy_library_list:
clear_lib_list(&libs); clear_lib_list(&libs);
ret_clear_renderers: ret_clear_renderers:
@ -234,4 +276,192 @@ ret_destroy_layer_mapping:
return ret; return ret;
} }
static void indent_line(int level)
{
while (level--)
printf("\t");
}
static int printf_indented(int level, const char *format, ...)
{
int ret;
va_list a_list;
va_start(a_list, format);
indent_line(level);
ret = vprintf(format, a_list);
va_end(a_list);
return ret;
}
static void print_simple_stat(GList *lib_stat_list)
{
int indentation_level = 0;
GList *lib_iter;
GList *cell_iter;
const struct gds_library *lib;
const struct gds_cell *cell;
const struct gds_lib_statistics *lib_stat;
const struct gds_cell_statistics *cell_stat;
for (lib_iter = lib_stat_list; lib_iter; lib_iter = g_list_next(lib_iter)) {
lib = (const struct gds_library *)lib_iter->data;
lib_stat = &lib->stats;
printf_indented(indentation_level, "Library %s\n", lib->name);
indentation_level++;
for (cell_iter = lib->cells; cell_iter; cell_iter = g_list_next(cell_iter)) {
cell = (const struct gds_cell *)cell_iter->data;
cell_stat = &cell->stats;
printf_indented(indentation_level, "Cell %s\n", cell->name);
indentation_level++;
printf_indented(indentation_level, "Reference count: %zu\n", cell_stat->reference_count);
printf_indented(indentation_level, "Graphics count: %zu\n", cell_stat->gfx_count);
printf_indented(indentation_level, "Total Graphics count: %zu\n", cell_stat->total_gfx_count);
printf_indented(indentation_level, "Vertex count: %zu\n", cell_stat->vertex_count);
printf_indented(indentation_level, "Total Vertex count: %zu\n", cell_stat->total_vertex_count);
printf_indented(indentation_level, "Unresolved children: %d\n",
cell->checks.unresolved_child_count);
printf_indented(indentation_level, "Reference loop: %s\n",
cell->checks.affected_by_reference_loop ? "yes" : "no");
indentation_level--;
}
printf_indented(indentation_level, "Cell count: %zu\n", lib_stat->cell_count);
printf_indented(indentation_level, "Reference count: %zu\n", lib_stat->reference_count);
printf_indented(indentation_level, "Graphics count: %zu\n", lib_stat->gfx_count);
printf_indented(indentation_level, "Vertex count: %zu\n", lib_stat->vertex_count);
}
}
static void table_stat_create_cell_row(struct gds_cell *cell, ft_table_t *tab)
{
ft_printf_ln(tab, "%s|%s|%zu|%zu|%zu|%zu|%zu|%d|%s",
cell->parent_library->name,
cell->name,
cell->stats.gfx_count,
cell->stats.total_gfx_count,
cell->stats.vertex_count,
cell->stats.total_vertex_count,
cell->stats.reference_count,
cell->checks.unresolved_child_count,
cell->checks.affected_by_reference_loop ? "yes" : "no");
}
static void table_stat_table_for_lib(struct gds_library *lib, ft_table_t *tab)
{
ft_printf_ln(tab, "%s|%zu|%zu|-|%zu|-|%zu|-|-",
lib->name,
lib->stats.cell_count,
lib->stats.gfx_count,
lib->stats.vertex_count,
lib->stats.reference_count);
g_list_foreach(lib->cells, (GFunc)table_stat_create_cell_row, tab);
}
static void print_table_stat(GList *lib_list)
{
ft_table_t *table;
table = ft_create_table();
ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
ft_write_ln(table, "Library", "Cell", "GFX", "GFX+", "Vertices", "Vertices+", "Refs", "Unresolved Refs", "Loops");
g_list_foreach(lib_list, (GFunc)table_stat_table_for_lib, table);
printf("%s\n", ft_to_string(table));
ft_destroy_table(table);
}
static void print_statistics(enum analysis_format format, GList *lib_list)
{
switch (format) {
case ANA_FORMAT_PRETTY:
print_table_stat(lib_list);
break;
default:
print_simple_stat(lib_list);
break;
}
}
static void print_cell_names(GList *lib_list)
{
GList *lib_iter;
GList *name_iter;
struct gds_library *lib;
for (lib_iter = lib_list; lib_iter; lib_iter = g_list_next(lib_iter)) {
lib = (struct gds_library *)lib_iter->data;
for (name_iter = lib->cell_names; name_iter; name_iter = name_iter->next) {
printf("%s\n", (const char *)name_iter->data);
}
}
}
int command_line_analyze_lib(const char *format, const char *gds_name)
{
enum analysis_format fmt = ANA_FORMAT_SIMPLE;
size_t idx;
int found = 0;
GList *lib_list = NULL;
const struct gds_library_parsing_opts parsing_opts = {
.simplified_polygons = 0,
};
int res;
int ret = 0;
GList *lib_iter;
g_return_val_if_fail(gds_name, -1002);
if (format && *format) {
/* Check format if it is not empty */
for (idx = 0; idx < COUNT_OF(analysis_format_lookup); idx++) {
if (!strcmp(analysis_format_lookup[idx].argument, format)) {
/* Format specifier matches */
fmt = analysis_format_lookup[idx].format;
found = 1;
}
}
if (!found) {
fprintf(stderr, "No format matches %s. Using default.\n", format);
}
}
/* Load the GDS file */
res = parse_gds_from_file(gds_name, &lib_list, &parsing_opts);
if (res) {
fprintf(stderr, "Error parsing GDS file\n");
(void)clear_lib_list(&lib_list);
ret = res;
goto return_val;
}
for (lib_iter = lib_list; lib_iter; lib_iter = g_list_next(lib_iter)) {
res = gds_tree_check_cell_references((struct gds_library *)lib_iter->data);
if (res < 0) {
fprintf(stderr, "Error checking cell references. Will continue...\n");
}
res = gds_tree_check_reference_loops((struct gds_library *)lib_iter->data);
if (res < 0) {
fprintf(stderr, "Error checking cell reference loops. Will continue...\n");
}
}
if (fmt == ANA_FORMAT_CELLS_ONLY) {
print_cell_names(lib_list);
goto return_clear_libs;
}
print_statistics(fmt, lib_list);
return_clear_libs:
clear_lib_list(&lib_list);
return_val:
return ret;
}
/** @} */ /** @} */

View File

@ -1,4 +1,4 @@
# Doxyfile 1.8.16 # Doxyfile 1.8.17
# This file describes the settings to be used by the documentation system # This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project. # doxygen (www.doxygen.org) for a project.
@ -309,7 +309,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
# parses. With this tag you can assign which parser to use for a given # parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it # extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and # using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript, # language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
@ -535,8 +535,8 @@ HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be # declarations. If set to NO, these declarations will be included in the
# included in the documentation. # documentation.
# The default value is: NO. # The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO HIDE_FRIEND_COMPOUNDS = NO
@ -851,8 +851,10 @@ INPUT_ENCODING = UTF-8
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. # *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \ FILE_PATTERNS = *.c \
*.cc \ *.cc \
@ -928,7 +930,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to # Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/* # exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = EXCLUDE_PATTERNS = */test/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the # (namespaces, classes, functions, etc.) that should be excluded from the
@ -1265,9 +1267,9 @@ HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that # documentation will contain a main index with vertical navigation menus that
# are dynamically created via Javascript. If disabled, the navigation index will # are dynamically created via JavaScript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML # consists of multiple levels of tabs that are statically embedded in every HTML
# page. Disable this option to support browsers that do not have Javascript, # page. Disable this option to support browsers that do not have JavaScript,
# like the Qt help browser. # like the Qt help browser.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
@ -1555,8 +1557,14 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# https://www.mathjax.org) which uses client side Javascript for the rendering # https://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When # installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path # enabled you may also need to install MathJax separately and configure the path
@ -1626,7 +1634,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = YES SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There # implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH # are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and # setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing

View File

@ -30,7 +30,7 @@ Development is done with the following library versions:
| Cairographics | GLib2 | GTK3 | | Cairographics | GLib2 | GTK3 |
| ------------- | ---------- | --------- | | ------------- | ---------- | --------- |
| 1.17.3 | 2.60.6-1 | 3.24.10-1 | | 1.17.2 | 2.64.2 | 3.24.18 |
@section comp-instr Compilation Instructions @section comp-instr Compilation Instructions
@subsection linux-build General Linux Build Instruction @subsection linux-build General Linux Build Instruction
@ -47,7 +47,7 @@ Once cmake has finished, type
make make
@endcode @endcode
to build the program and to build the program and
@code @code
make documentation make documentation
@endcode @endcode
@ -59,7 +59,7 @@ The subfolder 'AUR' contains a PKGBUILD file to build an Archlinux/Pacman packag
@subsection comp-warnings Compiler Warnings @subsection comp-warnings Compiler Warnings
The compiler will throw the following warnings. Compiled with GCC 8.2.1. The compiler will throw the following warnings. Compiled with GCC 9.3.0.
| Warning | Assessment | | Warning | Assessment |
| ------- | ---------- | | ------- | ---------- |

View File

@ -5,7 +5,7 @@
The version number of this application consists of a given version in the format of 'v1.0'. The version number of this application consists of a given version in the format of 'v1.0'.
Where the first number indicates a major release and the second number indicates minor changes. Where the first number indicates a major release and the second number indicates minor changes.
Versions, including release candidates and path-levels, are tagged in git. Versions, including release candidates and patch-levels, are tagged in git.
@subsection rc Release Candidates @subsection rc Release Candidates
Release candidates are software versions that seem stable and functional to become a new version but testing is not fully finished. These versions are marked with an '-rcX', where X is the number of the release candidate. Release candidates are software versions that seem stable and functional to become a new version but testing is not fully finished. These versions are marked with an '-rcX', where X is the number of the release candidate.

View File

@ -37,6 +37,7 @@
#include <gds-render/layer/layer-selector.h> #include <gds-render/layer/layer-selector.h>
#include <gds-render/widgets/activity-bar.h> #include <gds-render/widgets/activity-bar.h>
#include <gds-render/cell-selector/lib-cell-renderer.h> #include <gds-render/cell-selector/lib-cell-renderer.h>
#include <gds-render/cell-selector/cell-statistics-renderer.h>
#include <gds-render/output-renderers/latex-renderer.h> #include <gds-render/output-renderers/latex-renderer.h>
#include <gds-render/output-renderers/cairo-renderer.h> #include <gds-render/output-renderers/cairo-renderer.h>
#include <gds-render/widgets/conv-settings-dialog.h> #include <gds-render/widgets/conv-settings-dialog.h>
@ -48,6 +49,7 @@ enum cell_store_columns {
CELL_SEL_LIBRARY = 0, CELL_SEL_LIBRARY = 0,
CELL_SEL_CELL, CELL_SEL_CELL,
CELL_SEL_CELL_ERROR_STATE, /**< Used for cell color and selectability */ CELL_SEL_CELL_ERROR_STATE, /**< Used for cell color and selectability */
CELL_SEL_STAT,
CELL_SEL_COLUMN_COUNT /**< @brief Not a column. Used to determine count of columns */ CELL_SEL_COLUMN_COUNT /**< @brief Not a column. Used to determine count of columns */
}; };
@ -219,10 +221,11 @@ int gds_render_gui_setup_cell_selector(GdsRenderGui *self)
{ {
GtkCellRenderer *render_cell; GtkCellRenderer *render_cell;
GtkCellRenderer *render_lib; GtkCellRenderer *render_lib;
GtkCellRenderer *render_vertex_count;
GtkTreeViewColumn *column; GtkTreeViewColumn *column;
self->cell_tree_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER, self->cell_tree_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER,
G_TYPE_POINTER, G_TYPE_UINT); G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_POINTER);
/* Searching */ /* Searching */
self->cell_filter = GTK_TREE_MODEL_FILTER( self->cell_filter = GTK_TREE_MODEL_FILTER(
@ -238,6 +241,7 @@ int gds_render_gui_setup_cell_selector(GdsRenderGui *self)
render_cell = lib_cell_renderer_new(); render_cell = lib_cell_renderer_new();
render_lib = lib_cell_renderer_new(); render_lib = lib_cell_renderer_new();
render_vertex_count = cell_statistics_renderer_new();
column = gtk_tree_view_column_new_with_attributes(_("Library"), render_lib, "gds-lib", CELL_SEL_LIBRARY, NULL); column = gtk_tree_view_column_new_with_attributes(_("Library"), render_lib, "gds-lib", CELL_SEL_LIBRARY, NULL);
gtk_tree_view_append_column(self->cell_tree_view, column); gtk_tree_view_append_column(self->cell_tree_view, column);
@ -246,6 +250,10 @@ int gds_render_gui_setup_cell_selector(GdsRenderGui *self)
"error-level", CELL_SEL_CELL_ERROR_STATE, NULL); "error-level", CELL_SEL_CELL_ERROR_STATE, NULL);
gtk_tree_view_append_column(self->cell_tree_view, column); gtk_tree_view_append_column(self->cell_tree_view, column);
column = gtk_tree_view_column_new_with_attributes(_("Vertex | GFX Count"), render_vertex_count, "cell-stat", CELL_SEL_STAT,
NULL);
gtk_tree_view_append_column(self->cell_tree_view, column);
/* Callback for selection /* Callback for selection
* This prevents selecting a library * This prevents selecting a library
*/ */
@ -255,6 +263,10 @@ int gds_render_gui_setup_cell_selector(GdsRenderGui *self)
return 0; return 0;
} }
const struct gds_cell_statistics cc = {
.vertex_count = 12,
};
/** /**
* @brief Callback function of Load GDS button * @brief Callback function of Load GDS button
* @param button * @param button
@ -278,6 +290,10 @@ static void on_load_gds(gpointer button, gpointer user)
char *filename; char *filename;
unsigned int cell_error_level; unsigned int cell_error_level;
const struct gds_library_parsing_opts gds_parsing_options = {
.simplified_polygons = 1,
};
self = RENDERER_GUI(user); self = RENDERER_GUI(user);
if (!self) if (!self)
return; return;
@ -307,7 +323,7 @@ static void on_load_gds(gpointer button, gpointer user)
clear_lib_list(&self->gds_libraries); clear_lib_list(&self->gds_libraries);
/* Parse new GDSII file */ /* Parse new GDSII file */
gds_result = parse_gds_from_file(filename, &self->gds_libraries); gds_result = parse_gds_from_file(filename, &self->gds_libraries, &gds_parsing_options);
/* Delete file name afterwards */ /* Delete file name afterwards */
g_free(filename); g_free(filename);
@ -349,6 +365,7 @@ static void on_load_gds(gpointer button, gpointer user)
CELL_SEL_CELL, gds_c, CELL_SEL_CELL, gds_c,
CELL_SEL_CELL_ERROR_STATE, cell_error_level, CELL_SEL_CELL_ERROR_STATE, cell_error_level,
CELL_SEL_LIBRARY, gds_c->parent_library, CELL_SEL_LIBRARY, gds_c->parent_library,
CELL_SEL_STAT, &gds_c->stats,
-1); -1);
} /* for cells */ } /* for cells */
} /* for libraries */ } /* for libraries */
@ -691,19 +708,13 @@ static void on_select_all_layers_clicked(GtkWidget *button, gpointer user_data)
layer_selector_select_all_layers(gui->layer_selector, TRUE); layer_selector_select_all_layers(gui->layer_selector, TRUE);
} }
static void auto_naming_clicked(GtkWidget *button, gpointer user_data) static gboolean auto_naming_ask_for_override(GdsRenderGui *gui)
{ {
GdsRenderGui *gui;
GtkDialog *dialog; GtkDialog *dialog;
gboolean overwrite; gint dialog_result;
int dialog_result; gboolean overwrite = FALSE;
(void)button;
gui = RENDERER_GUI(user_data); g_return_val_if_fail(RENDERER_IS_GUI(gui), FALSE);
/* Don't do anything if the selector is empty. */
if (!layer_selector_contains_elements(gui->layer_selector))
return;
/* Ask for overwrite */ /* Ask for overwrite */
dialog = GTK_DIALOG(gtk_message_dialog_new(gui->main_window, GTK_DIALOG_USE_HEADER_BAR, GTK_MESSAGE_QUESTION, dialog = GTK_DIALOG(gtk_message_dialog_new(gui->main_window, GTK_DIALOG_USE_HEADER_BAR, GTK_MESSAGE_QUESTION,
@ -720,6 +731,25 @@ static void auto_naming_clicked(GtkWidget *button, gpointer user_data)
} }
gtk_widget_destroy(GTK_WIDGET(dialog)); gtk_widget_destroy(GTK_WIDGET(dialog));
return overwrite;
}
static void auto_naming_clicked(GtkWidget *button, gpointer user_data)
{
GdsRenderGui *gui;
gboolean overwrite = FALSE;
(void)button;
gui = RENDERER_GUI(user_data);
/* Don't do anything if the selector is empty. */
if (!layer_selector_contains_elements(gui->layer_selector))
return;
/* Ask, if names shall be overwritten, if they are not empty */
if (layer_selector_num_of_named_elements(gui->layer_selector) > 0)
overwrite = auto_naming_ask_for_override(gui);
layer_selector_auto_name_layers(gui->layer_selector, overwrite); layer_selector_auto_name_layers(gui->layer_selector, overwrite);
} }

View File

@ -43,6 +43,7 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <gds-render/gds-utils/gds-parser.h> #include <gds-render/gds-utils/gds-parser.h>
#include <gds-render/gds-utils/gds-statistics.h>
/** /**
* @brief Default units assumed for library. * @brief Default units assumed for library.
@ -50,8 +51,8 @@
*/ */
#define GDS_DEFAULT_UNITS (10E-9) #define GDS_DEFAULT_UNITS (10E-9)
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS error*/ #define GDS_ERROR(fmt, ...) fprintf(stderr, "[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 */ #define GDS_WARN(fmt, ...) fprintf(stderr, "[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */
#if GDS_PRINT_DEBUG_INFOS #if GDS_PRINT_DEBUG_INFOS
/**< @brief standard printf. But can be disabled in code. */ /**< @brief standard printf. But can be disabled in code. */
@ -80,6 +81,7 @@ enum gds_record {
STRANS = 0x1A01, STRANS = 0x1A01,
BOX = 0x2D00, BOX = 0x2D00,
LAYER = 0x0D02, LAYER = 0x0D02,
DATATYPE = 0x0E02,
WIDTH = 0x0F03, WIDTH = 0x0F03,
PATHTYPE = 0x2102, PATHTYPE = 0x2102,
COLROW = 0x1302, COLROW = 0x1302,
@ -265,7 +267,8 @@ static uint16_t gds_convert_unsigned_int16(const char *data)
* @param library_ptr Return of newly created library. * @param library_ptr Return of newly created library.
* @return Newly created list pointer * @return Newly created list pointer
*/ */
static GList *append_library(GList *curr_list, struct gds_library **library_ptr) static GList *append_library(GList *curr_list, const struct gds_library_parsing_opts *opts,
struct gds_library **library_ptr)
{ {
struct gds_library *lib; struct gds_library *lib;
@ -275,8 +278,15 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
lib->name[0] = 0; lib->name[0] = 0;
lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten
lib->cell_names = NULL; lib->cell_names = NULL;
} else /* Copy the settings into the library */
memcpy(&lib->parsing_opts, opts, sizeof(struct gds_library_parsing_opts));
lib->stats.cell_count = 0;
lib->stats.gfx_count = 0;
lib->stats.reference_count = 0;
lib->stats.vertex_count = 0;
} else {
return NULL; return NULL;
}
if (library_ptr) if (library_ptr)
*library_ptr = lib; *library_ptr = lib;
@ -352,6 +362,11 @@ static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
cell->parent_library = NULL; cell->parent_library = NULL;
cell->checks.unresolved_child_count = GDS_CELL_CHECK_NOT_RUN; cell->checks.unresolved_child_count = GDS_CELL_CHECK_NOT_RUN;
cell->checks.affected_by_reference_loop = GDS_CELL_CHECK_NOT_RUN; cell->checks.affected_by_reference_loop = GDS_CELL_CHECK_NOT_RUN;
cell->stats.reference_count = 0;
cell->stats.total_vertex_count = 0;
cell->stats.total_gfx_count = 0;
cell->stats.gfx_count = 0;
cell->stats.vertex_count = 0;
} else } else
return NULL; return NULL;
/* return cell */ /* return cell */
@ -487,20 +502,102 @@ static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
} }
/** /**
* @brief Scans cell references inside cell * @brief Simplify graphics objects
This function searches all the references in \p gcell and updates the gds_cell_instance::cell_ref field in each instance * @param graphics gfx struct
* @param user_data GDS library
*/
static void simplify_graphics(gpointer graphics, gpointer user_data)
{
struct gds_graphics *gfx;
const struct gds_point *first_vertex = NULL;
const struct gds_point *prev_vertex = NULL;
const struct gds_point *current_vertex;
GList *vertex_iter;
GList *next_iter;
(void)user_data;
size_t processed_count = 0U;
size_t removed_count = 0U;
gfx = (struct gds_graphics *)graphics;
if (gfx->gfx_type == GRAPHIC_POLYGON) {
GDS_INF("\t\t\tPolygon found\n");
/* Loop over all vertices */
for (vertex_iter = gfx->vertices; vertex_iter;) {
current_vertex = (const struct gds_point *)vertex_iter->data;
next_iter = g_list_next(vertex_iter);
processed_count++;
if (vertex_iter == gfx->vertices) {
/* This is the first vertex */
first_vertex = current_vertex;
prev_vertex = NULL;
}
if (prev_vertex) {
if (current_vertex->x == prev_vertex->x && current_vertex->y == prev_vertex->y) {
/* Vertex is the same as the previous one */
GDS_INF("\t\t\t\tDuplicate vertex (%d,%d). Removing...\n",
current_vertex->x, current_vertex->y);
/* Delete the current one from the list */
gfx->vertices = g_list_remove_link(gfx->vertices, vertex_iter);
/* Free the data */
if (vertex_iter->data)
free(vertex_iter->data);
vertex_iter->data = NULL;
g_list_free_1(vertex_iter);
removed_count++;
} else if (!g_list_next(vertex_iter)) {
/* This is the last element in the list */
if (current_vertex->x == first_vertex->x &&
current_vertex->y == first_vertex->y) {
GDS_INF("\t\t\t\tLast vertex is identical to first vertex (%d,%d). Removing\n",
current_vertex->x, current_vertex->y);
gfx->vertices = g_list_remove_link(gfx->vertices, vertex_iter);
if (vertex_iter->data)
free(vertex_iter->data);
g_list_free_1(vertex_iter);
removed_count++;
} else {
GDS_WARN("First vertex is not coincident with first vertex, although the GDS file format specifies this. However, this is not a problem.");
}
}
}
vertex_iter = next_iter;
prev_vertex = current_vertex;
}
GDS_INF("\t\t\tProcessed %zu vertices. %zu removed.\n", processed_count, removed_count);
}
}
/**
* @brief Scans cell and resolves references and simplifies polygons
* 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 gcell pointer cast of #gds_cell *
* @param library Library where the cell references are searched in * @param library Library where the cell references are searched in
*/ */
static void scan_cell_reference_dependencies(gpointer gcell, gpointer library) static void scan_cell_references_and_polygons(gpointer gcell, gpointer library)
{ {
struct gds_cell *cell = (struct gds_cell *)gcell; struct gds_cell *cell = (struct gds_cell *)gcell;
struct gds_library *my_lib = (struct gds_library *)library;
int simplify_polygons;
simplify_polygons = my_lib->parsing_opts.simplified_polygons;
GDS_INF("\tScanning cell: %s\n", cell->name); GDS_INF("\tScanning cell: %s\n", cell->name);
GDS_INF("\t\tCell references\n");
/* Scan all library references */ /* Scan all library references */
g_list_foreach(cell->child_cells, parse_reference_list, library); g_list_foreach(cell->child_cells, parse_reference_list, library);
GDS_INF("\t\tSimplifying Polygons%s\n", simplify_polygons ? "" : ": skipped");
if (simplify_polygons) {
g_list_foreach(cell->graphic_objs, simplify_graphics, library);
}
} }
/** /**
@ -516,7 +613,16 @@ static void scan_library_references(gpointer library_list_item, gpointer user)
(void)user; (void)user;
GDS_INF("Scanning Library: %s\n", lib->name); GDS_INF("Scanning Library: %s\n", lib->name);
g_list_foreach(lib->cells, scan_cell_reference_dependencies, lib); g_list_foreach(lib->cells, scan_cell_references_and_polygons, lib);
}
static void calc_library_stats(gpointer library_list_item, gpointer user)
{
struct gds_library *lib = (struct gds_library *)library_list_item;
(void)user;
GDS_INF("Calculating stats for Library: %s\n", lib->name);
gds_statistics_calc_cummulative_counts_in_lib(lib);
} }
/** /**
@ -600,6 +706,7 @@ static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gd
for (row = 0; row < aref->rows; row++) { for (row = 0; row < aref->rows; row++) {
/* Create new instance for this row/column and configure data */ /* Create new instance for this row/column and configure data */
container_cell->child_cells = append_cell_ref(container_cell->child_cells, &sref_inst); container_cell->child_cells = append_cell_ref(container_cell->child_cells, &sref_inst);
container_cell->stats.reference_count++;
if (!sref_inst) { if (!sref_inst) {
GDS_ERROR("Appending cell ref failed!"); GDS_ERROR("Appending cell ref failed!");
continue; continue;
@ -616,7 +723,8 @@ static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gd
GDS_INF("Converted AREF to SREFs\n"); GDS_INF("Converted AREF to SREFs\n");
} }
int parse_gds_from_file(const char *filename, GList **library_list) int parse_gds_from_file(const char *filename, GList **library_list,
const struct gds_library_parsing_opts *parsing_options)
{ {
char *workbuff; char *workbuff;
int read; int read;
@ -696,7 +804,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
/* if begin: Allocate structures */ /* if begin: Allocate structures */
switch (rec_type) { switch (rec_type) {
case BGNLIB: case BGNLIB:
lib_list = append_library(lib_list, &current_lib); lib_list = append_library(lib_list, parsing_options, &current_lib);
if (lib_list == NULL) { if (lib_list == NULL) {
GDS_ERROR("Allocating memory failed"); GDS_ERROR("Allocating memory failed");
run = -3; run = -3;
@ -770,7 +878,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
run = -4; run = -4;
break; break;
} }
GDS_INF("\tEntering boundary/Box\n"); GDS_INF("\tEntering boundary of type %s\n", rec_type==BOUNDARY ? "polygon" : "box");
break; break;
case SREF: case SREF:
if (current_cell == NULL) { if (current_cell == NULL) {
@ -780,6 +888,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
} }
current_cell->child_cells = append_cell_ref(current_cell->child_cells, current_cell->child_cells = append_cell_ref(current_cell->child_cells,
&current_s_reference); &current_s_reference);
current_cell->stats.reference_count++;
if (current_cell->child_cells == NULL) { if (current_cell->child_cells == NULL) {
GDS_ERROR("Memory allocation failed"); GDS_ERROR("Memory allocation failed");
run = -4; run = -4;
@ -805,8 +914,13 @@ int parse_gds_from_file(const char *filename, GList **library_list)
break; break;
case ENDEL: case ENDEL:
if (current_graphics != NULL) { if (current_graphics != NULL) {
GDS_INF("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary" : "path")); GDS_INF("\tLeaving %s\n", (current_graphics->gfx_type == GRAPHIC_POLYGON ? "boundary"
: (current_graphics->gfx_type == GRAPHIC_PATH ? "path"
: "box")));
current_graphics = NULL; current_graphics = NULL;
if (current_cell) {
current_cell->stats.gfx_count++;
}
} }
if (current_s_reference != NULL) { if (current_s_reference != NULL) {
GDS_INF("\tLeaving Reference\n"); GDS_INF("\tLeaving Reference\n");
@ -824,11 +938,11 @@ int parse_gds_from_file(const char *filename, GList **library_list)
} else if (current_s_reference) { } else if (current_s_reference) {
if (rec_data_length != 8) { if (rec_data_length != 8) {
GDS_WARN("Instance has weird coordinates. Rendered output might be screwed!"); GDS_WARN("Instance has weird coordinates. Rendered output might be wrong!");
} }
} else if (current_a_reference) { } else if (current_a_reference) {
if (rec_data_length != (3*(4+4))) if (rec_data_length != (3*(4+4)))
GDS_WARN("Array instance has weird coordinates. Rendered output might be screwed!"); GDS_WARN("Array instance has weird coordinates. Rendered output might be wrong!");
} }
break; break;
case AREF: case AREF:
@ -867,6 +981,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
case LIBNAME: case LIBNAME:
case SNAME: case SNAME:
case LAYER: case LAYER:
case DATATYPE:
case STRNAME: case STRNAME:
break; break;
default: default:
@ -955,7 +1070,9 @@ int parse_gds_from_file(const char *filename, GList **library_list)
current_graphics->vertices = current_graphics->vertices =
append_vertex(current_graphics->vertices, x, y); append_vertex(current_graphics->vertices, x, y);
GDS_INF("\t\tSet coordinate: %d/%d\n", x, y); GDS_INF("\t\tSet coordinate: %d/%d\n", x, y);
if (current_cell) {
current_cell->stats.vertex_count++;
}
} }
} else if (current_a_reference) { } else if (current_a_reference) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
@ -1003,6 +1120,16 @@ int parse_gds_from_file(const char *filename, GList **library_list)
} }
GDS_INF("\t\tAdded layer %d\n", (int)current_graphics->layer); GDS_INF("\t\tAdded layer %d\n", (int)current_graphics->layer);
break; break;
case DATATYPE:
if (!current_graphics) {
GDS_WARN("Datatype has to be defined inside graphics object. Probably unknown object. Implement it yourself!");
break;
}
current_graphics->datatype = gds_convert_signed_int16(workbuff);
if (current_graphics->datatype < 0)
GDS_WARN("Datatype negative!");
GDS_INF("\t\tAdded datatype %d\n", (int)current_graphics->datatype);
break;
case MAG: case MAG:
if (rec_data_length != 8) { if (rec_data_length != 8) {
GDS_WARN("Magnification is not an 8 byte real. Results may be wrong"); GDS_WARN("Magnification is not an 8 byte real. Results may be wrong");
@ -1061,8 +1188,13 @@ int parse_gds_from_file(const char *filename, GList **library_list)
if (!run) { if (!run) {
/* Iterate and find references to cells */ /* Iterate and find references to cells */
g_list_foreach(lib_list, scan_library_references, NULL); g_list_foreach(lib_list, scan_library_references, NULL);
/* Calculate lib stats and cummulative total counts */
g_list_foreach(lib_list, calc_library_stats, NULL);
} }
*library_list = lib_list; *library_list = lib_list;
free(workbuff); free(workbuff);

View File

@ -0,0 +1,93 @@
/*
* 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-statistics.c
* @brief Statistics of GDS files
* @author Mario Hüttel <mario.huettel@gmx.net>
*
*/
#include <gds-render/gds-utils/gds-statistics.h>
#include <stdio.h>
/**
* @addtogroup GDS-Utilities
* @{
*/
#define MAX_RECURSION_DEPTH (1024)
static void calculate_vertex_gfx_count_cell(struct gds_cell *cell, unsigned int recursion_depth)
{
GList *cell_iter;
struct gds_cell_instance *cell_ref;
struct gds_cell *sub_cell;
g_return_if_fail(cell);
/* Check if cell has already been calculated */
if (cell->stats.total_gfx_count && cell->stats.total_vertex_count) {
/* Return. This cell and all of its subcells have been calculated */
return;
}
/* Update with own vertex / GFX count */
cell->stats.total_vertex_count = cell->stats.vertex_count;
cell->stats.total_gfx_count = cell->stats.gfx_count;
/* Do not analyze further, if maximum recursion depth is reached */
if (!recursion_depth)
return;
for (cell_iter = cell->child_cells; cell_iter; cell_iter = g_list_next(cell_iter)) {
/* Scan all subcells recursively, if there are any */
cell_ref = (struct gds_cell_instance *)cell_iter->data;
sub_cell = (struct gds_cell *)cell_ref->cell_ref;
calculate_vertex_gfx_count_cell(sub_cell, recursion_depth - 1);
/* Increment count */
cell->stats.total_vertex_count += sub_cell->stats.total_vertex_count;
cell->stats.total_gfx_count += sub_cell->stats.total_vertex_count;
}
}
void gds_statistics_calc_cummulative_counts_in_lib(struct gds_library *lib)
{
GList *cell_iter;
struct gds_cell *cell;
g_return_if_fail(lib);
for (cell_iter = lib->cells; cell_iter; cell_iter = g_list_next(cell_iter)) {
cell = (struct gds_cell *)cell_iter->data;
calculate_vertex_gfx_count_cell(cell, MAX_RECURSION_DEPTH);
lib->stats.vertex_count += cell->stats.vertex_count;
lib->stats.cell_count++;
lib->stats.gfx_count += cell->stats.gfx_count;
lib->stats.reference_count += cell->stats.reference_count;
}
}
/** @} */

View File

@ -37,7 +37,7 @@
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */ #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a)) #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) void bounding_box_calculate_from_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; double xmin = DBL_MAX, xmax = -DBL_MAX, ymin = DBL_MAX, ymax = -DBL_MAX;
struct vector_2d temp_vec; struct vector_2d temp_vec;
@ -68,7 +68,7 @@ void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t
box->vectors.upper_right.y = ymax; box->vectors.upper_right.y = ymax;
} }
void bounding_box_update_box(union bounding_box *destination, union bounding_box *update) void bounding_box_update_with_box(union bounding_box *destination, union bounding_box *update)
{ {
if (!destination || !update) if (!destination || !update)
return; return;
@ -151,8 +151,6 @@ void bounding_box_update_with_path(GList *vertices, double thickness,
GList *vertex_iterator; GList *vertex_iterator;
struct vector_2d pt; struct vector_2d pt;
/* printf("Warning! Function %s not yet implemented correctly!\n", __func__); */
if (!vertices || !box) if (!vertices || !box)
return; return;
@ -173,7 +171,7 @@ void bounding_box_update_with_path(GList *vertices, double thickness,
} }
} }
void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt) void bounding_box_update_with_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt)
{ {
struct vector_2d point; struct vector_2d point;
@ -224,7 +222,7 @@ void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_a
vector_2d_rotate(&input_points[i], rotation_deg * M_PI / 180.0); vector_2d_rotate(&input_points[i], rotation_deg * M_PI / 180.0);
vector_2d_scale(&input_points[i], scale); vector_2d_scale(&input_points[i], scale);
bounding_box_update_point(box, NULL, &input_points[i]); bounding_box_update_with_point(box, NULL, &input_points[i]);
} }
} }

View File

@ -53,7 +53,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf
case GRAPHIC_BOX: case GRAPHIC_BOX:
/* Expected fallthrough */ /* Expected fallthrough */
case GRAPHIC_POLYGON: case GRAPHIC_POLYGON:
bounding_box_calculate_polygon(gfx->vertices, bounding_box_calculate_from_polygon(gfx->vertices,
(conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector, (conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector,
&current_box); &current_box);
break; break;
@ -74,7 +74,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf
} }
/* Update box with results */ /* Update box with results */
bounding_box_update_box(box, &current_box); bounding_box_update_with_box(box, &current_box);
} }
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell) void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell)
@ -113,7 +113,7 @@ void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell)
temp_box.vectors.upper_right.y += sub_cell->origin.y; temp_box.vectors.upper_right.y += sub_cell->origin.y;
/* update the parent's box */ /* update the parent's box */
bounding_box_update_box(box, &temp_box); bounding_box_update_with_box(box, &temp_box);
} }
} }

View File

@ -65,7 +65,7 @@ void vector_2d_rotate(struct vector_2d *vec, double angle)
sin_val = sin(angle); sin_val = sin(angle);
cos_val = cos(angle); cos_val = cos(angle);
vector_2d_copy(&temp, vec); (void)vector_2d_copy(&temp, vec);
/* Apply rotation matrix */ /* Apply rotation matrix */
vec->x = (cos_val * temp.x) - (sin_val * temp.y); vec->x = (cos_val * temp.x) - (sin_val * temp.y);

View File

@ -0,0 +1,56 @@
/*
* GDSII-Converter
* Copyright (C) 2022 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-statistics-renderer.h
* @brief Header file for the CellStatisticsRenderer GObject Class
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup CellStatisticsRenderer
* @{
*/
#ifndef _CELL_STATISTICS_RENDERER_H_
#define _CELL_STATISTICS_RENDERER_H_
#include <gtk/gtk.h>
#include <gds-render/gds-utils/gds-statistics.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(CellStatisticsRenderer, cell_statistics_renderer, GDS_RENDER, CELL_STAT_RENDERER, GtkCellRendererText)
#define TYPE_GDS_RENDER_CELL_STAT_RENDERER (cell_statistics_renderer_get_type())
typedef struct _CellStatisticsRenderer {
GtkCellRendererText super;
} CellStatisticsRenderer;
/**
* @brief New Cell statistics renderer
* @return GObject
*/
GtkCellRenderer *cell_statistics_renderer_new(void);
G_END_DECLS
#endif /* _CELL_STATISTICS_RENDERER_H_ */
/** @} */

View File

@ -71,6 +71,14 @@ int command_line_convert_gds(const char *gds_name,
gboolean tex_layers, gboolean tex_layers,
double scale); double scale);
/**
* @brief Analyze the given GDS file
* @param format Output format of the analysis result
* @param gds_name GDS file name
* @return 0 if successful
*/
int command_line_analyze_lib(const char *format, const char *gds_name);
#endif /* _COMMAND_LINE_H_ */ #endif /* _COMMAND_LINE_H_ */
/** @} */ /** @} */

View File

@ -48,9 +48,11 @@
* *
* @param[in] filename Path to the GDS file * @param[in] filename Path to the GDS file
* @param[in,out] library_array GList Pointer. * @param[in,out] library_array GList Pointer.
* @param[in] parsing_options Parsing options.
* @return 0 if successful * @return 0 if successful
*/ */
int parse_gds_from_file(const char *filename, GList **library_array); int parse_gds_from_file(const char *filename, GList **library_array,
const struct gds_library_parsing_opts *parsing_options);
/** /**
* @brief Deletes all libraries including cells, references etc. * @brief Deletes all libraries including cells, references etc.

View File

@ -0,0 +1,42 @@
/*
* 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-parser.h
* @brief Header file for the GDS statistics
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#ifndef _GDS_STATISTICS_H_
#define _GDS_STATISTICS_H_
/**
* @addtogroup GDS-Utilities
* @{
*/
#include <glib.h>
#include <gds-render/gds-utils/gds-types.h>
void gds_statistics_calc_cummulative_counts_in_lib(struct gds_library *lib);
/** @} */
#endif /* _GDS_STATISTICS_H_ */

View File

@ -65,6 +65,22 @@ struct gds_point {
int y; int y;
}; };
struct gds_cell_statistics {
size_t gfx_count;
size_t vertex_count;
size_t total_vertex_count;
size_t total_gfx_count;
size_t reference_count;
};
struct gds_lib_statistics {
size_t gfx_count;
size_t vertex_count;
size_t reference_count;
size_t cell_count;
};
/** /**
* @brief Stores the result of the cell checks. * @brief Stores the result of the cell checks.
*/ */
@ -101,7 +117,7 @@ struct gds_graphics {
enum path_type path_render_type; /**< @brief Line cap */ enum path_type path_render_type; /**< @brief Line cap */
int width_absolute; /**< @brief Width. Not used for objects other than paths */ int width_absolute; /**< @brief Width. Not used for objects other than paths */
int16_t layer; /**< @brief Layer the graphic object is on */ int16_t layer; /**< @brief Layer the graphic object is on */
uint16_t datatype; int16_t datatype; /**< @brief Data type of graphic object */
}; };
/** /**
@ -127,6 +143,14 @@ struct gds_cell {
GList *graphic_objs; /**< @brief List of #gds_graphics */ GList *graphic_objs; /**< @brief List of #gds_graphics */
struct gds_library *parent_library; /**< @brief Pointer to parent library */ struct gds_library *parent_library; /**< @brief Pointer to parent library */
struct gds_cell_checks checks; /**< @brief Checking results */ struct gds_cell_checks checks; /**< @brief Checking results */
struct gds_cell_statistics stats; /**< @brief Optional statistic info */
};
/**
* @brief Options, hwo this liobrary was parsed.
*/
struct gds_library_parsing_opts {
int simplified_polygons; /**< @brief Polygons have been simplified. Coincident end point removed. */
}; };
/** /**
@ -136,11 +160,14 @@ struct gds_library {
char name[CELL_NAME_MAX]; char name[CELL_NAME_MAX];
struct gds_time_field mod_time; struct gds_time_field mod_time;
struct gds_time_field access_time; struct gds_time_field access_time;
struct gds_library_parsing_opts parsing_opts;
double unit_in_meters; /**< Length of a database unit in meters */ 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 *cells; /**< List of #gds_cell that contains all cells in this library*/
GList *cell_names /**< List of strings that contains all cell names */; GList *cell_names /**< List of strings that contains all cell names */;
struct gds_lib_statistics stats;
}; };
/** @} */ /** @} */
#endif /* __GDS_TYPES_H__ */ #endif /* __GDS_TYPES_H__ */

View File

@ -35,15 +35,44 @@
#include <gds-render/geometric/vector-operations.h> #include <gds-render/geometric/vector-operations.h>
#include <stdbool.h> #include <stdbool.h>
/**
* @brief Union describing a bounding box
*
* Two ways of accessing a bounding box are possible.
*
* Either, use the "named" vectors struct to specifically access the points
* @code
* lower_left = box.vectors.lower_left;
* upper right = box.vectors.upper_right;
* @endcode
*
* or use the iterable vector array:
* @code
* for (i = 0; i < 2; i++)
* box.vector_array[i] = points[i];
* @endcode
*/
union bounding_box { union bounding_box {
/** Coordinate System is (y up | x right) */ /**
* @brief Location vectors of upper right and lower left bounding box points
* @note Coordinate System is (y up | x right)
*/
struct _vectors { struct _vectors {
/** @brief Lower left point of the bounding box */
struct vector_2d lower_left; struct vector_2d lower_left;
/** @brief Upper right point of the bounding box */
struct vector_2d upper_right; struct vector_2d upper_right;
} vectors; } vectors;
/**
* @brief Array of vectors representing a bounding box
* @note This is more convenient for iterating
*/
struct vector_2d vector_array[2]; struct vector_2d vector_array[2];
}; };
/*
* @brief Pointer to a function that takes any pointer and converts this object to a vector_2d struct
*/
typedef void (*conv_generic_to_vector_2d_t)(void *, struct vector_2d *); typedef void (*conv_generic_to_vector_2d_t)(void *, struct vector_2d *);
/** /**
@ -52,14 +81,14 @@ typedef void (*conv_generic_to_vector_2d_t)(void *, struct vector_2d *);
* @param conv_func Conversion function to convert vertices to vector_2d structs. * @param conv_func Conversion function to convert vertices to vector_2d structs.
* @param box Box to write to. This box is not updated! All previous data is discarded * @param box Box to write to. This box is not updated! All previous data is discarded
*/ */
void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box); void bounding_box_calculate_from_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);
/** /**
* @brief Update an exisitng bounding box with another one. * @brief Update an exisitng bounding box with another one.
* @param destination Target box to update * @param destination Target box to update
* @param update Box to update the target with * @param update Box to update the target with
*/ */
void bounding_box_update_box(union bounding_box *destination, union bounding_box *update); void bounding_box_update_with_box(union bounding_box *destination, union bounding_box *update);
/** /**
* @brief Prepare an empty bounding box. * @brief Prepare an empty bounding box.
@ -76,7 +105,7 @@ void bounding_box_prepare_empty(union bounding_box *box);
* @param conv_func Conversion function to convert \p pt to a vector_2d. May be NULL * @param conv_func Conversion function to convert \p pt to a vector_2d. May be NULL
* @param pt Point to update bounding box with * @param pt Point to update bounding box with
*/ */
void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt); void bounding_box_update_with_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt);
/** /**
* @brief Return all four corner points of a bounding box * @brief Return all four corner points of a bounding box
@ -102,7 +131,7 @@ void bounding_box_get_all_points(struct vector_2d *points, union bounding_box *b
* @param rotation_deg Rotation of bounding box around the origin in degrees (counterclockwise) * @param rotation_deg Rotation of bounding box around the origin in degrees (counterclockwise)
* @param flip_at_x Flip the boundig box on the x axis before rotating. * @param flip_at_x Flip the boundig box on the x axis before rotating.
* @param box Bounding box the operations should be applied to. * @param box Bounding box the operations should be applied to.
* @note Keep in mind, that this bounding boxy is actually the bounding box of the rotated boundig box and not the object itself. * @note Keep in mind, that this bounding box is actually the bounding box of the rotated boundig box and not the object itself.
* It might be too big. * It might be too big.
*/ */
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box); void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box);
@ -113,6 +142,9 @@ void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_a
* @param thickness Thisckness of the path * @param thickness Thisckness of the path
* @param conv_func Conversion function for vertices to vector_2d structs * @param conv_func Conversion function for vertices to vector_2d structs
* @param box Bounding box to write results in. * @param box Bounding box to write results in.
* @warning This function is not yet implemented correctly. Miter points of paths are not taken into account.
* If a path is the outmost object of your cell _and_ it is not parallel to one of the coordinate axes,
* the calculated bounding box size might be off. In other cases it should be reasonable close to the real bounding box.
*/ */
void bounding_box_update_with_path(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box); void bounding_box_update_with_path(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);

View File

@ -35,10 +35,17 @@
#include <gds-render/gds-utils/gds-types.h> #include <gds-render/gds-utils/gds-types.h>
/** /**
* @brief calculate_cell_bounding_box Calculate bounding box of gds cell * @brief Calculate bounding box of a gds cell.
* @param box Resulting boundig box. Will be uüdated and not overwritten *
* This function updates a given bounding box with the dimensions of a
* gds_cell. Please note that the handling of path miter points is not complete yet.
* If a path object is the outmost object of your cell at any edge,
* the resulting bounding box might be the wrong size. The devistion from the real size
* is guaranteed to be within the width of the path object.
*
* @param box Resulting boundig box. Will be updated and not overwritten
* @param cell Toplevel cell * @param cell Toplevel cell
* @warning Path handling not yet implemented correctly. * @warning Handling of Path graphic objects not yet implemented correctly.
*/ */
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell); void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell);

View File

@ -130,6 +130,13 @@ void layer_selector_auto_name_layers(LayerSelector *layer_selector, gboolean ove
*/ */
gboolean layer_selector_contains_elements(LayerSelector *layer_selector); gboolean layer_selector_contains_elements(LayerSelector *layer_selector);
/**
* @brief Get number of layer elements that are named
* @param[in] layer_selector Layer selector
* @return Number of layers with a name != NULL or != ""
*/
size_t layer_selector_num_of_named_elements(LayerSelector *layer_selector);
G_END_DECLS G_END_DECLS
#endif /* __LAYER_SELECTOR_H__ */ #endif /* __LAYER_SELECTOR_H__ */

View File

@ -41,7 +41,7 @@ struct layer_info
{ {
int layer; /**< @brief Layer number */ int layer; /**< @brief Layer number */
char *name; /**< @brief Layer name. */ 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 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 */ GdkRGBA color; /**< @brief RGBA color used to render this layer */
int render; /**< @brief true: Render to output */ int render; /**< @brief true: Render to output */
}; };

View File

@ -38,7 +38,7 @@ G_DECLARE_FINAL_TYPE(CairoRenderer, cairo_renderer, GDS_RENDER, CAIRO_RENDERER,
#define GDS_RENDER_TYPE_CAIRO_RENDERER (cairo_renderer_get_type()) #define GDS_RENDER_TYPE_CAIRO_RENDERER (cairo_renderer_get_type())
#define MAX_LAYERS (300) /**< \brief Maximum layer count the output renderer can process. Typically GDS only specifies up to 255 layers.*/ #define MAX_LAYERS (5000) /**< \brief Maximum layer count the output renderer can process. Typically GDS only specifies up to 255 layers.*/
/** /**
* @brief Create new CairoRenderer for SVG output * @brief Create new CairoRenderer for SVG output

View File

@ -1,3 +1,22 @@
/*
* GDSII-Converter
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EXTERNAL_RENDERER_INTERFACES_H__ #ifndef __EXTERNAL_RENDERER_INTERFACES_H__
#define __EXTERNAL_RENDERER_INTERFACES_H__ #define __EXTERNAL_RENDERER_INTERFACES_H__

View File

@ -238,6 +238,7 @@ static void color_palette_dispose(GObject *gobj)
if (palette->color_array) { if (palette->color_array) {
palette->color_array_length = 0; palette->color_array_length = 0;
free(palette->color_array); free(palette->color_array);
palette->color_array = NULL;
} }
/* Chain up to parent class */ /* Chain up to parent class */

View File

@ -822,12 +822,10 @@ void layer_selector_auto_color_layers(LayerSelector *layer_selector, ColorPalett
unsigned int color_count; unsigned int color_count;
GdkRGBA color; GdkRGBA color;
if (GDS_RENDER_IS_COLOR_PALETTE(palette) == FALSE || LAYER_IS_SELECTOR(layer_selector) == FALSE) g_return_if_fail(GDS_RENDER_IS_COLOR_PALETTE(palette));
return; g_return_if_fail(LAYER_IS_SELECTOR(layer_selector));
if (global_alpha <= 0) g_return_if_fail(global_alpha > 0);
return; g_return_if_fail(GTK_IS_LIST_BOX(layer_selector->list_box));
if (GTK_IS_LIST_BOX(layer_selector->list_box) == FALSE)
return;
le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box)); le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
@ -898,4 +896,31 @@ gboolean layer_selector_contains_elements(LayerSelector *layer_selector)
return (layer_element_list ? TRUE : FALSE); return (layer_element_list ? TRUE : FALSE);
} }
size_t layer_selector_num_of_named_elements(LayerSelector *layer_selector)
{
GList *le_list;
GList *le_list_ptr;
LayerElement *le;
const char *layer_name;
size_t count = 0U;
g_return_val_if_fail(LAYER_IS_SELECTOR(layer_selector), 0U);
le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
for (le_list_ptr = le_list; le_list_ptr != NULL; le_list_ptr = g_list_next(le_list_ptr)) {
le = LAYER_ELEMENT(le_list_ptr->data);
if (!le)
continue;
layer_name = layer_element_get_name(le);
if (layer_name && *layer_name) {
/* Layer name is not empty. Count it */
count++;
}
}
return count;
}
/** @} */ /** @} */

15
main.c
View File

@ -262,6 +262,8 @@ int main(int argc, char **argv)
gchar *cellname = NULL; gchar *cellname = NULL;
gchar **renderer_args = NULL; gchar **renderer_args = NULL;
gboolean version = FALSE, pdf_standalone = FALSE, pdf_layers = FALSE; gboolean version = FALSE, pdf_standalone = FALSE, pdf_layers = FALSE;
gboolean analyze = FALSE;
gchar *format = NULL;
int scale = 1000; int scale = 1000;
int app_status = 0; int app_status = 0;
struct external_renderer_params so_render_params; struct external_renderer_params so_render_params;
@ -275,6 +277,8 @@ int main(int argc, char **argv)
GOptionEntry entries[] = { GOptionEntry entries[] = {
{"version", 'v', 0, G_OPTION_ARG_NONE, &version, _("Print version"), NULL}, {"version", 'v', 0, G_OPTION_ARG_NONE, &version, _("Print version"), NULL},
{"analyze", 'A', 0, G_OPTION_ARG_NONE, &analyze, _("Anaylze GDS file"), NULL},
{"format", 'f', 0, G_OPTION_ARG_STRING, &format, _("Output format of analysis result, Default simple"), "[simple | pretty | cellsonly]"},
{"renderer", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &renderer_args, {"renderer", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &renderer_args,
_("Renderer to use. Can be used multiple times."), "pdf|svg|tikz|ext"}, _("Renderer to use. Can be used multiple times."), "pdf|svg|tikz|ext"},
{"scale", 's', 0, G_OPTION_ARG_INT, &scale, _("Divide output coordinates by <SCALE>"), "<SCALE>" }, {"scale", 's', 0, G_OPTION_ARG_INT, &scale, _("Divide output coordinates by <SCALE>"), "<SCALE>" },
@ -320,10 +324,13 @@ int main(int argc, char **argv)
for (i = 2; i < argc; i++) for (i = 2; i < argc; i++)
printf(_("Ignored argument: %s"), argv[i]); printf(_("Ignored argument: %s"), argv[i]);
app_status = if (analyze) {
command_line_convert_gds(gds_name, cellname, renderer_args, output_paths, mappingname, app_status = command_line_analyze_lib(format, gds_name);
&so_render_params, pdf_standalone, pdf_layers, scale); } else {
app_status =
command_line_convert_gds(gds_name, cellname, renderer_args, output_paths, mappingname,
&so_render_params, pdf_standalone, pdf_layers, scale);
}
} else { } else {
app_status = start_gui(argc, argv); app_status = start_gui(argc, argv);
} }

View File

@ -275,12 +275,20 @@ static int cairo_renderer_render_cell_to_vector_file(GdsOutputRenderer *renderer
goto ret_parent; goto ret_parent;
} }
/* Close stdin and (stdout and stderr may live on) */ /* We are now in a separate process just for rendering the output image.
* You may print a log message to the activity bar of the gui by writing a line
* teminated with '\n' to comm_pipe[1]. This will be handled by the parent process.
* Directly calling the update function
* gds_output_renderer_update_async_progress()
* does not have any effect because this is a separate process.
*/
/*
* Close stdin and (stdout and stderr may live on)
*/
close(0); close(0);
//close(1);
close(comm_pipe[0]); close(comm_pipe[0]);
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer)); layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
/* Clear layers */ /* Clear layers */
@ -363,8 +371,6 @@ static int cairo_renderer_render_cell_to_vector_file(GdsOutputRenderer *renderer
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) { for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
linfo = (struct layer_info *)info_list->data; linfo = (struct layer_info *)info_list->data;
dprintf(comm_pipe[1], _("Exporting layer %d to file\n"), linfo->layer);
if (linfo->layer >= MAX_LAYERS) { if (linfo->layer >= MAX_LAYERS) {
printf(_("Layer outside of spec.\n")); printf(_("Layer outside of spec.\n"));
continue; continue;
@ -373,6 +379,8 @@ static int cairo_renderer_render_cell_to_vector_file(GdsOutputRenderer *renderer
if (!linfo->render) if (!linfo->render)
continue; continue;
dprintf(comm_pipe[1], _("Exporting layer %d to file\n"), linfo->layer);
if (pdf_file && pdf_cr) { if (pdf_file && pdf_cr) {
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin); cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha); cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);

View File

@ -100,6 +100,11 @@ static void gds_output_renderer_dispose(GObject *self_obj)
if (priv->output_file) if (priv->output_file)
g_free(priv->output_file); g_free(priv->output_file);
if (priv->idle_function_parameters.status_message) {
g_free(priv->idle_function_parameters.status_message);
priv->idle_function_parameters.status_message = NULL;
}
g_clear_object(&priv->layer_settings); g_clear_object(&priv->layer_settings);
/* Chain up to parent class */ /* Chain up to parent class */

View File

@ -370,7 +370,7 @@ static int latex_renderer_render_output(GdsOutputRenderer *renderer,
l_renderer->pdf_layers, l_renderer->tex_standalone, renderer); l_renderer->pdf_layers, l_renderer->tex_standalone, renderer);
fclose(tex_file); fclose(tex_file);
} else { } else {
g_error(_("Could not open LaTeX output file")); g_warning(_("Could not open LaTeX output file"));
} }
if (settings) if (settings)

View File

@ -1,26 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 --> <!-- Generated with glade 3.38.2 -->
<interface> <interface>
<requires lib="gtk+" version="3.20"/> <requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="adjustment1"> <object class="GtkAdjustment" id="adjustment1">
<property name="upper">1</property> <property name="upper">1</property>
<property name="value">1</property> <property name="value">1</property>
<property name="step_increment">0.01</property> <property name="step-increment">0.01</property>
<property name="page_increment">0.10000000000000001</property> <property name="page-increment">0.10</property>
</object> </object>
<object class="GtkBox" id="box"> <object class="GtkBox" id="box">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="spacing">3</property> <property name="spacing">3</property>
<child> <child>
<object class="GtkEventBox" id="event-box"> <object class="GtkEventBox" id="event-box">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-justify-fill</property> <property name="icon-name">open-menu-symbolic</property>
</object> </object>
</child> </child>
</object> </object>
@ -33,7 +33,7 @@
<child> <child>
<object class="GtkLabel" id="layer"> <object class="GtkLabel" id="layer">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">label</property> <property name="label" translatable="yes">label</property>
</object> </object>
<packing> <packing>
@ -45,9 +45,9 @@
<child> <child>
<object class="GtkColorButton" id="color"> <object class="GtkColorButton" id="color">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="use_alpha">True</property> <property name="use-alpha">True</property>
<property name="title" translatable="yes">Select Layer Color and Opacity</property> <property name="title" translatable="yes">Select Layer Color and Opacity</property>
<property name="rgba">rgb(0,0,0)</property> <property name="rgba">rgb(0,0,0)</property>
</object> </object>
@ -61,9 +61,9 @@
<object class="GtkCheckButton" id="export"> <object class="GtkCheckButton" id="export">
<property name="label" translatable="yes">Export Layer</property> <property name="label" translatable="yes">Export Layer</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">False</property> <property name="receives-default">False</property>
<property name="draw_indicator">True</property> <property name="draw-indicator">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -74,7 +74,7 @@
<child> <child>
<object class="GtkEntry" id="entry"> <object class="GtkEntry" id="entry">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>

View File

@ -1,145 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 --> <!-- Generated with glade 3.38.2 -->
<interface> <interface>
<requires lib="gtk+" version="3.20"/> <requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="auto-name-img"> <object class="GtkImage" id="auto-name-img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-edit</property> <property name="icon-name">format-text-rich-symbolic</property>
</object> </object>
<object class="GtkImage" id="color-img"> <object class="GtkImage" id="color-img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-select-color</property> <property name="icon-name">color-select-symbolic</property>
</object>
<object class="GtkImage" id="load-mapping-img">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-open</property>
</object>
<object class="GtkImage" id="save-mapping-img">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Save the current layer configuration to CSV</property>
<property name="stock">gtk-save-as</property>
</object> </object>
<object class="GtkImage" id="select-all-img"> <object class="GtkImage" id="select-all-img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-apply</property> <property name="icon-name">emblem-ok-symbolic</property>
</object> </object>
<object class="GtkImage" id="sort-down-img"> <object class="GtkImage" id="sort-down-img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-sort-ascending</property> <property name="icon-name">view-sort-descending-symbolic</property>
</object> </object>
<object class="GtkImage" id="sort-up-img"> <object class="GtkImage" id="sort-up-img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="stock">gtk-sort-descending</property> <property name="icon-name">view-sort-ascending-symbolic</property>
</object> </object>
<object class="GtkWindow" id="main-window"> <object class="GtkWindow" id="main-window">
<property name="height_request">250</property> <property name="height-request">250</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="icon_name">gds-render</property> <property name="icon-name">gds-render</property>
<child type="titlebar">
<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-Render</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkButton" id="button-load-gds">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Open GDS2 Database</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="button-load-mapping">
<property name="label" translatable="yes">Load Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Load the current layer configuration from CSV</property>
<property name="image">load-mapping-img</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-save-mapping">
<property name="label" translatable="yes">Save Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">save-mapping-img</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="convert-button">
<property name="label">gtk-convert</property>
<property name="name">button-convert</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Convert selected cell</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkSearchEntry" id="cell-search"> <object class="GtkSearchEntry" id="cell-search">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="primary_icon_name">edit-find-symbolic</property> <property name="primary-icon-name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property> <property name="primary-icon-activatable">False</property>
<property name="primary_icon_sensitive">False</property> <property name="primary-icon-sensitive">False</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -150,15 +62,15 @@
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="hscrollbar_policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="shadow_type">in</property> <property name="shadow-type">in</property>
<child> <child>
<object class="GtkTreeView" id="cell-tree"> <object class="GtkTreeView" id="cell-tree">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="enable_search">False</property> <property name="enable-search">False</property>
<property name="enable_grid_lines">both</property> <property name="enable-grid-lines">both</property>
<child internal-child="selection"> <child internal-child="selection">
<object class="GtkTreeSelection"/> <object class="GtkTreeSelection"/>
</child> </child>
@ -181,20 +93,20 @@
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<child> <child>
<object class="GtkButton" id="button-up-sort"> <object class="GtkButton" id="button-up-sort">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="tooltip_text" translatable="yes">Sort layers ascending</property> <property name="tooltip-text" translatable="yes">Sort layers ascending</property>
<property name="image">sort-up-img</property> <property name="image">sort-up-img</property>
<property name="always_show_image">True</property> <property name="always-show-image">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -205,11 +117,11 @@
<child> <child>
<object class="GtkButton" id="button-down-sort"> <object class="GtkButton" id="button-down-sort">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="tooltip_text" translatable="yes">Sort layers descending</property> <property name="tooltip-text" translatable="yes">Sort layers descending</property>
<property name="image">sort-down-img</property> <property name="image">sort-down-img</property>
<property name="always_show_image">True</property> <property name="always-show-image">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -220,11 +132,11 @@
<child> <child>
<object class="GtkButton" id="auto-color-button"> <object class="GtkButton" id="auto-color-button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="tooltip_text" translatable="yes">Automatically color layers</property> <property name="tooltip-text" translatable="yes">Automatically color layers</property>
<property name="image">color-img</property> <property name="image">color-img</property>
<property name="always_show_image">True</property> <property name="always-show-image">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -235,11 +147,11 @@
<child> <child>
<object class="GtkButton" id="button-select-all"> <object class="GtkButton" id="button-select-all">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="tooltip_text" translatable="yes">Select all layers for export</property> <property name="tooltip-text" translatable="yes">Select all layers for export</property>
<property name="image">select-all-img</property> <property name="image">select-all-img</property>
<property name="always_show_image">True</property> <property name="always-show-image">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -250,11 +162,11 @@
<child> <child>
<object class="GtkButton" id="button-auto-name"> <object class="GtkButton" id="button-auto-name">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="receives_default">True</property> <property name="receives-default">True</property>
<property name="tooltip_text" translatable="yes">Automatically name layers</property> <property name="tooltip-text" translatable="yes">Automatically name layers</property>
<property name="image">auto-name-img</property> <property name="image">auto-name-img</property>
<property name="always_show_image">True</property> <property name="always-show-image">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -272,19 +184,19 @@
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can-focus">True</property>
<property name="margin_top">1</property> <property name="margin-top">1</property>
<property name="hscrollbar_policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="shadow_type">in</property> <property name="shadow-type">in</property>
<child> <child>
<object class="GtkViewport"> <object class="GtkViewport">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<child> <child>
<object class="GtkListBox" id="layer-list"> <object class="GtkListBox" id="layer-list">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="selection_mode">none</property> <property name="selection-mode">none</property>
</object> </object>
</child> </child>
</object> </object>
@ -313,7 +225,7 @@
<child> <child>
<object class="GtkBox" id="activity-bar"> <object class="GtkBox" id="activity-bar">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<placeholder/> <placeholder/>
@ -327,5 +239,75 @@
</child> </child>
</object> </object>
</child> </child>
<child type="titlebar">
<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-Render</property>
<property name="show-close-button">True</property>
<child>
<object class="GtkButton" id="button-load-gds">
<property name="label">Open GDS</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Open GDS2 Database</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="button-load-mapping">
<property name="label" translatable="yes">Load Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Load the current layer configuration from CSV</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button-save-mapping">
<property name="label" translatable="yes">Save Mapping</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="convert-button">
<property name="label">Convert Cell</property>
<property name="name">button-convert</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Convert selected cell</property>
<property name="always-show-image">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object> </object>
</interface> </interface>

41
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,41 @@
project(gds-render-test)
add_custom_target(test "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" "-r compact" "-s" DEPENDS ${PROJECT_NAME})
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(ColorBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
cmake_minimum_required(VERSION 2.8)
find_package(PkgConfig REQUIRED)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/catch-framework")
aux_source_directory("geometric" GEOMETRIC_TEST_SOURCES)
set(TEST_SOURCES
${GEOMETRIC_TEST_SOURCES}
)
set(DUT_SOURCES
"../geometric/vector-operations.c"
)
add_executable(${PROJECT_NAME} EXCLUDE_FROM_ALL "test-main.cpp" ${TEST_SOURCES} ${DUT_SOURCES})
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS})

17618
test/catch-framework/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
#include <catch.hpp>
#include <limits>
extern "C" {
#include <gds-render/geometric/vector-operations.h>
}
TEST_CASE("geometric/vector-operations/vector_2d_add", "[GEOMETRIC]")
{
struct vector_2d res;
struct vector_2d a;
struct vector_2d b;
a.x = 1;
a.y = 2;
b.x = 2;
b.y = 6;
vector_2d_add(&res, &a, &b);
REQUIRE(res.x == Approx(a.x + b.x));
REQUIRE(res.y == Approx(a.y + b.y));
}
TEST_CASE("geometric/vector-operations/vector_2d_calculate_angle_between", "[GEOMETRIC]")
{
double angle;
struct vector_2d a;
struct vector_2d b;
a.x = 1;
a.y = 0;
b.x = 0;
b.y = 1;
angle = vector_2d_calculate_angle_between(&a, &a);
REQUIRE(angle == Approx(0.0));
angle = vector_2d_calculate_angle_between(&a, &b);
REQUIRE(angle == Approx(90.0 / 180.0 * M_PI));
}
TEST_CASE("geometric/vector-operations/vector_2d_subtract", "[GEOMETRIC]")
{
struct vector_2d res;
struct vector_2d a;
struct vector_2d b;
a.x = 1;
a.y = 2;
b.x = 2;
b.y = 6;
vector_2d_subtract(&res, &a, &b);
REQUIRE(res.x == Approx(a.x - b.x));
REQUIRE(res.y == Approx(a.y - b.y));
}
TEST_CASE("geometric/vector-operations/vector_2d_abs", "[GEOMETRIC]")
{
struct vector_2d c;
struct vector_2d a;
struct vector_2d b;
double a_len, b_len, c_len;
a.x = 1;
a.y = 0;
b.x = 0;
b.y = 2;
c.x = 3;
c.y = 4;
a_len = vector_2d_abs(&a);
b_len = vector_2d_abs(&b);
c_len = vector_2d_abs(&c);
REQUIRE(a_len == Approx(1.0));
REQUIRE(b_len == Approx(2.0));
REQUIRE(c_len == Approx(5.0));
}
TEST_CASE("geometric/vector-operations/vector_2d_scalar_multipy", "[GEOMETRIC]")
{
struct vector_2d c;
struct vector_2d a;
struct vector_2d b;
double mult;
a.x = 1;
a.y = 0;
b.x = 0;
b.y = 2;
mult = vector_2d_scalar_multipy(&a, &b);
REQUIRE(mult == Approx(0.0));
a.x = 1;
a.y = 1;
b.x = 1;
b.y = 1;
mult = vector_2d_scalar_multipy(&a, &b);
REQUIRE(mult == Approx(2.0));
}
TEST_CASE("geometric/vector-operations/vector_2d_normalize", "[GEOMETRIC]")
{
struct vector_2d a;
a.x = 1;
a.y = 0;
vector_2d_normalize(&a);
REQUIRE(a.x == Approx(1.0));
REQUIRE(a.y == Approx(0.0));
a.x = 1;
a.y = -1;
vector_2d_normalize(&a);
REQUIRE(a.x == Approx(1.0/sqrt(2)));
REQUIRE(a.y == Approx(-1.0/sqrt(2)));
}
TEST_CASE("geometric/vector-operations/vector_2d_rotate", "[GEOMETRIC]")
{
struct vector_2d a;
a.x = 1;
a.y = 0;
vector_2d_rotate(&a, M_PI/2);
REQUIRE(a.x == Approx(0.0).scale(0.001));
REQUIRE(a.y == Approx(1.0));
a.x = 0;
a.y = 1;
vector_2d_rotate(&a, -M_PI/2);
vector_2d_rotate(&a, M_PI);
REQUIRE(a.x == Approx(-1.0));
REQUIRE(a.y == Approx(0.0).scale(0.001));
}
TEST_CASE("geometric/vector-operations/vector_2d_scale", "[GEOMETRIC]")
{
struct vector_2d a;
a.x = 1;
a.y = 0;
vector_2d_scale(&a, 2.0);
REQUIRE(a.x == Approx(2.0));
REQUIRE(a.y == Approx(0.0));
a.x = 1;
a.y = -3;
vector_2d_scale(&a, 0.5);
REQUIRE(a.x == Approx(0.5));
REQUIRE(a.y == Approx(-1.5));
}

2
test/test-main.cpp Normal file
View File

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch-framework/catch.hpp"