Initial commit.

This commit is contained in:
Martin Preuss
2022-03-24 20:49:19 +01:00
commit d0490c01db
56 changed files with 7863 additions and 0 deletions

11
src/lib/0BUILD Normal file
View File

@@ -0,0 +1,11 @@
<?xml?>
<gwbuild>
<subdirs>
aqdiagram
</subdirs>
</gwbuild>

11
src/lib/Makefile.am Normal file
View File

@@ -0,0 +1,11 @@
SUBDIRS=aqdiagram
typefiles:
for d in $(SUBDIRS); do \
$(MAKE) -C $$d typefiles; \
done
typedefs:
for d in $(SUBDIRS); do \
$(MAKE) -C $$d typedefs; \
done

79
src/lib/aqdiagram/0BUILD Normal file
View File

@@ -0,0 +1,79 @@
<?xml?>
<gwbuild>
<target type="InstallLibrary" name="aqdiagram"
so_current="$(project_so_current)"
so_age="$(project_so_age)"
so_revision="$(project_so_revision)"
install="$(libdir)" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)/src/lib
-I$(topbuilddir)/src/lib
-I$(topbuilddir)
-I$(topsrcdir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
--include=$(builddir)/../types
--include=$(topsrcdir)/src/lib/typemaker2/c
--include=$(topbuilddir)/src/lib/typemaker2/c
</includes>
<define name="BUILDING_AQDIAGRAM" />
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
--api=AQDG_API
</setVar>
<headers >
aqdiagram.h
aqdg_api.h
</headers>
<sources>
aqdiagram.c
</sources>
<data DIST="FALSE" generated="TRUE" >
</data>
<extradist>
</extradist>
<useTargets>
aqdg_draw
aqdg_graph
</useTargets>
<libraries>
$(gwenhywfar_libs)
$(cairo_libs)
$(zlib_libs)
</libraries>
<subdirs>
<!-- placement -->
draw
graph
</subdirs>
</target>
</gwbuild>

View File

@@ -0,0 +1,62 @@
SUBDIRS=draw graph
AM_CPPFLAGS=$(gwenhywfar_includes) -I$(srcdir)/.. -I$(builddir)/.. -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CFLAGS=$(visibility_cflags)
DEFS+=\
-DBUILDING_AQDIAGRAM \
-DLOCALEDIR=\"@aqdiagram_locale_searchdir@\" \
-DAQDIAGRAM_DATA_DIR=\"$(aqdiagram_data_searchdir)\"
noinst_LTLIBRARIES=libaqdiagram.la
libaqdiagram_la_SOURCES=\
aqdiagram.c
iheaderdir=${includedir}/aqhmcontrol
iheader_HEADERS=$(build_headers_pub)\
aqdiagram.h \
aqdg_api.h
noinst_HEADERS=$(build_headers_priv)
libaqdiagram_la_LIBADD=$(gwenhywfar_libs)\
draw/libaqdg_draw.la \
graph/libaqdg_graph.la
EXTRA_DIST=$(typefiles) $(built_sources) $(build_headers)
clean_build_files:
rm -f $(built_sources) $(build_headers)
format_build_files:
for f in $(built_sources) $(build_headers); do \
astyle --style=linux -s2 --min-conditional-indent=0 --indent-labels --pad-oper -a --suffix=none $$f; \
done
typefiles:
for d in $(SUBDIRS); do \
$(MAKE) -C $$d typefiles; \
done
typedefs:
for d in $(SUBDIRS); do \
$(MAKE) -C $$d typedefs; \
done

View File

@@ -0,0 +1,59 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_API_H
#define AQDG_API_H
#ifdef BUILDING_AQDIAGRAM
# /* building AqGmControl */
# if AQDG_SYS_IS_WINDOWS
# /* for windows */
# ifdef __declspec
# define AQDG_API __declspec (dllexport)
# else /* if __declspec */
# define AQDG_API
# endif /* if NOT __declspec */
# else
# /* for non-win32 */
# ifdef GCC_WITH_VISIBILITY_ATTRIBUTE
# define AQDG_API __attribute__((visibility("default")))
# else
# define AQDG_API
# endif
# endif
#else
# /* not building AqFinance */
# if AQDG_SYS_IS_WINDOWS
# /* for windows */
# ifdef __declspec
# define AQDG_API __declspec (dllimport)
# else /* if __declspec */
# define AQDG_API
# endif /* if NOT __declspec */
# else
# /* for non-win32 */
# define AQDG_API
# endif
#endif
#ifdef GCC_WITH_VISIBILITY_ATTRIBUTE
# define AQDG_EXPORT __attribute__((visibility("default")))
# define AQDG_NOEXPORT __attribute__((visibility("hidden")))
#else
# define AQDG_EXPORT
# define AQDG_NOEXPORT
#endif
#endif

View File

@@ -0,0 +1,130 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./aqdiagram.h"
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/pathmanager.h>
#include <gwenhywfar/debug.h>
int AQDG_Init()
{
int rv;
const char *s;
rv=GWEN_Init();
if (rv) {
DBG_ERROR(AQDG_LOGDOMAIN, "here (%d)", rv);
return rv;
}
if (!GWEN_Logger_IsOpen(AQDG_LOGDOMAIN)) {
GWEN_Logger_Open(AQDG_LOGDOMAIN,
"aqdiagram", 0,
GWEN_LoggerType_Console,
GWEN_LoggerFacility_User);
}
s=getenv("AQDG_LOGLEVEL");
if (s && *s) {
GWEN_LOGGER_LEVEL ll;
ll=GWEN_Logger_Name2Level(s);
GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, ll);
}
else
GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, GWEN_LoggerLevel_Notice);
DBG_INFO(AQDG_LOGDOMAIN,
"AqDiagram v%s: initialising",
AQDG_VERSION_FULL_STRING);
/* define locale paths */
GWEN_PathManager_DefinePath(AQDG_PM_LIBNAME, AQDG_PM_LOCALEDIR);
#if defined(OS_WIN32) || defined(ENABLE_LOCAL_INSTALL)
/* add folder relative to EXE */
GWEN_PathManager_AddRelPath(AQDG_PM_LIBNAME,
AQDG_PM_LIBNAME,
AQDG_PM_LOCALEDIR,
LOCALEDIR,
GWEN_PathManager_RelModeExe);
#else
/* add absolute folder */
GWEN_PathManager_AddPath(AQDG_PM_LIBNAME,
AQDG_PM_LIBNAME,
AQDG_PM_LOCALEDIR,
LOCALEDIR);
#endif
/* define data paths */
GWEN_PathManager_DefinePath(AQDG_PM_LIBNAME, AQDG_PM_DATADIR);
#if defined(OS_WIN32) || defined(ENABLE_LOCAL_INSTALL)
/* add folder relative to EXE */
GWEN_PathManager_AddRelPath(AQDG_PM_LIBNAME,
AQDG_PM_LIBNAME,
AQDG_PM_DATADIR,
AQDIAGRAM_DATA_DIR,
GWEN_PathManager_RelModeExe);
#else
/* add absolute folder */
GWEN_PathManager_AddPath(AQDG_PM_LIBNAME,
AQDG_PM_LIBNAME,
AQDG_PM_DATADIR,
AQDIAGRAM_DATA_DIR);
#endif
if (1) {
GWEN_STRINGLIST *sl=GWEN_PathManager_GetPaths(AQDG_PM_LIBNAME, AQDG_PM_LOCALEDIR);
if (sl) {
const char *localedir=GWEN_StringList_FirstString(sl);
rv=GWEN_I18N_BindTextDomain_Dir(PACKAGE, localedir);
if (rv) {
DBG_ERROR(AQDG_LOGDOMAIN, "Could not bind textdomain (%d)", rv);
}
else {
rv=GWEN_I18N_BindTextDomain_Codeset(PACKAGE, "UTF-8");
if (rv) {
DBG_ERROR(AQDG_LOGDOMAIN, "Could not set codeset (%d)", rv);
}
}
GWEN_StringList_free(sl);
}
}
return 0;
}
int AQDG_Fini()
{
/* undefine our own paths */
GWEN_PathManager_UndefinePath(AQDG_PM_LIBNAME, AQDG_PM_LOCALEDIR);
GWEN_PathManager_UndefinePath(AQDG_PM_LIBNAME, AQDG_PM_DATADIR);
/* remove AqBanking additions to all pathmanagers */
GWEN_PathManager_RemovePaths(AQDG_PM_LIBNAME);
GWEN_Logger_Close(AQDG_LOGDOMAIN);
GWEN_Fini();
return 0;
}

View File

@@ -0,0 +1,50 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_AQDIAGRAM_H
#define AQDG_AQDIAGRAM_H
#define AQDG_LOGDOMAIN "aqdiagram"
#include <aqdiagram/aqdg_api.h>
#include <gwenhywfar/i18n.h>
#include <inttypes.h>
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
#define AQDG_PM_LIBNAME "aqhmcontrol"
#define AQDG_PM_SYSCONFDIR "sysconfdir"
#define AQDG_PM_DATADIR "datadir"
#define AQDG_PM_LOCALEDIR "localedir"
#ifdef __cplusplus
extern "C" {
#endif
AQDG_API int AQDG_Init();
AQDG_API int AQDG_Fini();
#ifdef __cplusplus
}
#endif
#endif

21
src/lib/aqdiagram/draw/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
aqdg_context.tm2
aqdg_context_list.tm2
aqdg_context_list2.tm2
context.c
context.h
context_p.h
aqdg_font.tm2
aqdg_font_list.tm2
aqdg_font_list2.tm2
font.c
font.h
font_p.h
aqdg_pen.tm2
aqdg_pen_list.tm2
aqdg_pen_list2.tm2
pen.c
pen.h
pen_p.h

View File

