Compare commits
332 Commits
Author | SHA1 | Date | |
---|---|---|---|
504dc476b1 | |||
8ff872cf36 | |||
9c4dbd51c8 | |||
2829143bbe | |||
5185097075 | |||
573cd59892 | |||
8b1f667819 | |||
c2ca2ff573 | |||
c0ac6cc3c5 | |||
22bc3a18d7 | |||
dbc9fcdf34 | |||
b39030aeaa | |||
2f59a762cd | |||
ab26f8a2af | |||
9a43cd53f8 | |||
ba6b07c8a2 | |||
1548c82542 | |||
fb6d31c120 | |||
f6c65d9c7a | |||
d43bec2cea | |||
05a1ef9014 | |||
a36b78b237 | |||
ac87cafa37 | |||
091729841a | |||
28368e8a32 | |||
2b3cc8222a | |||
c23150b819 | |||
049e6c2a4c | |||
600e10e4d5 | |||
238f2cea82 | |||
91706ccf2e | |||
17e7239e54 | |||
554b73c406 | |||
4eebff04a4 | |||
04525611fa | |||
cb92d64ec3 | |||
37ff2080f9 | |||
e1b85d1a99 | |||
b0c9afdae5 | |||
f6abfada2c | |||
f135b42d8a | |||
058564326b | |||
fd1eac7fda | |||
2c91956b32 | |||
232d025211 | |||
ceeb67355d | |||
ba51a437a4 | |||
e461b0be1d | |||
42f1636860 | |||
d29109e516 | |||
b784f28d4c | |||
94851570e9 | |||
f4fa1bd4e5 | |||
2e7bb03c17 | |||
39ff0dec1a | |||
74f9663bde | |||
330285cc2f | |||
24ae5e4d5b | |||
f7d15c7267 | |||
00d02b8291 | |||
75e01b80c8 | |||
89f9a638c6 | |||
7b1722661c | |||
5a43a8a4bf | |||
f11e11e6a7 | |||
0c5dd3c8e7 | |||
77a3a0da5a | |||
f8b0b63937 | |||
2d389342fd | |||
1ca04aaa71 | |||
b8fc904af5 | |||
fdfa478fed | |||
c0182220f1 | |||
798262383e | |||
0bfe8df92f | |||
de9066f181 | |||
87bc60bed0 | |||
20d72a5edb | |||
9e8d0b4611 | |||
4550815901 | |||
e3b6ee66ef | |||
f3786cf282 | |||
c085a62036 | |||
55799b2266 | |||
4970585cee | |||
c6483dbebd | |||
86342da2a2 | |||
ce8386799b | |||
374e3b54c0 | |||
3651296c3a | |||
5fe21f1d73 | |||
2d7103abbb | |||
392d7e1b3c | |||
2fddfa475b | |||
e6603d4c13 | |||
80730ab9c4 | |||
2b0e2095e6 | |||
0c20db39bd | |||
1b1f742ae1 | |||
3b6837b886 | |||
efb1af7ee0 | |||
fa1a78e54c | |||
0417784877 | |||
c186d3cdb3 | |||
f02a720f99 | |||
374a893dda | |||
83a7848c14 | |||
7977ee7c8b | |||
e7f0f904e8 | |||
48eb2c296f | |||
3d5c4daad9 | |||
9899b94db6 | |||
f153485996 | |||
f15e82b5dc | |||
daf12a7d8c | |||
11f2068b76 | |||
24d66e74fe | |||
58a0bd85c4 | |||
f8de3468de | |||
4cc31c81e3 | |||
74dfbd9b34 | |||
40a7e5a650 | |||
d8f6981fe6 | |||
4e38d8f452 | |||
866d36873a | |||
74eb17b2dc | |||
0304c0d08b | |||
70ea6a8901 | |||
529b49ee2e | |||
6d31193123 | |||
e7bf59aa8c | |||
188c6f5d87 | |||
92e40cb8ca | |||
8f788e262f | |||
2e8e258b49 | |||
547b002e57 | |||
c7ce62673f | |||
dd488c3105 | |||
be0d58c54e | |||
4a6b0dc879 | |||
f7b2a331ec | |||
e90cd1313d | |||
0fbbc1db64 | |||
8005e8bcc7 | |||
31a47339f8 | |||
7753e42078 | |||
b2ffc709bb | |||
b6c6262662 | |||
c70f99a283 | |||
592dcbae53 | |||
f1102162b7 | |||
8bef6bcb17 | |||
dc40dec212 | |||
56591fb675 | |||
7fdd1f6c92 | |||
1f914d1218 | |||
13e202424b | |||
a48fe9ab58 | |||
9bd225b837 | |||
00d6710922 | |||
67b8dc2443 | |||
6eaf86dc1c | |||
1de96f501c | |||
01e61a79fd | |||
dc30950df5 | |||
23775b079a | |||
a65295fbeb | |||
9245d68da1 | |||
0a04f2fed4 | |||
62388e4053 | |||
c365c89908 | |||
f20826ccf7 | |||
94ef879a94 | |||
977547d91d | |||
0dc91c14de | |||
5ec7832ac4 | |||
52fb07bea6 | |||
eefe0df984 | |||
e3e39a80ee | |||
448de30b91 | |||
ec9a65cec5 | |||
7cbde0f30a | |||
00d7691bda | |||
b8a02912b0 | |||
e703d4427a | |||
f9e16fa4d7 | |||
1bf01a5cd2 | |||
cd3ef452f1 | |||
40edd21f0a | |||
bcc8623382 | |||
a9ccf6533d | |||
e16b7f9d25 | |||
16b18fc5b3 | |||
941711129a | |||
d90c1b389e | |||
291ded0277 | |||
5f6dbbed0e | |||
8b1d3709b7 | |||
4db8593e5b | |||
bea35bf952 | |||
ad5e0ebe11 | |||
ee99e50656 | |||
c016a5e96e | |||
cfc156c1c0 | |||
bd97ccf44f | |||
df7cc6d0fc | |||
8be5bd230b | |||
3a72796b2f | |||
9f7e1e1696 | |||
27f5a5e3d2 | |||
ec72fb2aa1 | |||
4968492eee | |||
4d6d2e6734 | |||
eba4238855 | |||
7492764666 | |||
6c840b8bd1 | |||
3489b74027 | |||
f60150e8c7 | |||
91633edc78 | |||
1dc23afa9a | |||
7fd8768fd0 | |||
c77c08299f | |||
dc0520e9d3 | |||
2af859b136 | |||
b102d90d33 | |||
c5e697b366 | |||
ea27443b39 | |||
5dbafcb8d5 | |||
7a0d61020b | |||
74bdbe6d79 | |||
8d57d63cf3 | |||
a2bcda6752 | |||
17af08b04d | |||
8a3721dc53 | |||
94ac44ddc5 | |||
1cbacef56c | |||
cae6a9c6c3 | |||
fe98499ce7 | |||
d5dde3658d | |||
b6bf0c30bf | |||
c908a8be47 | |||
7aa7a0c773 | |||
a10c09c674 | |||
a0d19bee39 | |||
4115fd97af | |||
32b8c4ccd3 | |||
1584769a51 | |||
dc4b377b13 | |||
08722cd6f9 | |||
4b238c55ea | |||
1b62427770 | |||
85f037ce59 | |||
92506485e0 | |||
3ec91ab322 | |||
92da653368 | |||
a38946b803 | |||
943e924337 | |||
e0f2e7d605 | |||
bd64e13d87 | |||
0123385b40 | |||
a4f9be1ef4 | |||
731e377b6e | |||
0d0b692960 | |||
c2323ab43d | |||
7fa769806a | |||
17c9d088cc | |||
5f40f148b6 | |||
86566a038f | |||
4ca1f75813 | |||
4d2f3b0d70 | |||
ed37fc0222 | |||
d4f14c52ed | |||
58d3f5c57c | |||
2510a54aac | |||
02a59c4cc5 | |||
40c4c8b4fb | |||
01c9701492 | |||
01ab56e07a | |||
3ffd63115f | |||
31c4efe99b | |||
f5bc8de86e | |||
d107954859 | |||
5c994f892a | |||
96f1347b2c | |||
2d2ca67c48 | |||
d9282d8e5a | |||
d5f1b2edf4 | |||
f224b28613 | |||
7b10d41160 | |||
302d462cda | |||
c146bcd094 | |||
e6abaddcd1 | |||
a35231b9ec | |||
24b70eec48 | |||
8ffcba830d | |||
022d9561db | |||
f5f8509b91 | |||
61f607ac94 | |||
ee1b55120f | |||
b04788b7d4 | |||
3c05b50bc7 | |||
dfadaa241e | |||
4f02854401 | |||
f2b02c0c1f | |||
e739305f46 | |||
5729ef0db8 | |||
88cd834d13 | |||
f625d2daba | |||
e42aa36520 | |||
2ffa09d104 | |||
feb69b6d60 | |||
20ec6bd41b | |||
eef012fc4d | |||
e847e691bd | |||
0d6b2c7a36 | |||
583f01faae | |||
795d496949 | |||
6ebd05007e | |||
906225f47f | |||
dadafa43a3 | |||
2d3241d8b7 | |||
0ecc60d2a1 | |||
9b0f268bbd | |||
6ae316f459 | |||
082a823575 | |||
1f7f3118fa | |||
5cfd93c18d | |||
6818357f64 | |||
b0fdb261e0 | |||
de8d6967c6 | |||
493f787fd1 | |||
a7b7ba71e5 |
40
.github/workflows/cmake.yml
vendored
Normal file
40
.github/workflows/cmake.yml
vendored
Normal 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}}
|
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -1,3 +1,8 @@
|
||||
[submodule "c-style-checker"]
|
||||
path = c-style-checker
|
||||
url = https://git.shimatta.de/mhu/c-style-checker
|
||||
branch = master
|
||||
[submodule "3rdparty/libfort"]
|
||||
path = 3rdparty/libfort
|
||||
url = https://git.shimatta.de/3rd-party/libfort
|
||||
branch = develop
|
||||
|
1
3rdparty/libfort
vendored
Submodule
1
3rdparty/libfort
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 41237162a9bd34a30a88069ee4e230584ae8d674
|
28
AUR/PKGBUILD
28
AUR/PKGBUILD
@ -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
|
||||
pkgver=20180725.001
|
||||
pkgver=v1.2_10_g00d02b8
|
||||
pkgrel=1
|
||||
pkgdesc="Conversion tool for converting GDS layout files into TikZ Code and PDF"
|
||||
arch=('i686' 'x86_64')
|
||||
@ -10,23 +10,31 @@ licence=('GPLv2')
|
||||
depends=('glib2' 'gtk3' 'cairo')
|
||||
makedepends=('cmake' 'git')
|
||||
privides=('gds-render')
|
||||
source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/gds-render.git")
|
||||
sha1sums=('SKIP')
|
||||
source=("${pkgname}-git"::"git+https://git.shimatta.de/mhu/gds-render.git" "https://git.shimatta.de/3rd-party/libfort.git")
|
||||
sha1sums=('SKIP' 'SKIP')
|
||||
|
||||
pkgver () {
|
||||
_date=`date +"%Y%m%d"`
|
||||
cd "${srcdir}/${pkgname}-git"
|
||||
echo "$_date.$(git rev-list --count master).$(git rev-parse --short master)"
|
||||
cd "${srcdir}/${pkgname}-git/version"
|
||||
echo "$(echo "$(sh ./generate-version-string.sh)" | sed 's/-/_/g')"
|
||||
}
|
||||
|
||||
build () {
|
||||
cd "$srcdir/$pkgname-git"
|
||||
cmake .
|
||||
mkdir "$srcdir/$pkgname-git/build"
|
||||
cd "$srcdir/$pkgname-git/build"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make
|
||||
}
|
||||
|
||||
prepare () {
|
||||
cd "${pkgname}-git"
|
||||
git submodule init
|
||||
git config submodule.libfort.url "$srcdir/libfort"
|
||||
git submodule update
|
||||
}
|
||||
|
||||
package () {
|
||||
cd "$srcdir/$pkgname-git"
|
||||
cd "$srcdir/$pkgname-git/build"
|
||||
make DESTDIR="${pkgdir}" install
|
||||
install -D -m664 "$srcdir/$pkgname-git/AUR/gds-render.desktop" \
|
||||
"$pkgdir/usr/share/applications/gds-render.desktop"
|
||||
@ -34,4 +42,6 @@ package () {
|
||||
"$pkgdir/usr/share/icons/hicolor/scalable/apps/gds-render.svg"
|
||||
install -D -m664 "$srcdir/$pkgname-git/icon/128x128/gds-render.png" \
|
||||
"$pkgdir/usr/share/icons/hicolor/128x128/apps/gds-render.png"
|
||||
|
||||
(cd $srcdir/$pkgname-git/build/translations/output/ && tar cf - "locale" | (cd "$pkgdir/usr/share/" && tar xf -))
|
||||
}
|
||||
|
@ -1,4 +1,28 @@
|
||||
project(gds-render)
|
||||
project(gds-render LANGUAGES C)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "/usr/" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
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)
|
||||
@ -6,41 +30,68 @@ pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||
|
||||
add_subdirectory(glade)
|
||||
add_subdirectory(doxygen)
|
||||
add_subdirectory(version)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||
add_subdirectory(plugins)
|
||||
|
||||
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message("${Yellow}Debug mode for translations used!${ColorReset}")
|
||||
add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"${CMAKE_CURRENT_BINARY_DIR}/translations/output\")
|
||||
message("${BoldMagenta}${CMAKE_CURRENT_BINARY_DIR}/translations/output used as data dir${ColorReset}")
|
||||
else(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message("Global locale directory used. Make sure files in /usr/share/locale are available")
|
||||
add_definitions(-DGETTEXT_PACKAGE=\"gds-render\" -DLOCALEDATADIR=\"/usr/share\")
|
||||
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
|
||||
|
||||
aux_source_directory("widgets" LAYER_SOURCES)
|
||||
aux_source_directory("tree-renderer" RENDERER_SOURCES)
|
||||
aux_source_directory("cell-selector" CELL_SELECTOR_SOURCES)
|
||||
aux_source_directory("gds-utils" GDS_SOURCES)
|
||||
aux_source_directory("latex-renderer" LATEX_SOURCES)
|
||||
aux_source_directory("cairo-renderer" CAIRO_SOURCES)
|
||||
aux_source_directory("output-renderers" OUTPUT_RENDERER_SOURCES)
|
||||
aux_source_directory("geometric" GEOMETRIC_SOURCES)
|
||||
aux_source_directory("layer" LAYER_SELECTOR_SOURCES)
|
||||
set(SOURCE "main.c" "command-line.c" "gds-render-gui.c" "external-renderer.c")
|
||||
set(SOURCE "main.c" "command-line.c" "gds-render-gui.c")
|
||||
|
||||
set(SOURCE
|
||||
${SOURCE}
|
||||
${LAYER_SOURCES}
|
||||
${RENDERER_SOURCES}
|
||||
${CELL_SELECTOR_SOURCES}
|
||||
${GDS_SOURCES}
|
||||
${LATEX_SOURCES}
|
||||
${CAIRO_SOURCES}
|
||||
${OUTPUT_RENDERER_SOURCES}
|
||||
${GEOMETRIC_SOURCES}
|
||||
${LAYER_SELECTOR_SOURCES}
|
||||
)
|
||||
|
||||
add_compile_options(-Wall)
|
||||
set(SOURCE_GENERATED
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resources/resources.c
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
|
||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||
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_dependencies(${PROJECT_NAME} glib-resources)
|
||||
add_dependencies(${PROJECT_NAME} version)
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS})
|
||||
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
|
||||
add_dependencies(${PROJECT_NAME} translations)
|
||||
|
||||
install (TARGETS ${PROJECT_NAME}
|
||||
RUNTIME
|
||||
DESTINATION bin
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m version ${CMAKE_DL_LIBS} fort)
|
||||
|
||||
add_custom_target(documentation DEPENDS doxygen)
|
||||
|
@ -1,5 +1,7 @@
|
||||
# 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.
|
||||
The GDS2 format is mainly used in integrated circuit development.
|
||||
This program allows the conversion of a GDS file to a vector graphics file.
|
||||
|
106
cell-selector/cell-statistics-renderer.c
Normal file
106
cell-selector/cell-statistics-renderer.c
Normal 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));
|
||||
}
|
||||
|
||||
/** @} */
|
@ -28,20 +28,21 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||
#include <gds-render/cell-selector/lib-cell-renderer.h>
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
|
||||
|
||||
enum {
|
||||
PROP_LIB = 1,
|
||||
PROP_CELL,
|
||||
PROP_ERROR_LEVEL,
|
||||
PROP_COUNT
|
||||
PROP_LIB = 1, /**< @brief Library to display the name of */
|
||||
PROP_CELL, /**< @brief Cell to display the name of */
|
||||
PROP_ERROR_LEVEL, /**< @brief Error level of cell/library for coloring */
|
||||
PROP_COUNT /**< @brief Sentinel */
|
||||
};
|
||||
|
||||
void lib_cell_renderer_init(LibCellRenderer *self)
|
||||
{
|
||||
(void)self;
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
@ -87,11 +88,13 @@ static void lib_cell_renderer_set_property(GObject *object,
|
||||
g_value_init(&val, G_TYPE_STRING);
|
||||
g_value_set_string(&val, ((struct gds_library *)g_value_get_pointer(value))->name);
|
||||
g_object_set_property(object, "text", &val);
|
||||
g_value_unset(&val);
|
||||
break;
|
||||
case PROP_CELL:
|
||||
g_value_init(&val, G_TYPE_STRING);
|
||||
g_value_set_string(&val, ((struct gds_cell *)g_value_get_pointer(value))->name);
|
||||
g_object_set_property(object, "text", &val);
|
||||
g_value_unset(&val);
|
||||
break;
|
||||
case PROP_ERROR_LEVEL:
|
||||
/* Set cell color according to error level */
|
||||
@ -99,6 +102,7 @@ static void lib_cell_renderer_set_property(GObject *object,
|
||||
convert_error_level_to_color(&color, g_value_get_uint(value));
|
||||
g_value_set_boxed(&val, &color);
|
||||
g_object_set_property(object, "foreground-rgba", &val);
|
||||
g_value_unset(&val);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
|
||||
@ -111,6 +115,8 @@ static void lib_cell_renderer_get_property(GObject *object,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
(void)value;
|
||||
|
||||
switch (param_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
|
505
command-line.c
505
command-line.c
@ -29,176 +29,439 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gds-render/command-line.h>
|
||||
#include <gds-render/gds-utils/gds-parser.h>
|
||||
#include <gds-render/layer/mapping-parser.h>
|
||||
#include <gds-render/layer/layer-info.h>
|
||||
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||
#include <gds-render/latex-renderer/latex-output.h>
|
||||
#include <gds-render/external-renderer.h>
|
||||
#include <gds-render/layer/layer-settings.h>
|
||||
#include <gds-render/output-renderers/cairo-renderer.h>
|
||||
#include <gds-render/output-renderers/latex-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-statistics.h>
|
||||
|
||||
/**
|
||||
* @brief Delete layer_info and free nem element.
|
||||
*
|
||||
* Like delete_layer_info_struct() but also frees layer_info::name
|
||||
* @param info
|
||||
* @warning This function must not be used if the layer_info::name field references the internal storage strings if e.g. an entry field
|
||||
*/
|
||||
static void delete_layer_info_with_name(struct layer_info *info)
|
||||
#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[] = {
|
||||
{
|
||||
if (info) {
|
||||
if (info->name)
|
||||
g_free(info->name);
|
||||
free(info);
|
||||
}
|
||||
.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)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (!string_array)
|
||||
return 0;
|
||||
|
||||
for (count = 0; *string_array; string_array++)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
||||
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
||||
gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file)
|
||||
static int create_renderers(char **renderers,
|
||||
char **output_file_names,
|
||||
gboolean tex_layers,
|
||||
gboolean tex_standalone,
|
||||
const struct external_renderer_params *ext_params,
|
||||
GList **renderer_list,
|
||||
LayerSettings *layer_settings)
|
||||
{
|
||||
GList *libs = NULL;
|
||||
FILE *tex_file;
|
||||
int res;
|
||||
GFile *file;
|
||||
int i;
|
||||
GFileInputStream *stream;
|
||||
GDataInputStream *dstream;
|
||||
gboolean layer_export;
|
||||
GdkRGBA layer_color;
|
||||
int layer;
|
||||
char *layer_name;
|
||||
GList *layer_info_list = NULL;
|
||||
GList *cell_list;
|
||||
struct layer_info *linfo_temp;
|
||||
struct gds_library *first_lib;
|
||||
struct gds_cell *toplevel_cell = NULL, *temp_cell;
|
||||
char **renderer_iter;
|
||||
char *current_renderer;
|
||||
int idx;
|
||||
char *current_out_file;
|
||||
int count_render, count_out;
|
||||
GdsOutputRenderer *output_renderer;
|
||||
|
||||
if (!renderer_list)
|
||||
return -1;
|
||||
|
||||
/* Check if parameters are valid */
|
||||
if (!gds_name || (!pdf_name && pdf) || (!tex_name && tex) || !layer_file || !cell_name) {
|
||||
printf("Probably missing argument. Check --help option\n");
|
||||
return;
|
||||
if (!renderers || !output_file_names) {
|
||||
fprintf(stderr, _("Please specify renderers and file names\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load GDS */
|
||||
clear_lib_list(&libs);
|
||||
res = parse_gds_from_file(gds_name, &libs);
|
||||
if (res)
|
||||
goto ret_destroy_library_list;
|
||||
|
||||
file = g_file_new_for_path(layer_file);
|
||||
stream = g_file_read(file, NULL, NULL);
|
||||
|
||||
if (!stream) {
|
||||
printf("Layer mapping not readable!\n");
|
||||
goto ret_destroy_file;
|
||||
count_render = string_array_count(renderers);
|
||||
count_out = string_array_count(output_file_names);
|
||||
if (count_render != count_out) {
|
||||
fprintf(stderr, _("Count of renderers %d does not match count of output file names %d\n"),
|
||||
count_render, count_out);
|
||||
return -1;
|
||||
}
|
||||
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
|
||||
i = 0;
|
||||
do {
|
||||
res = mapping_parser_load_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
|
||||
if (res == 0) {
|
||||
if (!layer_export)
|
||||
|
||||
/* Parse cmd line parameters */
|
||||
for (renderer_iter = renderers, idx = 0; *renderer_iter; renderer_iter++, idx++) {
|
||||
current_renderer = *renderer_iter;
|
||||
current_out_file = output_file_names[idx];
|
||||
|
||||
/* File valid ? */
|
||||
if (!current_out_file || !current_out_file[0])
|
||||
continue;
|
||||
|
||||
if (!strcmp(current_renderer, "tikz")) {
|
||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(latex_renderer_new_with_options(tex_layers,
|
||||
tex_standalone));
|
||||
} else if (!strcmp(current_renderer, "pdf")) {
|
||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_pdf());
|
||||
} else if (!strcmp(current_renderer, "svg")) {
|
||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_svg());
|
||||
} else if (!strcmp(current_renderer, "ext")) {
|
||||
if (!ext_params->so_path) {
|
||||
fprintf(stderr, _("Please specify shared object for external renderer. Will ignore this renderer.\n"));
|
||||
continue;
|
||||
linfo_temp = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||
if (!linfo_temp) {
|
||||
printf("Out of memory\n");
|
||||
goto ret_clear_layer_list;
|
||||
}
|
||||
linfo_temp->color.alpha = layer_color.alpha;
|
||||
linfo_temp->color.red = layer_color.red;
|
||||
linfo_temp->color.green = layer_color.green;
|
||||
linfo_temp->color.blue = layer_color.blue;
|
||||
linfo_temp->name = layer_name;
|
||||
linfo_temp->stacked_position = i++;
|
||||
linfo_temp->layer = layer;
|
||||
layer_info_list = g_list_append(layer_info_list, (gpointer)linfo_temp);
|
||||
output_renderer = GDS_RENDER_OUTPUT_RENDERER(
|
||||
external_renderer_new_with_so_and_param(ext_params->so_path,
|
||||
ext_params->cli_params));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} while(res >= 0);
|
||||
|
||||
|
||||
/* find_cell in first library. */
|
||||
if (!libs)
|
||||
goto ret_clear_layer_list;
|
||||
|
||||
first_lib = (struct gds_library *)libs->data;
|
||||
if (!first_lib) {
|
||||
fprintf(stderr, "No library in library list. This should not happen.\n");
|
||||
goto ret_clear_layer_list;
|
||||
gds_output_renderer_set_output_file(output_renderer, current_out_file);
|
||||
gds_output_renderer_set_layer_settings(output_renderer, layer_settings);
|
||||
*renderer_list = g_list_append(*renderer_list, output_renderer);
|
||||
}
|
||||
|
||||
for (cell_list = first_lib->cells; cell_list != NULL; cell_list = g_list_next(cell_list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gds_cell *find_gds_cell_in_lib(struct gds_library *lib, const char *cell_name)
|
||||
{
|
||||
GList *cell_list;
|
||||
struct gds_cell *return_cell = NULL;
|
||||
struct gds_cell *temp_cell;
|
||||
|
||||
for (cell_list = lib->cells; cell_list; cell_list = g_list_next(cell_list)) {
|
||||
temp_cell = (struct gds_cell *)cell_list->data;
|
||||
if (!strcmp(temp_cell->name, cell_name)) {
|
||||
toplevel_cell = temp_cell;
|
||||
if (!strncmp(temp_cell->name, cell_name, CELL_NAME_MAX)) {
|
||||
return_cell = temp_cell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return return_cell;
|
||||
}
|
||||
|
||||
int command_line_convert_gds(const char *gds_name,
|
||||
const char *cell_name,
|
||||
char **renderers,
|
||||
char **output_file_names,
|
||||
const char *layer_file,
|
||||
struct external_renderer_params *ext_param,
|
||||
gboolean tex_standalone,
|
||||
gboolean tex_layers,
|
||||
double scale)
|
||||
{
|
||||
int ret = -1;
|
||||
GList *libs = NULL;
|
||||
int res;
|
||||
GList *renderer_list = NULL;
|
||||
GList *list_iter;
|
||||
struct gds_library *first_lib;
|
||||
struct gds_cell *toplevel_cell = NULL;
|
||||
LayerSettings *layer_sett;
|
||||
GdsOutputRenderer *current_renderer;
|
||||
|
||||
const struct gds_library_parsing_opts gds_parsing_options = {
|
||||
.simplified_polygons = 1,
|
||||
};
|
||||
|
||||
/* Check if parameters are valid */
|
||||
if (!gds_name || !cell_name || !output_file_names || !layer_file || !renderers) {
|
||||
printf(_("Probably missing argument. Check --help option\n"));
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Load layer_settings */
|
||||
layer_sett = layer_settings_new();
|
||||
layer_settings_load_from_csv(layer_sett, layer_file);
|
||||
|
||||
/* Create renderers */
|
||||
if (create_renderers(renderers, output_file_names, tex_layers, tex_standalone,
|
||||
ext_param, &renderer_list, layer_sett))
|
||||
goto ret_destroy_layer_mapping;
|
||||
|
||||
|
||||
/* Load GDS */
|
||||
clear_lib_list(&libs);
|
||||
res = parse_gds_from_file(gds_name, &libs, &gds_parsing_options);
|
||||
if (res)
|
||||
goto ret_destroy_library_list;
|
||||
|
||||
/* find_cell in first library. */
|
||||
if (!libs)
|
||||
goto ret_clear_renderers;
|
||||
|
||||
first_lib = (struct gds_library *)libs->data;
|
||||
if (!first_lib) {
|
||||
fprintf(stderr, _("No library in library list. This should not happen.\n"));
|
||||
/* This is safe. Library destruction can handle an empty list element */
|
||||
goto ret_destroy_library_list;
|
||||
}
|
||||
|
||||
/* Find cell in first library */
|
||||
toplevel_cell = find_gds_cell_in_lib(first_lib, cell_name);
|
||||
|
||||
if (!toplevel_cell) {
|
||||
printf("Couldn't find cell in first library!\n");
|
||||
goto ret_clear_layer_list;
|
||||
printf(_("Couldn't find cell in first library!\n"));
|
||||
goto ret_destroy_library_list;
|
||||
}
|
||||
|
||||
/* Check if cell passes vital checks */
|
||||
res = gds_tree_check_reference_loops(toplevel_cell->parent_library);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Checking library %s failed.\n", first_lib->name);
|
||||
goto ret_clear_layer_list;
|
||||
fprintf(stderr, _("Checking library %s failed.\n"), first_lib->name);
|
||||
goto ret_destroy_library_list;
|
||||
} else if (res > 0) {
|
||||
fprintf(stderr, "%d reference loops found.\n", res);
|
||||
fprintf(stderr, _("%d reference loops found.\n"), res);
|
||||
|
||||
/* do further checking if the specified cell and/or its subcells are affected */
|
||||
if (toplevel_cell->checks.affected_by_reference_loop == 1) {
|
||||
fprintf(stderr, "Cell is affected by reference loop. Abort!\n");
|
||||
goto ret_clear_layer_list;
|
||||
fprintf(stderr, _("Cell is affected by reference loop. Abort!\n"));
|
||||
goto ret_destroy_library_list;
|
||||
}
|
||||
}
|
||||
|
||||
if (toplevel_cell->checks.affected_by_reference_loop == GDS_CELL_CHECK_NOT_RUN)
|
||||
fprintf(stderr, "Cell was not checked. This should not happen. Please report this issue. Will continue either way.\n");
|
||||
fprintf(stderr, _("Cell was not checked. This should not happen. Please report this issue. Will continue either way.\n"));
|
||||
|
||||
/* Note: unresolved references are not an abort condition.
|
||||
* Deal with it.
|
||||
*/
|
||||
|
||||
/* Render outputs */
|
||||
if (pdf == TRUE || svg == TRUE) {
|
||||
cairo_render_cell_to_vector_file(toplevel_cell, layer_info_list, (pdf == TRUE ? pdf_name : NULL),
|
||||
(svg == TRUE ? svg_name : NULL), scale);
|
||||
/* Execute all rendererer instances */
|
||||
for (list_iter = renderer_list; list_iter; list_iter = list_iter->next) {
|
||||
current_renderer = GDS_RENDER_OUTPUT_RENDERER(list_iter->data);
|
||||
gds_output_renderer_render_output(current_renderer, toplevel_cell, scale);
|
||||
}
|
||||
|
||||
if (tex == TRUE) {
|
||||
tex_file = fopen(tex_name, "w");
|
||||
if (!tex_file)
|
||||
goto ret_clear_layer_list;
|
||||
latex_render_cell_to_code(toplevel_cell, layer_info_list, tex_file, scale, pdf_layers, pdf_standalone);
|
||||
fclose(tex_file);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
if (so_name && so_out_file) {
|
||||
if (strlen(so_name) == 0 || strlen(so_out_file) == 0)
|
||||
goto ret_clear_layer_list;
|
||||
|
||||
/* Render output using external renderer */
|
||||
printf("Invoking external renderer!\n");
|
||||
external_renderer_render_cell(toplevel_cell, layer_info_list, so_out_file, so_name);
|
||||
printf("External renderer finished!\n");
|
||||
}
|
||||
|
||||
ret_clear_layer_list:
|
||||
g_list_free_full(layer_info_list, (GDestroyNotify)delete_layer_info_with_name);
|
||||
|
||||
g_object_unref(dstream);
|
||||
g_object_unref(stream);
|
||||
ret_destroy_file:
|
||||
g_object_unref(file);
|
||||
/* Delete all allocated libraries */
|
||||
ret_destroy_library_list:
|
||||
clear_lib_list(&libs);
|
||||
ret_clear_renderers:
|
||||
for (list_iter = renderer_list; list_iter; list_iter = list_iter->next)
|
||||
g_object_unref(list_iter->data);
|
||||
ret_destroy_layer_mapping:
|
||||
g_object_unref(layer_sett);
|
||||
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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -1,10 +1,19 @@
|
||||
find_package(Doxygen)
|
||||
|
||||
if (DOXYGEN_FOUND)
|
||||
add_custom_target(doxygen
|
||||
add_custom_target(documentation DEPENDS doxygen doxygen-pdf)
|
||||
|
||||
add_custom_target(doxygen
|
||||
COMMAND ./build-doxygen.sh "${PROJECT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating documentation with Doxygen")
|
||||
|
||||
add_custom_target(
|
||||
doxygen-pdf
|
||||
COMMAND make
|
||||
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/latex"
|
||||
DEPENDS doxygen
|
||||
)
|
||||
else (DOXYGEN_FOUND)
|
||||
message("Doxygen need to be installed to generate the doxygen documentation")
|
||||
message("Doxygen needs to be installed to generate the doxygen documentation")
|
||||
endif (DOXYGEN_FOUND)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.8.15
|
||||
# Doxyfile 1.8.17
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@ -197,6 +197,16 @@ SHORT_NAMES = NO
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||
# such as
|
||||
# /***************
|
||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||
# Javadoc-style will behave just like regular comments and it will not be
|
||||
# interpreted by doxygen.
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_BANNER = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
@ -234,7 +244,7 @@ SEPARATE_MEMBER_PAGES = NO
|
||||
# uses this value to replace tabs by spaces in code fragments.
|
||||
# Minimum value: 1, maximum value: 16, default value: 4.
|
||||
|
||||
TAB_SIZE = 4
|
||||
TAB_SIZE = 8
|
||||
|
||||
# This tag can be used to specify a number of aliases that act as commands in
|
||||
# the documentation. An alias has the form:
|
||||
@ -299,7 +309,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# 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
|
||||
# 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,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
@ -329,7 +339,7 @@ MARKDOWN_SUPPORT = YES
|
||||
# to that level are automatically included in the table of contents, even if
|
||||
# they do not have an id attribute.
|
||||
# Note: This feature currently applies only to Markdown headings.
|
||||
# Minimum value: 0, maximum value: 99, default value: 0.
|
||||
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
@ -465,6 +475,12 @@ EXTRACT_ALL = YES
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
@ -519,8 +535,8 @@ HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# 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
|
||||
# included in the documentation.
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
@ -543,7 +559,7 @@ INTERNAL_DOCS = NO
|
||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
@ -835,8 +851,10 @@ INPUT_ENCODING = UTF-8
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.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 \
|
||||
*.cc \
|
||||
@ -912,7 +930,7 @@ EXCLUDE_SYMLINKS = NO
|
||||
# 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_PATTERNS =
|
||||
EXCLUDE_PATTERNS = */test/*
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
@ -1249,9 +1267,9 @@ HTML_TIMESTAMP = NO
|
||||
|
||||
# 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
|
||||
# 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
|
||||
# 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.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@ -1402,7 +1420,7 @@ QCH_FILE =
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@ -1410,7 +1428,7 @@ QHP_NAMESPACE = org.doxygen.Project
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
@ -1419,7 +1437,7 @@ QHP_VIRTUAL_FOLDER = doc
|
||||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@ -1427,7 +1445,7 @@ QHP_CUST_FILTER_NAME =
|
||||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@ -1435,7 +1453,7 @@ QHP_CUST_FILTER_ATTRS =
|
||||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
@ -1539,8 +1557,14 @@ FORMULA_FONTSIZE = 10
|
||||
|
||||
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
|
||||
# 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
|
||||
# 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
|
||||
@ -1610,7 +1634,7 @@ MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
|
||||
# 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
|
||||
# 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
|
||||
@ -1714,10 +1738,11 @@ LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||
# generate index for LaTeX.
|
||||
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||
# it will be automatically added in the LaTeX code.
|
||||
# Note: This tag is used in the generated output file (.tex).
|
||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||
# The default value is: \makeindex.
|
||||
# The default value is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_MAKEINDEX_CMD = \makeindex
|
||||
@ -1749,7 +1774,7 @@ PAPER_TYPE = a4
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
EXTRA_PACKAGES = amsmath
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
||||
# generated LaTeX document. The header should contain everything until the first
|
||||
@ -1854,7 +1879,7 @@ LATEX_BIB_STYLE = plain
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_TIMESTAMP = YES
|
||||
|
||||
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# path from which the emoji images will be read. If a relative path is entered,
|
||||
@ -1982,7 +2007,7 @@ MAN_LINKS = NO
|
||||
# captures the structure of the code including all documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_XML = NO
|
||||
GENERATE_XML = YES
|
||||
|
||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
@ -2102,7 +2127,7 @@ ENABLE_PREPROCESSING = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||
@ -2110,7 +2135,7 @@ MACRO_EXPANSION = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
|
||||
# INCLUDE_PATH will be searched if a #include is found.
|
||||
@ -2142,7 +2167,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = __attribute__(x)=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
@ -2209,12 +2234,6 @@ EXTERNAL_GROUPS = YES
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
@ -2228,15 +2247,6 @@ PERL_PATH = /usr/bin/perl
|
||||
|
||||
CLASS_DIAGRAMS = NO
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
@ -2417,7 +2427,7 @@ DIRECTORY_GRAPH = YES
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_IMAGE_FORMAT = svg
|
||||
|
||||
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
|
||||
# enable generation of interactive SVG images that allow zooming and panning.
|
||||
@ -2429,7 +2439,7 @@ DOT_IMAGE_FORMAT = png
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
INTERACTIVE_SVG = NO
|
||||
INTERACTIVE_SVG = YES
|
||||
|
||||
# The DOT_PATH tag can be used to specify the path where the dot tool can be
|
||||
# found. If left blank, it is assumed the dot tool can be found in the path.
|
||||
|
6
doxygen/activity-bar.dox
Normal file
6
doxygen/activity-bar.dox
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @defgroup ActivityBar Activity Bar
|
||||
* @ingroup Widgets
|
||||
*
|
||||
* Activity Status Bar
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
* @defgroup Cairo-Renderer Cairo Renderer
|
||||
* @ingroup renderers
|
||||
* @ingroup GdsOutputRenderer
|
||||
*/
|
||||
|
@ -28,40 +28,61 @@ The dependency list of GTK3 already includes Cairographics and GLib2. You should
|
||||
|
||||
Development is done with the following library versions:
|
||||
|
||||
| Cairographics | GLib2 | GTK3 |
|
||||
| ------------- | ---------- | ------ |
|
||||
| 1.16.0-2 | 2.60.0-1 | 3.24.7 |
|
||||
| Cairographics | GLib2 | GTK3 |
|
||||
| ------------- | ---------- | --------- |
|
||||
| 1.17.2 | 2.64.2 | 3.24.18 |
|
||||
|
||||
@section comp-instr Compilation Instructions
|
||||
@subsection linux-build General Linux Build Instruction
|
||||
Go to the build directory you want to compile in. This may be the gds-render project root.
|
||||
Execute
|
||||
@code
|
||||
cmake <Path to gds-render root>
|
||||
cmake -DCMAKE_BUILD_TYPE=Release <Path to gds-render root>
|
||||
@endcode
|
||||
|
||||
Cmake will check the dependencies. Once cmake has finished. Type
|
||||
for a build in release configuartion. Use `-DCMAKE_BUILD_TYPE=Debug` for debugging. Cmake will check the dependencies.
|
||||
|
||||
Once cmake has finished, type
|
||||
@code
|
||||
make
|
||||
@endcode
|
||||
|
||||
in order to build the program and
|
||||
|
||||
to build the program and
|
||||
|
||||
@code
|
||||
make documentation
|
||||
@endcode
|
||||
to build the doxygen documentation.
|
||||
to build the doxygen documentation.
|
||||
|
||||
@subsection arch-makepkg Archlinux Package
|
||||
|
||||
The subfolder 'AUR' contains a PKGBUILD file to build an Archlinux/Pacman package.
|
||||
|
||||
@subsection 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: ‘calculate_path_miter_points’ defined but not used [-Wunused-function] | Ignore. Function will be used in later versions. |
|
||||
|
||||
|
||||
@subsection windows-compilation Compilation for Windows
|
||||
|
||||
@warning Windows is not a target system for this application, considering that this program converts GDS files which are most likely generated under a Linux system. The tips shown in this section are a guidance for anyone trying to build this application for Windows.
|
||||
|
||||
@warning Note that the Windows compatibility may decrease in future releases and a simple compilation like with this version might not be possible anymore.
|
||||
|
||||
The current release of 'gds-render' does not compile under a windows system, due to incompatibilities in the external library renderer.
|
||||
It is possible to comment out the code that causes the incompatibility. The external renderer will not be usable after this.
|
||||
|
||||
Steps:
|
||||
|
||||
- Go to file external-renderer.c
|
||||
- Remove `#include` <dlfcn.h>
|
||||
- comment out all code in #external_renderer_render_cell
|
||||
|
||||
The program should now compile.
|
||||
|
||||
@warning This guide is out of date. The Cairo renderer doesn't compile under windows anymore due to the usage of the fork() system call. It is possible to patch this out in order to restore Windows compatibility.
|
||||
|
||||
*/
|
||||
|
@ -1,4 +1,26 @@
|
||||
/**
|
||||
* @defgroup external-renderer External Shared Object Renderer
|
||||
* @ingroup renderers
|
||||
* @defgroup ExternalRenderer External Shared Object Renderer
|
||||
* @ingroup GdsOutputRenderer
|
||||
*
|
||||
* @section ExternalRendererProps Properties
|
||||
* This class inherits all properties from its parent @ref GdsOutputRenderer.
|
||||
* In addition to that, it implements the following properties:
|
||||
*
|
||||
* Property Name | Description
|
||||
* -----------------|----------------------------------------------------------------
|
||||
* shared-object-path | Path to the shared object used for rendering
|
||||
* param-string | Command line parameters passed to external renderer's init function
|
||||
*
|
||||
* All these properties have to be set for rendering.
|
||||
*
|
||||
* @section ExternalRendererFuncs Necessary Functions
|
||||
*
|
||||
* The following functions and variables are necessary for an external renderer to implement:
|
||||
*
|
||||
* Code Define | Prototype | Description
|
||||
* ---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------
|
||||
* @ref EXTERNAL_LIBRARY_RENDER_FUNCTION | int EXTERNAL_LIBRARY_RENDER_FUNCTION(struct gds_cell *toplevel, GList *layer_info_list, const char *output_file_name, double scale) | Render cell to output file
|
||||
* @ref EXTERNAL_LIBRARY_INIT_FUNCTION | int EXTERNAL_LIBRARY_INIT_FUNCTION(const char *option_string, const char *version_string) | Init function. Executed before rendering. This is given the command line parameters specified for the external renderer and the version string of the currently running gds-render program.
|
||||
* @ref EXTERNAL_LIBRARY_FORK_REQUEST | int EXTERNAL_LIBRARY_FORK_REQUEST; | The pure presence of this integer results in the execution inside a subprocess of hte whole shared object's code
|
||||
*
|
||||
*/
|
||||
|
34
doxygen/gds-output-renderer.dox
Normal file
34
doxygen/gds-output-renderer.dox
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @defgroup GdsOutputRenderer GDS Output Renderer base class
|
||||
*
|
||||
* The renderers are used to convert the cell structures read from the GDS layout file
|
||||
* into different output formats.
|
||||
*
|
||||
* The GdsOutputRenderer base class is used to derive all renderers from.
|
||||
*
|
||||
* @warning Although the GdsOutputRenderer class provides compatibility for asynchronous rendering,
|
||||
* the class is not thread safe / re-entrant. Only use it from a signle context. Not even the rendering function called is allowed to modifiy this object.
|
||||
*
|
||||
* A allowed function to be called from the async rendering thread is #gds_output_renderer_update_async_progress and the get functions for the properties.
|
||||
*
|
||||
* @note The context that owned the renderer has to ensure that only one rendering is active at a time for a single instance of a renderer.
|
||||
*
|
||||
* By default this class implements the following features:
|
||||
*
|
||||
* @section GdsOutputRendererProps Properties
|
||||
* Property Name | Description
|
||||
* -----------------|----------------------------------------------------------------
|
||||
* layer-settings | LayerSettings object containing the layer rendering information
|
||||
* output-file | Output file name for rendering
|
||||
*
|
||||
* All these properties have to be set for rendering.
|
||||
*
|
||||
* @section GdsOutputRendererSignals Signals / Events
|
||||
* Signal Name | Description | Callback prototype
|
||||
* -----------------|-------------------------------------------------|-----------------------------------------------------------
|
||||
* async-finished | The asynchronous rendering is finished | void callback(GdsOutputRenderer *src, gpointer user_data)
|
||||
* progress-changed | The asynchronous rendering progress changed | void callback(GdsOutputRenderer *src, const char *progress, gpointer user_data)
|
||||
*
|
||||
* @note The `char *progress` supplied to the callback function must not be modified or freed.
|
||||
*
|
||||
*/
|
Binary file not shown.
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
@ -1,4 +1,16 @@
|
||||
/**
|
||||
* @defgroup LaTeX-Renderer LaTeX/TikZ Renderer
|
||||
* @ingroup renderers
|
||||
* @defgroup LaTeX-Renderer LaTeX / TikZ Renderer
|
||||
* @ingroup GdsOutputRenderer
|
||||
*
|
||||
* This is the class implementing the \f$\mbox{\LaTeX}\f$ / TikZ output rendering
|
||||
|
||||
* @section LaTeXRendererProps Properties
|
||||
* This class inherits all properties from its parent @ref GdsOutputRenderer.
|
||||
* In addition to that, it implements the following properties:
|
||||
*
|
||||
* Property Name | Description
|
||||
* -----------------|----------------------------------------------------------------
|
||||
* standalone | Configure output LaTeX document to be standalone compilable (requires standalone documentclass)
|
||||
* pdf-layers | Create OCG layers in LaTeX output
|
||||
*
|
||||
*/
|
||||
|
6
doxygen/plugins.dox
Normal file
6
doxygen/plugins.dox
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @defgroup plugins External Renderer Plugins
|
||||
*
|
||||
* These plugins can be loaded with the @ref ExternalRenderer
|
||||
*
|
||||
*/
|
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* @defgroup renderers Output Renderers
|
||||
*
|
||||
* The renderers are used to convert the cell structures read from the GDS layout file
|
||||
* into different output formats.
|
||||
*
|
||||
* Currently the renders are statically implemented without the use of GObjects.
|
||||
* This will probably change in future releases in order to make it easier to integrate new rendering methods.
|
||||
*/
|
@ -3,19 +3,25 @@
|
||||
@section cmd Command Line Interface
|
||||
To use the application on the command line check 'gds-render `--`help'.
|
||||
|
||||
Application Options:
|
||||
- -t, `--`tikz Output TikZ code
|
||||
- -p, `--`pdf Output PDF document
|
||||
- -s, `--`scale=SCALE Divide output coordinates by SCALE
|
||||
- -o, `--`tex-output=PATH Optional path for TeX file
|
||||
- -O, `--`pdf-output=PATH Optional path for PDF file
|
||||
- -m, `--`mapping=PATH Path for Layer Mapping File
|
||||
- -c, `--`cell=NAME Cell to render
|
||||
- -a, `--`tex-standalone Create standalone PDF
|
||||
- -l, `--`tex-layers Create PDF Layers (OCG)
|
||||
- -P, `--`custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
|
||||
- -e, `--`external-lib-output=PATH Output path for external render library
|
||||
- `--`display=DISPLAY X display to use
|
||||
Usage:
|
||||
gds-render [OPTION…] FILE - Convert GDS file `<FILE>` to graphic
|
||||
|
||||
Help Options:
|
||||
-h, `--`help Show help options
|
||||
`--`help-all Show all help options
|
||||
`--`help-gtk Show GTK+ Options
|
||||
|
||||
Application Options:
|
||||
-v, `--`version Print version
|
||||
-r, `--`renderer=pdf|svg|tikz|ext Renderer to use
|
||||
-s, `--`scale=`<SCALE>` Divide output coordinates by `<SCALE>`
|
||||
-o, `--`output-file=PATH Output file path
|
||||
-m, `--`mapping=PATH Path for Layer Mapping File
|
||||
-c, `--`cell=NAME Cell to render
|
||||
-a, `--`tex-standalone Create standalone PDF
|
||||
-l, `--`tex-layers Create PDF Layers (OCG)
|
||||
-P, `--`custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
|
||||
`--`display=DISPLAY X display to use
|
||||
|
||||
|
||||
@section gui Graphical User Interface
|
||||
@ -27,8 +33,8 @@ It is possible to export the layer configurations so they can be used later on.
|
||||
@image html gui.png
|
||||
@image latex gui.png
|
||||
|
||||
The cell selector on the left shows the GDS Libraries and Cells. The cells are marked green if all references inside the cell could be found. If not all references could be found, the cell is marked orange. This doens't show if child cells have missing childs. Only one level of the hierarchy is checked in order to make it easier to spot an errorneous cell. Cells with missing child cells are still renderable but -- obviously -- faulty. If a cell or any sub-cell contains a reference loop, the cell is marked red. In this case it can't be selected for rendering.
|
||||
|
||||
In the above image the cell is green; so everything is okay.
|
||||
The cell selector on the left shows the GDS Libraries and Cells. The cells are marked green if all references inside the cell could be found. If not all references could be found, the cell is marked orange. This doens't show if child cells have missing childs. Only one level of the hierarchy is checked in order to make it easier to spot an errorneous cell. Cells with missing child cells are still renderable but `--` obviously `--` faulty. If a cell or any sub-cell contains a reference loop, the cell is marked red. In this case it can't be selected for rendering.
|
||||
|
||||
In the above image one cell is green; so everything is okay. And the other one is red, which indicates a reference loop. This cell cannot be selected for rendering!
|
||||
*/
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
@ -31,6 +31,6 @@ In tabular form: *v1.0-rc4-41-gaa41373-dirty*
|
||||
| 1.0-rc4 | 41 | aa41373 | yes |
|
||||
|
||||
|
||||
This git-based version number is automatically put into the application and this doxumentation during the application's compilation / the documentation's generation. For this *git* is needed. Therefore, it is highly recommended to have 'git' installed for compilation although it is no build dependency. In case of a missing git installation, the string "! version not set !" is compiled into the application.
|
||||
This git-based version number is automatically put into the application and this documentation during the application's compilation / the documentation's generation. For this *git* is needed. Therefore, it is highly recommended to have 'git' installed for compilation although it is no build dependency. In case of a missing git installation, the string "! version not set !" is compiled into the application.
|
||||
|
||||
**/
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file external-renderer.c
|
||||
* @brief This file implements the dynamic library loading for the external rendering feature
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup external-renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gds-render/external-renderer.h>
|
||||
|
||||
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list,
|
||||
char *output_file, char *so_path)
|
||||
{
|
||||
int (*so_render_func)(struct gds_cell *, GList *, char *) = NULL;
|
||||
void *so_handle = NULL;
|
||||
char *error_msg;
|
||||
int ret = 0;
|
||||
|
||||
/* Check parameter sanity */
|
||||
if (!output_file || !so_path || !toplevel_cell || !layer_info_list)
|
||||
return -3000;
|
||||
|
||||
/* Load shared object */
|
||||
so_handle = dlopen(so_path, RTLD_LAZY);
|
||||
if (!so_handle) {
|
||||
printf("Could not load external library '%s'\nDetailed error is:\n%s\n", so_path, dlerror());
|
||||
return -2000;
|
||||
}
|
||||
|
||||
/* Load symbol from library */
|
||||
so_render_func = (int (*)(struct gds_cell *, GList *, char *))dlsym(so_handle, EXTERNAL_LIBRARY_FUNCTION);
|
||||
error_msg = dlerror();
|
||||
if (error_msg != NULL) {
|
||||
printf("Rendering function not found in library:\n%s\n", error_msg);
|
||||
goto ret_close_so_handle;
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
if (so_render_func)
|
||||
so_render_func(toplevel_cell, layer_info_list, output_file);
|
||||
|
||||
ret_close_so_handle:
|
||||
dlclose(so_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} */
|
466
gds-render-gui.c
466
gds-render-gui.c
@ -29,23 +29,39 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <gds-render/gds-render-gui.h>
|
||||
#include <gds-render/gds-utils/gds-parser.h>
|
||||
#include <gds-render/gds-utils/gds-tree-checker.h>
|
||||
#include <gds-render/layer/layer-selector.h>
|
||||
#include <gds-render/tree-renderer/tree-store.h>
|
||||
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||
#include <gds-render/latex-renderer/latex-output.h>
|
||||
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||
#include <gds-render/widgets/activity-bar.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/cairo-renderer.h>
|
||||
#include <gds-render/widgets/conv-settings-dialog.h>
|
||||
#include <gds-render/geometric/cell-geometrics.h>
|
||||
#include <gds-render/version.h>
|
||||
|
||||
/** @brief Columns of selection tree view */
|
||||
enum cell_store_columns {
|
||||
CELL_SEL_LIBRARY = 0,
|
||||
CELL_SEL_CELL,
|
||||
CELL_SEL_CELL_ERROR_STATE, /**< Used for cell color and selectability */
|
||||
CELL_SEL_STAT,
|
||||
CELL_SEL_COLUMN_COUNT /**< @brief Not a column. Used to determine count of columns */
|
||||
};
|
||||
|
||||
enum gds_render_gui_signal_sig_ids {SIGNAL_WINDOW_CLOSED = 0, SIGNAL_COUNT};
|
||||
|
||||
static guint gds_render_gui_signals[SIGNAL_COUNT];
|
||||
|
||||
struct gui_button_states {
|
||||
gboolean rendering_active;
|
||||
gboolean valid_cell_selected;
|
||||
};
|
||||
|
||||
struct _GdsRenderGui {
|
||||
/* Parent GObject */
|
||||
GObject parent;
|
||||
@ -53,12 +69,20 @@ struct _GdsRenderGui {
|
||||
/* Custom fields */
|
||||
GtkWindow *main_window;
|
||||
GtkWidget *convert_button;
|
||||
GtkWidget *open_button;
|
||||
GtkWidget *load_layer_button;
|
||||
GtkWidget *save_layer_button;
|
||||
GtkWidget *select_all_button;
|
||||
GtkTreeStore *cell_tree_store;
|
||||
GtkTreeModelFilter *cell_filter;
|
||||
GtkWidget *cell_search_entry;
|
||||
LayerSelector *layer_selector;
|
||||
GtkTreeView *cell_tree_view;
|
||||
GList *gds_libraries;
|
||||
ActivityBar *activity_status_bar;
|
||||
struct render_settings render_dialog_settings;
|
||||
ColorPalette *palette;
|
||||
struct gui_button_states button_state_data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
|
||||
@ -73,6 +97,7 @@ G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
|
||||
static gboolean on_window_close(gpointer window, GdkEvent *event, gpointer user)
|
||||
{
|
||||
GdsRenderGui *self;
|
||||
(void)event;
|
||||
|
||||
self = RENDERER_GUI(user);
|
||||
/* Don't close window in case of error */
|
||||
@ -92,24 +117,156 @@ static gboolean on_window_close(gpointer window, GdkEvent *event, gpointer user)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generate string from gds_time_field
|
||||
* @param date Date to convert
|
||||
* @return String with date
|
||||
* @brief This function only allows valid cells to be selected
|
||||
* @param selection
|
||||
* @param model
|
||||
* @param path
|
||||
* @param path_currently_selected
|
||||
* @param data
|
||||
* @return TRUE if element is selectable, FALSE if not
|
||||
*/
|
||||
static GString *generate_string_from_date(struct gds_time_field *date)
|
||||
static gboolean tree_sel_func(GtkTreeSelection *selection,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
gboolean path_currently_selected,
|
||||
gpointer data)
|
||||
{
|
||||
GString *str;
|
||||
GtkTreeIter iter;
|
||||
struct gds_cell *cell;
|
||||
unsigned int error_level;
|
||||
gboolean ret = FALSE;
|
||||
(void)selection;
|
||||
(void)path_currently_selected;
|
||||
(void)data;
|
||||
|
||||
str = g_string_new_len(NULL, 50);
|
||||
g_string_printf(str, "%02u.%02u.%u - %02u:%02u",
|
||||
(unsigned int)date->day,
|
||||
(unsigned int)date->month,
|
||||
(unsigned int)date->year,
|
||||
(unsigned int)date->hour,
|
||||
(unsigned int)date->minute);
|
||||
return str;
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, CELL_SEL_CELL_ERROR_STATE, &error_level, -1);
|
||||
|
||||
/* Allow only rows with _valid_ cell to be selected */
|
||||
if (cell) {
|
||||
/* Cell available. Check if it passed the critical checks */
|
||||
if (!(error_level & LIB_CELL_RENDERER_ERROR_ERR))
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger refiltering of cell filter
|
||||
* @param entry Unused widget, that emitted the signal
|
||||
* @param data GdsrenderGui self instance
|
||||
*/
|
||||
static void cell_tree_view_change_filter(GtkWidget *entry, gpointer data)
|
||||
{
|
||||
GdsRenderGui *self = RENDERER_GUI(data);
|
||||
(void)entry;
|
||||
|
||||
gtk_tree_model_filter_refilter(self->cell_filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief cell_store_filter_visible_func Decides whether an element of the tree model @p model is visible.
|
||||
* @param model Tree model
|
||||
* @param iter Current element / iter in Model to check
|
||||
* @param data Data. Set to static stores variable
|
||||
* @return TRUE if visible, else FALSE
|
||||
* @note TODO: Maybe implement Damerau-Levenshtein distance matching
|
||||
*/
|
||||
static gboolean cell_store_filter_visible_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
GdsRenderGui *self;
|
||||
struct gds_cell *cell;
|
||||
struct gds_library *lib;
|
||||
gboolean result = FALSE;
|
||||
const char *search_string;
|
||||
|
||||
self = RENDERER_GUI(data);
|
||||
g_return_val_if_fail(RENDERER_IS_GUI(self), FALSE);
|
||||
|
||||
if (!model || !iter)
|
||||
goto exit_filter;
|
||||
|
||||
gtk_tree_model_get(model, iter, CELL_SEL_CELL, &cell, CELL_SEL_LIBRARY, &lib, -1);
|
||||
|
||||
/* Show always, if this is a pure lib entry */
|
||||
if (lib && !cell) {
|
||||
result = TRUE;
|
||||
goto exit_filter;
|
||||
}
|
||||
|
||||
if (!cell)
|
||||
goto exit_filter;
|
||||
|
||||
search_string = gtk_entry_get_text(GTK_ENTRY(self->cell_search_entry));
|
||||
|
||||
/* Show all, if field is empty */
|
||||
if (!strlen(search_string))
|
||||
result = TRUE;
|
||||
|
||||
if (strstr(cell->name, search_string))
|
||||
result = TRUE;
|
||||
|
||||
gtk_tree_view_expand_all(self->cell_tree_view);
|
||||
|
||||
exit_filter:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup a GtkTreeView with the necessary columns
|
||||
* @param self Current GUI object
|
||||
*/
|
||||
int gds_render_gui_setup_cell_selector(GdsRenderGui *self)
|
||||
{
|
||||
GtkCellRenderer *render_cell;
|
||||
GtkCellRenderer *render_lib;
|
||||
GtkCellRenderer *render_vertex_count;
|
||||
GtkTreeViewColumn *column;
|
||||
|
||||
self->cell_tree_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER,
|
||||
G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_POINTER);
|
||||
|
||||
/* Searching */
|
||||
self->cell_filter = GTK_TREE_MODEL_FILTER(
|
||||
gtk_tree_model_filter_new(GTK_TREE_MODEL(self->cell_tree_store), NULL));
|
||||
|
||||
gtk_tree_model_filter_set_visible_func(self->cell_filter,
|
||||
(GtkTreeModelFilterVisibleFunc)cell_store_filter_visible_func,
|
||||
self, NULL);
|
||||
g_signal_connect(GTK_SEARCH_ENTRY(self->cell_search_entry), "search-changed",
|
||||
G_CALLBACK(cell_tree_view_change_filter), self);
|
||||
|
||||
gtk_tree_view_set_model(self->cell_tree_view, GTK_TREE_MODEL(self->cell_filter));
|
||||
|
||||
render_cell = 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);
|
||||
gtk_tree_view_append_column(self->cell_tree_view, column);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes(_("Cell"), render_cell, "gds-cell", CELL_SEL_CELL,
|
||||
"error-level", CELL_SEL_CELL_ERROR_STATE, NULL);
|
||||
gtk_tree_view_append_column(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
|
||||
* This prevents selecting a library
|
||||
*/
|
||||
gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(self->cell_tree_view),
|
||||
tree_sel_func, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct gds_cell_statistics cc = {
|
||||
.vertex_count = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Callback function of Load GDS button
|
||||
* @param button
|
||||
@ -131,25 +288,27 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
gint dialog_result;
|
||||
int gds_result;
|
||||
char *filename;
|
||||
GString *mod_date;
|
||||
GString *acc_date;
|
||||
unsigned int cell_error_level;
|
||||
|
||||
const struct gds_library_parsing_opts gds_parsing_options = {
|
||||
.simplified_polygons = 1,
|
||||
};
|
||||
|
||||
self = RENDERER_GUI(user);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", self->main_window,
|
||||
open_dialog = gtk_file_chooser_dialog_new(_("Open GDSII File"), self->main_window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"Cancel", GTK_RESPONSE_CANCEL,
|
||||
"Open GDSII", GTK_RESPONSE_ACCEPT,
|
||||
_("Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("Open GDSII"), GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
file_chooser = GTK_FILE_CHOOSER(open_dialog);
|
||||
|
||||
/* Add GDS II Filter */
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(filter, "*.gds");
|
||||
gtk_file_filter_set_name(filter, "GDSII-Files");
|
||||
gtk_file_filter_set_name(filter, _("GDSII-Files"));
|
||||
gtk_file_chooser_add_filter(file_chooser, filter);
|
||||
|
||||
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
|
||||
@ -164,7 +323,7 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
clear_lib_list(&self->gds_libraries);
|
||||
|
||||
/* 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 */
|
||||
g_free(filename);
|
||||
@ -180,30 +339,17 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
/* Create top level iter */
|
||||
gtk_tree_store_append(self->cell_tree_store, &libiter, NULL);
|
||||
|
||||
/* Convert dates to String */
|
||||
mod_date = generate_string_from_date(&gds_lib->mod_time);
|
||||
acc_date = generate_string_from_date(&gds_lib->access_time);
|
||||
|
||||
gtk_tree_store_set(self->cell_tree_store, &libiter,
|
||||
CELL_SEL_LIBRARY, gds_lib,
|
||||
CELL_SEL_MODDATE, mod_date->str,
|
||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||
-1);
|
||||
|
||||
/* Check this library. This might take a while */
|
||||
(void)gds_tree_check_cell_references(gds_lib);
|
||||
(void)gds_tree_check_reference_loops(gds_lib);
|
||||
/* Delete GStrings including string data. */
|
||||
/* Cell store copies String type data items */
|
||||
g_string_free(mod_date, TRUE);
|
||||
g_string_free(acc_date, TRUE);
|
||||
|
||||
for (cell = gds_lib->cells; cell != NULL; cell = cell->next) {
|
||||
gds_c = (struct gds_cell *)cell->data;
|
||||
gtk_tree_store_append(self->cell_tree_store, &celliter, &libiter);
|
||||
/* Convert dates to String */
|
||||
mod_date = generate_string_from_date(&gds_c->mod_time);
|
||||
acc_date = generate_string_from_date(&gds_c->access_time);
|
||||
|
||||
/* Get the checking results for this cell */
|
||||
cell_error_level = 0;
|
||||
@ -217,15 +363,10 @@ static void on_load_gds(gpointer button, gpointer user)
|
||||
/* Add cell to tree store model */
|
||||
gtk_tree_store_set(self->cell_tree_store, &celliter,
|
||||
CELL_SEL_CELL, gds_c,
|
||||
CELL_SEL_MODDATE, mod_date->str,
|
||||
CELL_SEL_ACCESSDATE, acc_date->str,
|
||||
CELL_SEL_CELL_ERROR_STATE, cell_error_level,
|
||||
CELL_SEL_LIBRARY, gds_c->parent_library,
|
||||
CELL_SEL_STAT, &gds_c->stats,
|
||||
-1);
|
||||
|
||||
/* Delete GStrings including string data. */
|
||||
/* Cell store copies String type data items */
|
||||
g_string_free(mod_date, TRUE);
|
||||
g_string_free(acc_date, TRUE);
|
||||
} /* for cells */
|
||||
} /* for libraries */
|
||||
|
||||
@ -237,6 +378,62 @@ end_destroy:
|
||||
gtk_widget_destroy(open_dialog);
|
||||
}
|
||||
|
||||
static void process_button_state_changes(GdsRenderGui *self)
|
||||
{
|
||||
gboolean convert_button_state = FALSE;
|
||||
gboolean open_gds_button_state = FALSE;
|
||||
|
||||
/* Calculate states */
|
||||
if (!self->button_state_data.rendering_active) {
|
||||
open_gds_button_state = TRUE;
|
||||
if (self->button_state_data.valid_cell_selected)
|
||||
convert_button_state = TRUE;
|
||||
}
|
||||
|
||||
/* Apply states */
|
||||
gtk_widget_set_sensitive(self->convert_button, convert_button_state);
|
||||
gtk_widget_set_sensitive(self->open_button, open_gds_button_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for auto coloring button
|
||||
* @param button
|
||||
* @param user
|
||||
*/
|
||||
static void on_auto_color_clicked(gpointer button, gpointer user)
|
||||
{
|
||||
GdsRenderGui *self;
|
||||
(void)button;
|
||||
|
||||
self = RENDERER_GUI(user);
|
||||
layer_selector_auto_color_layers(self->layer_selector, self->palette, 1.0);
|
||||
}
|
||||
|
||||
static void async_rendering_finished_callback(GdsOutputRenderer *renderer, gpointer gui)
|
||||
{
|
||||
GdsRenderGui *self;
|
||||
|
||||
self = RENDERER_GUI(gui);
|
||||
|
||||
self->button_state_data.rendering_active = FALSE;
|
||||
process_button_state_changes(self);
|
||||
activity_bar_set_ready(self->activity_status_bar);
|
||||
|
||||
g_object_unref(renderer);
|
||||
}
|
||||
|
||||
static void async_rendering_status_update_callback(GdsOutputRenderer *renderer,
|
||||
const char *status_message,
|
||||
gpointer data)
|
||||
{
|
||||
GdsRenderGui *gui;
|
||||
(void)renderer;
|
||||
|
||||
gui = RENDERER_GUI(data);
|
||||
|
||||
activity_bar_set_busy(gui->activity_status_bar, status_message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert button callback
|
||||
* @param button
|
||||
@ -249,9 +446,7 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
GList *layer_list;
|
||||
struct gds_cell *cell_to_render;
|
||||
FILE *output_file;
|
||||
GtkWidget *dialog;
|
||||
RendererSettingsDialog *settings;
|
||||
GtkFileFilter *filter;
|
||||
@ -260,12 +455,18 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
union bounding_box cell_box;
|
||||
unsigned int height, width;
|
||||
struct render_settings *sett;
|
||||
LayerSettings *layer_settings;
|
||||
GdsOutputRenderer *render_engine;
|
||||
|
||||
self = RENDERER_GUI(user);
|
||||
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
/* Abort if rendering is already active */
|
||||
if (self->button_state_data.rendering_active == TRUE)
|
||||
return;
|
||||
|
||||
sett = &self->render_dialog_settings;
|
||||
|
||||
/* Get selected cell */
|
||||
@ -279,7 +480,7 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
return;
|
||||
|
||||
/* Get layers that are rendered */
|
||||
layer_list = layer_selector_export_rendered_layer_info(self->layer_selector);
|
||||
layer_settings = layer_selector_export_rendered_layer_info(self->layer_selector);
|
||||
|
||||
/* Calculate cell size in DB units */
|
||||
bounding_box_prepare_empty(&cell_box);
|
||||
@ -342,30 +543,44 @@ static void on_convert_clicked(gpointer button, gpointer user)
|
||||
|
||||
switch (sett->renderer) {
|
||||
case RENDERER_LATEX_TIKZ:
|
||||
output_file = fopen(file_name, "w");
|
||||
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett->scale,
|
||||
sett->tex_pdf_layers, sett->tex_standalone);
|
||||
fclose(output_file);
|
||||
render_engine =
|
||||
GDS_RENDER_OUTPUT_RENDERER(latex_renderer_new_with_options(sett->tex_pdf_layers,
|
||||
sett->tex_standalone));
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS_SVG:
|
||||
render_engine = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_svg());
|
||||
break;
|
||||
case RENDERER_CAIROGRAPHICS_PDF:
|
||||
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
|
||||
(sett->renderer == RENDERER_CAIROGRAPHICS_PDF
|
||||
? file_name
|
||||
: NULL),
|
||||
(sett->renderer == RENDERER_CAIROGRAPHICS_SVG
|
||||
? file_name
|
||||
: NULL),
|
||||
sett->scale);
|
||||
render_engine = GDS_RENDER_OUTPUT_RENDERER(cairo_renderer_new_pdf());
|
||||
break;
|
||||
default:
|
||||
/* Abort rendering */
|
||||
render_engine = NULL;
|
||||
break;
|
||||
}
|
||||
g_free(file_name);
|
||||
|
||||
if (render_engine) {
|
||||
gds_output_renderer_set_output_file(render_engine, file_name);
|
||||
gds_output_renderer_set_layer_settings(render_engine, layer_settings);
|
||||
/* Prevent user from overwriting library or triggering additional conversion */
|
||||
self->button_state_data.rendering_active = TRUE;
|
||||
process_button_state_changes(self);
|
||||
|
||||
g_signal_connect(render_engine, "async-finished", G_CALLBACK(async_rendering_finished_callback),
|
||||
self);
|
||||
|
||||
activity_bar_set_busy(self->activity_status_bar, _("Rendering cell..."));
|
||||
|
||||
g_signal_connect(render_engine, "progress-changed",
|
||||
G_CALLBACK(async_rendering_status_update_callback), self);
|
||||
gds_output_renderer_render_output_async(render_engine, cell_to_render, sett->scale);
|
||||
}
|
||||
g_free(file_name);
|
||||
} else {
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
ret_layer_destroy:
|
||||
g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
|
||||
g_object_unref(layer_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,7 +600,6 @@ static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
|
||||
on_convert_clicked(NULL, user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback for cell-selection change event
|
||||
*
|
||||
@ -401,10 +615,12 @@ static void cell_selection_changed(GtkTreeSelection *sel, GdsRenderGui *self)
|
||||
|
||||
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
|
||||
/* Node selected. Show button */
|
||||
gtk_widget_set_sensitive(self->convert_button, TRUE);
|
||||
self->button_state_data.valid_cell_selected = TRUE;
|
||||
} else {
|
||||
gtk_widget_set_sensitive(self->convert_button, FALSE);
|
||||
self->button_state_data.valid_cell_selected = FALSE;
|
||||
}
|
||||
|
||||
process_button_state_changes(self);
|
||||
}
|
||||
|
||||
static void sort_up_callback(GtkWidget *widget, gpointer user)
|
||||
@ -441,7 +657,14 @@ static void gds_render_gui_dispose(GObject *gobject)
|
||||
g_clear_object(&self->convert_button);
|
||||
g_clear_object(&self->layer_selector);
|
||||
g_clear_object(&self->cell_tree_store);
|
||||
g_clear_object(&self->cell_filter);
|
||||
g_clear_object(&self->cell_search_entry);
|
||||
g_clear_object(&self->activity_status_bar);
|
||||
g_clear_object(&self->palette);
|
||||
g_clear_object(&self->load_layer_button);
|
||||
g_clear_object(&self->save_layer_button);
|
||||
g_clear_object(&self->open_button);
|
||||
g_clear_object(&self->select_all_button);
|
||||
|
||||
if (self->main_window) {
|
||||
g_signal_handlers_destroy(self->main_window);
|
||||
@ -471,6 +694,65 @@ static void gds_render_gui_class_init(GdsRenderGuiClass *klass)
|
||||
gobject_class->dispose = gds_render_gui_dispose;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for the 'select all layers'-button
|
||||
* @param button Button that triggered the event
|
||||
* @param user_data the GdsrenderGui object containing the main-window the button is placed in
|
||||
*/
|
||||
static void on_select_all_layers_clicked(GtkWidget *button, gpointer user_data)
|
||||
{
|
||||
GdsRenderGui *gui;
|
||||
(void)button;
|
||||
|
||||
gui = RENDERER_GUI(user_data);
|
||||
layer_selector_select_all_layers(gui->layer_selector, TRUE);
|
||||
}
|
||||
|
||||
static gboolean auto_naming_ask_for_override(GdsRenderGui *gui)
|
||||
{
|
||||
GtkDialog *dialog;
|
||||
gint dialog_result;
|
||||
gboolean overwrite = FALSE;
|
||||
|
||||
g_return_val_if_fail(RENDERER_IS_GUI(gui), FALSE);
|
||||
|
||||
/* Ask for overwrite */
|
||||
dialog = GTK_DIALOG(gtk_message_dialog_new(gui->main_window, GTK_DIALOG_USE_HEADER_BAR, GTK_MESSAGE_QUESTION,
|
||||
GTK_BUTTONS_YES_NO, "Overwrite existing layer names?"));
|
||||
dialog_result = gtk_dialog_run(dialog);
|
||||
switch (dialog_result) {
|
||||
case GTK_RESPONSE_YES:
|
||||
overwrite = TRUE;
|
||||
break;
|
||||
case GTK_RESPONSE_NO: /* Expected fallthrough */
|
||||
default:
|
||||
overwrite = FALSE;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
GtkWindow *gds_render_gui_get_main_window(GdsRenderGui *gui)
|
||||
{
|
||||
return gui->main_window;
|
||||
@ -481,21 +763,22 @@ static void gds_render_gui_init(GdsRenderGui *self)
|
||||
GtkBuilder *main_builder;
|
||||
GtkWidget *listbox;
|
||||
GtkHeaderBar *header_bar;
|
||||
struct tree_stores *cell_selector_stores;
|
||||
GtkWidget *sort_up_button;
|
||||
GtkWidget *sort_down_button;
|
||||
GtkWidget *activity_bar_box;
|
||||
GtkWidget *auto_color_button;
|
||||
GtkWidget *auto_naming_button;
|
||||
|
||||
main_builder = gtk_builder_new_from_resource("/main.glade");
|
||||
main_builder = gtk_builder_new_from_resource("/gui/main.glade");
|
||||
|
||||
self->cell_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree"));
|
||||
self->cell_search_entry = GTK_WIDGET(gtk_builder_get_object(main_builder, "cell-search"));
|
||||
|
||||
cell_selector_stores = setup_cell_selector(self->cell_tree_view, GTK_ENTRY(self->cell_search_entry));
|
||||
|
||||
self->cell_tree_store = cell_selector_stores->base_store;
|
||||
gds_render_gui_setup_cell_selector(self);
|
||||
|
||||
self->main_window = GTK_WINDOW(gtk_builder_get_object(main_builder, "main-window"));
|
||||
g_signal_connect(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds")),
|
||||
self->open_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds"));
|
||||
g_signal_connect(self->open_button,
|
||||
"clicked", G_CALLBACK(on_load_gds), (gpointer)self);
|
||||
|
||||
self->convert_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
|
||||
@ -505,6 +788,7 @@ static void gds_render_gui_init(GdsRenderGui *self)
|
||||
/* Create layer selector */
|
||||
self->layer_selector = layer_selector_new(GTK_LIST_BOX(listbox));
|
||||
|
||||
activity_bar_box = GTK_WIDGET(gtk_builder_get_object(main_builder, "activity-bar"));
|
||||
|
||||
/* Callback for selection change of cell selector */
|
||||
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(self->cell_tree_view)), "changed",
|
||||
@ -523,17 +807,25 @@ static void gds_render_gui_init(GdsRenderGui *self)
|
||||
g_signal_connect(sort_down_button, "clicked", G_CALLBACK(sort_down_callback), self);
|
||||
|
||||
/* Set buttons for loading and saving */
|
||||
layer_selector_set_load_mapping_button(self->layer_selector,
|
||||
GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping")),
|
||||
self->main_window);
|
||||
layer_selector_set_save_mapping_button(self->layer_selector, GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping")),
|
||||
self->main_window);
|
||||
self->load_layer_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping"));
|
||||
self->save_layer_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping"));
|
||||
layer_selector_set_load_mapping_button(self->layer_selector, self->load_layer_button, self->main_window);
|
||||
layer_selector_set_save_mapping_button(self->layer_selector, self->save_layer_button, self->main_window);
|
||||
|
||||
/* Connect delete-event */
|
||||
g_signal_connect(GTK_WIDGET(self->main_window), "delete-event",
|
||||
G_CALLBACK(on_window_close), self);
|
||||
|
||||
g_object_unref(main_builder);
|
||||
/* Create and apply ActivityBar */
|
||||
self->activity_status_bar = activity_bar_new();
|
||||
gtk_container_add(GTK_CONTAINER(activity_bar_box), GTK_WIDGET(self->activity_status_bar));
|
||||
gtk_widget_show(GTK_WIDGET(self->activity_status_bar));
|
||||
|
||||
/* Create color palette */
|
||||
self->palette = color_palette_new_from_resource("/data/color-palette.txt");
|
||||
auto_color_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "auto-color-button"));
|
||||
g_signal_connect(auto_color_button, "clicked", G_CALLBACK(on_auto_color_clicked), self);
|
||||
|
||||
|
||||
/* Set default conversion/rendering settings */
|
||||
self->render_dialog_settings.scale = 1000;
|
||||
@ -541,14 +833,32 @@ static void gds_render_gui_init(GdsRenderGui *self)
|
||||
self->render_dialog_settings.tex_pdf_layers = FALSE;
|
||||
self->render_dialog_settings.tex_standalone = FALSE;
|
||||
|
||||
/* Get select all button and connect callback */
|
||||
self->select_all_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-select-all"));
|
||||
g_signal_connect(self->select_all_button, "clicked", G_CALLBACK(on_select_all_layers_clicked), self);
|
||||
|
||||
/* Setup auto naming button */
|
||||
auto_naming_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-auto-name"));
|
||||
g_signal_connect(auto_naming_button, "clicked", G_CALLBACK(auto_naming_clicked), self);
|
||||
|
||||
g_object_unref(main_builder);
|
||||
|
||||
/* Setup default button sensibility data */
|
||||
self->button_state_data.rendering_active = FALSE;
|
||||
self->button_state_data.valid_cell_selected = FALSE;
|
||||
|
||||
/* Reference all objects referenced by this object */
|
||||
g_object_ref(self->activity_status_bar);
|
||||
g_object_ref(self->main_window);
|
||||
g_object_ref(self->cell_tree_view);
|
||||
g_object_ref(self->convert_button);
|
||||
g_object_ref(self->layer_selector);
|
||||
g_object_ref(self->cell_tree_store);
|
||||
/* g_object_ref(self->layer_selector); <= This is already referenced by the _new() function */
|
||||
g_object_ref(self->cell_search_entry);
|
||||
/* g_object_ref(self->palette); */
|
||||
g_object_ref(self->open_button);
|
||||
g_object_ref(self->load_layer_button);
|
||||
g_object_ref(self->save_layer_button);
|
||||
g_object_ref(self->select_all_button);
|
||||
}
|
||||
|
||||
GdsRenderGui *gds_render_gui_new()
|
||||
|
@ -40,8 +40,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <cairo.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <gds-render/gds-utils/gds-parser.h>
|
||||
#include <gds-render/gds-utils/gds-statistics.h>
|
||||
|
||||
/**
|
||||
* @brief Default units assumed for library.
|
||||
@ -49,11 +51,12 @@
|
||||
*/
|
||||
#define GDS_DEFAULT_UNITS (10E-9)
|
||||
|
||||
#define GDS_ERROR(fmt, ...) printf("[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS error*/
|
||||
#define GDS_WARN(fmt, ...) printf("[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */
|
||||
#define GDS_ERROR(fmt, ...) fprintf(stderr, "[PARSE_ERROR] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS error*/
|
||||
#define GDS_WARN(fmt, ...) fprintf(stderr, "[PARSE_WARNING] " fmt "\n", ##__VA_ARGS__) /**< @brief Print GDS warning */
|
||||
|
||||
#if GDS_PRINT_DEBUG_INFOS
|
||||
#define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__) /**< @brief standard printf. But can be disabled in code */
|
||||
/**< @brief standard printf. But can be disabled in code. */
|
||||
#define GDS_INF(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define GDS_INF(fmt, ...)
|
||||
#endif
|
||||
@ -78,8 +81,28 @@ enum gds_record {
|
||||
STRANS = 0x1A01,
|
||||
BOX = 0x2D00,
|
||||
LAYER = 0x0D02,
|
||||
DATATYPE = 0x0E02,
|
||||
WIDTH = 0x0F03,
|
||||
PATHTYPE = 0x2102
|
||||
PATHTYPE = 0x2102,
|
||||
COLROW = 0x1302,
|
||||
AREF = 0x0B00
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Struct representing an array instantiation.
|
||||
*
|
||||
* This struct is defined locally because it is not exposed to the outside of the
|
||||
* parser. Array references are internally converted to a bunch of standard @ref gds_cell_instance elements.
|
||||
*/
|
||||
struct gds_cell_array_instance {
|
||||
char ref_name[CELL_NAME_MAX]; /**< @brief Name of referenced cell */
|
||||
struct gds_cell *cell_ref; /**< @brief Referenced gds_cell structure */
|
||||
struct gds_point control_points[3]; /**< @brief The three control points */
|
||||
int flipped; /**< @brief Mirror each instance on x-axis before rotation */
|
||||
double angle; /**< @brief Angle of rotation for each instance (counter clockwise) in degrees */
|
||||
double magnification; /**< @brief Magnification of each instance */
|
||||
int columns; /**< @brief Column count */
|
||||
int rows; /**< @brief Row count */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -112,6 +135,36 @@ static int name_cell_ref(struct gds_cell_instance *cell_inst,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Name cell reference
|
||||
* @param cell_inst Cell reference
|
||||
* @param bytes Length of name
|
||||
* @param data Name
|
||||
* @return 0 if successful
|
||||
*/
|
||||
static int name_array_cell_ref(struct gds_cell_array_instance *cell_inst,
|
||||
unsigned int bytes, char *data)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (cell_inst == NULL) {
|
||||
GDS_ERROR("Naming array cell ref with no opened cell ref");
|
||||
return -1;
|
||||
}
|
||||
data[bytes] = 0; // Append '0'
|
||||
len = (int)strlen(data);
|
||||
if (len > CELL_NAME_MAX-1) {
|
||||
GDS_ERROR("Cell name '%s' too long: %d\n", data, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* else: */
|
||||
strcpy(cell_inst->ref_name, data);
|
||||
GDS_INF("\tCell referenced: %s\n", cell_inst->ref_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert GDS 8-byte real to double
|
||||
* @param data 8 Byte GDS real
|
||||
@ -133,7 +186,7 @@ static double gds_convert_double(const char *data)
|
||||
if (data[i] != 0)
|
||||
break;
|
||||
if (i == 7) {
|
||||
/* 7 bytes all 0 */
|
||||
/* All 8 bytes are 0 */
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
@ -167,7 +220,7 @@ static signed int gds_convert_signed_int(const char *data)
|
||||
int ret;
|
||||
|
||||
if (!data) {
|
||||
GDS_ERROR("This should not happen");
|
||||
GDS_ERROR("Conversion from GDS data to signed int failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -198,7 +251,7 @@ static int16_t gds_convert_signed_int16(const char *data)
|
||||
* @param data Buffer containing the uint16
|
||||
* @return result
|
||||
*/
|
||||
static uint16_t gds_convert_unsigend_int16(const char *data)
|
||||
static uint16_t gds_convert_unsigned_int16(const char *data)
|
||||
{
|
||||
if (!data) {
|
||||
GDS_ERROR("This should not happen");
|
||||
@ -214,7 +267,8 @@ static uint16_t gds_convert_unsigend_int16(const char *data)
|
||||
* @param library_ptr Return of newly created library.
|
||||
* @return Newly created list pointer
|
||||
*/
|
||||
static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
static GList *append_library(GList *curr_list, const struct gds_library_parsing_opts *opts,
|
||||
struct gds_library **library_ptr)
|
||||
{
|
||||
struct gds_library *lib;
|
||||
|
||||
@ -224,8 +278,15 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
lib->name[0] = 0;
|
||||
lib->unit_in_meters = GDS_DEFAULT_UNITS; // Default. Will be overwritten
|
||||
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;
|
||||
}
|
||||
if (library_ptr)
|
||||
*library_ptr = lib;
|
||||
|
||||
@ -233,13 +294,13 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append graphics to list
|
||||
* @brief Prepend graphics to list
|
||||
* @param curr_list List containing gds_graphics elements. May be NULL
|
||||
* @param type Type of graphics
|
||||
* @param graphics_ptr newly created graphic is written here
|
||||
* @return new list pointer
|
||||
*/
|
||||
static GList *append_graphics(GList *curr_list, enum graphics_type type,
|
||||
static __attribute__((warn_unused_result)) GList *prepend_graphics(GList *curr_list, enum graphics_type type,
|
||||
struct gds_graphics **graphics_ptr)
|
||||
{
|
||||
struct gds_graphics *gfx;
|
||||
@ -258,7 +319,7 @@ static GList *append_graphics(GList *curr_list, enum graphics_type type,
|
||||
if (graphics_ptr)
|
||||
*graphics_ptr = gfx;
|
||||
|
||||
return g_list_append(curr_list, gfx);
|
||||
return g_list_prepend(curr_list, gfx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -301,6 +362,11 @@ static GList *append_cell(GList *curr_list, struct gds_cell **cell_ptr)
|
||||
cell->parent_library = NULL;
|
||||
cell->checks.unresolved_child_count = GDS_CELL_CHECK_NOT_RUN;
|
||||
cell->checks.affected_by_reference_loop = GDS_CELL_CHECK_NOT_RUN;
|
||||
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
|
||||
return NULL;
|
||||
/* return cell */
|
||||
@ -327,9 +393,9 @@ static GList *append_cell_ref(GList *curr_list, struct gds_cell_instance **insta
|
||||
if (inst) {
|
||||
inst->cell_ref = NULL;
|
||||
inst->ref_name[0] = 0;
|
||||
inst->magnification = 1;
|
||||
inst->magnification = 1.0;
|
||||
inst->flipped = 0;
|
||||
inst->angle = 0;
|
||||
inst->angle = 0.0;
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
@ -436,20 +502,102 @@ static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scans cell references inside cell
|
||||
This function searches all the references in \p gcell and updates the gds_cell_instance::cell_ref field in each instance
|
||||
* @brief Simplify graphics objects
|
||||
* @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 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_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("\t\tCell references\n");
|
||||
/* Scan all library references */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -465,7 +613,16 @@ static void scan_library_references(gpointer library_list_item, gpointer user)
|
||||
(void)user;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -491,17 +648,17 @@ static void gds_parse_date(const char *buffer, int length, struct gds_time_field
|
||||
}
|
||||
|
||||
for (temp_date = mod_date; 1; temp_date = access_date) {
|
||||
temp_date->year = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->year = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
temp_date->month = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->month = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
temp_date->day = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->day = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
temp_date->hour = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->hour = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
temp_date->minute = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->minute = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
temp_date->second = gds_convert_unsigend_int16(buffer);
|
||||
temp_date->second = gds_convert_unsigned_int16(buffer);
|
||||
buffer += 2;
|
||||
|
||||
if (temp_date == access_date)
|
||||
@ -509,7 +666,65 @@ static void gds_parse_date(const char *buffer, int length, struct gds_time_field
|
||||
}
|
||||
}
|
||||
|
||||
int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
/**
|
||||
* @brief Convert AREF to a bunch of SREFs and append them to \p container_cell
|
||||
*
|
||||
* This function converts a single array reference (\p aref) to gds_cell_array_instance::rows * gds_cell_array_instance::columns
|
||||
* single references (SREFs). See @ref gds_cell_instance.
|
||||
*
|
||||
* Both gds_cell_array_instance::rows and gds_cell_array_instance::columns must be larger than zero.
|
||||
*
|
||||
* @param[in] aref Array reference to parse
|
||||
* @param[in] container_cell cell to add the converted single references to.
|
||||
*/
|
||||
static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gds_cell *container_cell)
|
||||
{
|
||||
struct gds_point origin;
|
||||
struct gds_point row_shift_vector;
|
||||
struct gds_point col_shift_vector;
|
||||
struct gds_cell_instance *sref_inst = NULL;
|
||||
int col;
|
||||
int row;
|
||||
|
||||
if (!aref || !container_cell)
|
||||
return;
|
||||
|
||||
if (aref->columns == 0 || aref->rows == 0) {
|
||||
GDS_ERROR("Conversion of array instance aborted. No rows / columns.");
|
||||
return;
|
||||
}
|
||||
origin.x = aref->control_points[0].x;
|
||||
origin.y = aref->control_points[0].y;
|
||||
|
||||
row_shift_vector.x = (aref->control_points[2].x - origin.x) / aref->rows;
|
||||
row_shift_vector.y = (aref->control_points[2].y - origin.y) / aref->rows;
|
||||
col_shift_vector.x = (aref->control_points[1].x - origin.x) / aref->columns;
|
||||
col_shift_vector.y = (aref->control_points[1].y - origin.y) / aref->columns;
|
||||
|
||||
/* Iterate over columns and rows */
|
||||
for (col = 0; col < aref->columns; col++) {
|
||||
for (row = 0; row < aref->rows; row++) {
|
||||
/* 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->stats.reference_count++;
|
||||
if (!sref_inst) {
|
||||
GDS_ERROR("Appending cell ref failed!");
|
||||
continue;
|
||||
}
|
||||
|
||||
sref_inst->angle = aref->angle;
|
||||
sref_inst->magnification = aref->magnification;
|
||||
sref_inst->flipped = aref->flipped;
|
||||
strncpy(sref_inst->ref_name, aref->ref_name, CELL_NAME_MAX);
|
||||
sref_inst->origin.x = origin.x + row_shift_vector.x * row + col_shift_vector.x * col;
|
||||
sref_inst->origin.y = origin.y + row_shift_vector.y * row + col_shift_vector.y * col;
|
||||
}
|
||||
}
|
||||
GDS_INF("Converted AREF to SREFs\n");
|
||||
}
|
||||
|
||||
int parse_gds_from_file(const char *filename, GList **library_list,
|
||||
const struct gds_library_parsing_opts *parsing_options)
|
||||
{
|
||||
char *workbuff;
|
||||
int read;
|
||||
@ -522,6 +737,8 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
struct gds_cell *current_cell = NULL;
|
||||
struct gds_graphics *current_graphics = NULL;
|
||||
struct gds_cell_instance *current_s_reference = NULL;
|
||||
struct gds_cell_array_instance *current_a_reference = NULL;
|
||||
struct gds_cell_array_instance temp_a_reference;
|
||||
int x, y;
|
||||
////////////
|
||||
GList *lib_list;
|
||||
@ -558,7 +775,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
}
|
||||
|
||||
rec_data_length = gds_convert_unsigend_int16(workbuff);
|
||||
rec_data_length = gds_convert_unsigned_int16(workbuff);
|
||||
|
||||
if (rec_data_length < 4) {
|
||||
/* Possible Zero-Padding: */
|
||||
@ -581,12 +798,13 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
GDS_ERROR("Unexpected end of file");
|
||||
break;
|
||||
}
|
||||
rec_type = gds_convert_unsigend_int16(workbuff);
|
||||
rec_type = gds_convert_unsigned_int16(workbuff);
|
||||
|
||||
|
||||
/* if begin: Allocate structures */
|
||||
switch (rec_type) {
|
||||
case BGNLIB:
|
||||
lib_list = append_library(lib_list, ¤t_lib);
|
||||
lib_list = append_library(lib_list, parsing_options, ¤t_lib);
|
||||
if (lib_list == NULL) {
|
||||
GDS_ERROR("Allocating memory failed");
|
||||
run = -3;
|
||||
@ -626,7 +844,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
|
||||
current_cell->parent_library = current_lib;
|
||||
|
||||
GDS_INF("Entering Cell\n");
|
||||
GDS_INF("Entering cell\n");
|
||||
break;
|
||||
case ENDSTR:
|
||||
if (current_cell == NULL) {
|
||||
@ -650,15 +868,17 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
current_cell->graphic_objs = append_graphics(current_cell->graphic_objs,
|
||||
(rec_type == BOUNDARY ? GRAPHIC_POLYGON : GRAPHIC_BOX),
|
||||
current_cell->graphic_objs = prepend_graphics(current_cell->graphic_objs,
|
||||
(rec_type == BOUNDARY
|
||||
? GRAPHIC_POLYGON
|
||||
: GRAPHIC_BOX),
|
||||
¤t_graphics);
|
||||
if (current_cell->graphic_objs == NULL) {
|
||||
GDS_ERROR("Memory allocation failed");
|
||||
run = -4;
|
||||
break;
|
||||
}
|
||||
GDS_INF("\tEntering boundary/Box\n");
|
||||
GDS_INF("\tEntering boundary of type %s\n", rec_type==BOUNDARY ? "polygon" : "box");
|
||||
break;
|
||||
case SREF:
|
||||
if (current_cell == NULL) {
|
||||
@ -668,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,
|
||||
¤t_s_reference);
|
||||
current_cell->stats.reference_count++;
|
||||
if (current_cell->child_cells == NULL) {
|
||||
GDS_ERROR("Memory allocation failed");
|
||||
run = -4;
|
||||
@ -682,7 +903,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
current_cell->graphic_objs = append_graphics(current_cell->graphic_objs,
|
||||
current_cell->graphic_objs = prepend_graphics(current_cell->graphic_objs,
|
||||
GRAPHIC_PATH, ¤t_graphics);
|
||||
if (current_cell->graphic_objs == NULL) {
|
||||
GDS_ERROR("Memory allocation failed");
|
||||
@ -693,40 +914,78 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
break;
|
||||
case ENDEL:
|
||||
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;
|
||||
if (current_cell) {
|
||||
current_cell->stats.gfx_count++;
|
||||
}
|
||||
}
|
||||
if (current_s_reference != NULL) {
|
||||
GDS_INF("\tLeaving Reference\n");
|
||||
current_s_reference = NULL;
|
||||
}
|
||||
if (current_a_reference != NULL) {
|
||||
GDS_INF("\tLeaving Array Reference\n");
|
||||
convert_aref_to_sref(current_a_reference, current_cell);
|
||||
current_a_reference = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
case XY:
|
||||
if (current_graphics) {
|
||||
|
||||
} else if (current_s_reference) {
|
||||
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) {
|
||||
if (rec_data_length != (3*(4+4)))
|
||||
GDS_WARN("Array instance has weird coordinates. Rendered output might be wrong!");
|
||||
}
|
||||
break;
|
||||
case AREF:
|
||||
if (current_cell == NULL) {
|
||||
GDS_ERROR("Cell array reference outside of cell");
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
if (current_a_reference != NULL) {
|
||||
GDS_ERROR("Recursive cell array reference");
|
||||
run = -3;
|
||||
break;
|
||||
}
|
||||
|
||||
GDS_INF("Entering Array Reference\n");
|
||||
|
||||
/* Array references are coverted after fully declared. Therefore,
|
||||
* only a static buffer is needed
|
||||
*/
|
||||
current_a_reference = &temp_a_reference;
|
||||
current_a_reference->ref_name[0] = '\0';
|
||||
current_a_reference->angle = 0.0;
|
||||
current_a_reference->magnification = 1.0;
|
||||
current_a_reference->flipped = 0;
|
||||
current_a_reference->rows = 0;
|
||||
current_a_reference->columns = 0;
|
||||
break;
|
||||
case COLROW:
|
||||
case MAG:
|
||||
break;
|
||||
case ANGLE:
|
||||
break;
|
||||
case STRANS:
|
||||
break;
|
||||
case WIDTH:
|
||||
break;
|
||||
case PATHTYPE:
|
||||
break;
|
||||
case UNITS:
|
||||
case LIBNAME:
|
||||
case SNAME:
|
||||
case LAYER:
|
||||
case DATATYPE:
|
||||
case STRNAME:
|
||||
break;
|
||||
default:
|
||||
//GDS_WARN("Record: %04x, len: %u", (unsigned int)rec_type, (unsigned int)rec_data_length);
|
||||
GDS_INF("Unhandled Record: %04x, len: %u\n", (unsigned int)rec_type, (unsigned int)rec_data_length);
|
||||
break;
|
||||
} /* switch(rec_type) */
|
||||
|
||||
@ -744,7 +1003,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
}
|
||||
|
||||
switch (rec_type) {
|
||||
|
||||
case AREF:
|
||||
case HEADER:
|
||||
case ENDLIB:
|
||||
case ENDSTR:
|
||||
@ -756,6 +1015,20 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
case INVALID:
|
||||
break;
|
||||
|
||||
case COLROW:
|
||||
if (!current_a_reference) {
|
||||
GDS_ERROR("COLROW record defined outside of array instance");
|
||||
break;
|
||||
}
|
||||
if (rec_data_length != 4 || read != 4) {
|
||||
GDS_ERROR("COLUMN/ROW count record contains too few data. Won't set column and row counts (%d, %d)",
|
||||
rec_data_length, read);
|
||||
break;
|
||||
}
|
||||
current_a_reference->columns = (int)gds_convert_signed_int16(&workbuff[0]);
|
||||
current_a_reference->rows = (int)gds_convert_signed_int16(&workbuff[2]);
|
||||
GDS_INF("\tRows: %d\n\tColumns: %d\n", current_a_reference->rows, current_a_reference->columns);
|
||||
break;
|
||||
case UNITS:
|
||||
if (!current_lib) {
|
||||
GDS_WARN("Units defined outside of library!\n");
|
||||
@ -797,23 +1070,37 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
current_graphics->vertices =
|
||||
append_vertex(current_graphics->vertices, 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) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
x = gds_convert_signed_int(&workbuff[i*8]);
|
||||
y = gds_convert_signed_int(&workbuff[i*8+4]);
|
||||
current_a_reference->control_points[i].x = x;
|
||||
current_a_reference->control_points[i].y = y;
|
||||
GDS_INF("\tSet control point %d: %d/%d\n", i, x, y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STRANS:
|
||||
if (!current_s_reference) {
|
||||
if (current_s_reference) {
|
||||
current_s_reference->flipped = ((workbuff[0] & 0x80) ? 1 : 0);
|
||||
} else if (current_a_reference) {
|
||||
current_a_reference->flipped = ((workbuff[0] & 0x80) ? 1 : 0);
|
||||
} else {
|
||||
GDS_ERROR("Transformation defined outside of instance");
|
||||
break;
|
||||
}
|
||||
current_s_reference->flipped = ((workbuff[0] & 0x80) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case SNAME:
|
||||
if (current_s_reference) {
|
||||
name_cell_ref(current_s_reference, (unsigned int)read, workbuff);
|
||||
} else if (current_a_reference) {
|
||||
name_array_cell_ref(current_a_reference, (unsigned int)read, workbuff);
|
||||
} else {
|
||||
GDS_ERROR("reference name set outside of cell reference.\n");
|
||||
GDS_ERROR("Reference name set outside of cell reference");
|
||||
}
|
||||
break;
|
||||
case WIDTH:
|
||||
@ -833,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);
|
||||
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:
|
||||
if (rec_data_length != 8) {
|
||||
GDS_WARN("Magnification is not an 8 byte real. Results may be wrong");
|
||||
@ -846,12 +1143,16 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
current_s_reference->magnification = gds_convert_double(workbuff);
|
||||
GDS_INF("\t\tMagnification defined: %lf\n", current_s_reference->magnification);
|
||||
}
|
||||
if (current_a_reference != NULL) {
|
||||
current_a_reference->magnification = gds_convert_double(workbuff);
|
||||
GDS_INF("\t\tMagnification defined: %lf\n", current_a_reference->magnification);
|
||||
}
|
||||
break;
|
||||
case ANGLE:
|
||||
if (rec_data_length != 8) {
|
||||
GDS_WARN("Angle is not an 8 byte real. Results may be wrong");
|
||||
}
|
||||
if (current_graphics != NULL && current_s_reference != NULL) {
|
||||
if (current_graphics != NULL && current_s_reference != NULL && current_a_reference != NULL) {
|
||||
GDS_ERROR("Open Graphics and Cell Reference\n\tMissing ENDEL?");
|
||||
run = -6;
|
||||
break;
|
||||
@ -860,6 +1161,10 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
current_s_reference->angle = gds_convert_double(workbuff);
|
||||
GDS_INF("\t\tAngle defined: %lf\n", current_s_reference->angle);
|
||||
}
|
||||
if (current_a_reference != NULL) {
|
||||
current_a_reference->angle = gds_convert_double(workbuff);
|
||||
GDS_INF("\t\tAngle defined: %lf\n", current_a_reference->angle);
|
||||
}
|
||||
break;
|
||||
case PATHTYPE:
|
||||
if (current_graphics == NULL) {
|
||||
@ -883,8 +1188,13 @@ int parse_gds_from_file(const char *filename, GList **library_list)
|
||||
if (!run) {
|
||||
/* Iterate and find references to cells */
|
||||
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;
|
||||
|
||||
free(workbuff);
|
||||
|
93
gds-utils/gds-statistics.c
Normal file
93
gds-utils/gds-statistics.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
@ -21,7 +21,7 @@
|
||||
* @file gds-tree-checker.c
|
||||
* @brief Checking functions of a cell tree
|
||||
*
|
||||
* This file contains cehcking functions for the GDS cell tree.
|
||||
* This file contains checking functions for the GDS cell tree.
|
||||
* These functions include checks if all child references could be resolved,
|
||||
* and if the cell tree contains loops.
|
||||
*
|
||||
@ -34,7 +34,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gds-render/gds-utils/gds-tree-checker.h>
|
||||
|
||||
int gds_tree_check_cell_references(struct gds_library *lib)
|
||||
@ -54,7 +54,7 @@ int gds_tree_check_cell_references(struct gds_library *lib)
|
||||
|
||||
/* Check if this list element is broken. This should never happen */
|
||||
if (!cell) {
|
||||
fprintf(stderr, "Broken cell list item found. Will continue.\n");
|
||||
fprintf(stderr, _("Broken cell list item found. Will continue.\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ int gds_tree_check_cell_references(struct gds_library *lib)
|
||||
|
||||
/* Check if broken. This should not happen */
|
||||
if (!cell_inst) {
|
||||
fprintf(stderr, "Broken cell list item found in cell %s. Will continue.\n",
|
||||
fprintf(stderr, _("Broken cell list item found in cell %s. Will continue.\n"),
|
||||
cell->name);
|
||||
continue;
|
||||
}
|
||||
@ -90,7 +90,8 @@ int gds_tree_check_cell_references(struct gds_library *lib)
|
||||
* @param cell Cell to check for
|
||||
* @return 0 if cell is not in list. 1 if cell is in list
|
||||
*/
|
||||
static int gds_tree_check_list_contains_cell(GList *list, struct gds_cell *cell) {
|
||||
static int gds_tree_check_list_contains_cell(GList *list, struct gds_cell *cell)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = list; iter != NULL; iter = g_list_next(iter)) {
|
||||
@ -177,13 +178,16 @@ int gds_tree_check_reference_loops(struct gds_library *lib)
|
||||
res = gds_tree_check_iterate_ref_and_check(cell_to_check, &visited_cells);
|
||||
|
||||
if (visited_cells) {
|
||||
/* If cell contains no loop, print error when list not empty.
|
||||
/*
|
||||
* If cell contains no loop, print error when list not empty.
|
||||
* In case of a loop, it is completely normal that the list is not empty,
|
||||
* due to the instant return from gds_tree_check_iterate_ref_and_check()
|
||||
*/
|
||||
if (res == 0)
|
||||
fprintf(stderr, "Visited cell list should be empty. This is a bug. Please report this.\n");
|
||||
fprintf(stderr,
|
||||
_("Visited cell list should be empty. This is a bug. Please report this.\n"));
|
||||
g_list_free(visited_cells);
|
||||
visited_cells = NULL;
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
|
@ -33,11 +33,11 @@
|
||||
|
||||
#include <gds-render/geometric/bounding-box.h>
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) /**< @brief Return smaller number */
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) /**< @brief Return bigger number */
|
||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
||||
|
||||
void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
return;
|
||||
@ -91,6 +91,17 @@ void bounding_box_prepare_empty(union bounding_box *box)
|
||||
box->vectors.upper_right.y = -DBL_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate path miter points for a pathwith a \p width and the anchors \p a \p b \p c.
|
||||
* @param[in] a
|
||||
* @param[in] b
|
||||
* @param[in] c
|
||||
* @param[out] m1
|
||||
* @param[out] m2
|
||||
* @param[in] width
|
||||
* @return Miter points in \p m1 and \p m2
|
||||
* @note This function is currently unused (and untested). Ignore any compiler warning regarding this function.
|
||||
*/
|
||||
static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b, struct vector_2d *c,
|
||||
struct vector_2d *m1, struct vector_2d *m2, double width)
|
||||
{
|
||||
@ -134,14 +145,12 @@ static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b
|
||||
vector_2d_subtract(m2, m2, &v_vec);
|
||||
}
|
||||
|
||||
void bounding_box_calculate_path_box(GList *vertices, double thickness,
|
||||
void bounding_box_update_with_path(GList *vertices, double thickness,
|
||||
conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
|
||||
{
|
||||
GList *vertex_iterator;
|
||||
struct vector_2d pt;
|
||||
|
||||
printf("Warning! Function bounding_box_calculate_path_box not yet implemented correctly!\n");
|
||||
|
||||
if (!vertices || !box)
|
||||
return;
|
||||
|
||||
@ -162,7 +171,7 @@ void bounding_box_calculate_path_box(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;
|
||||
|
||||
@ -180,24 +189,40 @@ void bounding_box_update_point(union bounding_box *destination, conv_generic_to_
|
||||
destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply transformations onto bounding box.
|
||||
* @param scale Scaling factor
|
||||
* @param rotation_deg Roation of bounding box around the origin in degrees (counterclockwise)
|
||||
* @param flip_at_x Flip the boundig box on the x axis before rotating.
|
||||
* @param box Bounding box the operations should be applied to.
|
||||
*/
|
||||
void bounding_box_get_all_points(struct vector_2d *points, union bounding_box *box)
|
||||
{
|
||||
if (!points || !box)
|
||||
return;
|
||||
|
||||
points[0].x = box->vectors.lower_left.x;
|
||||
points[0].y = box->vectors.lower_left.y;
|
||||
points[1].x = box->vectors.upper_right.x;
|
||||
points[1].y = box->vectors.lower_left.y;
|
||||
points[2].x = box->vectors.upper_right.x;
|
||||
points[2].y = box->vectors.upper_right.y;
|
||||
points[3].x = box->vectors.lower_left.x;
|
||||
points[3].y = box->vectors.upper_right.y;
|
||||
}
|
||||
|
||||
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box)
|
||||
{
|
||||
int i;
|
||||
struct vector_2d input_points[4];
|
||||
|
||||
/* Due to linearity, the order of the operations does not matter.
|
||||
* flip must be applied before rotation as defined by the GDS format
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
box->vector_array[i].y *= (flip_at_x ? -1 : 1);
|
||||
vector_2d_rotate(&box->vector_array[i], rotation_deg * M_PI / 180);
|
||||
vector_2d_scale(&box->vector_array[i], scale);
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
bounding_box_get_all_points(input_points, box);
|
||||
|
||||
/* Reset box */
|
||||
bounding_box_prepare_empty(box);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
input_points[i].y *= (flip_at_x ? -1 : 1);
|
||||
vector_2d_rotate(&input_points[i], rotation_deg * M_PI / 180.0);
|
||||
vector_2d_scale(&input_points[i], scale);
|
||||
|
||||
bounding_box_update_with_point(box, NULL, &input_points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf
|
||||
case GRAPHIC_BOX:
|
||||
/* Expected fallthrough */
|
||||
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,
|
||||
¤t_box);
|
||||
break;
|
||||
@ -63,7 +63,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf
|
||||
* Please be aware if paths are the outmost elements of your cell.
|
||||
* You might end up with a completely wrong calculated cell size.
|
||||
*/
|
||||
bounding_box_calculate_path_box(gfx->vertices, gfx->width_absolute,
|
||||
bounding_box_update_with_path(gfx->vertices, gfx->width_absolute,
|
||||
(conv_generic_to_vector_2d_t)&convert_gds_point_to_2d_vector,
|
||||
¤t_box);
|
||||
break;
|
||||
@ -74,7 +74,7 @@ static void update_box_with_gfx(union bounding_box *box, struct gds_graphics *gf
|
||||
}
|
||||
|
||||
/* Update box with results */
|
||||
bounding_box_update_box(box, ¤t_box);
|
||||
bounding_box_update_with_box(box, ¤t_box);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* update the parent's box */
|
||||
bounding_box_update_box(box, &temp_box);
|
||||
bounding_box_update_with_box(box, &temp_box);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include <gds-render/geometric/vector-operations.h>
|
||||
|
||||
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
|
||||
#define ABS_DBL(a) ((a) < 0.0 ? -(a) : (a))
|
||||
|
||||
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
@ -46,9 +46,10 @@ double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)
|
||||
void vector_2d_normalize(struct vector_2d *vec)
|
||||
{
|
||||
double len;
|
||||
|
||||
if (!vec)
|
||||
return;
|
||||
len = sqrt(pow(vec->x,2)+pow(vec->y,2));
|
||||
len = sqrt(pow(vec->x, 2) + pow(vec->y, 2));
|
||||
vec->x = vec->x/len;
|
||||
vec->y = vec->y/len;
|
||||
}
|
||||
@ -64,7 +65,7 @@ void vector_2d_rotate(struct vector_2d *vec, double angle)
|
||||
sin_val = sin(angle);
|
||||
cos_val = cos(angle);
|
||||
|
||||
vector_2d_copy(&temp, vec);
|
||||
(void)vector_2d_copy(&temp, vec);
|
||||
|
||||
/* Apply rotation matrix */
|
||||
vec->x = (cos_val * temp.x) - (sin_val * temp.y);
|
||||
@ -97,9 +98,8 @@ struct vector_2d *vector_2d_alloc(void)
|
||||
|
||||
void vector_2d_free(struct vector_2d *vec)
|
||||
{
|
||||
if (vec) {
|
||||
if (vec)
|
||||
free(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void vector_2d_scale(struct vector_2d *vec, double scale)
|
||||
@ -114,9 +114,9 @@ void vector_2d_scale(struct vector_2d *vec, double scale)
|
||||
double vector_2d_abs(struct vector_2d *vec)
|
||||
{
|
||||
double len = 0.0;
|
||||
if (vec) {
|
||||
len = sqrt(pow(vec->x,2)+pow(vec->y,2));
|
||||
}
|
||||
|
||||
if (vec)
|
||||
len = sqrt(pow(vec->x, 2) + pow(vec->y, 2));
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ void vector_2d_subtract(struct vector_2d *res, struct vector_2d *a, struct vecto
|
||||
void vector_2d_add(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b)
|
||||
{
|
||||
if (res && a && b) {
|
||||
res->x = a->x +b->x;
|
||||
res->x = a->x + b->x;
|
||||
res->y = a->y + b->y;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
add_custom_target(glib-resources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resources.c)
|
||||
add_custom_command(DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.glade
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/resources.xml
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resources.c
|
||||
COMMAND
|
||||
glib-compile-resources --target="${CMAKE_CURRENT_BINARY_DIR}/resources.c" --sourcedir="${CMAKE_CURRENT_SOURCE_DIR}" --generate-source "${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
|
||||
)
|
224
glade/main.glade
224
glade/main.glade
@ -1,224 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-up</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-go-down</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="main-window">
|
||||
<property name="height_request">250</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">gds-render</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header-bar">
|
||||
<property name="name">header</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">GDS Renderer</property>
|
||||
<property name="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="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>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-save-mapping">
|
||||
<property name="label" translatable="yes">Save Mapping</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="convert-button">
|
||||
<property name="label">gtk-convert</property>
|
||||
<property name="name">button-convert</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="cell-search">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_name">edit-find-symbolic</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="cell-tree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="enable_search">False</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-up-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">image1</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-down-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">image2</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="layer-list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="selection_mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/">
|
||||
<file compressed="true">main.glade</file>
|
||||
<file compressed="true">about.glade</file>
|
||||
<file>layer-widget.glade</file>
|
||||
<file>dialog.glade</file>
|
||||
<file compressed="true" alias="logo.svg">../icon/gds-render.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
|
56
include/gds-render/cell-selector/cell-statistics-renderer.h
Normal file
56
include/gds-render/cell-selector/cell-statistics-renderer.h
Normal 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_ */
|
||||
|
||||
/** @} */
|
@ -34,27 +34,50 @@
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Convert GDS according to supplied parameters
|
||||
* @param gds_name GDS File path
|
||||
* @param pdf_name Cairo-PDF path
|
||||
* @param tex_name TeX/TikZ path
|
||||
* @param pdf Render Cairo
|
||||
* @param tex Render LaTeX
|
||||
* @param layer_file Layer mapping file
|
||||
* @param cell_name Cell name to render
|
||||
* @param scale Scale image down by this value
|
||||
* @param pdf_layers TikZ creates OCG layers
|
||||
* @param pdf_standalone LaTeX document is standalone7
|
||||
* @param svg Render to SVG file
|
||||
* @param so_name Path to shared object of custom renderer
|
||||
* @param so_out_file Output file path for custom renderer
|
||||
* @param svg_name SVG file name
|
||||
*
|
||||
* @note This function is pretty damn retarded (Lots of parameters). Will be reworked when generating GObjects for renderers.
|
||||
* @brief External renderer paramameters to command line renderer
|
||||
*/
|
||||
void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gboolean pdf, gboolean tex,
|
||||
char *layer_file, char *cell_name, double scale, gboolean pdf_layers,
|
||||
gboolean pdf_standalone, gboolean svg, char *svg_name, char *so_name, char *so_out_file);
|
||||
struct external_renderer_params {
|
||||
/**
|
||||
* @brief Path to shared object
|
||||
*/
|
||||
char *so_path;
|
||||
|
||||
/**
|
||||
* @brief Command line parameters given
|
||||
*/
|
||||
char *cli_params;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Convert GDS according to command line parameters
|
||||
* @param gds_name Path to GDS File
|
||||
* @param cell_name Cell name
|
||||
* @param renderers Renderer ids
|
||||
* @param output_file_names Output file names
|
||||
* @param layer_file Layer mapping file
|
||||
* @param ext_param Settings for external library renderer
|
||||
* @param tex_standalone Standalone TeX
|
||||
* @param tex_layers TeX OCR layers
|
||||
* @param scale Scale value
|
||||
* @return Error code, 0 if successful
|
||||
*/
|
||||
int command_line_convert_gds(const char *gds_name,
|
||||
const char *cell_name,
|
||||
char **renderers,
|
||||
char **output_file_names,
|
||||
const char *layer_file,
|
||||
struct external_renderer_params *ext_param,
|
||||
gboolean tex_standalone,
|
||||
gboolean tex_layers,
|
||||
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_ */
|
||||
|
||||
|
@ -23,21 +23,37 @@
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _GDSPARSER_H_
|
||||
#define _GDSPARSER_H_
|
||||
|
||||
/**
|
||||
* @addtogroup GDS-Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GDSPARSER_H_
|
||||
#define _GDSPARSER_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
|
||||
|
||||
int parse_gds_from_file(const char *filename, GList **library_array);
|
||||
/**
|
||||
* @brief Parse a GDS file
|
||||
*
|
||||
* This function parses a GDS File and creates a list of libraries,
|
||||
* which then contain the different cells.
|
||||
*
|
||||
* The function appends The detected libraries to the \p library_array list.
|
||||
* The library array may be empty, meaning *library_list may be NULL.
|
||||
*
|
||||
* @param[in] filename Path to the GDS file
|
||||
* @param[in,out] library_array GList Pointer.
|
||||
* @param[in] parsing_options Parsing options.
|
||||
* @return 0 if successful
|
||||
*/
|
||||
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.
|
||||
* @param library_list Pointer to a list of #gds_library. Is set to NULL after completion.
|
||||
@ -47,4 +63,4 @@ int clear_lib_list(GList **library_list);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _GDSPARSE_H_ */
|
||||
#endif /* _GDSPARSER_H_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
@ -18,16 +18,25 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-info.c
|
||||
* @brief Helper functions for layer info struct
|
||||
* @file gds-parser.h
|
||||
* @brief Header file for the GDS statistics
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include <gds-render/layer/layer-info.h>
|
||||
#ifndef _GDS_STATISTICS_H_
|
||||
#define _GDS_STATISTICS_H_
|
||||
|
||||
void layer_info_delete_struct(struct layer_info *info)
|
||||
{
|
||||
if (info)
|
||||
free(info);
|
||||
}
|
||||
/**
|
||||
* @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_ */
|
@ -58,13 +58,29 @@ enum graphics_type
|
||||
enum path_type {PATH_FLUSH = 0, PATH_ROUNDED = 1, PATH_SQUARED = 2}; /**< Path line caps */
|
||||
|
||||
/**
|
||||
* @brief A point in the 2D plane. Sometimes references as vertex
|
||||
* @brief A point in the 2D plane. Sometimes referred to as vertex
|
||||
*/
|
||||
struct gds_point {
|
||||
int x;
|
||||
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.
|
||||
*/
|
||||
@ -101,7 +117,7 @@ struct gds_graphics {
|
||||
enum path_type path_render_type; /**< @brief Line cap */
|
||||
int width_absolute; /**< @brief Width. Not used for objects other than paths */
|
||||
int16_t layer; /**< @brief Layer the graphic object is on */
|
||||
uint16_t datatype;
|
||||
int16_t datatype; /**< @brief Data type of graphic object */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,6 +143,14 @@ struct gds_cell {
|
||||
GList *graphic_objs; /**< @brief List of #gds_graphics */
|
||||
struct gds_library *parent_library; /**< @brief Pointer to parent library */
|
||||
struct gds_cell_checks checks; /**< @brief Checking results */
|
||||
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];
|
||||
struct gds_time_field mod_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 */
|
||||
GList *cells; /**< List of #gds_cell that contains all cells in this library*/
|
||||
GList *cell_names /**< List of strings that contains all cell names */;
|
||||
struct gds_lib_statistics stats;
|
||||
};
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __GDS_TYPES_H__ */
|
||||
|
@ -35,23 +35,118 @@
|
||||
#include <gds-render/geometric/vector-operations.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 {
|
||||
/** 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 {
|
||||
/** @brief Lower left point of the bounding box */
|
||||
struct vector_2d lower_left;
|
||||
/** @brief Upper right point of the bounding box */
|
||||
struct vector_2d upper_right;
|
||||
} vectors;
|
||||
/**
|
||||
* @brief Array of vectors representing a bounding box
|
||||
* @note This is more convenient for iterating
|
||||
*/
|
||||
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 *);
|
||||
|
||||
void bounding_box_calculate_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);
|
||||
void bounding_box_update_box(union bounding_box *destination, union bounding_box *update);
|
||||
/**
|
||||
* @brief Calculate bounding box of polygon
|
||||
* @param vertices List of vertices that describe the polygon
|
||||
* @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
|
||||
*/
|
||||
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.
|
||||
* @param destination Target box to update
|
||||
* @param update Box to update the target with
|
||||
*/
|
||||
void bounding_box_update_with_box(union bounding_box *destination, union bounding_box *update);
|
||||
|
||||
/**
|
||||
* @brief Prepare an empty bounding box.
|
||||
*
|
||||
* Updating this specially prepared box, results in a bounding box that is the same size as the update
|
||||
*
|
||||
* @param box Box to preapre
|
||||
*/
|
||||
void bounding_box_prepare_empty(union bounding_box *box);
|
||||
void bounding_box_update_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt);
|
||||
|
||||
/**
|
||||
* @brief Update bounding box with a point
|
||||
* @param destination Bounding box to update
|
||||
* @param conv_func Conversion function to convert \p pt to a vector_2d. May be NULL
|
||||
* @param pt Point to update bounding box with
|
||||
*/
|
||||
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
|
||||
* @param[out] points Array of 4 vector_2d structs that has to be allocated by the caller
|
||||
* @param box Bounding box
|
||||
*/
|
||||
void bounding_box_get_all_points(struct vector_2d *points, union bounding_box *box);
|
||||
|
||||
/**
|
||||
* @brief Apply transformations onto bounding box.
|
||||
*
|
||||
* All corner points \f$ \vec{P_i} \f$ of the bounding box are transformed to output points \f$ \vec{P_o} \f$ by:
|
||||
*
|
||||
* \f$ \vec{P_o} = s \cdot \begin{pmatrix}\cos\left(\phi\right) & -\sin\left(\phi\right)\\ \sin\left(\phi\right) & \cos\left(\phi\right)\end{pmatrix} \cdot \begin{pmatrix} 1 & 0 \\ 0 & -1^{m} \end{pmatrix} \cdot \vec{P_i} \f$, with:
|
||||
*
|
||||
* * \f$s\f$: Scale
|
||||
* * \f$m\f$: 1, if flipped_at_x is True, else 0
|
||||
* * \f$\phi\f$: Rotation angle in radians. The conversion degrees => radians is done internally
|
||||
*
|
||||
* The result is the bounding box generated around all output points
|
||||
*
|
||||
* @param scale Scaling factor
|
||||
* @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 box Bounding box the operations should be applied to.
|
||||
* @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.
|
||||
*/
|
||||
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box);
|
||||
void bounding_box_calculate_path_box(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box);
|
||||
|
||||
/**
|
||||
* @brief Calculate the bounding box of a path and update the given bounding box
|
||||
* @param vertices Vertices the path is made up of
|
||||
* @param thickness Thisckness of the path
|
||||
* @param conv_func Conversion function for vertices to vector_2d structs
|
||||
* @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);
|
||||
|
||||
#endif /* _BOUNDING_BOX_H_ */
|
||||
|
||||
|
@ -35,10 +35,17 @@
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
/**
|
||||
* @brief calculate_cell_bounding_box Calculate bounding box of gds cell
|
||||
* @param box Resulting boundig box. Will be uüdated and not overwritten
|
||||
* @brief Calculate bounding box of a gds cell.
|
||||
*
|
||||
* 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
|
||||
* @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);
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file latex-output.h
|
||||
* @brief LaTeX output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef __LATEX_OUTPUT_H__
|
||||
#define __LATEX_OUTPUT_H__
|
||||
|
||||
/**
|
||||
* @addtogroup LaTeX-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gds-render/layer/layer-info.h"
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
#define LATEX_LINE_BUFFER_KB (10) /**< @brief Buffer for LaTeX Code line in KiB */
|
||||
|
||||
/**
|
||||
* @brief Render \p cell to LateX/TikZ code
|
||||
* @param cell Cell to render
|
||||
* @param layer_infos Layer information
|
||||
* @param tex_file Already opened file to write data in
|
||||
* @param scale Scale image down by this value
|
||||
* @param create_pdf_layers Optional content groups used
|
||||
* @param standalone_document document can be compiled standalone
|
||||
*/
|
||||
void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
|
||||
gboolean create_pdf_layers, gboolean standalone_document);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __LATEX_OUTPUT_H__ */
|
70
include/gds-render/layer/color-palette.h
Normal file
70
include/gds-render/layer/color-palette.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file color-palette.h
|
||||
* @brief Class representing a color palette
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _COLOR_PALETTE_H_
|
||||
#define _COLOR_PALETTE_H_
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(ColorPalette, color_palette, GDS_RENDER, COLOR_PALETTE, GObject);
|
||||
|
||||
#define TYPE_GDS_RENDER_COLOR_PALETTE (color_palette_get_type())
|
||||
|
||||
/**
|
||||
* @brief Create a new object with from a resource containing the html hex color scheme
|
||||
* @param resource_name Name of the resource
|
||||
* @return New object
|
||||
*/
|
||||
ColorPalette *color_palette_new_from_resource(char *resource_name);
|
||||
|
||||
/**
|
||||
* @brief Get the n-th color in the palette identified by the index.
|
||||
*
|
||||
* This function fills the nth color into the supplied \p color.
|
||||
* \p color is returned.
|
||||
*
|
||||
* If \p color is NULL, a new GdkRGBA is created and returned.
|
||||
* This element must be freed afterwards.
|
||||
*
|
||||
* @param palette Color palette
|
||||
* @param color GdkRGBA struct to fill data in. May be NULL.
|
||||
* @param index Index of color. Starts at 0
|
||||
* @return GdkRGBA color. If \p color is NULL, the returned color must be freed afterwards
|
||||
*/
|
||||
GdkRGBA *color_palette_get_color(ColorPalette *palette, GdkRGBA *color, unsigned int index);
|
||||
|
||||
/**
|
||||
* @brief Return amount of stored colors in \p palette
|
||||
* @param palette Color palette
|
||||
* @return Count of colors
|
||||
*/
|
||||
unsigned int color_palette_get_color_count(ColorPalette *palette);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _COLOR_PALETTE_H_ */
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-info.h
|
||||
* @brief Helper functions and definition of layer info struct
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _LAYER_INFO_H_
|
||||
#define _LAYER_INFO_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* @brief Layer information.
|
||||
*
|
||||
* This structs contains information on how to render a layer
|
||||
*/
|
||||
struct layer_info
|
||||
{
|
||||
int layer; /**< @brief Layer number */
|
||||
char *name; /**< @brief Layer name */
|
||||
int stacked_position; ///< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top
|
||||
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Delete a layer_info struct
|
||||
* @param info Struct to be deleted.
|
||||
* @note The layer_info::name Element has to be freed manually
|
||||
*/
|
||||
void layer_info_delete_struct(struct layer_info *info);
|
||||
|
||||
#endif // _LAYER_INFO_H_
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include <gds-render/layer/color-palette.h>
|
||||
#include <gds-render/layer/layer-settings.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -79,9 +81,9 @@ void layer_selector_set_save_mapping_button(LayerSelector *selector, GtkWidget *
|
||||
/**
|
||||
* @brief Get a list of all layers that shall be exported when rendering the cells
|
||||
* @param selector Layer selector instance
|
||||
* @return List of layer_info structures containing the layer information
|
||||
* @return LayerSettings containing the layer information
|
||||
*/
|
||||
GList *layer_selector_export_rendered_layer_info(LayerSelector *selector);
|
||||
LayerSettings *layer_selector_export_rendered_layer_info(LayerSelector *selector);
|
||||
|
||||
/**
|
||||
* @brief Force the layer selector list to be sorted according to \p sort_function
|
||||
@ -90,6 +92,51 @@ GList *layer_selector_export_rendered_layer_info(LayerSelector *selector);
|
||||
*/
|
||||
void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function);
|
||||
|
||||
/**
|
||||
* @brief Set 'export' value of all layers in the LayerSelector to the supplied select value
|
||||
* @param layer_selector LayerSelector object
|
||||
* @param select
|
||||
*/
|
||||
void layer_selector_select_all_layers(LayerSelector *layer_selector, gboolean select);
|
||||
|
||||
/**
|
||||
* @brief Apply colors from palette to all layers. Aditionally set alpha
|
||||
* @param layer_selector LayerSelector object
|
||||
* @param palette Color palette to use
|
||||
* @param global_alpha Additional alpha value that is applied to all layers. Must be > 0
|
||||
*/
|
||||
void layer_selector_auto_color_layers(LayerSelector *layer_selector, ColorPalette *palette, double global_alpha);
|
||||
|
||||
/**
|
||||
* @brief Auto name all layers in the layer selector.
|
||||
*
|
||||
* This functions sets the name of the layer equal to its number.
|
||||
* The \p overwrite parameter specifies if already set layer names are overwritten.
|
||||
*
|
||||
* @param layer_selector LayerSelector
|
||||
* @param overwrite Overwrite existing layer names
|
||||
*/
|
||||
void layer_selector_auto_name_layers(LayerSelector *layer_selector, gboolean overwrite);
|
||||
|
||||
/**
|
||||
* @brief Check if the given layer selector contains layer elements.
|
||||
*
|
||||
* This function checks whether there are elements present.
|
||||
* If an invalid object pointer \p layer_selector is passed,
|
||||
* the function returns FALSE
|
||||
*
|
||||
* @param[in] layer_selector Selector to check
|
||||
* @return True, if there is at least one layer present inside the 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
|
||||
|
||||
#endif /* __LAYER_SELECTOR_H__ */
|
||||
|
123
include/gds-render/layer/layer-settings.h
Normal file
123
include/gds-render/layer/layer-settings.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-settings.h
|
||||
* @brief LayerSettings class header file
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _LAYER_INFO_H_
|
||||
#define _LAYER_INFO_H_
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Layer information.
|
||||
*
|
||||
* This structs contains information on how to render a layer
|
||||
* @note You probably don't want to use this struct standalone but in combination
|
||||
* with a LayerSettings object.
|
||||
*/
|
||||
struct layer_info
|
||||
{
|
||||
int layer; /**< @brief Layer number */
|
||||
char *name; /**< @brief Layer name. */
|
||||
int stacked_position; /**< @brief Position of layer in output @warning This parameter is not used by any renderer so far @note Lower is bottom, higher is top */
|
||||
GdkRGBA color; /**< @brief RGBA color used to render this layer */
|
||||
int render; /**< @brief true: Render to output */
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE(LayerSettings, layer_settings, GDS_RENDER, LAYER_SETTINGS, GObject)
|
||||
|
||||
#define GDS_RENDER_TYPE_LAYER_SETTINGS (layer_settings_get_type())
|
||||
|
||||
/**
|
||||
* @brief Maximum length of a layer mapping CSV line
|
||||
*/
|
||||
#define CSV_LINE_MAX_LEN (1024)
|
||||
|
||||
/**
|
||||
* @brief New LayerSettings object
|
||||
* @return New object
|
||||
*/
|
||||
LayerSettings *layer_settings_new();
|
||||
|
||||
/**
|
||||
* @brief layer_settings_append_layer_info
|
||||
* @param settings LayerSettings object.
|
||||
* @param info Info to append
|
||||
* @return Error code. 0 if successful
|
||||
* @note \p info is copied internally. You can free this struct afterwards.
|
||||
*/
|
||||
int layer_settings_append_layer_info(LayerSettings *settings, struct layer_info *info);
|
||||
|
||||
/**
|
||||
* @brief Clear all layers in this settings object
|
||||
* @param settings LayerSettings object
|
||||
*/
|
||||
void layer_settings_clear(LayerSettings *settings);
|
||||
|
||||
/**
|
||||
* @brief Remove a specific layer number from the layer settings.
|
||||
* @param settings LayerSettings object
|
||||
* @param layer Layer number
|
||||
* @return Error code. 0 if successful
|
||||
*/
|
||||
int layer_settings_remove_layer(LayerSettings *settings, int layer);
|
||||
|
||||
/**
|
||||
* @brief Get a GList with layer_info structs
|
||||
*
|
||||
* This function returns a GList with all layer_info structs in rendering order
|
||||
* (bottom to top) that shall be rendered.
|
||||
*
|
||||
* @param settings LayerSettings object
|
||||
* @return GList with struct layer_info elements.
|
||||
*/
|
||||
GList *layer_settings_get_layer_info_list(LayerSettings *settings);
|
||||
|
||||
/**
|
||||
* @brief Write layer settings to a CSV file.
|
||||
*
|
||||
* This function writes the layer settings to a CSV file according to the
|
||||
* layer mapping specification (@ref lmf-spec)
|
||||
* @param settings LayerSettings object
|
||||
* @param path Output path for CSV file.
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int layer_settings_to_csv(LayerSettings *settings, const char *path);
|
||||
|
||||
/**
|
||||
* @brief Load new layer Settings from CSV
|
||||
*
|
||||
* This function loads the layer information from a CSV file.
|
||||
* All data inside the \p settings is cleared beforehand.
|
||||
*
|
||||
* @param settings Settings to write to.
|
||||
* @param path CSV file path
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int layer_settings_load_from_csv(LayerSettings *settings, const char *path);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // _LAYER_INFO_H_
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mapping-parser.h
|
||||
* @brief Function to read a mapping file line and parse it.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef __MAPPING_PARSER_H__
|
||||
#define __MAPPING_PARSER_H__
|
||||
|
||||
/**
|
||||
* @addtogroup Mapping-Parser
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <gds-render/widgets/layer-element.h>
|
||||
|
||||
/**
|
||||
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||
* @param stream Input data stream
|
||||
* @param export Layer shall be exported
|
||||
* @param name Layer name. Free returned pointer after using.
|
||||
* @param layer Layer number
|
||||
* @param color RGBA color.
|
||||
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
||||
*/
|
||||
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
|
||||
|
||||
/**
|
||||
* @brief Create Line for LayerMapping file with supplied information
|
||||
* @param layer_element information
|
||||
* @param line_buffer buffer to write to
|
||||
* @param max_len Maximum length that cna be used in \p line_buffer
|
||||
*/
|
||||
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __MAPPING_PARSER_H__ */
|
@ -17,7 +17,7 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file cairo-output.h
|
||||
* @file cairo-renderer.h
|
||||
* @brief Header File for Cairo output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
@ -25,24 +25,36 @@
|
||||
#define _CAIRO_OUTPUT_H_
|
||||
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
#include <gds-render/layer/layer-info.h>
|
||||
#include <gds-render/output-renderers/gds-output-renderer.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/** @addtogroup Cairo-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define MAX_LAYERS (300) /**< \brief Maximum layer count the output renderer can process. Typically GDS only specifies up to 255 layers.*/
|
||||
G_DECLARE_FINAL_TYPE(CairoRenderer, cairo_renderer, GDS_RENDER, CAIRO_RENDERER, GdsOutputRenderer)
|
||||
|
||||
#define GDS_RENDER_TYPE_CAIRO_RENDERER (cairo_renderer_get_type())
|
||||
|
||||
#define MAX_LAYERS (5000) /**< \brief Maximum layer count the output renderer can process. Typically GDS only specifies up to 255 layers.*/
|
||||
|
||||
/**
|
||||
* @brief Render \p cell to a PDF file specified by \p pdf_file
|
||||
* @param cell Toplevel cell to @ref Cairo-Renderer
|
||||
* @param layer_infos List of layer information. Specifies color and layer stacking
|
||||
* @param pdf_file PDF output file. Set to NULL if no PDF file has to be generated
|
||||
* @param svg_file SVG output file. Set to NULL if no SVG file has to be generated
|
||||
* @param scale Scale the output image down by \p scale
|
||||
* @brief Create new CairoRenderer for SVG output
|
||||
* @return New object
|
||||
*/
|
||||
void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale);
|
||||
CairoRenderer *cairo_renderer_new_svg();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create new CairoRenderer for PDF output
|
||||
* @return New object
|
||||
*/
|
||||
CairoRenderer *cairo_renderer_new_pdf();
|
||||
|
||||
/** @} */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CAIRO_OUTPUT_H_ */
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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__
|
||||
#define __EXTERNAL_RENDERER_INTERFACES_H__
|
||||
|
||||
#ifndef xstr
|
||||
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
|
||||
#endif /* xstr */
|
||||
|
||||
/**
|
||||
* @addtogroup ExternalRenderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This define is used to export a function from a shared object
|
||||
*/
|
||||
#define EXPORT_FUNC __attribute__((visibility("default")))
|
||||
|
||||
/**
|
||||
* @brief Function name expected to be found in external library for rendering.
|
||||
*
|
||||
* The function has to be defined as follows:
|
||||
* @code
|
||||
* int EXTERNAL_LIBRARY_RENDER_FUNCTION(struct gds_cell *toplevel, GList *layer_info_list, const char *output_file_name, double scale);
|
||||
* @endcode
|
||||
*/
|
||||
#define EXTERNAL_LIBRARY_RENDER_FUNCTION exported_render_cell_to_file
|
||||
|
||||
/**
|
||||
* @brief Function name expected to be found in external library for initialization.
|
||||
*
|
||||
* @code
|
||||
* int EXTERNAL_LIBRARY_INIT_FUNCTION(const char *option_string, const char *version_string);
|
||||
* @endcode
|
||||
*/
|
||||
#define EXTERNAL_LIBRARY_INIT_FUNCTION exported_init
|
||||
|
||||
/**
|
||||
* @brief Global integer specified by an external renderer to signal, that the init and render functions shall be executed in a subprocess
|
||||
*
|
||||
* The pure presence of this symbol name causes forking. The content of this variable is don't care.
|
||||
* @note Use this if you mess with the internal structures of gds-render
|
||||
*/
|
||||
#define EXTERNAL_LIBRARY_FORK_REQUEST exported_fork_request
|
||||
|
||||
/**
|
||||
* @brief Define for declaring the exported functions.
|
||||
*
|
||||
* This not only helps with the declaration but also makes the symbols visible, so they can be called form outside the library
|
||||
*/
|
||||
#define EXPORTED_FUNC_DECL(FUNC) EXPORT_FUNC FUNC
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __EXTERNAL_RENDERER_INTERFACES_H__ */
|
@ -24,35 +24,38 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup external-renderer
|
||||
* @addtogroup ExternalRenderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _EXTERNAL_RENDERER_H_
|
||||
#define _EXTERNAL_RENDERER_H_
|
||||
|
||||
#include <gds-render/output-renderers/gds-output-renderer.h>
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
#include <glib.h>
|
||||
#include <gds-render/output-renderers/external-renderer-interfaces.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDS_RENDER_TYPE_EXTERNAL_RENDERER (external_renderer_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE(ExternalRenderer, external_renderer, GDS_RENDER, EXTERNAL_RENDERER, GdsOutputRenderer)
|
||||
|
||||
/**
|
||||
* @brief function name expected to be found in external library.
|
||||
*
|
||||
* The function has to be defined as follows:
|
||||
* @code
|
||||
* int function_name(gds_cell *toplevel, GList *layer_info_list, char *output_file_name)
|
||||
* @endcode
|
||||
* @brief Create new ExternalRenderer object
|
||||
* @return New object
|
||||
*/
|
||||
#define EXTERNAL_LIBRARY_FUNCTION "render_cell_to_file"
|
||||
ExternalRenderer *external_renderer_new();
|
||||
|
||||
/**
|
||||
* @brief external_renderer_render_cell
|
||||
* @param toplevel_cell The toplevel cell to render
|
||||
* @param layer_info_list The layer information. Contains #layer_info elements
|
||||
* @param output_file Output file
|
||||
* @param so_path Path to the shared object file containing #EXTERNAL_LIBRARY_FUNCTION
|
||||
* @return 0 on success
|
||||
* @brief Create new ExternalRenderer object with specified shared object path
|
||||
* @param so_path Path to shared object, the rendering function is searched in
|
||||
* @param param_string Command line parameter string passed to external renderer
|
||||
* @return New object.
|
||||
*/
|
||||
int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list, char *output_file, char *so_path);
|
||||
ExternalRenderer *external_renderer_new_with_so_and_param(const char *so_path, const char *param_string);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _EXTERNAL_RENDERER_H_ */
|
||||
|
161
include/gds-render/output-renderers/gds-output-renderer.h
Normal file
161
include/gds-render/output-renderers/gds-output-renderer.h
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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-output-renderer.h
|
||||
* @brief Header for output renderer base class
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GdsOutputRenderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GDS_OUTPUT_RENDERER_H_
|
||||
#define _GDS_OUTPUT_RENDERER_H_
|
||||
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
#include <glib-object.h>
|
||||
#include <glib.h>
|
||||
#include <gds-render/layer/layer-settings.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDS_RENDER_TYPE_OUTPUT_RENDERER (gds_output_renderer_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE(GdsOutputRenderer, gds_output_renderer, GDS_RENDER, OUTPUT_RENDERER, GObject);
|
||||
|
||||
/**
|
||||
* @brief Base output renderer class structure.
|
||||
* @note This structure is only used for internal inheritance of GObjects. Do not use in code outside of these classes.
|
||||
*/
|
||||
struct _GdsOutputRendererClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
/**
|
||||
* @brief Virtual render output function. Overwritten by final class implementation
|
||||
*/
|
||||
int (*render_output)(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale);
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
enum {
|
||||
GDS_OUTPUT_RENDERER_GEN_ERR = -100, /**< @brief Error set by the _GdsOutputRendererClass::render_output virtual function, if renderer is invalid. */
|
||||
GDS_OUTPUT_RENDERER_PARAM_ERR = -200 /**< @brief Error set by the _GdsOutputRendererClass::render_output virtual function, if parameters are faulty. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new GdsOutputRenderer GObject.
|
||||
* @return New object
|
||||
*/
|
||||
GdsOutputRenderer *gds_output_renderer_new();
|
||||
|
||||
/**
|
||||
* @brief Create a new GdsOutputRenderer GObject with its properties
|
||||
* @param output_file Output file of the renderer
|
||||
* @param layer_settings Layer settings object
|
||||
* @return New object
|
||||
*/
|
||||
GdsOutputRenderer *gds_output_renderer_new_with_props(const char *output_file, LayerSettings *layer_settings);
|
||||
|
||||
/**
|
||||
* @brief gds_output_renderer_render_output
|
||||
* @param renderer Renderer object
|
||||
* @param cell Cell to render
|
||||
* @param scale scale value. The output is scaled *down* by this value
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int gds_output_renderer_render_output(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for setting the "output-file" property
|
||||
* @param renderer Renderer object
|
||||
* @param file_name Output file path
|
||||
*/
|
||||
void gds_output_renderer_set_output_file(GdsOutputRenderer *renderer, const gchar *file_name);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for getting the "output-file" property
|
||||
* @param renderer
|
||||
* @return Output file path. This must not be freed
|
||||
*/
|
||||
const char *gds_output_renderer_get_output_file(GdsOutputRenderer *renderer);
|
||||
|
||||
/**
|
||||
* @brief Get layer settings
|
||||
*
|
||||
* This is a convenience function for getting the
|
||||
* "layer-settings" property. This also references it.
|
||||
* This is to prevent race conditions with another thread that might
|
||||
* alter the layer settings before they are read out.
|
||||
*
|
||||
* @param renderer Renderer
|
||||
* @return Layer settings object
|
||||
*/
|
||||
LayerSettings *gds_output_renderer_get_and_ref_layer_settings(GdsOutputRenderer *renderer);
|
||||
|
||||
/**
|
||||
* @brief Set layer settings
|
||||
*
|
||||
* This is a convenience function for setting the
|
||||
* "layer-settings" property.
|
||||
*
|
||||
* If another Layer settings has previously been supplied,
|
||||
* it is unref'd.
|
||||
*
|
||||
* @param renderer Renderer
|
||||
* @param settings LayerSettings object
|
||||
*/
|
||||
void gds_output_renderer_set_layer_settings(GdsOutputRenderer *renderer, LayerSettings *settings);
|
||||
|
||||
/**
|
||||
* @brief Render output asynchronously
|
||||
*
|
||||
* This function will render in a separate thread.
|
||||
* To wait for the completion of the rendering process.
|
||||
*
|
||||
* @note A second async thread cannot be spawned.
|
||||
*
|
||||
* @param renderer Output renderer
|
||||
* @param cell Cell to render
|
||||
* @param scale Scale
|
||||
* @return 0 if successful. In case no thread can be spawned < 0
|
||||
*/
|
||||
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale);
|
||||
|
||||
/**
|
||||
* @brief This function emits the 'progress-changed' in the thread/context that triggered an asynchronous rendering
|
||||
*
|
||||
* If the rendering is not asynchronous, this function has no effect.
|
||||
*
|
||||
* @param renderer GdsOutputrenderer object
|
||||
* @param status Status to supply to signal emission
|
||||
*/
|
||||
void gds_output_renderer_update_async_progress(GdsOutputRenderer *renderer, const char *status);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GDS_OUTPUT_RENDERER_H_ */
|
||||
|
||||
/** @} */
|
74
include/gds-render/output-renderers/latex-renderer.h
Normal file
74
include/gds-render/output-renderers/latex-renderer.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 latex-renderer.h
|
||||
* @brief LaTeX output renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LaTeX-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LATEX_OUTPUT_H_
|
||||
#define _LATEX_OUTPUT_H_
|
||||
|
||||
#include <gds-render/output-renderers/gds-output-renderer.h>
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(LatexRenderer, latex_renderer, GDS_RENDER, LATEX_RENDERER, GdsOutputRenderer)
|
||||
|
||||
#define GDS_RENDER_TYPE_LATEX_RENDERER (latex_renderer_get_type())
|
||||
|
||||
/**
|
||||
* @brief Buffer for LaTeX Code line in KiB
|
||||
*/
|
||||
#define LATEX_LINE_BUFFER_KB (10)
|
||||
|
||||
/**
|
||||
* @brief Create new LatexRenderer object
|
||||
* @return New object
|
||||
*/
|
||||
LatexRenderer *latex_renderer_new();
|
||||
|
||||
/**
|
||||
* @brief Create new LatexRenderer object
|
||||
*
|
||||
* This function sets the 'pdf-layers' and 'standalone'
|
||||
* properties for the newly created object.
|
||||
*
|
||||
* They can later be changes by modifying the properties again.
|
||||
* On top of that, The options can be changed in the resulting
|
||||
* LaTeX output file if needed.
|
||||
*
|
||||
* @param pdf_layers If PDF OCR layers should be enabled
|
||||
* @param standalone If output TeX file should be standalone compilable
|
||||
* @return New object
|
||||
*/
|
||||
LatexRenderer *latex_renderer_new_with_options(gboolean pdf_layers, gboolean standalone);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _LATEX_OUTPUT_H_ */
|
||||
|
||||
/** @} */
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tree-store.h
|
||||
* @brief Header file for Tree store implementation
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GUI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __TREE_STORE_H__
|
||||
#define __TREE_STORE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/** @brief Columns of selection tree view */
|
||||
enum cell_store_columns {
|
||||
CELL_SEL_LIBRARY = 0,
|
||||
CELL_SEL_CELL,
|
||||
CELL_SEL_CELL_ERROR_STATE, /**< Used for cell color and selectability */
|
||||
CELL_SEL_MODDATE,
|
||||
CELL_SEL_ACCESSDATE,
|
||||
CELL_SEL_COLUMN_COUNT /**< @brief Not a column. Used to determine count of columns */
|
||||
};
|
||||
|
||||
struct tree_stores {
|
||||
GtkTreeView *base_tree_view;
|
||||
GtkTreeStore *base_store;
|
||||
GtkTreeModelFilter *filter;
|
||||
GtkEntry *search_entry;
|
||||
};
|
||||
|
||||
struct tree_stores *setup_cell_selector(GtkTreeView* view, GtkEntry *search_entry);
|
||||
|
||||
#endif /* __TREE_STORE_H__ */
|
||||
|
||||
/** @} */
|
@ -25,4 +25,6 @@
|
||||
/** @brief This string holds the @ref git-version-num of the app */
|
||||
extern const char *_app_version_string;
|
||||
|
||||
/** @brief This string holds the git commit hash of the current HEAD revision */
|
||||
extern const char *_app_git_commit;
|
||||
/** @} */
|
||||
|
68
include/gds-render/widgets/activity-bar.h
Normal file
68
include/gds-render/widgets/activity-bar.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file activity-bar.h
|
||||
* @brief Header file for activity bar widget
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup ActivityBar
|
||||
* @ingroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __LAYER_ELEMENT_H__
|
||||
#define __LAYER_ELEMENT_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Creates Class structure etc */
|
||||
G_DECLARE_FINAL_TYPE(ActivityBar, activity_bar, ACTIVITY, BAR, GtkBox)
|
||||
|
||||
#define TYPE_ACTIVITY_BAR (activity_bar_get_type())
|
||||
|
||||
/**
|
||||
* @brief Create new Object ActivityBar
|
||||
* @return New object. In case of error: NULL.
|
||||
*/
|
||||
ActivityBar *activity_bar_new();
|
||||
|
||||
/**
|
||||
* @brief Deletes all applied tasks and sets bar to "Ready".
|
||||
* @param[in] bar AcitivityBar object.
|
||||
*/
|
||||
void activity_bar_set_ready(ActivityBar *bar);
|
||||
|
||||
/**
|
||||
* @brief Enable spinner and set \p text. If text is NULL, 'Working...' is displayed
|
||||
* @param bar Activity bar object
|
||||
* @param text Text to display, may be NULL
|
||||
|
||||
*/
|
||||
void activity_bar_set_busy(ActivityBar *bar, const char *text);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __LAYER_ELEMENT_H__ */
|
||||
|
||||
/** @} */
|
@ -19,7 +19,7 @@
|
||||
|
||||
/**
|
||||
* @file layer-element.h
|
||||
* @brief Omplementation of the layer element used for configuring layer colors etc.
|
||||
* @brief Implementation of the layer element used for configuring layer colors etc.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
|
260
layer/color-palette.c
Normal file
260
layer/color-palette.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file color-palette.c
|
||||
* @brief Class representing a color palette
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include <gds-render/layer/color-palette.h>
|
||||
|
||||
struct _ColorPalette {
|
||||
/* Inheritance */
|
||||
GObject parent;
|
||||
|
||||
/* Custom fields */
|
||||
/** @brief The internal array to store the colors */
|
||||
GdkRGBA *color_array;
|
||||
/** @brief The length of the _ColorPalette::color_array array */
|
||||
unsigned int color_array_length;
|
||||
|
||||
/* Dummy bytes to ensure ABI compatibility in future versions */
|
||||
gpointer dummy[4];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ColorPalette, color_palette, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* @brief Return the number of non empty lines in array
|
||||
*
|
||||
* This function returns the number of non empty lines in an
|
||||
* array. The scanning is either terminated by the given length
|
||||
* or if a \0 terminator is found.
|
||||
*
|
||||
* @param[in] data Array to count lines in
|
||||
* @param[in] length Length of \p data
|
||||
* @return < 0: Error, >=0: Lines
|
||||
*/
|
||||
static int count_non_empty_lines_in_array(const char *data, size_t length)
|
||||
{
|
||||
unsigned int idx;
|
||||
int non_empty_lines = 0;
|
||||
char last_char = '\n';
|
||||
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
/* Count each '\n' as a new line if it is not directly preceded by another '\n' */
|
||||
for (idx = 0; idx < length && data[idx]; idx++) {
|
||||
if (data[idx] == '\n' && last_char != '\n')
|
||||
non_empty_lines++;
|
||||
last_char = data[idx];
|
||||
}
|
||||
|
||||
/* Count the last line in case the data does not end with a '\n' */
|
||||
if (data[idx-1] != '\n')
|
||||
non_empty_lines++;
|
||||
|
||||
return non_empty_lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief color_palette_fill_with_resource
|
||||
* @param palette
|
||||
* @param resource_name
|
||||
* @return 0 if successful
|
||||
*/
|
||||
static int color_palette_fill_with_resource(ColorPalette *palette, char *resource_name)
|
||||
{
|
||||
GBytes *data;
|
||||
char line[10];
|
||||
int line_idx;
|
||||
unsigned int color_idx;
|
||||
int idx;
|
||||
const char *char_array;
|
||||
gsize byte_count;
|
||||
int lines;
|
||||
GRegex *regex;
|
||||
GMatchInfo *mi;
|
||||
char *match;
|
||||
|
||||
if (!palette || !resource_name)
|
||||
return -1;
|
||||
|
||||
data = g_resources_lookup_data(resource_name, 0, NULL);
|
||||
|
||||
if (!data)
|
||||
return -2;
|
||||
|
||||
char_array = (const char *)g_bytes_get_data(data, &byte_count);
|
||||
|
||||
if (!char_array || !byte_count)
|
||||
goto ret_unref_data;
|
||||
|
||||
/* Get maximum lenght of color palette, assuming all entries are valid */
|
||||
lines = count_non_empty_lines_in_array(char_array, byte_count);
|
||||
|
||||
if (lines <= 0)
|
||||
goto ret_unref_data;
|
||||
|
||||
palette->color_array = (GdkRGBA *)malloc(sizeof(GdkRGBA) * (unsigned int)lines);
|
||||
|
||||
/* Setup regex for hexadecimal RGB colors like 'A0CB3F' */
|
||||
regex = g_regex_new("^(?<red>[0-9A-Fa-f][0-9A-Fa-f])(?<green>[0-9A-Fa-f][0-9A-Fa-f])(?<blue>[0-9A-Fa-f][0-9A-Fa-f])$",
|
||||
0, 0, NULL);
|
||||
|
||||
/* Reset line */
|
||||
line_idx = 0;
|
||||
line[0] = '\0';
|
||||
|
||||
/* Set color index */
|
||||
color_idx = 0;
|
||||
|
||||
/* interate over lines and match */
|
||||
for (idx = 0 ; (unsigned int)idx < byte_count; idx++) {
|
||||
/* Fillup line. */
|
||||
line[line_idx] = char_array[idx];
|
||||
|
||||
/* If end of line/string is reached, process */
|
||||
if (line[line_idx] == '\n' || line[line_idx] == '\0') {
|
||||
line[line_idx] = '\0';
|
||||
|
||||
/* Match the line */
|
||||
g_regex_match(regex, line, 0, &mi);
|
||||
if (g_match_info_matches(mi) && color_idx < (unsigned int)lines) {
|
||||
match = g_match_info_fetch_named(mi, "red");
|
||||
palette->color_array[color_idx].red =
|
||||
(double)g_ascii_strtoll(match, NULL, 16) / 255.0;
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "green");
|
||||
palette->color_array[color_idx].green =
|
||||
(double)g_ascii_strtoll(match, NULL, 16) / 255.0;
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "blue");
|
||||
palette->color_array[color_idx].blue =
|
||||
(double)g_ascii_strtoll(match, NULL, 16) / 255.0;
|
||||
g_free(match);
|
||||
|
||||
/* Only RGB supported so far. Fix alpha channel to 1.0 */
|
||||
palette->color_array[color_idx].alpha = 1.0;
|
||||
|
||||
color_idx++;
|
||||
}
|
||||
|
||||
g_match_info_free(mi);
|
||||
|
||||
/* End of string */
|
||||
if (char_array[idx] == '\0')
|
||||
break;
|
||||
|
||||
line_idx = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* increment line index. If end is reached write all bytes to the line end.
|
||||
* Line is longer than required for parsing. This ensures, that everything works as expected
|
||||
*/
|
||||
line_idx += ((unsigned int)line_idx < sizeof(line)-1 ? 1 : 0);
|
||||
}
|
||||
|
||||
/* Data read; Shrink array in case of invalid lines */
|
||||
palette->color_array = realloc(palette->color_array, (size_t)color_idx * sizeof(GdkRGBA));
|
||||
palette->color_array_length = color_idx;
|
||||
|
||||
g_regex_unref(regex);
|
||||
ret_unref_data:
|
||||
g_bytes_unref(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ColorPalette *color_palette_new_from_resource(char *resource_name)
|
||||
{
|
||||
ColorPalette *palette;
|
||||
|
||||
palette = GDS_RENDER_COLOR_PALETTE(g_object_new(TYPE_GDS_RENDER_COLOR_PALETTE, NULL));
|
||||
if (palette)
|
||||
(void)color_palette_fill_with_resource(palette, resource_name);
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
GdkRGBA *color_palette_get_color(ColorPalette *palette, GdkRGBA *color, unsigned int index)
|
||||
{
|
||||
GdkRGBA *c = NULL;
|
||||
|
||||
if (!palette)
|
||||
goto ret_c;
|
||||
|
||||
if (index >= palette->color_array_length)
|
||||
goto ret_c;
|
||||
|
||||
if (color)
|
||||
c = color;
|
||||
else
|
||||
c = (GdkRGBA *)malloc(sizeof(GdkRGBA));
|
||||
|
||||
/* Copy color */
|
||||
c->red = palette->color_array[index].red;
|
||||
c->green = palette->color_array[index].green;
|
||||
c->blue = palette->color_array[index].blue;
|
||||
c->alpha = palette->color_array[index].alpha;
|
||||
ret_c:
|
||||
return c;
|
||||
}
|
||||
|
||||
unsigned int color_palette_get_color_count(ColorPalette *palette)
|
||||
{
|
||||
unsigned int return_val = 0;
|
||||
|
||||
if (palette)
|
||||
return_val = palette->color_array_length;
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
static void color_palette_dispose(GObject *gobj)
|
||||
{
|
||||
ColorPalette *palette;
|
||||
|
||||
palette = GDS_RENDER_COLOR_PALETTE(gobj);
|
||||
if (palette->color_array) {
|
||||
palette->color_array_length = 0;
|
||||
free(palette->color_array);
|
||||
palette->color_array = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to parent class */
|
||||
G_OBJECT_CLASS(color_palette_parent_class)->dispose(gobj);
|
||||
}
|
||||
|
||||
static void color_palette_class_init(ColorPaletteClass *klass)
|
||||
{
|
||||
GObjectClass *gclass;
|
||||
|
||||
gclass = G_OBJECT_CLASS(klass);
|
||||
gclass->dispose = color_palette_dispose;
|
||||
}
|
||||
|
||||
static void color_palette_init(ColorPalette *self)
|
||||
{
|
||||
self->color_array = NULL;
|
||||
self->color_array_length = 0;
|
||||
}
|
@ -34,10 +34,8 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gds-render/layer/layer-selector.h>
|
||||
#include <gds-render/layer/layer-info.h>
|
||||
#include <gds-render/gds-utils/gds-parser.h>
|
||||
#include <gds-render/widgets/layer-element.h>
|
||||
#include <gds-render/layer/mapping-parser.h>
|
||||
|
||||
struct _LayerSelector {
|
||||
/* Parent */
|
||||
@ -56,7 +54,8 @@ struct _LayerSelector {
|
||||
|
||||
G_DEFINE_TYPE(LayerSelector, layer_selector, G_TYPE_OBJECT)
|
||||
|
||||
/* Drag and drop code
|
||||
/*
|
||||
* Drag and drop code
|
||||
* Original code from https://blog.gtk.org/2017/06/01/drag-and-drop-in-lists-revisited/
|
||||
*/
|
||||
|
||||
@ -74,16 +73,16 @@ static void sel_layer_element_drag_begin(GtkWidget *widget, GdkDragContext *cont
|
||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
|
||||
cr = cairo_create(surface);
|
||||
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context(row), "drag-icon");
|
||||
gtk_widget_draw (row, cr);
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-icon");
|
||||
gtk_widget_draw(row, cr);
|
||||
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-icon");
|
||||
|
||||
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
|
||||
cairo_surface_set_device_offset (surface, -x, -y);
|
||||
gtk_drag_set_icon_surface (context, surface);
|
||||
gtk_widget_translate_coordinates(widget, row, 0, 0, &x, &y);
|
||||
cairo_surface_set_device_offset(surface, -x, -y);
|
||||
gtk_drag_set_icon_surface(context, surface);
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
|
||||
@ -117,14 +116,14 @@ static void sel_layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *c
|
||||
32, (const guchar *)&widget, sizeof(gpointer));
|
||||
}
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
|
||||
static GtkListBoxRow *layer_selector_get_last_row(GtkListBox *list)
|
||||
{
|
||||
int i;
|
||||
GtkListBoxRow *row;
|
||||
GtkListBoxRow *tmp;
|
||||
|
||||
row = NULL;
|
||||
for (i = 0; ; i++) {
|
||||
GtkListBoxRow *tmp;
|
||||
tmp = gtk_list_box_get_row_at_index(list, i);
|
||||
if (tmp == NULL)
|
||||
break;
|
||||
@ -134,15 +133,15 @@ static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
|
||||
return row;
|
||||
}
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_row_before (GtkListBox *list, GtkListBoxRow *row)
|
||||
static GtkListBoxRow *layer_selector_get_row_before(GtkListBox *list, GtkListBoxRow *row)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = gtk_list_box_row_get_index (row);
|
||||
return gtk_list_box_get_row_at_index (list, pos - 1);
|
||||
pos = gtk_list_box_row_get_index(row);
|
||||
return gtk_list_box_get_row_at_index(list, pos - 1);
|
||||
}
|
||||
|
||||
static GtkListBoxRow *layer_selector_get_row_after (GtkListBox *list, GtkListBoxRow *row)
|
||||
static GtkListBoxRow *layer_selector_get_row_after(GtkListBox *list, GtkListBoxRow *row)
|
||||
{
|
||||
int pos;
|
||||
|
||||
@ -159,6 +158,14 @@ static void layer_selector_drag_data_received(GtkWidget *widget, GdkDragContext
|
||||
GtkWidget *source;
|
||||
int pos;
|
||||
|
||||
/* Handle unused parameters */
|
||||
(void)context;
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)info;
|
||||
(void)time;
|
||||
(void)data;
|
||||
|
||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||
row_after = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-after"));
|
||||
|
||||
@ -197,6 +204,10 @@ static gboolean layer_selector_drag_motion(GtkWidget *widget, GdkDragContext *co
|
||||
GtkWidget *drag_row;
|
||||
GtkWidget *row_before;
|
||||
GtkWidget *row_after;
|
||||
(void)context;
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)time;
|
||||
|
||||
row = GTK_WIDGET(gtk_list_box_get_row_at_y(GTK_LIST_BOX(widget), y));
|
||||
|
||||
@ -250,6 +261,8 @@ static void layer_selector_drag_leave(GtkWidget *widget, GdkDragContext *context
|
||||
GtkWidget *drag_row;
|
||||
GtkWidget *row_before;
|
||||
GtkWidget *row_after;
|
||||
(void)context;
|
||||
(void)time;
|
||||
|
||||
drag_row = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "drag-row"));
|
||||
row_before = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "row-before"));
|
||||
@ -264,40 +277,40 @@ static void layer_selector_drag_leave(GtkWidget *widget, GdkDragContext *context
|
||||
}
|
||||
|
||||
static const char *dnd_additional_css =
|
||||
".row:not(:first-child) { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:first-child { "
|
||||
" border-top: 1px solid transparent; "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:last-child { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid alpha(gray,0.5); "
|
||||
"}"
|
||||
".row.drag-icon { "
|
||||
" background: #282828; "
|
||||
" border: 1px solid blue; "
|
||||
"}"
|
||||
".row.drag-row { "
|
||||
" color: gray; "
|
||||
" background: alpha(gray,0.2); "
|
||||
"}"
|
||||
".row.drag-row.drag-hover { "
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover image, "
|
||||
".row.drag-hover label { "
|
||||
" color: #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-top {"
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-bottom {"
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}";
|
||||
".row:not(:first-child) { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:first-child { "
|
||||
" border-top: 1px solid transparent; "
|
||||
" border-bottom: 1px solid transparent; "
|
||||
"}"
|
||||
".row:last-child { "
|
||||
" border-top: 1px solid alpha(gray,0.5); "
|
||||
" border-bottom: 1px solid alpha(gray,0.5); "
|
||||
"}"
|
||||
".row.drag-icon { "
|
||||
" background: #282828; "
|
||||
" border: 1px solid blue; "
|
||||
"}"
|
||||
".row.drag-row { "
|
||||
" color: gray; "
|
||||
" background: alpha(gray,0.2); "
|
||||
"}"
|
||||
".row.drag-row.drag-hover { "
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover image, "
|
||||
".row.drag-hover label { "
|
||||
" color: #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-top {"
|
||||
" border-top: 1px solid #4e9a06; "
|
||||
"}"
|
||||
".row.drag-hover-bottom {"
|
||||
" border-bottom: 1px solid #4e9a06; "
|
||||
"}";
|
||||
|
||||
static void layer_selector_dispose(GObject *self)
|
||||
{
|
||||
@ -336,7 +349,8 @@ static void layer_selector_class_init(LayerSelectorClass *klass)
|
||||
|
||||
static void layer_selector_setup_dnd(LayerSelector *self)
|
||||
{
|
||||
gtk_drag_dest_set(GTK_WIDGET(self->list_box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, &self->dnd_target, 1, GDK_ACTION_MOVE);
|
||||
gtk_drag_dest_set(GTK_WIDGET(self->list_box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
|
||||
&self->dnd_target, 1, GDK_ACTION_MOVE);
|
||||
g_signal_connect(self->list_box, "drag-data-received", G_CALLBACK(layer_selector_drag_data_received), NULL);
|
||||
g_signal_connect(self->list_box, "drag-motion", G_CALLBACK(layer_selector_drag_motion), NULL);
|
||||
g_signal_connect(self->list_box, "drag-leave", G_CALLBACK(layer_selector_drag_leave), NULL);
|
||||
@ -371,39 +385,39 @@ LayerSelector *layer_selector_new(GtkListBox *list_box)
|
||||
return selector;
|
||||
}
|
||||
|
||||
GList *layer_selector_export_rendered_layer_info(LayerSelector *selector)
|
||||
LayerSettings *layer_selector_export_rendered_layer_info(LayerSelector *selector)
|
||||
{
|
||||
GList *info_list = NULL;
|
||||
LayerElement *le;
|
||||
struct layer_info *linfo;
|
||||
LayerSettings *layer_settings;
|
||||
struct layer_info linfo;
|
||||
GList *row_list;
|
||||
GList *temp;
|
||||
GList *iterator;
|
||||
LayerElement *le;
|
||||
int i;
|
||||
|
||||
if (!selector)
|
||||
layer_settings = layer_settings_new();
|
||||
if (!layer_settings)
|
||||
return NULL;
|
||||
|
||||
row_list = gtk_container_get_children(GTK_CONTAINER(selector->list_box));
|
||||
|
||||
/* Iterate through widgets and add layers that shall be exported */
|
||||
for (i = 0, temp = row_list; temp != NULL; temp = temp->next, i++) {
|
||||
for (i = 0, iterator = row_list; iterator != NULL; iterator = g_list_next(iterator), i++) {
|
||||
le = LAYER_ELEMENT(iterator->data);
|
||||
|
||||
le = LAYER_ELEMENT(temp->data);
|
||||
/* Get name from layer element. This must not be freed */
|
||||
linfo.name = (char *)layer_element_get_name(le);
|
||||
|
||||
if (layer_element_get_export(le) == TRUE) {
|
||||
/* Allocate new info and fill with info */
|
||||
linfo = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||
layer_element_get_color(le, &linfo->color);
|
||||
linfo->layer = layer_element_get_layer(le);
|
||||
linfo->stacked_position = i;
|
||||
linfo->name = (char *)layer_element_get_name(le);
|
||||
layer_element_get_color(le, &linfo.color);
|
||||
linfo.render = (layer_element_get_export(le) ? 1 : 0);
|
||||
linfo.stacked_position = i;
|
||||
linfo.layer = layer_element_get_layer(le);
|
||||
|
||||
/* Append to list */
|
||||
info_list = g_list_append(info_list, (gpointer)linfo);
|
||||
}
|
||||
/* This function copies the entire layer info struct including the name string.
|
||||
* Therefore, using the same layer_info struct over and over is safe.
|
||||
*/
|
||||
layer_settings_append_layer_info(layer_settings, &linfo);
|
||||
}
|
||||
|
||||
return info_list;
|
||||
return layer_settings;
|
||||
}
|
||||
|
||||
static void layer_selector_clear_widgets(LayerSelector *self)
|
||||
@ -412,9 +426,9 @@ static void layer_selector_clear_widgets(LayerSelector *self)
|
||||
GList *temp;
|
||||
|
||||
list = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||
for (temp = list; temp != NULL; temp = temp->next) {
|
||||
for (temp = list; temp != NULL; temp = temp->next)
|
||||
gtk_container_remove(GTK_CONTAINER(self->list_box), GTK_WIDGET(temp->data));
|
||||
}
|
||||
|
||||
/* Widgets are already destroyed when removed from box because they are only referenced inside the container */
|
||||
|
||||
g_list_free(list);
|
||||
@ -432,7 +446,8 @@ static void layer_selector_clear_widgets(LayerSelector *self)
|
||||
* @param layer Layer number to check for
|
||||
* @return TRUE if layer is present, else FALSE
|
||||
*/
|
||||
static gboolean layer_selector_check_if_layer_widget_exists(LayerSelector *self, int layer) {
|
||||
static gboolean layer_selector_check_if_layer_widget_exists(LayerSelector *self, int layer)
|
||||
{
|
||||
GList *list;
|
||||
GList *temp;
|
||||
LayerElement *widget;
|
||||
@ -540,9 +555,8 @@ void layer_selector_generate_layer_widgets(LayerSelector *selector, GList *libs)
|
||||
|
||||
for (; libs != NULL; libs = libs->next) {
|
||||
lib = (struct gds_library *)libs->data;
|
||||
for (cell_list = lib->cells; cell_list != NULL; cell_list = cell_list->next) {
|
||||
for (cell_list = lib->cells; cell_list != NULL; cell_list = cell_list->next)
|
||||
layer_selector_analyze_cell_layers(selector, (struct gds_cell *)cell_list->data);
|
||||
} /* For Cell List */
|
||||
} /* For libs */
|
||||
|
||||
/* Sort the layers */
|
||||
@ -564,6 +578,7 @@ void layer_selector_generate_layer_widgets(LayerSelector *selector, GList *libs)
|
||||
static LayerElement *layer_selector_find_layer_element_in_list(GList *el_list, int layer)
|
||||
{
|
||||
LayerElement *ret = NULL;
|
||||
|
||||
for (; el_list != NULL; el_list = el_list->next) {
|
||||
if (layer_element_get_layer(LAYER_ELEMENT(el_list->data)) == layer) {
|
||||
ret = LAYER_ELEMENT(el_list->data);
|
||||
@ -584,19 +599,18 @@ static LayerElement *layer_selector_find_layer_element_in_list(GList *el_list, i
|
||||
* @param self LayerSelector instance
|
||||
* @param file_name File name to load from
|
||||
*/
|
||||
static void layer_selector_load_layer_mapping_from_file(LayerSelector *self, gchar *file_name)
|
||||
static void layer_selector_load_layer_mapping_from_file(LayerSelector *self, const gchar *file_name)
|
||||
{
|
||||
GFile *file;
|
||||
GFileInputStream *stream;
|
||||
GDataInputStream *dstream;
|
||||
LayerElement *le;
|
||||
char *name;
|
||||
gboolean export;
|
||||
int layer;
|
||||
GdkRGBA color;
|
||||
int result;
|
||||
GList *rows;
|
||||
GList *temp;
|
||||
GList *layer_infos;
|
||||
int status;
|
||||
LayerSettings *layer_settings;
|
||||
struct layer_info *linfo;
|
||||
|
||||
file = g_file_new_for_path(file_name);
|
||||
stream = g_file_read(file, NULL, NULL);
|
||||
@ -611,31 +625,40 @@ static void layer_selector_load_layer_mapping_from_file(LayerSelector *self, gch
|
||||
/* Reference and remove all rows from box */
|
||||
for (temp = rows; temp != NULL; temp = temp->next) {
|
||||
le = LAYER_ELEMENT(temp->data);
|
||||
/* Referencing protets the widget from being deleted when removed */
|
||||
/* Referencing protects the widget from being deleted when removed */
|
||||
g_object_ref(G_OBJECT(le));
|
||||
gtk_container_remove(GTK_CONTAINER(self->list_box), GTK_WIDGET(le));
|
||||
}
|
||||
|
||||
while((result = mapping_parser_load_line(dstream, &export, &name, &layer, &color)) >= 0) {
|
||||
/* skip broken line */
|
||||
if (result == 1)
|
||||
/* Load Layer settings. No need to check pointer, will be checked by load csv func. */
|
||||
layer_settings = layer_settings_new();
|
||||
|
||||
status = layer_settings_load_from_csv(layer_settings, file_name);
|
||||
if (status)
|
||||
goto abort_layer_settings;
|
||||
|
||||
layer_infos = layer_settings_get_layer_info_list(layer_settings);
|
||||
if (!layer_infos)
|
||||
goto abort_layer_settings;
|
||||
|
||||
/* Loop over all layer infos read from the CSV file */
|
||||
for (; layer_infos; layer_infos = g_list_next(layer_infos)) {
|
||||
linfo = (struct layer_info *)layer_infos->data;
|
||||
le = layer_selector_find_layer_element_in_list(rows, linfo->layer);
|
||||
if (!le)
|
||||
continue;
|
||||
|
||||
/* Add rows in the same order as in file */
|
||||
if ((le = layer_selector_find_layer_element_in_list(rows, layer))) {
|
||||
gtk_list_box_insert(self->list_box, GTK_WIDGET(le), -1);
|
||||
|
||||
layer_element_set_color(le, &color);
|
||||
layer_element_set_export(le, export);
|
||||
layer_element_set_name(le, name);
|
||||
g_free(name);
|
||||
|
||||
/* Dereference and remove from list */
|
||||
g_object_unref(G_OBJECT(le));
|
||||
rows = g_list_remove(rows, le);
|
||||
}
|
||||
layer_element_set_name(le, linfo->name);
|
||||
layer_element_set_export(le, (linfo->render ? TRUE : FALSE));
|
||||
layer_element_set_color(le, &linfo->color);
|
||||
gtk_container_add(GTK_CONTAINER(self->list_box), GTK_WIDGET(le));
|
||||
rows = g_list_remove(rows, le);
|
||||
}
|
||||
|
||||
abort_layer_settings:
|
||||
/* Destroy layer settings. Not needed for adding remaining elements */
|
||||
g_object_unref(layer_settings);
|
||||
|
||||
/* Add remaining elements */
|
||||
for (temp = rows; temp != NULL; temp = temp->next) {
|
||||
le = LAYER_ELEMENT(temp->data);
|
||||
@ -665,10 +688,12 @@ static void layer_selector_load_mapping_clicked(GtkWidget *button, gpointer user
|
||||
GtkWidget *dialog;
|
||||
gint res;
|
||||
gchar *file_name;
|
||||
(void)button;
|
||||
|
||||
sel = LAYER_SELECTOR(user_data);
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Load Mapping File", GTK_WINDOW(sel->load_parent_window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
dialog = gtk_file_chooser_dialog_new("Load Mapping File", GTK_WINDOW(sel->load_parent_window),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"Cancel", GTK_RESPONSE_CANCEL, "Load Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
||||
res = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
if (res == GTK_RESPONSE_ACCEPT) {
|
||||
@ -688,29 +713,14 @@ static void layer_selector_load_mapping_clicked(GtkWidget *button, gpointer user
|
||||
*/
|
||||
static void layer_selector_save_layer_mapping_data(LayerSelector *self, const gchar *file_name)
|
||||
{
|
||||
FILE *file;
|
||||
char workbuff[512];
|
||||
GList *le_list;
|
||||
GList *temp;
|
||||
LayerSettings *layer_settings;
|
||||
|
||||
/* Overwrite existing file */
|
||||
file = fopen((const char *)file_name, "w");
|
||||
g_return_if_fail(LAYER_IS_SELECTOR(self));
|
||||
g_return_if_fail(file_name);
|
||||
|
||||
le_list = gtk_container_get_children(GTK_CONTAINER(self->list_box));
|
||||
|
||||
/* File format is CSV: <Layer>,<target_pos>,<R>,<G>,<B>,<Alpha>,<Export?>,<Name> */
|
||||
for (temp = le_list; temp != NULL; temp = temp->next) {
|
||||
/* To be sure it is a valid string */
|
||||
workbuff[0] = 0;
|
||||
mapping_parser_gen_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
|
||||
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
|
||||
}
|
||||
|
||||
g_list_free(le_list);
|
||||
|
||||
/* Save File */
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
/* Get layer settings. No need to check return value. to_csv func is safe */
|
||||
layer_settings = layer_selector_export_rendered_layer_info(self);
|
||||
(void)layer_settings_to_csv(layer_settings, file_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -724,10 +734,12 @@ static void layer_selector_save_mapping_clicked(GtkWidget *button, gpointer user
|
||||
gint res;
|
||||
gchar *file_name;
|
||||
LayerSelector *sel;
|
||||
(void)button;
|
||||
|
||||
sel = LAYER_SELECTOR(user_data);
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(sel->save_parent_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
dialog = gtk_file_chooser_dialog_new("Save Mapping File", GTK_WINDOW(sel->save_parent_window),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"Cancel", GTK_RESPONSE_CANCEL, "Save Mapping", GTK_RESPONSE_ACCEPT, NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
@ -781,4 +793,134 @@ void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort
|
||||
gtk_list_box_set_sort_func(box, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void layer_selector_select_all_layers(LayerSelector *layer_selector, gboolean select)
|
||||
{
|
||||
GList *le_list;
|
||||
GList *iter;
|
||||
LayerElement *le;
|
||||
|
||||
g_return_if_fail(LAYER_IS_SELECTOR(layer_selector));
|
||||
g_return_if_fail(GTK_IS_LIST_BOX(layer_selector->list_box));
|
||||
|
||||
le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
|
||||
|
||||
for (iter = le_list; iter != NULL; iter = g_list_next(iter)) {
|
||||
le = LAYER_ELEMENT(iter->data);
|
||||
if (LAYER_IS_ELEMENT(le))
|
||||
layer_element_set_export(le, select);
|
||||
}
|
||||
|
||||
g_list_free(le_list);
|
||||
}
|
||||
|
||||
void layer_selector_auto_color_layers(LayerSelector *layer_selector, ColorPalette *palette, double global_alpha)
|
||||
{
|
||||
GList *le_list;
|
||||
GList *le_list_ptr;
|
||||
LayerElement *le;
|
||||
unsigned int color_index = 0;
|
||||
unsigned int color_count;
|
||||
GdkRGBA color;
|
||||
|
||||
g_return_if_fail(GDS_RENDER_IS_COLOR_PALETTE(palette));
|
||||
g_return_if_fail(LAYER_IS_SELECTOR(layer_selector));
|
||||
g_return_if_fail(global_alpha > 0);
|
||||
g_return_if_fail(GTK_IS_LIST_BOX(layer_selector->list_box));
|
||||
|
||||
le_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
|
||||
|
||||
/* iterate over layer elements and fill colors */
|
||||
color_index = 0;
|
||||
color_count = color_palette_get_color_count(palette);
|
||||
if (color_count == 0)
|
||||
goto ret_free_le_list;
|
||||
|
||||
for (le_list_ptr = le_list; le_list_ptr != NULL; le_list_ptr = le_list_ptr->next) {
|
||||
le = LAYER_ELEMENT(le_list_ptr->data);
|
||||
if (le) {
|
||||
color_palette_get_color(palette, &color, color_index++);
|
||||
color.alpha *= global_alpha;
|
||||
layer_element_set_color(le, &color);
|
||||
|
||||
if (color_index >= color_count)
|
||||
color_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ret_free_le_list:
|
||||
g_list_free(le_list);
|
||||
}
|
||||
|
||||
void layer_selector_auto_name_layers(LayerSelector *layer_selector, gboolean overwrite)
|
||||
{
|
||||
GList *le_list;
|
||||
GList *le_list_ptr;
|
||||
LayerElement *le;
|
||||
const char *old_layer_name;
|
||||
GString *new_layer_name;
|
||||
|
||||
g_return_if_fail(LAYER_IS_SELECTOR(layer_selector));
|
||||
|
||||
new_layer_name = g_string_new_len(NULL, 10);
|
||||
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;
|
||||
old_layer_name = layer_element_get_name(le);
|
||||
|
||||
/* Check if layer name is empty or may be overwritten */
|
||||
if (!old_layer_name || *old_layer_name == '\0' || overwrite) {
|
||||
g_string_printf(new_layer_name, "Layer %d", layer_element_get_layer(le));
|
||||
layer_element_set_name(le, new_layer_name->str);
|
||||
}
|
||||
}
|
||||
|
||||
g_string_free(new_layer_name, TRUE);
|
||||
g_list_free(le_list);
|
||||
}
|
||||
|
||||
gboolean layer_selector_contains_elements(LayerSelector *layer_selector)
|
||||
{
|
||||
GList *layer_element_list;
|
||||
|
||||
/* Check objects */
|
||||
g_return_val_if_fail(LAYER_IS_SELECTOR(layer_selector), FALSE);
|
||||
g_return_val_if_fail(GTK_IS_LIST_BOX(layer_selector->list_box), FALSE);
|
||||
|
||||
/* Get a list of the child elements inside the list boy associated with this selector */
|
||||
layer_element_list = gtk_container_get_children(GTK_CONTAINER(layer_selector->list_box));
|
||||
|
||||
/* Return TRUE if there is an element in the list, else return 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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
354
layer/layer-settings.c
Normal file
354
layer/layer-settings.c
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file layer-settings.c
|
||||
* @brief Implementation of the LayerSettings class
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include <gds-render/layer/layer-settings.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct _LayerSettings {
|
||||
GObject parent;
|
||||
GList *layer_infos;
|
||||
gpointer padding[12];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(LayerSettings, layer_settings, G_TYPE_OBJECT)
|
||||
|
||||
static void layer_settings_init(LayerSettings *self)
|
||||
{
|
||||
self->layer_infos = NULL;
|
||||
}
|
||||
|
||||
static void layer_info_delete_with_name(struct layer_info *const info)
|
||||
{
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
if (info->name)
|
||||
free(info->name);
|
||||
free(info);
|
||||
}
|
||||
|
||||
static void layer_settings_dispose(GObject *obj)
|
||||
{
|
||||
LayerSettings *self;
|
||||
|
||||
self = GDS_RENDER_LAYER_SETTINGS(obj);
|
||||
|
||||
if (self->layer_infos) {
|
||||
g_list_free_full(self->layer_infos, (GDestroyNotify)layer_info_delete_with_name);
|
||||
self->layer_infos = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(layer_settings_parent_class)->dispose(obj);
|
||||
}
|
||||
|
||||
static void layer_settings_class_init(LayerSettingsClass *klass)
|
||||
{
|
||||
GObjectClass *oclass;
|
||||
|
||||
oclass = G_OBJECT_CLASS(klass);
|
||||
oclass->dispose = layer_settings_dispose;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy layer_info struct
|
||||
*
|
||||
* This function copies a layer info struct.
|
||||
*
|
||||
* @note Be aware, that it does not only copy the pointer to the
|
||||
* layer name, but instead duplicates the string.
|
||||
* @param info Info to copy
|
||||
* @return new layer_info struct
|
||||
*/
|
||||
static struct layer_info *layer_info_copy(const struct layer_info * const info)
|
||||
{
|
||||
struct layer_info *copy;
|
||||
|
||||
if (!info)
|
||||
return 0;
|
||||
|
||||
copy = (struct layer_info *)malloc(sizeof(struct layer_info));
|
||||
if (!copy)
|
||||
return 0;
|
||||
|
||||
/* Copy data */
|
||||
memcpy(copy, info, sizeof(struct layer_info));
|
||||
/* Duplicate string */
|
||||
if (info->name)
|
||||
copy->name = strdup(info->name);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
LayerSettings *layer_settings_new()
|
||||
{
|
||||
return g_object_new(GDS_RENDER_TYPE_LAYER_SETTINGS, NULL);
|
||||
}
|
||||
|
||||
int layer_settings_append_layer_info(LayerSettings *settings, struct layer_info *info)
|
||||
{
|
||||
struct layer_info *info_copy;
|
||||
|
||||
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), -1);
|
||||
if (!info)
|
||||
return -2;
|
||||
|
||||
/* Copy layer info */
|
||||
info_copy = layer_info_copy(info);
|
||||
|
||||
/* Append to list */
|
||||
settings->layer_infos = g_list_append(settings->layer_infos, info_copy);
|
||||
|
||||
return (settings->layer_infos ? 0 : -3);
|
||||
}
|
||||
|
||||
void layer_settings_clear(LayerSettings *settings)
|
||||
{
|
||||
g_return_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings));
|
||||
|
||||
/* Clear list and delete layer_info structs including the name field */
|
||||
g_list_free_full(settings->layer_infos, (GDestroyNotify)layer_info_delete_with_name);
|
||||
settings->layer_infos = NULL;
|
||||
}
|
||||
|
||||
int layer_settings_remove_layer(LayerSettings *settings, int layer)
|
||||
{
|
||||
GList *list_iter;
|
||||
GList *found = NULL;
|
||||
struct layer_info *inf;
|
||||
|
||||
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), -1);
|
||||
|
||||
/* Find in list */
|
||||
for (list_iter = settings->layer_infos; list_iter; list_iter = list_iter->next) {
|
||||
inf = (struct layer_info *)list_iter->data;
|
||||
|
||||
if (!inf)
|
||||
continue;
|
||||
if (inf->layer == layer)
|
||||
found = list_iter;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/* Free the layer_info struct */
|
||||
layer_info_delete_with_name((struct layer_info *)found->data);
|
||||
/* Delete the list element */
|
||||
settings->layer_infos = g_list_delete_link(settings->layer_infos, found);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
GList *layer_settings_get_layer_info_list(LayerSettings *settings)
|
||||
{
|
||||
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), NULL);
|
||||
return settings->layer_infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a layer mapping CSV line for a given layer_info struct
|
||||
* @param string Buffer to write to
|
||||
* @param linfo Layer information
|
||||
*/
|
||||
static void layer_settings_gen_csv_line(GString *string, struct layer_info *linfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_string_printf(string, "%d:%lf:%lf:%lf:%lf:%d:%s\n",
|
||||
linfo->layer, linfo->color.red, linfo->color.green,
|
||||
linfo->color.blue, linfo->color.alpha, (linfo->render ? 1 : 0), linfo->name);
|
||||
/* Fix broken locale settings */
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ',')
|
||||
string->str[i] = '.';
|
||||
}
|
||||
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ':')
|
||||
string->str[i] = ',';
|
||||
}
|
||||
}
|
||||
|
||||
int layer_settings_to_csv(LayerSettings *settings, const char *path)
|
||||
{
|
||||
GFile *file;
|
||||
GOutputStream *w_fstream;
|
||||
GString *string;
|
||||
GList *info_iter;
|
||||
struct layer_info *linfo;
|
||||
int ret = 0;
|
||||
|
||||
file = g_file_new_for_path(path);
|
||||
w_fstream = G_OUTPUT_STREAM(g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
|
||||
if (!w_fstream) {
|
||||
ret = -1;
|
||||
goto ret_unref_file;
|
||||
}
|
||||
|
||||
/* Allocate new working buffer string. A size bigger than 200 is unexpected, but possible
|
||||
* 200 is a tradeoff between memory usage and preventing the necessity of realloc'ing the string
|
||||
*/
|
||||
string = g_string_new_len(NULL, 200);
|
||||
if (!string) {
|
||||
ret = -2;
|
||||
goto ret_close_file;
|
||||
}
|
||||
|
||||
/* Loop over layers and write CSV lines */
|
||||
for (info_iter = settings->layer_infos; info_iter; info_iter = info_iter->next) {
|
||||
linfo = (struct layer_info *)info_iter->data;
|
||||
|
||||
layer_settings_gen_csv_line(string, linfo);
|
||||
g_output_stream_write(w_fstream, string->str, string->len * sizeof(gchar), NULL, NULL);
|
||||
}
|
||||
|
||||
/* Delete string */
|
||||
g_string_free(string, TRUE);
|
||||
ret_close_file:
|
||||
g_output_stream_flush(w_fstream, NULL, NULL);
|
||||
g_output_stream_close(w_fstream, NULL, NULL);
|
||||
g_object_unref(w_fstream);
|
||||
ret_unref_file:
|
||||
g_object_unref(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load a line from \p stream and parse try to parse it as layer information
|
||||
* @param stream Input data stream
|
||||
* @param linfo Layer info struct to fill
|
||||
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
|
||||
*/
|
||||
static int layer_settings_load_csv_line_from_stream(GDataInputStream *stream, struct layer_info *linfo)
|
||||
{
|
||||
int ret;
|
||||
gsize len;
|
||||
gchar *line;
|
||||
GRegex *regex;
|
||||
GMatchInfo *mi;
|
||||
char *match;
|
||||
|
||||
if (!linfo) {
|
||||
ret = 1;
|
||||
goto ret_direct;
|
||||
}
|
||||
|
||||
regex = g_regex_new("^(?<layer>[0-9]+),(?<r>[0-9\\.]+),(?<g>[0-9\\.]+),(?<b>[0-9\\.]+),(?<a>[0-9\\.]+),(?<export>[01]),(?<name>.*)$", 0, 0, NULL);
|
||||
|
||||
line = g_data_input_stream_read_line(stream, &len, NULL, NULL);
|
||||
if (!line) {
|
||||
ret = -1;
|
||||
goto destroy_regex;
|
||||
}
|
||||
|
||||
/* Match line in CSV */
|
||||
g_regex_match(regex, line, 0, &mi);
|
||||
if (g_match_info_matches(mi)) {
|
||||
/* Line is valid */
|
||||
match = g_match_info_fetch_named(mi, "layer");
|
||||
linfo->layer = (int)g_ascii_strtoll(match, NULL, 10);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "r");
|
||||
linfo->color.red = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "g");
|
||||
linfo->color.green = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "b");
|
||||
linfo->color.blue = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "a");
|
||||
linfo->color.alpha = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "export");
|
||||
linfo->render = ((!strcmp(match, "1")) ? 1 : 0);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "name");
|
||||
linfo->name = match;
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Line is malformatted */
|
||||
printf("Could not recognize line in CSV as valid entry: %s\n", line);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
g_match_info_free(mi);
|
||||
g_free(line);
|
||||
destroy_regex:
|
||||
g_regex_unref(regex);
|
||||
ret_direct:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int layer_settings_load_from_csv(LayerSettings *settings, const char *path)
|
||||
{
|
||||
GFile *file;
|
||||
int ret = 0;
|
||||
GInputStream *in_stream;
|
||||
GDataInputStream *data_stream;
|
||||
int parser_ret;
|
||||
int stacked_pos;
|
||||
struct layer_info linfo;
|
||||
|
||||
file = g_file_new_for_path(path);
|
||||
in_stream = G_INPUT_STREAM(g_file_read(file, NULL, NULL));
|
||||
|
||||
g_return_val_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings), -2);
|
||||
|
||||
if (!in_stream) {
|
||||
ret = -1;
|
||||
goto ret_destroy_file;
|
||||
}
|
||||
/* Delete old settings */
|
||||
layer_settings_clear(settings);
|
||||
|
||||
data_stream = g_data_input_stream_new(in_stream);
|
||||
|
||||
stacked_pos = 0;
|
||||
while ((parser_ret = layer_settings_load_csv_line_from_stream(data_stream, &linfo)) >= 0) {
|
||||
/* Line broken */
|
||||
if (parser_ret == 1)
|
||||
continue;
|
||||
|
||||
linfo.stacked_position = stacked_pos++;
|
||||
|
||||
layer_settings_append_layer_info(settings, &linfo);
|
||||
/* Clear name to prevent memory leak */
|
||||
if (linfo.name)
|
||||
g_free(linfo.name);
|
||||
}
|
||||
|
||||
g_object_unref(data_stream);
|
||||
g_object_unref(in_stream);
|
||||
ret_destroy_file:
|
||||
g_object_unref(file);
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mapping-parser.c
|
||||
* @brief Function to read a mapping file line and parse it.
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Mapping-Parser
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gds-render/layer/mapping-parser.h>
|
||||
|
||||
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
|
||||
{
|
||||
int ret;
|
||||
gsize len;
|
||||
gchar *line;
|
||||
GRegex *regex;
|
||||
GMatchInfo *mi;
|
||||
char *match;
|
||||
|
||||
if ((!export) || (!name) || (!layer) || (!color)) {
|
||||
ret = 1;
|
||||
goto ret_direct;
|
||||
}
|
||||
|
||||
regex = g_regex_new("^(?<layer>[0-9]+),(?<r>[0-9\\.]+),(?<g>[0-9\\.]+),(?<b>[0-9\\.]+),(?<a>[0-9\\.]+),(?<export>[01]),(?<name>.*)$", 0, 0, NULL);
|
||||
|
||||
line = g_data_input_stream_read_line(stream, &len, NULL, NULL);
|
||||
if (!line) {
|
||||
ret = -1;
|
||||
goto destroy_regex;
|
||||
}
|
||||
|
||||
/* Match line in CSV */
|
||||
g_regex_match(regex, line, 0, &mi);
|
||||
if (g_match_info_matches(mi)) {
|
||||
/* Line is valid */
|
||||
match = g_match_info_fetch_named(mi, "layer");
|
||||
*layer = (int)g_ascii_strtoll(match, NULL, 10);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "r");
|
||||
color->red = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "g");
|
||||
color->green = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "b");
|
||||
color->blue = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "a");
|
||||
color->alpha = g_ascii_strtod(match, NULL);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "export");
|
||||
*export = ((!strcmp(match, "1")) ? TRUE : FALSE);
|
||||
g_free(match);
|
||||
match = g_match_info_fetch_named(mi, "name");
|
||||
*name = match;
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Line is malformatted */
|
||||
printf("Could not recognize line in CSV as valid entry: %s\n", line);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
g_match_info_free(mi);
|
||||
g_free(line);
|
||||
destroy_regex:
|
||||
g_regex_unref(regex);
|
||||
ret_direct:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
|
||||
{
|
||||
int i;
|
||||
GString *string;
|
||||
gboolean export;
|
||||
const gchar *name;
|
||||
int layer;
|
||||
GdkRGBA color;
|
||||
|
||||
string = g_string_new_len(NULL, max_len-1);
|
||||
|
||||
/* Extract values */
|
||||
export = layer_element_get_export(layer_element);
|
||||
name = (const gchar*)layer_element_get_name(layer_element);
|
||||
layer = layer_element_get_layer(layer_element);
|
||||
layer_element_get_color(layer_element, &color);
|
||||
|
||||
/* print values to line */
|
||||
g_string_printf(string, "%d:%lf:%lf:%lf:%lf:%d:%s\n",
|
||||
layer, color.red, color.green,
|
||||
color.blue, color.alpha, (export == TRUE ? 1 : 0), name);
|
||||
/* Fix broken locale settings */
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ',')
|
||||
string->str[i] = '.';
|
||||
}
|
||||
|
||||
for (i = 0; string->str[i]; i++) {
|
||||
if (string->str[i] == ':')
|
||||
string->str[i] = ',';
|
||||
}
|
||||
|
||||
if (string->len > (max_len-1)) {
|
||||
printf("Layer Definition too long. Please shorten Layer Name!!\n");
|
||||
line_buffer[0] = 0x0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy max_len bytes of string */
|
||||
strncpy(line_buffer, (char *)string->str, max_len-1);
|
||||
line_buffer[max_len-1] = 0;
|
||||
|
||||
/* Completely remove string */
|
||||
g_string_free(string, TRUE);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
167
main.c
167
main.c
@ -26,10 +26,12 @@
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <gds-render/gds-render-gui.h>
|
||||
#include <gds-render/command-line.h>
|
||||
#include <gds-render/external-renderer.h>
|
||||
#include <gds-render/output-renderers/external-renderer.h>
|
||||
#include <gds-render/version.h>
|
||||
|
||||
/**
|
||||
@ -89,14 +91,21 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_
|
||||
(void)user_data;
|
||||
(void)action;
|
||||
(void)parameter;
|
||||
GString *comment_text;
|
||||
|
||||
builder = gtk_builder_new_from_resource("/about.glade");
|
||||
comment_text = g_string_new(_("gds-render is a free tool for rendering GDS2 layout files into vector graphics."));
|
||||
g_string_append_printf(comment_text, _("\n\nFull git commit: %s"), _app_git_commit);
|
||||
|
||||
builder = gtk_builder_new_from_resource("/gui/about.glade");
|
||||
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
|
||||
gtk_window_set_transient_for(GTK_WINDOW(dialog), NULL);
|
||||
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), _app_version_string);
|
||||
gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), comment_text->str);
|
||||
|
||||
g_string_free(comment_text, TRUE);
|
||||
|
||||
/* Load icon from resource */
|
||||
logo_buf = gdk_pixbuf_new_from_resource_at_scale("/logo.svg", 100, 100, TRUE, &error);
|
||||
logo_buf = gdk_pixbuf_new_from_resource_at_scale("/images/logo.svg", 100, 100, TRUE, &error);
|
||||
if (logo_buf) {
|
||||
/* Set logo */
|
||||
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), logo_buf);
|
||||
@ -104,7 +113,7 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_
|
||||
/* Pixbuf is now owned by about dialog. Unref */
|
||||
g_object_unref(logo_buf);
|
||||
} else if (error) {
|
||||
fprintf(stderr, "Logo could not be displayed: %s\n", error->message);
|
||||
fprintf(stderr, _("Logo could not be displayed: %s\n"), error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
@ -117,16 +126,16 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_
|
||||
/**
|
||||
* @brief Contains the application menu entries
|
||||
*/
|
||||
const static GActionEntry app_actions[] = {
|
||||
{"quit", app_quit, NULL, NULL, NULL, {0}},
|
||||
{"about", app_about, NULL, NULL, NULL, {0}}
|
||||
static const GActionEntry app_actions[] = {
|
||||
{ "quit", app_quit, NULL, NULL, NULL, {0} },
|
||||
{ "about", app_about, NULL, NULL, NULL, {0} },
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Called when a GUI main window is closed
|
||||
*
|
||||
* The GdsRenderGui object associated with the closed main window
|
||||
* is removed from the list of open GUIs (\p user_data) and unreferenced.
|
||||
* is removed from the list of open GUIs (\p user_data) and dereferenced.
|
||||
*
|
||||
* @param gui The GUI instance the closed main window belongs to
|
||||
* @param user_data List of GUIs
|
||||
@ -149,7 +158,6 @@ static void gapp_activate(GApplication *app, gpointer user_data)
|
||||
{
|
||||
GtkWindow *main_window;
|
||||
GdsRenderGui *gui;
|
||||
|
||||
struct application_data * const appdata = (struct application_data *)user_data;
|
||||
|
||||
gui = gds_render_gui_new();
|
||||
@ -176,8 +184,8 @@ static void gapp_activate(GApplication *app, gpointer user_data)
|
||||
*/
|
||||
static int start_gui(int argc, char **argv)
|
||||
{
|
||||
|
||||
GtkApplication *gapp;
|
||||
GString *application_domain;
|
||||
int app_status;
|
||||
static struct application_data appdata = {
|
||||
.gui_list = NULL
|
||||
@ -186,21 +194,30 @@ static int start_gui(int argc, char **argv)
|
||||
GMenu *m_quit;
|
||||
GMenu *m_about;
|
||||
|
||||
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
|
||||
/*
|
||||
* Generate version dependent application id
|
||||
* This allows running the application in different versions at the same time.
|
||||
*/
|
||||
application_domain = g_string_new(NULL);
|
||||
g_string_printf(application_domain, "de.shimatta.gds_render_%s", _app_git_commit);
|
||||
|
||||
gapp = gtk_application_new(application_domain->str, G_APPLICATION_FLAGS_NONE);
|
||||
g_string_free(application_domain, TRUE);
|
||||
|
||||
g_application_register(G_APPLICATION(gapp), NULL, NULL);
|
||||
g_signal_connect(gapp, "activate", G_CALLBACK(gapp_activate), &appdata);
|
||||
|
||||
if (g_application_get_is_remote(G_APPLICATION(gapp)) == TRUE) {
|
||||
g_application_activate(G_APPLICATION(gapp));
|
||||
printf("There is already an open instance. Will open second window in said instance.\n");
|
||||
printf(_("There is already an open instance. Will open second window in that instance.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
menu = g_menu_new();
|
||||
m_quit = g_menu_new();
|
||||
m_about = g_menu_new();
|
||||
g_menu_append(m_quit, "Quit", "app.quit");
|
||||
g_menu_append(m_about, "About", "app.about");
|
||||
g_menu_append(m_quit, _("Quit"), "app.quit");
|
||||
g_menu_append(m_about, _("About"), "app.about");
|
||||
g_menu_append_section(menu, NULL, G_MENU_MODEL(m_about));
|
||||
g_menu_append_section(menu, NULL, G_MENU_MODEL(m_quit));
|
||||
g_action_map_add_action_entries(G_ACTION_MAP(gapp), app_actions,
|
||||
@ -224,7 +241,7 @@ static int start_gui(int argc, char **argv)
|
||||
*/
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n",
|
||||
printf(_("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n"),
|
||||
_app_version_string);
|
||||
}
|
||||
|
||||
@ -240,42 +257,55 @@ int main(int argc, char **argv)
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
gchar *gds_name;
|
||||
gchar *basename;
|
||||
gchar *pdfname = NULL, *texname = NULL, *mappingname = NULL, *cellname = NULL, *svgname = NULL;
|
||||
gboolean tikz = FALSE, pdf = FALSE, pdf_layers = FALSE, pdf_standalone = FALSE, svg = FALSE;
|
||||
gboolean version = FALSE;
|
||||
gchar *custom_library_path = NULL;
|
||||
gchar *custom_library_file_name = NULL;
|
||||
gchar **output_paths = NULL;
|
||||
gchar *mappingname = NULL;
|
||||
gchar *cellname = NULL;
|
||||
gchar **renderer_args = NULL;
|
||||
gboolean version = FALSE, pdf_standalone = FALSE, pdf_layers = FALSE;
|
||||
gboolean analyze = FALSE;
|
||||
gchar *format = NULL;
|
||||
int scale = 1000;
|
||||
int app_status = 0;
|
||||
struct external_renderer_params so_render_params;
|
||||
|
||||
so_render_params.so_path = NULL;
|
||||
so_render_params.cli_params = NULL;
|
||||
|
||||
bindtextdomain(GETTEXT_PACKAGE, LOCALEDATADIR "/locale");
|
||||
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain(GETTEXT_PACKAGE);
|
||||
|
||||
GOptionEntry entries[] = {
|
||||
{"version", 'v', 0, G_OPTION_ARG_NONE, &version, "Print version", NULL},
|
||||
{"tikz", 't', 0, G_OPTION_ARG_NONE, &tikz, "Output TikZ code", NULL },
|
||||
{"pdf", 'p', 0, G_OPTION_ARG_NONE, &pdf, "Output PDF document", NULL },
|
||||
//{"svg", 'S', 0, G_OPTION_ARG_NONE, &svg, "Output SVG image", NULL },
|
||||
{"scale", 's', 0, G_OPTION_ARG_INT, &scale, "Divide output coordinates by <SCALE>", "<SCALE>" },
|
||||
{"tex-output", 'o', 0, G_OPTION_ARG_FILENAME, &texname, "Optional path for TeX file", "PATH" },
|
||||
{"pdf-output", 'O', 0, G_OPTION_ARG_FILENAME, &pdfname, "Optional path for PDF file", "PATH" },
|
||||
//{"svg-output", 0, 0, G_OPTION_ARG_FILENAME, &svgname, "Optional path for PDF file", "PATH"},
|
||||
{"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, "Path for Layer Mapping File", "PATH" },
|
||||
{"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, "Cell to render", "NAME" },
|
||||
{"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, "Create standalone PDF", NULL },
|
||||
{"tex-layers", 'l', 0, G_OPTION_ARG_NONE, &pdf_layers, "Create PDF Layers (OCG)", NULL },
|
||||
{"custom-render-lib", 'P', 0, G_OPTION_ARG_FILENAME, &custom_library_path, "Path to a custom shared object, that implements the " EXTERNAL_LIBRARY_FUNCTION " function", "PATH"},
|
||||
{"external-lib-output", 'e', 0, G_OPTION_ARG_FILENAME, &custom_library_file_name, "Output path for external render library", "PATH"},
|
||||
{NULL}
|
||||
{"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 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>" },
|
||||
{"output-file", 'o', 0, G_OPTION_ARG_FILENAME_ARRAY, &output_paths,
|
||||
_("Output file path. Can be used multiple times."), "PATH" },
|
||||
{"mapping", 'm', 0, G_OPTION_ARG_FILENAME, &mappingname, _("Path for Layer Mapping File"), "PATH" },
|
||||
{"cell", 'c', 0, G_OPTION_ARG_STRING, &cellname, _("Cell to render"), "NAME" },
|
||||
{"tex-standalone", 'a', 0, G_OPTION_ARG_NONE, &pdf_standalone, _("Create standalone TeX"), NULL },
|
||||
{"tex-layers", 'l', 0, G_OPTION_ARG_NONE, &pdf_layers, _("Create PDF Layers (OCG)"), NULL },
|
||||
{"custom-render-lib", 'P', 0, G_OPTION_ARG_FILENAME, &so_render_params.so_path,
|
||||
_("Path to a custom shared object, that implements the necessary rendering functions"), "PATH"},
|
||||
{"render-lib-params", 'W', 0, G_OPTION_ARG_STRING, &so_render_params.cli_params,
|
||||
_("Argument string passed to render lib"), NULL},
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
context = g_option_context_new(" FILE - Convert GDS file <FILE> to graphic");
|
||||
context = g_option_context_new(_(" FILE - Convert GDS file <FILE> to graphic"));
|
||||
g_option_context_add_main_entries(context, entries, NULL);
|
||||
g_option_context_add_group(context, gtk_get_option_group(TRUE));
|
||||
|
||||
if (!g_option_context_parse(context, &argc, &argv, &error)) {
|
||||
g_print("Option parsing failed: %s\n", error->message);
|
||||
g_print(_("Option parsing failed: %s\n"), error->message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_option_context_free(context);
|
||||
|
||||
if (version) {
|
||||
print_version();
|
||||
goto ret_status;
|
||||
@ -283,52 +313,45 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc >= 2) {
|
||||
if (scale < 1) {
|
||||
printf("Scale < 1 not allowed. Setting to 1\n");
|
||||
printf(_("Scale < 1 not allowed. Setting to 1\n"));
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
/* No format selected */
|
||||
if (!(tikz || pdf || svg))
|
||||
tikz = TRUE;
|
||||
|
||||
/* Get gds name */
|
||||
gds_name = argv[1];
|
||||
|
||||
/* Print out additional arguments as ignored */
|
||||
for (i = 2; i < argc; i++) {
|
||||
printf("Ignored argument: %s", argv[i]);
|
||||
for (i = 2; i < argc; i++)
|
||||
printf(_("Ignored argument: %s"), argv[i]);
|
||||
|
||||
if (analyze) {
|
||||
app_status = command_line_analyze_lib(format, gds_name);
|
||||
} else {
|
||||
app_status =
|
||||
command_line_convert_gds(gds_name, cellname, renderer_args, output_paths, mappingname,
|
||||
&so_render_params, pdf_standalone, pdf_layers, scale);
|
||||
}
|
||||
|
||||
/* Check if PDF/TeX names are supplied. if not generate */
|
||||
basename = g_path_get_basename(gds_name);
|
||||
|
||||
if (!texname)
|
||||
texname = g_strdup_printf("./%s.tex", basename);
|
||||
|
||||
if (!pdfname)
|
||||
pdfname = g_strdup_printf("./%s.pdf", basename);
|
||||
|
||||
if (!svgname)
|
||||
svgname = g_strdup_printf("./%s.svg", basename);
|
||||
|
||||
command_line_convert_gds(gds_name, pdfname, texname, pdf, tikz,
|
||||
mappingname, cellname, (double)scale,
|
||||
pdf_layers, pdf_standalone, svg, svgname,
|
||||
custom_library_path, custom_library_file_name);
|
||||
/* Clean up */
|
||||
g_free(pdfname);
|
||||
g_free(texname);
|
||||
g_free(svgname);
|
||||
g_free(basename);
|
||||
if (mappingname)
|
||||
g_free(mappingname);
|
||||
if (cellname)
|
||||
g_free(cellname);
|
||||
app_status = 0;
|
||||
} else {
|
||||
app_status = start_gui(argc, argv);
|
||||
}
|
||||
|
||||
ret_status:
|
||||
/* If necessary, free command line parameters.
|
||||
* This is only really necessary for automated mem-leak testing.
|
||||
* Omitting these frees would be perfectly fine.
|
||||
*/
|
||||
if (output_paths)
|
||||
g_strfreev(output_paths);
|
||||
if (renderer_args)
|
||||
g_strfreev(renderer_args);
|
||||
if (mappingname)
|
||||
g_free(mappingname);
|
||||
if (cellname)
|
||||
free(cellname);
|
||||
if (so_render_params.so_path)
|
||||
free(so_render_params.so_path);
|
||||
if (so_render_params.cli_params)
|
||||
g_free(so_render_params.cli_params);
|
||||
|
||||
return app_status;
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file cairo-output.c
|
||||
* @brief Output renderer for Cairo PDF export
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
* @file cairo-renderer.c
|
||||
* @brief Output renderer for Cairo PDF export
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/** @addtogroup Cairo-Renderer
|
||||
* @{
|
||||
@ -31,8 +31,18 @@
|
||||
#include <cairo.h>
|
||||
#include <cairo-pdf.h>
|
||||
#include <cairo-svg.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <gds-render/cairo-renderer/cairo-output.h>
|
||||
#include <gds-render/output-renderers/cairo-renderer.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct _CairoRenderer {
|
||||
GdsOutputRenderer parent;
|
||||
gboolean svg; /**< @brief TRUE: SVG output, FALSE: PDF output */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(CairoRenderer, cairo_renderer, GDS_RENDER_TYPE_OUTPUT_RENDERER)
|
||||
|
||||
/**
|
||||
* @brief The cairo_layer struct
|
||||
@ -65,7 +75,7 @@ static void revert_inherited_transform(struct cairo_layer *layers)
|
||||
* @param origin Origin translation
|
||||
* @param magnification Scaling
|
||||
* @param flipping Mirror image on x-axis before rotating
|
||||
* @param rotation Rotattion in degrees
|
||||
* @param rotation Rotation in degrees
|
||||
* @param scale Scale the image down by. Only used for sclaing origin coordinates. Not applied to layer.
|
||||
*/
|
||||
static void apply_inherited_transform_to_all_layers(struct cairo_layer *layers,
|
||||
@ -112,7 +122,8 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
/* Render child cells */
|
||||
for (instance_list = cell->child_cells; instance_list != NULL; instance_list = instance_list->next) {
|
||||
cell_instance = (struct gds_cell_instance *)instance_list->data;
|
||||
if ((temp_cell = cell_instance->cell_ref) != NULL) {
|
||||
temp_cell = cell_instance->cell_ref;
|
||||
if (temp_cell != NULL) {
|
||||
apply_inherited_transform_to_all_layers(layers,
|
||||
&cell_instance->origin,
|
||||
cell_instance->magnification,
|
||||
@ -131,7 +142,9 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
/* Get layer renderer */
|
||||
if (gfx->layer >= MAX_LAYERS)
|
||||
continue;
|
||||
if ((cr = layers[gfx->layer].cr) == NULL)
|
||||
|
||||
cr = layers[gfx->layer].cr;
|
||||
if (cr == NULL)
|
||||
continue;
|
||||
|
||||
/* Apply settings */
|
||||
@ -158,7 +171,6 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
cairo_move_to(cr, vertex->x/scale, vertex->y/scale);
|
||||
else
|
||||
cairo_line_to(cr, vertex->x/scale, vertex->y/scale);
|
||||
|
||||
}
|
||||
|
||||
/* Create graphics object */
|
||||
@ -167,6 +179,7 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
cairo_stroke(cr);
|
||||
break;
|
||||
case GRAPHIC_BOX:
|
||||
/* Expected fallthrough */
|
||||
case GRAPHIC_POLYGON:
|
||||
cairo_set_line_width(cr, 0.1/scale);
|
||||
cairo_close_path(cr);
|
||||
@ -174,15 +187,58 @@ static void render_cell(struct gds_cell *cell, struct cairo_layer *layers, doubl
|
||||
cairo_fill(cr);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} /* for gfx list */
|
||||
}
|
||||
|
||||
void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos, char *pdf_file, char *svg_file, double scale)
|
||||
/**
|
||||
* @brief Read a line from a file descriptor
|
||||
*
|
||||
* In case of a broken pipe / closed writing end, it will terminate
|
||||
*
|
||||
* @param fd File descriptor to read from
|
||||
* @param buff Buffer to write data in
|
||||
* @param buff_size Buffer size
|
||||
* @return length of read data
|
||||
*/
|
||||
static int read_line_from_fd(int fd, char *buff, size_t buff_size)
|
||||
{
|
||||
cairo_surface_t *pdf_surface, *svg_surface;
|
||||
cairo_t *pdf_cr, *svg_cr;
|
||||
ssize_t cnt;
|
||||
char c;
|
||||
unsigned int buff_cnt = 0;
|
||||
|
||||
while ((cnt = read(fd, &c, 1)) == 1) {
|
||||
if (buff_cnt < (buff_size-1)) {
|
||||
buff[buff_cnt++] = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buff[buff_cnt] = 0;
|
||||
return (int)buff_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Render \p cell to a PDF file specified by \p pdf_file
|
||||
* @param renderer The current renderer this function is running from
|
||||
* @param cell Toplevel cell to @ref Cairo-Renderer
|
||||
* @param layer_infos List of layer information. Specifies color and layer stacking
|
||||
* @param pdf_file PDF output file. Set to NULL if no PDF file has to be generated
|
||||
* @param svg_file SVG output file. Set to NULL if no SVG file has to be generated
|
||||
* @param scale Scale the output image down by \p scale
|
||||
* @return Error
|
||||
*/
|
||||
static int cairo_renderer_render_cell_to_vector_file(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
GList *layer_infos,
|
||||
const char *pdf_file,
|
||||
const char *svg_file,
|
||||
double scale)
|
||||
{
|
||||
cairo_surface_t *pdf_surface = NULL, *svg_surface = NULL;
|
||||
cairo_t *pdf_cr = NULL, *svg_cr = NULL;
|
||||
struct layer_info *linfo;
|
||||
struct cairo_layer *layers;
|
||||
struct cairo_layer *lay;
|
||||
@ -190,12 +246,49 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
int i;
|
||||
double rec_x0, rec_y0, rec_width, rec_height;
|
||||
double xmin = INT32_MAX, xmax = INT32_MIN, ymin = INT32_MAX, ymax = INT32_MIN;
|
||||
pid_t process_id;
|
||||
int comm_pipe[2];
|
||||
char receive_message[200];
|
||||
|
||||
if (pdf_file == NULL && svg_file == NULL) {
|
||||
/* No output specified */
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate communication pipe for status updates */
|
||||
if (pipe(comm_pipe) == -1)
|
||||
return -2;
|
||||
|
||||
/* Fork to a new child process. This ensures the memory leaks (see issue #16) in Cairo don't
|
||||
* brick everything.
|
||||
*
|
||||
* And by the way: This now bricks all Windows compatibility. Deal with it.
|
||||
*/
|
||||
process_id = fork();
|
||||
//process_id = -1;
|
||||
if (process_id < 0) {
|
||||
/* This should not happen */
|
||||
fprintf(stderr, _("Fatal error: Cairo Renderer: Could not spawn child process!"));
|
||||
exit(-2);
|
||||
} else if (process_id > 0) {
|
||||
/* Woohoo... Successfully dumped the shitty code to an unknowing victim */
|
||||
goto ret_parent;
|
||||
}
|
||||
|
||||
/* 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(comm_pipe[0]);
|
||||
|
||||
layers = (struct cairo_layer *)calloc(MAX_LAYERS, sizeof(struct cairo_layer));
|
||||
|
||||
/* Clear layers */
|
||||
@ -208,6 +301,10 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
for (info_list = layer_infos; info_list != NULL; info_list = g_list_next(info_list)) {
|
||||
linfo = (struct layer_info *)info_list->data;
|
||||
if (linfo->layer < MAX_LAYERS) {
|
||||
/* Layer shall not be rendered */
|
||||
if (!linfo->render)
|
||||
continue;
|
||||
|
||||
lay = &(layers[(unsigned int)linfo->layer]);
|
||||
lay->linfo = linfo;
|
||||
lay->rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,
|
||||
@ -221,7 +318,7 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dprintf(comm_pipe[1], "Rendering layers\n");
|
||||
render_cell(cell, layers, scale);
|
||||
|
||||
/* get size of image and top left coordinate */
|
||||
@ -229,14 +326,17 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
linfo = (struct layer_info *)info_list->data;
|
||||
|
||||
if (linfo->layer >= MAX_LAYERS) {
|
||||
printf("Layer outside of Spec.\n");
|
||||
printf(_("Layer number too high / outside of spec.\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!linfo->render)
|
||||
continue;
|
||||
|
||||
/* Print size */
|
||||
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
|
||||
&rec_width, &rec_height);
|
||||
printf("Size of layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n",
|
||||
dprintf(comm_pipe[1], _("Size of layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n"),
|
||||
linfo->layer,
|
||||
(linfo->name && linfo->name[0] ? " (" : ""),
|
||||
(linfo->name && linfo->name[0] ? linfo->name : ""),
|
||||
@ -255,7 +355,7 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
|
||||
}
|
||||
|
||||
printf("Cell bounding box: (%lf | %lf) -- (%lf | %lf)\n", xmin, ymin, xmax, ymax);
|
||||
/* printf("Cell bounding box: (%lf | %lf) -- (%lf | %lf)\n", xmin, ymin, xmax, ymax); */
|
||||
|
||||
if (pdf_file) {
|
||||
pdf_surface = cairo_pdf_surface_create(pdf_file, xmax-xmin, ymax-ymin);
|
||||
@ -272,20 +372,24 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
linfo = (struct layer_info *)info_list->data;
|
||||
|
||||
if (linfo->layer >= MAX_LAYERS) {
|
||||
printf("Layer outside of Spec.\n");
|
||||
printf(_("Layer outside of spec.\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdf_file) {
|
||||
if (!linfo->render)
|
||||
continue;
|
||||
|
||||
dprintf(comm_pipe[1], _("Exporting layer %d to file\n"), linfo->layer);
|
||||
|
||||
if (pdf_file && pdf_cr) {
|
||||
cairo_set_source_surface(pdf_cr, layers[linfo->layer].rec, -xmin, -ymin);
|
||||
cairo_paint_with_alpha(pdf_cr, linfo->color.alpha);
|
||||
}
|
||||
|
||||
if (svg_file) {
|
||||
if (svg_file && svg_cr) {
|
||||
cairo_set_source_surface(svg_cr, layers[linfo->layer].rec, -xmin, -ymin);
|
||||
cairo_paint_with_alpha(svg_cr, linfo->color.alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (pdf_file) {
|
||||
@ -303,14 +407,105 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
|
||||
ret_clear_layers:
|
||||
for (i = 0; i < MAX_LAYERS; i++) {
|
||||
lay = &layers[i];
|
||||
if(lay->cr) {
|
||||
if (lay->cr) {
|
||||
cairo_destroy(lay->cr);
|
||||
cairo_surface_destroy(lay->rec);
|
||||
}
|
||||
}
|
||||
free(layers);
|
||||
|
||||
printf("cairo export finished. It might still be buggy!\n");
|
||||
printf(_("Cairo export finished. It might still be buggy!\n"));
|
||||
|
||||
/* Suspend child process */
|
||||
exit(0);
|
||||
|
||||
ret_parent:
|
||||
close(comm_pipe[1]);
|
||||
|
||||
while (read_line_from_fd(comm_pipe[0], receive_message, sizeof(receive_message)) > 0) {
|
||||
/* Strip \n from string and replace with ' ' */
|
||||
for (i = 0; receive_message[i] != '\0'; i++) {
|
||||
if (receive_message[i] == '\n')
|
||||
receive_message[i] = ' ';
|
||||
}
|
||||
|
||||
/* Update asyc progress*/
|
||||
gds_output_renderer_update_async_progress(renderer, receive_message);
|
||||
}
|
||||
|
||||
waitpid(process_id, NULL, 0);
|
||||
|
||||
close(comm_pipe[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cairo_renderer_init(CairoRenderer *self)
|
||||
{
|
||||
/* PDF default */
|
||||
self->svg = FALSE;
|
||||
}
|
||||
|
||||
static int cairo_renderer_render_output(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale)
|
||||
{
|
||||
CairoRenderer *c_renderer = GDS_RENDER_CAIRO_RENDERER(renderer);
|
||||
const char *pdf_file = NULL;
|
||||
const char *svg_file = NULL;
|
||||
LayerSettings *settings;
|
||||
GList *layer_infos = NULL;
|
||||
const char *output_file;
|
||||
int ret;
|
||||
|
||||
if (!c_renderer)
|
||||
return -2000;
|
||||
|
||||
output_file = gds_output_renderer_get_output_file(renderer);
|
||||
settings = gds_output_renderer_get_and_ref_layer_settings(renderer);
|
||||
|
||||
/* Set layer info list. In case of failure it remains NULL */
|
||||
if (settings)
|
||||
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||
|
||||
if (c_renderer->svg == TRUE)
|
||||
svg_file = output_file;
|
||||
else
|
||||
pdf_file = output_file;
|
||||
|
||||
gds_output_renderer_update_async_progress(renderer, _("Rendering Cairo Output..."));
|
||||
ret = cairo_renderer_render_cell_to_vector_file(renderer, cell, layer_infos, pdf_file, svg_file, scale);
|
||||
|
||||
if (settings)
|
||||
g_object_unref(settings);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cairo_renderer_class_init(CairoRendererClass *klass)
|
||||
{
|
||||
GdsOutputRendererClass *renderer_class = GDS_RENDER_OUTPUT_RENDERER_CLASS(klass);
|
||||
|
||||
renderer_class->render_output = cairo_renderer_render_output;
|
||||
}
|
||||
|
||||
CairoRenderer *cairo_renderer_new_pdf()
|
||||
{
|
||||
CairoRenderer *renderer;
|
||||
|
||||
renderer = GDS_RENDER_CAIRO_RENDERER(g_object_new(GDS_RENDER_TYPE_CAIRO_RENDERER, NULL));
|
||||
renderer->svg = FALSE;
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
CairoRenderer *cairo_renderer_new_svg()
|
||||
{
|
||||
CairoRenderer *renderer;
|
||||
|
||||
renderer = GDS_RENDER_CAIRO_RENDERER(g_object_new(GDS_RENDER_TYPE_CAIRO_RENDERER, NULL));
|
||||
renderer->svg = TRUE;
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/** @} */
|
281
output-renderers/external-renderer.c
Normal file
281
output-renderers/external-renderer.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file external-renderer.c
|
||||
* @brief This file implements the dynamic library loading for the external rendering feature
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup ExternalRenderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <gds-render/output-renderers/external-renderer.h>
|
||||
#include <gds-render/version.h>
|
||||
|
||||
#define FORCE_FORK 0U /**< @brief if != 0, then forking is forced regardless of the shared object's settings */
|
||||
|
||||
struct _ExternalRenderer {
|
||||
GdsOutputRenderer parent;
|
||||
char *shared_object_path;
|
||||
char *cli_param_string;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_SO_PATH = 1, /**< @brief Shared object path property */
|
||||
PROP_PARAM_STRING, /** @brief Shared object renderer parameter string from CLI */
|
||||
N_PROPERTIES /**< @brief Used to get property count */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ExternalRenderer, external_renderer, GDS_RENDER_TYPE_OUTPUT_RENDERER)
|
||||
|
||||
/**
|
||||
* @brief Execute render function in shared object to render the supplied cell
|
||||
* @param toplevel_cell Cell to render
|
||||
* @param layer_info_list Layer information (Color etc.)
|
||||
* @param output_file Destination file
|
||||
* @param scale the scaling value to scale the output cell down by.
|
||||
* @param so_path Path to shared object
|
||||
* @param params Parameters passed to EXTERNAL_LIBRARY_INIT_FUNCTION
|
||||
* @return 0 if successful
|
||||
*/
|
||||
static int external_renderer_render_cell(struct gds_cell *toplevel_cell, GList *layer_info_list,
|
||||
const char *output_file, double scale, const char *so_path, const char *params)
|
||||
{
|
||||
int (*so_render_func)(struct gds_cell *, GList *, const char *, double) = NULL;
|
||||
int (*so_init_func)(const char *, const char *) = NULL;
|
||||
void *so_handle = NULL;
|
||||
char *error_msg;
|
||||
int forking_req;
|
||||
int ret = 0;
|
||||
pid_t fork_pid = 0;
|
||||
int forked_status;
|
||||
|
||||
if (!so_path) {
|
||||
fprintf(stderr, _("Path to shared object not set!\n"));
|
||||
return -3000;
|
||||
}
|
||||
|
||||
/* Check parameter sanity */
|
||||
if (!output_file || !toplevel_cell || !layer_info_list)
|
||||
return -3000;
|
||||
|
||||
/* Load shared object */
|
||||
so_handle = dlopen(so_path, RTLD_LAZY);
|
||||
if (!so_handle) {
|
||||
fprintf(stderr, _("Could not load external library '%s'\nDetailed error is:\n%s\n"), so_path, dlerror());
|
||||
return -2000;
|
||||
}
|
||||
|
||||
/* Load rendering symbol from library */
|
||||
so_render_func = (int (*)(struct gds_cell *, GList *, const char *, double))
|
||||
dlsym(so_handle, xstr(EXTERNAL_LIBRARY_RENDER_FUNCTION));
|
||||
error_msg = dlerror();
|
||||
if (error_msg != NULL) {
|
||||
fprintf(stderr, _("Rendering function not found in library:\n%s\n"), error_msg);
|
||||
goto ret_close_so_handle;
|
||||
}
|
||||
|
||||
/* Load the init function */
|
||||
so_init_func = (int (*)(const char *, const char *))dlsym(so_handle, xstr(EXTERNAL_LIBRARY_INIT_FUNCTION));
|
||||
error_msg = dlerror();
|
||||
if (error_msg != NULL) {
|
||||
fprintf(stderr, _("Init function not found in library:\n%s\n"), error_msg);
|
||||
goto ret_close_so_handle;
|
||||
}
|
||||
|
||||
/* Check if forking is requested */
|
||||
if (dlsym(so_handle, xstr(EXTERNAL_LIBRARY_FORK_REQUEST)))
|
||||
forking_req = 1;
|
||||
else if (FORCE_FORK)
|
||||
forking_req = 1;
|
||||
else
|
||||
forking_req = 0;
|
||||
|
||||
/* Execute */
|
||||
|
||||
g_message(_("Calling external renderer."));
|
||||
|
||||
if (forking_req)
|
||||
fork_pid = fork();
|
||||
if (fork_pid != 0)
|
||||
goto end_forked;
|
||||
|
||||
ret = so_init_func(params, _app_version_string);
|
||||
if (!ret)
|
||||
ret = so_render_func(toplevel_cell, layer_info_list, output_file, scale);
|
||||
|
||||
/* If we are in a separate process, terminate here */
|
||||
if (forking_req)
|
||||
exit(ret);
|
||||
|
||||
/* The forked paths end here */
|
||||
end_forked:
|
||||
if (forking_req) {
|
||||
waitpid(fork_pid, &forked_status, 0);
|
||||
ret = WEXITSTATUS(forked_status);
|
||||
}
|
||||
|
||||
g_message(_("External renderer finished."));
|
||||
|
||||
ret_close_so_handle:
|
||||
dlclose(so_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int external_renderer_render_output(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale)
|
||||
{
|
||||
ExternalRenderer *ext_renderer = GDS_RENDER_EXTERNAL_RENDERER(renderer);
|
||||
LayerSettings *settings;
|
||||
GList *layer_infos = NULL;
|
||||
const char *output_file;
|
||||
int ret;
|
||||
|
||||
output_file = gds_output_renderer_get_output_file(renderer);
|
||||
settings = gds_output_renderer_get_and_ref_layer_settings(renderer);
|
||||
|
||||
/* Set layer info list. In case of failure it remains NULL */
|
||||
if (settings)
|
||||
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||
|
||||
ret = external_renderer_render_cell(cell, layer_infos, output_file, scale, ext_renderer->shared_object_path,
|
||||
ext_renderer->cli_param_string);
|
||||
if (settings)
|
||||
g_object_unref(settings);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void external_renderer_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ExternalRenderer *self;
|
||||
|
||||
self = GDS_RENDER_EXTERNAL_RENDERER(obj);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SO_PATH:
|
||||
g_value_set_string(value, self->shared_object_path);
|
||||
break;
|
||||
case PROP_PARAM_STRING:
|
||||
g_value_set_string(value, self->cli_param_string);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void external_renderer_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
ExternalRenderer *self;
|
||||
|
||||
self = GDS_RENDER_EXTERNAL_RENDERER(obj);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SO_PATH:
|
||||
if (self->shared_object_path)
|
||||
g_free(self->shared_object_path);
|
||||
self->shared_object_path = g_value_dup_string(value);
|
||||
break;
|
||||
case PROP_PARAM_STRING:
|
||||
if (self->cli_param_string)
|
||||
g_free(self->cli_param_string);
|
||||
self->cli_param_string = g_value_dup_string(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void external_renderer_dispose(GObject *self_obj)
|
||||
{
|
||||
ExternalRenderer *self;
|
||||
|
||||
self = GDS_RENDER_EXTERNAL_RENDERER(self_obj);
|
||||
|
||||
if (self->shared_object_path) {
|
||||
g_free(self->shared_object_path);
|
||||
self->shared_object_path = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(external_renderer_parent_class)->dispose(self_obj);
|
||||
}
|
||||
|
||||
static GParamSpec *external_renderer_properties[N_PROPERTIES] = {NULL};
|
||||
|
||||
static void external_renderer_class_init(ExternalRendererClass *klass)
|
||||
{
|
||||
GdsOutputRendererClass *inherited_parent_class;
|
||||
GObjectClass *oclass;
|
||||
|
||||
inherited_parent_class = GDS_RENDER_OUTPUT_RENDERER_CLASS(klass);
|
||||
oclass = G_OBJECT_CLASS(klass);
|
||||
|
||||
/* Override virtual function */
|
||||
inherited_parent_class->render_output = external_renderer_render_output;
|
||||
|
||||
/* Setup Gobject callbacks */
|
||||
oclass->set_property = external_renderer_set_property;
|
||||
oclass->get_property = external_renderer_get_property;
|
||||
oclass->dispose = external_renderer_dispose;
|
||||
|
||||
/* Setup properties */
|
||||
external_renderer_properties[PROP_SO_PATH] =
|
||||
g_param_spec_string(N_("shared-object-path"),
|
||||
N_("Shared object file path"),
|
||||
N_("Path to the shared object to search rendering function in."),
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
external_renderer_properties[PROP_PARAM_STRING] =
|
||||
g_param_spec_string(N_("param-string"),
|
||||
N_("Shared object renderer parameter string"),
|
||||
N_("Command line arguments passed to the external shared object renderer"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_properties(oclass, N_PROPERTIES, external_renderer_properties);
|
||||
}
|
||||
|
||||
static void external_renderer_init(ExternalRenderer *self)
|
||||
{
|
||||
self->shared_object_path = NULL;
|
||||
self->cli_param_string = NULL;
|
||||
}
|
||||
|
||||
ExternalRenderer *external_renderer_new()
|
||||
{
|
||||
return g_object_new(GDS_RENDER_TYPE_EXTERNAL_RENDERER, NULL);
|
||||
}
|
||||
|
||||
ExternalRenderer *external_renderer_new_with_so_and_param(const char *so_path, const char *param_string)
|
||||
{
|
||||
return g_object_new(GDS_RENDER_TYPE_EXTERNAL_RENDERER, N_("shared-object-path"), so_path,
|
||||
N_("param-string"), param_string, NULL);
|
||||
}
|
||||
|
||||
/** @} */
|
455
output-renderers/gds-output-renderer.c
Normal file
455
output-renderers/gds-output-renderer.c
Normal file
@ -0,0 +1,455 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gds-output-renderer.c
|
||||
* @brief Base GObject class for output renderers
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/** @addtogroup GdsOutputRenderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gds-render/output-renderers/gds-output-renderer.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
struct renderer_params {
|
||||
struct gds_cell *cell;
|
||||
double scale;
|
||||
};
|
||||
|
||||
struct idle_function_params {
|
||||
GMutex message_lock;
|
||||
char *status_message;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
gchar *output_file;
|
||||
LayerSettings *layer_settings;
|
||||
GMutex settings_lock;
|
||||
gboolean mutex_init_status;
|
||||
GTask *task;
|
||||
GMainContext *main_context;
|
||||
struct renderer_params async_params;
|
||||
struct idle_function_params idle_function_parameters;
|
||||
gpointer padding[11];
|
||||
} GdsOutputRendererPrivate;
|
||||
|
||||
enum {
|
||||
PROP_OUTPUT_FILE = 1,
|
||||
PROP_LAYER_SETTINGS,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(GdsOutputRenderer, gds_output_renderer, G_TYPE_OBJECT)
|
||||
|
||||
enum gds_output_renderer_signal_ids {ASYNC_FINISHED = 0, ASYNC_PROGRESS_CHANGED, GDS_OUTPUT_RENDERER_SIGNAL_COUNT};
|
||||
static guint gds_output_renderer_signals[GDS_OUTPUT_RENDERER_SIGNAL_COUNT];
|
||||
|
||||
static int gds_output_renderer_render_dummy(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale)
|
||||
{
|
||||
(void)renderer;
|
||||
(void)cell;
|
||||
(void)scale;
|
||||
|
||||
g_warning(_("Output renderer does not define a render_output function!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gds_output_renderer_dispose(GObject *self_obj)
|
||||
{
|
||||
GdsOutputRenderer *renderer = GDS_RENDER_OUTPUT_RENDERER(self_obj);
|
||||
GdsOutputRendererPrivate *priv;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
|
||||
if (priv->mutex_init_status) {
|
||||
/* Try locking the mutex, to test if it's free */
|
||||
g_mutex_lock(&priv->settings_lock);
|
||||
g_mutex_unlock(&priv->settings_lock);
|
||||
g_mutex_clear(&priv->settings_lock);
|
||||
|
||||
g_mutex_lock(&priv->idle_function_parameters.message_lock);
|
||||
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||
g_mutex_clear(&priv->idle_function_parameters.message_lock);
|
||||
|
||||
priv->mutex_init_status = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object(&priv->task);
|
||||
|
||||
if (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);
|
||||
|
||||
/* Chain up to parent class */
|
||||
G_OBJECT_CLASS(gds_output_renderer_parent_class)->dispose(self_obj);
|
||||
}
|
||||
|
||||
static void gds_output_renderer_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GdsOutputRenderer *self = GDS_RENDER_OUTPUT_RENDERER(obj);
|
||||
GdsOutputRendererPrivate *priv;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(self);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_OUTPUT_FILE:
|
||||
g_value_set_string(value, priv->output_file);
|
||||
break;
|
||||
case PROP_LAYER_SETTINGS:
|
||||
g_value_set_object(value, priv->layer_settings);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gds_output_renderer_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GdsOutputRenderer *self = GDS_RENDER_OUTPUT_RENDERER(obj);
|
||||
GdsOutputRendererPrivate *priv;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(self);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_OUTPUT_FILE:
|
||||
g_mutex_lock(&priv->settings_lock);
|
||||
if (priv->output_file)
|
||||
g_free(priv->output_file);
|
||||
priv->output_file = g_strdup(g_value_get_string(value));
|
||||
g_mutex_unlock(&priv->settings_lock);
|
||||
break;
|
||||
case PROP_LAYER_SETTINGS:
|
||||
g_mutex_lock(&priv->settings_lock);
|
||||
g_clear_object(&priv->layer_settings);
|
||||
priv->layer_settings = g_value_get_object(value);
|
||||
g_object_ref(priv->layer_settings);
|
||||
g_mutex_unlock(&priv->settings_lock);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GParamSpec *gds_output_renderer_properties[N_PROPERTIES] = {NULL};
|
||||
|
||||
static void gds_output_renderer_class_init(GdsOutputRendererClass *klass)
|
||||
{
|
||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||
GType progress_changed_param_types[1] = {G_TYPE_POINTER};
|
||||
|
||||
klass->render_output = gds_output_renderer_render_dummy;
|
||||
|
||||
oclass->dispose = gds_output_renderer_dispose;
|
||||
oclass->set_property = gds_output_renderer_set_property;
|
||||
oclass->get_property = gds_output_renderer_get_property;
|
||||
|
||||
/* Setup properties */
|
||||
gds_output_renderer_properties[PROP_OUTPUT_FILE] =
|
||||
g_param_spec_string(N_("output-file"), N_("output file"), N_("Output file for renderer"),
|
||||
NULL, G_PARAM_READWRITE);
|
||||
gds_output_renderer_properties[PROP_LAYER_SETTINGS] =
|
||||
g_param_spec_object(N_("layer-settings"), N_("Layer Settings object"),
|
||||
N_("Object containing the layer rendering information"),
|
||||
GDS_RENDER_TYPE_LAYER_SETTINGS, G_PARAM_READWRITE);
|
||||
g_object_class_install_properties(oclass, N_PROPERTIES, gds_output_renderer_properties);
|
||||
|
||||
/* Setup output signals */
|
||||
gds_output_renderer_signals[ASYNC_FINISHED] =
|
||||
g_signal_newv(N_("async-finished"), GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
NULL);
|
||||
gds_output_renderer_signals[ASYNC_PROGRESS_CHANGED] =
|
||||
g_signal_newv(N_("progress-changed"), GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
progress_changed_param_types);
|
||||
}
|
||||
|
||||
void gds_output_renderer_init(GdsOutputRenderer *self)
|
||||
{
|
||||
GdsOutputRendererPrivate *priv;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(self);
|
||||
|
||||
priv->layer_settings = NULL;
|
||||
priv->output_file = NULL;
|
||||
priv->task = NULL;
|
||||
priv->mutex_init_status = TRUE;
|
||||
priv->main_context = NULL;
|
||||
priv->idle_function_parameters.status_message = NULL;
|
||||
g_mutex_init(&priv->settings_lock);
|
||||
g_mutex_init(&priv->idle_function_parameters.message_lock);
|
||||
}
|
||||
|
||||
GdsOutputRenderer *gds_output_renderer_new()
|
||||
{
|
||||
return GDS_RENDER_OUTPUT_RENDERER(g_object_new(GDS_RENDER_TYPE_OUTPUT_RENDERER, NULL));
|
||||
}
|
||||
|
||||
GdsOutputRenderer *gds_output_renderer_new_with_props(const char *output_file, LayerSettings *layer_settings)
|
||||
{
|
||||
return GDS_RENDER_OUTPUT_RENDERER(g_object_new(GDS_RENDER_TYPE_OUTPUT_RENDERER,
|
||||
N_("layer-settings"), layer_settings,
|
||||
N_("output-file"), output_file,
|
||||
NULL));
|
||||
}
|
||||
|
||||
void gds_output_renderer_set_output_file(GdsOutputRenderer *renderer, const gchar *file_name)
|
||||
{
|
||||
g_return_if_fail(GDS_RENDER_IS_OUTPUT_RENDERER(renderer));
|
||||
|
||||
/* Check if the filename is actually filled */
|
||||
if (!file_name || !file_name[0])
|
||||
return;
|
||||
g_object_set(renderer, N_("output-file"), file_name, NULL);
|
||||
}
|
||||
|
||||
const char *gds_output_renderer_get_output_file(GdsOutputRenderer *renderer)
|
||||
{
|
||||
const char *file = NULL;
|
||||
|
||||
g_object_get(renderer, N_("output-file"), &file, NULL);
|
||||
return file;
|
||||
}
|
||||
|
||||
LayerSettings *gds_output_renderer_get_and_ref_layer_settings(GdsOutputRenderer *renderer)
|
||||
{
|
||||
LayerSettings *ret = NULL;
|
||||
GdsOutputRendererPrivate *priv;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
|
||||
/* Acquire settings lock */
|
||||
g_mutex_lock(&priv->settings_lock);
|
||||
|
||||
/* This function seems to already reference the LayerSettings object */
|
||||
g_object_get(renderer, N_("layer-settings"), &ret, NULL);
|
||||
|
||||
/* It is now safe to clear the lock */
|
||||
g_mutex_unlock(&priv->settings_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gds_output_renderer_set_layer_settings(GdsOutputRenderer *renderer, LayerSettings *settings)
|
||||
{
|
||||
g_return_if_fail(GDS_RENDER_IS_LAYER_SETTINGS(settings));
|
||||
|
||||
g_object_set(renderer, N_("layer-settings"), settings, NULL);
|
||||
}
|
||||
|
||||
int gds_output_renderer_render_output(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale)
|
||||
{
|
||||
int ret;
|
||||
GdsOutputRendererClass *klass;
|
||||
GdsOutputRendererPrivate *priv = gds_output_renderer_get_instance_private(renderer);
|
||||
|
||||
if (GDS_RENDER_IS_OUTPUT_RENDERER(renderer) == FALSE) {
|
||||
g_error(_("Output Renderer not valid."));
|
||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||
}
|
||||
|
||||
if (!priv->output_file || !priv->output_file[0]) {
|
||||
g_error(_("No/invalid output file set."));
|
||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||
}
|
||||
|
||||
if (!priv->layer_settings) {
|
||||
g_error(_("No layer specification supplied."));
|
||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||
}
|
||||
|
||||
if (!cell) {
|
||||
g_error(_("Output renderer called without cell to render."));
|
||||
return GDS_OUTPUT_RENDERER_PARAM_ERR;
|
||||
}
|
||||
|
||||
klass = GDS_RENDER_OUTPUT_RENDERER_GET_CLASS(renderer);
|
||||
if (klass->render_output == NULL) {
|
||||
g_critical(_("Output Renderer: Rendering function broken. This is a bug."));
|
||||
return GDS_OUTPUT_RENDERER_GEN_ERR;
|
||||
}
|
||||
|
||||
ret = klass->render_output(renderer, cell, scale);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gds_output_renderer_async_wrapper(GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GdsOutputRenderer *renderer;
|
||||
GdsOutputRendererPrivate *priv;
|
||||
int ret;
|
||||
(void)task_data;
|
||||
(void)cancellable;
|
||||
|
||||
renderer = GDS_RENDER_OUTPUT_RENDERER(source_object);
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
if (!priv) {
|
||||
ret = -1000;
|
||||
goto ret_from_task;
|
||||
}
|
||||
if (!priv->mutex_init_status) {
|
||||
ret = -1001;
|
||||
goto ret_from_task;
|
||||
}
|
||||
|
||||
ret = gds_output_renderer_render_output(renderer, priv->async_params.cell, priv->async_params.scale);
|
||||
|
||||
ret_from_task:
|
||||
g_task_return_int(task, ret);
|
||||
}
|
||||
|
||||
static void gds_output_renderer_async_finished(GObject *src_obj, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
GdsOutputRendererPrivate *priv;
|
||||
(void)user_data;
|
||||
(void)res; /* Will hopefully be destroyed later */
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(GDS_RENDER_OUTPUT_RENDERER(src_obj));
|
||||
|
||||
priv->main_context = NULL;
|
||||
|
||||
g_signal_emit(src_obj, gds_output_renderer_signals[ASYNC_FINISHED], 0);
|
||||
g_clear_object(&priv->task);
|
||||
|
||||
/* Clear reference set in gds_output_renderer_render_output_async() */
|
||||
g_object_unref(src_obj);
|
||||
}
|
||||
|
||||
int gds_output_renderer_render_output_async(GdsOutputRenderer *renderer, struct gds_cell *cell, double scale)
|
||||
{
|
||||
GdsOutputRendererPrivate *priv;
|
||||
int ret = -1;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
if (priv->task) {
|
||||
g_warning(_("Renderer already started asynchronously"));
|
||||
return -2000;
|
||||
}
|
||||
|
||||
priv->task = g_task_new(renderer, NULL, gds_output_renderer_async_finished, NULL);
|
||||
|
||||
/* This function is not available on current debian distros. */
|
||||
/* g_task_set_name(priv->task, "Rendering Thread"); */
|
||||
|
||||
g_mutex_lock(&priv->settings_lock);
|
||||
priv->async_params.cell = cell;
|
||||
priv->async_params.scale = scale;
|
||||
priv->main_context = g_main_context_default();
|
||||
g_mutex_unlock(&priv->settings_lock);
|
||||
|
||||
/* Self reference. This could end up being nasty... */
|
||||
g_object_ref(renderer);
|
||||
|
||||
/* Do the magic */
|
||||
g_task_run_in_thread(priv->task, gds_output_renderer_async_wrapper);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean idle_event_processor_callback(gpointer user_data)
|
||||
{
|
||||
GdsOutputRenderer *renderer;
|
||||
GdsOutputRendererPrivate *priv;
|
||||
char *status_message;
|
||||
|
||||
/* If the rendering is finished before the mainloop gets to this point
|
||||
* the renderer is already disposed. Catch this!
|
||||
*/
|
||||
if (!GDS_RENDER_IS_OUTPUT_RENDERER(user_data))
|
||||
return FALSE;
|
||||
|
||||
renderer = GDS_RENDER_OUTPUT_RENDERER(user_data);
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
|
||||
if (g_mutex_trylock(&priv->idle_function_parameters.message_lock)) {
|
||||
status_message = priv->idle_function_parameters.status_message;
|
||||
g_signal_emit(renderer, gds_output_renderer_signals[ASYNC_PROGRESS_CHANGED], 0, status_message);
|
||||
g_free(priv->idle_function_parameters.status_message);
|
||||
priv->idle_function_parameters.status_message = NULL;
|
||||
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void gds_output_renderer_update_async_progress(GdsOutputRenderer *renderer, const char *status)
|
||||
{
|
||||
GSource *idle_event_processor;
|
||||
GdsOutputRendererPrivate *priv;
|
||||
gboolean skip_source = FALSE;
|
||||
|
||||
g_return_if_fail(GDS_RENDER_IS_OUTPUT_RENDERER(renderer));
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
priv = gds_output_renderer_get_instance_private(renderer);
|
||||
|
||||
/* If rendering is not async */
|
||||
if (!priv->main_context)
|
||||
return;
|
||||
|
||||
g_mutex_lock(&priv->idle_function_parameters.message_lock);
|
||||
if (priv->idle_function_parameters.status_message) {
|
||||
g_free(priv->idle_function_parameters.status_message);
|
||||
|
||||
/* Skip adding new idle source because there's already an active one */
|
||||
skip_source = TRUE;
|
||||
}
|
||||
priv->idle_function_parameters.status_message = g_strdup(status);
|
||||
g_mutex_unlock(&priv->idle_function_parameters.message_lock);
|
||||
|
||||
if (!skip_source) {
|
||||
idle_event_processor = g_idle_source_new();
|
||||
g_source_set_callback(idle_event_processor, idle_event_processor_callback, (gpointer)renderer, NULL);
|
||||
g_source_attach(idle_event_processor, priv->main_context);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
@ -18,21 +18,45 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file latex-output.c
|
||||
* @brief LaTeX output renderer
|
||||
* @file latex-renderer.c
|
||||
* @brief LaTeX Output Renderer
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <gds-render/latex-renderer/latex-output.h>
|
||||
#include <stdio.h>
|
||||
#include <gds-render/output-renderers/latex-renderer.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
/**
|
||||
* @addtogroup LaTeX-Renderer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Writes a GString \p buffer to the fixed file tex_file */
|
||||
/**
|
||||
* @brief Struct representing the LaTeX-Renderer object.
|
||||
*
|
||||
* This struct holds the LaTeX renderer internal data. It is only used inside the @ref LaTeX-Renderer class.
|
||||
*/
|
||||
struct _LatexRenderer {
|
||||
GdsOutputRenderer parent;
|
||||
gboolean tex_standalone;
|
||||
gboolean pdf_layers;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(LatexRenderer, latex_renderer, GDS_RENDER_TYPE_OUTPUT_RENDERER)
|
||||
|
||||
enum {
|
||||
PROP_STANDALONE = 1,
|
||||
PROP_PDF_LAYERS,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Writes a GString \p buffer to the fixed file tex_file
|
||||
* @note This is a convinience macro. Do not use this anywhere else. It might change behavior in futurtre releases
|
||||
*/
|
||||
#define WRITEOUT_BUFFER(buff) fwrite((buff)->str, sizeof(char), (buff)->len, tex_file)
|
||||
|
||||
/**
|
||||
@ -51,10 +75,13 @@ static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString
|
||||
{
|
||||
GList *list;
|
||||
struct layer_info *lifo;
|
||||
char *end_str;
|
||||
|
||||
for (list = layer_infos; list != NULL; list = list->next) {
|
||||
lifo = (struct layer_info *)list->data;
|
||||
|
||||
if (!lifo->render)
|
||||
continue;
|
||||
|
||||
g_string_printf(buffer, "\\pgfdeclarelayer{l%d}\n\\definecolor{c%d}{rgb}{%lf,%lf,%lf}\n",
|
||||
lifo->layer, lifo->layer,
|
||||
lifo->color.red, lifo->color.green, lifo->color.blue);
|
||||
@ -67,14 +94,14 @@ static void write_layer_definitions(FILE *tex_file, GList *layer_infos, GString
|
||||
for (list = layer_infos; list != NULL; list = list->next) {
|
||||
lifo = (struct layer_info *)list->data;
|
||||
|
||||
if (list->next == NULL)
|
||||
end_str = ",main}";
|
||||
else
|
||||
end_str = ",";
|
||||
g_string_printf(buffer, "l%d%s", lifo->layer, end_str);
|
||||
if (!lifo->render)
|
||||
continue;
|
||||
|
||||
g_string_printf(buffer, "l%d,", lifo->layer);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
}
|
||||
fwrite("\n", sizeof(char), 1, tex_file);
|
||||
g_string_printf(buffer, "main}\n");
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,12 +137,13 @@ static gboolean write_layer_env(FILE *tex_file, GdkRGBA *color, int layer, GList
|
||||
|
||||
for (temp = linfo; temp != NULL; temp = temp->next) {
|
||||
inf = (struct layer_info *)temp->data;
|
||||
if (inf->layer == layer) {
|
||||
if (inf->layer == layer && inf->render) {
|
||||
color->alpha = inf->color.alpha;
|
||||
color->red = inf->color.red;
|
||||
color->green = inf->color.green;
|
||||
color->blue = inf->color.blue;
|
||||
g_string_printf(buffer, "\\begin{pgfonlayer}{l%d}\n\\ifcreatepdflayers\n\\begin{scope}[ocg={ref=%d, status=visible,name={%s}}]\n\\fi\n",
|
||||
g_string_printf(buffer,
|
||||
"\\begin{pgfonlayer}{l%d}\n\\ifcreatepdflayers\n\\begin{scope}[ocg={ref=%d, status=visible,name={%s}}]\n\\fi\n",
|
||||
layer, layer, inf->name);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
return TRUE;
|
||||
@ -142,21 +170,26 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
|
||||
struct gds_graphics *gfx;
|
||||
struct gds_point *pt;
|
||||
GdkRGBA color;
|
||||
static const char *line_caps[] = {"butt", "round", "rect"};
|
||||
static const char * const line_caps[] = {"butt", "round", "rect"};
|
||||
|
||||
for (temp = graphics; temp != NULL; temp = temp->next) {
|
||||
gfx = (struct gds_graphics *)temp->data;
|
||||
if (write_layer_env(tex_file, &color, (int)gfx->layer, linfo, buffer) == TRUE) {
|
||||
|
||||
/* Layer is defined => create graphics */
|
||||
if (gfx->gfx_type == GRAPHIC_POLYGON || gfx->gfx_type == GRAPHIC_BOX ) {
|
||||
g_string_printf(buffer, "\\draw[line width=0.00001 pt, draw={c%d}, fill={c%d}, fill opacity={%lf}] ",
|
||||
if (gfx->gfx_type == GRAPHIC_POLYGON || gfx->gfx_type == GRAPHIC_BOX) {
|
||||
g_string_printf(buffer,
|
||||
"\\draw[line width=0.00001 pt, draw={c%d}, fill={c%d}, fill opacity={%lf}] ",
|
||||
gfx->layer, gfx->layer, color.alpha);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
/* Append vertices */
|
||||
for (temp_vertex = gfx->vertices; temp_vertex != NULL; temp_vertex = temp_vertex->next) {
|
||||
for (temp_vertex = gfx->vertices;
|
||||
temp_vertex != NULL;
|
||||
temp_vertex = temp_vertex->next) {
|
||||
pt = (struct gds_point *)temp_vertex->data;
|
||||
g_string_printf(buffer, "(%lf pt, %lf pt) -- ", ((double)pt->x)/scale, ((double)pt->y)/scale);
|
||||
g_string_printf(buffer, "(%lf pt, %lf pt) -- ",
|
||||
((double)pt->x)/scale,
|
||||
((double)pt->y)/scale);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
}
|
||||
g_string_printf(buffer, "cycle;\n");
|
||||
@ -179,7 +212,9 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
|
||||
/* Append vertices */
|
||||
for (temp_vertex = gfx->vertices; temp_vertex != NULL; temp_vertex = temp_vertex->next) {
|
||||
for (temp_vertex = gfx->vertices;
|
||||
temp_vertex != NULL;
|
||||
temp_vertex = temp_vertex->next) {
|
||||
pt = (struct gds_point *)temp_vertex->data;
|
||||
g_string_printf(buffer, "(%lf pt, %lf pt)%s",
|
||||
((double)pt->x)/scale,
|
||||
@ -205,13 +240,20 @@ static void generate_graphics(FILE *tex_file, GList *graphics, GList *linfo, GSt
|
||||
* @param tex_file File to write to
|
||||
* @param buffer Working buffer
|
||||
* @param scale Scale output down by this value
|
||||
* @param renderer The current renderer as GdsOutputRenderer. This is used to emit the status updates to the GUI
|
||||
*/
|
||||
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale)
|
||||
static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, GString *buffer, double scale,
|
||||
GdsOutputRenderer *renderer)
|
||||
{
|
||||
|
||||
GString *status;
|
||||
GList *list_child;
|
||||
struct gds_cell_instance *inst;
|
||||
|
||||
status = g_string_new(NULL);
|
||||
g_string_printf(status, _("Generating cell %s"), cell->name);
|
||||
gds_output_renderer_update_async_progress(renderer, status->str);
|
||||
g_string_free(status, TRUE);
|
||||
|
||||
/* Draw polygons of current cell */
|
||||
generate_graphics(tex_file, cell->graphic_objs, layer_infos, buffer, scale);
|
||||
|
||||
@ -225,17 +267,18 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
|
||||
|
||||
/* generate translation scope */
|
||||
g_string_printf(buffer, "\\begin{scope}[shift={(%lf pt,%lf pt)}]\n",
|
||||
((double)inst->origin.x)/scale,((double)inst->origin.y)/scale);
|
||||
((double)inst->origin.x) / scale, ((double)inst->origin.y) / scale);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
|
||||
g_string_printf(buffer, "\\begin{scope}[rotate=%lf]\n", inst->angle);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
|
||||
g_string_printf(buffer, "\\begin{scope}[yscale=%lf, xscale=%lf]\n", (inst->flipped ? -1*inst->magnification : inst->magnification),
|
||||
g_string_printf(buffer, "\\begin{scope}[yscale=%lf, xscale=%lf]\n",
|
||||
(inst->flipped ? -1*inst->magnification : inst->magnification),
|
||||
inst->magnification);
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
|
||||
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale);
|
||||
render_cell(inst->cell_ref, layer_infos, tex_file, buffer, scale, renderer);
|
||||
|
||||
g_string_printf(buffer, "\\end{scope}\n");
|
||||
WRITEOUT_BUFFER(buffer);
|
||||
@ -249,14 +292,14 @@ static void render_cell(struct gds_cell *cell, GList *layer_infos, FILE *tex_fil
|
||||
|
||||
}
|
||||
|
||||
void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
|
||||
gboolean create_pdf_layers, gboolean standalone_document)
|
||||
static int latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *tex_file, double scale,
|
||||
gboolean create_pdf_layers, gboolean standalone_document, GdsOutputRenderer *renderer)
|
||||
{
|
||||
GString *working_line;
|
||||
|
||||
|
||||
if (!tex_file || !layer_infos || !cell)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
/* 10 kB Line working buffer should be enough */
|
||||
working_line = g_string_new_len(NULL, LATEX_LINE_BUFFER_KB*1024);
|
||||
@ -270,7 +313,8 @@ void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *
|
||||
WRITEOUT_BUFFER(working_line);
|
||||
g_string_printf(working_line, "\\iftestmode\n");
|
||||
WRITEOUT_BUFFER(working_line);
|
||||
g_string_printf(working_line, "\\documentclass[tikz]{standalone}\n\\usepackage{xcolor}\n\\usetikzlibrary{ocgx}\n\\begin{document}\n");
|
||||
g_string_printf(working_line,
|
||||
"\\documentclass[tikz]{standalone}\n\\usepackage{xcolor}\n\\usetikzlibrary{ocgx}\n\\begin{document}\n");
|
||||
WRITEOUT_BUFFER(working_line);
|
||||
g_string_printf(working_line, "\\fi\n");
|
||||
WRITEOUT_BUFFER(working_line);
|
||||
@ -283,7 +327,7 @@ void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *
|
||||
WRITEOUT_BUFFER(working_line);
|
||||
|
||||
/* Generate graphics output */
|
||||
render_cell(cell, layer_infos, tex_file, working_line, scale);
|
||||
render_cell(cell, layer_infos, tex_file, working_line, scale, renderer);
|
||||
|
||||
|
||||
g_string_printf(working_line, "\\end{tikzpicture}\n");
|
||||
@ -298,6 +342,124 @@ void latex_render_cell_to_code(struct gds_cell *cell, GList *layer_infos, FILE *
|
||||
|
||||
fflush(tex_file);
|
||||
g_string_free(working_line, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int latex_renderer_render_output(GdsOutputRenderer *renderer,
|
||||
struct gds_cell *cell,
|
||||
double scale)
|
||||
{
|
||||
LatexRenderer *l_renderer = GDS_RENDER_LATEX_RENDERER(renderer);
|
||||
FILE *tex_file;
|
||||
int ret = -2;
|
||||
LayerSettings *settings;
|
||||
GList *layer_infos = NULL;
|
||||
const char *output_file;
|
||||
|
||||
output_file = gds_output_renderer_get_output_file(renderer);
|
||||
settings = gds_output_renderer_get_and_ref_layer_settings(renderer);
|
||||
|
||||
/* Set layer info list. In case of failure it remains NULL */
|
||||
if (settings)
|
||||
layer_infos = layer_settings_get_layer_info_list(settings);
|
||||
|
||||
tex_file = fopen(output_file, "w");
|
||||
if (tex_file) {
|
||||
ret = latex_render_cell_to_code(cell, layer_infos, tex_file, scale,
|
||||
l_renderer->pdf_layers, l_renderer->tex_standalone, renderer);
|
||||
fclose(tex_file);
|
||||
} else {
|
||||
g_warning(_("Could not open LaTeX output file"));
|
||||
}
|
||||
|
||||
if (settings)
|
||||
g_object_unref(settings);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void latex_renderer_init(LatexRenderer *self)
|
||||
{
|
||||
self->pdf_layers = FALSE;
|
||||
self->tex_standalone = FALSE;
|
||||
}
|
||||
|
||||
static void latex_renderer_get_property(GObject *obj, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
LatexRenderer *self = GDS_RENDER_LATEX_RENDERER(obj);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_STANDALONE:
|
||||
g_value_set_boolean(value, self->tex_standalone);
|
||||
break;
|
||||
case PROP_PDF_LAYERS:
|
||||
g_value_set_boolean(value, self->pdf_layers);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void latex_renderer_set_property(GObject *obj, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
LatexRenderer *self = GDS_RENDER_LATEX_RENDERER(obj);
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_STANDALONE:
|
||||
self->tex_standalone = g_value_get_boolean(value);
|
||||
break;
|
||||
case PROP_PDF_LAYERS:
|
||||
self->pdf_layers = g_value_get_boolean(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GParamSpec *latex_renderer_properties[N_PROPERTIES] = {NULL};
|
||||
|
||||
static void latex_renderer_class_init(LatexRendererClass *klass)
|
||||
{
|
||||
GdsOutputRendererClass *render_class = GDS_RENDER_OUTPUT_RENDERER_CLASS(klass);
|
||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||
|
||||
/* Overwrite virtual function */
|
||||
render_class->render_output = latex_renderer_render_output;
|
||||
|
||||
/* Property stuff */
|
||||
oclass->get_property = latex_renderer_get_property;
|
||||
oclass->set_property = latex_renderer_set_property;
|
||||
|
||||
latex_renderer_properties[PROP_STANDALONE] =
|
||||
g_param_spec_boolean("standalone",
|
||||
N_("Standalone TeX file"),
|
||||
N_("Generate a standalone LaTeX file."),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
latex_renderer_properties[PROP_PDF_LAYERS] =
|
||||
g_param_spec_boolean("pdf-layers",
|
||||
N_("PDF OCR layers"),
|
||||
N_("Generate OCR layers"),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties(oclass, N_PROPERTIES, latex_renderer_properties);
|
||||
}
|
||||
|
||||
LatexRenderer *latex_renderer_new()
|
||||
{
|
||||
return GDS_RENDER_LATEX_RENDERER(g_object_new(GDS_RENDER_TYPE_LATEX_RENDERER, NULL));
|
||||
}
|
||||
|
||||
LatexRenderer *latex_renderer_new_with_options(gboolean pdf_layers, gboolean standalone)
|
||||
{
|
||||
GObject *obj;
|
||||
|
||||
obj = g_object_new(GDS_RENDER_TYPE_LATEX_RENDERER, "standalone", standalone, "pdf-layers", pdf_layers, NULL);
|
||||
return GDS_RENDER_LATEX_RENDERER(obj);
|
||||
}
|
||||
|
||||
/** @} */
|
2
plugins/CMakeLists.txt
Normal file
2
plugins/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
add_subdirectory(plugin-example)
|
||||
add_custom_target(plugins DEPENDS pluginexample)
|
14
plugins/plugin-example/CMakeLists.txt
Normal file
14
plugins/plugin-example/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
project(pluginexample)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(PYTHON REQUIRED python3)
|
||||
|
||||
aux_source_directory(src SOURCES)
|
||||
|
||||
include_directories(${PYTHON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
link_libraries(${PYTHON_LDFLAGS} version)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED EXCLUDE_FROM_ALL ${SOURCES})
|
||||
add_dependencies(${PROJECT_NAME} version)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
49
plugins/plugin-example/src/plugin-main.c
Normal file
49
plugins/plugin-example/src/plugin-main.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* GDSII-Converter example plugin
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup example-plugin Example Plugin for External Renderer
|
||||
* @ingroup plugins
|
||||
* This is a template / example for an external renderer plugin
|
||||
* @addtogroup example-plugin
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
#include <gds-render/output-renderers/external-renderer-interfaces.h>
|
||||
|
||||
int EXPORTED_FUNC_DECL(EXTERNAL_LIBRARY_RENDER_FUNCTION)(struct gds_cell *toplevel, GList *layer_info_list, const char *output_file_name, double scale)
|
||||
{
|
||||
if (!toplevel)
|
||||
return -1000;
|
||||
|
||||
printf("Rendering %s\n", toplevel->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EXPORTED_FUNC_DECL(EXTERNAL_LIBRARY_INIT_FUNCTION)(const char *params, const char *version)
|
||||
{
|
||||
printf("Init with params: %s\ngds-render version: %s\n", params, version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
10
resources/CMakeLists.txt
Normal file
10
resources/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
add_custom_target(glib-resources DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/resources.c")
|
||||
add_custom_command(DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.glade"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/color-palette.txt"
|
||||
OUTPUT
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/resources.c"
|
||||
COMMAND
|
||||
glib-compile-resources --target="${CMAKE_CURRENT_BINARY_DIR}/resources.c" --sourcedir="${CMAKE_CURRENT_SOURCE_DIR}" --generate-source "${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
|
||||
)
|
@ -6,7 +6,8 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="program_name">GDS-Render Tool </property>
|
||||
<property name="comments" translatable="yes">Tool for rendering GDS(II) layout files into LaTeX/TikZ code or directly into a PDF file</property>
|
||||
<property name="version">!! Replaced during runtime !!</property>
|
||||
<property name="comments" translatable="yes">!! Replaced during runtime !!</property>
|
||||
<property name="website">https://git.shimatta.de/mhu/gds-render</property>
|
||||
<property name="website_label" translatable="yes">Git Repository</property>
|
||||
<property name="authors">Mario Hüttel <mario.huettel@gmx.net></property>
|
255
resources/color-palette.txt
Normal file
255
resources/color-palette.txt
Normal file
@ -0,0 +1,255 @@
|
||||
800000
|
||||
008000
|
||||
808000
|
||||
000080
|
||||
800080
|
||||
008080
|
||||
c0c0c0
|
||||
808080
|
||||
ff0000
|
||||
00ff00
|
||||
ffff00
|
||||
0000ff
|
||||
ff00ff
|
||||
00ffff
|
||||
f105f5
|
||||
000000
|
||||
00005f
|
||||
000087
|
||||
0000af
|
||||
0000d7
|
||||
0000ff
|
||||
005f00
|
||||
005f5f
|
||||
005f87
|
||||
005faf
|
||||
005fd7
|
||||
005fff
|
||||
008700
|
||||
00875f
|
||||
008787
|
||||
0087af
|
||||
0087d7
|
||||
0087ff
|
||||
00af00
|
||||
00af5f
|
||||
00af87
|
||||
00afaf
|
||||
00afd7
|
||||
00afff
|
||||
00d700
|
||||
00d75f
|
||||
00d787
|
||||
00d7af
|
||||
00d7d7
|
||||
00d7ff
|
||||
00ff00
|
||||
00ff5f
|
||||
00ff87
|
||||
00ffaf
|
||||
00ffd7
|
||||
00ffff
|
||||
5f0000
|
||||
5f005f
|
||||
5f0087
|
||||
5f00af
|
||||
5f00d7
|
||||
5f00ff
|
||||
5f5f00
|
||||
5f5f5f
|
||||
5f5f87
|
||||
5f5faf
|
||||
5f5fd7
|
||||
5f5fff
|
||||
5f8700
|
||||
5f875f
|
||||
5f8787
|
||||
5f87af
|
||||
5f87d7
|
||||
5f87ff
|
||||
5faf00
|
||||
5faf5f
|
||||
5faf87
|
||||
5fafaf
|
||||
5fafd7
|
||||
5fafff
|
||||
5fd700
|
||||
5fd75f
|
||||
5fd787
|
||||
5fd7af
|
||||
5fd7d7
|
||||
5fd7ff
|
||||
5fff00
|
||||
5fff5f
|
||||
5fff87
|
||||
5fffaf
|
||||
5fffd7
|
||||
5fffff
|
||||
870000
|
||||
87005f
|
||||
870087
|
||||
8700af
|
||||
8700d7
|
||||
8700ff
|
||||
875f00
|
||||
875f5f
|
||||
875f87
|
||||
875faf
|
||||
875fd7
|
||||
875fff
|
||||
878700
|
||||
87875f
|
||||
878787
|
||||
8787af
|
||||
8787d7
|
||||
8787ff
|
||||
87af00
|
||||
87af5f
|
||||
87af87
|
||||
87afaf
|
||||
87afd7
|
||||
87afff
|
||||
87d700
|
||||
87d75f
|
||||
87d787
|
||||
87d7af
|
||||
87d7d7
|
||||
87d7ff
|
||||
87ff00
|
||||
87ff5f
|
||||
87ff87
|
||||
87ffaf
|
||||
87ffd7
|
||||
87ffff
|
||||
af0000
|
||||
af005f
|
||||
af0087
|
||||
af00af
|
||||
af00d7
|
||||
af00ff
|
||||
af5f00
|
||||
af5f5f
|
||||
af5f87
|
||||
af5faf
|
||||
af5fd7
|
||||
af5fff
|
||||
af8700
|
||||
af875f
|
||||
af8787
|
||||
af87af
|
||||
af87d7
|
||||
af87ff
|
||||
afaf00
|
||||
afaf5f
|
||||
afaf87
|
||||
afafaf
|
||||
afafd7
|
||||
afafff
|
||||
afd700
|
||||
afd75f
|
||||
afd787
|
||||
afd7af
|
||||
afd7d7
|
||||
afd7ff
|
||||
afff00
|
||||
afff5f
|
||||
afff87
|
||||
afffaf
|
||||
afffd7
|
||||
afffff
|
||||
d70000
|
||||
d7005f
|
||||
d70087
|
||||
d700af
|
||||
d700d7
|
||||
d700ff
|
||||
d75f00
|
||||
d75f5f
|
||||
d75f87
|
||||
d75faf
|
||||
d75fd7
|
||||
d75fff
|
||||
d78700
|
||||
d7875f
|
||||
d78787
|
||||
d787af
|
||||
d787d7
|
||||
d787ff
|
||||
d7af00
|
||||
d7af5f
|
||||
d7af87
|
||||
d7afaf
|
||||
d7afd7
|
||||
d7afff
|
||||
d7d700
|
||||
d7d75f
|
||||
d7d787
|
||||
d7d7af
|
||||
d7d7d7
|
||||
d7d7ff
|
||||
d7ff00
|
||||
d7ff5f
|
||||
d7ff87
|
||||
d7ffaf
|
||||
d7ffd7
|
||||
d7ffff
|
||||
ff0000
|
||||
ff005f
|
||||
ff0087
|
||||
ff00af
|
||||
ff00d7
|
||||
ff00ff
|
||||
ff5f00
|
||||
ff5f5f
|
||||
ff5f87
|
||||
ff5faf
|
||||
ff5fd7
|
||||
ff5fff
|
||||
ff8700
|
||||
ff875f
|
||||
ff8787
|
||||
ff87af
|
||||
ff87d7
|
||||
ff87ff
|
||||
ffaf00
|
||||
ffaf5f
|
||||
ffaf87
|
||||
ffafaf
|
||||
ffafd7
|
||||
ffafff
|
||||
ffd700
|
||||
ffd75f
|
||||
ffd787
|
||||
ffd7af
|
||||
ffd7d7
|
||||
ffd7ff
|
||||
ffff00
|
||||
ffff5f
|
||||
ffff87
|
||||
ffffaf
|
||||
ffffd7
|
||||
ffffff
|
||||
080808
|
||||
121212
|
||||
1c1c1c
|
||||
262626
|
||||
303030
|
||||
3a3a3a
|
||||
444444
|
||||
4e4e4e
|
||||
585858
|
||||
626262
|
||||
6c6c6c
|
||||
767676
|
||||
808080
|
||||
8a8a8a
|
||||
949494
|
||||
9e9e9e
|
||||
a8a8a8
|
||||
b2b2b2
|
||||
bcbcbc
|
||||
c6c6c6
|
||||
d0d0d0
|
||||
dadada
|
||||
e4e4e4
|
||||
eeeeee
|
@ -1,26 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="upper">1</property>
|
||||
<property name="value">1</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">0.10000000000000001</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
<property name="page-increment">0.10</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="event-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-justify-fill</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -33,7 +33,7 @@
|
||||
<child>
|
||||
<object class="GtkLabel" id="layer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">label</property>
|
||||
</object>
|
||||
<packing>
|
||||
@ -45,9 +45,9 @@
|
||||
<child>
|
||||
<object class="GtkColorButton" id="color">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_alpha">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-alpha">True</property>
|
||||
<property name="title" translatable="yes">Select Layer Color and Opacity</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
</object>
|
||||
@ -61,9 +61,9 @@
|
||||
<object class="GtkCheckButton" id="export">
|
||||
<property name="label" translatable="yes">Export Layer</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@ -74,7 +74,7 @@
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
313
resources/main.glade
Normal file
313
resources/main.glade
Normal file
@ -0,0 +1,313 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkImage" id="auto-name-img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">format-text-rich-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="color-img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">color-select-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="select-all-img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">emblem-ok-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="sort-down-img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">view-sort-descending-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="sort-up-img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">view-sort-ascending-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="main-window">
|
||||
<property name="height-request">250</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">gds-render</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="cell-search">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="primary-icon-name">edit-find-symbolic</property>
|
||||
<property name="primary-icon-activatable">False</property>
|
||||
<property name="primary-icon-sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="cell-tree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="enable-search">False</property>
|
||||
<property name="enable-grid-lines">both</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-up-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Sort layers ascending</property>
|
||||
<property name="image">sort-up-img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-down-sort">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Sort layers descending</property>
|
||||
<property name="image">sort-down-img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="auto-color-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Automatically color layers</property>
|
||||
<property name="image">color-img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-select-all">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Select all layers for export</property>
|
||||
<property name="image">select-all-img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-auto-name">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Automatically name layers</property>
|
||||
<property name="image">auto-name-img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-top">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="layer-list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="selection-mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="activity-bar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</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>
|
||||
</interface>
|
17
resources/resources.xml
Normal file
17
resources/resources.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/gui">
|
||||
<file compressed="true">main.glade</file>
|
||||
<file compressed="true">about.glade</file>
|
||||
<file>layer-widget.glade</file>
|
||||
<file>dialog.glade</file>
|
||||
</gresource>
|
||||
<gresource prefix="/data">
|
||||
<file compressed="true">color-palette.txt</file>
|
||||
</gresource>
|
||||
<gresource prefix="/images">
|
||||
<file compressed="true" alias="logo.svg">../icon/gds-render.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
|
41
test/CMakeLists.txt
Normal file
41
test/CMakeLists.txt
Normal 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
17618
test/catch-framework/catch.hpp
Normal file
File diff suppressed because it is too large
Load Diff
160
test/geometric/vector-operations.cpp
Normal file
160
test/geometric/vector-operations.cpp
Normal 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
2
test/test-main.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch-framework/catch.hpp"
|
16
translations/CMakeLists.txt
Normal file
16
translations/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
add_custom_target(translations
|
||||
DEPENDS
|
||||
"${PROJECT_BINARY_DIR}/translations/output/"
|
||||
)
|
||||
|
||||
add_custom_command(DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pot/po/*"
|
||||
OUTPUT
|
||||
"${PROJECT_BINARY_DIR}/translations/output/"
|
||||
COMMAND
|
||||
COMMAND ./generate-mo.sh "${PROJECT_BINARY_DIR}/translations/output"
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT
|
||||
"Generating translation locales"
|
||||
)
|
24
translations/generate-mo.sh
Executable file
24
translations/generate-mo.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
cd "$DIR"
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "Must supply an output name"
|
||||
exit -2
|
||||
fi
|
||||
|
||||
for langdir in `find ./pot/po -mindepth 1 -maxdepth 1 -type d`; do
|
||||
lang=`basename "$langdir"`
|
||||
dest="$1/locale/$lang/LC_MESSAGES"
|
||||
mkdir -p "$dest"
|
||||
pofiles=`find "$langdir" -name "*.po" | tr '\n' ' '`
|
||||
comb=`msgcat $pofiles`
|
||||
echo "$comb" | msgfmt --output-file="$dest/gds-render.mo" -
|
||||
done
|
39
translations/generate_templates.sh
Executable file
39
translations/generate_templates.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
cd "$DIR"
|
||||
|
||||
files=`find ../ -name "*.c"`
|
||||
mkdir -p "pot"
|
||||
|
||||
# C Files
|
||||
|
||||
pot="pot/gds-render.pot"
|
||||
|
||||
for file in $files; do
|
||||
echo "Parsing C file $file"
|
||||
# pot="pot/"$(echo "${file#*/}" | sed -e "s/\//_/g")
|
||||
# pot="${pot%.c}.pot"
|
||||
if [[ -f "$pot" ]]; then
|
||||
xgettext --package-name="gds-render" --join-existing --keyword=_ --language=C --add-comments --sort-output -o "$pot" "$file"
|
||||
else
|
||||
xgettext --package-name="gds-render" --keyword=_ --language=C --add-comments --sort-output -o "$pot" "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Glade files
|
||||
glade_files=`find ../resources/ -name "*.glade"`
|
||||
for glade in $glade_files; do
|
||||
echo "Parsing Glade file $glade"
|
||||
if [[ -f "$pot" ]]; then
|
||||
xgettext --package-name="gds-render" --join-existing --keyword=_ -L Glade --sort-output -o "$pot" "$glade"
|
||||
else
|
||||
xgettext --package-name="gds-render" --keyword=_ -L Glade --sort-output -o "$pot" "$glade"
|
||||
fi
|
||||
done
|
456
translations/pot/gds-render.pot
Normal file
456
translations/pot/gds-render.pot
Normal file
@ -0,0 +1,456 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gds-render package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gds-render\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-12-16 18:27+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../main.c:97
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Full git commit: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:294
|
||||
msgid " FILE - Convert GDS file <FILE> to graphic"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/about.glade:10
|
||||
msgid "!! Replaced during runtime !!"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:205
|
||||
#, c-format
|
||||
msgid "%d reference loops found.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:220
|
||||
msgid "About"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:290
|
||||
msgid "Argument string passed to render lib"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:225
|
||||
msgid "Automatically color layers"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:255
|
||||
msgid "Automatically name layers"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:71
|
||||
#, c-format
|
||||
msgid "Broken cell list item found in cell %s. Will continue.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:57
|
||||
#, c-format
|
||||
msgid "Broken cell list item found. Will continue.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:409
|
||||
#, c-format
|
||||
msgid "Cairo export finished. It might still be buggy!\n"
|
||||
msgstr ""
|
||||
|
||||
#. Execute
|
||||
#: ../output-renderers/external-renderer.c:120
|
||||
msgid "Calling external renderer."
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:286 ../widgets/conv-settings-dialog.c:291
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:244
|
||||
msgid "Cell"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:209
|
||||
#, c-format
|
||||
msgid "Cell is affected by reference loop. Abort!\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:284
|
||||
msgid "Cell to render"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:215
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Cell was not checked. This should not happen. Please report this issue. Will "
|
||||
"continue either way.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:202
|
||||
#, c-format
|
||||
msgid "Checking library %s failed.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/dialog.glade:79
|
||||
msgid "Configure LaTeX as standalone document"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:109
|
||||
msgid "Convert selected cell"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/external-renderer.c:89
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not load external library '%s'\n"
|
||||
"Detailed error is:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/latex-renderer.c:373
|
||||
msgid "Could not open LaTeX output file"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:195
|
||||
#, c-format
|
||||
msgid "Couldn't find cell in first library!\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:81
|
||||
#, c-format
|
||||
msgid "Count of renderers %d does not match count of output file names %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:286
|
||||
msgid "Create PDF Layers (OCG)"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:285
|
||||
msgid "Create standalone TeX"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:280
|
||||
msgid "Divide output coordinates by <SCALE>"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/layer-widget.glade:62
|
||||
msgid "Export Layer"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:366
|
||||
#, c-format
|
||||
msgid "Exporting layer %d to file\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/external-renderer.c:142
|
||||
msgid "External renderer finished."
|
||||
msgstr ""
|
||||
|
||||
#. This should not happen
|
||||
#: ../output-renderers/cairo-renderer.c:271
|
||||
#, c-format
|
||||
msgid "Fatal error: Cairo Renderer: Could not spawn child process!"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:50
|
||||
msgid "GDS-Render"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:294
|
||||
msgid "GDSII-Files"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/dialog.glade:18
|
||||
msgid "Generate LaTeX/TikZ output"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/dialog.glade:93
|
||||
msgid "Generate PDF Layers"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/latex-renderer.c:253
|
||||
#, c-format
|
||||
msgid "Generating cell %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/about.glade:12
|
||||
msgid "Git Repository"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:246
|
||||
#, c-format
|
||||
msgid "Height: %.3lf %sm"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:321
|
||||
#, c-format
|
||||
msgid "Ignored argument: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/external-renderer.c:106
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Init function not found in library:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:321
|
||||
#, c-format
|
||||
msgid "Layer number too high / outside of spec.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:369
|
||||
#, c-format
|
||||
msgid "Layer outside of spec.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/layer-element.c:102
|
||||
#, c-format
|
||||
msgid "Layer: %d"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:241
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:68
|
||||
msgid "Load Mapping"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:73
|
||||
msgid "Load the current layer configuration from CSV"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:116
|
||||
#, c-format
|
||||
msgid "Logo could not be displayed: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:293
|
||||
msgid "No layer specification supplied."
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:186
|
||||
#, c-format
|
||||
msgid "No library in library list. This should not happen.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:288
|
||||
msgid "No/invalid output file set."
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:291
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:58
|
||||
msgid "Open GDS2 Database"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:287
|
||||
msgid "Open GDSII"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:284
|
||||
msgid "Open GDSII File"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:299
|
||||
#, c-format
|
||||
msgid "Option parsing failed: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:255
|
||||
#, c-format
|
||||
msgid "Output Height: %u px"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:283
|
||||
msgid "Output Renderer not valid."
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:304
|
||||
msgid "Output Renderer: Rendering function broken. This is a bug."
|
||||
msgstr ""
|
||||
|
||||
#. Set the pixel sizes
|
||||
#: ../widgets/conv-settings-dialog.c:252
|
||||
#, c-format
|
||||
msgid "Output Width: %u px"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:282
|
||||
msgid "Output file path. Can be used multiple times."
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:298
|
||||
msgid "Output renderer called without cell to render."
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:74
|
||||
msgid "Output renderer does not define a render_output function!"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:283
|
||||
msgid "Path for Layer Mapping File"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:288
|
||||
msgid ""
|
||||
"Path to a custom shared object, that implements the necessary rendering "
|
||||
"functions"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/external-renderer.c:78
|
||||
#, c-format
|
||||
msgid "Path to shared object not set!\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:74
|
||||
#, c-format
|
||||
msgid "Please specify renderers and file names\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:104
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please specify shared object for external renderer. Will ignore this "
|
||||
"renderer.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:277
|
||||
msgid "Print version"
|
||||
msgstr ""
|
||||
|
||||
#: ../command-line.c:160
|
||||
#, c-format
|
||||
msgid "Probably missing argument. Check --help option\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:219
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/activity-bar.c:104
|
||||
msgid "Ready"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/dialog.glade:33
|
||||
msgid "Render PDF using Cairographics"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/dialog.glade:48
|
||||
msgid "Render SVG using Cairographics (too buggy at the moment)"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:293
|
||||
msgid "Renderer Settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:365
|
||||
msgid "Renderer already started asynchronously"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:279
|
||||
msgid "Renderer to use. Can be used multiple times."
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:467
|
||||
msgid "Rendering Cairo Output..."
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-render-gui.c:554
|
||||
msgid "Rendering cell..."
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/external-renderer.c:98
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Rendering function not found in library:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:86
|
||||
msgid "Save Mapping"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:23
|
||||
msgid "Save the current layer configuration to CSV"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:312
|
||||
#, c-format
|
||||
msgid "Scale < 1 not allowed. Setting to 1\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/layer-widget.glade:51
|
||||
msgid "Select Layer Color and Opacity"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:240
|
||||
msgid "Select all layers for export"
|
||||
msgstr ""
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:331
|
||||
#, c-format
|
||||
msgid "Size of layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:195
|
||||
msgid "Sort layers ascending"
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/main.glade:210
|
||||
msgid "Sort layers descending"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:212
|
||||
#, c-format
|
||||
msgid ""
|
||||
"There is already an open instance. Will open second window in that "
|
||||
"instance.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:244
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This is gds-render, version: %s\n"
|
||||
"\n"
|
||||
"For a list of supported commands execute with --help option.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:188
|
||||
#, c-format
|
||||
msgid "Visited cell list should be empty. This is a bug. Please report this.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:244
|
||||
#, c-format
|
||||
msgid "Width: %.3lf %sm"
|
||||
msgstr ""
|
||||
|
||||
#: ../widgets/activity-bar.c:110
|
||||
msgid "Working..."
|
||||
msgstr ""
|
||||
|
||||
#: ../main.c:96
|
||||
msgid ""
|
||||
"gds-render is a free tool for rendering GDS2 layout files into vector "
|
||||
"graphics."
|
||||
msgstr ""
|
||||
|
||||
#: ../resources/layer-widget.glade:37
|
||||
msgid "label"
|
||||
msgstr ""
|
487
translations/pot/po/de/gds-render.po
Normal file
487
translations/pot/po/de/gds-render.po
Normal file
@ -0,0 +1,487 @@
|
||||
# German translations for gds-render package.
|
||||
# Copyright (C) 2019 THE gds-render'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gds-render package.
|
||||
# マリオ <mario.huettel@gmx.net>, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gds-render\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-12-16 18:27+0100\n"
|
||||
"PO-Revision-Date: 2019-12-16 22:00+0100\n"
|
||||
"Last-Translator: Mario Hüttel <mario.huettel@gmx.net>\n"
|
||||
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.2.4\n"
|
||||
|
||||
#: ../main.c:97
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Full git commit: %s"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\n"
|
||||
"Vollständiger git-Commit: %s"
|
||||
|
||||
#: ../main.c:294
|
||||
msgid " FILE - Convert GDS file <FILE> to graphic"
|
||||
msgstr " DATEI - Konvertiere GDS-Datei <DATEI> in Grafik"
|
||||
|
||||
#: ../resources/about.glade:10
|
||||
msgid "!! Replaced during runtime !!"
|
||||
msgstr "!! Ersetzt zur Laufzeit !!"
|
||||
|
||||
#: ../command-line.c:205
|
||||
#, c-format
|
||||
msgid "%d reference loops found.\n"
|
||||
msgstr "%d Referenzschleifen gefunden.\n"
|
||||
|
||||
#: ../main.c:220
|
||||
msgid "About"
|
||||
msgstr "Info"
|
||||
|
||||
#: ../main.c:290
|
||||
msgid "Argument string passed to render lib"
|
||||
msgstr "An Render-Bibliothek übergebener Argument-String"
|
||||
|
||||
#: ../resources/main.glade:225
|
||||
msgid "Automatically color layers"
|
||||
msgstr "Färbe Layer automatisch"
|
||||
|
||||
#: ../resources/main.glade:255
|
||||
msgid "Automatically name layers"
|
||||
msgstr "Bename Layer automatisch"
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:71
|
||||
#, c-format
|
||||
msgid "Broken cell list item found in cell %s. Will continue.\n"
|
||||
msgstr "Defektes Listenelement in Zelle %s. Ignoriere.\n"
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:57
|
||||
#, c-format
|
||||
msgid "Broken cell list item found. Will continue.\n"
|
||||
msgstr "Defektes Zellenelement in Liste gefunden. Ignoriere.\n"
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:409
|
||||
#, c-format
|
||||
msgid "Cairo export finished. It might still be buggy!\n"
|
||||
msgstr "Cairo-Export abgeschlossen. Möglicherweise fehlerhaft!\n"
|
||||
|
||||
#. Execute
|
||||
#: ../output-renderers/external-renderer.c:120
|
||||
msgid "Calling external renderer."
|
||||
msgstr "Rufe externen Renderer auf."
|
||||
|
||||
#: ../gds-render-gui.c:286 ../widgets/conv-settings-dialog.c:291
|
||||
msgid "Cancel"
|
||||
msgstr "Abbruch"
|
||||
|
||||
#: ../gds-render-gui.c:244
|
||||
msgid "Cell"
|
||||
msgstr "Zelle"
|
||||
|
||||
#: ../command-line.c:209
|
||||
#, c-format
|
||||
msgid "Cell is affected by reference loop. Abort!\n"
|
||||
msgstr "Zelle ist von referenzschleife betroffen. Abbruch!\n"
|
||||
|
||||
#: ../main.c:284
|
||||
msgid "Cell to render"
|
||||
msgstr "Zu rendernde Zelle"
|
||||
|
||||
#: ../command-line.c:215
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Cell was not checked. This should not happen. Please report this issue. Will "
|
||||
"continue either way.\n"
|
||||
msgstr ""
|
||||
"Zelle wurde nicht überprüft. Das sollte nicht passieren. Bitte melden Sie "
|
||||
"dieses Problem. Es wird dennoch fortgefahren.\n"
|
||||
|
||||
#: ../command-line.c:202
|
||||
#, c-format
|
||||
msgid "Checking library %s failed.\n"
|
||||
msgstr "Überprüfung von Bibliothek %s fehlgeschlagen.\n"
|
||||
|
||||
#: ../resources/dialog.glade:79
|
||||
msgid "Configure LaTeX as standalone document"
|
||||
msgstr "Konfiguriere LaTeX als eigenständiges Dokument"
|
||||
|
||||
#: ../resources/main.glade:109
|
||||
msgid "Convert selected cell"
|
||||
msgstr "Konvertiere ausgewählte Zelle"
|
||||
|
||||
#: ../output-renderers/external-renderer.c:89
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not load external library '%s'\n"
|
||||
"Detailed error is:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
"Externe Bibliothek '%s' konnte nicht geladen werden.\n"
|
||||
"Detailierter Fehler:\n"
|
||||
"%s\n"
|
||||
|
||||
#: ../output-renderers/latex-renderer.c:373
|
||||
msgid "Could not open LaTeX output file"
|
||||
msgstr "LaTeX-Ausgabedatei konnte nicht geöffnet werden"
|
||||
|
||||
#: ../command-line.c:195
|
||||
#, c-format
|
||||
msgid "Couldn't find cell in first library!\n"
|
||||
msgstr "Zelle nicht in erster Bibliothek gefunden!\n"
|
||||
|
||||
#: ../command-line.c:81
|
||||
#, c-format
|
||||
msgid "Count of renderers %d does not match count of output file names %d\n"
|
||||
msgstr ""
|
||||
"Anzahl der Renderer %d stimmt nicht mit der Anzahl der angegebenen "
|
||||
"Ausgabedateinamen %d überein\n"
|
||||
|
||||
#: ../main.c:286
|
||||
msgid "Create PDF Layers (OCG)"
|
||||
msgstr "Generiere PDF-Layer (OCG)"
|
||||
|
||||
#: ../main.c:285
|
||||
msgid "Create standalone TeX"
|
||||
msgstr "Generiere eingenständiges TeX"
|
||||
|
||||
#: ../main.c:280
|
||||
msgid "Divide output coordinates by <SCALE>"
|
||||
msgstr "Dividiere Ausgabekoordinaten durch <SCALE>"
|
||||
|
||||
#: ../resources/layer-widget.glade:62
|
||||
msgid "Export Layer"
|
||||
msgstr "Exportiere Layer"
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:366
|
||||
#, c-format
|
||||
msgid "Exporting layer %d to file\n"
|
||||
msgstr "Exportiere Layer %d in Datei\n"
|
||||
|
||||
#: ../output-renderers/external-renderer.c:142
|
||||
msgid "External renderer finished."
|
||||
msgstr "Externer Renderer beendet."
|
||||
|
||||
#. This should not happen
|
||||
#: ../output-renderers/cairo-renderer.c:271
|
||||
#, c-format
|
||||
msgid "Fatal error: Cairo Renderer: Could not spawn child process!"
|
||||
msgstr ""
|
||||
"Fataler Fehler: Cairo Renderer: Sub-Prozess konnte nicht gestartet werden!"
|
||||
|
||||
#: ../resources/main.glade:50
|
||||
msgid "GDS-Render"
|
||||
msgstr "GDS-Render"
|
||||
|
||||
#: ../gds-render-gui.c:294
|
||||
msgid "GDSII-Files"
|
||||
msgstr "GDSII-Dateien"
|
||||
|
||||
#: ../resources/dialog.glade:18
|
||||
msgid "Generate LaTeX/TikZ output"
|
||||
msgstr "Generiere LaTeX/TikZ Ausgabe"
|
||||
|
||||
#: ../resources/dialog.glade:93
|
||||
msgid "Generate PDF Layers"
|
||||
msgstr "Generiere PDF Layers"
|
||||
|
||||
#: ../output-renderers/latex-renderer.c:253
|
||||
#, c-format
|
||||
msgid "Generating cell %s"
|
||||
msgstr "Generiere Zelle %s"
|
||||
|
||||
#: ../resources/about.glade:12
|
||||
msgid "Git Repository"
|
||||
msgstr "Git Repository"
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:246
|
||||
#, c-format
|
||||
msgid "Height: %.3lf %sm"
|
||||
msgstr "Höhe: %.3lf %sm"
|
||||
|
||||
#: ../main.c:321
|
||||
#, c-format
|
||||
msgid "Ignored argument: %s"
|
||||
msgstr "Ignoriertes Argument: %s"
|
||||
|
||||
#: ../output-renderers/external-renderer.c:106
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Init function not found in library:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
"Init-Funktion nicht in Bibliothek gefunden:\n"
|
||||
"%s\n"
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:321
|
||||
#, c-format
|
||||
msgid "Layer number too high / outside of spec.\n"
|
||||
msgstr "Layer-Nummer zu hoch / Außerhalb der Spezifikation.\n"
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:369
|
||||
#, c-format
|
||||
msgid "Layer outside of spec.\n"
|
||||
msgstr "Layer außerhalb der Spezifikation\n"
|
||||
|
||||
#: ../widgets/layer-element.c:102
|
||||
#, c-format
|
||||
msgid "Layer: %d"
|
||||
msgstr "Layer: %d"
|
||||
|
||||
#: ../gds-render-gui.c:241
|
||||
msgid "Library"
|
||||
msgstr "Bibliothek"
|
||||
|
||||
#: ../resources/main.glade:68
|
||||
msgid "Load Mapping"
|
||||
msgstr "Zuordnung laden"
|
||||
|
||||
#: ../resources/main.glade:73
|
||||
msgid "Load the current layer configuration from CSV"
|
||||
msgstr "Lade die aktuelle Layer-Zuordnung aus einer CSV-Datei"
|
||||
|
||||
#: ../main.c:116
|
||||
#, c-format
|
||||
msgid "Logo could not be displayed: %s\n"
|
||||
msgstr "Logo konnte nicht angezeigt werden: %s\n"
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:293
|
||||
msgid "No layer specification supplied."
|
||||
msgstr "Keine Layer-Spezifikation angegeben."
|
||||
|
||||
#: ../command-line.c:186
|
||||
#, c-format
|
||||
msgid "No library in library list. This should not happen.\n"
|
||||
msgstr "Keine Bibliothek in Bibliotheksliste. Das sollte nicht passieren.\n"
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:288
|
||||
msgid "No/invalid output file set."
|
||||
msgstr "Keine oder invalide Ausgabedatei angegeben."
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:291
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: ../resources/main.glade:58
|
||||
msgid "Open GDS2 Database"
|
||||
msgstr "Öffne GDS2 Datenbank"
|
||||
|
||||
#: ../gds-render-gui.c:287
|
||||
msgid "Open GDSII"
|
||||
msgstr "Öffne GDSII"
|
||||
|
||||
#: ../gds-render-gui.c:284
|
||||
msgid "Open GDSII File"
|
||||
msgstr "Öffne GDSII-Datei"
|
||||
|
||||
#: ../main.c:299
|
||||
#, c-format
|
||||
msgid "Option parsing failed: %s\n"
|
||||
msgstr "Optionsverarbeitung fehlgeschlagen: %s\n"
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:255
|
||||
#, c-format
|
||||
msgid "Output Height: %u px"
|
||||
msgstr "Ausgabehöhe: %u px"
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:283
|
||||
msgid "Output Renderer not valid."
|
||||
msgstr "Ausgaberenderer invalide."
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:304
|
||||
msgid "Output Renderer: Rendering function broken. This is a bug."
|
||||
msgstr ""
|
||||
"Ausgaberenderer: Render-Funktion defekt. Dies ist ein interner "
|
||||
"Programmfehler."
|
||||
|
||||
#. Set the pixel sizes
|
||||
#: ../widgets/conv-settings-dialog.c:252
|
||||
#, c-format
|
||||
msgid "Output Width: %u px"
|
||||
msgstr "Ausgabebreite: %u px"
|
||||
|
||||
#: ../main.c:282
|
||||
msgid "Output file path. Can be used multiple times."
|
||||
msgstr "Ausgabepfad. Kann mehrfach angegeben werden."
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:298
|
||||
msgid "Output renderer called without cell to render."
|
||||
msgstr "Ausgaberenderer ohne zu rendernde Zelle aufgerufen."
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:74
|
||||
msgid "Output renderer does not define a render_output function!"
|
||||
msgstr "Ausgaberenderer definiert keine render_output Funktion!"
|
||||
|
||||
#: ../main.c:283
|
||||
msgid "Path for Layer Mapping File"
|
||||
msgstr "Pfad zur Lagenzuordnungsdatei"
|
||||
|
||||
#: ../main.c:288
|
||||
msgid ""
|
||||
"Path to a custom shared object, that implements the necessary rendering "
|
||||
"functions"
|
||||
msgstr ""
|
||||
"Pfad zu einem benutzerdefiniertem Shared-Object, welches die notwendigen "
|
||||
"Funktionen implementiert"
|
||||
|
||||
#: ../output-renderers/external-renderer.c:78
|
||||
#, c-format
|
||||
msgid "Path to shared object not set!\n"
|
||||
msgstr "Kein Pfad zu einem Shared-Object gesetzt!\n"
|
||||
|
||||
#: ../command-line.c:74
|
||||
#, c-format
|
||||
msgid "Please specify renderers and file names\n"
|
||||
msgstr "Bitte Renderer und Dateinamen angeben.\n"
|
||||
|
||||
#: ../command-line.c:104
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please specify shared object for external renderer. Will ignore this "
|
||||
"renderer.\n"
|
||||
msgstr ""
|
||||
"Bitte Shares-Object für externen Renderer angeben. Dieser Renderer wird "
|
||||
"ignoriert.\n"
|
||||
|
||||
#: ../main.c:277
|
||||
msgid "Print version"
|
||||
msgstr "Zeige Versionsnummer"
|
||||
|
||||
#: ../command-line.c:160
|
||||
#, c-format
|
||||
msgid "Probably missing argument. Check --help option\n"
|
||||
msgstr "Vermutlich ein fehlendes Argument. Bitte --help überprüfen\n"
|
||||
|
||||
#: ../main.c:219
|
||||
msgid "Quit"
|
||||
msgstr "Beenden"
|
||||
|
||||
#: ../widgets/activity-bar.c:104
|
||||
msgid "Ready"
|
||||
msgstr "Bereit"
|
||||
|
||||
#: ../resources/dialog.glade:33
|
||||
msgid "Render PDF using Cairographics"
|
||||
msgstr "Rendere PDF mit Cairographics"
|
||||
|
||||
#: ../resources/dialog.glade:48
|
||||
msgid "Render SVG using Cairographics (too buggy at the moment)"
|
||||
msgstr "Rendere SVG mit Cairographics (Experimentell)"
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:293
|
||||
msgid "Renderer Settings"
|
||||
msgstr "Renderer Einstellungen"
|
||||
|
||||
#: ../output-renderers/gds-output-renderer.c:365
|
||||
msgid "Renderer already started asynchronously"
|
||||
msgstr "Renderer wird bereits asynchron ausgeführt"
|
||||
|
||||
#: ../main.c:279
|
||||
msgid "Renderer to use. Can be used multiple times."
|
||||
msgstr "Zu nutzender Renderer. Kann mehrfach angegeben werden."
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:467
|
||||
msgid "Rendering Cairo Output..."
|
||||
msgstr "Rendere Cairo-Ausgabe..."
|
||||
|
||||
#: ../gds-render-gui.c:554
|
||||
msgid "Rendering cell..."
|
||||
msgstr "Renderere Zelle..."
|
||||
|
||||
#: ../output-renderers/external-renderer.c:98
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Rendering function not found in library:\n"
|
||||
"%s\n"
|
||||
msgstr ""
|
||||
"Render Funktion nicht in Bibliothek gefunden:\n"
|
||||
"%s\n"
|
||||
|
||||
#: ../resources/main.glade:86
|
||||
msgid "Save Mapping"
|
||||
msgstr "Zuordnung speichern"
|
||||
|
||||
#: ../resources/main.glade:23
|
||||
msgid "Save the current layer configuration to CSV"
|
||||
msgstr "Die aktuelle Lagenkonfiguration als CSV-Datei speichern"
|
||||
|
||||
#: ../main.c:312
|
||||
#, c-format
|
||||
msgid "Scale < 1 not allowed. Setting to 1\n"
|
||||
msgstr "Skaliereung < 1 nicht erlaubt. Setze auf 1\n"
|
||||
|
||||
#: ../resources/layer-widget.glade:51
|
||||
msgid "Select Layer Color and Opacity"
|
||||
msgstr "Wähle Layer-Farbe und Transparenz"
|
||||
|
||||
#: ../resources/main.glade:240
|
||||
msgid "Select all layers for export"
|
||||
msgstr "Wähle alle Layer zum Exporieren"
|
||||
|
||||
#: ../output-renderers/cairo-renderer.c:331
|
||||
#, c-format
|
||||
msgid "Size of layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n"
|
||||
msgstr "Größe von Layer %d%s%s%s: <%lf x %lf> @ (%lf | %lf)\n"
|
||||
|
||||
#: ../resources/main.glade:195
|
||||
msgid "Sort layers ascending"
|
||||
msgstr "Sortiere Layer aufsteigend"
|
||||
|
||||
#: ../resources/main.glade:210
|
||||
msgid "Sort layers descending"
|
||||
msgstr "Sortiere Layer absteigend"
|
||||
|
||||
#: ../main.c:212
|
||||
#, c-format
|
||||
msgid ""
|
||||
"There is already an open instance. Will open second window in that "
|
||||
"instance.\n"
|
||||
msgstr ""
|
||||
"Es ist bereits eine Instanz dieses Programms geöffnet. Es wird ein zweites "
|
||||
"Fenster in jener Instanz geöffnet.\n"
|
||||
|
||||
#: ../main.c:244
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This is gds-render, version: %s\n"
|
||||
"\n"
|
||||
"For a list of supported commands execute with --help option.\n"
|
||||
msgstr ""
|
||||
"Dies ist gds-render, Version: %s\n"
|
||||
"\n"
|
||||
"Für eine Liste der unterstützten Kommandos mit der Option --help ausführen.\n"
|
||||
|
||||
#: ../gds-utils/gds-tree-checker.c:188
|
||||
#, c-format
|
||||
msgid "Visited cell list should be empty. This is a bug. Please report this.\n"
|
||||
msgstr ""
|
||||
"Liste markierter Zellen sollte leer sein. Dies ist ein Fehler. Bitte "
|
||||
"melden.\n"
|
||||
|
||||
#: ../widgets/conv-settings-dialog.c:244
|
||||
#, c-format
|
||||
msgid "Width: %.3lf %sm"
|
||||
msgstr "Breite: %.3lf %sm"
|
||||
|
||||
#: ../widgets/activity-bar.c:110
|
||||
msgid "Working..."
|
||||
msgstr "Arbeite..."
|
||||
|
||||
#: ../main.c:96
|
||||
msgid ""
|
||||
"gds-render is a free tool for rendering GDS2 layout files into vector "
|
||||
"graphics."
|
||||
msgstr ""
|
||||
"gds-render ist ein freies Programm, um GDS2-Layouts in Vektorgrafiken zu "
|
||||
"konvertieren."
|
||||
|
||||
#: ../resources/layer-widget.glade:37
|
||||
msgid "label"
|
||||
msgstr "label"
|
34
translations/pot/prepare_language.sh
Executable file
34
translations/pot/prepare_language.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
|
||||
cd "$DIR"
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "Please specify language code to generate/update"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
locale="$1"
|
||||
podir="./po/$locale"
|
||||
echo "Selected locale: $locale"
|
||||
mkdir -p "$podir"
|
||||
pots=`find . -name '*.pot'`
|
||||
for pot in $pots; do
|
||||
po=`echo "$podir/${pot%.pot}.po" | sed -e "s/\/.\//\//g"`
|
||||
echo -n "$po: "
|
||||
|
||||
if [ -f "$po" ]; then
|
||||
echo "update"
|
||||
msgmerge --update "$po" "$pot"
|
||||
else
|
||||
echo "generate"
|
||||
msginit --input="$pot" --locale="$locale" --output="$po"
|
||||
fi
|
||||
|
||||
done
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tree-store.h
|
||||
* @brief Tree store implementation
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup GUI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gds-render/tree-renderer/tree-store.h>
|
||||
#include <gds-render/tree-renderer/lib-cell-renderer.h>
|
||||
#include <gds-render/gds-utils/gds-types.h>
|
||||
|
||||
/**
|
||||
* @brief this function olny allows cells to be selected
|
||||
* @param selection
|
||||
* @param model
|
||||
* @param path
|
||||
* @param path_currently_selected
|
||||
* @param data
|
||||
* @return TRUE if element is selectable, FALSE if not
|
||||
*/
|
||||
static gboolean tree_sel_func(GtkTreeSelection *selection,
|
||||
GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
gboolean path_currently_selected,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
struct gds_cell *cell;
|
||||
unsigned int error_level;
|
||||
gboolean ret = FALSE;
|
||||
(void)selection;
|
||||
(void)path_currently_selected;
|
||||
(void)data;
|
||||
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell, CELL_SEL_CELL_ERROR_STATE, &error_level, -1);
|
||||
|
||||
/* Allow only rows with _valid_ cell to be selected */
|
||||
if (cell) {
|
||||
/* Cell available. Check if it passed the critical checks */
|
||||
if (!(error_level & LIB_CELL_RENDERER_ERROR_ERR))
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief cell_store_filter_visible_func Decides whether an element of the tree model @p model is visible.
|
||||
* @param model Tree model
|
||||
* @param iter Current element / iter in Model to check
|
||||
* @param data Data. Set to static stores variable
|
||||
* @return TRUE if visible, else FALSE
|
||||
* @note TODO: Maybe implement Damerau-Levenshtein distance matching
|
||||
*/
|
||||
static gboolean cell_store_filter_visible_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
struct tree_stores *stores = (struct tree_stores *)data;
|
||||
struct gds_cell *cell;
|
||||
struct gds_library *lib;
|
||||
gboolean result = FALSE;
|
||||
const char *search_string;
|
||||
|
||||
if (!model || !iter || !stores)
|
||||
goto exit_filter;
|
||||
|
||||
gtk_tree_model_get(model, iter, CELL_SEL_CELL, &cell, CELL_SEL_LIBRARY, &lib, -1);
|
||||
|
||||
if (lib) {
|
||||
result = TRUE;
|
||||
goto exit_filter;
|
||||
}
|
||||
|
||||
if (!cell)
|
||||
goto exit_filter;
|
||||
|
||||
search_string = gtk_entry_get_text(stores->search_entry);
|
||||
|
||||
/* Show all, if field is empty */
|
||||
if (!strlen(search_string))
|
||||
result = TRUE;
|
||||
|
||||
if (strstr(cell->name, search_string))
|
||||
result = TRUE;
|
||||
|
||||
gtk_tree_view_expand_all(stores->base_tree_view);
|
||||
|
||||
exit_filter:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void change_filter(GtkWidget *entry, gpointer data)
|
||||
{
|
||||
struct tree_stores *stores = (struct tree_stores *)data;
|
||||
(void)entry;
|
||||
|
||||
gtk_tree_model_filter_refilter(stores->filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup a GtkTreeView with the necessary columns
|
||||
* @param view Tree view to set up
|
||||
* @param search_entry Entry field for search
|
||||
* @return Tree stores for storing data inside the GtkTreeView
|
||||
*/
|
||||
struct tree_stores *setup_cell_selector(GtkTreeView* view, GtkEntry *search_entry)
|
||||
{
|
||||
static struct tree_stores stores;
|
||||
GtkCellRenderer *render_dates;
|
||||
GtkCellRenderer *render_cell;
|
||||
GtkCellRenderer *render_lib;
|
||||
GtkTreeViewColumn *column;
|
||||
|
||||
stores.base_tree_view = view;
|
||||
stores.search_entry = search_entry;
|
||||
|
||||
stores.base_store = gtk_tree_store_new(CELL_SEL_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
/* Searching */
|
||||
if (search_entry) {
|
||||
stores.filter = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(GTK_TREE_MODEL(stores.base_store), NULL));
|
||||
gtk_tree_model_filter_set_visible_func (stores.filter,
|
||||
(GtkTreeModelFilterVisibleFunc)cell_store_filter_visible_func,
|
||||
&stores, NULL);
|
||||
g_signal_connect(GTK_SEARCH_ENTRY(search_entry), "search-changed", G_CALLBACK(change_filter), &stores);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_model(view, GTK_TREE_MODEL(stores.filter));
|
||||
|
||||
render_dates = gtk_cell_renderer_text_new();
|
||||
render_cell = lib_cell_renderer_new();
|
||||
render_lib = lib_cell_renderer_new();
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes("Library", render_lib, "gds-lib", CELL_SEL_LIBRARY, NULL);
|
||||
gtk_tree_view_append_column(view, column);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes("Cell", render_cell, "gds-cell", CELL_SEL_CELL,
|
||||
"error-level", CELL_SEL_CELL_ERROR_STATE, NULL);
|
||||
gtk_tree_view_append_column(view, column);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes("Mod. Date", render_dates, "text", CELL_SEL_MODDATE, NULL);
|
||||
gtk_tree_view_append_column(view, column);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes("Acc. Date", render_dates, "text", CELL_SEL_ACCESSDATE, NULL);
|
||||
gtk_tree_view_append_column(view, column);
|
||||
|
||||
/* Callback for selection
|
||||
* This prevents selecting a library */
|
||||
gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(view), tree_sel_func, NULL, NULL);
|
||||
|
||||
return &stores;
|
||||
}
|
||||
/** @} */
|
@ -1,5 +1,36 @@
|
||||
project(libversion)
|
||||
|
||||
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()
|
||||
|
||||
add_library(version STATIC "version.c")
|
||||
execute_process(COMMAND bash ./generate-version-string.sh
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_VER)
|
||||
target_compile_definitions(version PUBLIC PROJECT_GIT_VERSION=${GIT_VER})
|
||||
execute_process(COMMAND bash ./generate-git-commit-string.sh
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT)
|
||||
message("${BoldGreen}Commit: ${GIT_COMMIT}")
|
||||
message("Version: ${GIT_VER}${ColorReset}")
|
||||
|
||||
IF(GIT_VER MATCHES "-dirty")
|
||||
message("${BoldRed}Build is dirty! Commit your changes before releasing this version!${ColorReset}")
|
||||
ENDIF(GIT_VER MATCHES "-dirty")
|
||||
target_compile_definitions(version PRIVATE PROJECT_GIT_VERSION=${GIT_VER} PROJECT_GIT_COMMIT=${GIT_COMMIT})
|
||||
|
3
version/generate-git-commit-string.sh
Executable file
3
version/generate-git-commit-string.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
git rev-parse --verify HEAD | tr -d '\n'
|
||||
|
@ -1 +1 @@
|
||||
git describe --tags --dirty
|
||||
git describe --tags --dirty | tr -d '\n'
|
||||
|
@ -17,7 +17,6 @@
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup version Version Number
|
||||
* See @ref git-version-num
|
||||
@ -33,4 +32,12 @@ const char *_app_version_string = xstr(PROJECT_GIT_VERSION);
|
||||
const char *_app_version_string = "! version not set !";
|
||||
#endif
|
||||
|
||||
#ifdef PROJECT_GIT_COMMIT
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
const char *_app_git_commit = xstr(PROJECT_GIT_COMMIT);
|
||||
#else
|
||||
const char *_app_git_commit = "! Commit hash not available !";
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
115
widgets/activity-bar.c
Normal file
115
widgets/activity-bar.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* GDSII-Converter
|
||||
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
|
||||
*
|
||||
* This file is part of GDSII-Converter.
|
||||
*
|
||||
* GDSII-Converter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* GDSII-Converter is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The drag and drop implementation is adapted from
|
||||
* https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/tests/testlist3.c
|
||||
*
|
||||
* Thanks to the GTK3 people for creating these examples.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file activity-bar.c
|
||||
* @brief Status bar indicating activity of the program
|
||||
* @author Mario Hüttel <mario.huettel@gmx.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup ActivityBar
|
||||
* @ingroup Widgets
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <gds-render/widgets/activity-bar.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
/** @brief Opaque ActivityBar object. Not viewable outside this source file. */
|
||||
struct _ActivityBar {
|
||||
GtkBox super;
|
||||
/* Private stuff */
|
||||
GtkWidget *spinner;
|
||||
GtkWidget *label;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ActivityBar, activity_bar, GTK_TYPE_BOX)
|
||||
|
||||
static void activity_bar_dispose(GObject *obj)
|
||||
{
|
||||
ActivityBar *bar;
|
||||
|
||||
bar = ACTIVITY_BAR(obj);
|
||||
|
||||
/* Clear references on owned objects */
|
||||
g_clear_object(&bar->label);
|
||||
g_clear_object(&bar->spinner);
|
||||
|
||||
/* Chain up */
|
||||
G_OBJECT_CLASS(activity_bar_parent_class)->dispose(obj);
|
||||
}
|
||||
|
||||
static void activity_bar_class_init(ActivityBarClass *klass)
|
||||
{
|
||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||
|
||||
oclass->dispose = activity_bar_dispose;
|
||||
}
|
||||
|
||||
static void activity_bar_init(ActivityBar *self)
|
||||
{
|
||||
GtkContainer *box = GTK_CONTAINER(self);
|
||||
|
||||
/* Create Widgets */
|
||||
self->label = gtk_label_new("");
|
||||
self->spinner = gtk_spinner_new();
|
||||
|
||||
/* Add to this widget and show */
|
||||
gtk_container_add(box, self->spinner);
|
||||
gtk_container_add(box, self->label);
|
||||
gtk_widget_show(self->label);
|
||||
gtk_widget_show(self->spinner);
|
||||
|
||||
g_object_ref(self->spinner);
|
||||
g_object_ref(self->label);
|
||||
}
|
||||
|
||||
ActivityBar *activity_bar_new()
|
||||
{
|
||||
ActivityBar *bar;
|
||||
|
||||
bar = ACTIVITY_BAR(g_object_new(TYPE_ACTIVITY_BAR, "orientation", GTK_ORIENTATION_HORIZONTAL, NULL));
|
||||
if (bar)
|
||||
activity_bar_set_ready(bar);
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
||||
void activity_bar_set_ready(ActivityBar *bar)
|
||||
{
|
||||
gtk_label_set_text(GTK_LABEL(bar->label), _("Ready"));
|
||||
gtk_spinner_stop(GTK_SPINNER(bar->spinner));
|
||||
}
|
||||
|
||||
void activity_bar_set_busy(ActivityBar *bar, const char *text)
|
||||
{
|
||||
gtk_label_set_text(GTK_LABEL(bar->label), (text ? text : _("Working...")));
|
||||
gtk_spinner_start(GTK_SPINNER(bar->spinner));
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <gds-render/widgets/conv-settings-dialog.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
struct _RendererSettingsDialog {
|
||||
GtkDialog parent;
|
||||
@ -102,9 +103,9 @@ static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *kla
|
||||
oclass->set_property = renderer_settings_dialog_set_property;
|
||||
oclass->get_property = renderer_settings_dialog_get_property;
|
||||
|
||||
properties[PROP_CELL_NAME] = g_param_spec_string("cell-name",
|
||||
"cell-name",
|
||||
"Cell name to be displayed in header bar",
|
||||
properties[PROP_CELL_NAME] = g_param_spec_string(N_("cell-name"),
|
||||
N_("cell-name"),
|
||||
N_("Cell name to be displayed in header bar"),
|
||||
"",
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_properties(oclass, PROP_COUNT, properties);
|
||||
@ -170,8 +171,11 @@ static gboolean shape_drawer_drawing_callback(GtkWidget *widget, cairo_t *cr, gp
|
||||
|
||||
final_scale_value = (width_scale < height_scale ? width_scale : height_scale);
|
||||
|
||||
cairo_rectangle(cr, -(double)dialog->cell_width*final_scale_value/2.0, -(double)dialog->cell_height*final_scale_value/2.0,
|
||||
(double)dialog->cell_width*final_scale_value, (double)dialog->cell_height*final_scale_value);
|
||||
cairo_rectangle(cr,
|
||||
-(double)dialog->cell_width * final_scale_value / 2.0,
|
||||
-(double)dialog->cell_height * final_scale_value / 2.0,
|
||||
(double)dialog->cell_width * final_scale_value,
|
||||
(double)dialog->cell_height * final_scale_value);
|
||||
cairo_stroke(cr);
|
||||
cairo_restore(cr);
|
||||
|
||||
@ -183,17 +187,17 @@ static double convert_number_to_engineering(double input, const char **out_prefi
|
||||
const char *selected_prefix = NULL;
|
||||
double return_val = 0.0;
|
||||
int idx;
|
||||
const static char * prefixes[] = {"y", "z", "a", "f", "p", "n", "u", "m", "c", "d", /* < 1 */
|
||||
"", /* 1 */
|
||||
"h", "k", "M", "G", "T", "P", "E", "Z", "Y"}; /* > 1 */
|
||||
const static double scale[] = {1E-24, 1E-21, 1E-18, 1E-15, 1E-12, 1E-9, 1E-6, 1E-3, 1E-2, 1E-1,
|
||||
static const char * const prefixes[] = {"y", "z", "a", "f", "p", "n", "u", "m", "c", "d", /* < 1 */
|
||||
"", /* 1 */
|
||||
"h", "k", "M", "G", "T", "P", "E", "Z", "Y"}; /* > 1 */
|
||||
static const double scale[] = {1E-24, 1E-21, 1E-18, 1E-15, 1E-12, 1E-9, 1E-6, 1E-3, 1E-2, 1E-1,
|
||||
1,
|
||||
1E2, 1E3, 1E6, 1E9, 1E12, 1E15, 1E18, 1E21, 1E24};
|
||||
const int prefix_count = (int)(sizeof(prefixes)/sizeof(char *));
|
||||
|
||||
/* If pointer is invalid, return NaN */
|
||||
if (!out_prefix)
|
||||
return 0.0 / 0.0;
|
||||
return (0.0 / 0.0);
|
||||
|
||||
/* Start with the 2nd smallest prefix */
|
||||
for (idx = 1; idx < prefix_count; idx++) {
|
||||
@ -237,18 +241,18 @@ static void renderer_settings_dialog_update_labels(RendererSettingsDialog *self)
|
||||
width_engineering = convert_number_to_engineering(width_meters, &width_prefix);
|
||||
height_engineering = convert_number_to_engineering(height_meters, &height_prefix);
|
||||
|
||||
snprintf(default_buff, sizeof(default_buff), "Width: %.3lf %sm", width_engineering, width_prefix);
|
||||
snprintf(default_buff, sizeof(default_buff), _("Width: %.3lf %sm"), width_engineering, width_prefix);
|
||||
gtk_label_set_text(self->x_label, default_buff);
|
||||
snprintf(default_buff, sizeof(default_buff), "Height: %.3lf %sm", height_engineering, height_prefix);
|
||||
snprintf(default_buff, sizeof(default_buff), _("Height: %.3lf %sm"), height_engineering, height_prefix);
|
||||
gtk_label_set_text(self->y_label, default_buff);
|
||||
|
||||
scale = gtk_range_get_value(GTK_RANGE(self->scale));
|
||||
|
||||
/* Set the pixel sizes */
|
||||
snprintf(default_buff, sizeof(default_buff), "Output Width: %u px",
|
||||
snprintf(default_buff, sizeof(default_buff), _("Output Width: %u px"),
|
||||
(unsigned int)((double)self->cell_width / scale));
|
||||
gtk_label_set_text(self->x_output_label, default_buff);
|
||||
snprintf(default_buff, sizeof(default_buff), "Output Height: %u px",
|
||||
snprintf(default_buff, sizeof(default_buff), _("Output Height: %u px"),
|
||||
(unsigned int)((double)self->cell_height / scale));
|
||||
gtk_label_set_text(self->y_output_label, default_buff);
|
||||
}
|
||||
@ -270,7 +274,7 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self)
|
||||
|
||||
dialog = &self->parent;
|
||||
|
||||
builder = gtk_builder_new_from_resource("/dialog.glade");
|
||||
builder = gtk_builder_new_from_resource("/gui/dialog.glade");
|
||||
box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
|
||||
self->radio_latex = GTK_WIDGET(gtk_builder_get_object(builder, "latex-radio"));
|
||||
self->radio_cairo_pdf = GTK_WIDGET(gtk_builder_get_object(builder, "cairo-pdf-radio"));
|
||||
@ -284,9 +288,9 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self)
|
||||
self->x_output_label = GTK_LABEL(gtk_builder_get_object(builder, "x-output-label"));
|
||||
self->y_output_label = GTK_LABEL(gtk_builder_get_object(builder, "y-output-label"));
|
||||
|
||||
gtk_dialog_add_buttons(dialog, "Cancel", GTK_RESPONSE_CANCEL, "OK", GTK_RESPONSE_OK, NULL);
|
||||
gtk_dialog_add_buttons(dialog, _("Cancel"), GTK_RESPONSE_CANCEL, _("OK"), GTK_RESPONSE_OK, NULL);
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)), box);
|
||||
gtk_window_set_title(GTK_WINDOW(self), "Renderer Settings");
|
||||
gtk_window_set_title(GTK_WINDOW(self), _("Renderer Settings"));
|
||||
|
||||
g_signal_connect(self->radio_latex, "toggled", G_CALLBACK(latex_render_callback), (gpointer)self);
|
||||
g_signal_connect(G_OBJECT(self->shape_drawing),
|
||||
@ -308,9 +312,9 @@ RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
|
||||
RendererSettingsDialog *res;
|
||||
|
||||
res = RENDERER_SETTINGS_DIALOG(g_object_new(RENDERER_TYPE_SETTINGS_DIALOG, NULL));
|
||||
if (res && parent) {
|
||||
if (res && parent)
|
||||
gtk_window_set_transient_for(GTK_WINDOW(res), parent);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -322,13 +326,12 @@ void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struc
|
||||
settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));
|
||||
|
||||
/* Get active radio button selection */
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE) {
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_latex)) == TRUE)
|
||||
settings->renderer = RENDERER_LATEX_TIKZ;
|
||||
} else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf)) == TRUE) {
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_pdf)) == TRUE)
|
||||
settings->renderer = RENDERER_CAIROGRAPHICS_PDF;
|
||||
} else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg)) == TRUE) {
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->radio_cairo_svg)) == TRUE)
|
||||
settings->renderer = RENDERER_CAIROGRAPHICS_SVG;
|
||||
}
|
||||
|
||||
settings->tex_pdf_layers = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->layer_check));
|
||||
settings->tex_standalone = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->standalone_check));
|
||||
|
@ -37,6 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <gds-render/widgets/layer-element.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
|
||||
|
||||
@ -54,6 +55,7 @@ static void layer_element_constructed(GObject *obj)
|
||||
static void layer_element_class_init(LayerElementClass *klass)
|
||||
{
|
||||
GObjectClass *oclass = G_OBJECT_CLASS(klass);
|
||||
|
||||
oclass->dispose = layer_element_dispose;
|
||||
oclass->constructed = layer_element_constructed;
|
||||
}
|
||||
@ -62,7 +64,8 @@ static void layer_element_init(LayerElement *self)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *glade_box;
|
||||
builder = gtk_builder_new_from_resource("/layer-widget.glade");
|
||||
|
||||
builder = gtk_builder_new_from_resource("/gui/layer-widget.glade");
|
||||
glade_box = GTK_WIDGET(gtk_builder_get_object(builder, "box"));
|
||||
gtk_container_add(GTK_CONTAINER(self), glade_box);
|
||||
|
||||
@ -86,7 +89,7 @@ const char *layer_element_get_name(LayerElement *elem)
|
||||
return gtk_entry_get_text(elem->priv.name);
|
||||
}
|
||||
|
||||
void layer_element_set_name(LayerElement *elem, const char* name)
|
||||
void layer_element_set_name(LayerElement *elem, const char *name)
|
||||
{
|
||||
gtk_entry_set_text(elem->priv.name, name);
|
||||
}
|
||||
@ -96,7 +99,7 @@ void layer_element_set_layer(LayerElement *elem, int layer)
|
||||
GString *string;
|
||||
|
||||
string = g_string_new_len(NULL, 100);
|
||||
g_string_printf(string, "Layer: %d", layer);
|
||||
g_string_printf(string, _("Layer: %d"), layer);
|
||||
gtk_label_set_text(elem->priv.layer, (const gchar *)string->str);
|
||||
elem->priv.layer_num = layer;
|
||||
g_string_free(string, TRUE);
|
||||
@ -139,8 +142,9 @@ void layer_element_set_dnd_callbacks(LayerElement *elem, struct layer_element_dn
|
||||
return;
|
||||
|
||||
/* Setup drag and drop */
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context(GTK_WIDGET(elem)), "row");
|
||||
gtk_drag_source_set(GTK_WIDGET(elem->priv.event_handle), GDK_BUTTON1_MASK, data->entries, data->entry_count, GDK_ACTION_MOVE);
|
||||
gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(elem)), "row");
|
||||
gtk_drag_source_set(GTK_WIDGET(elem->priv.event_handle), GDK_BUTTON1_MASK,
|
||||
data->entries, data->entry_count, GDK_ACTION_MOVE);
|
||||
g_signal_connect(elem->priv.event_handle, "drag-begin", G_CALLBACK(data->drag_begin), NULL);
|
||||
g_signal_connect(elem->priv.event_handle, "drag-data-get", G_CALLBACK(data->drag_data_get), NULL);
|
||||
g_signal_connect(elem->priv.event_handle, "drag-end", G_CALLBACK(data->drag_end), NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user