+++ /dev/null
-##
-## Makefile
-##
-## Made by Johnny Q. Hacker
-## Login <solarionjohnathan>
-##
-## Started on Thu Jul 17 10:56:05 2008 Johnny Q. Hacker
-## Last update Thu Jul 17 10:56:05 2008 Johnny Q. Hacker
-##
-##############################
-# Complete this to make it ! #
-##############################
-NAME = scdataviz # Name of executable file
-SRC = $(wildcard *.c) # List of *.c
-INCL = # List of *.h
-################
-# Optional add #
-################
-IPATH = -I. # path of include file
-OBJOPT = -ggdb -g3 -pg -Wall -Wstrict-prototypes -DDEBUG -std=c99 -D_GNU_SOURCE # option for obj
-EXEOPT = -ggdb -g3 -pg -Wall -Wstrict-prototypes -std=c99 -D_GNU_SOURCE # option for exe (-lefence ...)
-LPATH = -L. # path for librairies ...
-
-#####################
-# Macro Definitions #
-#####################
-CC = gcc
-MAKE = make
-SHELL = /bin/sh
-OBJS = $(SRC:.c=.o)
-RM = /bin/rm -f
-COMP = gzip -9v
-UNCOMP = gzip -df
-STRIP = strip
-
-CFLAGS = $(OBJOPT) $(IPATH) `pkg-config --cflags gtk+-2.0`
-LDFLAGS = $(EXEOPT) $(LPATH) `pkg-config --libs gtk+-2.0`
-
-.SUFFIXES: .h.Z .c.Z .h.gz .c.gz .c.z .h.z
-
-##############################
-# Basic Compile Instructions #
-##############################
-
-all: $(NAME)
-$(NAME): $(OBJS) $(SRC) $(INCL)
- $(CC) $(OBJS) $(LDFLAGS) -o $(NAME)
-# $(STRIP) ./$(NAME) # if you debug ,don't strip ...
-
-depend:
- gcc $(IPATH) -MM $(SRC)
-clean:
- -$(RM) $(NAME) $(OBJS)
-fclean:
- -$(RM) $(NAME)
-comp: clean
- $(COMP) $(INCL) $(SRC)
-ucomp:
- $(UNCOMP) $(SRC) $(INCL)
-
-.c.Z.c .h.Z.h .c.gz.c .h.gz.h .c.z.c .h.z.h :
- -$(UNCOMP) $<
-
-.c.o:
- $(CC) $(CFLAGS) -c $<
-################
-# Dependencies #
-################
--- /dev/null
+## Makefile.am -- Process this file with automake to produce Makefile.in
+AUTOMAKE_OPTIONS = gnu subdir-objects
+AM_DEFAULT_SOURCE_EXT = .c++
+ACLOCAL_AMFLAGS=-I m4
+AM_YFLAGS=-d
+AM_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS)
+AM_CPPFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS)
+
+bin_PROGRAMS = kdotp/kdotp kdotp/makestruct
+lib_LTLIBRARIES = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la
+
+#Tests which should succeed
+TESTS=tests/tests
+
+check_PROGRAMS = tests/tests
+tests_tests_SOURCES =
+LIBS += -lm
+#Tests which should fail.
+XFAIL_TESTS=
+
+CLEANFILES = program_version.c
+
+program_version.c:
+ echo -n 'char *version_info = "' > program_version.c
+ bzr version-info | perl -ne 'chomp; print; print "\\n";' >> program_version.c
+ echo '";' >> program_version.c
+
+include_HEADERS=
+include libkdotp.am
+include libmodelxx.am
+
+kdotp_kdotp_SOURCES = kdotp/kdotp.c++
+kdotp_kdotp_LDADD = libkdotp/libkdotp-0.1.la
+LIBS += $(GLIB_LIBS) $(GIO_LIBS)
+
+kdotp_makestruct_SOURCES = kdotp/makestruct.c++ kdotp/structspec_parser.y++ kdotp/structspec_lexer.l++
+kdotp_makestruct_LDADD = libkdotp/libkdotp-0.1.la libmodelxx/libmodelxx-0.1.la
+LIBS += $(GLIB_LIBS) $(GIO_LIBS)
--- /dev/null
+AC_PREREQ(2.61)
+AC_INIT([gimme-alpha], [0.1], [gimme-alpha@pingenot.org])
+AM_INIT_AUTOMAKE([gnu -Wno-portability])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+AM_PROG_LEX
+AC_PROG_YACC
+
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.6, have_glib=true, have_glib=false)
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.18, have_gio=true, have_gio=false)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
+PKG_CHECK_MODULES(FFTW3, fftw3 >= 3.1.2, have_fftw3=true, have_fftw3=false)
+AC_SUBST(FFTW3_CFLAGS)
+AC_SUBST(FFTW3_LIBS)
+
+dnl Check for GNU Scientific Lib, link to it if found.
+AC_CHECK_LIB([m],[cos])
+AC_CHECK_LIB([gslcblas],[cblas_dgemm])
+AC_CHECK_LIB([gsl],[gsl_blas_dgemm])
+
+dnl PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 3.1, have_gtk=true, have_gtk=false)
+dnl AC_SUBST(GTK_CFLAGS)
+dnl AC_SUBST(GTK_LIBS)
+
+AC_ARG_ENABLE([debug],
+[ --enable-debug Turn on debugging],
+[case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+esac],[debug=false])
+AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
+
+COMMMON_CFLAGS="-pipe -Wall -Werror -std=gnu99 -pedantic -Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-unused-value -Wno-unused-function -march=native -mfpmath=sse -msse -mmmx -msse2 -msse3 -mssse3 -ftracer -fbranch-target-load-optimize"
+if test "x$debug" = "xtrue"; then
+ CFLAGS="$COMMMON_CFLAGS -O0 -g3"
+else
+ CFLAGS="$COMMMON_CFLAGS -O3 -frename-registers "
+fi
+dnl CPPFLAGS=
+
+AC_ARG_ENABLE([mudflap],
+[ --enable-mudflap Turn on mudflap, which debugs pointer use (verbosely)],
+[case "${enableval}" in
+ yes) mudflap=true ;;
+ no) mudflap=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-mudflap]) ;;
+esac],[mudflap=false])
+AM_CONDITIONAL([MUDFLAP], [test x$mudflap = xtrue])
+if test "x$mudflap" = "xtrue"; then
+ CFLAGS="$CFLAGS -fmudflap -lmudflap"
+fi
+
+AC_ARG_ENABLE([profiling],
+[ --enable-profiling Turn on profiling],
+[case "${enableval}" in
+ yes) profiling=true ;;
+ no) profiling=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-profiling]) ;;
+esac],[profiling=false])
+AM_CONDITIONAL([PROFILING], [test x$profiling = xtrue])
+if test "x$profiling" = "xtrue"; then
+ CFLAGS="$CFLAGS -pg -fprofile-generate"
+fi
+
+AC_ARG_ENABLE([openmpi],
+[ --enable-openmpi Turn on OpenMPI support],
+[case "${enableval}" in
+ yes) openmpi=true ;;
+ no) openmpi=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-openmpi]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([OPENMPI], [test x$openmpi = xtrue])
+if test "x$openmpi" = "xtrue"; then
+ CFLAGS="$CFLAGS -DOPENMPI"
+fi
+
+AC_ARG_ENABLE([acml],
+[ --enable-acml Turn on AMD Core Math Library support],
+[case "${enableval}" in
+ yes) acml=true ;;
+ no) acml=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-acml]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([ACML], [test x$acml = xtrue])
+if test "x$acml" = "xtrue"; then
+ CFLAGS="$CFLAGS -DACML"
+fi
+
+AC_ARG_ENABLE([mkl],
+[ --enable-mkl Turn on Intel's Math Kernel Library support],
+[case "${enableval}" in
+ yes) mkl=true ;;
+ no) mkl=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-mkl]) ;;
+esac],[mkl=false])
+AM_CONDITIONAL([MKL], [test x$mkl = xtrue])
+if test "x$mkl" = "xtrue"; then
+ CFLAGS="$CFLAGS -DMKL"
+fi
+
+AC_ARG_ENABLE([atlas],
+[ --enable-atlas Turn on ATLAS support],
+[case "${enableval}" in
+ yes) atlas=true ;;
+ no) atlas=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-atlas]) ;;
+esac],[atlas=false])
+AM_CONDITIONAL([ATLAS], [test x$atlas = xtrue])
+if test "x$atlas" = "xtrue"; then
+ CFLAGS="$CFLAGS -DATLAS"
+fi
+
+LIBKDOTP_ABI_VERSION=0
+LIBMODELXX_ABI_VERSION=0
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+++ /dev/null
-/*
-** Graph.c
-**
-** Made by (Johnny Q. Hacker)
-** Login <solarion@johnathan>
-**
-
-
-Copyright (C) 2008 Joseph Pingenot
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program 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 Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-**Many thanks to Davyd Madeley for the excellent Cairo Tutorial
-** at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28
-
-** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Sun May 12 01:17:25 2002 Speed Blue
-*/
-
-#include <graph.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-#ifdef DEBUG
-#define DEBUG_AUTOAXIS
-#endif
-
-G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT);
-
-static void graph_class_init(GraphClass *klass) {
- GObjectClass *gobject_klass;
- gobject_klass = G_OBJECT_CLASS(klass);
-}
-
-static void graph_init(Graph *graph) {
- graph->symbol = CIRCLE;
- graph->points = g_ptr_array_new();
- graph->lines = NULL;
- graph->xaxis = graph->yaxis = NULL;
-}
-
-Graph *graph_new(void) {
- return g_object_new(GRAPH_TYPE, NULL);
-}
-
-/*1 means you're stupid and passed NULL*/
-int graph_add_graph_point(Graph* graph, struct graph_point *pt) {
- if(pt == NULL) return 1;
- g_ptr_array_add(graph->points, pt);
- if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) {
- graph->maxx = graph->minx = pt->x;
- graph->maxy = graph->miny = pt->y;
- }else{
- if(pt->x > graph->maxx) graph->maxx = pt->x;
- if(pt->x < graph->minx) graph->minx = pt->x;
- if(pt->y > graph->maxy) graph->maxy = pt->y;
- if(pt->y < graph->miny) graph->miny = pt->y;
- }
- return 0;
-}
-
-/*
- *
- *1 means failed to allocate point
- *NOTE: label is duplicated if not NULL (using g_strdup)
- */
-int graph_add_point(Graph* graph, double x, double y, const GString *label) {
- struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point));
- if(pt == NULL) return 1;
- pt->x = x;
- pt->y = y;
- pt->label = (label)?g_string_new(label->str):NULL;
- graph_add_graph_point(graph, pt);
- return 0;
-}
-
-int graph_add_graph_line(Graph* graph, struct graph_line *l) {
- if(l == NULL) return 1;
- if(graph->lines == NULL) {
- if((graph->lines = g_ptr_array_new()) == NULL) return 1;
- }
- g_ptr_array_add(graph->lines, l);
- if((graph->points->len == 0) &&
- (graph->lines->len == 1)) {
- graph->maxx = graph->minx = l->p0_x;
- graph->maxy = graph->miny = l->p0_y;
- }else{
- if(l->p0_x > graph->maxx) graph->maxx = l->p0_x;
- if(l->p0_x < graph->minx) graph->minx = l->p0_x;
- if(l->p0_y > graph->maxy) graph->maxy = l->p0_y;
- if(l->p0_y < graph->miny) graph->miny = l->p0_y;
- }
- if(l->p3_x > graph->maxx) graph->maxx = l->p3_x;
- if(l->p3_x < graph->minx) graph->minx = l->p3_x;
- if(l->p3_y > graph->maxy) graph->maxy = l->p3_y;
- if(l->p3_y < graph->miny) graph->miny = l->p3_y;
- return 0;
-}
-
-
-int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) {
- #ifdef DEBUG
- fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
- #endif
- struct graph_line *l;
- if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2;
- l->p0_x=p0_x;
- l->p0_y=p0_y;
- l->p1_x=p1_x;
- l->p1_y=p1_y;
- l->p2_x=p2_x;
- l->p2_y=p2_y;
- l->p3_x=p3_x;
- l->p3_y=p3_y;
- return graph_add_graph_line(graph, l);
-}
-
-struct cxt {
- Graph *graph;
- struct graph_point *p0;
-};
-
-static void linear_interpolate(gpointer data, gpointer user_data) {
- struct cxt *cxt = user_data;
- struct graph_point *p3 = data;
- if(cxt->p0 != NULL) {
- double p1_x = (p3->x + 2*cxt->p0->x)/3.0;
- double p1_y = (p3->y + 2*cxt->p0->y)/3.0;
- double p2_x = (2*p3->x + cxt->p0->x)/3.0;
- double p2_y = (2*p3->y + cxt->p0->y)/3.0;
- graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y);
- }
- cxt->p0 = p3;
-}
-
-void graph_add_linear_connectors(Graph* graph) {
- struct cxt cxt;
- cxt.graph = graph;
- cxt.p0 = NULL;
- g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt);
-}
-
-void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) {
- *x1 = (x3 + 2.0*x0)/3.0;
- *x2 = (2.0*x3 + x0)/3.0;
-}
-
-void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) {
- *x1 = (x3 + x0)/2.0;
-}
-
-void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) {
- *x2 = (x3-2.0*(*x1))/3.0;
- *x1 = (x0-2.0*(*x1))/3.0;
-}
-
-void graph_set_xaxis(Graph *g, struct graph_axis *axis) {
- if(g->xaxis != NULL) {
- free(g->xaxis);
- }
- g->xaxis=axis;
-}
-void graph_set_yaxis(Graph *g, struct graph_axis *axis) {
- if(g->yaxis != NULL) {
- free(g->yaxis);
- }
- g->yaxis=axis;
-}
-
-struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) {
- struct graph_axis *axis;
- double range_mag;
- double start_mag;
- double stop_mag;
- int i, j;
- if(g->points->len == 0) {
- return NULL;
- }
- if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) {
- return NULL;
- }
- if(g->points->len == 1) {
- axis->major=1;
- axis->minor=0;
- axis->subminor=0;
- axis->major_start=min;
- axis->major_step=max;
- }else{
- range_mag = logb(max - min);
- if(min == 0)
- start_mag = 0;
- else
- start_mag = copysign(pow(10, floor(log10(min))), min);
- if(max == 0)
- stop_mag = 0;
- else
- stop_mag = copysign(pow(10, ceil(log10(max))), max);
- for(i=1; i<9; i++) {
- if(i*start_mag > min) break;
- }
- i--;
- for(j=10; j>1; j--) {
- if(j*(stop_mag/10) < max) break;
- }
- j++;
- axis->major=10;
- axis->minor=1;
- axis->subminor=4;
- axis->major_start=i*start_mag;
- axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major);
- }
- axis->title=g_string_new(title->str);
- #ifdef DEBUG_AUTOAXIS
- fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min)))));
- fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max)))));
- fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag);
- #endif
- return axis;
-}
-
-int graph_autoset_xaxis(Graph *g, GString *title) {
- graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx));
- return 0;
-}
-
-int graph_autoset_yaxis(Graph *g, GString *title) {
- graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy));
- return 0;
-}
+++ /dev/null
-/*
-** Graph.h
-**
-** Made by Johnny Q. Hacker
-** Login <solarion@johnathan>
-**
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-*/
-
-#ifndef GRAPHCLASS_H_
-#define GRAPHCLASS_H_
-
-#include <glib-2.0/glib-object.h>
-
-typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol;
-
-struct graph_point {
- double x;
- double y;
- GString *label;
-};
-
-/*Bezier line*/
-struct graph_line {
- /*First point*/
- double p0_x;
- double p0_y;
- /*Control pts*/
- double p1_x;
- double p1_y;
- double p2_x;
- double p2_y;
- /*End point*/
- double p3_x;
- double p3_y;
-};
-
-struct graph_axis {
- double major_start;
- double major_step;
- int major;
- int minor;
- int subminor;
- GString *title;
-};
-
-typedef struct _Graph {
- GObject parent_instance;
- /*Array of n_points sets of x,y coords*/
- GPtrArray *points;
- /*This draws all of the lines (generally between points)*/
- GPtrArray *lines;
- double maxx;
- double minx;
- double maxy;
- double miny;
- graph_symbol symbol;
- struct graph_axis *xaxis;
- struct graph_axis *yaxis;
-} Graph;
-
-typedef struct _GraphClass {
- GObjectClass parent_class;
-} GraphClass;
-
-#define GRAPH_TYPE (graph_get_type())
-#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph))
-#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass))
-#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE))
-#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE))
-#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass))
-
-Graph *graph_new(void);
-int graph_add_point(Graph* graph, double x, double y, const GString *label);
-int graph_add_graph_point(Graph* graph, struct graph_point *pt);
-int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y);
-int graph_add_graph_line(Graph* graph, struct graph_line *l);
-void graph_add_linear_connectors(Graph* graph);
-/*Provide x0, x3; x1 and x2 will be set*/
-void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2);
-/*Provide x0, x1, x2. x1 and x2 will be set appropriately.*/
-void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2);
-void graph_set_xaxis(Graph *g, struct graph_axis *axis);
-void graph_set_yaxis(Graph *g, struct graph_axis *axis);
-int graph_autoset_xaxis(Graph *g, GString *title);
-int graph_autoset_yaxis(Graph *g, GString *title);
-
-
-
-#endif /* !GRAPHCLASS_H_ */
+++ /dev/null
-/*
-** Graph.c
-**
-** Made by (Johnny Q. Hacker)
-** Login <solarion@johnathan>
-**
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial
-** at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
-
-** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Oct 8 17:13:50 2009 Johnny Q. Hacker
-*/
-
-#include <graphwidget.h>
-#include <math.h>
-
-G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA);
-
-#define INSET_PERCENT 0.1
-#define TITLE_PERCENT 0.15
-#define DEBUG_DRAW_AXIS
-
-struct drawing_context {
- GtkWidget *widget;
- cairo_t *cr;
- double radius;
- double xoffset;
- double yoffset;
- double xscaling;
- double yscaling;
- /*Semi-normalized maxima*/
- double xmax;
- double ymax;
- cairo_matrix_t data_scale;
- cairo_matrix_t data_xlat;
-};
-
-static void draw_point(gpointer data, gpointer user_data) {
- struct drawing_context *cxt = user_data;
- struct graph_point *pt = data;
- double x = (pt->x + cxt->xoffset)*cxt->xscaling;
- double y = (pt->y + cxt->yoffset)*cxt->yscaling;
- cairo_move_to(cxt->cr, x, y);
- cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI);
- if(pt->label != NULL) {
- cairo_save(cxt->cr);
- cairo_scale(cxt->cr, 1, -1);
- cairo_show_text(cxt->cr, pt->label->str);
- cairo_restore(cxt->cr);
- }
-}
-
-static void draw_lines(gpointer data, gpointer user_data) {
- struct drawing_context *cxt = user_data;
- struct graph_line *l = data;
- double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling;
- double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling;
- double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling;
- double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling;
- double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling;
- double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling;
- double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling;
- double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling;
- #ifdef DEBUG_DRAW
- fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
- #endif
- cairo_move_to(cxt->cr, p0_x, p0_y);
- cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
-}
-
-static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) {
- #ifdef DEBUG_DRAW_AXIS
- fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str);
- #endif
- cairo_move_to(cxt->cr, 0, 0);
- cairo_line_to(cxt->cr, max, 0);
- register int i, j, k;
- register double pos, mpos, smpos;
- for(i=0; i<axis->major; i++) {
- pos=i*axis->major_step + axis->major_start;
- cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
- cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
- for(k=0; k<axis->subminor; k++) {
- smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos;
- cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
- cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
- }
- for(j=0; j<axis->minor; j++) {
- mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos;
- cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0);
- cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025);
- for(k=0; k<axis->subminor; k++) {
- smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos;
- cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
- cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
- }
- }
- }
- pos=i*axis->major_step + axis->major_start;
- cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
- cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
-}
-
-static void draw(GtkWidget *graph, cairo_t *cr) {
- struct drawing_context cxt;
- GraphWidget *gw = GRAPH_WIDGET(graph);
- #ifdef DEBUG_DRAW
- fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr);
- fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width);
- #endif
- double x0=graph->allocation.x;
- double y0=graph->allocation.y;
- double height=graph->allocation.height;
- double width=graph->allocation.width;
- double minx = gw->graph->minx;
- double maxx = gw->graph->maxx;
- double miny = gw->graph->miny;
- double maxy = gw->graph->maxy;
- if(gw->graph->xaxis != NULL) {
- minx = gw->graph->xaxis->major_start;
- maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major;
- }
- if(gw->graph->yaxis != NULL) {
- miny = gw->graph->yaxis->major_start;
- maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major;
- }
- cxt.widget = graph;
- cxt.cr = cr;
- cxt.radius = 0.01;
- /*Set up our semi-normalized scaling. The shortest direction range
- [0, 1]; the other range depends upon the relative sizes.*/
- double effective_height = height;
- double effective_width = width;
- double inset, axis_inset;
- if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) {
- inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT;
- effective_height -= inset;
- effective_width -= inset;
- }
- if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) {
- /*key off the smaller size.*/
- axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT;
- effective_height -= axis_inset;
- effective_width -= axis_inset;
- }else if(gw->graph->xaxis != NULL) {
- effective_height -= effective_height*TITLE_PERCENT;
- }else if(gw->graph->yaxis != NULL) {
- effective_width -= effective_width*TITLE_PERCENT;
- }
- if(effective_width > effective_height) {
- cxt.xmax = effective_width/effective_height;
- cxt.ymax = 1.0;
- }else{
- cxt.xmax = 1.0;
- cxt.ymax = effective_height/effective_width;
- }
- /*Convert from data space to the semi-normalized space*/
- double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx));
- double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny));
- double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
- double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
- /*Finish up our context information.*/
- cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx)));
- cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny)));
- cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
- cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
- cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset);
- cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling);
- #ifdef DEBUG
- fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset);
- fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width);
- fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0));
- #endif
- double offset_height = ((width>=height)?height*INSET_PERCENT:0);;
- double offset_width = ((height>=width)?width*INSET_PERCENT:0);
- double inset_height = height - offset_height;
- double inset_width = width - offset_width;
- cairo_save(cr);
- cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2);
- cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax);
- cairo_set_line_width(cr, 0.005);
- cairo_select_font_face (cr, "Georgia",
- CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size (cr, 0.05);
- if(gw->graph->lines != NULL) {
- cairo_set_source_rgba(cr, 0, 0, 0, 0.25);
- g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt);
- cairo_stroke(cr);
- }
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_fill_preserve(cr);
- cairo_set_source_rgb(cr, 0, 0, 0);
- g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt);
- if(gw->graph->xaxis != NULL)
- draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax);
- if(gw->graph->yaxis != NULL) {
- cairo_save(cr);
- cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 };
- cairo_transform(cr, &matrix);
- draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax);
- cairo_restore(cr);
- }
- cairo_stroke(cr);
- cairo_restore(cr);
-}
-
-static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) {
- cairo_t *cr = gdk_cairo_create(graph->window);
- cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
- cairo_clip(cr);
- draw(graph, cr);
- cairo_destroy(cr);
- return FALSE;
-}
-
-static void graph_widget_class_init(GraphWidgetClass *klass) {
- GtkWidgetClass *widget_class;
- widget_class = GTK_WIDGET_CLASS(klass);
- widget_class->expose_event = graph_widget_expose;
-}
-
-static void graph_widget_init(GraphWidget *graph) {
- /*Get a graph.*/
- graph->graph = graph_new();
-}
-
-GtkWidget *graph_widget_new(void) {
- return g_object_new(GRAPH_WIDGET_TYPE, NULL);
-}
-
-Graph* graph_widget_get_graph(GraphWidget* gw) {
- return gw->graph;
-}
-
+++ /dev/null
-/*
-** Graph.h
-**
-** Made by Johnny Q. Hacker
-** Login <solarion@johnathan>
-**
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
-** Last update Thu Oct 8 14:28:34 2009 Johnny Q. Hacker
-*/
-
-#ifndef GRAPHWIDGET_H_
-#define GRAPHWIDGET_H_
-
-#include <gtk/gtkdrawingarea.h>
-#include <graph.h>
-
-typedef struct _GraphWidget {
- GtkDrawingArea parent_instance;
- Graph *graph;
-} GraphWidget;
-
-typedef struct _GraphWidgetClass {
- GtkDrawingAreaClass parent_class;
-} GraphWidgetClass;
-
-#define GRAPH_WIDGET_TYPE (graph_widget_get_type())
-#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget))
-#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass))
-#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE))
-#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE))
-#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass))
-
-GtkWidget* graph_widget_new(void);
-
-Graph* graph_widget_get_graph(GraphWidget* gw);
-
-#endif /* !GRAPHWIDGET_H_ */
+++ /dev/null
-/*
- * matdb-dotcode: reads in Craig's Dotcode materials database.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <matdb-dotcode.h>
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <strings.h>
-#include <stdlib.h>
-
-#ifdef DEBUG
-#undef DEBUG
-#endif
-#ifdef DEBUG_2
-#undef DEBUG_2
-#endif
-
-/*Functions to be used by the hash.*/
-static void destroy_string(gpointer data) {
- free((char*)data);
-}
-static void destroy_double(gpointer data){
- free((double*)data);
-}
-static void destroy_inner_bowhash(gpointer data) {
- g_hash_table_unref(data);
-}
-
-int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
- if((*mat) != NULL) {
-#ifdef DEBUG
- fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
-#endif
- g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
- (*mat) = NULL;
- }
- if((*bow) != NULL) {
-#ifdef DEBUG
- fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
-#endif
- /*Inner table*/
- GHashTable *it;
- if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
- if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
- (*bow) = NULL;
- return 1;
- }
- g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
- #ifdef DEBUG
- fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
- #endif
- }
- g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
- (*bow) = NULL;
- }
- return 0;
-}
-
-/*Removes leading and trailing whitespace, comments, and reduces
- redundant whitespace down to one tab, makes an empty line an empty string.*/
-static void prettify_line(char *line) {
- register char *look;
- register char *write;
- register int in_whitespace;
- register int leading_whitespace;
- for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
-#ifdef DEBUG_2
- fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
-#endif
- if(*look == '#') {
-#ifdef DEBUG_2
- fprintf(stderr, "comment\n");
-#endif
- *write = '\0';
- break;
- }
- switch(*look) {
- case ' ':
- case '\n':
- case '\t':
-#ifdef DEBUG_2
- fprintf(stderr, "whitespace\n");
-#endif
- if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
- in_whitespace=1;
- break;
- default:
-#ifdef DEBUG_2
- fprintf(stderr, "default\n");
-#endif
- *write++ = *look;
- in_whitespace=leading_whitespace=0;
- }
- }
- *write='\0';
- for(look=write=line; *look != '\0'; look++) {
- switch(*look) {
- case ' ':
- case '\n':
- case '\t':
- if(*(look+1) == '\0') {
- *look = '\0';
- }
- }
- }
-}
-
-/*Error values:
- * 0: success
- * 1: failure malloc'ing / initializing mdb struct
- * 2: failure opening file.
- * 4: failure reading line.
- * 8: warning reading line: no tab separator (line parsing error)
- * 16: warning reading line: bad section declaration
- * 32: warning reading line: unable to allocate material struct.
- * 64: warning reading line: ignored line (unallocated material struct)
- * 128: warning reading line: unable to allocate bowing struct
- * 256: warning reading line: ignored line (unallocated bowing struct)
- * 512: warning reading file: improper section detected (programming
- * error)
- *1024: warning reading file: no : separator in bowing materials
- * description.
- *2048: warning reading file: unable to read numeric value for property.
- */
-struct matdb* read_matdb_dotcode(const GString *name, int* err) {
-#ifdef DEBUG_2
- fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
-#endif
- *err=0;
- struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
- if(mdb == NULL) {*err = 1; return NULL;}
-
- double *value;
- if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
- *err = 1;
- free(mdb);
- return NULL;
- }
- if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
- *err = 1;
- g_hash_table_unref(mdb->materials);
- free(mdb);
- return NULL;
- }
- struct matdb_material *mat = NULL;
- struct matdb_bowing *bow = NULL;
- /*Valid sections:
- * 0 (no/global section)
- * 1 (material)
- * 2 (bow)
- */
- int section=0;
- int n;
- char *line;
- FILE *infile = fopen(name->str, "r");
- if(infile == NULL) {
- g_hash_table_unref(mdb->materials);
- g_hash_table_unref(mdb->bowings);
- free(mdb);
- *err=2;
- return NULL;
-#ifdef DEBUG_2
- }else{
- fprintf(stderr, "infile=%x\n", (unsigned int)infile);
-#endif
- }
- int val;
- while(!feof(infile)) {
-#ifdef DEBUG
- fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
-#endif
- line=NULL;
- if((val = getline(&line, &n, infile)) == -1) {
-#ifdef DEBUG_2
- fprintf(stderr, "getline returned %d\n", val);
-#endif
- if(!feof(infile)) *err = 4;
- //fclose(infile);
- break;
- }
-#ifdef DEBUG_2
- fprintf(stderr, "line=(%s)\n", line);
-#endif
- prettify_line(line);
-#ifdef DEBUG
- fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
-#endif
- if(*line == '\0') {
- free(line);
- continue;
- }
- char *i = index(line, '\t');
- if(i == NULL) {
- *err &= 8;
- }
- *i++ = '\0';
- /*At this point, we have line which stores the first word on the
- line, and i which stores the second word on the line.
- */
- char *to;
- GHashTable *ht;
-#ifdef DEBUG_2
- fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
-#endif
- /*If we have a material or bowing underway, save it off*/
- if(strcasecmp(line, "material") == 0) {
- insert_into_matdb(mdb, &mat, &bow);
- if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
- *err &= 32;
- }
- if((mat->name = g_string_new(i)) == NULL) {
- *err &= 32;
- free(mat);
- section=0;
- continue;
- }
- if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
- *err &= 32;
- g_string_free(mat->name, TRUE);
- free(bow);
- section=0;
- continue;
- }
-#ifdef DEBUG_2
- fprintf(stderr, "new material (%s):\n", i);
-#endif
- section=1;
- }else if(strcasecmp(line, "bow") == 0) {
- insert_into_matdb(mdb, &mat, &bow);
- if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
- *err &= 128;
- }
- if((to = index(i, ':')) == NULL) {
- *err &= 1024;
- free(bow);
- section=0;
- continue;
- }
- *to++ = '\0';
- /*Same trick as before, but i now stores the from material,
- and to the to material
- */
- if((bow->from = g_string_new(i)) == NULL) {
- *err &= 128;
- free(bow);
- section=0;
- continue;
- }
- if((bow->to = g_string_new(to)) == NULL) {
- *err &= 128;
- g_string_free(bow->from, TRUE);
- free(bow);
- section=0;
- continue;
- }
- if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
- *err &= 128;
- g_string_free(bow->to, TRUE);
- g_string_free(bow->from, TRUE);
- free(bow);
- section=0;
- continue;
- }
-#ifdef DEBUG_2
- fprintf(stderr, "new bowing (%s:%s):\n", i, to);
-#endif
- section=2;
- }else{
- #ifdef DEBUG
- fprintf(stderr, "\t%d/%s\t", section, line);
- #endif
- /*Process a property.*/
- switch(section) {
- case 1:
- #ifdef DEBUG
- fprintf(stderr, "(1)\t");
- #endif
- ht = mat->properties;
- break;
- case 2:
- #ifdef DEBUG
- fprintf(stderr, "(2)\t");
- #endif
- ht = bow->properties;
- break;
- default:
- #ifdef DEBUG
- fprintf(stderr, "(default)\t");
- #endif
- *err &= 16;
- section = 0;
- }
- if(section == 0) {
- #ifdef DEBUG
- fprintf(stderr, "section was 0\n");
- #endif
- continue;
- }
- if((value = (double*)malloc(sizeof(double))) == NULL) {
- *err &= 2048;
- #ifdef DEBUG
- fprintf(stderr, "malloc of value failed\n");
- #endif
- continue;
- }
- int num;
- if((num=sscanf(i, " %lg", value)) != 1) {
- *err &= 2048;
- free(value);
- #ifdef DEBUG
- fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
- #endif
- continue;
- }
- g_hash_table_insert(ht, g_strdup(line), value);
-#ifdef DEBUG
- fprintf(stderr, "%g(%s)\n", *value, line);
-#endif
- }
- free(line);
- line=i=to=NULL;
- value=NULL;
- }
- fclose(infile);
- insert_into_matdb(mdb, &mat, &bow);
- return mdb;
-}
-
+++ /dev/null
-/*
- * matdb-dotcode: reads in Craig's Dotcode materials database.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef MATDB_DOTCODE_H_
-#define MATDB_DOTCODE_H_
-
-#include <matdb.h>
-
-struct matdb* read_matdb_dotcode(const GString *name, int *err);
-
-#endif
+++ /dev/null
-/*
- * matdb: generic materials database information.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <matdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static void print_property(gpointer key, gpointer value, gpointer user_data) {
- fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value);
-}
-static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) {
- struct matdb_bowing *bowing = (struct matdb_bowing*)value;
- fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key);
- g_hash_table_foreach(bowing->properties, &print_property, NULL);
-}
-static void print_material(gpointer key, gpointer value, gpointer user_data) {
- struct matdb_material *mat = (struct matdb_material*)value;
- fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key);
- g_hash_table_foreach(mat->properties, &print_property, NULL);
-}
-static void print_bowing(gpointer key, gpointer value, gpointer user_data) {
- GHashTable *ht = value;
- g_hash_table_foreach(ht, &print_inner_bowing, key);
-}
-
-void print_matdb(const struct matdb *mdb) {
- fprintf(stderr, "matdb:\n");
- g_hash_table_foreach(mdb->materials, &print_material, NULL);
- g_hash_table_foreach(mdb->bowings, &print_bowing, NULL);
-}
-
-void destroy_material_gpointer(gpointer data) {
- destroy_material((struct matdb_material *)data);
-}
-void destroy_bowing_gpointer(gpointer data) {
- destroy_bowing((struct matdb_bowing *)data);
-}
-void destroy_material(struct matdb_material *mat) {
- #ifdef DEBUG
- fprintf(stderr, "destroy_material\n");
- #endif
- g_string_free(mat->name, TRUE);
- g_hash_table_unref(mat->properties);
- free(mat);
-}
-void destroy_bowing(struct matdb_bowing *bow) {
- #ifdef DEBUG
- fprintf(stderr, "destroy_bowing\n");
- #endif
- g_string_free(bow->from, TRUE);
- g_string_free(bow->to, TRUE);
- g_hash_table_unref(bow->properties);
- free(bow);
-}
+++ /dev/null
-/*
- * matdb: generic materials database information.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef MATDB_H_
-#define MATDB_H_
-
-#include <glib-2.0/glib.h>
-
-struct matdb_material {
- GString *name;
- GHashTable *properties;
-};
-
-struct matdb_bowing {
- GString *from;
- GString *to;
- GHashTable *properties;
-};
-
-struct matdb {
- GHashTable *materials;
- GHashTable *bowings;
-};
-
-void print_matdb(const struct matdb *mdb);
-void destroy_material_gpointer(gpointer data);
-void destroy_bowing_gpointer(gpointer data);
-void destroy_material(struct matdb_material *mat);
-void destroy_bowing(struct matdb_bowing *bow);
-
-#endif
+++ /dev/null
-/*
-** scdataviz.c
-**
-** Made by (Johnny Q. Hacker)
-** Login <solarion@johnathan>
-**
-** Holds the SC graphing widget.
-
-
-
- Copyright (C) 2008 Joseph Pingenot
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-** Started on Thu Jul 17 11:03:27 2008 Johnny Q. Hacker
-** Last update Thu Oct 8 19:13:57 2009 Johnny Q. Hacker
-*/
-
-#include <gtk/gtk.h>
-#include <graphwidget.h>
-#include <matdb-dotcode.h>
-#include <stdlib.h>
-#include <strings.h>
-
-#define DEBUG_SHOW_ONLY_BOWED
-
-struct xy_properties {
- GString *xprop;
- GString *yprop;
- Graph *graph;
- struct matdb *mdb;
- struct matdb_material *mat;
-};
-
-static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) {
- *x=g_hash_table_lookup(propts, xprop->str);
- *y=g_hash_table_lookup(propts, yprop->str);
-}
-
-static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) {
- struct xy_properties *propmap = user_data;
- struct matdb_material *mat = value;
- if(!strcasecmp(mat->name->str, "vacuum")) return;
- if(!strcasecmp(mat->name->str, "pvb")) return;
- double *x, *y;
- #ifdef DEBUG_ASSIGNMENT
- fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str);
- #endif
- lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y);
- if((x != NULL) && (y != NULL)) {
- graph_add_point(propmap->graph, *x, *y, mat->name);
- #ifdef DEBUG_ASSIGNMENT
- fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y);
- }else{
- fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str);
- #endif
- }
-}
-
-static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) {
- struct xy_properties *propmap = user_data;
- struct matdb_material *mat = value;
- if(!strcasecmp(mat->name->str, "vacuum")) return;
- if(!strcasecmp(mat->name->str, "pvb")) return;
- if(g_string_equal(mat->name, propmap->mat->name)) return;
- struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line));
- if(l == NULL) return;
- struct matdb_bowing *bow = NULL;
- GHashTable *subtable;
- double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y;
- lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y);
- lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y);
-#ifdef DEBUG_ASSIGNMENT
- fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0);
-#endif
- if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) {
- l->p0_x = *p0_x;
- l->p0_y = *p0_y;
- l->p3_x = *p3_x;
- l->p3_y = *p3_y;
- if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) {
- /*Try the other way 'round*/
- if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) )
- != NULL) {
- bow = g_hash_table_lookup(subtable, propmap->mat->name->str);
- }
- }else{
- bow = g_hash_table_lookup(subtable, mat->name->str);
- }
- if(bow != NULL) {
- if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) {
- l->p1_x = *p1_x/2.0;
- graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
- }else{
- graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
- }
- if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) {
- l->p1_y = *p1_y/2.0;
- graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
- }else{
- graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
- }
- }else{
- #ifdef DEBUG_SHOW_ONLY_BOWED
- free(l);
- return;
- #endif
- graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
- graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
- }
- #ifdef DEBUG_ASSIGNMENT
- fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y);
- #endif
- graph_add_graph_line(propmap->graph, l);
- }else{
- free(l);
- }
-}
-
-static void link_materials(gpointer key, gpointer value, gpointer user_data) {
- struct xy_properties *propmap = user_data;
- struct matdb_material *mat = value;
- if(!strcasecmp(mat->name->str, "vacuum")) return;
- if(!strcasecmp(mat->name->str, "pvb")) return;
- propmap->mat = mat;
- g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap);
-}
-
-int main(int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *graph;
- GString *file = g_string_new("matdb.txt");
- int err=0;
- struct matdb *mdb = read_matdb_dotcode(file, &err);
- //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err,
- //(int)mdb);
- //fprintf(stderr, "err=%d\n", err);
- //print_matdb(mdb);
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- graph = graph_widget_new();
-
- struct xy_properties propmap;
- propmap.xprop = g_string_new("a_lc");
- propmap.yprop = g_string_new("E_g_Gamma");
- propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph));
- propmap.mdb = mdb;
- g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap);
- //graph_add_linear_connectors(propmap.graph);
- g_hash_table_foreach(mdb->materials, &link_materials, &propmap);
- graph_autoset_xaxis(propmap.graph, propmap.xprop);
- graph_autoset_yaxis(propmap.graph, propmap.yprop);
-
- //Connect signals
- g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
-
- gtk_container_add(GTK_CONTAINER(window), graph);
- /*
- graph_add_point(graph_widget_get_graph(graph), 5, 3);
- graph_add_point(graph_widget_get_graph(graph), 8, 12);
- graph_add_point(graph_widget_get_graph(graph), 11, 48);
- */
-
- gtk_widget_show_all (window);
-
- gtk_main ();
-
- return 0;
-}
--- /dev/null
+/*
+** Graph.c
+**
+** Made by (Johnny Q. Hacker)
+** Login <solarion@johnathan>
+**
+
+
+Copyright (C) 2008 Joseph Pingenot
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program 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 Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+**Many thanks to Davyd Madeley for the excellent Cairo Tutorial
+** at http://gnomejournal.org/article/34/writing-a--using-cairo-and-gtk28
+
+** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Sun May 12 01:17:25 2002 Speed Blue
+*/
+
+#include <graph.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifdef DEBUG
+#define DEBUG_AUTOAXIS
+#endif
+
+G_DEFINE_TYPE(Graph, graph, G_TYPE_OBJECT);
+
+static void graph_class_init(GraphClass *klass) {
+ GObjectClass *gobject_klass;
+ gobject_klass = G_OBJECT_CLASS(klass);
+}
+
+static void graph_init(Graph *graph) {
+ graph->symbol = CIRCLE;
+ graph->points = g_ptr_array_new();
+ graph->lines = NULL;
+ graph->xaxis = graph->yaxis = NULL;
+}
+
+Graph *graph_new(void) {
+ return g_object_new(GRAPH_TYPE, NULL);
+}
+
+/*1 means you're stupid and passed NULL*/
+int graph_add_graph_point(Graph* graph, struct graph_point *pt) {
+ if(pt == NULL) return 1;
+ g_ptr_array_add(graph->points, pt);
+ if((graph->points->len == 1) && ((graph->lines == NULL) || (graph->lines->len == 0))) {
+ graph->maxx = graph->minx = pt->x;
+ graph->maxy = graph->miny = pt->y;
+ }else{
+ if(pt->x > graph->maxx) graph->maxx = pt->x;
+ if(pt->x < graph->minx) graph->minx = pt->x;
+ if(pt->y > graph->maxy) graph->maxy = pt->y;
+ if(pt->y < graph->miny) graph->miny = pt->y;
+ }
+ return 0;
+}
+
+/*
+ *
+ *1 means failed to allocate point
+ *NOTE: label is duplicated if not NULL (using g_strdup)
+ */
+int graph_add_point(Graph* graph, double x, double y, const GString *label) {
+ struct graph_point *pt = (struct graph_point*)malloc(sizeof(struct graph_point));
+ if(pt == NULL) return 1;
+ pt->x = x;
+ pt->y = y;
+ pt->label = (label)?g_string_new(label->str):NULL;
+ graph_add_graph_point(graph, pt);
+ return 0;
+}
+
+int graph_add_graph_line(Graph* graph, struct graph_line *l) {
+ if(l == NULL) return 1;
+ if(graph->lines == NULL) {
+ if((graph->lines = g_ptr_array_new()) == NULL) return 1;
+ }
+ g_ptr_array_add(graph->lines, l);
+ if((graph->points->len == 0) &&
+ (graph->lines->len == 1)) {
+ graph->maxx = graph->minx = l->p0_x;
+ graph->maxy = graph->miny = l->p0_y;
+ }else{
+ if(l->p0_x > graph->maxx) graph->maxx = l->p0_x;
+ if(l->p0_x < graph->minx) graph->minx = l->p0_x;
+ if(l->p0_y > graph->maxy) graph->maxy = l->p0_y;
+ if(l->p0_y < graph->miny) graph->miny = l->p0_y;
+ }
+ if(l->p3_x > graph->maxx) graph->maxx = l->p3_x;
+ if(l->p3_x < graph->minx) graph->minx = l->p3_x;
+ if(l->p3_y > graph->maxy) graph->maxy = l->p3_y;
+ if(l->p3_y < graph->miny) graph->miny = l->p3_y;
+ return 0;
+}
+
+
+int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y) {
+ #ifdef DEBUG
+ fprintf(stderr, "graph_add_line(%d, p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", (unsigned int) graph, p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+ #endif
+ struct graph_line *l;
+ if((l=(struct graph_line*)malloc(sizeof(struct graph_line))) == NULL) return 2;
+ l->p0_x=p0_x;
+ l->p0_y=p0_y;
+ l->p1_x=p1_x;
+ l->p1_y=p1_y;
+ l->p2_x=p2_x;
+ l->p2_y=p2_y;
+ l->p3_x=p3_x;
+ l->p3_y=p3_y;
+ return graph_add_graph_line(graph, l);
+}
+
+struct cxt {
+ Graph *graph;
+ struct graph_point *p0;
+};
+
+static void linear_interpolate(gpointer data, gpointer user_data) {
+ struct cxt *cxt = user_data;
+ struct graph_point *p3 = data;
+ if(cxt->p0 != NULL) {
+ double p1_x = (p3->x + 2*cxt->p0->x)/3.0;
+ double p1_y = (p3->y + 2*cxt->p0->y)/3.0;
+ double p2_x = (2*p3->x + cxt->p0->x)/3.0;
+ double p2_y = (2*p3->y + cxt->p0->y)/3.0;
+ graph_add_line(cxt->graph, cxt->p0->x, cxt->p0->y, p1_x, p1_y, p2_x, p2_y, p3->x, p3->y);
+ }
+ cxt->p0 = p3;
+}
+
+void graph_add_linear_connectors(Graph* graph) {
+ struct cxt cxt;
+ cxt.graph = graph;
+ cxt.p0 = NULL;
+ g_ptr_array_foreach(graph->points, &linear_interpolate, &cxt);
+}
+
+void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2) {
+ *x1 = (x3 + 2.0*x0)/3.0;
+ *x2 = (2.0*x3 + x0)/3.0;
+}
+
+void graph_bezier_linear_to_quadratic(double x0, double x3, double *x1) {
+ *x1 = (x3 + x0)/2.0;
+}
+
+void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2) {
+ *x2 = (x3-2.0*(*x1))/3.0;
+ *x1 = (x0-2.0*(*x1))/3.0;
+}
+
+void graph_set_xaxis(Graph *g, struct graph_axis *axis) {
+ if(g->xaxis != NULL) {
+ free(g->xaxis);
+ }
+ g->xaxis=axis;
+}
+void graph_set_yaxis(Graph *g, struct graph_axis *axis) {
+ if(g->yaxis != NULL) {
+ free(g->yaxis);
+ }
+ g->yaxis=axis;
+}
+
+struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max) {
+ struct graph_axis *axis;
+ double range_mag;
+ double start_mag;
+ double stop_mag;
+ int i, j;
+ if(g->points->len == 0) {
+ return NULL;
+ }
+ if((axis=(struct graph_axis *)malloc(sizeof(struct graph_axis))) == NULL) {
+ return NULL;
+ }
+ if(g->points->len == 1) {
+ axis->major=1;
+ axis->minor=0;
+ axis->subminor=0;
+ axis->major_start=min;
+ axis->major_step=max;
+ }else{
+ range_mag = logb(max - min);
+ if(min == 0)
+ start_mag = 0;
+ else
+ start_mag = copysign(pow(10, floor(log10(min))), min);
+ if(max == 0)
+ stop_mag = 0;
+ else
+ stop_mag = copysign(pow(10, ceil(log10(max))), max);
+ for(i=1; i<9; i++) {
+ if(i*start_mag > min) break;
+ }
+ i--;
+ for(j=10; j>1; j--) {
+ if(j*(stop_mag/10) < max) break;
+ }
+ j++;
+ axis->major=10;
+ axis->minor=1;
+ axis->subminor=4;
+ axis->major_start=i*start_mag;
+ axis->major_step=(j*(stop_mag/10) - axis->major_start)/(axis->major);
+ }
+ axis->title=g_string_new(title->str);
+ #ifdef DEBUG_AUTOAXIS
+ fprintf(stderr, "graph_autoset_xaxis: xmin=%g, log10(xmin)=%g, floor=%g, pow=%g round=%g\n", min, log10(min), floor(log10(min)), pow(10, floor(log10(min))), round(pow(10, floor(log10(min)))));
+ fprintf(stderr, "graph_autoset_xaxis: xmax=%g, log10(xmax)=%g, floor=%g, pow=%g round=%g\n", max, log10(max), floor(log10(max)), pow(10, floor(log10(max))), round(pow(10, floor(log10(max)))));
+ fprintf(stderr, "graph_autoset_xaxis: xmin=%g,max=%g start_mag=%g, stop_mag=%g range_mag=%g\n", min, max, start_mag, stop_mag, range_mag);
+ #endif
+ return axis;
+}
+
+int graph_autoset_xaxis(Graph *g, GString *title) {
+ graph_set_xaxis(g, autoset_axis(g, title, g->minx, g->maxx));
+ return 0;
+}
+
+int graph_autoset_yaxis(Graph *g, GString *title) {
+ graph_set_yaxis(g, autoset_axis(g, title, g->miny, g->maxy));
+ return 0;
+}
--- /dev/null
+/*
+** Graph.h
+**
+** Made by Johnny Q. Hacker
+** Login <solarion@johnathan>
+**
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+*/
+
+#ifndef GRAPHCLASS_H_
+#define GRAPHCLASS_H_
+
+#include <glib-2.0/glib-object.h>
+
+typedef enum {SQUARE, CIRCLE, STAR, PLUS, MINUS, CROSS} graph_symbol;
+
+struct graph_point {
+ double x;
+ double y;
+ GString *label;
+};
+
+/*Bezier line*/
+struct graph_line {
+ /*First point*/
+ double p0_x;
+ double p0_y;
+ /*Control pts*/
+ double p1_x;
+ double p1_y;
+ double p2_x;
+ double p2_y;
+ /*End point*/
+ double p3_x;
+ double p3_y;
+};
+
+struct graph_axis {
+ double major_start;
+ double major_step;
+ int major;
+ int minor;
+ int subminor;
+ GString *title;
+};
+
+typedef struct _Graph {
+ GObject parent_instance;
+ /*Array of n_points sets of x,y coords*/
+ GPtrArray *points;
+ /*This draws all of the lines (generally between points)*/
+ GPtrArray *lines;
+ double maxx;
+ double minx;
+ double maxy;
+ double miny;
+ graph_symbol symbol;
+ struct graph_axis *xaxis;
+ struct graph_axis *yaxis;
+} Graph;
+
+typedef struct _GraphClass {
+ GObjectClass parent_class;
+} GraphClass;
+
+#define GRAPH_TYPE (graph_get_type())
+#define GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_TYPE, Graph))
+#define GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH, GraphClass))
+#define IS_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_TYPE))
+#define IS_GRAPH_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_CLASS_TYPE))
+#define GRAPH_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH, GraphClass))
+
+Graph *graph_new(void);
+int graph_add_point(Graph* graph, double x, double y, const GString *label);
+int graph_add_graph_point(Graph* graph, struct graph_point *pt);
+int graph_add_line(Graph* graph, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y);
+int graph_add_graph_line(Graph* graph, struct graph_line *l);
+void graph_add_linear_connectors(Graph* graph);
+/*Provide x0, x3; x1 and x2 will be set*/
+void graph_bezier_linear_to_cubic(double x0, double x3, double *x1, double *x2);
+/*Provide x0, x1, x2. x1 and x2 will be set appropriately.*/
+void graph_bezier_quadratic_to_cubic(double x0, double x3, double *x1, double *x2);
+void graph_set_xaxis(Graph *g, struct graph_axis *axis);
+void graph_set_yaxis(Graph *g, struct graph_axis *axis);
+int graph_autoset_xaxis(Graph *g, GString *title);
+int graph_autoset_yaxis(Graph *g, GString *title);
+
+
+
+#endif /* !GRAPHCLASS_H_ */
--- /dev/null
+/*
+** Graph.c
+**
+** Made by (Johnny Q. Hacker)
+** Login <solarion@johnathan>
+**
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+**Many thanks to Davyd Madeley for the excellent Cairo Widget Tutorial
+** at http://gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
+
+** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Oct 8 17:13:50 2009 Johnny Q. Hacker
+*/
+
+#include <graphwidget.h>
+#include <math.h>
+
+G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA);
+
+#define INSET_PERCENT 0.1
+#define TITLE_PERCENT 0.15
+#define DEBUG_DRAW_AXIS
+
+struct drawing_context {
+ GtkWidget *widget;
+ cairo_t *cr;
+ double radius;
+ double xoffset;
+ double yoffset;
+ double xscaling;
+ double yscaling;
+ /*Semi-normalized maxima*/
+ double xmax;
+ double ymax;
+ cairo_matrix_t data_scale;
+ cairo_matrix_t data_xlat;
+};
+
+static void draw_point(gpointer data, gpointer user_data) {
+ struct drawing_context *cxt = user_data;
+ struct graph_point *pt = data;
+ double x = (pt->x + cxt->xoffset)*cxt->xscaling;
+ double y = (pt->y + cxt->yoffset)*cxt->yscaling;
+ cairo_move_to(cxt->cr, x, y);
+ cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI);
+ if(pt->label != NULL) {
+ cairo_save(cxt->cr);
+ cairo_scale(cxt->cr, 1, -1);
+ cairo_show_text(cxt->cr, pt->label->str);
+ cairo_restore(cxt->cr);
+ }
+}
+
+static void draw_lines(gpointer data, gpointer user_data) {
+ struct drawing_context *cxt = user_data;
+ struct graph_line *l = data;
+ double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling;
+ double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling;
+ double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling;
+ double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling;
+ double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling;
+ double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling;
+ double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling;
+ double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling;
+ #ifdef DEBUG_DRAW
+ fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+ #endif
+ cairo_move_to(cxt->cr, p0_x, p0_y);
+ cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y);
+}
+
+static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset, double max) {
+ #ifdef DEBUG_DRAW_AXIS
+ fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str);
+ #endif
+ cairo_move_to(cxt->cr, 0, 0);
+ cairo_line_to(cxt->cr, max, 0);
+ register int i, j, k;
+ register double pos, mpos, smpos;
+ for(i=0; i<axis->major; i++) {
+ pos=i*axis->major_step + axis->major_start;
+ cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
+ cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
+ for(k=0; k<axis->subminor; k++) {
+ smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + pos;
+ cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
+ cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
+ }
+ for(j=0; j<axis->minor; j++) {
+ mpos=(j+1)*(axis->major_step/(axis->minor+1)) + pos;
+ cairo_move_to(cxt->cr, (mpos + offset)*scaling, 0);
+ cairo_line_to(cxt->cr, (mpos + offset)*scaling, 0.025);
+ for(k=0; k<axis->subminor; k++) {
+ smpos=(k+1)*(axis->major_step/(axis->minor+1)/(axis->subminor+1)) + mpos;
+ cairo_move_to(cxt->cr, (smpos + offset)*scaling, 0);
+ cairo_line_to(cxt->cr, (smpos + offset)*scaling, 0.0125);
+ }
+ }
+ }
+ pos=i*axis->major_step + axis->major_start;
+ cairo_move_to(cxt->cr, (pos + offset)*scaling, 0);
+ cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05);
+}
+
+static void draw(GtkWidget *graph, cairo_t *cr) {
+ struct drawing_context cxt;
+ GraphWidget *gw = GRAPH_WIDGET(graph);
+ #ifdef DEBUG_DRAW
+ fprintf(stderr, "draw(%d, %d)\n", (int)graph, (int)cr);
+ fprintf(stderr, "allocation.x=%d, allocation.y=%d, allocation.height=%d, allocation.width=%d\n", graph->allocation.x, graph->allocation.y, graph->allocation.height, graph->allocation.width);
+ #endif
+ double x0=graph->allocation.x;
+ double y0=graph->allocation.y;
+ double height=graph->allocation.height;
+ double width=graph->allocation.width;
+ double minx = gw->graph->minx;
+ double maxx = gw->graph->maxx;
+ double miny = gw->graph->miny;
+ double maxy = gw->graph->maxy;
+ if(gw->graph->xaxis != NULL) {
+ minx = gw->graph->xaxis->major_start;
+ maxx = gw->graph->xaxis->major_start + gw->graph->xaxis->major_step*gw->graph->xaxis->major;
+ }
+ if(gw->graph->yaxis != NULL) {
+ miny = gw->graph->yaxis->major_start;
+ maxy = gw->graph->yaxis->major_start + gw->graph->yaxis->major_step*gw->graph->yaxis->major;
+ }
+ cxt.widget = graph;
+ cxt.cr = cr;
+ cxt.radius = 0.01;
+ /*Set up our semi-normalized scaling. The shortest direction range
+ [0, 1]; the other range depends upon the relative sizes.*/
+ double effective_height = height;
+ double effective_width = width;
+ double inset, axis_inset;
+ if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) {
+ inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT;
+ effective_height -= inset;
+ effective_width -= inset;
+ }
+ if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) {
+ /*key off the smaller size.*/
+ axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT;
+ effective_height -= axis_inset;
+ effective_width -= axis_inset;
+ }else if(gw->graph->xaxis != NULL) {
+ effective_height -= effective_height*TITLE_PERCENT;
+ }else if(gw->graph->yaxis != NULL) {
+ effective_width -= effective_width*TITLE_PERCENT;
+ }
+ if(effective_width > effective_height) {
+ cxt.xmax = effective_width/effective_height;
+ cxt.ymax = 1.0;
+ }else{
+ cxt.xmax = 1.0;
+ cxt.ymax = effective_height/effective_width;
+ }
+ /*Convert from data space to the semi-normalized space*/
+ double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx));
+ double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny));
+ double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
+ double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
+ /*Finish up our context information.*/
+ cxt.xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(((maxx - minx)==0)?1:(maxx-minx)));
+ cxt.yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(((maxy - miny)==0)?1:(maxy-miny)));
+ cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx);
+ cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny);
+ cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset);
+ cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling);
+ #ifdef DEBUG
+ fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset);
+ fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width);
+ fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0));
+ #endif
+ double offset_height = ((width>=height)?height*INSET_PERCENT:0);;
+ double offset_width = ((height>=width)?width*INSET_PERCENT:0);
+ double inset_height = height - offset_height;
+ double inset_width = width - offset_width;
+ cairo_save(cr);
+ cairo_translate(cr, x0 + (width - effective_width) - inset/2, y0 + effective_height + inset/2);
+ cairo_scale(cr, effective_width/cxt.xmax, -effective_height/cxt.ymax);
+ cairo_set_line_width(cr, 0.005);
+ cairo_select_font_face (cr, "Georgia",
+ CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, 0.05);
+ if(gw->graph->lines != NULL) {
+ cairo_set_source_rgba(cr, 0, 0, 0, 0.25);
+ g_ptr_array_foreach(gw->graph->lines, &draw_lines, (gpointer)&cxt);
+ cairo_stroke(cr);
+ }
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill_preserve(cr);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ g_ptr_array_foreach(gw->graph->points, &draw_point, (gpointer)&cxt);
+ if(gw->graph->xaxis != NULL)
+ draw_axis(&cxt, gw->graph->xaxis, cxt.xscaling, cxt.xoffset, cxt.xmax);
+ if(gw->graph->yaxis != NULL) {
+ cairo_save(cr);
+ cairo_matrix_t matrix = { .xx=0, .xy = 1, .x0 = 0, .yx = 1, .yy = 0, .y0 = 0 };
+ cairo_transform(cr, &matrix);
+ draw_axis(&cxt, gw->graph->yaxis, cxt.yscaling, cxt.yoffset, cxt.ymax);
+ cairo_restore(cr);
+ }
+ cairo_stroke(cr);
+ cairo_restore(cr);
+}
+
+static gboolean graph_widget_expose(GtkWidget *graph, GdkEventExpose *event) {
+ cairo_t *cr = gdk_cairo_create(graph->window);
+ cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
+ cairo_clip(cr);
+ draw(graph, cr);
+ cairo_destroy(cr);
+ return FALSE;
+}
+
+static void graph_widget_class_init(GraphWidgetClass *klass) {
+ GtkWidgetClass *widget_class;
+ widget_class = GTK_WIDGET_CLASS(klass);
+ widget_class->expose_event = graph_widget_expose;
+}
+
+static void graph_widget_init(GraphWidget *graph) {
+ /*Get a graph.*/
+ graph->graph = graph_new();
+}
+
+GtkWidget *graph_widget_new(void) {
+ return g_object_new(GRAPH_WIDGET_TYPE, NULL);
+}
+
+Graph* graph_widget_get_graph(GraphWidget* gw) {
+ return gw->graph;
+}
+
--- /dev/null
+/*
+** Graph.h
+**
+** Made by Johnny Q. Hacker
+** Login <solarion@johnathan>
+**
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+** Started on Thu Jul 17 10:51:32 2008 Johnny Q. Hacker
+** Last update Thu Oct 8 14:28:34 2009 Johnny Q. Hacker
+*/
+
+#ifndef GRAPHWIDGET_H_
+#define GRAPHWIDGET_H_
+
+#include <gtk/gtkdrawingarea.h>
+#include <graph.h>
+
+typedef struct _GraphWidget {
+ GtkDrawingArea parent_instance;
+ Graph *graph;
+} GraphWidget;
+
+typedef struct _GraphWidgetClass {
+ GtkDrawingAreaClass parent_class;
+} GraphWidgetClass;
+
+#define GRAPH_WIDGET_TYPE (graph_widget_get_type())
+#define GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRAPH_WIDGET_TYPE, GraphWidget))
+#define GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GRAPH_WIDGET, GraphWidgetClass))
+#define IS_GRAPH_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRAPH_WIDGET_TYPE))
+#define IS_GRAPH_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GRAPH_WIDGET_CLASS_TYPE))
+#define GRAPH_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GRAPH_WIDGET, GraphWidgetClass))
+
+GtkWidget* graph_widget_new(void);
+
+Graph* graph_widget_get_graph(GraphWidget* gw);
+
+#endif /* !GRAPHWIDGET_H_ */
--- /dev/null
+/*
+ * matdb-dotcode: reads in Craig's Dotcode materials database.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <matdb-dotcode.h>
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+#ifdef DEBUG_2
+#undef DEBUG_2
+#endif
+
+/*Functions to be used by the hash.*/
+static void destroy_string(gpointer data) {
+ free((char*)data);
+}
+static void destroy_double(gpointer data){
+ free((double*)data);
+}
+static void destroy_inner_bowhash(gpointer data) {
+ g_hash_table_unref(data);
+}
+
+int insert_into_matdb(struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow) {
+ if((*mat) != NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
+#endif
+ g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
+ (*mat) = NULL;
+ }
+ if((*bow) != NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
+#endif
+ /*Inner table*/
+ GHashTable *it;
+ if((it=g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
+ if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
+ (*bow) = NULL;
+ return 1;
+ }
+ g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
+ #ifdef DEBUG
+ fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
+ #endif
+ }
+ g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
+ (*bow) = NULL;
+ }
+ return 0;
+}
+
+/*Removes leading and trailing whitespace, comments, and reduces
+ redundant whitespace down to one tab, makes an empty line an empty string.*/
+static void prettify_line(char *line) {
+ register char *look;
+ register char *write;
+ register int in_whitespace;
+ register int leading_whitespace;
+ for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
+#ifdef DEBUG_2
+ fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
+#endif
+ if(*look == '#') {
+#ifdef DEBUG_2
+ fprintf(stderr, "comment\n");
+#endif
+ *write = '\0';
+ break;
+ }
+ switch(*look) {
+ case ' ':
+ case '\n':
+ case '\t':
+#ifdef DEBUG_2
+ fprintf(stderr, "whitespace\n");
+#endif
+ if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
+ in_whitespace=1;
+ break;
+ default:
+#ifdef DEBUG_2
+ fprintf(stderr, "default\n");
+#endif
+ *write++ = *look;
+ in_whitespace=leading_whitespace=0;
+ }
+ }
+ *write='\0';
+ for(look=write=line; *look != '\0'; look++) {
+ switch(*look) {
+ case ' ':
+ case '\n':
+ case '\t':
+ if(*(look+1) == '\0') {
+ *look = '\0';
+ }
+ }
+ }
+}
+
+/*Error values:
+ * 0: success
+ * 1: failure malloc'ing / initializing mdb struct
+ * 2: failure opening file.
+ * 4: failure reading line.
+ * 8: warning reading line: no tab separator (line parsing error)
+ * 16: warning reading line: bad section declaration
+ * 32: warning reading line: unable to allocate material struct.
+ * 64: warning reading line: ignored line (unallocated material struct)
+ * 128: warning reading line: unable to allocate bowing struct
+ * 256: warning reading line: ignored line (unallocated bowing struct)
+ * 512: warning reading file: improper section detected (programming
+ * error)
+ *1024: warning reading file: no : separator in bowing materials
+ * description.
+ *2048: warning reading file: unable to read numeric value for property.
+ */
+struct matdb* read_matdb_dotcode(const GString *name, int* err) {
+#ifdef DEBUG_2
+ fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
+#endif
+ *err=0;
+ struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
+ if(mdb == NULL) {*err = 1; return NULL;}
+
+ double *value;
+ if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
+ *err = 1;
+ free(mdb);
+ return NULL;
+ }
+ if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
+ *err = 1;
+ g_hash_table_unref(mdb->materials);
+ free(mdb);
+ return NULL;
+ }
+ struct matdb_material *mat = NULL;
+ struct matdb_bowing *bow = NULL;
+ /*Valid sections:
+ * 0 (no/global section)
+ * 1 (material)
+ * 2 (bow)
+ */
+ int section=0;
+ int n;
+ char *line;
+ FILE *infile = fopen(name->str, "r");
+ if(infile == NULL) {
+ g_hash_table_unref(mdb->materials);
+ g_hash_table_unref(mdb->bowings);
+ free(mdb);
+ *err=2;
+ return NULL;
+#ifdef DEBUG_2
+ }else{
+ fprintf(stderr, "infile=%x\n", (unsigned int)infile);
+#endif
+ }
+ int val;
+ while(!feof(infile)) {
+#ifdef DEBUG
+ fprintf(stderr, "mat=%x(%s), bow=%x(%s:%s)\n", (unsigned int)mat, mat?mat->name->str:"", (unsigned int)bow, bow?bow->from->str:"", bow?bow->to->str:"");
+#endif
+ line=NULL;
+ if((val = getline(&line, &n, infile)) == -1) {
+#ifdef DEBUG_2
+ fprintf(stderr, "getline returned %d\n", val);
+#endif
+ if(!feof(infile)) *err = 4;
+ //fclose(infile);
+ break;
+ }
+#ifdef DEBUG_2
+ fprintf(stderr, "line=(%s)\n", line);
+#endif
+ prettify_line(line);
+#ifdef DEBUG
+ fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
+#endif
+ if(*line == '\0') {
+ free(line);
+ continue;
+ }
+ char *i = index(line, '\t');
+ if(i == NULL) {
+ *err &= 8;
+ }
+ *i++ = '\0';
+ /*At this point, we have line which stores the first word on the
+ line, and i which stores the second word on the line.
+ */
+ char *to;
+ GHashTable *ht;
+#ifdef DEBUG_2
+ fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
+#endif
+ /*If we have a material or bowing underway, save it off*/
+ if(strcasecmp(line, "material") == 0) {
+ insert_into_matdb(mdb, &mat, &bow);
+ if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
+ *err &= 32;
+ }
+ if((mat->name = g_string_new(i)) == NULL) {
+ *err &= 32;
+ free(mat);
+ section=0;
+ continue;
+ }
+ if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
+ *err &= 32;
+ g_string_free(mat->name, TRUE);
+ free(bow);
+ section=0;
+ continue;
+ }
+#ifdef DEBUG_2
+ fprintf(stderr, "new material (%s):\n", i);
+#endif
+ section=1;
+ }else if(strcasecmp(line, "bow") == 0) {
+ insert_into_matdb(mdb, &mat, &bow);
+ if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
+ *err &= 128;
+ }
+ if((to = index(i, ':')) == NULL) {
+ *err &= 1024;
+ free(bow);
+ section=0;
+ continue;
+ }
+ *to++ = '\0';
+ /*Same trick as before, but i now stores the from material,
+ and to the to material
+ */
+ if((bow->from = g_string_new(i)) == NULL) {
+ *err &= 128;
+ free(bow);
+ section=0;
+ continue;
+ }
+ if((bow->to = g_string_new(to)) == NULL) {
+ *err &= 128;
+ g_string_free(bow->from, TRUE);
+ free(bow);
+ section=0;
+ continue;
+ }
+ if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
+ *err &= 128;
+ g_string_free(bow->to, TRUE);
+ g_string_free(bow->from, TRUE);
+ free(bow);
+ section=0;
+ continue;
+ }
+#ifdef DEBUG_2
+ fprintf(stderr, "new bowing (%s:%s):\n", i, to);
+#endif
+ section=2;
+ }else{
+ #ifdef DEBUG
+ fprintf(stderr, "\t%d/%s\t", section, line);
+ #endif
+ /*Process a property.*/
+ switch(section) {
+ case 1:
+ #ifdef DEBUG
+ fprintf(stderr, "(1)\t");
+ #endif
+ ht = mat->properties;
+ break;
+ case 2:
+ #ifdef DEBUG
+ fprintf(stderr, "(2)\t");
+ #endif
+ ht = bow->properties;
+ break;
+ default:
+ #ifdef DEBUG
+ fprintf(stderr, "(default)\t");
+ #endif
+ *err &= 16;
+ section = 0;
+ }
+ if(section == 0) {
+ #ifdef DEBUG
+ fprintf(stderr, "section was 0\n");
+ #endif
+ continue;
+ }
+ if((value = (double*)malloc(sizeof(double))) == NULL) {
+ *err &= 2048;
+ #ifdef DEBUG
+ fprintf(stderr, "malloc of value failed\n");
+ #endif
+ continue;
+ }
+ int num;
+ if((num=sscanf(i, " %lg", value)) != 1) {
+ *err &= 2048;
+ free(value);
+ #ifdef DEBUG
+ fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
+ #endif
+ continue;
+ }
+ g_hash_table_insert(ht, g_strdup(line), value);
+#ifdef DEBUG
+ fprintf(stderr, "%g(%s)\n", *value, line);
+#endif
+ }
+ free(line);
+ line=i=to=NULL;
+ value=NULL;
+ }
+ fclose(infile);
+ insert_into_matdb(mdb, &mat, &bow);
+ return mdb;
+}
+
--- /dev/null
+/*
+ * matdb-dotcode: reads in Craig's Dotcode materials database.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MATDB_DOTCODE_H_
+#define MATDB_DOTCODE_H_
+
+#include <matdb.h>
+
+struct matdb* read_matdb_dotcode(const GString *name, int *err);
+
+#endif
--- /dev/null
+/*
+ * matdb: generic materials database information.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <matdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void print_property(gpointer key, gpointer value, gpointer user_data) {
+ fprintf(stderr, "\t\t%s=%g:\n", (char*)key, *(double*)value);
+}
+static void print_inner_bowing(gpointer key, gpointer value, gpointer user_data) {
+ struct matdb_bowing *bowing = (struct matdb_bowing*)value;
+ fprintf(stderr, "\tbowing %s:%s[%s:%s]:\n", bowing->from->str, bowing->to->str, (char*)user_data, (char*)key);
+ g_hash_table_foreach(bowing->properties, &print_property, NULL);
+}
+static void print_material(gpointer key, gpointer value, gpointer user_data) {
+ struct matdb_material *mat = (struct matdb_material*)value;
+ fprintf(stderr, "\tmaterial %s(%s):\n", mat->name->str, (char*)key);
+ g_hash_table_foreach(mat->properties, &print_property, NULL);
+}
+static void print_bowing(gpointer key, gpointer value, gpointer user_data) {
+ GHashTable *ht = value;
+ g_hash_table_foreach(ht, &print_inner_bowing, key);
+}
+
+void print_matdb(const struct matdb *mdb) {
+ fprintf(stderr, "matdb:\n");
+ g_hash_table_foreach(mdb->materials, &print_material, NULL);
+ g_hash_table_foreach(mdb->bowings, &print_bowing, NULL);
+}
+
+void destroy_material_gpointer(gpointer data) {
+ destroy_material((struct matdb_material *)data);
+}
+void destroy_bowing_gpointer(gpointer data) {
+ destroy_bowing((struct matdb_bowing *)data);
+}
+void destroy_material(struct matdb_material *mat) {
+ #ifdef DEBUG
+ fprintf(stderr, "destroy_material\n");
+ #endif
+ g_string_free(mat->name, TRUE);
+ g_hash_table_unref(mat->properties);
+ free(mat);
+}
+void destroy_bowing(struct matdb_bowing *bow) {
+ #ifdef DEBUG
+ fprintf(stderr, "destroy_bowing\n");
+ #endif
+ g_string_free(bow->from, TRUE);
+ g_string_free(bow->to, TRUE);
+ g_hash_table_unref(bow->properties);
+ free(bow);
+}
--- /dev/null
+/*
+ * matdb: generic materials database information.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MATDB_H_
+#define MATDB_H_
+
+#include <glib-2.0/glib.h>
+
+struct matdb_material {
+ GString *name;
+ GHashTable *properties;
+};
+
+struct matdb_bowing {
+ GString *from;
+ GString *to;
+ GHashTable *properties;
+};
+
+struct matdb {
+ GHashTable *materials;
+ GHashTable *bowings;
+};
+
+void print_matdb(const struct matdb *mdb);
+void destroy_material_gpointer(gpointer data);
+void destroy_bowing_gpointer(gpointer data);
+void destroy_material(struct matdb_material *mat);
+void destroy_bowing(struct matdb_bowing *bow);
+
+#endif
--- /dev/null
+/*
+** scdataviz.c
+**
+** Made by (Johnny Q. Hacker)
+** Login <solarion@johnathan>
+**
+** Holds the SC graphing widget.
+
+
+
+ Copyright (C) 2008 Joseph Pingenot
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+** Started on Thu Jul 17 11:03:27 2008 Johnny Q. Hacker
+** Last update Thu Oct 8 19:13:57 2009 Johnny Q. Hacker
+*/
+
+#include <gtk/gtk.h>
+#include <graphwidget.h>
+#include <matdb-dotcode.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#define DEBUG_SHOW_ONLY_BOWED
+
+struct xy_properties {
+ GString *xprop;
+ GString *yprop;
+ Graph *graph;
+ struct matdb *mdb;
+ struct matdb_material *mat;
+};
+
+static void lookup_xy(GHashTable* propts, GString* xprop, GString* yprop, double **x, double **y) {
+ *x=g_hash_table_lookup(propts, xprop->str);
+ *y=g_hash_table_lookup(propts, yprop->str);
+}
+
+static void put_mat_in_graph(gpointer key, gpointer value, gpointer user_data) {
+ struct xy_properties *propmap = user_data;
+ struct matdb_material *mat = value;
+ if(!strcasecmp(mat->name->str, "vacuum")) return;
+ if(!strcasecmp(mat->name->str, "pvb")) return;
+ double *x, *y;
+ #ifdef DEBUG_ASSIGNMENT
+ fprintf(stderr, "put_mat_in_graph(%s) (x->%s, y->%s): ", (char*)key, propmap->xprop->str, propmap->yprop->str);
+ #endif
+ lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &x, &y);
+ if((x != NULL) && (y != NULL)) {
+ graph_add_point(propmap->graph, *x, *y, mat->name);
+ #ifdef DEBUG_ASSIGNMENT
+ fprintf(stderr, "added (x->%s=%g, y->%s=%g)\n", propmap->xprop->str, *x, propmap->yprop->str, *y);
+ }else{
+ fprintf(stderr, "no such properties (x->%s, y->%s)\n", propmap->xprop->str, propmap->yprop->str);
+ #endif
+ }
+}
+
+static void inner_link_materials(gpointer key, gpointer value, gpointer user_data) {
+ struct xy_properties *propmap = user_data;
+ struct matdb_material *mat = value;
+ if(!strcasecmp(mat->name->str, "vacuum")) return;
+ if(!strcasecmp(mat->name->str, "pvb")) return;
+ if(g_string_equal(mat->name, propmap->mat->name)) return;
+ struct graph_line *l = (struct graph_line *)malloc(sizeof(struct graph_line));
+ if(l == NULL) return;
+ struct matdb_bowing *bow = NULL;
+ GHashTable *subtable;
+ double *p0_x, *p0_y, *p1_x, *p1_y, *p3_x, *p3_y;
+ lookup_xy(propmap->mat->properties, propmap->xprop, propmap->yprop, &p0_x, &p0_y);
+ lookup_xy(mat->properties, propmap->xprop, propmap->yprop, &p3_x, &p3_y);
+#ifdef DEBUG_ASSIGNMENT
+ fprintf(stderr, "%s:%s x=%s y=%s p0(%g,%g) p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, propmap->xprop->str, propmap->yprop->str, (p0_x)?*p0_x:0, (p0_y)?*p0_y:0, (p3_x)?*p3_x:0, (p3_y)?*p3_y:0);
+#endif
+ if((p0_x != NULL) && (p0_y != NULL) && (p3_x != NULL) && (p3_y != NULL)) {
+ l->p0_x = *p0_x;
+ l->p0_y = *p0_y;
+ l->p3_x = *p3_x;
+ l->p3_y = *p3_y;
+ if((subtable = g_hash_table_lookup(propmap->mdb->bowings, propmap->mat->name->str)) == NULL) {
+ /*Try the other way 'round*/
+ if((subtable = g_hash_table_lookup(propmap->mdb->bowings, mat->name->str) )
+ != NULL) {
+ bow = g_hash_table_lookup(subtable, propmap->mat->name->str);
+ }
+ }else{
+ bow = g_hash_table_lookup(subtable, mat->name->str);
+ }
+ if(bow != NULL) {
+ if((p1_x = g_hash_table_lookup(bow->properties, propmap->xprop->str)) != NULL) {
+ l->p1_x = *p1_x/2.0;
+ graph_bezier_quadratic_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+ }else{
+ graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+ }
+ if((p1_y = g_hash_table_lookup(bow->properties, propmap->yprop->str)) != NULL) {
+ l->p1_y = *p1_y/2.0;
+ graph_bezier_quadratic_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+ }else{
+ graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+ }
+ }else{
+ #ifdef DEBUG_SHOW_ONLY_BOWED
+ free(l);
+ return;
+ #endif
+ graph_bezier_linear_to_cubic(l->p0_x, l->p3_x, &(l->p1_x), &(l->p2_x));
+ graph_bezier_linear_to_cubic(l->p0_y, l->p3_y, &(l->p1_y), &(l->p2_y));
+ }
+ #ifdef DEBUG_ASSIGNMENT
+ fprintf(stderr, "%s:%s p0(%g,%g) p1(%g,%g) p2(%g,%g), p3(%g,%g)\n", propmap->mat->name->str, mat->name->str, l->p0_x, l->p0_y, l->p1_x, l->p1_y, l->p2_x, l->p2_y, l->p3_x, l->p3_y);
+ #endif
+ graph_add_graph_line(propmap->graph, l);
+ }else{
+ free(l);
+ }
+}
+
+static void link_materials(gpointer key, gpointer value, gpointer user_data) {
+ struct xy_properties *propmap = user_data;
+ struct matdb_material *mat = value;
+ if(!strcasecmp(mat->name->str, "vacuum")) return;
+ if(!strcasecmp(mat->name->str, "pvb")) return;
+ propmap->mat = mat;
+ g_hash_table_foreach(propmap->mdb->materials, &inner_link_materials, propmap);
+}
+
+int main(int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *graph;
+ GString *file = g_string_new("matdb.txt");
+ int err=0;
+ struct matdb *mdb = read_matdb_dotcode(file, &err);
+ //fprintf(stderr, "read_matdb_dotcode(%s, %d)=%x", file->str, err,
+ //(int)mdb);
+ //fprintf(stderr, "err=%d\n", err);
+ //print_matdb(mdb);
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ graph = graph_widget_new();
+
+ struct xy_properties propmap;
+ propmap.xprop = g_string_new("a_lc");
+ propmap.yprop = g_string_new("E_g_Gamma");
+ propmap.graph = graph_widget_get_graph(GRAPH_WIDGET(graph));
+ propmap.mdb = mdb;
+ g_hash_table_foreach(mdb->materials, &put_mat_in_graph, &propmap);
+ //graph_add_linear_connectors(propmap.graph);
+ g_hash_table_foreach(mdb->materials, &link_materials, &propmap);
+ graph_autoset_xaxis(propmap.graph, propmap.xprop);
+ graph_autoset_yaxis(propmap.graph, propmap.yprop);
+
+ //Connect signals
+ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
+
+ gtk_container_add(GTK_CONTAINER(window), graph);
+ /*
+ graph_add_point(graph_widget_get_graph(graph), 5, 3);
+ graph_add_point(graph_widget_get_graph(graph), 8, 12);
+ graph_add_point(graph_widget_get_graph(graph), 11, 48);
+ */
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}