@@ -0,0 +1,105 @@
<?xml?>
<gwbuild>
<target type="ConvenienceLibrary" name="aqdg_draw" >
<includes type="c" >
$(gwenhywfar_cflags)
$(cairo_cflags)
-I$(topsrcdir)/src/lib
-I$(topbuilddir)/src/lib
-I$(topbuilddir)
-I$(topsrcdir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
--include=$(builddir)/../types
--include=$(topsrcdir)/src/lib/typemaker2/c
--include=$(topbuilddir)/src/lib/typemaker2/c
</includes>
<define name="BUILDING_AQDIAGRAM" />
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
--api=AQDG_API
</setVar>
<setVar name="local/typefiles" >
context.xml
font.xml
pen.xml
</setVar>
<setVar name="local/built_sources" >
context.c
font.c
pen.c
</setVar>
<setVar name="local/built_headers_pub">
context.h
font.h
pen.h
</setVar>
<setVar name="local/built_headers_priv" >
context_p.h
font_p.h
pen_p.h
</setVar>
<headers dist="false" install="$(pkgincludedir)">
$(local/built_headers_pub)
</headers>
<headers dist="false" >
$(local/built_headers_priv)
</headers>
<headers dist="true" install="$(pkgincludedir)">
context_cairo.h
</headers>
<headers dist="true" >
context_cairo_p.h
</headers>
<sources>
$(local/typefiles)
$(local/sources)
</sources>
<extradist>
</extradist>
<data DIST="FALSE" generated="TRUE" >
aqdg_context.tm2 aqdg_context_list.tm2 aqdg_context_list2.tm2
aqdg_font.tm2 aqdg_font_list.tm2 aqdg_font_list2.tm2
aqdg_pen.tm2 aqdg_pen_list.tm2 aqdg_pen_list2.tm2
</data>
<useTargets>
</useTargets>
<subdirs>
</subdirs>
</target>
</gwbuild>

View File

@@ -0,0 +1,87 @@
AM_CPPFLAGS=$(gwenhywfar_includes) -I$(srcdir)/.. -I$(builddir)/.. -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CFLAGS=$(visibility_cflags)
DEFS+=\
-DBUILDING_AQDIAGRAM \
-DLOCALEDIR=\"@aqdatabase_locale_searchdir@\" \
-DAQDIAGRAM_DATA_DIR=\"$(aqdiagram_data_searchdir)\"
typefiles=\
context.xml \
font.xml \
pen.xml
built_sources=\
context.c \
font.c \
pen.c
build_headers_priv=\
context_p.h \
font_p.h \
pen_p.h
build_headers_pub=\
context.h \
font.h \
pen.h
build_headers=$(build_headers_priv) $(build_headers_pub)
noinst_LTLIBRARIES=libaqdg_draw.la
libaqdg_draw_la_SOURCES=$(built_sources)\
context_cairo.c
iheaderdir=${includedir}/aqdiagram
iheader_HEADERS=$(build_headers_pub)\
context_cairo.h
noinst_HEADERS=$(build_headers_priv)
EXTRA_DIST=$(typefiles) $(built_sources) $(build_headers)
clean_build_files:
rm -f $(built_sources) $(build_headers)
format_build_files:
for f in $(built_sources) $(build_headers); do \
astyle --style=linux -s2 --min-conditional-indent=0 --indent-labels --pad-oper -a --suffix=none $$f; \
done
build_sources: $(built_sources)
list='$(SUBDIRS)'; for d in $$list; do \
$(MAKE) -C $$d build_sources; \
done ;
sources:
for f in $(libaqdg_draw_la_SOURCES); do \
echo $(subdir)/$$f >>$(top_srcdir)/i18nsources; \
done
for d in $(SUBDIRS); do \
$(MAKE) -C $$d sources; \
done
typefiles: $(typefiles)
$(typemaker2_exe) -D AQDG_API -I $(top_srcdir)/src/typemaker2/c -I $(gwenhywfar_dir)/share/gwenhywfar/typemaker2/c -I $(srcdir) --destfolder="$(srcdir)" $(typefiles)
typedefs: $(typefiles)
$(typemaker2_exe) --defs-only -D AQDG_API -I $(top_srcdir)/src/typemaker2/c -I $(gwenhywfar_dir)/share/gwenhywfar/typemaker2/c -I $(srcdir) --destfolder="$(srcdir)" $(typefiles)

View File

@@ -0,0 +1 @@
Previous af_graphics

View File

@@ -0,0 +1,286 @@
<?xml?>
<tm2>
<type id="AQDG_DRAW_CONTEXT" type="pointer">
<descr>
This class contains a data set (containing image info, series and study lists).
The coordinate system starts with x=0, y=0 in the upper left corner.
</descr>
<lang id="c">
<identifier>AQDG_DRAW_CONTEXT</identifier>
<prefix>AQDG_Draw_Context</prefix>
<baseFileName>context</baseFileName>
<flags>
with_list1
with_list2
with_inherit
with_refcount
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
</headers>
</lang>
<defines>
<define id="AQDG_DRAW_CONTEXT_RTFLAGS" prefix="AQDG_DRAW_CONTEXT_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
</define>
</defines>
<enums>
<enum id="AQDG_SLANT" prefix="AQDG_Slant_">
<item name="none" value="0">
<descr>none</descr>
</item>
<item name="italic">
<descr>italic</descr>
</item>
</enum>
<enum id="AQDG_WEIGHT" prefix="AQDG_Weight_">
<item name="none" value="0">
<descr>none</descr>
</item>
<item name="bold">
<descr>bold</descr>
</item>
</enum>
<enum id="AQDG_DIRECTION" prefix="AQDG_Direction_">
<item name="vertical">
<descr>draw vertically</descr>
</item>
<item name="horizontal">
<descr>draw horizontally</descr>
</item>
</enum>
<enum id="AQDG_DASH" prefix="AQDG_Dash_">
<item name="none" value="0">
<descr>no dash</descr>
</item>
<item name="Format1">
<descr>Dash format 1</descr>
</item>
<item name="Format2">
<descr>Dash format 2</descr>
</item>
<item name="Format3">
<descr>Dash format 3</descr>
</item>
<item name="Format4">
<descr>Dash format 4</descr>
</item>
<item name="Format5">
<descr>Dash format 5</descr>
</item>
<item name="Format6">
<descr>Dash format 6</descr>
</item>
<item name="Format7">
<descr>Dash format 7</descr>
</item>
<item name="Format8">
<descr>Dash format 8</descr>
</item>
</enum>
</enums>
<members>
<member name="id" type="int" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>volatile with_getbymember</flags>
<access>public</access>
</member>
<member name="typeName" type="char_ptr" maxlen="64" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
</member>
</members>
<virtualFns>
<fn name="penCreate" location="post" >
<descr>Creates a pen from the given info.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="uint32_t" name="frontColor">
<descr>Foreground colour used for drawing</descr>
</param>
<param type="int" name="lineWidth"/>
<param type="int" name="dashType"/>
</params>
</fn>
<fn name="penRelease" location="post" >
<descr>Release the given pen.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="pen"/>
</params>
</fn>
<fn name="drawLine" location="post" >
<descr>Draws a line from xStart/yStart to xEnd/yEnd using the given pen.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="pen">
<descr>Pen to be used.</descr>
</param>
<param type="int" name="xStart"/>
<param type="int" name="yStart"/>
<param type="int" name="xEnd"/>
<param type="int" name="yEnd"/>
</params>
</fn>
<fn name="drawRect" location="post" >
<descr>Draws a non-filled rectangle.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="pen">
<descr>Pen to be used.</descr>
</param>
<param type="int" name="x"/>
<param type="int" name="y"/>
<param type="int" name="width"/>
<param type="int" name="height"/>
</params>
</fn>
<fn name="drawFilledRect" location="post" >
<descr>Draws a filled rectangle.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="pen">
<descr>Pen to be used.</descr>
</param>
<param type="int" name="x"/>
<param type="int" name="y"/>
<param type="int" name="width"/>
<param type="int" name="height"/>
</params>
</fn>
<fn name="fontCreate" location="post" >
<descr>Creates a font from the given info.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="const char*" name="fontName"/>
<param type="int" name="fontSize"/>
<param type="int" name="fontSlant"/>
<param type="int" name="fontWeight"/>
</params>
</fn>
<fn name="fontRelease" location="post" >
<descr>Releases the given font.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="font"/>
</params>
</fn>
<fn name="drawText" location="post" >
<descr>Draws the given text at the given position using the given font and pen.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="pen">
<descr>Pen to be used.</descr>
</param>
<param type="int" name="font">
<descr>Font to be used.</descr>
</param>
<param type="int" name="direction"/>
<param type="int" name="x"/>
<param type="int" name="y"/>
<param type="const char*" name="text"/>
</params>
</fn>
<fn name="getTextWidth" location="post" >
<descr>Query the width used for the given text using the given font.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="font"/>
<param type="const char*" name="text"/>
</params>
</fn>
<fn name="getTextHeight" location="post" >
<descr>Query the height used for the given text using the given font.</descr>
<access>public</access>
<defaultReturnValue>GWEN_ERROR_NOT_IMPLEMENTED</defaultReturnValue>
<returnType>int</returnType>
<params>
<param type="int" name="font"/>
<param type="const char*" name="text"/>
</params>
</fn>
<fn name="finish" location="post" >
<descr>Call this when your are finished drawing.</descr>
<access>public</access>
<defaultReturnValue>0</defaultReturnValue>
<returnType>int</returnType>
</fn>
</virtualFns>
</type>
</tm2>

View File

@@ -0,0 +1,769 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "context_cairo_p.h"
#include <gwenhywfar/debug.h>
GWEN_INHERIT(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO);
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static GWENHYWFAR_CB void _freeData(void *bp, void *p);
static int _penCreate(AQDG_DRAW_CONTEXT *g, uint32_t frontColour, int lineWidth, int dashType);
static int _penRelease(AQDG_DRAW_CONTEXT *g, int penId);
static int _drawLine(AQDG_DRAW_CONTEXT *g, int penId, int xStart, int yStart, int xEnd, int yEnd);
static int _drawRect(AQDG_DRAW_CONTEXT *g, int penId, int x, int y, int w, int h);
static int _drawFilledRect(AQDG_DRAW_CONTEXT *g, int penId, int x, int y, int w, int h);
static int _fontCreate(AQDG_DRAW_CONTEXT *g, const char *face, int fontSize, int fontSlant, int fontWeight);
static int _fontRelease(AQDG_DRAW_CONTEXT *g, int fontId);
static int _drawText(AQDG_DRAW_CONTEXT *g, int penId, int fontId, int direction, int x, int y, const char *text);
static int _getTextWidth(AQDG_DRAW_CONTEXT *g, int fontId, const char *text);
static int _getTextHeight(AQDG_DRAW_CONTEXT *g, int fontId, const char *text);
static int _finish(AQDG_DRAW_CONTEXT *g);
/* ------------------------------------------------------------------------------------------------
* implementations
* ------------------------------------------------------------------------------------------------
*/
const double AQDG_Draw_ContextCairo_DashPattern1[2]= {1.0, 1.0};
const double AQDG_Draw_ContextCairo_DashPattern2[2]= {1.0, 2.0};
const double AQDG_Draw_ContextCairo_DashPattern3[2]= {1.0, 5.0};
const double AQDG_Draw_ContextCairo_DashPattern4[2]= {1.0, 10.0};
const double AQDG_Draw_ContextCairo_DashPattern5[2]= {10.0, 2.0};
AQDG_DRAW_CONTEXT *AQDG_Draw_ContextCairo_Pdf_new(const char *fileName, int w, int h)
{
AQDG_DRAW_CONTEXT *g;
AQDG_DRAW_CONTEXT_CAIRO *xg;
g=AQDG_Draw_Context_new();
GWEN_NEW_OBJECT(AQDG_DRAW_CONTEXT_CAIRO, xg);
assert(xg);
GWEN_INHERIT_SETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g, xg, _freeData);
xg->fontList=AQDG_Draw_Font_List_new();
xg->penList=AQDG_Draw_Pen_List_new();
if (fileName)
xg->fileName=strdup(fileName);
xg->width=w;
xg->height=h;
xg->surface=cairo_pdf_surface_create(fileName, w, h);
if (xg->surface==NULL) {
DBG_ERROR(0, "Unable to create surface");
}
xg->cr=cairo_create(xg->surface);
if (xg->cr==NULL) {
DBG_ERROR(0, "Could not create cairo context");
}
/* set virtual functions */
AQDG_Draw_Context_SetPenCreateFn(g, _penCreate);
AQDG_Draw_Context_SetPenReleaseFn(g, _penRelease);
AQDG_Draw_Context_SetDrawLineFn(g, _drawLine);
AQDG_Draw_Context_SetDrawRectFn(g, _drawRect);
AQDG_Draw_Context_SetDrawFilledRectFn(g, _drawFilledRect);
AQDG_Draw_Context_SetFontCreateFn(g, _fontCreate);
AQDG_Draw_Context_SetFontReleaseFn(g, _fontRelease);
AQDG_Draw_Context_SetDrawTextFn(g, _drawText);
AQDG_Draw_Context_SetGetTextWidthFn(g, _getTextWidth);
AQDG_Draw_Context_SetGetTextHeightFn(g, _getTextHeight);
AQDG_Draw_Context_SetFinishFn(g, _finish);
return g;
}
AQDG_DRAW_CONTEXT *AQDG_Draw_ContextCairo_Ps_new(const char *fileName, int w, int h)
{
AQDG_DRAW_CONTEXT *g;
AQDG_DRAW_CONTEXT_CAIRO *xg;
g=AQDG_Draw_Context_new();
GWEN_NEW_OBJECT(AQDG_DRAW_CONTEXT_CAIRO, xg);
assert(xg);
GWEN_INHERIT_SETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g, xg, _freeData);
xg->fontList=AQDG_Draw_Font_List_new();
xg->penList=AQDG_Draw_Pen_List_new();
if (fileName)
xg->fileName=strdup(fileName);
xg->width=w;
xg->height=h;
xg->surface=cairo_ps_surface_create(fileName, w, h);
if (xg->surface==NULL) {
DBG_ERROR(0, "Unable to create surface");
}
xg->cr=cairo_create(xg->surface);
if (xg->cr==NULL) {
DBG_ERROR(0, "Could not create cairo context");
}
/* set virtual functions */
AQDG_Draw_Context_SetPenCreateFn(g, _penCreate);
AQDG_Draw_Context_SetPenReleaseFn(g, _penRelease);
AQDG_Draw_Context_SetDrawLineFn(g, _drawLine);
AQDG_Draw_Context_SetDrawRectFn(g, _drawRect);
AQDG_Draw_Context_SetDrawFilledRectFn(g, _drawFilledRect);
AQDG_Draw_Context_SetFontCreateFn(g, _fontCreate);
AQDG_Draw_Context_SetFontReleaseFn(g, _fontRelease);
AQDG_Draw_Context_SetDrawTextFn(g, _drawText);
AQDG_Draw_Context_SetGetTextWidthFn(g, _getTextWidth);
AQDG_Draw_Context_SetGetTextHeightFn(g, _getTextHeight);
AQDG_Draw_Context_SetFinishFn(g, _finish);
return g;
}
AQDG_DRAW_CONTEXT *AQDG_Draw_ContextCairo_Png_new(const char *fileName, int w, int h)
{
AQDG_DRAW_CONTEXT *g;
AQDG_DRAW_CONTEXT_CAIRO *xg;
g=AQDG_Draw_Context_new();
GWEN_NEW_OBJECT(AQDG_DRAW_CONTEXT_CAIRO, xg);
assert(xg);
GWEN_INHERIT_SETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g, xg, _freeData);
xg->fontList=AQDG_Draw_Font_List_new();
xg->penList=AQDG_Draw_Pen_List_new();
if (fileName)
xg->fileName=strdup(fileName);
xg->width=w;
xg->height=h;
xg->stride=cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
xg->writePng=1;
xg->surface=cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
if (xg->surface==NULL) {
DBG_ERROR(0, "Unable to create surface");
}
xg->cr=cairo_create(xg->surface);
if (xg->cr==NULL) {
DBG_ERROR(0, "Could not create cairo context");
}
/* set virtual functions */
AQDG_Draw_Context_SetPenCreateFn(g, _penCreate);
AQDG_Draw_Context_SetPenReleaseFn(g, _penRelease);
AQDG_Draw_Context_SetDrawLineFn(g, _drawLine);
AQDG_Draw_Context_SetDrawRectFn(g, _drawRect);
AQDG_Draw_Context_SetDrawFilledRectFn(g, _drawFilledRect);
AQDG_Draw_Context_SetFontCreateFn(g, _fontCreate);
AQDG_Draw_Context_SetFontReleaseFn(g, _fontRelease);
AQDG_Draw_Context_SetDrawTextFn(g, _drawText);
AQDG_Draw_Context_SetGetTextWidthFn(g, _getTextWidth);
AQDG_Draw_Context_SetGetTextHeightFn(g, _getTextHeight);
AQDG_Draw_Context_SetFinishFn(g, _finish);
return g;
}
GWENHYWFAR_CB void _freeData(void *bp, void *p)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
xg=(AQDG_DRAW_CONTEXT_CAIRO *) p;
if (xg->cr) {
cairo_destroy(xg->cr);
xg->cr=NULL;
}
if (xg->surface) {
cairo_surface_destroy(xg->surface);
xg->surface=NULL;
}
free(xg->fileName);
AQDG_Draw_Font_List_free(xg->fontList);
xg->fontList=NULL;
AQDG_Draw_Pen_List_free(xg->penList);
xg->penList=NULL;
GWEN_FREE_OBJECT(xg);
}
int _penCreate(AQDG_DRAW_CONTEXT *g, uint32_t frontColour, int lineWidth, int dashType)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_PEN *pen;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
pen=AQDG_Draw_Pen_new();
AQDG_Draw_Pen_SetId(pen, ++(xg->lastPenId));
AQDG_Draw_Pen_SetFrontColour(pen, frontColour);
AQDG_Draw_Pen_SetLineWidth(pen, lineWidth);
AQDG_Draw_Pen_SetDashType(pen, dashType);
AQDG_Draw_Pen_List_Add(pen, xg->penList);
return xg->lastPenId;
}
int _penRelease(AQDG_DRAW_CONTEXT *g, int penId)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_PEN *pen;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
pen=AQDG_Draw_Pen_List_GetById(xg->penList, penId);
if (pen==NULL) {
DBG_INFO(0, "Pen %d not found", penId);
return GWEN_ERROR_NOT_FOUND;
}
AQDG_Draw_Pen_List_Del(pen);
AQDG_Draw_Pen_free(pen);
return 0;
}
int _drawLine(AQDG_DRAW_CONTEXT *g, int penId, int xStart, int yStart, int xEnd, int yEnd)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_PEN *pen;
uint32_t fgCol;
double red, green, blue;
int i;
int dashType;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_ERROR(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
pen=AQDG_Draw_Pen_List_GetById(xg->penList, penId);
if (pen==NULL) {
DBG_ERROR(0, "Pen %d not found", penId);
return GWEN_ERROR_NOT_FOUND;
}
/* set foreground color */;
fgCol=AQDG_Draw_Pen_GetFrontColour(pen);
red=(double)((fgCol>>24) & 0xff)/255.0;
green=(double)((fgCol>>16) & 0xff)/255.0;
blue=(double)((fgCol>>8) & 0xff)/255.0;
cairo_set_source_rgb(xg->cr, red, green, blue);
/* set line width */
i=AQDG_Draw_Pen_GetLineWidth(pen);
cairo_set_line_width(xg->cr, i);
dashType=AQDG_Draw_Pen_GetDashType(pen);
switch (dashType) {
default:
case 0:
cairo_set_dash(xg->cr, NULL, 0, 0.0);
break;
case 1:
cairo_set_dash(xg->cr, AQDG_Draw_ContextCairo_DashPattern1, 2, 0.0);
break;
case 2:
cairo_set_dash(xg->cr, AQDG_Draw_ContextCairo_DashPattern2, 2, 0.0);
break;
case 3:
cairo_set_dash(xg->cr, AQDG_Draw_ContextCairo_DashPattern3, 2, 0.0);
break;
case 4:
cairo_set_dash(xg->cr, AQDG_Draw_ContextCairo_DashPattern4, 2, 0.0);
break;
case 5:
cairo_set_dash(xg->cr, AQDG_Draw_ContextCairo_DashPattern5, 2, 0.0);
break;
}
/* draw line from start to end position */
cairo_move_to(xg->cr, xStart, yStart);
cairo_line_to(xg->cr, xEnd, yEnd);
cairo_stroke(xg->cr);
return 0;
}
int _drawRect(AQDG_DRAW_CONTEXT *g, int penId, int x, int y, int w, int h)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_PEN *pen;
uint32_t fgCol;
double red, green, blue;
int i;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
pen=AQDG_Draw_Pen_List_GetById(xg->penList, penId);
if (pen==NULL) {
DBG_INFO(0, "Pen %d not found", penId);
return GWEN_ERROR_NOT_FOUND;
}
/* set foreground color */;
fgCol=AQDG_Draw_Pen_GetFrontColour(pen);
red=(double)((fgCol>>24) & 0xff)/255.0;
green=(double)((fgCol>>16) & 0xff)/255.0;
blue=(double)((fgCol>>8) & 0xff)/255.0;
cairo_set_source_rgb(xg->cr, red, green, blue);
/* set line width */
i=AQDG_Draw_Pen_GetLineWidth(pen);
cairo_set_line_width(xg->cr, i);
cairo_set_dash(xg->cr, NULL, 0, 0.0);
/* draw line from start to end position */
cairo_rectangle(xg->cr, x, y, w, h);
cairo_stroke(xg->cr);
return 0;
}
int _drawFilledRect(AQDG_DRAW_CONTEXT *g, int penId, int x, int y, int w, int h)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_PEN *pen;
uint32_t fgCol;
double red, green, blue;
int i;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
pen=AQDG_Draw_Pen_List_GetById(xg->penList, penId);
if (pen==NULL) {
DBG_INFO(0, "Pen %d not found", penId);
return GWEN_ERROR_NOT_FOUND;
}
/* set foreground color */;
fgCol=AQDG_Draw_Pen_GetFrontColour(pen);
red=(double)((fgCol>>24) & 0xff)/255.0;
green=(double)((fgCol>>16) & 0xff)/255.0;
blue=(double)((fgCol>>8) & 0xff)/255.0;
cairo_set_source_rgb(xg->cr, red, green, blue);
/* set line width */
i=AQDG_Draw_Pen_GetLineWidth(pen);
cairo_set_line_width(xg->cr, i);
cairo_set_dash(xg->cr, NULL, 0, 0.0);
/* draw line from start to end position */
cairo_rectangle(xg->cr, x, y, w, h);
cairo_stroke_preserve(xg->cr);
cairo_fill(xg->cr);
return 0;
}
int _fontCreate(AQDG_DRAW_CONTEXT *g, const char *face, int fontSize, int fontSlant, int fontWeight)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_FONT *font;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
font=AQDG_Draw_Font_new();
AQDG_Draw_Font_SetId(font, ++(xg->lastFontId));
AQDG_Draw_Font_SetFontName(font, face);
AQDG_Draw_Font_SetFontSize(font, fontSize);
AQDG_Draw_Font_SetFontSlant(font, fontSlant);
AQDG_Draw_Font_SetFontWeight(font, fontWeight);
AQDG_Draw_Font_List_Add(font, xg->fontList);
return xg->lastFontId;
}
int _fontRelease(AQDG_DRAW_CONTEXT *g, int fontId)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_FONT *font;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
font=AQDG_Draw_Font_List_GetById(xg->fontList, fontId);
if (font==NULL) {
DBG_INFO(0, "Font %d not found", fontId);
return GWEN_ERROR_NOT_FOUND;
}
AQDG_Draw_Font_List_Del(font);
AQDG_Draw_Font_free(font);
return 0;
}
int _drawText(AQDG_DRAW_CONTEXT *g, int penId, int fontId, int direction, int x, int y, const char *text)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_FONT *font;
int crSlant;
int crWeight;
AQDG_DRAW_PEN *pen;
uint32_t fgCol;
double red, green, blue;
int i;
cairo_font_extents_t extents;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
/* get and handle pen */
pen=AQDG_Draw_Pen_List_GetById(xg->penList, penId);
if (pen==NULL) {
DBG_INFO(0, "Pen %d not found", penId);
return GWEN_ERROR_NOT_FOUND;
}
/* set foreground color */;
fgCol=AQDG_Draw_Pen_GetFrontColour(pen);
red=(double)((fgCol>>24) & 0xff)/255.0;
green=(double)((fgCol>>16) & 0xff)/255.0;
blue=(double)((fgCol>>8) & 0xff)/255.0;
cairo_set_source_rgb(xg->cr, red, green, blue);
/* set line width */
i=AQDG_Draw_Pen_GetLineWidth(pen);
cairo_set_line_width(xg->cr, i);
/* get and handle font */
font=AQDG_Draw_Font_List_GetById(xg->fontList, fontId);
if (font==NULL) {
DBG_INFO(0, "Font %d not found", fontId);
return GWEN_ERROR_NOT_FOUND;
}
switch (AQDG_Draw_Font_GetFontSlant(font)) {
default:
case AQDG_Slant_None:
crSlant=CAIRO_FONT_SLANT_NORMAL;
break;
case AQDG_Slant_Italic:
crSlant=CAIRO_FONT_SLANT_ITALIC;
break;
}
switch (AQDG_Draw_Font_GetFontWeight(font)) {
default:
case AQDG_Weight_None:
crWeight=CAIRO_FONT_WEIGHT_NORMAL;
break;
case AQDG_Weight_Bold:
crWeight=CAIRO_FONT_WEIGHT_BOLD;
break;
}
cairo_select_font_face(xg->cr, AQDG_Draw_Font_GetFontName(font), crSlant, crWeight);
cairo_set_font_size(xg->cr, AQDG_Draw_Font_GetFontSize(font));
cairo_font_extents(xg->cr, &extents);
/* TODO: translate pos and rotate according to given direction (use cairo_save and cairo_restore) */
cairo_move_to(xg->cr, x, y+extents.ascent);
cairo_show_text(xg->cr, text);
return 0;
}
int _getTextWidth(AQDG_DRAW_CONTEXT *g, int fontId, const char *text)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_FONT *font;
int crSlant;
int crWeight;
cairo_text_extents_t extents;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
/* get and handle font */
font=AQDG_Draw_Font_List_GetById(xg->fontList, fontId);
if (font==NULL) {
DBG_INFO(0, "Font %d not found", fontId);
return GWEN_ERROR_NOT_FOUND;
}
switch (AQDG_Draw_Font_GetFontSlant(font)) {
default:
case AQDG_Slant_None:
crSlant=CAIRO_FONT_SLANT_NORMAL;
break;
case AQDG_Slant_Italic:
crSlant=CAIRO_FONT_SLANT_ITALIC;
break;
}
switch (AQDG_Draw_Font_GetFontWeight(font)) {
default:
case AQDG_Weight_None:
crWeight=CAIRO_FONT_WEIGHT_NORMAL;
break;
case AQDG_Weight_Bold:
crWeight=CAIRO_FONT_WEIGHT_BOLD;
break;
}
cairo_select_font_face(xg->cr, AQDG_Draw_Font_GetFontName(font), crSlant, crWeight);
cairo_set_font_size(xg->cr, AQDG_Draw_Font_GetFontSize(font));
cairo_text_extents(xg->cr, text, &extents);
return (int)(extents.width);
}
int _getTextHeight(AQDG_DRAW_CONTEXT *g, int fontId, const char *text)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
AQDG_DRAW_FONT *font;
int crSlant;
int crWeight;
cairo_text_extents_t extents;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
/* get and handle font */
font=AQDG_Draw_Font_List_GetById(xg->fontList, fontId);
if (font==NULL) {
DBG_INFO(0, "Font %d not found", fontId);
return GWEN_ERROR_NOT_FOUND;
}
switch (AQDG_Draw_Font_GetFontSlant(font)) {
default:
case AQDG_Slant_None:
crSlant=CAIRO_FONT_SLANT_NORMAL;
break;
case AQDG_Slant_Italic:
crSlant=CAIRO_FONT_SLANT_ITALIC;
break;
}
switch (AQDG_Draw_Font_GetFontWeight(font)) {
default:
case AQDG_Weight_None:
crWeight=CAIRO_FONT_WEIGHT_NORMAL;
break;
case AQDG_Weight_Bold:
crWeight=CAIRO_FONT_WEIGHT_BOLD;
break;
}
cairo_select_font_face(xg->cr, AQDG_Draw_Font_GetFontName(font), crSlant, crWeight);
cairo_set_font_size(xg->cr, AQDG_Draw_Font_GetFontSize(font));
cairo_text_extents(xg->cr, text, &extents);
return (int)(extents.height);
}
int _finish(AQDG_DRAW_CONTEXT *g)
{
AQDG_DRAW_CONTEXT_CAIRO *xg;
assert(g);
xg=GWEN_INHERIT_GETDATA(AQDG_DRAW_CONTEXT, AQDG_DRAW_CONTEXT_CAIRO, g);
assert(xg);
if (xg->surface==NULL) {
DBG_ERROR(0, "No surface created");
return GWEN_ERROR_INVALID;
}
if (xg->cr==NULL) {
DBG_INFO(0, "Graphics context not active, call \"AQDG_Draw_Context_BeginDraw()\" before");
return GWEN_ERROR_INVALID;
}
if (xg->writePng) {
cairo_status_t st;
cairo_surface_flush(xg->surface);
st=cairo_surface_write_to_png(xg->surface, xg->fileName);
if (st!=CAIRO_STATUS_SUCCESS) {
DBG_ERROR(0, "Cairo Status: %d (%s)", st, cairo_status_to_string(st));
}
}
#if 0
if (1) {
cairo_status_t st;
fprintf(stderr, "Writing to PNG\n");
cairo_surface_flush(xg->surface);
st=cairo_surface_write_to_png(xg->surface, "/tmp/test.png");
if (st!=CAIRO_STATUS_SUCCESS) {
fprintf(stderr, "Cairo Status: %d (%s)\n", st, cairo_status_to_string(st));
}
}
#endif
cairo_surface_finish(xg->surface);
return 0;
}

