42 Commits

Author SHA1 Message Date
7f7b4cc7bf Fix #17: Reference loop detection fix. This will be part of v1.0-1 2019-06-08 13:32:42 +02:00
d08cd3626d Update Usage page and application screenshot 2019-05-14 19:59:43 +02:00
ef180f3ea2 Add version generation script to doxygen generation script 2019-05-14 19:58:52 +02:00
74ecde9807 Revert "gds-parser: Remove unnecessary code. Fix #13"
Code wasn't unnecessary. Oops.

This reverts commit aa413732f1.
2019-05-14 19:46:17 +02:00
cd2cf8c5c7 Add versioning scheme to documentation 2019-05-14 19:39:29 +02:00
63eb65a3c4 Fix #12: Wrong markdown in usage page. 2019-05-14 19:37:23 +02:00
aa413732f1 gds-parser: Remove unnecessary code. Fix #13 2019-05-14 18:35:40 +02:00
54165a8475 conv-settings-dialog: harden number2eng function against null pointer 2019-05-12 14:16:36 +02:00
c3c4636334 Add cell name to renderer settings dialog title bar 2019-04-08 19:05:07 +02:00
f4de9c4402 Code rework 2019-04-08 18:23:30 +02:00
a016a18587 Improve doxygen 2019-03-30 19:55:47 +01:00
a3626e7b33 Improve doxygen documentation 2019-03-30 19:51:56 +01:00
4dcafeed3f Update doxygen reference 2019-03-28 22:14:11 +01:00
03e2b15571 Add dirty flag to git describe command used for the version string. 2019-03-28 22:02:00 +01:00
e278ad6d94 Move each GTK Widget to its own documentation group 2019-03-26 21:12:37 +01:00
8d8af8d211 Add compiler warnings to documentation 2019-03-26 21:12:05 +01:00
4bed016f01 Update documentation: Add compilation page, fix additional mistake in cell-geometrics.h 2019-03-26 21:00:05 +01:00
e8c7f78af4 Update include file hierarchy: Move include file to central include tree 2019-03-26 19:57:19 +01:00
60e20f45cc Merge branch 'master' into dev 2019-03-25 19:06:26 +01:00
cd55137951 Grouped widgets into GUI group 2019-03-25 19:05:57 +01:00
d6fb6ba6b0 Remove SVG output from GUI, fixes issue #9 2019-03-25 18:57:48 +01:00
829c9a2386 Restructure code, improve doxygen documentation 2019-03-25 18:47:12 +01:00
a99a469cf0 Rename functions of mapping parser 2019-03-25 17:56:57 +01:00
f237004e6c Remove useless function call 2019-03-22 22:43:24 +01:00
188086de52 Rework code: simplify if 2019-03-22 22:24:48 +01:00
38f18009fc Rework Cairo-Render output messages 2019-03-22 22:15:56 +01:00
ff3f692f2c Make renderer settings dialog settings unique for each window 2019-03-22 21:59:43 +01:00
5537c076a8 Add logo as resource and configure about dialog to use logo from resource 2019-03-21 22:22:35 +01:00
b43b142a75 Coding improvements in conversion settings dialog 2019-03-21 21:48:11 +01:00
4c0df56386 cast unused variables 2019-03-21 21:26:31 +01:00
008fe52cb2 Rename gds-parser folder to gds-utils because it no longer contains only the parser 2019-03-21 21:24:59 +01:00
67f9d9b4ee Add source for ListBox Drag and Drop 2019-03-18 21:12:47 +01:00
e289e7b301 fix compiler warnings 2019-03-16 16:24:39 +01:00
b9cc8570ac Use signal for gui disposement. Whena gui is closed, the library data is relesed 2019-03-16 16:09:29 +01:00
5357aff1b8 Fix bug which allowd moving layer elements between different windows. 2019-03-15 23:46:06 +01:00
64508104bc Move drag and drop code from layer element to layer selector. 2019-03-15 23:17:03 +01:00
60f54e2240 Typo 2019-03-15 23:16:39 +01:00
19b26a3c26 Fix bugs in closing gds render windows 2019-03-15 20:36:23 +01:00
28734a797a Merge branch 'master' into rework-main-window-gui 2019-03-15 20:02:53 +01:00
31d9d26aa4 Implement multiple GUI per process feature. Still buggy. 2019-03-15 20:02:03 +01:00
45f0d90a87 remove layer-selector-dnd.h file 2019-03-15 18:23:25 +01:00
33deba8ca4 Command line: Fix auto-guessing of SVG file name. 2019-03-15 18:03:29 +01:00
65 changed files with 1376 additions and 2833 deletions

View File

@@ -10,27 +10,27 @@ add_subdirectory(glade)
add_subdirectory(doxygen)
add_subdirectory(version)
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
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})
aux_source_directory("widgets" LAYER_SOURCES)
aux_source_directory("tree-renderer" RENDERER_SOURCES)
aux_source_directory("gds-parser" PARSER_SOURCES)
aux_source_directory("latex-output" LATEX_SOURCES)
aux_source_directory("cairo-output" CAIRO_SOURCES)
aux_source_directory("trigonometric" TRIG_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("geometric" GEOMETRIC_SOURCES)
aux_source_directory("layer" LAYER_SELECTOR_SOURCES)
set(SOURCE "main.c" "mapping-parser.c" "command-line.c" "main-window.c" "external-renderer.c")
set(SOURCE "main.c" "command-line.c" "gds-render-gui.c" "external-renderer.c")
set(SOURCE
${SOURCE}
${LAYER_SOURCES}
${RENDERER_SOURCES}
${PARSER_SOURCES}
${GDS_SOURCES}
${LATEX_SOURCES}
${CAIRO_SOURCES}
${TRIG_SOURCES}
${GEOMETRIC_SOURCES}
${LAYER_SELECTOR_SOURCES}
)

View File

@@ -1,4 +1,4 @@
# GDS-Render
# GDS-Render Readme
This software is a rendering programm for GDS2 layout files.
The GDS2 format is mainly used in integrated circuit development.

View File

@@ -26,13 +26,14 @@
* @{
*/
#include "cairo-output.h"
#include <math.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-pdf.h>
#include <cairo-svg.h>
#include <gds-render/cairo-renderer/cairo-output.h>
/**
* @brief The cairo_layer struct
* Each rendered layer is represented by this struct.
@@ -235,8 +236,12 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
/* Print size */
cairo_recording_surface_ink_extents(layers[linfo->layer].rec, &rec_x0, &rec_y0,
&rec_width, &rec_height);
printf("Size of layer %d: %lf -- %lf\n", linfo->layer,
rec_width, rec_height);
printf("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 : ""),
(linfo->name && linfo->name[0] ? ")" : ""),
rec_width, rec_height, rec_x0, rec_y0);
/* update bounding box */
xmin = MIN(xmin, rec_x0);
@@ -250,7 +255,7 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
}
printf("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);

View File

@@ -24,19 +24,20 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup cmdline
* @{
*/
#include <stdio.h>
#include "command-line.h"
#include "gds-parser/gds-parser.h"
#include "mapping-parser.h"
#include "layer/layer-info.h"
#include "cairo-output/cairo-output.h"
#include "latex-output/latex-output.h"
#include "external-renderer.h"
#include "gds-parser/gds-tree-checker.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/gds-utils/gds-tree-checker.h>
/**
* @brief Delete layer_info and free nem element.
@@ -98,7 +99,7 @@ void command_line_convert_gds(char *gds_name, char *pdf_name, char *tex_name, gb
dstream = g_data_input_stream_new(G_INPUT_STREAM(stream));
i = 0;
do {
res = load_csv_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
res = mapping_parser_load_line(dstream, &layer_export, &layer_name, &layer, &layer_color);
if (res == 0) {
if (!layer_export)
continue;

View File

@@ -9,7 +9,7 @@ done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
cd "$DIR"
export PROJECT_NUMBER=`git describe --tags`
export PROJECT_NUMBER=`../version/generate-version-string.sh`
if [ $# != 1 ]; then
export OUTPUT_DIRECTORY="./output"

View File

@@ -0,0 +1,4 @@
/**
* @defgroup Cairo-Renderer Cairo Renderer
* @ingroup renderers
*/

3
doxygen/command-line.dox Normal file
View File

@@ -0,0 +1,3 @@
/**
* @defgroup cmdline Command Line Interface
*/

67
doxygen/compilation.dox Normal file
View File

@@ -0,0 +1,67 @@
/**
@page compilation Compilation
@section Preface
GDS-Render is designed for UNIX-like, especially GNU/Linux based systems.
It was developed under a Linux system. Therefore, best performance is expected using a Linux operating system.
@section depencencies Dependencies
The dependencies of GDS-Render are:
@subsection run-deps Program Dependencies
- GLib2
- GTK3
- Cairographics
@subsection comp-deps Compilation Dependencies
These dependencies are not needed for running the program; just for compilation.
- Build System (GCC + binutils, make, etc...). Most distributions supply a "development" meta-package containing this stuff.
- cmake >= 2.8
- More or less optional: git. Used for extraction of the precise version number. It is strongly recommended to provide git!
- Optional: doxygen for this nice documentation.
The dependency list of GTK3 already includes Cairographics and GLib2. You should be on the safe side with a recent GTK3 version.
Development is done with the following library versions:
| Cairographics | GLib2 | GTK3 |
| ------------- | ---------- | ------ |
| 1.16.0-2 | 2.60.0-1 | 3.24.7 |
@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>
@endcode
Cmake will check the dependencies. Once cmake has finished. Type
@code
make
@endcode
in order to build the program and
@code
make documentation
@endcode
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
The compiler will throw the following warnings. Compiled with GCC 8.2.1.
| Warning | Assessment |
| ------- | ---------- |
| warning: calculate_path_miter_points defined but not used [-Wunused-function] | Ignore. Function will be used in later versions. |
*/

View File

@@ -0,0 +1,4 @@
/**
* @defgroup external-renderer External Shared Object Renderer
* @ingroup renderers
*/

View File

@@ -1,8 +1,8 @@
/* This file only contains help information for doxygen */
/**
* @defgroup trigonometric Trigonometric Helper Functions
* @defgroup geometric Geometric Helper Functions
*
* The trigonometric helper function are used to calculate bounding boxes
* The geometric helper function are used to calculate bounding boxes
* @warning Code is incomplete. Please double check for functionality!
*/

View File

@@ -1,6 +1,5 @@
/* This file only contains help information for doxygen */
/**
* @defgroup MainApplication Main Application
*
* @defgroup GUI Graphical User Interface
*/

Binary file not shown.

BIN
doxygen/images/gui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 114 KiB

View File

@@ -0,0 +1,4 @@
/**
* @defgroup LaTeX-Renderer LaTeX/TikZ Renderer
* @ingroup renderers
*/

View File

@@ -0,0 +1,7 @@
/**
* @defgroup layer-selector LayerSelector Object
* @ingroup GUI
*
* This objects implements the layer selector and displays the layers in a list box.
* It uses @ref LayerElement objects to display the individual layers inside the list box.
*/

View File

@@ -0,0 +1,18 @@
/**
* @defgroup LibCellRenderer LibCellRenderer GObject
* @ingroup GUI
*
* The LibCellRenderer Object is used to render @ref gds_cell and @ref gds_library elements
* to a GtkTreeView.
*
* The LibCellRenderer class is derived from a GtkCellRendererText and works the same way.
* The additinal features are three new properties:
*
* - *gds-lib*: This property can be used to set a @ref gds_library structure. The renderer will render the name of the library.
* - *gds-cell*: This property can be used to set a @ref gds_cell structure. The renderer will render the name of the cell.
* - *error-level*: Set the error level of the cell/library. This affects the foreground color of hte rendered output.
*
* Internally the class operates by setting the 'text' property, which is inherited form the base class to the library/cell name (gds_library::name and gds_cell::name fields).
* The error level (@ref LIB_CELL_RENDERER_ERROR_WARN and @ref LIB_CELL_RENDERER_ERROR_ERR) is translated to the inherited 'foreground-rgba' property.
*
*/

View File

@@ -6,10 +6,7 @@ This programm converts GDS layout files to
- PDF Files using the @ref Cairo-Renderer
- Latex code (TikZ) using the @ref LaTeX-Renderer
See the @subpage usage page for details
See the @subpage usage page for details and @subpage compilation for building instructions and @subpage versioning for the versioning scheme of this program.

9
doxygen/renderers.dox Normal file
View File

@@ -0,0 +1,9 @@
/**
* @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.
*/

View File

@@ -1,21 +1,21 @@
/**
@page usage Usage
@section cmd Command Line Interface
To use the application on the command line check 'gds-render --help'.
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
- -t, `--`tikz Output TikZ code
- -p, `--`pdf Output PDF document
- -s, `--`scale=SCALE Divide output coordinates by SCALE
- -o, `--`tex-output=PATH Optional path for TeX file
- -O, `--`pdf-output=PATH Optional path for PDF file
- -m, `--`mapping=PATH Path for Layer Mapping File
- -c, `--`cell=NAME Cell to render
- -a, `--`tex-standalone Create standalone PDF
- -l, `--`tex-layers Create PDF Layers (OCG)
- -P, `--`custom-render-lib=PATH Path to a custom shared object, that implements the render_cell_to_file function
- -e, `--`external-lib-output=PATH Output path for external render library
- `--`display=DISPLAY X display to use
@section gui Graphical User Interface
@@ -24,7 +24,11 @@ The graphical user interface (GUI) can be used to open GDS Files, configure the
It is possible to export the layer configurations so they can be used later on. Even in the @ref cmd
@image html gui.svg
@image latex gui.pdf
@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.
*/

36
doxygen/versioning.dox Normal file
View File

@@ -0,0 +1,36 @@
/**
@page versioning Version Number
@section main-version Main Versioning Scheme
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.
@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.
The 3rd release candidate of version 4.2 would be '*v4.2-rc3*'.
Release candidates are in a frozen state. Only bugfixes that are necessary for functionality are applied to these versions before releasing the final version.
@subsection patch-level Patch Levels
If an already released version contains bugs that need to be fixed, the version number is not incremented. Insted a new version number with a patch-level is created. The patch-level is appended with a dash directly after the version number. The fist patch-level of version 3.5 would be: 'v3.5-1'.
@section git-version-num Git Based Version Number
The application and this documentation contain a git-based version number. With this version number not only released versions but all development points of the software can be uniquely identified.
An example for such a version number is: *v1.0-rc4-41-gaa41373-dirty*
It consists of the last @ref main-version (in this case version 1.0 -- Release candidate 4) and some other information from the source code management system. The number after the version tag is the commit count after the given version. In this case the specified version is 41 commits after the last tagged version 'v1.0-rc4'. The next section always starts with a 'g' (for git) and after that contains the first letters of the commit ID. In this case an additional '-dirty' is appended, showing that the software version contains unstaged changes.
In tabular form: *v1.0-rc4-41-gaa41373-dirty*
| Last tagged version | Commits since that version | Start of commit ID | Unstaged changes? |
|---------------------|----------------------------|--------------------|---------------------|
| 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.
**/

View File

@@ -2,5 +2,5 @@
/**
* @defgroup Widgets Custom GTK Widgets
*
* @ingroup GUI
*/

View File

@@ -24,14 +24,15 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup external-renderer
* @{
*/
#include "external-renderer.h"
#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)
{

559
gds-render-gui.c Normal file
View File

@@ -0,0 +1,559 @@
/*
* 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-render-gui.c
* @brief Handling of GUI
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/** @addtogroup GUI
* @{
*/
#include <stdio.h>
#include <gtk/gtk.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/conv-settings-dialog.h>
#include <gds-render/geometric/cell-geometrics.h>
#include <gds-render/version.h>
enum gds_render_gui_signal_sig_ids {SIGNAL_WINDOW_CLOSED = 0, SIGNAL_COUNT};
static guint gds_render_gui_signals[SIGNAL_COUNT];
struct _GdsRenderGui {
/* Parent GObject */
GObject parent;
/* Custom fields */
GtkWindow *main_window;
GtkWidget *convert_button;
GtkTreeStore *cell_tree_store;
GtkWidget *cell_search_entry;
LayerSelector *layer_selector;
GtkTreeView *cell_tree_view;
GList *gds_libraries;
struct render_settings render_dialog_settings;
};
G_DEFINE_TYPE(GdsRenderGui, gds_render_gui, G_TYPE_OBJECT)
/**
* @brief Main window close event
* @param window GtkWindow which is closed
* @param event unused event
* @param user GdsRenderGui instance
* @return Status of the event handling. Always true.
*/
static gboolean on_window_close(gpointer window, GdkEvent *event, gpointer user)
{
GdsRenderGui *self;
self = RENDERER_GUI(user);
/* Don't close window in case of error */
if (!self)
return TRUE;
/* Close Window. Leads to termination of the program/the current instance */
g_clear_object(&self->main_window);
gtk_widget_destroy(GTK_WIDGET(window));
/* Delete loaded library data */
clear_lib_list(&self->gds_libraries);
g_signal_emit(self, gds_render_gui_signals[SIGNAL_WINDOW_CLOSED], 0);
return TRUE;
}
/**
* @brief generate string from gds_time_field
* @param date Date to convert
* @return String with date
*/
static GString *generate_string_from_date(struct gds_time_field *date)
{
GString *str;
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;
}
/**
* @brief Callback function of Load GDS button
* @param button
* @param user GdsRenderGui instance
*/
static void on_load_gds(gpointer button, gpointer user)
{
GList *cell;
GtkTreeIter libiter;
GtkTreeIter celliter;
GList *lib;
struct gds_library *gds_lib;
struct gds_cell *gds_c;
GdsRenderGui *self;
GtkWidget *open_dialog;
GtkFileChooser *file_chooser;
GtkFileFilter *filter;
GtkStyleContext *button_style;
gint dialog_result;
int gds_result;
char *filename;
GString *mod_date;
GString *acc_date;
unsigned int cell_error_level;
self = RENDERER_GUI(user);
if (!self)
return;
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,
NULL);
file_chooser = GTK_FILE_CHOOSER(open_dialog);
/* Add GDS II Filter */
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.gds");
gtk_file_filter_set_name(filter, "GDSII-Files");
gtk_file_chooser_add_filter(file_chooser, filter);
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
if (dialog_result != GTK_RESPONSE_ACCEPT)
goto end_destroy;
/* Get File name */
filename = gtk_file_chooser_get_filename(file_chooser);
gtk_tree_store_clear(self->cell_tree_store);
clear_lib_list(&self->gds_libraries);
/* Parse new GDSII file */
gds_result = parse_gds_from_file(filename, &self->gds_libraries);
/* Delete file name afterwards */
g_free(filename);
if (gds_result)
goto end_destroy;
/* remove suggested action from Open button */
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
gtk_style_context_remove_class(button_style, "suggested-action");
for (lib = self->gds_libraries; lib != NULL; lib = lib->next) {
gds_lib = (struct gds_library *)lib->data;
/* 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;
if (gds_c->checks.unresolved_child_count)
cell_error_level |= LIB_CELL_RENDERER_ERROR_WARN;
/* Check if it is completely b0rken */
if (gds_c->checks.affected_by_reference_loop)
cell_error_level |= LIB_CELL_RENDERER_ERROR_ERR;
/* Add cell to tree store model */
gtk_tree_store_set(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,
-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 */
/* Create Layers in Layer Box */
layer_selector_generate_layer_widgets(self->layer_selector, self->gds_libraries);
end_destroy:
/* Destroy dialog and filter */
gtk_widget_destroy(open_dialog);
}
/**
* @brief Convert button callback
* @param button
* @param user
*/
static void on_convert_clicked(gpointer button, gpointer user)
{
(void)button;
GdsRenderGui *self;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
GList *layer_list;
struct gds_cell *cell_to_render;
FILE *output_file;
GtkWidget *dialog;
RendererSettingsDialog *settings;
GtkFileFilter *filter;
gint res;
char *file_name;
union bounding_box cell_box;
unsigned int height, width;
struct render_settings *sett;
self = RENDERER_GUI(user);
if (!self)
return;
sett = &self->render_dialog_settings;
/* Get selected cell */
selection = gtk_tree_view_get_selection(self->cell_tree_view);
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
return;
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell_to_render, -1);
if (!cell_to_render)
return;
/* Get layers that are rendered */
layer_list = layer_selector_export_rendered_layer_info(self->layer_selector);
/* Calculate cell size in DB units */
bounding_box_prepare_empty(&cell_box);
calculate_cell_bounding_box(&cell_box, cell_to_render);
/* Calculate size in database units
* Note that the results are bound to be positive,
* so casting them to unsigned int is absolutely valid
*/
height = (unsigned int)(cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y);
width = (unsigned int)(cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x);
/* Show settings dialog */
settings = renderer_settings_dialog_new(GTK_WINDOW(self->main_window));
renderer_settings_dialog_set_settings(settings, sett);
renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters);
renderer_settings_dialog_set_cell_height(settings, height);
renderer_settings_dialog_set_cell_width(settings, width);
g_object_set(G_OBJECT(settings), "cell-name", cell_to_render->name, NULL);
res = gtk_dialog_run(GTK_DIALOG(settings));
if (res == GTK_RESPONSE_OK) {
renderer_settings_dialog_get_settings(settings, sett);
gtk_widget_destroy(GTK_WIDGET(settings));
} else {
gtk_widget_destroy(GTK_WIDGET(settings));
goto ret_layer_destroy;
}
/* save file dialog */
dialog = gtk_file_chooser_dialog_new((sett->renderer == RENDERER_LATEX_TIKZ
? "Save LaTeX File" : "Save PDF"),
GTK_WINDOW(self->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
/* Set file filter according to settings */
filter = gtk_file_filter_new();
switch (sett->renderer) {
case RENDERER_LATEX_TIKZ:
gtk_file_filter_add_pattern(filter, "*.tex");
gtk_file_filter_set_name(filter, "LaTeX-Files");
break;
case RENDERER_CAIROGRAPHICS_PDF:
gtk_file_filter_add_pattern(filter, "*.pdf");
gtk_file_filter_set_name(filter, "PDF-Files");
break;
case RENDERER_CAIROGRAPHICS_SVG:
gtk_file_filter_add_pattern(filter, "*.svg");
gtk_file_filter_set_name(filter, "SVG-Files");
break;
}
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
gtk_widget_destroy(dialog);
switch (sett->renderer) {
case RENDERER_LATEX_TIKZ:
output_file = fopen(file_name, "w");
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett->scale,
sett->tex_pdf_layers, sett->tex_standalone);
fclose(output_file);
break;
case RENDERER_CAIROGRAPHICS_SVG:
case RENDERER_CAIROGRAPHICS_PDF:
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
(sett->renderer == RENDERER_CAIROGRAPHICS_PDF
? file_name
: NULL),
(sett->renderer == RENDERER_CAIROGRAPHICS_SVG
? file_name
: NULL),
sett->scale);
break;
}
g_free(file_name);
} else {
gtk_widget_destroy(dialog);
}
ret_layer_destroy:
g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
}
/**
* @brief cell_tree_view_activated Callback for 'double click' on cell selector element
* @param tree_view The tree view the event occured in
* @param path path to the selected row
* @param column The clicked column
* @param user pointer to GdsRenderGui object
*/
static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
GtkTreeViewColumn *column, gpointer user)
{
(void)tree_view;
(void)path;
(void)column;
on_convert_clicked(NULL, user);
}
/**
* @brief Callback for cell-selection change event
*
* This function activates/deactivates the convert button depending on whether
* a cell is selected for conversion or not
* @param sel
* @param self
*/
static void cell_selection_changed(GtkTreeSelection *sel, GdsRenderGui *self)
{
GtkTreeModel *model = NULL;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
/* Node selected. Show button */
gtk_widget_set_sensitive(self->convert_button, TRUE);
} else {
gtk_widget_set_sensitive(self->convert_button, FALSE);
}
}
static void sort_up_callback(GtkWidget *widget, gpointer user)
{
(void)widget;
GdsRenderGui *self;
self = RENDERER_GUI(user);
if (!self)
return;
layer_selector_force_sort(self->layer_selector, LAYER_SELECTOR_SORT_UP);
}
static void sort_down_callback(GtkWidget *widget, gpointer user)
{
(void)widget;
GdsRenderGui *self;
self = RENDERER_GUI(user);
if (!self)
return;
layer_selector_force_sort(self->layer_selector, LAYER_SELECTOR_SORT_DOWN);
}
static void gds_render_gui_dispose(GObject *gobject)
{
GdsRenderGui *self;
self = RENDERER_GUI(gobject);
clear_lib_list(&self->gds_libraries);
g_clear_object(&self->cell_tree_view);
g_clear_object(&self->convert_button);
g_clear_object(&self->layer_selector);
g_clear_object(&self->cell_tree_store);
g_clear_object(&self->cell_search_entry);
if (self->main_window) {
g_signal_handlers_destroy(self->main_window);
gtk_widget_destroy(GTK_WIDGET(self->main_window));
self->main_window = NULL;
}
/* Chain up */
G_OBJECT_CLASS(gds_render_gui_parent_class)->dispose(gobject);
}
static void gds_render_gui_class_init(GdsRenderGuiClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
gds_render_gui_signals[SIGNAL_WINDOW_CLOSED] =
g_signal_newv("window-closed", RENDERER_TYPE_GUI,
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
NULL,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0,
NULL);
gobject_class->dispose = gds_render_gui_dispose;
}
GtkWindow *gds_render_gui_get_main_window(GdsRenderGui *gui)
{
return gui->main_window;
}
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;
main_builder = gtk_builder_new_from_resource("/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;
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")),
"clicked", G_CALLBACK(on_load_gds), (gpointer)self);
self->convert_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
g_signal_connect(self->convert_button, "clicked", G_CALLBACK(on_convert_clicked), (gpointer)self);
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
/* Create layer selector */
self->layer_selector = layer_selector_new(GTK_LIST_BOX(listbox));
/* Callback for selection change of cell selector */
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(self->cell_tree_view)), "changed",
G_CALLBACK(cell_selection_changed), self);
g_signal_connect(self->cell_tree_view, "row-activated", G_CALLBACK(cell_tree_view_activated), self);
/* Set version in main window subtitle */
header_bar = GTK_HEADER_BAR(gtk_builder_get_object(main_builder, "header-bar"));
gtk_header_bar_set_subtitle(header_bar, _app_version_string);
/* Get layer sorting buttons and set callbacks */
sort_up_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-up-sort"));
sort_down_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-down-sort"));
g_signal_connect(sort_up_button, "clicked", G_CALLBACK(sort_up_callback), 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);
/* Connect delete-event */
g_signal_connect(GTK_WIDGET(self->main_window), "delete-event",
G_CALLBACK(on_window_close), self);
g_object_unref(main_builder);
/* Set default conversion/rendering settings */
self->render_dialog_settings.scale = 1000;
self->render_dialog_settings.renderer = RENDERER_LATEX_TIKZ;
self->render_dialog_settings.tex_pdf_layers = FALSE;
self->render_dialog_settings.tex_standalone = FALSE;
/* Reference all objects referenced by this object */
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->cell_search_entry);
}
GdsRenderGui *gds_render_gui_new()
{
return RENDERER_GUI(g_object_new(RENDERER_TYPE_GUI, NULL));
}
/** @} */