View File

@@ -0,0 +1,34 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_DRAW_CONTEXT_CAIRO_H
#define AQDG_DRAW_CONTEXT_CAIRO_H
#include <aqdiagram/draw/context.h>
#ifdef __cplusplus
extern "C" {
#endif
AQDG_API AQDG_DRAW_CONTEXT *AQDG_ContextCairo_Pdf_new(const char *fileName, int w, int h);
AQDG_API AQDG_DRAW_CONTEXT *AQDG_ContextCairo_Ps_new(const char *fileName, int w, int h);
AQDG_API AQDG_DRAW_CONTEXT *AQDG_ContextCairo_Png_new(const char *fileName, int w, int h);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,51 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_DRAW_CONTEXT_CAIRO_P_H
#define AQDG_DRAW_CONTEXT_CAIRO_P_H
#include <aqdiagram/draw/context_cairo.h>
#include <aqdiagram/draw/context.h>
#include <aqdiagram/draw/font.h>
#include <aqdiagram/draw/pen.h>
#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>
#include <cairo/cairo-ps.h>
typedef struct AQDG_DRAW_CONTEXT_CAIRO AQDG_DRAW_CONTEXT_CAIRO;
struct AQDG_DRAW_CONTEXT_CAIRO {
char *fileName;
int width;
int height;
cairo_surface_t *surface;
cairo_t *cr;
AQDG_DRAW_FONT_LIST *fontList;
AQDG_DRAW_PEN_LIST *penList;
int lastFontId;
int lastPenId;
int stride; /* only for memory buffer surface */
int writePng;
};
#endif

View File

@@ -0,0 +1,78 @@
<?xml?>
<tm2>
<type id="AQDG_DRAW_FONT" type="pointer">
<descr>
This class contains information about a font. This class is to be used by implemnentations only.
</descr>
<lang id="c">
<identifier>AQDG_DRAW_FONT</identifier>
<prefix>AQDG_Draw_Font</prefix>
<baseFileName>font</baseFileName>
<flags>
with_list1
with_list2
with_inherit
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/draw/context.h</header>
</headers>
</lang>
<defines>
<define id="AQDG_DRAW_FONT_RTFLAGS" prefix="AQDG_DRAW_FONT_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
</define>
</defines>
<members>
<member name="id" type="int" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>volatile with_getbymember</flags>
<access>public</access>
</member>
<member name="fontName" type="char_ptr" maxlen="64" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
</member>
<member name="fontSize" type="int" maxlen="8" >
<default>12</default>
<preset>12</preset>
<access>public</access>
</member>
<member name="fontSlant" type="int" maxlen="8" >
<default>AQDG_Slant_None</default>
<preset>AQDG_Slant_None</preset>
<access>public</access>
</member>
<member name="fontWeight" type="int" maxlen="8" >
<default>AQDG_Weight_None</default>
<preset>AQDG_Weight_None</preset>
<access>public</access>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,72 @@
<?xml?>
<tm2>
<type id="AQDG_DRAW_PEN" type="pointer">
<descr>
This class contains information about a pen. This class is to be used by implemnentations only.
</descr>
<lang id="c">
<identifier>AQDG_DRAW_PEN</identifier>
<prefix>AQDG_Draw_Pen</prefix>
<baseFileName>pen</baseFileName>
<flags>
with_list1
with_list2
with_inherit
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/draw/context.h</header>
</headers>
</lang>
<defines>
<define id="AQDG_DRAW_PEN_RTFLAGS" prefix="AQDG_DRAW_PEN_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
</define>
</defines>
<members>
<member name="id" type="int" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>volatile with_getbymember</flags>
<access>public</access>
</member>
<member name="frontColour" type="uint32_t" maxlen="8" >
<default>0x00000000</default>
<preset>0x00000000</preset>
<access>public</access>
</member>
<member name="lineWidth" type="int" maxlen="8" >
<default>1</default>
<preset>1</preset>
<access>public</access>
</member>
<member name="dashType" type="int" maxlen="8" >
<default>AQDG_Dash_None</default>
<preset>AQDG_Dash_None</preset>
<access>public</access>
</member>
</members>
</type>
</tm2>

29
src/lib/aqdiagram/graph/.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
*.tm2
af_graph_datapair.c
af_graph_dataset.c
af_graph_tick.c
af_graph_subgraph.c
af_graph_settings_pen.c
af_graph_settings_font.c
af_graph_settings_graph.c
af_graph_settings.c
af_graph_datapair_p.h
af_graph_dataset_p.h
af_graph_tick_p.h
af_graph_subgraph_p.h
af_graph_settings_pen_p.h
af_graph_settings_font_p.h
af_graph_settings_graph_p.h
af_graph_settings_p.h
af_graph_datapair.h
af_graph_dataset.h
af_graph_tick.h
af_graph_subgraph.h
af_graph_settings_pen.h
af_graph_settings_font.h
af_graph_settings_graph.h
af_graph_settings.h

View File

@@ -0,0 +1,140 @@
<?xml?>
<gwbuild>
<target type="ConvenienceLibrary" name="aqdg_graph" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)/src/lib
-I$(topbuilddir)/src/lib
-I$(topbuilddir)
-I$(topsrcdir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
--include=$(builddir)/../types
--include=$(topsrcdir)/src/lib/typemaker2/c
--include=$(topbuilddir)/src/lib/typemaker2/c
</includes>
<define name="BUILDING_AQDIAGRAM" />
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
--api=AQDG_API
</setVar>
<setVar name="local/typefiles" >
datapair.xml
dataset.xml
tick.xml
subgraph.xml
settings_pen.xml
settings_font.xml
settings.xml
</setVar>
<setVar name="local/built_sources" >
datapair.c
dataset.c
tick.c
subgraph.c
settings_pen.c
settings_font.c
settings.c
</setVar>
<setVar name="local/built_headers_pub">
datapair.h
dataset.h
tick.h
subgraph.h
settings_pen.h
settings_font.h
settings.h
</setVar>
<setVar name="local/built_headers_priv" >
datapair_p.h
dataset_p.h
tick_p.h
subgraph_p.h
settings_pen_p.h
settings_font_p.h
settings_p.h
</setVar>
<headers dist="false" install="$(pkgincludedir)">
$(local/built_headers_pub)
</headers>
<headers dist="false" >
$(local/built_headers_priv)
</headers>
<headers dist="true" install="$(pkgincludedir)">
graph.h
</headers>
<headers dist="true">
graph_p.h
g_draw_data.h
g_draw_xticks.h
g_draw_yticks.h
g_config.h
g_layout.h
</headers>
<sources>
$(local/typefiles)
graph.c
g_draw_data.c
g_draw_xticks.c
g_draw_yticks.c
g_config.c
g_layout.c
</sources>
<data DIST="FALSE" generated="TRUE" >
aqdg_graph_datapair.tm2 aqdg_graph_datapair_list.tm2 aqdg_graph_datapair_list2.tm2
aqdg_graph_dataset.tm2 aqdg_graph_dataset_list.tm2 aqdg_graph_dataset_list2.tm2
aqdg_graph_tick.tm2 aqdg_graph_tick_list.tm2 aqdg_graph_tick_list2.tm2
aqdg_graph_subgraph.tm2 aqdg_graph_subgraph_list.tm2 aqdg_graph_subgraph_list2.tm2
aqdg_graph_settings_pen.tm2 aqdg_graph_settings_pen_list.tm2 aqdg_graph_settings_pen_list2.tm2
aqdg_graph_settings_font.tm2 aqdg_graph_settings_font_list.tm2 aqdg_graph_settings_font_list2.tm2
aqdg_graph_settings.tm2 aqdg_graph_settings_list.tm2 aqdg_graph_settings_list2.tm2
</data>
<extradist>
dataset_fns.c dataset_fns.h
tick_fns.c tick_fns.h
</extradist>
<useTargets>
</useTargets>
<subdirs>
</subdirs>
</target>
</gwbuild>

View File

@@ -0,0 +1,131 @@
AM_CPPFLAGS=$(gwenhywfar_includes) -I$(srcdir)/.. -I$(builddir)/.. -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CFLAGS=$(visibility_cflags)
DEFS+=\
-DBUILDING_AQDIAGRAM \
-DLOCALEDIR=\"@aqdiagram_locale_searchdir@\" \
-DAQDIAGRAM_DATA_DIR=\"$(aqdiagram_data_searchdir)\"
noinst_LTLIBRARIES=libaqdg_graph.la
typefiles=\
datapair.xml \
dataset.xml \
tick.xml \
subgraph.xml \
settings_pen.xml \
settings_font.xml \
settings.xml
# typedef files generated by typemaker2
typedatadir=$(datadir)/aqfinance/typemaker2/c
dist_typedata_DATA=\
aqdg_graph_datapair.tm2 aqdg_graph_datapair_list.tm2 aqdg_graph_datapair_list2.tm2 \
aqdg_graph_dataset.tm2 aqdg_graph_dataset_list.tm2 aqdg_graph_dataset_list2.tm2 \
aqdg_graph_tick.tm2 aqdg_graph_tick_list.tm2 aqdg_graph_tick_list2.tm2 \
aqdg_graph_subgraph.tm2 aqdg_graph_subgraph_list.tm2 aqdg_graph_subgraph_list2.tm2 \
aqdg_graph_settings_pen.tm2 aqdg_graph_settings_pen_list.tm2 aqdg_graph_settings_pen_list2.tm2 \
aqdg_graph_settings_font.tm2 aqdg_graph_settings_font_list.tm2 aqdg_graph_settings_font_list2.tm2 \
aqdg_graph_settings.tm2 aqdg_graph_settings_list.tm2 aqdg_graph_settings_list2.tm2
built_sources= \
datapair.c \
dataset.c \
tick.c \
subgraph.c \
settings_pen.c \
settings_font.c \
settings.c
build_headers_priv= \
datapair_p.h \
dataset_p.h \
tick_p.h \
subgraph_p.h \
settings_pen_p.h \
settings_font_p.h \
settings_p.h
build_headers_pub= \
datapair.h \
dataset.h \
tick.h \
subgraph.h \
settings_pen.h \
settings_font.h \
settings.h
build_headers=$(build_headers_priv) $(build_headers_pub)
libaqdg_graph_la_SOURCES=$(built_sources) \
graph.c
libaqdg_graph_la_LIBADD=$(CAIRO_LIBS)
iheaderdir=${includedir}/aqfinance/graphs
iheader_HEADERS=$(build_headers_pub) \
graph.h
noinst_HEADERS=$(build_headers_priv) \
graph_p.h
EXTRA_DIST=$(typefiles) \
dataset_fns.dataset_fns.h \
tick_fns.c tick_fns.h
build_sources: $(built_sources)
list='$(SUBDIRS)'; for d in $$list; do \
$(MAKE) -C $$d build_sources; \
done ;
clean_build_files:
rm -f $(built_sources) $(build_headers)
format_build_files:
for f in $(built_sources) $(build_headers); do \
astyle -s2 --min-conditional-indent=0 --indent-labels --pad=oper -a --suffix=none $$f; \
done
#%.c: %.xml
# typemaker2 -I $(top_srcdir)/src/lib/typemaker2/c -I $(srcdir) -I $(AQDATABASE_TYPEMAKERDIR)/c --destfolder="$(srcdir)" -D AE_API $<
#%.h: %.xml
# typemaker2 -I $(top_srcdir)/src/lib/typemaker2/c -I $(srcdir) -I $(AQDATABASE_TYPEMAKERDIR)/c --destfolder="$(srcdir)" -D AE_API $<
#SUFFIXES = .xml .c
typefiles: $(typefiles) typedefs
$(typemaker2_exe) -I $(top_srcdir)/src/lib/typemaker2/c -I $(gwenhywfar_dir)/share/gwenhywfar/typemaker2/c -I $(srcdir) -I $(AQDATABASE_TYPEMAKERDIR)/c --destfolder="$(srcdir)" -D AQDG_API $(typefiles)
typedefs: $(typefiles)
$(typemaker2_exe) --defs-only -I $(top_srcdir)/src/lib/typemaker2/c -I $(gwenhywfar_dir)/share/gwenhywfar/typemaker2/c -I $(srcdir) -I $(AQDATABASE_TYPEMAKERDIR)/c --destfolder="$(srcdir)" -D AQDG_API $(typefiles)
sources:
for f in $(libaqdg_graph_la_SOURCES) $(built_sources); do \
echo $(subdir)/$$f >>$(top_srcdir)/i18nsources; \
done
for d in $(SUBDIRS); do \
$(MAKE) -C $$d sources; \
done

View File

@@ -0,0 +1,71 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_DATAPAIR" type="pointer">
<descr>
This class describes data axis.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_DATAPAIR</identifier>
<prefix>AQDG_Graph_DataPair</prefix>
<baseFileName>datapair</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
</headers>
</lang>
<members>
<member name="valueX" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
<flags>sortbymember</flags>
</member>
<member name="valueY" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
<flags>sortbymember</flags>
</member>
<member name="level" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="label" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,195 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_DATASET" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_DATASET</identifier>
<prefix>AQDG_Graph_DataSet</prefix>
<baseFileName>dataset</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
<header type="sys" loc="pre">aqdiagram/graph/datapair.h</header>
<header type="sys" loc="pre">aqdiagram/graph/tick.h</header>
<header type="sys" loc="pre">aqdiagram/graph/subgraph.h</header>
<header type="sys" loc="post">dataset_fns.h</header>
<header type="local" loc="codeEnd">dataset_fns.c</header>
</headers>
</lang>
<enums>
<enum id="AQDG_GRAPH_DATASET_DATATYPE" prefix="AQDG_Graph_DataSet_DataType_">
<item name="integer">
<descr>integer type</descr>
</item>
<item name="double">
<descr>floating point type (double precision)</descr>
</item>
<item name="date">
<descr>date type</descr>
</item>
</enum>
</enums>
<members>
<member name="title" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="subTitle" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="dataPairList" type="AQDG_GRAPH_DATAPAIR_LIST" >
<default>NULL</default>
<preset>AQDG_Graph_DataPair_List_new()</preset>
<access>public</access>
<flags>own</flags>
<setflags>nodup</setflags>
<getflags>none</getflags>
</member>
<member name="subGraphList" type="AQDG_GRAPH_SUBGRAPH_LIST" >
<default>NULL</default>
<preset>AQDG_Graph_SubGraph_List_new()</preset>
<access>public</access>
<flags>own</flags>
<setflags>nodup</setflags>
<getflags>none</getflags>
</member>
<!-- X-axis -->
<member name="dataTypeX" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="precisionX" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="minValueX" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
</member>
<member name="maxValueX" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
</member>
<member name="labelX" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="xTickList" type="AQDG_GRAPH_TICK_LIST" >
<default>NULL</default>
<preset>AQDG_Graph_Tick_List_new()</preset>
<access>public</access>
<flags>own</flags>
<setflags>nodup</setflags>
<getflags>none</getflags>
</member>
<!-- Y-axis -->
<member name="dataTypeY" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="precisionY" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="minValueY" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
</member>
<member name="maxValueY" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
</member>
<member name="labelY" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="yTickList" type="AQDG_GRAPH_TICK_LIST" >
<default>NULL</default>
<preset>AQDG_Graph_Tick_List_new()</preset>
<access>public</access>
<flags>own</flags>
<setflags>nodup</setflags>
<getflags>none</getflags>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,453 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
void AQDG_Graph_DataSet_AdjustXRange(AQDG_GRAPH_DATASET *ds)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
if (dp) {
double minVal;
double maxVal;
minVal=AQDG_Graph_DataPair_GetValueX(dp);
maxVal=minVal;
dp=AQDG_Graph_DataPair_List_Next(dp);
while (dp) {
double v;
v=AQDG_Graph_DataPair_GetValueX(dp);
if (v<minVal)
minVal=v;
if (v>maxVal)
maxVal=v;
dp=AQDG_Graph_DataPair_List_Next(dp);
}
ds->minValueX=minVal;
ds->maxValueX=maxVal;
}
}
}
void AQDG_Graph_DataSet_AdjustYRange(AQDG_GRAPH_DATASET *ds)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
if (dp) {
double minVal;
double maxVal;
minVal=AQDG_Graph_DataPair_GetValueY(dp);
maxVal=minVal;
dp=AQDG_Graph_DataPair_List_Next(dp);
while (dp) {
double v;
v=AQDG_Graph_DataPair_GetValueY(dp);
if (v<minVal)
minVal=v;
if (v>maxVal)
maxVal=v;
dp=AQDG_Graph_DataPair_List_Next(dp);
}
ds->minValueY=minVal;
ds->maxValueY=maxVal;
}
}
}
void AQDG_Graph_DataSet_AddTicks(AQDG_GRAPH_DATASET *ds)
{
if (ds->xTickList)
AQDG_Graph_Tick_AddTicks(ds->xTickList, ds->dataTypeX, ds->minValueX, ds->maxValueX, ds->precisionX);
if (ds->yTickList)
AQDG_Graph_Tick_AddTicks(ds->yTickList, ds->dataTypeY, ds->minValueY, ds->maxValueY, ds->precisionY);
}
void AQDG_Graph_DataSet_AddSubGraph(AQDG_GRAPH_DATASET *ds, const char *label,
int level, int graphType, int dataMode, int colour, int lineWidth, int dashType)
{
AQDG_GRAPH_SUBGRAPH *sg;
if (ds->subGraphList==NULL)
ds->subGraphList=AQDG_Graph_SubGraph_List_new();
sg=AQDG_Graph_SubGraph_new();
AQDG_Graph_SubGraph_SetLabel(sg, label);
AQDG_Graph_SubGraph_SetLevel(sg, level);
AQDG_Graph_SubGraph_SetGraphType(sg, graphType);
AQDG_Graph_SubGraph_SetColour(sg, colour);
AQDG_Graph_SubGraph_SetLineWidth(sg, lineWidth);
AQDG_Graph_SubGraph_SetDashType(sg, dashType);
AQDG_Graph_SubGraph_List_Add(sg, ds->subGraphList);
}
AQDG_GRAPH_SUBGRAPH *AQDG_Graph_DataSet_GetSubGraphByLevel(AQDG_GRAPH_DATASET *ds, int level)
{
if (ds->subGraphList)
return AQDG_Graph_SubGraph_List_GetByLevel(ds->subGraphList, level);
return NULL;
}
void AQDG_Graph_DataSet_AddDataPair(AQDG_GRAPH_DATASET *ds, AQDG_GRAPH_DATAPAIR *dp)
{
assert(ds);
if (ds->dataPairList==NULL)
ds->dataPairList=AQDG_Graph_DataPair_List_new();
AQDG_Graph_DataPair_List_Add(dp, ds->dataPairList);
}
void AQDG_Graph_DataSet_SortDataPairsByX(AQDG_GRAPH_DATASET *ds, int ascending)
{
assert(ds);
if (ds->dataPairList)
AQDG_Graph_DataPair_List_SortByValueX(ds->dataPairList, ascending);
}
void AQDG_Graph_DataSet_SortDataPairsByY(AQDG_GRAPH_DATASET *ds, int ascending)
{
assert(ds);
if (ds->dataPairList)
AQDG_Graph_DataPair_List_SortByValueY(ds->dataPairList, ascending);
}
void AQDG_Graph_DataSet_AccumulateDataPairs(AQDG_GRAPH_DATASET *ds, int level)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
double totalSum=0.0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double v;
v=AQDG_Graph_DataPair_GetValueY(dp);
totalSum+=v;
AQDG_Graph_DataPair_SetValueY(dp, totalSum);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DataSet_AverageDataPairs(AQDG_GRAPH_DATASET *ds, int level)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
double totalSum=0.0;
int cnt=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double v;
v=AQDG_Graph_DataPair_GetValueY(dp);
totalSum+=v;
cnt++;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
if (cnt) {
double average;
average=totalSum/((double)cnt);
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
AQDG_Graph_DataPair_SetValueY(dp, average);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
}
void AQDG_Graph_DataSet_FloatingAverageDataPairs(AQDG_GRAPH_DATASET *ds, int level, int num)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
double lastValues[num];
int cnt=0;
int idx=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double v;
int i;
v=AQDG_Graph_DataPair_GetValueY(dp);
if (idx>=num)
idx=0;
lastValues[idx]=v;
idx++;
cnt++;
if (cnt<num) {
/* buffer not full, average over the values we already have */
if (cnt) {
double totalSum=0.0;
for (i=0; i<cnt; i++) {
totalSum+=lastValues[i];
}
AQDG_Graph_DataPair_SetValueY(dp, totalSum/((double)cnt));
}
}
else {
double totalSum=0.0;
/* buffer full, average over full buffer */
for (i=0; i<num; i++) {
totalSum+=lastValues[i];
}
AQDG_Graph_DataPair_SetValueY(dp, totalSum/((double)num));
}
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
int AQDG_Graph_DataSet_GetAverageValueDistX(const AQDG_GRAPH_DATASET *ds, int level, double *pResult)
{
if (ds->dataPairList) {
const AQDG_GRAPH_DATAPAIR *dp;
double sumOfDists=0.0;
double lastValue=0.0;
int cnt=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double d;
d=AQDG_Graph_DataPair_GetValueX(dp);
if (cnt)
sumOfDists+=abs(d-lastValue);
lastValue=d;
cnt++;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
if (cnt>1) {
*pResult=sumOfDists/((double)(cnt-1));
return 0;
}
else
return 1;
}
else {
return GWEN_ERROR_NO_DATA;
}
}
int AQDG_Graph_DataSet_GetAverageValueDistY(const AQDG_GRAPH_DATASET *ds, int level, double *pResult)
{
if (ds->dataPairList) {
const AQDG_GRAPH_DATAPAIR *dp;
double sumOfDists=0.0;
double lastValue=0.0;
int cnt=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double d;
d=AQDG_Graph_DataPair_GetValueY(dp);
if (cnt)
sumOfDists+=abs(d-lastValue);
lastValue=d;
cnt++;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
if (cnt>1) {
*pResult=sumOfDists/((double)(cnt-1));
return 0;
}
else
return 1;
}
else {
return GWEN_ERROR_NO_DATA;
}
}
int AQDG_Graph_DataSet_GetMinValueDistX(const AQDG_GRAPH_DATASET *ds, int level, double *pResult)
{
if (ds->dataPairList) {
const AQDG_GRAPH_DATAPAIR *dp;
double minDist=0.0;
double lastValue=0.0;
int cnt=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double d;
d=AQDG_Graph_DataPair_GetValueX(dp);
if (cnt) {
double dist;
dist=abs(d-lastValue);
if (cnt>1) {
if (dist<minDist)
minDist=dist;
}
else
minDist=dist;
}
lastValue=d;
cnt++;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
if (cnt>1) {
*pResult=minDist;
return 0;
}
else
return 1;
}
else {
return GWEN_ERROR_NO_DATA;
}
}
int AQDG_Graph_DataSet_GetMinValueDistY(const AQDG_GRAPH_DATASET *ds, int level, double *pResult)
{
if (ds->dataPairList) {
const AQDG_GRAPH_DATAPAIR *dp;
double minDist=0.0;
double lastValue=0.0;
int cnt=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double d;
d=AQDG_Graph_DataPair_GetValueY(dp);
if (cnt) {
double dist;
dist=abs(d-lastValue);
if (dist<minDist)
minDist=dist;
}
lastValue=d;
cnt++;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
if (cnt>1) {
*pResult=minDist;
return 0;
}
else
return 1;
}
else {
return GWEN_ERROR_NO_DATA;
}
}
void AQDG_Graph_DataSet_KeepFirstNValues(AQDG_GRAPH_DATASET *ds, int n)
{
assert(ds);
if (ds->dataPairList) {
AQDG_GRAPH_DATAPAIR *dp;
int i=0;
dp=AQDG_Graph_DataPair_List_First(ds->dataPairList);
while (dp) {
dp=AQDG_Graph_DataPair_List_Next(dp);
i++;
if (i>=n)
break;
}
if (dp && i>=n) {
while (dp) {
AQDG_GRAPH_DATAPAIR *dpNext;
/* remove remaining entries */
dpNext=AQDG_Graph_DataPair_List_Next(dp);
AQDG_Graph_DataPair_List_Del(dp);
AQDG_Graph_DataPair_free(dp);
dp=dpNext;
}
}
}
}