View File

@@ -34,8 +34,6 @@
* @{
*/
#include "gds-parser.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -43,6 +41,8 @@
#include <math.h>
#include <cairo.h>
#include <gds-render/gds-utils/gds-parser.h>
/**
* @brief Default units assumed for library.
* @note This value is usually overwritten with the value defined in the library.

View File

@@ -33,9 +33,10 @@
* @{
*/
#include "gds-tree-checker.h"
#include <stdio.h>
#include <gds-render/gds-utils/gds-tree-checker.h>
int gds_tree_check_cell_references(struct gds_library *lib)
{
GList *cell_iter;
@@ -175,6 +176,16 @@ int gds_tree_check_reference_loops(struct gds_library *lib)
/* iterate through references and check if loop exists */
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.
* 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");
g_list_free(visited_cells);
}
if (res < 0) {
/* Error */
return res;
@@ -189,10 +200,6 @@ int gds_tree_check_reference_loops(struct gds_library *lib)
}
if (visited_cells) {
fprintf(stderr, "Visited cell list should be empty. This is a bug. Please report this.\n");
g_list_free(visited_cells);
}
return loop_count;
}

View File

@@ -24,14 +24,15 @@
*/
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/
#include <stdio.h>
#include "bounding-box.h"
#include <math.h>
#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 ABS_DBL(a) ((a) < 0 ? -(a) : (a))

View File

@@ -18,16 +18,17 @@
*/
/**
* @file cell-trigonometrics.c
* @file cell-geometrics.c
* @brief Calculation of gds_cell trigonometrics
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#include "cell-trigonometrics.h"
#include <math.h>
#include <gds-render/geometric/cell-geometrics.h>
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/

View File

@@ -24,14 +24,15 @@
*/
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/
#include "vector-operations.h"
#include <math.h>
#include <stdlib.h>
#include <gds-render/geometric/vector-operations.h>
#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
double vector_2d_scalar_multipy(struct vector_2d *a, struct vector_2d *b)

View File

@@ -1,6 +1,7 @@
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

View File

@@ -10,7 +10,7 @@
<property name="website">https://git.shimatta.de/mhu/gds-render</property>
<property name="website_label" translatable="yes">Git Repository</property>
<property name="authors">Mario Hüttel &lt;mario.huettel@gmx.net&gt;</property>
<property name="logo_icon_name">gds-render</property>
<property name="logo_icon_name"/>
<property name="license_type">gpl-2-0-only</property>
<child>
<placeholder/>

View File

@@ -16,7 +16,6 @@
<child>
<object class="GtkRadioButton" id="latex-radio">
<property name="label" translatable="yes">Generate LaTeX/TikZ output</property>
<property name="use_action_appearance">True</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -32,11 +31,9 @@
<child>
<object class="GtkRadioButton" id="cairo-pdf-radio">
<property name="label" translatable="yes">Render PDF using Cairographics</property>
<property name="use_action_appearance">True</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">latex-radio</property>
</object>
@@ -49,11 +46,10 @@
<child>
<object class="GtkRadioButton" id="cairo-svg-radio">
<property name="label" translatable="yes">Render SVG using Cairographics (too buggy at the moment)</property>
<property name="use_action_appearance">True</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">latex-radio</property>
</object>