View File

@@ -0,0 +1,65 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_GRAPH_DATASET_FNS_H
#define AQDG_GRAPH_DATASET_FNS_H
#ifdef __cplusplus
extern "C" {
#endif
AQDG_API double AQDG_Graph_DataSet_GetRoundedMaxVal(double val);
/**
* Calculates minValueX and maxValueX from the dataset.
*/
AQDG_API void AQDG_Graph_DataSet_AdjustXRange(AQDG_GRAPH_DATASET *ds);
/**
* Calculates minValueY and maxValueY from the dataset.
*/
AQDG_API void AQDG_Graph_DataSet_AdjustYRange(AQDG_GRAPH_DATASET *ds);
AQDG_API void AQDG_Graph_DataSet_AddTicks(AQDG_GRAPH_DATASET *ds);
AQDG_API void AQDG_Graph_DataSet_AddSubGraph(AQDG_GRAPH_DATASET *ds, const char *label,
int level, int graphType, int dataMode, int colour, int lineWidth, int dashType);
AQDG_API AQDG_GRAPH_SUBGRAPH *AQDG_Graph_DataSet_GetSubGraphByLevel(AQDG_GRAPH_DATASET *ds, int level);
AQDG_API void AQDG_Graph_DataSet_AddDataPair(AQDG_GRAPH_DATASET *ds, AQDG_GRAPH_DATAPAIR *dp);
AQDG_API int AQDG_Graph_DataSet_GetAverageValueDistX(const AQDG_GRAPH_DATASET *ds, int level, double *pResult);
AQDG_API int AQDG_Graph_DataSet_GetAverageValueDistY(const AQDG_GRAPH_DATASET *ds, int level, double *pResult);
AQDG_API int AQDG_Graph_DataSet_GetMinValueDistX(const AQDG_GRAPH_DATASET *ds, int level, double *pResult);
AQDG_API int AQDG_Graph_DataSet_GetMinValueDistY(const AQDG_GRAPH_DATASET *ds, int level, double *pResult);
AQDG_API void AQDG_Graph_DataSet_SortDataPairsByX(AQDG_GRAPH_DATASET *ds, int ascending);
AQDG_API void AQDG_Graph_DataSet_SortDataPairsByY(AQDG_GRAPH_DATASET *ds, int ascending);
AQDG_API void AQDG_Graph_DataSet_AccumulateDataPairs(AQDG_GRAPH_DATASET *ds, int level);
AQDG_API void AQDG_Graph_DataSet_AverageDataPairs(AQDG_GRAPH_DATASET *ds, int level);
AQDG_API void AQDG_Graph_DataSet_FloatingAverageDataPairs(AQDG_GRAPH_DATASET *ds, int level, int num);
AQDG_API void AQDG_Graph_DataSet_KeepFirstNValues(AQDG_GRAPH_DATASET *ds, int n);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,517 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_config.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
static int _createPenFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name);
static int _createFontFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize);
static int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig);
static int _createPenFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_PEN *sp);
static int _createFontFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_FONT *sf);
static int _createPensAndFontsFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *settings);
static void _releasePensAndFonts(AQDG_GRAPH *gr);
int AQDG_Graph_Init_fromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
{
int rv;
int i;
uint32_t flags=0;
rv=_createPensAndFontsFromDb(gr, dbConfig);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
for (i=0; i<100; i++) {
const char *s;
s=GWEN_DB_GetCharValue(dbConfig, "flags", i, NULL);
if (!(s && *s))
break;
if (strcasecmp(s, "grid")==0)
flags|=AQDG_GRAPH_FLAGS_WITH_GRID;
}
gr->flags=flags;
return 0;
}
int AQDG_Graph_Init(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *gs)
{
int rv;
rv=_createPensAndFontsFromSettings(gr, gs);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->flags=AQDG_Graph_Settings_GetFlags(gs);
return 0;
}
int AQDG_Graph_Fini(AQDG_GRAPH *gr)
{
_releasePensAndFonts(gr);
return 0;
}
void _releasePensAndFonts(AQDG_GRAPH *gr)
{
if (gr->penTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penTitle);
gr->penTitle=-1;
}
if (gr->penSubTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penSubTitle);
gr->penSubTitle=-1;
}
if (gr->penAxisLabel>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxisLabel);
gr->penAxisLabel=-1;
}
if (gr->penAxis>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxis);
gr->penAxis=-1;
}
if (gr->penGraph>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraph);
gr->penGraph=-1;
}
if (gr->penGraphBackground>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraphBackground);
gr->penGraphBackground=-1;
}
if (gr->penGrid>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGrid);
gr->penGrid=-1;
}
if (gr->fontTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTitle);
gr->fontTitle=-1;
}
if (gr->fontSubTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontSubTitle);
gr->fontSubTitle=-1;
}
if (gr->fontAxisLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontAxisLabel);
gr->fontAxisLabel=-1;
}
if (gr->fontTickLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTickLabel);
gr->fontTickLabel=-1;
}
}
int _createPenFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name)
{
GWEN_DB_NODE *db;
uint32_t frontColour;
int lineWidth;
int dashType;
int rv;
db=GWEN_DB_GetGroup(dbConfig, 0, name);
assert(db);
frontColour=(uint32_t)GWEN_DB_GetIntValue(db, "frontColour", 0, (int)0x000000ff);
lineWidth=GWEN_DB_GetIntValue(db, "lineWidth", 0, 1);
dashType=GWEN_DB_GetIntValue(db, "dashType", 0, 0);
rv=AQDG_Draw_Context_PenCreate(gr->drawContext, frontColour, lineWidth, dashType);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
return rv;
}
int _createFontFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize)
{
GWEN_DB_NODE *db;
const char *fontName;
int fontSize;
int fontSlant;
int fontWeight;
int rv;
db=GWEN_DB_GetGroup(dbConfig, 0, name);
assert(db);
fontName=GWEN_DB_GetCharValue(db, "fontName", 0, "");
fontSize=GWEN_DB_GetIntValue(db, "fontSize", 0, defaultFontSize);
fontSlant=AQDG_Slant_fromString(GWEN_DB_GetCharValue(db, "fontSlant", 0, "none"));
fontWeight=AQDG_Weight_fromString(GWEN_DB_GetCharValue(db, "fontWeight", 0, "none"));
rv=AQDG_Draw_Context_FontCreate(gr->drawContext, fontName, fontSize, fontSlant, fontWeight);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
return rv;
}
int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
{
int rv;
AQDG_GRAPH_SUBGRAPH_LIST *sgList;
rv=_createPenFromConfig(gr, dbConfig, "penTitle");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penTitle=rv;
rv=_createPenFromConfig(gr, dbConfig, "penSubTitle");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penSubTitle=rv;
rv=_createPenFromConfig(gr, dbConfig, "penAxisLabel");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxisLabel=rv;
rv=_createPenFromConfig(gr, dbConfig, "penAxis");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxis=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGraph");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraph=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGraphBackground");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraphBackground=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGrid");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGrid=rv;
rv=_createPenFromConfig(gr, dbConfig, "penBackground");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penBackground=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontTitle", 16);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontTitle=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontSubTitle", 14);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontSubTitle=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontAxisLabel", 12);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontAxisLabel=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontTickLabel", 10);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontTickLabel=rv;
/* create pens for graphs */
sgList=AQDG_Graph_DataSet_GetSubGraphList(gr->dataSet);
if (sgList) {
AQDG_GRAPH_SUBGRAPH *sg;
sg=AQDG_Graph_SubGraph_List_First(sgList);
while (sg) {
rv=AQDG_Draw_Context_PenCreate(gr->drawContext,
AQDG_Graph_SubGraph_GetColour(sg),
AQDG_Graph_SubGraph_GetLineWidth(sg),
AQDG_Graph_SubGraph_GetDashType(sg));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
AQDG_Graph_SubGraph_SetPenId(sg, rv);
sg=AQDG_Graph_SubGraph_List_Next(sg);
}
}
return 0;
}
int _createPenFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_PEN *sp)
{
int rv;
rv=AQDG_Draw_Context_PenCreate(gr->drawContext,
AQDG_Graph_SettingsPen_GetFrontColour(sp),
AQDG_Graph_SettingsPen_GetLineWidth(sp),
AQDG_Graph_SettingsPen_GetDashType(sp));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
return rv;
}
int _createFontFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_FONT *sf)
{
int rv;
rv=AQDG_Draw_Context_FontCreate(gr->drawContext, "",
AQDG_Graph_SettingsFont_GetFontSize(sf),
AQDG_Graph_SettingsFont_GetFontSlant(sf),
AQDG_Graph_SettingsFont_GetFontWeight(sf));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
return rv;
}
int _createPensAndFontsFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *settings)
{
int rv;
const AQDG_GRAPH_SETTINGS_PEN *pen;
const AQDG_GRAPH_SETTINGS_FONT *fnt;
const AQDG_GRAPH_SUBGRAPH_LIST *sgList;
pen=AQDG_Graph_Settings_GetPenTitle(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penTitle=rv;
}
pen=AQDG_Graph_Settings_GetPenSubTitle(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penSubTitle=rv;
}
pen=AQDG_Graph_Settings_GetPenAxisLabel(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxisLabel=rv;
}
pen=AQDG_Graph_Settings_GetPenAxis(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxis=rv;
}
pen=AQDG_Graph_Settings_GetPenGraph(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraph=rv;
}
pen=AQDG_Graph_Settings_GetPenGraphBackground(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraphBackground=rv;
}
pen=AQDG_Graph_Settings_GetPenGrid(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGrid=rv;
}
pen=AQDG_Graph_Settings_GetPenBackground(settings);
if (pen) {
rv=_createPenFromSettings(gr, pen);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penBackground=rv;
}
fnt=AQDG_Graph_Settings_GetFontTitle(settings);
if (fnt) {
rv=_createFontFromSettings(gr, fnt);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontTitle=rv;
}
fnt=AQDG_Graph_Settings_GetFontSubTitle(settings);
if (fnt) {
rv=_createFontFromSettings(gr, fnt);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontSubTitle=rv;
}
fnt=AQDG_Graph_Settings_GetFontAxisLabel(settings);
if (fnt) {
rv=_createFontFromSettings(gr, fnt);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontAxisLabel=rv;
}
fnt=AQDG_Graph_Settings_GetFontTickLabel(settings);
if (fnt) {
rv=_createFontFromSettings(gr, fnt);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontTickLabel=rv;
}
/* create pens for graphs */
sgList=AQDG_Graph_DataSet_GetSubGraphList(gr->dataSet);
if (sgList) {
AQDG_GRAPH_SUBGRAPH *sg;
sg=AQDG_Graph_SubGraph_List_First(sgList);
while (sg) {
rv=AQDG_Draw_Context_PenCreate(gr->drawContext,
AQDG_Graph_SubGraph_GetColour(sg),
AQDG_Graph_SubGraph_GetLineWidth(sg),
AQDG_Graph_SubGraph_GetDashType(sg));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
AQDG_Graph_SubGraph_SetPenId(sg, rv);
sg=AQDG_Graph_SubGraph_List_Next(sg);
}
}
return 0;
}

View File

@@ -0,0 +1,18 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_CONFIG_H
#define AQDG_G_CONFIG_H
#include <aqdiagram/graph/graph.h>
#endif

View File

@@ -0,0 +1,245 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "aqdiagram/graph/dataset_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
int lastX;
int lastY;
int first=1;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
if (!first)
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, lastX, lastY, x, y);
else
first=0;
lastX=x;
lastY=y;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
int leftX, bw;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw the bar */
if ((x-(barWidth/2))<gr->graphAreaPosX) {
leftX=x;
bw=barWidth/2;
}
else {
leftX=x-(barWidth/2);
bw=barWidth;
}
if ((leftX+bw)>=(gr->graphAreaPosX+gr->graphAreaWidth)) {
bw=barWidth/2;
}
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, penId,
leftX, gr->xAxisPosY,
bw, y-gr->xAxisPosY);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DrawDataAsPoints(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}

View File

@@ -0,0 +1,24 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_DRAW_DATA_H
#define AQDG_G_DRAW_DATA_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId);
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId);
void AQDG_Graph_DrawDataAsPoints(AQDG_GRAPH *gr, int level, int penId);
#endif

View File

@@ -0,0 +1,232 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawXTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetXTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaWidth);
assert(pMask);
memset(pMask, 0, gr->graphAreaWidth);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxWidth=0;
int every=1;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "X-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxWidth)
maxWidth=i;
}
}
else {
DBG_ERROR(0, "X-Level %d: No tick label", level);
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
/* check medium width for the current level */
{
int first=1;
int hasSecond=0;
double lastValue;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (first) {
lastValue=v;
first=0;
}
else {
int dist;
dist=(int)((v-lastValue)*gr->graphFactorX);
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
else if ((dist*2)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=2;
}
else if ((dist*4)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=4;
}
DBG_ERROR(0, "X-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
hasSecond=1;
break;
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (!first && !hasSecond) {
int dist;
dist=gr->graphAreaWidth;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxWidth+SMALL_BORDER)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
DBG_ERROR(0, "X-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
}
}
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
int tickIntervalCnt=every;
minVal=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
tickIntervalCnt--;
v=AQDG_Graph_Tick_GetValue(t);
if (v>=minVal && v<=maxVal) {
int x, y;
int w;
x=gr->graphOriginX + (v * gr->graphFactorX);
y=gr->xAxisPosY;
/* draw grid line */
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, x, gr->graphAreaPosY, x, gr->graphAreaPosY+gr->graphAreaHeight);
}
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x, y-w, x, y+w);
}
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
if (tickIntervalCnt<1) {
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->penAxisLabel, s);
if (i<0) {
}
else {
if ((x+(i/2) < (gr->graphAreaPosX+gr->graphAreaWidth)) &&
(x-(i/2) > gr->graphAreaPosX)) {
int j;
int doesFit=1;
int m1, m2;
m1=SMALL_BORDER+x-(i/2)-gr->graphAreaPosX;
m2=SMALL_BORDER+x+(i/2)-gr->graphAreaPosX;
for (j=m1; j<m2; j++) {
if (pMask[j]!=0) {
doesFit=0;
break;
}
}
if (doesFit) {
m1=x-(i/2)-gr->graphAreaPosX;
m2=x+(i/2)-gr->graphAreaPosX;
for (j=m1; j<m2; j++)
pMask[j]=1;
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
x-(i/2), gr->xTickLabelPosY, s);
}
}
}
}
tickIntervalCnt=every;
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}