View File

@@ -5,6 +5,7 @@
<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>

View File

@@ -21,11 +21,11 @@
* @brief Header File for Cairo output renderer
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#ifndef __CAIRO_OUTPUT_H__
#define __CAIRO_OUTPUT_H__
#ifndef _CAIRO_OUTPUT_H_
#define _CAIRO_OUTPUT_H_
#include "../layer/layer-info.h"
#include "../gds-parser/gds-types.h"
#include <gds-render/gds-utils/gds-types.h>
#include <gds-render/layer/layer-info.h>
/** @addtogroup Cairo-Renderer
* @{
@@ -45,4 +45,4 @@ void cairo_render_cell_to_vector_file(struct gds_cell *cell, GList *layer_infos,
/** @} */
#endif /* __CAIRO_OUTPUT_H__ */
#endif /* _CAIRO_OUTPUT_H_ */

View File

@@ -24,12 +24,13 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup cmdline
* @{
*/
#ifndef _COMMAND_LINE_H_
#define _COMMAND_LINE_H_
#include <glib.h>
/**
@@ -48,6 +49,8 @@
* @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.
*/
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,

View File

@@ -24,14 +24,14 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup external-renderer
* @{
*/
#ifndef _EXTERNAL_RENDERER_H_
#define _EXTERNAL_RENDERER_H_
#include "gds-parser/gds-types.h"
#include <gds-render/gds-utils/gds-types.h>
#include <glib.h>
/**

View File

@@ -18,29 +18,44 @@
*/
/**
* @file main-window.h
* @brief Header for main-window
* @file gds-render-gui.h
* @brief Header for GdsRenderGui Object
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#ifndef _MAIN_WINDOW_H_
#define _MAIN_WINDOW_H_
#ifndef _GDS_RENDER_GUI_
#define _GDS_RENDER_GUI_
/**
* @addtogroup MainApplication
* @addtogroup GUI
* @{
*/
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(GdsRenderGui, gds_render_gui, RENDERER, GUI, GObject);
#define RENDERER_TYPE_GUI (gds_render_gui_get_type())
/**
* @brief Create main window
*
* This function creates the main window and sets the necessary callback routines.
* @return
* @brief Create new GdsRenderGui Object
* @return New object
*/
GtkWindow *create_main_window();
GdsRenderGui *gds_render_gui_new();
/**
* @brief Get main window
*
* This function returns the main window of the GUI, which can later be displayed.
* All handling of hte GUI is taken care of inside the GdsRenderGui Object
* @return The generated main window
*/
GtkWindow *gds_render_gui_get_main_window(GdsRenderGui *gui);
G_END_DECLS
/** @} */
#endif /* _MAIN_WINDOW_H_ */
#endif /* _GDS_RENDER_GUI_ */

View File

@@ -28,11 +28,12 @@
* @{
*/
#ifndef __GDSPARSE_H__
#define __GDSPARSE_H__
#ifndef _GDSPARSER_H_
#define _GDSPARSER_H_
#include <glib.h>
#include "gds-types.h"
#include <gds-render/gds-utils/gds-types.h>
#define GDS_PRINT_DEBUG_INFOS (0) /**< @brief 1: Print infos, 0: Don't print */
@@ -46,4 +47,4 @@ int clear_lib_list(GList **library_list);
/** @} */
#endif /* __GDSPARSE_H__ */
#endif /* _GDSPARSE_H_ */

View File

@@ -31,7 +31,7 @@
#ifndef _GDS_TREE_CHECKER_H_
#define _GDS_TREE_CHECKER_H_
#include "gds-types.h"
#include <gds-render/gds-utils/gds-types.h>
/**
* @brief gds_tree_check_cell_references checks if all child cell references can be resolved in the given library

View File

@@ -69,8 +69,8 @@ struct gds_point {
* @brief Stores the result of the cell checks.
*/
struct gds_cell_checks {
int unresolved_child_count; /**< @brief Number of unresolved cell instances inside this cell. Default: GDS_CELL_CHECK_NOT_RUN */
int affected_by_reference_loop; /**< @brief 1 if the cell is affected by a reference loop and therefore not renderable. Default: GDS_CELL_CHECK_NOT_RUN*/
int unresolved_child_count; /**< @brief Number of unresolved cell instances inside this cell. Default: @ref GDS_CELL_CHECK_NOT_RUN */
int affected_by_reference_loop; /**< @brief 1 if the cell is affected by a reference loop and therefore not renderable. Default: @ref GDS_CELL_CHECK_NOT_RUN*/
/**
* @brief For the internal use of the checker.
* @warning Do not use this structure and its contents!

View File

@@ -24,14 +24,15 @@
*/
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/
#ifndef _BOUNDING_BOX_H_
#define _BOUNDING_BOX_H_
#include <glib.h>
#include "vector-operations.h"
#include <gds-render/geometric/vector-operations.h>
#include <stdbool.h>
union bounding_box {

View File

@@ -18,30 +18,30 @@
*/
/**
* @file cell-trigonometrics.h
* @brief Calculation of gds_cell trigonometrics
* @file cell-geometrics.h
* @brief Calculation of gds_cell geometrics
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/
#ifndef _CELL_TRIGONOMETRICS_H_
#define _CELL_TRIGONOMETRICS_H_
#ifndef _CELL_GEOMETRICS_H_
#define _CELL_GEOMETRICS_H_
#include "bounding-box.h"
#include "../gds-parser/gds-types.h"
#include <gds-render/geometric/bounding-box.h>
#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
* @param cell toplevel cell
* @warning Path handling not yet implemented correctly
* @param cell Toplevel cell
* @warning Path handling not yet implemented correctly.
*/
void calculate_cell_bounding_box(union bounding_box *box, struct gds_cell *cell);
#endif /* _CELL_TRIGONOMETRICS_H_ */
#endif /* _CELL_GEOMETRICS_H_ */
/** @} */

View File

@@ -24,7 +24,7 @@
*/
/**
* @addtogroup trigonometric
* @addtogroup geometric
* @{
*/

View File

@@ -31,10 +31,11 @@
* @{
*/
#include "../gds-parser/gds-types.h"
#include <glib.h>
#include <stdio.h>
#include "../layer/layer-info.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 */

View File

@@ -18,14 +18,34 @@
*/
/**
* @file layer-selector-dnd.h
* @brief Header for drag and drop of layer selector
* @file layer-info.h
* @brief Helper functions and definition of layer info struct
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#ifndef _LAYER_SELECTOR_DND_H_
#define _LAYER_SELECTOR_DND_H_
#ifndef _LAYER_INFO_H_
#define _LAYER_INFO_H_
#include <gtk/gtk.h>
#endif /* _LAYER_SELECTOR_DND_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_

View File

@@ -23,6 +23,11 @@
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup layer-selector
* @{
*/
#ifndef __LAYER_SELECTOR_H__
#define __LAYER_SELECTOR_H__
@@ -48,42 +53,45 @@ enum layer_selector_sort_algo {LAYER_SELECTOR_SORT_DOWN = 0, LAYER_SELECTOR_SORT
LayerSelector *layer_selector_new(GtkListBox *list_box);
/**
* @brief Generate layer widgets in \p listbox
* @brief Generate layer widgets in in the LayerSelector instance
* @note This clears all previously inserted elements
* @param listbox
* @param selector LayerSelector instance
* @param libs The libraries to add
*/
void layer_selector_generate_layer_widgets(LayerSelector *selector, GList *libs);
/**
* @brief Supply button for loading the layer mapping
* @param button
* @param main_window Parent window for dialogs
* @param selector LayerSelector instance
* @param button Load button. Will be referenced
* @param main_window Parent window for dialogs. Will be referenced
*/
void layer_selector_set_load_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window);
/**
* @brief Supply button for saving the layer mapping
* @param button
* @param main_window Parent window for dialogs
* @param selector LayerSelector instance
* @param button Save button. Will be refeneced
* @param main_window Parent window for dialogs. Will be referenced
*/
void layer_selector_set_save_mapping_button(LayerSelector *selector, GtkWidget *button, GtkWindow *main_window);
/**
* @brief get the layer information present in the listbox of the selector
* @return List with layer_info elements
* @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
*/
GList *layer_selector_export_rendered_layer_info(LayerSelector *selector);
/**
* @brief Force sorting of the layer selector in a specified way
*
* If the layer selector is not yet set up, this function has no effect.
*
* @param sort_function Sorting direction
* @brief Force the layer selector list to be sorted according to \p sort_function
* @param selector LayerSelector instance
* @param sort_function The sorting method (up or down sorting)
*/
void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort_algo sort_function);
G_END_DECLS
#endif /* __LAYER_SELECTOR_H__ */
/** @} */

View File

@@ -27,12 +27,13 @@
#define __MAPPING_PARSER_H__
/**
* @addtogroup MainApplication
* @addtogroup Mapping-Parser
* @{
*/
#include <gtk/gtk.h>
#include "widgets/layer-element.h"
#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
@@ -43,7 +44,7 @@
* @param color RGBA color.
* @return 1 if malformatted line, 0 if parsing was successful and parameters are valid, -1 if file end
*/
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color);
/**
* @brief Create Line for LayerMapping file with supplied information
@@ -51,7 +52,7 @@ int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *
* @param line_buffer buffer to write to
* @param max_len Maximum length that cna be used in \p line_buffer
*/
void create_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len);
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len);
/** @} */

View File

@@ -17,6 +17,17 @@
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file lib-cell-renderer.h
* @brief Header file for the LibCellRenderer GObject Class
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup LibCellRenderer
* @{
*/
#ifndef __LIB_CELL_RENDERER_H__
#define __LIB_CELL_RENDERER_H__
@@ -27,8 +38,12 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(LibCellRenderer, lib_cell_renderer, LIB_CELL, RENDERER, GtkCellRendererText)
#define TYPE_LIB_CELL_RENDERER (lib_cell_renderer_get_type())
/** @{
* Error levels
*/
#define LIB_CELL_RENDERER_ERROR_WARN (1U<<0)
#define LIB_CELL_RENDERER_ERROR_ERR (1U<<1)
/** @} */
typedef struct _LibCellRenderer {
/* Inheritance */
@@ -36,9 +51,20 @@ typedef struct _LibCellRenderer {
/* Custom Elements */
} LibCellRenderer;
/**
* @brief lib_cell_renderer_get_type
* @return GObject Type
*/
GType lib_cell_renderer_get_type(void);
/**
* @brief Create a new renderer for renderering @ref gds_cell and @ref gds_library elements.
* @return New renderer object
*/
GtkCellRenderer *lib_cell_renderer_new(void);
G_END_DECLS
#endif /* __LIB_CELL_RENDERER_H__ */
/** @} */

View File

@@ -24,7 +24,7 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup GUI
* @{
*/

View File

@@ -18,11 +18,11 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup version
* @{
*/
/** @brief This string holds the 'git describe' version of the app */
extern char *_app_version_string;
/** @brief This string holds the @ref git-version-num of the app */
extern const char *_app_version_string;
/** @} */

View File

@@ -24,7 +24,8 @@
*/
/**
* @addtogroup Widgets
* @addtogroup RendererSettingsDialog
* @ingroup Widgets
* @{
*/

View File

@@ -24,7 +24,8 @@
*/
/**
* @addtogroup Widgets
* @addtogroup LayerElement
* @ingroup Widgets
* @{
*/
@@ -56,6 +57,22 @@ struct _LayerElement {
LayerElementPriv priv;
};
/**
* @brief This structure holds the necessary data to set up a LayerElement for Drag'n'Drop
*/
struct layer_element_dnd_data {
/** @brief Array of target entries for the DnD operation */
GtkTargetEntry *entries;
/** @brief Count of elements in layer_element_dnd_data::entries array */
int entry_count;
/** @brief Callback function for drag_begin event */
void (*drag_begin)(GtkWidget *, GdkDragContext *, gpointer);
/** @brief Callback fucktion for data_get event */
void (*drag_data_get)(GtkWidget *, GdkDragContext *, GtkSelectionData *, guint, guint, gpointer);
/** @brief Callback function for drag_end event */
void (*drag_end)(GtkWidget *, GdkDragContext *, gpointer);
};
/**
* @brief Create new layer element object
* @return new object
@@ -118,6 +135,13 @@ void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba);
*/
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba);
/**
* @brief Setup drag and drop of \p elem for use in the LayerSelector
* @param elem Layer element to set up
* @param data Data array containing the necessary callbacks etc. for drag and drop.
*/
void layer_element_set_dnd_callbacks(LayerElement *elem, struct layer_element_dnd_data *data);
G_END_DECLS
#endif /* __LAYER_ELEMENT_H__ */

View File

@@ -23,9 +23,10 @@
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#include "latex-output.h"
#include <math.h>
#include <gds-render/latex-renderer/latex-output.h>
/**
* @addtogroup LaTeX-Renderer
* @{

View File

@@ -1,9 +1,33 @@
/*
* GDSII-Converter
* Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of GDSII-Converter.
*
* GDSII-Converter is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file layer-info.c
* @brief Helper functions for layer info struct
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#include "layer-info.h"
#include <gds-render/layer/layer-info.h>
void layer_info_delete_struct(struct layer_info *info)
{
if (info)
free(info);
}

View File

@@ -1,26 +0,0 @@
#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_

View File

@@ -24,21 +24,21 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup layer-selector
* @{
*/
#include "layer-selector.h"
#include "layer-selector-dnd.h"
#include "layer-info.h"
#include "../gds-parser/gds-parser.h"
#include "../widgets/layer-element.h"
#include "../mapping-parser.h"
#include <glib.h>
#include <string.h>
#include <stdio.h>
#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 */
GObject parent;
@@ -49,16 +49,73 @@ struct _LayerSelector {
GtkWindow *save_parent_window;
GtkListBox *list_box;
GtkTargetEntry dnd_target;
gpointer dummy[4];
};
G_DEFINE_TYPE(LayerSelector, layer_selector, G_TYPE_OBJECT)
/* Drag and drop code
* Original code from https://blog.gtk.org/2017/06/01/drag-and-drop-in-lists-revisited/
*/
/* Drag and drop code */
static GtkTargetEntry entries[] = {
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
};
static void sel_layer_element_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
{
GtkWidget *row;
GtkAllocation alloc;
cairo_surface_t *surface;
cairo_t *cr;
int x, y;
(void)data;
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
gtk_widget_get_allocation(row, &alloc);
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
cr = cairo_create(surface);
gtk_style_context_add_class (gtk_widget_get_style_context(row), "drag-icon");
gtk_widget_draw (row, cr);
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-icon");
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
cairo_surface_set_device_offset (surface, -x, -y);
gtk_drag_set_icon_surface (context, surface);
cairo_destroy (cr);
cairo_surface_destroy (surface);
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
}
static void sel_layer_element_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
{
GtkWidget *row;
(void)context;
(void)data;
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL);
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-row");
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-hover");
}
static void sel_layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *context,
GtkSelectionData *selection_data,
guint info, guint time, gpointer data)
{
(void)context;
(void)info;
(void)time;
(void)data;
GdkAtom atom;
atom = gdk_atom_intern_static_string("GTK_LIST_BOX_ROW");
gtk_selection_data_set(selection_data, atom,
32, (const guchar *)&widget, sizeof(gpointer));
}
static GtkListBoxRow *layer_selector_get_last_row (GtkListBox *list)
{
@@ -160,10 +217,12 @@ static gboolean layer_selector_drag_motion(GtkWidget *widget, GdkDragContext *co
if (y < hover_row_y + hover_row_height/2) {
row_after = row;
row_before = GTK_WIDGET(layer_selector_get_row_before(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
row_before = GTK_WIDGET(layer_selector_get_row_before(GTK_LIST_BOX(widget),
GTK_LIST_BOX_ROW(row)));
} else {
row_before = row;
row_after = GTK_WIDGET(layer_selector_get_row_after(GTK_LIST_BOX(widget), GTK_LIST_BOX_ROW(row)));
row_after = GTK_WIDGET(layer_selector_get_row_after(GTK_LIST_BOX(widget),
GTK_LIST_BOX_ROW(row)));
}
} else {
row_before = GTK_WIDGET(layer_selector_get_last_row(GTK_LIST_BOX(widget)));
@@ -250,6 +309,11 @@ static void layer_selector_dispose(GObject *self)
g_clear_object(&sel->associated_load_button);
g_clear_object(&sel->associated_save_button);
if (sel->dnd_target.target) {
g_free(sel->dnd_target.target);
sel->dnd_target.target = NULL;
}
/* Chain up to parent's dispose function */
G_OBJECT_CLASS(layer_selector_parent_class)->dispose(self);
}
@@ -270,23 +334,26 @@ static void layer_selector_class_init(LayerSelectorClass *klass)
g_object_unref(provider);
}
static void layer_selector_setup_dnd(GtkListBox *box)
static void layer_selector_setup_dnd(LayerSelector *self)
{
gtk_drag_dest_set(GTK_WIDGET(box), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, entries, 1, GDK_ACTION_MOVE);
g_signal_connect(box, "drag-data-received", G_CALLBACK(layer_selector_drag_data_received), NULL);
g_signal_connect(box, "drag-motion", G_CALLBACK(layer_selector_drag_motion), NULL);
g_signal_connect(box, "drag-leave", G_CALLBACK(layer_selector_drag_leave), NULL);
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);
}
/* Drag and drop end */
static void layer_selector_init(LayerSelector *self)
{
/* Setup drag and drop for associated list box */
self->load_parent_window = NULL;
self->save_parent_window = NULL;
self->associated_load_button = NULL;
self->associated_save_button = NULL;
self->dnd_target.target = g_strdup_printf("LAYER_SELECTOR_DND_%p", self);
self->dnd_target.info = 0;
self->dnd_target.flags = GTK_TARGET_SAME_APP;
}
LayerSelector *layer_selector_new(GtkListBox *list_box)
@@ -298,7 +365,7 @@ LayerSelector *layer_selector_new(GtkListBox *list_box)
selector = LAYER_SELECTOR(g_object_new(TYPE_LAYER_SELECTOR, NULL));
selector->list_box = list_box;
layer_selector_setup_dnd(list_box);
layer_selector_setup_dnd(selector);
g_object_ref(G_OBJECT(list_box));
return selector;
@@ -360,9 +427,10 @@ static void layer_selector_clear_widgets(LayerSelector *self)
}
/**
* @brief Check if specific layer number is present in list box
* @param layer Layer nu,ber
* @return TRUE if present
* @brief Check if a specific layer element with the given layer number is present in the layer selector
* @param self LayerSelector instance
* @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) {
GList *list;
@@ -386,8 +454,29 @@ static gboolean layer_selector_check_if_layer_widget_exists(LayerSelector *self,
}
/**
* @brief Analyze \p cell and append used layers to list box
* @param listbox listbox to add layer
* @brief Setup the necessary drag and drop callbacks of layer elements.
* @param self LayerSelector instance. Used to get the DnD target entry.
* @param element LayerElement instance to set the callbacks
*/
static void sel_layer_element_setup_dnd_callbacks(LayerSelector *self, LayerElement *element)
{
struct layer_element_dnd_data dnd_data;
if (!self || !element)
return;
dnd_data.entries = &self->dnd_target;
dnd_data.entry_count = 1;
dnd_data.drag_end = sel_layer_element_drag_end;
dnd_data.drag_begin = sel_layer_element_drag_begin;
dnd_data.drag_data_get = sel_layer_element_drag_data_get;
layer_element_set_dnd_callbacks(element, &dnd_data);
}
/**
* @brief Analyze \p cell layers and append detected layers to layer selector \p self
* @param self LayerSelector instance
* @param cell Cell to analyze
*/
static void layer_selector_analyze_cell_layers(LayerSelector *self, struct gds_cell *cell)
@@ -402,6 +491,7 @@ static void layer_selector_analyze_cell_layers(LayerSelector *self, struct gds_c
layer = (int)gfx->layer;
if (layer_selector_check_if_layer_widget_exists(self, layer) == FALSE) {
le = layer_element_new();
sel_layer_element_setup_dnd_callbacks(self, LAYER_ELEMENT(le));
layer_element_set_layer(LAYER_ELEMENT(le), layer);
gtk_list_box_insert(self->list_box, le, -1);
gtk_widget_show(le);
@@ -484,8 +574,15 @@ static LayerElement *layer_selector_find_layer_element_in_list(GList *el_list, i
}
/**
* @brief Load file and apply layer definitions to listbox
* @param file_name CSV Layer Mapping File
* @brief Load the layer mapping from a CSV formatted file
*
* This function imports the layer specification from a file (see @ref lmf-spec).
* The layer ordering defined in the file is kept. All layers present in the
* current loaded library, which are not present in the layer mapping file
* are appended at the end of the layer selector list.
*
* @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)
{
@@ -519,7 +616,7 @@ static void layer_selector_load_layer_mapping_from_file(LayerSelector *self, gch
gtk_container_remove(GTK_CONTAINER(self->list_box), GTK_WIDGET(le));
}
while((result = load_csv_line(dstream, &export, &name, &layer, &color)) >= 0) {
while((result = mapping_parser_load_line(dstream, &export, &name, &layer, &color)) >= 0) {
/* skip broken line */
if (result == 1)
continue;
@@ -585,9 +682,9 @@ static void layer_selector_load_mapping_clicked(GtkWidget *button, gpointer user
/**
* @brief Save layer mapping of whole list box into file
* @param file_name layer mapping file
* @param list_box listbox
* @brief Save layer mapping of selector \p self to a file
* @param self LayerSelector instance
* @param file_name File name to save to
*/
static void layer_selector_save_layer_mapping_data(LayerSelector *self, const gchar *file_name)
{
@@ -605,7 +702,7 @@ static void layer_selector_save_layer_mapping_data(LayerSelector *self, const gc
for (temp = le_list; temp != NULL; temp = temp->next) {
/* To be sure it is a valid string */
workbuff[0] = 0;
create_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
mapping_parser_gen_csv_line(LAYER_ELEMENT(temp->data), workbuff, sizeof(workbuff));
fwrite(workbuff, sizeof(char), strlen(workbuff), file);
}
@@ -678,7 +775,7 @@ void layer_selector_force_sort(LayerSelector *selector, enum layer_selector_sort
if (!box)
return;
/* Set dorting function, sort, and disable sorting function */
/* Set sorting function, sort, and disable sorting function */
gtk_list_box_set_sort_func(box, layer_selector_sort_func, (gpointer)&sort_function, NULL);
gtk_list_box_invalidate_sort(box);
gtk_list_box_set_sort_func(box, NULL, NULL, NULL);

View File

@@ -25,13 +25,13 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup Mapping-Parser
* @{
*/
#include "mapping-parser.h"
#include <gds-render/layer/mapping-parser.h>
int load_csv_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
int mapping_parser_load_line(GDataInputStream *stream, gboolean *export, char **name, int *layer, GdkRGBA *color)
{
int ret;
gsize len;
@@ -94,7 +94,7 @@ ret_direct:
}
void create_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
void mapping_parser_gen_csv_line(LayerElement *layer_element, char *line_buffer, size_t max_len)
{
int i;
GString *string;

View File

@@ -1,491 +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 main-window.c
* @brief Handling of GUI
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/** @addtogroup MainApplication
* @{
*/
#include "main-window.h"
#include <stdio.h>
#include "gds-parser/gds-parser.h"
#include <gtk/gtk.h>
#include "layer/layer-selector.h"
#include "layer/layer-selector-dnd.h"
#include "tree-renderer/tree-store.h"
#include "latex-output/latex-output.h"
#include "widgets/conv-settings-dialog.h"
#include "cairo-output/cairo-output.h"
#include "trigonometric/cell-trigonometrics.h"
#include "version/version.h"
#include "tree-renderer/lib-cell-renderer.h"
#include "gds-parser/gds-tree-checker.h"
/**
* @brief User data supplied to callback function of the open button
*/
struct open_button_data {
GtkWindow *main_window;
GList **list_ptr;
GtkTreeStore *cell_store;
GtkSearchEntry *search_entry;
LayerSelector *layer_selector;
};
/**
* @brief User data supplied to callback function of the convert button
*/
struct convert_button_data {
GtkTreeView *tree_view;
GtkWindow *main_window;
LayerSelector *layer_selector;
};
/**
* @brief Window close event of main window
*
* Closes the main window. This leads to the termination of the whole application
* @param window main window
* @param user not used
* @return TRUE. This indicates that the event has been fully handled
*/
static gboolean on_window_close(gpointer window, GdkEvent *event, gpointer user)
{
/* Destroy all objects helb by this module, that are not part of the GUI itself */
g_object_unref(LAYER_SELECTOR(user));
/* Close Window. Leads to termination of the program */
gtk_widget_destroy(GTK_WIDGET(window));
return TRUE;
}
/**
* @brief generate string from gds_time_field
* @param date Date to convert
* @return String with date
*/
static GString *generate_string_from_date(struct gds_time_field *date)
{
GString *str;
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;
}
/**
* @brief Callback function of Load GDS button
* @param button
* @param user Necessary Data
*/
static void on_load_gds(gpointer button, gpointer user)
{
GList *cell;
GtkTreeIter libiter;
GtkTreeIter celliter;
GList *lib;
struct gds_library *gds_lib;
struct gds_cell *gds_c;
struct open_button_data *ptr = (struct open_button_data *)user;
GtkTreeStore *store = ptr->cell_store;
GtkWidget *open_dialog;
GtkFileChooser *file_chooser;
GtkFileFilter *filter;
GtkStyleContext *button_style;
gint dialog_result;
int gds_result;
char *filename;
GString *mod_date;
GString *acc_date;
unsigned int cell_error_level;
open_dialog = gtk_file_chooser_dialog_new("Open GDSII File", ptr->main_window,
GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL,
"Open GDSII", GTK_RESPONSE_ACCEPT,
NULL);
file_chooser = GTK_FILE_CHOOSER(open_dialog);
/* Add GDS II Filter */
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.gds");
gtk_file_filter_set_name(filter, "GDSII-Files");
gtk_file_chooser_add_filter(file_chooser, filter);
dialog_result = gtk_dialog_run(GTK_DIALOG(open_dialog));
if (dialog_result == GTK_RESPONSE_ACCEPT) {
/* Get File name */
filename = gtk_file_chooser_get_filename(file_chooser);
gtk_tree_store_clear(store);
clear_lib_list(ptr->list_ptr);
/* Parse new GDSII file */
gds_result = parse_gds_from_file(filename, ptr->list_ptr);
/* Delete file name afterwards */
g_free(filename);
if (gds_result)
goto end_destroy;
/* remove suggested action from Open button */
button_style = gtk_widget_get_style_context(GTK_WIDGET(button));
gtk_style_context_remove_class(button_style, "suggested-action");
for (lib = *(ptr->list_ptr); lib != NULL; lib = lib->next) {
gds_lib = (struct gds_library *)lib->data;
/* Create top level iter */
gtk_tree_store_append(store, &libiter, NULL);
/* Convert dates to String */
mod_date = generate_string_from_date(&gds_lib->mod_time);
acc_date = generate_string_from_date(&gds_lib->access_time);
gtk_tree_store_set(store, &libiter,
CELL_SEL_LIBRARY, gds_lib,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
-1);
/* 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(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;
if (gds_c->checks.unresolved_child_count)
cell_error_level |= LIB_CELL_RENDERER_ERROR_WARN;
/* Check if it is completely b0rken */
if (gds_c->checks.affected_by_reference_loop)
cell_error_level |= LIB_CELL_RENDERER_ERROR_ERR;
/* Add cell to tree store model */
gtk_tree_store_set(store, &celliter,
CELL_SEL_CELL, gds_c,
CELL_SEL_MODDATE, mod_date->str,
CELL_SEL_ACCESSDATE, acc_date->str,
CELL_SEL_CELL_ERROR_STATE, cell_error_level,
-1);
/* Delete GStrings including string data. */
/* Cell store copies String type data items */
g_string_free(mod_date, TRUE);
g_string_free(acc_date, TRUE);
}
}
/* Create Layers in Layer Box */
layer_selector_generate_layer_widgets(ptr->layer_selector, *(ptr->list_ptr));
}
end_destroy:
/* Destroy dialog and filter */
gtk_widget_destroy(open_dialog);
}
/**
* @brief Convert button callback
* @param button
* @param user
*/
static void on_convert_clicked(gpointer button, gpointer user)
{
(void)button;
static struct render_settings sett = {
.scale = 1000.0,
.renderer = RENDERER_LATEX_TIKZ,
};
struct convert_button_data *data = (struct convert_button_data *)user;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
GList *layer_list;
struct gds_cell *cell_to_render;
FILE *output_file;
GtkWidget *dialog;
RendererSettingsDialog *settings;
GtkFileFilter *filter;
gint res;
char *file_name;
union bounding_box cell_box;
unsigned int height, width;
if (!data)
return;
/* Get selected cell */
selection = gtk_tree_view_get_selection(data->tree_view);
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
return;
gtk_tree_model_get(model, &iter, CELL_SEL_CELL, &cell_to_render, -1);
if (!cell_to_render)
return;
/* Get layers that are rendered */
layer_list = layer_selector_export_rendered_layer_info(data->layer_selector);
/* Calculate cell size in DB units */
bounding_box_prepare_empty(&cell_box);
calculate_cell_bounding_box(&cell_box, cell_to_render);
/* Calculate size in database units
* Note that the results are bound to be positive,
* so casting them to unsigned int is absolutely valid
*/
height = (unsigned int)(cell_box.vectors.upper_right.y - cell_box.vectors.lower_left.y);
width = (unsigned int)(cell_box.vectors.upper_right.x - cell_box.vectors.lower_left.x);
/* Show settings dialog */
settings = renderer_settings_dialog_new(GTK_WINDOW(data->main_window));
renderer_settings_dialog_set_settings(settings, &sett);
renderer_settings_dialog_set_database_unit_scale(settings, cell_to_render->parent_library->unit_in_meters);
renderer_settings_dialog_set_cell_height(settings, height);
renderer_settings_dialog_set_cell_width(settings, width);
res = gtk_dialog_run(GTK_DIALOG(settings));
if (res == GTK_RESPONSE_OK) {
renderer_settings_dialog_get_settings(settings, &sett);
gtk_widget_destroy(GTK_WIDGET(settings));
} else {
gtk_widget_destroy(GTK_WIDGET(settings));
goto ret_layer_destroy;
}
/* save file dialog */
dialog = gtk_file_chooser_dialog_new((sett.renderer == RENDERER_LATEX_TIKZ
? "Save LaTeX File" : "Save PDF"),
GTK_WINDOW(data->main_window), GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
/* Set file filter according to settings */
filter = gtk_file_filter_new();
switch (sett.renderer) {
case RENDERER_LATEX_TIKZ:
gtk_file_filter_add_pattern(filter, "*.tex");
gtk_file_filter_set_name(filter, "LaTeX-Files");
break;
case RENDERER_CAIROGRAPHICS_PDF:
gtk_file_filter_add_pattern(filter, "*.pdf");
gtk_file_filter_set_name(filter, "PDF-Files");
break;
case RENDERER_CAIROGRAPHICS_SVG:
gtk_file_filter_add_pattern(filter, "*.svg");
gtk_file_filter_set_name(filter, "SVG-Files");
break;
}
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
gtk_widget_destroy(dialog);
switch (sett.renderer) {
case RENDERER_LATEX_TIKZ:
output_file = fopen(file_name, "w");
latex_render_cell_to_code(cell_to_render, layer_list, output_file, sett.scale,
sett.tex_pdf_layers, sett.tex_standalone);
fclose(output_file);
break;
case RENDERER_CAIROGRAPHICS_SVG:
case RENDERER_CAIROGRAPHICS_PDF:
cairo_render_cell_to_vector_file(cell_to_render, layer_list,
(sett.renderer == RENDERER_CAIROGRAPHICS_PDF
? file_name
: NULL),
(sett.renderer == RENDERER_CAIROGRAPHICS_SVG
? file_name
: NULL),
sett.scale);
break;
}
g_free(file_name);
} else {
gtk_widget_destroy(dialog);
}
ret_layer_destroy:
g_list_free_full(layer_list, (GDestroyNotify)layer_info_delete_struct);
}
/**
* @brief cell_tree_view_activated
* @param tree_view Not used
* @param user convert button data
*/
static void cell_tree_view_activated(gpointer tree_view, GtkTreePath *path,
GtkTreeViewColumn *column, gpointer user)
{
(void)tree_view;
(void)path;
(void)column;
on_convert_clicked(NULL, user);
}
/**
* @brief Callback for cell-selection change event
*
* This function activates/deactivates the convert button depending on whether
* a cell is selected for conversion or not
* @param sel
* @param convert_button
*/
static void cell_selection_changed(GtkTreeSelection *sel, GtkWidget *convert_button)
{
GtkTreeModel *model = NULL;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
/* Node selected. Show button */
gtk_widget_set_sensitive(convert_button, TRUE);
} else {
gtk_widget_set_sensitive(convert_button, FALSE);
}
}
static void sort_up_callback(GtkWidget *widget, gpointer user)
{
(void)widget;
LayerSelector *sel;
sel = LAYER_SELECTOR(user);
if (!sel)
return;
layer_selector_force_sort(sel, LAYER_SELECTOR_SORT_UP);
}
static void sort_down_callback(GtkWidget *widget, gpointer user)
{
(void)widget;
LayerSelector *sel;
sel = LAYER_SELECTOR(user);
if (!sel)
return;
layer_selector_force_sort(sel, LAYER_SELECTOR_SORT_DOWN);
}
GtkWindow *create_main_window()
{
GtkBuilder *main_builder;
GtkTreeView *cell_tree;
GtkWidget *listbox;
GtkWidget *conv_button;
GtkWidget *search_entry;
GtkHeaderBar *header_bar;
LayerSelector *layer_selector;
static GList *gds_libs;
static struct open_button_data open_data;
static struct convert_button_data conv_data;
struct tree_stores *cell_selector_stores;
GtkWidget *sort_up_button;
GtkWidget *sort_down_button;
main_builder = gtk_builder_new_from_resource("/main.glade");
gtk_builder_connect_signals(main_builder, NULL);
cell_tree = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree"));
search_entry = GTK_WIDGET(gtk_builder_get_object(main_builder, "cell-search"));
open_data.search_entry = GTK_SEARCH_ENTRY(search_entry);
cell_selector_stores = setup_cell_selector(cell_tree, GTK_ENTRY(search_entry));
open_data.cell_store = cell_selector_stores->base_store;
open_data.list_ptr = &gds_libs;
open_data.main_window = GTK_WINDOW(gtk_builder_get_object(main_builder, "main-window"));
g_signal_connect(GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-gds")),
"clicked", G_CALLBACK(on_load_gds), (gpointer)&open_data);
/* Connect Convert button */
conv_data.tree_view = cell_tree;
conv_data.main_window = open_data.main_window;
conv_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "convert-button"));
g_signal_connect(conv_button, "clicked", G_CALLBACK(on_convert_clicked), &conv_data);
listbox = GTK_WIDGET(gtk_builder_get_object(main_builder, "layer-list"));
/* Create layer selector */
layer_selector = layer_selector_new(GTK_LIST_BOX(listbox));
conv_data.layer_selector = layer_selector;
open_data.layer_selector = layer_selector;
/* Callback for selection change of cell selector */
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(cell_tree)), "changed",
G_CALLBACK(cell_selection_changed), conv_button);
g_signal_connect(cell_tree, "row-activated", G_CALLBACK(cell_tree_view_activated), &conv_data);
/* Set version in main window subtitle */
header_bar = GTK_HEADER_BAR(gtk_builder_get_object(main_builder, "header-bar"));
gtk_header_bar_set_subtitle(header_bar, _app_version_string);
/* Get layer sorting buttons and set callbacks */
sort_up_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-up-sort"));
sort_down_button = GTK_WIDGET(gtk_builder_get_object(main_builder, "button-down-sort"));
g_signal_connect(sort_up_button, "clicked", G_CALLBACK(sort_up_callback), layer_selector);
g_signal_connect(sort_down_button, "clicked", G_CALLBACK(sort_down_callback), layer_selector);
/* Set buttons for loading and saving */
layer_selector_set_load_mapping_button(layer_selector,
GTK_WIDGET(gtk_builder_get_object(main_builder, "button-load-mapping")),
conv_data.main_window);
layer_selector_set_save_mapping_button(layer_selector, GTK_WIDGET(gtk_builder_get_object(main_builder, "button-save-mapping")),
conv_data.main_window);
/* Connect delete-event */
g_signal_connect(GTK_WIDGET(open_data.main_window), "delete-event",
G_CALLBACK(on_window_close), layer_selector);
g_object_unref(main_builder);
return conv_data.main_window;
}
/** @} */

148
main.c
View File

@@ -17,76 +17,185 @@
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file main.c
* @brief main.c
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
#include <stdio.h>
#include <gtk/gtk.h>
#include <glib.h>
#include "main-window.h"
#include "command-line.h"
#include "external-renderer.h"
#include "version/version.h"
#include <gds-render/gds-render-gui.h>
#include <gds-render/command-line.h>
#include <gds-render/external-renderer.h>
#include <gds-render/version.h>
/**
* @brief Structure containing The GtkApplication and a list containing the GdsRenderGui objects.
*/
struct application_data {
GtkApplication *app;
GtkWindow *main_window;
GList *gui_list;
};
/**
* @brief Callback for the menu entry 'Quit'
*
* Destroys all GUIs contained in the application_data structure
* provided by \p user_data.
*
* The complete suspension of all main windows leads to the termination of the
* GApplication.
*
* @param action unused
* @param parameter unused
* @param user_data application_data structure
*/
static void app_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
const struct application_data * const appdata = (const struct application_data *)user_data;
struct application_data * const appdata = (struct application_data *)user_data;
(void)action;
(void)parameter;
GList *list_iter;
GdsRenderGui *gui;
gtk_widget_destroy(GTK_WIDGET(appdata->main_window));
/* Dispose all GUIs */
for (list_iter = appdata->gui_list; list_iter != NULL; list_iter = g_list_next(list_iter)) {
gui = RENDERER_GUI(list_iter->data);
g_object_unref(gui);
}
g_list_free(appdata->gui_list);
appdata->gui_list = NULL;
}
/**
* @brief Callback for the 'About' menu entry
*
* This function shows the about dialog.
*
* @param action GSimpleAction, unused
* @param parameter Unused.
* @param user_data Unused
*/
static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
GtkBuilder *builder;
GtkDialog *dialog;
const struct application_data * const appdata = (const struct application_data *)user_data;
GdkPixbuf *logo_buf;
GError *error = NULL;
(void)user_data;
(void)action;
(void)parameter;
builder = gtk_builder_new_from_resource("/about.glade");
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog"));
gtk_window_set_transient_for(GTK_WINDOW(dialog), appdata->main_window);
gtk_window_set_transient_for(GTK_WINDOW(dialog), NULL);
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), _app_version_string);
/* Load icon from resource */
logo_buf = gdk_pixbuf_new_from_resource_at_scale("/logo.svg", 100, 100, TRUE, &error);
if (logo_buf) {
/* Set logo */
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), logo_buf);
/* 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);
g_error_free(error);
}
gtk_dialog_run(dialog);
gtk_widget_destroy(GTK_WIDGET(dialog));
g_object_unref(builder);
}
/**
* @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}}
};
/**
* @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.
*
* @param gui The GUI instance the closed main window belongs to
* @param user_data List of GUIs
*/
static void gui_window_closed_callback(GdsRenderGui *gui, gpointer user_data)
{
GList **gui_list = (GList **)user_data;
/* Dispose of Gui element */
*gui_list = g_list_remove(*gui_list, gui);
g_object_unref(gui);
}
/**
* @brief Activation of the GUI
* @param app The GApplication reference
* @param user_data Used to store the individual GUI instances.
*/
static void gapp_activate(GApplication *app, gpointer user_data)
{
GtkWindow *main_window;
GdsRenderGui *gui;
struct application_data * const appdata = (struct application_data *)user_data;
main_window = create_main_window();
appdata->main_window = main_window;
gui = gds_render_gui_new();
appdata->gui_list = g_list_append(appdata->gui_list, gui);
g_signal_connect(gui, "window-closed", G_CALLBACK(gui_window_closed_callback), &appdata->gui_list);
main_window = gds_render_gui_get_main_window(gui);
gtk_application_add_window(GTK_APPLICATION(app), main_window);
gtk_widget_show(GTK_WIDGET(main_window));
}
/**
* @brief Start the graphical interface.
*
* This function starts the GUI. If there's already a
* running instance of this program, a second window will be
* created in that instance and the second one is terminated.
*
* @param argc
* @param argv
* @return
*/
static int start_gui(int argc, char **argv)
{
GtkApplication *gapp;
int app_status;
static struct application_data appdata;
static struct application_data appdata = {
.gui_list = NULL
};
GMenu *menu;
GMenu *m_quit;
GMenu *m_about;
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_NON_UNIQUE);
gapp = gtk_application_new("de.shimatta.gds-render", G_APPLICATION_FLAGS_NONE);
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");
return 0;
}
menu = g_menu_new();
m_quit = g_menu_new();
m_about = g_menu_new();
@@ -105,15 +214,26 @@ static int start_gui(int argc, char **argv)
app_status = g_application_run(G_APPLICATION(gapp), argc, argv);
g_object_unref(gapp);
g_list_free(appdata.gui_list);
return app_status;
}
static void print_version()
/**
* @brief Print the application version string to stdout
*/
static void print_version(void)
{
printf("This is gds-render, version: %s\n\nFor a list of supported commands execute with --help option.\n",
_app_version_string);
}
/**
* @brief The "entry point" of the application
* @param argc Number of command line parameters
* @param argv Command line parameters
* @return Execution status of the application
*/
int main(int argc, char **argv)
{
int i;

View File

@@ -17,8 +17,19 @@
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lib-cell-renderer.h"
#include "../gds-parser/gds-types.h"
/**
* @file lib-cell-renderer.c
* @brief LibCellRenderer GObject Class
* @author Mario Hüttel <mario.huettel@gmx.net>
*/
/**
* @addtogroup LibCellRenderer
* @{
*/
#include <gds-render/tree-renderer/lib-cell-renderer.h>
#include <gds-render/gds-utils/gds-types.h>
G_DEFINE_TYPE(LibCellRenderer, lib_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
@@ -107,11 +118,12 @@ static void lib_cell_renderer_get_property(GObject *object,
}
}
static GParamSpec *properties [PROP_COUNT];
static GParamSpec *properties[PROP_COUNT];
void lib_cell_renderer_class_init(LibCellRendererClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->constructed = lib_cell_renderer_constructed;
oclass->set_property = lib_cell_renderer_set_property;
oclass->get_property = lib_cell_renderer_get_property;
@@ -132,3 +144,5 @@ GtkCellRenderer *lib_cell_renderer_new()
{
return GTK_CELL_RENDERER(g_object_new(TYPE_LIB_CELL_RENDERER, NULL));
}
/** @} */

View File

@@ -24,13 +24,13 @@
*/
/**
* @addtogroup MainApplication
* @addtogroup GUI
* @{
*/
#include "tree-store.h"
#include "lib-cell-renderer.h"
#include "../gds-parser/gds-types.h"
#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
@@ -51,6 +51,9 @@ static gboolean tree_sel_func(GtkTreeSelection *selection,
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);
@@ -112,6 +115,8 @@ exit_filter:
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);
}