View File

@@ -0,0 +1,22 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_DRAW_XTICKS_H
#define AQDG_G_DRAW_XTICKS_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawXTicks(AQDG_GRAPH *gr);
#endif

View File

@@ -0,0 +1,214 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawYTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetYTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaHeight);
assert(pMask);
memset(pMask, 0, gr->graphAreaHeight);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxHeight=0;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "Y-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxHeight)
maxHeight=i;
}
}
else {
DBG_ERROR(0, "No tick label");
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
/* get 1st and 2nd entry for the current level and check width */
{
int first=1;
int hasSecond=0;
double lastValue;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (first) {
lastValue=v;
first=0;
}
else {
int dist;
dist=(int)((v-lastValue)*gr->graphFactorY);
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+5)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
DBG_ERROR(0, "Y-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
hasSecond=1;
break;
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (!first && !hasSecond) {
int dist;
dist=gr->graphAreaHeight;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+2)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
}
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
minVal=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (AQDG_Graph_Tick_GetLevel(t)==level) {
if (v>=minVal && v<=maxVal) {
int x, y;
int w;
x=gr->yAxisPosX;
y=gr->graphOriginY - (v * gr->graphFactorY);
/* draw grid line */
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, gr->graphAreaPosX, y, gr->graphAreaPosX+gr->graphAreaWidth, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x-w, y, x+w, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->penAxisLabel, s);
if (i<0) {
}
else {
if ((y+(i/2) < (gr->graphAreaPosY+gr->graphAreaHeight)) &&
(y-(i/2)>= gr->graphAreaPosY)) {
int j;
int doesFit=1;
int m1, m2;
m1=SMALL_BORDER+y-(i/2)-gr->graphAreaPosY;
m2=SMALL_BORDER+y+(i/2)-gr->graphAreaPosY;
for (j=m1; j<m2; j++) {
if (pMask[j]!=0) {
doesFit=0;
break;
}
}
if (doesFit) {
m1=y-(i/2)-gr->graphAreaPosY;
m2=y+(i/2)-gr->graphAreaPosY;
for (j=m1; j<m2; j++)
pMask[j]=1;
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
gr->yTickLabelPosX, y-(i/2), s);
}
}
}
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}

View File

@@ -0,0 +1,22 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_DRAW_YTICKS_H
#define AQDG_G_DRAW_YTICKS_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawYTicks(AQDG_GRAPH *gr);
#endif

View File

@@ -0,0 +1,311 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_layout.h"
#include "aqdiagram/graph/tick_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
static void _getTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight);
static void _sampleSizes(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
static void _layout(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
static void _calcGraphArea(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetXTickList(gr->dataSet);
if (tl)
AQDG_Graph_Tick_List_SortByValueAndLevel(tl, 1);
tl=AQDG_Graph_DataSet_GetYTickList(gr->dataSet);
if (tl)
AQDG_Graph_Tick_List_SortByValueAndLevel(tl, 1);
_sampleSizes(gr, gr->dataSet);
_layout(gr, gr->dataSet);
_calcGraphArea(gr, gr->dataSet);
}
void _getTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight)
{
if (tl) {
AQDG_GRAPH_TICK *t;
int maxWidth=0;
int maxHeight=0;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxWidth)
maxWidth=i;
}
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text height (%d)", i);
}
else {
if (i>maxHeight)
maxHeight=i;
}
}
else {
DBG_ERROR(0, "No tick label");
}
t=AQDG_Graph_Tick_List_Next(t);
}
*pMaxWidth=maxWidth;
*pMaxHeight=maxHeight;
}
}
void _sampleSizes(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds)
{
AQDG_GRAPH_TICK_LIST *tl;
const char *s;
gr->xTickLabelMaxWidth=-1;
gr->xTickLabelMaxHeight=-1;
gr->xTickLabelPosY=-1;
tl=AQDG_Graph_DataSet_GetXTickList(ds);
if (tl)
_getTickLabelMaxSizes(gr, tl, &(gr->xTickLabelMaxWidth), &(gr->xTickLabelMaxHeight));
gr->yTickLabelMaxWidth=-1;
gr->yTickLabelMaxHeight=-1;
gr->yTickLabelPosX=-1;
tl=AQDG_Graph_DataSet_GetYTickList(ds);
if (tl)
_getTickLabelMaxSizes(gr, tl, &(gr->yTickLabelMaxWidth), &(gr->yTickLabelMaxHeight));
/* title */
gr->titleWidth=-1;
gr->titleHeight=-1;
gr->titlePosX=-1;
gr->titlePosY=-1;
s=AQDG_Graph_DataSet_GetTitle(ds);
if (s && *s) {
gr->titleWidth=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontTitle, s);
gr->titleHeight=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontTitle, s);
}
/* subTitle */
gr->subTitleWidth=-1;
gr->subTitleHeight=-1;
gr->subTitlePosX=-1;
gr->subTitlePosY=-1;
s=AQDG_Graph_DataSet_GetSubTitle(ds);
if (s && *s) {
gr->subTitleWidth=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontSubTitle, s);
gr->subTitleHeight=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontSubTitle, s);
}
/* xLabel */
gr->xAxisLabelWidth=-1;
gr->xAxisLabelHeight=-1;
gr->xAxisLabelPosX=-1;
gr->xAxisLabelPosY=-1;
s=AQDG_Graph_DataSet_GetLabelX(ds);
if (s && *s) {
gr->xAxisLabelWidth=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontAxisLabel, s);
gr->xAxisLabelHeight=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontAxisLabel, s);
}
/* yAxisLabel */
gr->yAxisLabelWidth=-1;
gr->yAxisLabelHeight=-1;
gr->yAxisLabelPosX=-1;
gr->yAxisLabelPosY=-1;
s=AQDG_Graph_DataSet_GetLabelY(ds);
if (s && *s) {
gr->yAxisLabelWidth=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontAxisLabel, s);
gr->yAxisLabelHeight=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontAxisLabel, s);
}
gr->graphAreaWidth=-1;
gr->graphAreaHeight=-1;
gr->graphAreaPosX=-1;
gr->graphAreaPosY=-1;
}
void _layout(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds)
{
int graphAreaMinX;
int graphAreaMinY;
int graphAreaMaxX;
int graphAreaMaxY;
graphAreaMinX=BORDER;
graphAreaMaxX=gr->width-BORDER-1;
graphAreaMinY=BORDER;
graphAreaMaxY=gr->height-BORDER-1;
/* title */
if (gr->titleWidth>0 && gr->titleHeight>0) {
gr->titlePosX=(gr->width-gr->titleWidth)/2;
gr->titlePosY=graphAreaMinY;
graphAreaMinY+=gr->titleHeight+SMALL_BORDER;
}
/* subtitle */
if (gr->subTitleWidth>0 && gr->subTitleHeight>0) {
gr->subTitlePosX=(gr->width-gr->subTitleWidth)/2;
gr->subTitlePosY=graphAreaMinY;
graphAreaMinY+=gr->subTitleHeight+SMALL_BORDER;
}
/* y-axis label */
if (gr->yAxisLabelWidth>0 && gr->yAxisLabelHeight>0) {
gr->yAxisLabelPosX=BORDER;
gr->yAxisLabelPosY=graphAreaMinY;
graphAreaMinY+=gr->yAxisLabelHeight+BORDER;
}
/* X-axis label */
if (gr->xAxisLabelWidth>0 && gr->xAxisLabelHeight>0) {
gr->xAxisLabelPosX=graphAreaMaxX-gr->xAxisLabelWidth;
gr->xAxisLabelPosY=gr->height-gr->xAxisLabelHeight-BORDER;
graphAreaMaxX=gr->xAxisLabelPosX-BORDER;
}
/* y-axis ticklabels */
if (gr->yTickLabelMaxWidth>0 && gr->yTickLabelMaxHeight>0) {
gr->yTickLabelPosX=BORDER;
graphAreaMinX+=gr->yTickLabelMaxWidth+BORDER;
}
/* x-axis ticklabels */
if (gr->xTickLabelMaxWidth>0 && gr->xTickLabelMaxHeight>0) {
gr->xTickLabelPosY=gr->height-gr->xTickLabelMaxHeight-BORDER;
graphAreaMaxY=gr->xTickLabelPosY-BORDER;
}
/* determine graphics area */
gr->graphAreaWidth=(graphAreaMaxX-graphAreaMinX);
gr->graphAreaHeight=(graphAreaMaxY-graphAreaMinY);
gr->graphAreaPosX=graphAreaMinX;
gr->graphAreaPosY=graphAreaMinY;
}
void _calcGraphArea(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds)
{
double minVal;
double maxVal;
double dist;
/* determine X-offset of graph origin and xFactor */
minVal=AQDG_Graph_DataSet_GetMinValueX(ds);
maxVal=AQDG_Graph_DataSet_GetMaxValueX(ds);
gr->graphFactorX=gr->graphAreaWidth/(maxVal-minVal);
if (minVal<=0.0 && maxVal>=0.0) {
/* one negative, the other positive */
dist=-minVal;
gr->graphOriginX=gr->graphAreaPosX+dist*gr->graphFactorX;
}
else if (minVal<0.0 && maxVal<0.0) {
/* both negative */
dist=-minVal;
gr->graphOriginX=gr->graphAreaPosX+dist*gr->graphFactorX;
}
else if (minVal>0.0 && maxVal>=0.0) {
/* both positive */
dist=minVal;
gr->graphOriginX=gr->graphAreaPosX-dist*gr->graphFactorX;
}
/* determine x-pos of the y-axis */
if (gr->graphOriginX<gr->graphAreaPosX) {
/* y-axis on left border */
gr->yAxisPosX=gr->graphAreaPosX;
}
else if (gr->graphOriginX>=gr->graphAreaWidth) {
/* y-axis on right border */
gr->yAxisPosX=gr->graphAreaPosX+gr->graphAreaWidth-1;
}
else {
/* y-axis somewhere within the graph area */
gr->yAxisPosX=gr->graphOriginX;
}
/* determine Y-offset of graph origin and yFactor */
minVal=AQDG_Graph_DataSet_GetMinValueY(ds);
maxVal=AQDG_Graph_DataSet_GetMaxValueY(ds);
gr->graphFactorY=gr->graphAreaHeight/(maxVal-minVal);
if (minVal<=0.0 && maxVal>=0.0) {
/* one negative, the other positive */
dist=maxVal;
gr->graphOriginY=gr->graphAreaPosY+(dist*gr->graphFactorY);
}
else if (minVal<0.0 && maxVal<0.0) {
/* both negative */
dist=maxVal;
gr->graphOriginY=gr->graphAreaPosY+dist*gr->graphFactorY;
}
else if (minVal>0.0 && maxVal>0.0) {
/* both positive */
dist=maxVal;
gr->graphOriginY=gr->graphAreaPosY+(dist*gr->graphFactorY);
}
/* determine y-pos of the x-axis */
if (gr->graphOriginY<gr->graphAreaPosY) {
/* y-axis on upper border */
gr->xAxisPosY=gr->graphAreaPosY;
}
else if (gr->graphOriginY>=gr->graphAreaHeight) {
/* x-axis on lower border */
gr->xAxisPosY=gr->graphAreaPosY+gr->graphAreaHeight-1;
}
else {
/* y-axis somewhere within the graph area */
gr->xAxisPosY=gr->graphOriginY;
}
DBG_ERROR(0, "Origin: %d / %d (Axis: x-axis y=%d / y-axis x=%d)",
gr->graphOriginX, gr->graphOriginY,
gr->xAxisPosY, gr->yAxisPosX);
}

View File

@@ -0,0 +1,22 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_LAYOUT_H
#define AQDG_G_LAYOUT_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr);
#endif

View File

@@ -0,0 +1,167 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "graph_p.h"
#include "aqdiagram/graph/g_draw_data.h"
#include "aqdiagram/graph/g_draw_xticks.h"
#include "aqdiagram/graph/g_draw_yticks.h"
#include "aqdiagram/graph/g_layout.h"
#include "aqdiagram/graph/g_config.h"
#include <gwenhywfar/debug.h>
GWEN_LIST_FUNCTIONS(AQDG_GRAPH, AQDG_Graph)
GWEN_LIST2_FUNCTIONS(AQDG_GRAPH, AQDG_Graph)
AQDG_GRAPH *AQDG_Graph_new(AQDG_GRAPH_DATASET *ds, AQDG_DRAW_CONTEXT *drawContext, int width, int height)
{
AQDG_GRAPH *gr;
GWEN_NEW_OBJECT(AQDG_GRAPH, gr);
GWEN_LIST_INIT(AQDG_GRAPH, gr)
gr->dataSet=ds;
gr->drawContext=drawContext;
gr->width=width;
gr->height=height;
return gr;
}
void AQDG_Graph_free(AQDG_GRAPH *gr)
{
if (gr) {
GWEN_LIST_FINI(AQDG_GRAPH, gr)
AQDG_Draw_Context_free(gr->drawContext);
AQDG_Graph_DataSet_free(gr->dataSet);
GWEN_FREE_OBJECT(gr);
}
}
void AQDG_Graph_DrawFramework(AQDG_GRAPH *gr)
{
const char *s;
/* draw background */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penBackground,
0, 0, gr->width, gr->height);
/* draw graph area */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penGraphBackground,
gr->graphAreaPosX, gr->graphAreaPosY,
gr->graphAreaWidth, gr->graphAreaHeight);
AQDG_Graph_DrawXTicks(gr);
/* draw x-axis */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->graphAreaPosX, gr->xAxisPosY,
gr->graphAreaPosX+gr->graphAreaWidth, gr->xAxisPosY);
/* x-axis label */
s=AQDG_Graph_DataSet_GetLabelX(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->xAxisLabelPosX, gr->xAxisLabelPosY, s);
/* draw y ticks */
AQDG_Graph_DrawYTicks(gr);
/* draw y-axis */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->yAxisPosX, gr->graphAreaPosY,
gr->yAxisPosX, gr->graphAreaPosY+gr->graphAreaHeight);
/* y-axis label */
s=AQDG_Graph_DataSet_GetLabelY(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->yAxisLabelPosX, gr->yAxisLabelPosY, s);
/* title */
s=AQDG_Graph_DataSet_GetTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penTitle, gr->fontTitle, AQDG_Direction_Horizontal,
gr->titlePosX, gr->titlePosY, s);
/* subtitle */
s=AQDG_Graph_DataSet_GetSubTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penSubTitle, gr->fontSubTitle, AQDG_Direction_Horizontal,
gr->subTitlePosX, gr->subTitlePosY, s);
}
int AQDG_Graph_Draw(AQDG_GRAPH *gr)
{
AQDG_GRAPH_SUBGRAPH_LIST *sgList;
AQDG_Graph_PrepareGraph(gr);
AQDG_Graph_DrawFramework(gr);
/* draw all levels */
sgList=AQDG_Graph_DataSet_GetSubGraphList(gr->dataSet);
if (sgList) {
AQDG_GRAPH_SUBGRAPH *sg;
sg=AQDG_Graph_SubGraph_List_First(sgList);
while (sg) {
/* TODO: select graph type */
switch (AQDG_Graph_SubGraph_GetGraphType(sg)) {
case AQDG_GRAPH_TYPE_POINTS:
AQDG_Graph_DrawDataAsPoints(gr, AQDG_Graph_SubGraph_GetLevel(sg), AQDG_Graph_SubGraph_GetPenId(sg));
break;
case AQDG_GRAPH_TYPE_LINE:
AQDG_Graph_DrawDataAsLine(gr, AQDG_Graph_SubGraph_GetLevel(sg), AQDG_Graph_SubGraph_GetPenId(sg));
break;
case AQDG_GRAPH_TYPE_BARS:
AQDG_Graph_DrawDataAsBars(gr, AQDG_Graph_SubGraph_GetLevel(sg), AQDG_Graph_SubGraph_GetPenId(sg));
break;
case AQDG_GRAPH_TYPE_NONE:
case AQDG_GRAPH_TYPE_UNKNOWN:
break;
}
sg=AQDG_Graph_SubGraph_List_Next(sg);
}
}
return 0;
}

View File

@@ -0,0 +1,71 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_GRAPH_H
#define AQDG_GRAPH_H
#include <aqdiagram/aqdiagram.h>
#include <aqdiagram/draw/context.h>
#include <aqdiagram/graph/dataset.h>
#include <aqdiagram/graph/subgraph.h>
#include <aqdiagram/graph/settings.h>
#include <gwenhywfar/db.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AQDG_GRAPH AQDG_GRAPH;
GWEN_LIST_FUNCTION_LIB_DEFS(AQDG_GRAPH, AQDG_Graph, AQDG_API)
GWEN_LIST2_FUNCTION_LIB_DEFS(AQDG_GRAPH, AQDG_Graph, AQDG_API)
#define AQDG_GRAPH_FLAGS_WITH_GRID 0x00000001
enum {
AQDG_GRAPH_TYPE_UNKNOWN=-1,
AQDG_GRAPH_TYPE_NONE=0,
AQDG_GRAPH_TYPE_LINE,
AQDG_GRAPH_TYPE_POINTS,
AQDG_GRAPH_TYPE_BARS
};
/**
* Takes over AQDG_GRAPHICS object (use AQDG_Graphics_Attach if you still need that object after destroying AQDG_GRAPH).
*/
AQDG_API AQDG_GRAPH *AQDG_Graph_new(AQDG_GRAPH_DATASET *ds, AQDG_DRAW_CONTEXT *drawContext, int width, int height);
AQDG_API void AQDG_Graph_free(AQDG_GRAPH *gr);
AQDG_API int AQDG_Graph_Init_fromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig);
AQDG_API int AQDG_Graph_Init(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *gs);
AQDG_API int AQDG_Graph_Fini(AQDG_GRAPH *gr);
AQDG_API int AQDG_Graph_Draw(AQDG_GRAPH *gr);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,104 @@
/****************************************************************************
* This file is part of the project AqFinance.
* AqFinance (c) by 2013 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_GRAPH_P_H
#define AQDG_GRAPH_P_H
#include <aqdiagram/graph/graph.h>
#define MAX_TICK_LEVELS 5
#define BORDER 12
#define SMALL_BORDER 8
#define MIN_DIST_FOR_TICKS 5
#define MIN_DIST_FOR_GRIDS 5
#define TICKDRAWFLAGS_MARKS 0x01
#define TICKDRAWFLAGS_GRIDS 0x02
#define TICKDRAWFLAGS_LABELS 0x04
struct AQDG_GRAPH {
GWEN_LIST_ELEMENT(AQDG_GRAPH)
AQDG_GRAPH_DATASET *dataSet;
AQDG_DRAW_CONTEXT *drawContext;
int width;
int height;
int penTitle;
int penSubTitle;
int penAxisLabel;
int penAxis;
int penGraph;
int penGraphBackground;
int penGrid;
int penBackground;
int fontTitle;
int fontSubTitle;
int fontAxisLabel;
int fontTickLabel;
int xTickLabelMaxWidth;
int xTickLabelMaxHeight;
int xTickLabelPosY;
int yTickLabelMaxWidth;
int yTickLabelMaxHeight;
int yTickLabelPosX;
int titleWidth;
int titleHeight;
int titlePosX;
int titlePosY;
int subTitleWidth;
int subTitleHeight;
int subTitlePosX;
int subTitlePosY;
int xAxisLabelWidth;
int xAxisLabelHeight;
int xAxisLabelPosX;
int xAxisLabelPosY;
int yAxisLabelWidth;
int yAxisLabelHeight;
int yAxisLabelPosX;
int yAxisLabelPosY;
int graphAreaWidth;
int graphAreaHeight;
int graphAreaPosX;
int graphAreaPosY;
double graphFactorX;
double graphFactorY;
int graphOriginX;
int graphOriginY;
int yAxisPosX;
int xAxisPosY;
uint32_t flags;
};
#endif

View File

@@ -0,0 +1,259 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_SETTINGS" type="pointer">
<descr>
This class describes data axis.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_SETTINGS</identifier>
<prefix>AQDG_Graph_Settings</prefix>
<baseFileName>settings</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
<header type="sys" loc="pre">aqdiagram/draw/context.h</header>
<header type="sys" loc="post">aqdiagram/graph/graph.h</header>
<header type="sys" loc="post">aqdiagram/graph/settings_pen.h</header>
<header type="sys" loc="post">aqdiagram/graph/settings_font.h</header>
</headers>
<inlines>
<inline loc="end" access="public">
<content>
$(api) void $(struct_prefix)_SetDefaults($(struct_type) *st);
</content>
</inline>
<inline loc="code">
<content>
void $(struct_prefix)_SetDefaults($(struct_type) *rs) {
AQDG_GRAPH_SETTINGS_PEN *pen;
AQDG_GRAPH_SETTINGS_FONT *font;
assert(rs);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0x00000000);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenTitle(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0xff000000);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenSubTitle(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0x0000000);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenAxisLabel(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0x0000ff00);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenAxis(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0x00ff0000);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenGraph(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0xffec5b00);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenGraphBackground(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0xc0c0c000);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 1);
$(struct_prefix)_SetPenGrid(rs, pen);
pen=AQDG_Graph_SettingsPen_new();
AQDG_Graph_SettingsPen_SetFrontColour(pen, (int)0xffffff00);
AQDG_Graph_SettingsPen_SetLineWidth(pen, 1);
AQDG_Graph_SettingsPen_SetDashType(pen, 0);
$(struct_prefix)_SetPenBackground(rs, pen);
font=AQDG_Graph_SettingsFont_new();
AQDG_Graph_SettingsFont_SetFontSize(font, 20);
AQDG_Graph_SettingsFont_SetFontSlant(font, AQDG_Slant_None);
AQDG_Graph_SettingsFont_SetFontWeight(font, AQDG_Weight_Bold);
$(struct_prefix)_SetFontTitle(rs, font);
font=AQDG_Graph_SettingsFont_new();
AQDG_Graph_SettingsFont_SetFontSize(font, 16);
AQDG_Graph_SettingsFont_SetFontSlant(font, AQDG_Slant_Italic);
AQDG_Graph_SettingsFont_SetFontWeight(font, AQDG_Weight_None);
$(struct_prefix)_SetFontSubTitle(rs, font);
font=AQDG_Graph_SettingsFont_new();
AQDG_Graph_SettingsFont_SetFontSize(font, 12);
AQDG_Graph_SettingsFont_SetFontSlant(font, AQDG_Slant_None);
AQDG_Graph_SettingsFont_SetFontWeight(font, AQDG_Weight_None);
$(struct_prefix)_SetFontAxisLabel(rs, font);
font=AQDG_Graph_SettingsFont_new();
AQDG_Graph_SettingsFont_SetFontSize(font, 9);
AQDG_Graph_SettingsFont_SetFontSlant(font, AQDG_Slant_None);
AQDG_Graph_SettingsFont_SetFontWeight(font, AQDG_Weight_None);
$(struct_prefix)_SetFontTickLabel(rs, font);
$(struct_prefix)_AddFlags(rs, AQDG_GRAPH_FLAGS_WITH_GRID);
}
</content>
</inline>
</inlines>
</lang>
<defines>
<define id="AQDG_GRAPH_SETTINGS_FLAGS" prefix="AQDG_GRAPH_SETTINGS_FLAGS_">
</define>
</defines>
<members>
<member name="id" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
</member>
<member name="penTitle" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penSubTitle" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penAxisLabel" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penAxis" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penGraph" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penGraphBackground" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penGrid" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="penBackground" type="AQDG_GRAPH_SETTINGS_PEN" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="fontTitle" type="AQDG_GRAPH_SETTINGS_FONT" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="fontSubTitle" type="AQDG_GRAPH_SETTINGS_FONT" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="fontAxisLabel" type="AQDG_GRAPH_SETTINGS_FONT" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="fontTickLabel" type="AQDG_GRAPH_SETTINGS_FONT" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
<setflags>assign</setflags>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,79 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_SETTINGS_FONT" type="pointer">
<descr>
This class describes data axis.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_SETTINGS_FONT</identifier>
<prefix>AQDG_Graph_SettingsFont</prefix>
<baseFileName>settings_font</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
</headers>
</lang>
<defines>
<define id="AQDG_GRAPH_SETTINGS_FONT_FLAGS" prefix="AQDG_GRAPH_SETTINGS_FONT_FLAGS_">
</define>
</defines>
<members>
<member name="fontSize" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="fontSlant" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="fontWeight" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
<member name="id" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>volatile with_getbymember</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,86 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_SETTINGS_PEN" type="pointer">
<descr>
This class describes data axis.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_SETTINGS_PEN</identifier>
<prefix>AQDG_Graph_SettingsPen</prefix>
<baseFileName>settings_pen</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
</headers>
</lang>
<defines>
<define id="AQDG_GRAPH_SETTINGS_PEN_FLAGS" prefix="AQDG_GRAPH_SETTINGS_PEN_FLAGS_">
</define>
</defines>
<members>
<member name="frontColour" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="backColour" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="lineWidth" type="int" maxlen="8" >
<default>1</default>
<preset>1</preset>
<access>public</access>
</member>
<member name="dashType" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
<member name="id" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>volatile with_getbymember</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,89 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_SUBGRAPH" type="pointer">
<descr>
This class describes a sub graph.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_SUBGRAPH</identifier>
<prefix>AQDG_Graph_SubGraph</prefix>
<baseFileName>subgraph</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
</headers>
</lang>
<members>
<member name="label" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="level" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
</member>
<member name="graphType" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="dataMode" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="colour" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="lineWidth" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="dashType" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="penId" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>volatile</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,71 @@
<?xml?>
<tm2>
<type id="AQDG_GRAPH_TICK" type="pointer">
<descr>
This class describes data axis.
</descr>
<lang id="c">
<identifier>AQDG_GRAPH_TICK</identifier>
<prefix>AQDG_Graph_Tick</prefix>
<baseFileName>tick</baseFileName>
<flags>
with_db
with_xml
with_list1
with_list2
with_refcount
</flags>
<headers>
<header type="sys" loc="pre">aqdiagram/aqdg_api.h</header>
<header type="sys" loc="post">aqdiagram/graph/dataset.h</header>
<header type="sys" loc="post">aqdiagram/graph/tick_fns.h</header>
<header type="local" loc="codeEnd">tick_fns.c</header>
<header type="sys" loc="pre">gwenhywfar/gwendate.h</header>
<header type="sys" loc="pre">gwenhywfar/i18n.h</header>
</headers>
</lang>
<members>
<member name="label" type="char_ptr" maxlen="128" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<setflags>const dup</setflags>
<getflags>const</getflags>
</member>
<member name="value" type="double" maxlen="8" >
<default>0.0</default>
<preset>0.0</preset>
<access>public</access>
<flags>sortbymember</flags>
</member>
<member name="level" type="int" maxlen="8" >
<default>0</default>
<preset>0</preset>
<access>public</access>
</member>
<member name="flags" type="uint32_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<flags>with_flags</flags>
<access>public</access>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,607 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#define I18N(msg) GWEN_I18N_Translate("aqdiagram", msg)
double AQDG_Graph_Tick_GetRoundedMaxVal(double val)
{
double maxVal;
if (val<0.0)
val=-val;
if (val>100000000.0)
maxVal=1000000000.0;
else if (val>10000000.0)
maxVal=100000000.0;
else if (val>1000000.0)
maxVal=10000000.0;
else if (val>100000.0)
maxVal=1000000.0;
else if (val>10000.0)
maxVal=100000.0;
else if (val>1000.0)
maxVal=10000.0;
else if (val>100.0)
maxVal=1000.0;
else if (val>10.0)
maxVal=100.0;
else if (val>10.0)
maxVal=100.0;
else if (val>1.0)
maxVal=10.0;
else if (val>0.1)
maxVal=1.0;
else if (val>0.01)
maxVal=0.1;
else if (val>0.001)
maxVal=0.01;
else if (val>0.0001)
maxVal=0.001;
else if (val>0.00001)
maxVal=0.0001;
else if (val>0.000001)
maxVal=0.00001;
else if (val<0.000001)
maxVal=0.000001;
else
maxVal=1;
return maxVal;
}
static void AQDG_Graph_Tick_AddTicks_IntSubTicks(AQDG_GRAPH_TICK_LIST *tickList,
double minVal, double maxVal, double stepFactor, int level)
{
double vCurrent;
double vMin, vMax, v;
double steps;
vMin=AQDG_Graph_Tick_GetRoundedMaxVal(minVal);
if (minVal<0.0)
vMin=-vMin;
vMax=AQDG_Graph_Tick_GetRoundedMaxVal(maxVal);
if (maxVal<0.0)
vMax=-vMax;
v=(vMin>vMax)?vMin:vMax;
steps=v/stepFactor;
if (vMin<0.0 && vMax>0.0) {
/* create ticks for negative values */
vCurrent=-v;
while (vCurrent<0.0) {
if (vCurrent>=minVal) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%d", (int)vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent+=steps;
}
/* create ticks for positive values */
vCurrent=0.0;
while (vCurrent<=vMax) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%d", (int)vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
vCurrent+=steps;
}
}
else if (vMin<0.0 && vMax<0.0) {
/* create ticks for negative values */
vCurrent=-v;
while (vCurrent<=vMax) {
if (vCurrent>=vMin) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%d", (int)vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent-=steps;
}
}
else if (vMin>0.0 && vMax>0.0) {
/* create ticks for negative values */
vCurrent=0.0;
while (vCurrent<=vMax) {
if (vCurrent>=vMin) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%d", (int)vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent+=steps;
}
}
}
void AQDG_Graph_Tick_AddTicks_Int(AQDG_GRAPH_TICK_LIST *tickList, double minVal, double maxVal)
{
DBG_ERROR(0, "Creating ticks from minVal=%f to maxVal=%f", minVal, maxVal);
#if 0
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 10.0, 1);
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 20.0, 2);
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 100.0, 3);
#else
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 2.0, 1);
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 20.0, 2);
AQDG_Graph_Tick_AddTicks_IntSubTicks(tickList, minVal, maxVal, 200.0, 3);
#endif
}
static void AQDG_Graph_Tick_AddTicks_DoubleSubTicks(AQDG_GRAPH_TICK_LIST *tickList,
double minVal, double maxVal, double stepFactor,
int prec, int level, int withText)
{
double vCurrent;
double vMin, vMax, v;
double steps;
vMin=AQDG_Graph_Tick_GetRoundedMaxVal(minVal);
vMax=AQDG_Graph_Tick_GetRoundedMaxVal(maxVal);
v=(vMin>vMax)?vMin:vMax;
if (minVal<0.0)
vMin=-vMin;
if (maxVal<0.0)
vMax=-vMax;
steps=v/stepFactor;
if (vMin<0.0 && vMax>0.0) {
/* create ticks for negative values */
vCurrent=-v;
while (vCurrent<0.0) {
if (vCurrent>=minVal) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%.*f", prec?prec:2, vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
if (withText)
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent+=steps;
}
/* create ticks for positive values */
vCurrent=0.0;
while (vCurrent<=maxVal) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%.*f", prec?prec:2, vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
if (withText)
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
vCurrent+=steps;
}
}
else if (vMin<0.0 && vMax<0.0) {
/* create ticks for negative values */
vCurrent=-v;
while (vCurrent<maxVal) {
if (vCurrent>=minVal) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%.*f", prec?prec:2, vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
if (withText)
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent+=steps;
}
}
else if (vMin>0.0 && vMax>0.0) {
/* create ticks for negative values */
vCurrent=0.0;
while (vCurrent<=maxVal) {
if (vCurrent>=minVal) {
AQDG_GRAPH_TICK *t;
char numbuf[64];
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, vCurrent);
AQDG_Graph_Tick_SetLevel(t, level);
snprintf(numbuf, sizeof(numbuf)-1, "%.*f", prec?prec:2, vCurrent);
numbuf[sizeof(numbuf)-1]=0;
DBG_ERROR(0, "Tick: %s (steps %f)", numbuf, steps);
if (withText)
AQDG_Graph_Tick_SetLabel(t, numbuf);
AQDG_Graph_Tick_List_Add(t, tickList);
}
vCurrent+=steps;
}
}
}
static void AQDG_Graph_Tick_AddTicks_Double(AQDG_GRAPH_TICK_LIST *tickList, double minVal, double maxVal, int prec)
{
int level=1;
DBG_ERROR(0, "Creating ticks from minVal=%f to maxVal=%f", minVal, maxVal);
#if 0
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 10.0, prec, level++, 1);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 20.0, prec, level++, 1);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 100.0, prec, level++, 1);
#else
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 2.0, prec, level++, 1);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 10.0, prec, level++, 0);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 20.0, prec, level++, 1);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 100.0, prec, level++, 0);
AQDG_Graph_Tick_AddTicks_DoubleSubTicks(tickList, minVal, maxVal, 200.0, prec, level++, 1);
#endif
}
void AQDG_Graph_Tick_AddTicks_DateYears(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal)
{
/* add ticks for years */
int i;
for (i=(int)minVal; i<=(int) maxVal; i++) {
GWEN_DATE *d;
d=GWEN_Date_fromJulian(i);
if (d==NULL) {
DBG_ERROR(0, "Invalid julian date %d", i);
}
else {
if (GWEN_Date_DaysInYear(d)==0) {
int rv;
GWEN_BUFFER *tbuf;
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
rv=GWEN_Date_toStringWithTemplate(d, I18N("YYYY"), tbuf);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
}
else {
AQDG_GRAPH_TICK *t;
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, i);
AQDG_Graph_Tick_SetLevel(t, level);
AQDG_Graph_Tick_SetLabel(t, GWEN_Buffer_GetStart(tbuf));
AQDG_Graph_Tick_List_Add(t, tickList);
}
GWEN_Buffer_free(tbuf);
}
GWEN_Date_free(d);
}
}
}
void AQDG_Graph_Tick_AddTicks_DateMonths(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal)
{
int i;
for (i=(int)minVal; i<=(int) maxVal; i++) {
GWEN_DATE *d;
d=GWEN_Date_fromJulian(i);
if (d==NULL) {
DBG_ERROR(0, "Invalid julian date %d", i);
}
else {
if (GWEN_Date_GetDay(d)==1) {
int rv;
GWEN_BUFFER *tbuf;
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
rv=GWEN_Date_toStringWithTemplate(d, I18N("YY/MM"), tbuf);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
}
else {
AQDG_GRAPH_TICK *t;
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, i);
AQDG_Graph_Tick_SetLevel(t, level);
AQDG_Graph_Tick_SetLabel(t, GWEN_Buffer_GetStart(tbuf));
AQDG_Graph_Tick_List_Add(t, tickList);
}
GWEN_Buffer_free(tbuf);
}
GWEN_Date_free(d);
}
}
}
void AQDG_Graph_Tick_AddTicks_DateWeeks(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal)
{
int i;
for (i=(int)minVal; i<=(int) maxVal; i++) {
GWEN_DATE *d;
d=GWEN_Date_fromJulian(i);
if (d==NULL) {
DBG_ERROR(0, "Invalid julian date %d", i);
}
else {
if (GWEN_Date_WeekDay(d)==1) { /* week starts at monday */
GWEN_BUFFER *tbuf;
int rv;
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
rv=GWEN_Date_toStringWithTemplate(d, I18N("YY/MM/DD"), tbuf);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
}
else {
AQDG_GRAPH_TICK *t;
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, i);
AQDG_Graph_Tick_SetLevel(t, level);
AQDG_Graph_Tick_SetLabel(t, GWEN_Buffer_GetStart(tbuf));
AQDG_Graph_Tick_List_Add(t, tickList);
}
GWEN_Buffer_free(tbuf);
}
GWEN_Date_free(d);
}
}
}
void AQDG_Graph_Tick_AddTicks_DateDays(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal)
{
int i;
for (i=(int)minVal; i<=(int) maxVal; i++) {
GWEN_DATE *d;
d=GWEN_Date_fromJulian(i);
if (d==NULL) {
DBG_ERROR(0, "Invalid julian date %d", i);
}
else {
int rv;
GWEN_BUFFER *tbuf;
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
rv=GWEN_Date_toStringWithTemplate(d, I18N("YY/MM/DD"), tbuf);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
}
else {
AQDG_GRAPH_TICK *t;
t=AQDG_Graph_Tick_new();
AQDG_Graph_Tick_SetValue(t, i);
AQDG_Graph_Tick_SetLevel(t, level);
AQDG_Graph_Tick_SetLabel(t, GWEN_Buffer_GetStart(tbuf));
AQDG_Graph_Tick_List_Add(t, tickList);
}
GWEN_Buffer_free(tbuf);
GWEN_Date_free(d);
}
}
}
static void AQDG_Graph_Tick_AddTicks_Date(AQDG_GRAPH_TICK_LIST *tickList, double minVal, double maxVal)
{
int dist;
int level;
dist=maxVal-minVal;
level=1;
/* add ticks for years */
if (dist>365)
AQDG_Graph_Tick_AddTicks_DateYears(tickList, level++, minVal, maxVal);
/* add ticks for months */
if (dist>30)
AQDG_Graph_Tick_AddTicks_DateMonths(tickList, level++, minVal, maxVal);
/* add ticks for weeks */
if (dist>7)
AQDG_Graph_Tick_AddTicks_DateWeeks(tickList, level++, minVal, maxVal);
/* add ticks for days */
if (dist>1)
AQDG_Graph_Tick_AddTicks_DateDays(tickList, level++, minVal, maxVal);
}
void AQDG_Graph_Tick_AddTicks(AQDG_GRAPH_TICK_LIST *tickList, int dataType, double minVal, double maxVal, int prec)
{
switch (dataType) {
case AQDG_Graph_DataSet_DataType_Integer:
AQDG_Graph_Tick_AddTicks_Int(tickList, minVal, maxVal);
break;
case AQDG_Graph_DataSet_DataType_Double:
AQDG_Graph_Tick_AddTicks_Double(tickList, minVal, maxVal, prec);
break;
case AQDG_Graph_DataSet_DataType_Date:
AQDG_Graph_Tick_AddTicks_Date(tickList, minVal, maxVal);
break;
default:
break;
}
}
static int GWENHYWFAR_CB AQDG_Graph_Tick_List_Compare_ValueAndLevel(const AQDG_GRAPH_TICK *p_a, const AQDG_GRAPH_TICK *p_b,
int p_ascending)
{
int p_rv;
if (p_b->value==p_a->value) {
if (p_b->level==p_a->level) {
p_rv=0;
}
else if (p_a->level<p_b->level)
p_rv=-1;
else
p_rv=1;
}
else if (p_a->value<p_b->value)
p_rv=-1;
else
p_rv=1;
if (p_ascending)
return p_rv;
else
return -p_rv;
}
void AQDG_Graph_Tick_List_SortByValueAndLevel(AQDG_GRAPH_TICK_LIST *p_list, int p_ascending)
{
AQDG_GRAPH_TICK_LIST_SORT_FN oldSortFn;
oldSortFn=AQDG_Graph_Tick_List_SetSortFn(p_list, AQDG_Graph_Tick_List_Compare_ValueAndLevel);
AQDG_Graph_Tick_List_Sort(p_list, p_ascending);
AQDG_Graph_Tick_List_SetSortFn(p_list, oldSortFn);
}
int AQDG_Graph_Tick_List_GetAverageValueDist(const AQDG_GRAPH_TICK_LIST *tl, int level, double *pResult)
{
if (tl) {
const AQDG_GRAPH_TICK *t;
double sumOfDists=0.0;
double lastValue=0.0;
int cnt=0;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double d;
d=AQDG_Graph_Tick_GetValue(t);
if (cnt)
sumOfDists+=abs(d-lastValue);
lastValue=d;
cnt++;
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (cnt>1) {
*pResult=sumOfDists/((double)(cnt-1));
return 0;
}
else
return 1;
}
else {
return GWEN_ERROR_NO_DATA;
}
}