View File

@@ -1 +1 @@
git describe --tags
git describe --tags --dirty

View File

@@ -17,13 +17,15 @@
* along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup MainApplication
* @defgroup version Version Number
* See @ref git-version-num
* @addtogroup version
* @{
*/
#ifdef PROJECT_GIT_VERSION
#define xstr(a) str(a)
#define str(a) #a
const char *_app_version_string = xstr(PROJECT_GIT_VERSION);

View File

@@ -24,11 +24,12 @@
*/
/**
* @addtogroup Widgets
* @addtogroup RendererSettingsDialog
* @ingroup Widgets
* @{
*/
#include "conv-settings-dialog.h"
#include <gds-render/widgets/conv-settings-dialog.h>
struct _RendererSettingsDialog {
GtkDialog parent;
@@ -53,10 +54,60 @@ struct _RendererSettingsDialog {
G_DEFINE_TYPE(RendererSettingsDialog, renderer_settings_dialog, GTK_TYPE_DIALOG)
enum {
PROP_CELL_NAME = 1,
PROP_COUNT
};
static GParamSpec *properties[PROP_COUNT];
static void renderer_settings_dialog_set_property(GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
const gchar *title = NULL;
switch (property_id) {
case PROP_CELL_NAME:
title = g_value_get_string(value);
if (title)
gtk_window_set_title(GTK_WINDOW(object), title);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void renderer_settings_dialog_get_property(GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
const gchar *title;
switch (property_id) {
case PROP_CELL_NAME:
title = gtk_window_get_title(GTK_WINDOW(object));
g_value_set_string(value, title);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void renderer_settings_dialog_class_init(RendererSettingsDialogClass *klass)
{
/* No special code needed. Child cells are destroyed automatically due to reference counter */
return;
GObjectClass *oclass = G_OBJECT_CLASS(klass);
/* Override virtual functions */
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",
"",
G_PARAM_READWRITE);
g_object_class_install_properties(oclass, PROP_COUNT, properties);
}
static void show_tex_options(RendererSettingsDialog *self)
@@ -140,6 +191,11 @@ static double convert_number_to_engineering(double input, const char **out_prefi
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;
/* Start with the 2nd smallest prefix */
for (idx = 1; idx < prefix_count; idx++) {
if (input < scale[idx]) {
/* This prefix is bigger than the number. Take the previous one */
@@ -212,7 +268,7 @@ static void renderer_settings_dialog_init(RendererSettingsDialog *self)
GtkWidget *box;
GtkDialog *dialog;
dialog = &(self->parent);
dialog = &self->parent;
builder = gtk_builder_new_from_resource("/dialog.glade");
box = GTK_WIDGET(gtk_builder_get_object(builder, "dialog-box"));
@@ -260,10 +316,7 @@ RendererSettingsDialog *renderer_settings_dialog_new(GtkWindow *parent)
void renderer_settings_dialog_get_settings(RendererSettingsDialog *dialog, struct render_settings *settings)
{
/*GList *radio_buttons;
*GList *temp_button_list;
*GtkToggleButton *temp_button = NULL;
*/
if (!settings || !dialog)
return;
settings->scale = gtk_range_get_value(GTK_RANGE(dialog->scale));

View File

@@ -31,11 +31,12 @@
*/
/**
* @addtogroup Widgets
* @addtogroup LayerElement
* @ingroup Widgets
* @{
*/
#include "layer-element.h"
#include <gds-render/widgets/layer-element.h>
G_DEFINE_TYPE(LayerElement, layer_element, GTK_TYPE_LIST_BOX_ROW)
@@ -57,65 +58,6 @@ static void layer_element_class_init(LayerElementClass *klass)
oclass->constructed = layer_element_constructed;
}
static GtkTargetEntry entries[] = {
{ "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
};
static void layer_element_drag_begin(GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
GtkWidget *row;
GtkAllocation alloc;
cairo_surface_t *surface;
cairo_t *cr;
int x, y;
(void)data;
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
gtk_widget_get_allocation(row, &alloc);
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
cr = cairo_create(surface);
gtk_style_context_add_class (gtk_widget_get_style_context(row), "drag-icon");
gtk_widget_draw (row, cr);
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-icon");
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
cairo_surface_set_device_offset (surface, -x, -y);
gtk_drag_set_icon_surface (context, surface);
cairo_destroy (cr);
cairo_surface_destroy (surface);
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", row);
gtk_style_context_add_class(gtk_widget_get_style_context(row), "drag-row");
}
static void layer_element_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
{
GtkWidget *row;
(void)context;
(void)data;
row = gtk_widget_get_ancestor(widget, GTK_TYPE_LIST_BOX_ROW);
g_object_set_data(G_OBJECT(gtk_widget_get_parent(row)), "drag-row", NULL);
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-row");
gtk_style_context_remove_class(gtk_widget_get_style_context(row), "drag-hover");
}
static void layer_element_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data,
guint info, guint time, gpointer data)
{
(void)context;
(void)info;
(void)time;
(void)data;
gtk_selection_data_set(selection_data, gdk_atom_intern_static_string("GTK_LIST_BOX_ROW"),
32, (const guchar *)&widget, sizeof(gpointer));
}
static void layer_element_init(LayerElement *self)
{
GtkBuilder *builder;
@@ -131,13 +73,6 @@ static void layer_element_init(LayerElement *self)
self->priv.name = GTK_ENTRY(gtk_builder_get_object(builder, "entry"));
self->priv.event_handle = GTK_EVENT_BOX(gtk_builder_get_object(builder, "event-box"));
/* Setup drag and drop */
gtk_style_context_add_class (gtk_widget_get_style_context(GTK_WIDGET(self)), "row");
gtk_drag_source_set(GTK_WIDGET(self->priv.event_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
g_signal_connect(self->priv.event_handle, "drag-begin", G_CALLBACK(layer_element_drag_begin), NULL);
g_signal_connect(self->priv.event_handle, "drag-data-get", G_CALLBACK(layer_element_drag_data_get), NULL);
g_signal_connect(self->priv.event_handle, "drag-end", G_CALLBACK(layer_element_drag_end), NULL);
g_object_unref(builder);
}
@@ -186,12 +121,30 @@ void layer_element_get_color(LayerElement *elem, GdkRGBA *rgba)
{
if (!rgba)
return;
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}
void layer_element_set_color(LayerElement *elem, GdkRGBA *rgba)
{
if (!elem || !rgba)
return;
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(elem->priv.color), rgba);
}
void layer_element_set_dnd_callbacks(LayerElement *elem, struct layer_element_dnd_data *data)
{
if (!elem || !data)
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);
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);
}
/** @} */