View File

@@ -0,0 +1,39 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_GRAPH_TICK_FNS_H
#define AQDG_GRAPH_TICK_FNS_H
#ifdef __cplusplus
extern "C" {
#endif
AQDG_API void AQDG_Graph_Tick_AddTicks(AQDG_GRAPH_TICK_LIST *tickList, int dataType, double minVal, double maxVal, int prec);
AQDG_API void AQDG_Graph_Tick_AddTicks_DateYears(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal);
AQDG_API void AQDG_Graph_Tick_AddTicks_DateMonths(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal);
AQDG_API void AQDG_Graph_Tick_AddTicks_DateWeeks(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal);
AQDG_API void AQDG_Graph_Tick_AddTicks_DateDays(AQDG_GRAPH_TICK_LIST *tickList, int level, double minVal, double maxVal);
AQDG_API void AQDG_Graph_Tick_List_SortByValueAndLevel(AQDG_GRAPH_TICK_LIST *list, int ascending);
AQDG_API int AQDG_Graph_Tick_List_GetAverageValueDist(const AQDG_GRAPH_TICK_LIST *tl, int level, double *pResult);
#ifdef __cplusplus
}
#endif
#endif

149
src/lib/aqdiagram/libtest.c Normal file
View File

@@ -0,0 +1,149 @@
/***************************************************************************
begin : Thut Oct 07 2020
copyright : (C) 2020 by Martin Preuss
email : martin@libchipcard.de
***************************************************************************
* Please see toplevel file COPYING for license details *
***************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <aqdiagram/aqdiagram.h>
#include <aqdiagram/draw/context_cairo.h>
#include <aqdiagram/graph/dataset.h>
#include <aqdiagram/graph/graph.h>
int testGraph1()
{
AQDG_DRAW_CONTEXT *g;
int graphWidth=1024;
int graphHeight=768;
g=AQDB_ContextCairo_Png_new(outFile, graphWidth, graphHeight);
if (g) {
AF_GRAPH *gr;
AF_GRAPH_DATASET *ds;
GWEN_DB_NODE *dbConfig;
GWEN_DB_NODE *dbT;
ds=AQDG_Graph_DataSet_new();
AQDG_Graph_DataSet_SetTitle(ds, "Test Title");
AQDG_Graph_DataSet_SetSubTitle(ds, "Subtitle");
AQDG_Graph_DataSet_SetDataTypeX(ds, AQDG_Graph_DataSet_DataType_Date);
AQDG_Graph_DataSet_SetLabelX(ds, "Date");
AQDG_Graph_DataSet_SetDataTypeY(ds, AQDG_Graph_DataSet_DataType_Double);
AQDG_Graph_DataSet_SetLabelY(ds, "EUR");
AQDG_Graph_DataSet_SetPrecisionY(ds, 2);
AQDG_Graph_DataSet_AdjustXRange(ds);
AQDG_Graph_DataSet_AdjustYRange(ds);
AQDG_Graph_DataSet_AddTicks(ds);
dbConfig=GWEN_DB_Group_new("config");
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penTitle");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0x00000000);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penSubTitle");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0xff000000);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penAxisLable");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0xff000000);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penAxis");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0x0000ff00);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penGraph");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0x00ff0000);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penGraphBackground");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0xffec5b00);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penGrid");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0xc0c0c000);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 1);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "penBackground");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "frontColour", (int)0xffffff00);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "lineWidth", 1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "dashType", 0);
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "fontTitle");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSize", 20);
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSlant", "none");
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontWeight", "bold");
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "fontSubTitle");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSize", 16);
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSlant", "italic");
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontWeight", "none");
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "fontAxisLabel");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSize", 12);
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSlant", "none");
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontWeight", "none");
dbT=GWEN_DB_GetGroup(dbConfig, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "fontTickLabel");
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSize", 9);
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontSlant", "none");
GWEN_DB_SetCharValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS, "fontWeight", "none");
GWEN_DB_SetCharValue(dbConfig, GWEN_DB_FLAGS_OVERWRITE_VARS, "flags", "grid");
AQDB_Context_Attach(g);
gr=AQDG_Graph_new(ds, g, graphWidth, graphHeight);
rv=AQDG_Graph_Init_fromDb(gr, dbConfig);
if (rv<0) {
DBG_ERROR(0, "Error on AQDG_Graph_Init_fromDb(): %d", rv);
return 2;
}
rv=AQDG_Graph_Draw(gr);
if (rv<0) {
DBG_ERROR(0, "Error on AQDG_Graph_Draw(): %d", rv);
return 2;
}
AQDG_Graph_Fini(gr);
AQDG_Graph_free(gr);
AQDB_Context_Finish(g);
AQDB_Context_free(g);
}
else {
DBG_ERROR(0, "Error creating graphics context");
return 2;
}
return 0;
}