commit d0490c01db310261b34bfb3a65878d2aa90c03f3 Author: Martin Preuss Date: Thu Mar 24 20:49:19 2022 +0100 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5975d97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +build/ diff --git a/0BUILD b/0BUILD new file mode 100644 index 0000000..c1c055b --- /dev/null +++ b/0BUILD @@ -0,0 +1,233 @@ + + + + + + + + $(project_name) + + + + $(project_vmajor).$(project_vminor).$(project_vpatchlevel) + + $(project_vmajor).$(project_vminor).$(project_vpatchlevel).$(project_vbuild)$(project_vtag) + + + + + + + + + + + + + $(option_prefix) + $(option_prefix)/etc + $(option_prefix)/bin + $(option_prefix)/lib + $(option_prefix)/include + $(option_prefix)/share + $(option_prefix)/share/locale + + $(libdir)/$(package) + $(includedir)/$(package) + $(datadir)/$(package) + + + + + + + + + + + + + + + + -ggdb -O0 -Wall + -ggdb -O0 -Wall + + + + + + + + 1 + etc + share/locale + share/aqdiagram" + + + + 0 + + + etc + share/locale + share/aqdiagram + + + $(sysconfdir) + $(datadir)/locale + $(datadir)/aqdiagram + + + + + + + + + + + + + + + + + + + + + -fvisibility=hidden + + + + -fvisibility=hidden + + + + + + locale.h libintl.h iconv.h + fcntl.h stdlib.h string.h unistd.h + assert.h ctype.h errno.h fcntl.h stdio.h stdlib.h string.h strings.h locale.h + + + + + setlocale + memmove + memset + strcasecmp + strdup + strerror + snprintf + + + + + + + + + + + + + + + + + src + + + + + + + + + + + + + aqdiagram.pot + + + + -C -c -ki18n -ktr2i18n -kI18N -kI18S -kI18N_NOOP -ktranslate -kaliasLocale -ktr -ktrUtf8 + --msgid-bugs-address=aqbanking-user@lists.aqbanking.de + -o $(OUTPUT[0]) $(INPUT[]) + + + + Extracting I18N strings into $(OUTPUT[0]) + + + + + + + + + + + + + + + + + + + --style=stroustrup + -s2 + --min-conditional-indent=0 + --indent-labels + --max-continuation-indent=80 + --pad-comma + --pad-header + --unpad-paren + --align-pointer=name + --break-closing-braces + --break-one-line-headers + --attach-return-type + --convert-tabs + --max-code-length=120 + --break-after-logical + --preserve-date + --suffix=none + $(INPUT[]) + + + + Formatting source files in-place. + + + + + + + AUTHORS + COPYING + README + + + + + + + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..31d5817 --- /dev/null +++ b/COPYING @@ -0,0 +1,469 @@ + +License +======= + +The following is the license text for the LGPL in a version that applies to +AqHmControl. + + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..2edfc73 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,93 @@ +SUBDIRS=m4 src + +EXTRA_DIST=\ + AUTHORS \ + COPYING \ + ChangeLog \ + Doxyfile.in \ + INSTALL \ + NEWS \ + README \ + Makefile.cvs + + +aclocaldir = $(datadir)/aclocal + +ACLOCAL_AMFLAGS = $(ADD_ACLOCAL_FLAGS) -I m4 + + +pkgconfigdir = $(libdir)/pkgconfig +#pkgconfig_DATA = aqdatabase.pc + + +ChangeLog: + if test -d .git; then \ + git log --pretty="format:------------------------------------------------------------------%n%ai %an%n%s%n%b" -n 100 >ChangeLog ;\ + else \ + touch ChangeLog; \ + fi + + +build_sources: $(built_sources) +# $(srcdir)/mksymlinks.sh $(srcdir) $(builddir) + + +sources: + $(MAKE) -C src sources + + + +listdoc.h: + $(gwenhywfar_bindir)/mklistdoc -I $(gwenhywfar_headers) -v `find $(aqdb_symlinkdir) -name '*.h' ` >listdoc.h + +srcdoc: Doxyfile listdoc.h + if test -d apidoc; then rm -Rf apidoc; fi + mkdir -p apidoc/html/aqdatabase-@AQDB_VERSION_RELEASE_STRING@ + doxygen + +install-srcdoc: srcdoc + test -d "$(DESTDIR)@docpath@/$(PACKAGE)" || \ + mkdir -p "$(DESTDIR)@docpath@/$(PACKAGE)" + for f in apidoc/html/aqdatabase-@AQDB_VERSION_RELEASE_STRING@/*; do \ + cp -dR $$f "$(DESTDIR)@docpath@/$(PACKAGE)/"; \ + done + cp "apidoc/$(PACKAGE).tag" "$(DESTDIR)@docpath@/" + + + + +cppcheck: + for f in `find . -name \*.c -o -name \*.cpp`; do cppcheck $$f; done + + +typefiles: + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d typefiles; \ + done + +typedefs: + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d typedefs; \ + done + + +format: + find . -name '*.[c,h,cpp]' -exec astyle \ + --style=stroustrup \ + -s2 \ + --min-conditional-indent=0 \ + --indent-labels \ + --max-continuation-indent=80 \ + --pad-comma \ + --pad-header \ + --unpad-paren \ + --align-pointer=name \ + --break-closing-braces \ + --break-one-line-headers \ + --attach-return-type \ + --convert-tabs \ + --max-code-length=120 \ + --break-after-logical \ + --preserve-date \ + --suffix=none \{\} \; + diff --git a/Makefile.cvs b/Makefile.cvs new file mode 100644 index 0000000..0dbf588 --- /dev/null +++ b/Makefile.cvs @@ -0,0 +1,127 @@ + +WIN32_OPTIONS=\ + --host=i586-mingw32msvc \ + --target=i586-mingw32msvc \ + --enable-version-specific-runtime-libs \ + --with-gcc \ + --with-gnu-ld \ + --without-x \ + --enable-threads=win32 \ + --disable-win32-registry + +MINGW32_PREFIX=/usr/i586-mingw32msvc + +WIN32_INSTALL_DIR=/home/martin/install/win32 + + +default: all + +dist: + @echo "This file is to make it easier for you to create all you need" + aclocal -I ./m4 + autoheader +# use --include-deps, if you want to release the stuff. Don't use it for +# yourself + automake --include-deps + autoconf + touch stamp-h.in + rm -f `find . -name \*~` + rm -Rf `find . -type d -name CVS` + rm -f `find . -type f -name .cvsignore` + rm -Rf apidoc + rm -Rf gwenipc + rm -f Makefile.cvs + rm -Rf autom4te.cache + +cvsclean:: + automake --include-deps + autoconf + touch stamp-h.in + rm -Rf gwenipc + rm -f `find . -name \*~` + rm -Rf apidoc + rm -Rf autom4te.cache + +all: + libtoolize -f --automake + @if test -r config.status; then \ + prefix=`grep '@prefix@' config.status |cut -d , -f 3`; \ + gwen_prefix=`grep '@GWEN_PREFIX@' config.status |cut -d , -f 3`; \ + fi; \ + for A in "$${gwen_prefix}/share/aclocal" "$${prefix}/share/aclocal" m4; do \ + if test -d "$${A}"; then \ + ACLOCAL_FLAGS="$${ACLOCAL_FLAGS} -I $${A}"; \ + fi; \ + done; \ + echo "aclocal $${ACLOCAL_FLAGS}"; \ + aclocal $${ACLOCAL_FLAGS} || (echo -e '***\n*** If the line above shows the error message "macro AC_GWENHYWFAR not \n*** found", you need to specify the environment variable ACLOCAL_FLAGS \n*** to be "-I GWENHYWFAR_PREFIX/share/aclocal". For example, do the following:\n***\n*** export ACLOCAL_FLAGS="-I ${HOME}/usr/share/aclocal"\n*** make -f Makefile.cvs\n***'; exit 1) + autoheader + automake --add-missing + @echo "autoconf"; \ + autoconf || (echo -e '***\n*** If the line above shows the error message "possibly undefined macro: \n*** AC_GWENHYWFAR", you need to specify the environment variable ACLOCAL_FLAGS \n*** to be "-I GWENHYWFAR_PREFIX/share/aclocal". For example, do the following:\n***\n*** export ACLOCAL_FLAGS="-I ${HOME}/usr/share/aclocal"\n*** make -f Makefile.cvs\n***'; exit 1) + @echo "Now you can run ./configure --enable-maintainer-mode" + + +mp: + libtoolize -f --automake + aclocal -I ./m4 + autoheader + automake --add-missing + autoconf + PKG_CONFIG_PATH="$PKG_CONFIG_PATH:./m4" CXXFLAGS="-ggdb -Wall -O0" CFLAGS="-ggdb -Wall -O0" \ + ./configure \ + --prefix=/usr/local \ + --enable-full-doc \ + --enable-testcode +# make build_sources + +mp-opt: + libtoolize -f --automake + aclocal -I ./m4 + autoheader + automake --add-missing + autoconf + PKG_CONFIG_PATH="$PKG_CONFIG_PATH:./m4" CXXFLAGS="-ggdb -Wall -O3" CFLAGS="-ggdb -Wall -O3" ./configure --prefix=/usr/local +# make build_sources + + + +clang: + libtoolize -f --automake + aclocal -I ./m4 + autoheader + automake --add-missing + autoconf + CC=clang CXX=clang PKG_CONFIG_PATH="$PKG_CONFIG_PATH:./m4" CXXFLAGS="-ggdb -Wall -O0" CFLAGS="-ggdb -Wall -O0" ./configure + make build_sources + + +mp-w32: + libtoolize -f --automake + aclocal -I ./m4 + autoheader + automake --add-missing + autoconf + PATH="$(MINGW32_PREFIX)/bin:$(PATH)" \ + PKG_CONFIG_PATH=$(WIN32_INSTALL_DIR)/lib/pkgconfig \ + CFLAGS="-I$(WIN32_INSTALL_DIR)/include" CXXFLAGS="-ggdb -Wall -I$(WIN32_INSTALL_DIR)/include" \ + LDFLAGS="-L$(WIN32_INSTALL_DIR)/lib" \ + DLLTOOL=i586-mingw32msvc-dlltool \ + OBJDUMP=i586-mingw32msvc-objdump \ + LD=i586-mingw32msvc-ld \ + AR=i586-mingw32msvc-ar \ + NM=i586-mingw32msvc-nm \ + RANLIB=i586-mingw32msvc-ranlib \ + STRIP=i586-mingw32msvc-strip \ + STRIPPROG=i586-mingw32msvc-strip \ + AS=i586-mingw32msvc-as \ + RC=i586-mingw32msvc-windres \ + ./configure \ + --prefix=$(WIN32_INSTALL_DIR) $(WIN32_OPTIONS) \ + --enable-release \ + --with-gwen-dir=$(WIN32_INSTALL_DIR) \ + --with-aqbanking-dir=$(WIN32_INSTALL_DIR) \ + --with-fox-includes=$(WIN32_INSTALL_DIR)/include/fox-1.6 \ + --with-fox-libs="-L$(WIN32_INSTALL_DIR)/lib -lFOX-1.6" \ + + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..d0ecb44 --- /dev/null +++ b/configure.ac @@ -0,0 +1,579 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.60) +AC_INIT +AC_CANONICAL_TARGET([]) +AC_CONFIG_SRCDIR([src/lib/aqdiagram/aqdg_api.h]) +AC_CONFIG_HEADER([config.h]) + + +###------------------------------------------------------------------------- +# +# versions +# +AQDG_VERSION_MAJOR=0 +AQDG_VERSION_MINOR=0 +AQDG_VERSION_PATCHLEVEL=1 +AQDG_VERSION_BUILD=0 +dnl "stable", "rcX", "betaX", "cvs" +AQDG_VERSION_TAG="git" + +AQDG_VERSION_FULL_STRING="$AQDG_VERSION_MAJOR.$AQDG_VERSION_MINOR.$AQDG_VERSION_PATCHLEVEL.$AQDG_VERSION_BUILD${AQDG_VERSION_TAG}" +AQDG_VERSION_STRING="$AQDG_VERSION_MAJOR.$AQDG_VERSION_MINOR.$AQDG_VERSION_PATCHLEVEL" + + +###------------------------------------------------------------------------- +# +# SO version +# +AQDG_SO_CURRENT=0 +AQDG_SO_AGE=0 +AQDG_SO_REVISION=1 +AQDG_SO_EFFECTIVE="`echo \$(($AQDG_SO_CURRENT-$AQDG_SO_AGE))`" + + + +###------------------------------------------------------------------------- +# +# datetime +# +DATETIME="`date +\"%Y%m%d%H%M%S\"`" +AC_SUBST(DATETIME) + + + +###------------------------------------------------------------------------- +# +# Create release string +# +case "$AQDG_VERSION_TAG" in + cvs | git | svn) + AQDG_VERSION_RELEASE_STRING="$AQDG_VERSION_FULL_STRING" + ;; + stable) + AQDG_VERSION_RELEASE_STRING="$AQDG_VERSION_MAJOR.$AQDG_VERSION_MINOR.$AQDG_VERSION_PATCHLEVEL" + ;; + *) + AQDG_VERSION_RELEASE_STRING="$AQDG_VERSION_MAJOR.$AQDG_VERSION_MINOR.$AQDG_VERSION_PATCHLEVEL" + + # add TAG + AQDG_VERSION_RELEASE_STRING="$AQDG_VERSION_RELEASE_STRING${AQDG_VERSION_TAG}" + ;; +esac + + +AC_SUBST(AQDG_VERSION_MAJOR) +AC_SUBST(AQDG_VERSION_MINOR) +AC_SUBST(AQDG_VERSION_PATCHLEVEL) +AC_SUBST(AQDG_VERSION_BUILD) +AC_SUBST(AQDG_VERSION_TAG) +AC_SUBST(AQDG_VERSION_FULL_STRING) +AC_SUBST(AQDG_VERSION_STRING) +AC_SUBST(AQDG_VERSION_RELEASE_STRING) + +AC_DEFINE_UNQUOTED(AQDG_VERSION_MAJOR,$AQDG_VERSION_MAJOR, + [major version]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_MINOR,$AQDG_VERSION_MINOR, + [minor version]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_PATCHLEVEL,$AQDG_VERSION_PATCHLEVEL, + [patchlevel]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_BUILD,$AQDG_VERSION_BUILD, [build]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_STRING,"$AQDG_VERSION_STRING", + [version string]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_FULL_STRING,"$AQDG_VERSION_FULL_STRING", + [full version string]) +AC_DEFINE_UNQUOTED(AQDG_VERSION_TAG,$AQDG_VERSION_TAG, [tag]) + +AC_SUBST(AQDG_SO_CURRENT) +AC_SUBST(AQDG_SO_REVISION) +AC_SUBST(AQDG_SO_AGE) +AC_SUBST(AQDG_SO_EFFECTIVE) +AC_DEFINE_UNQUOTED(AQDG_SO_EFFECTIVE_STR, "$AQDG_SO_EFFECTIVE", + [effective SO version]) + + AM_INIT_AUTOMAKE(aqdiagram, $AQDG_VERSION_RELEASE_STRING) + + +###------------------------------------------------------------------------- +# +# prefix handling +# +AC_PREFIX_DEFAULT(/usr/local) +if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + ac_configure_args="$ac_configure_args --prefix $prefix" +fi +AC_SUBST(prefix) + + +###------------------------------------------------------------------------- +# +# Checks for programs. +# +AC_PROG_CC +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LIBTOOL +AC_CHECK_PROG(USE_DOT,dot,YES,NO) +AC_CHECK_PROG(SED,sed,sed) +PKG_PROG_PKG_CONFIG + +###------------------------------------------------------------------------- +# +# Checks for libraries. +# + + +###------------------------------------------------------------------------- +# +# Checks for header files. +# + +AC_HEADER_STDC +AC_CHECK_HEADERS([locale.h]) + + +###------------------------------------------------------------------------- +# +# Checks for typedefs, structures, and compiler characteristics. +# + +AC_C_CONST + + +###------------------------------------------------------------------------- +# +# Checks for library functions. +# +AC_CHECK_FUNCS([setlocale localeconv]) + + + +###------------------------------------------------------------------------- +# +# OS dependent settings +# +AQ_CHECK_OS + +aqdg_internal_libs="\$(top_builddir)/src/lib/libaqdiagram.la" +aqdg_libs="-L\$(libdir) -laqdiagram" +aqdg_includes="-I`eval echo $prefix/include`" +aqdg_pkgdatadir="`eval echo $prefix/share`/aqdiagram" + +case "$OS_TYPE" in + posix) + aqdg_sys_is_windows=0 + ;; + windows) + aqdg_sys_is_windows=1 + AC_DEFINE(AQDG_SYS_IS_WINDOWS, 1, [whether the system is WIN32]) + ACX_WINDOWS_PATHS + ;; +esac + + +AM_CONDITIONAL(IS_WINDOWS, [test "$OS_TYPE" = "windows"]) +AM_CONDITIONAL(IS_OSX, [test "$OSYSTEM" = "osx"]) +AM_CONDITIONAL(IS_LINUX, [test "$OSYSTEM" = "linux"]) + + +###------------------------------------------------------------------------- +# +# Check for Gwen +# + +AC_GWENHYWFAR(5,2,0,0) + + + +###------------------------------------------------------------------------- +# +# check typemaker2 +# + +AC_MSG_CHECKING(typemaker2 binary) +AC_ARG_WITH(typemaker2-exe, + [ --with-typemaker2-exe=EXE path and name of the executable typemaker2], + [typemaker2_exe="$withval"], + [typemaker2_exe="\$(gwenhywfar_bindir)/typemaker2"] +) +AC_MSG_RESULT($typemaker2_exe) +AC_SUBST(typemaker2_exe) + + + +###------------------------------------------------------------------------- +# Check for Cairo +# + +AC_MSG_CHECKING(whether cairo support is wanted) +AC_ARG_ENABLE(cairo, + [ --enable-cairo enable cairo support (default=yes)], + enable_cairo="$enableval", + enable_cairo="yes") +AC_MSG_RESULT($enable_cairo) + +if test "$enable_cairo" != "no"; then + PKG_CHECK_MODULES([CAIRO], [cairo], [HAVE_CAIRO="yes"], [HAVE_CAIRO="no"]) + if test "$HAVE_CAIRO" = "yes"; then + AC_DEFINE(HAVE_CAIRO, 1, [if Cairo is available]) + fi +else + HAVE_CAIRO="no" +fi + + + +###------------------------------------------------------------------------- +# +# check whether local installation mode is enabled +# + +AC_MSG_CHECKING(whether local installation mode is wanted) +AC_ARG_ENABLE(local-install, + [ --enable-local-install allow local installation mode (default=no)], + enable_local_install="$enableval", + enable_local_install="no") +AC_MSG_RESULT($enable_local_install) + +if test "$enable_local_install" != "no"; then + AC_DEFINE(ENABLE_LOCAL_INSTALL, 1, [whether local install is wanted]) +fi + + + +###------------------------------------------------------------------------- +# +# check cfg search dir +# +AC_MSG_CHECKING(cfg search dir) +AC_ARG_WITH(cfg-searchdir, [ --with-cfg-searchdir=DIR where to search for cfg files], + [aqdiagram_cfg_searchdir="$withval"], + [aqdiagram_cfg_searchdir=""]) + +if test -z "$aqdiagram_cfg_searchdir"; then + if test "$OSYSTEM" = "windows"; then + aqdiagram_cfg_searchdir="etc" + else + if test "$enable_local_install" != "no"; then + aqdiagram_cfg_searchdir="etc" + else + aqdiagram_cfg_searchdir="\$(sysconfdir)" + fi + fi +fi + + +AC_SUBST(aqdiagram_cfg_searchdir) +AC_MSG_RESULT($aqdiagram_cfg_searchdir) + + + +###------------------------------------------------------------------------- +# +# check locale search dir +# +AC_MSG_CHECKING(locale search dir) +AC_ARG_WITH(locale-searchdir, [ --with-locale-searchdir=DIR where to search for locale files], + [aqdiagram_locale_searchdir="$withval"], + [aqdiagram_locale_searchdir=""]) + +if test -z "${aqdiagram_locale_searchdir}"; then + if test "$OSYSTEM" = "windows"; then + aqdiagram_locale_searchdir="share/locale" + else + if test "$enable_local_install" != "no"; then + aqdiagram_locale_searchdir="share/locale" + else + aqdiagram_locale_searchdir="\$(localedir)" + fi + fi +fi + +AC_SUBST(aqdiagram_locale_searchdir) +AC_MSG_RESULT($aqdiagram_locale_searchdir) + + + +###------------------------------------------------------------------------- +# +# check data search dir +# +AC_MSG_CHECKING(data search dir) +AC_ARG_WITH(data-searchdir, [ --with-data-searchdir=DIR where to search for data files], + [aqdiagram_data_searchdir="$withval"], + [aqdiagram_data_searchdir=""]) + +if test -z "${aqdiagram_data_searchdir}"; then + if test "$OSYSTEM" = "windows"; then + aqdiagram_data_searchdir="share/aqdiagram" + else + if test "$enable_local_install" != "no"; then + aqdiagram_data_searchdir="share/aqdiagram" + else + aqdiagram_data_searchdir="\$(datadir)/aqdiagram" + fi + fi +fi + +AC_SUBST(aqdiagram_data_searchdir) +AC_MSG_RESULT($aqdiagram_data_searchdir) + + + +###------------------------------------------------------------------------- +# +# check for I18N +# + +HAVE_I18N="yes" +AC_CHECK_PROG(XGETTEXT,xgettext,xgettext, missing) +AC_PATH_PROG([MSGFMT], [msgfmt], [missing]) +if test "$XGETTEXT" = "missing" -o "$MSGFMT" = "missing" ; then + HAVE_I18N="no" + AC_MSG_WARN([xgettext is missing. Locale support is disabled.]) +else + # Watch out: The AC_CHECK_HEADERS macro will force the inclusion + # of several other important macros immediately. However, at + # this point those other macros would only occur inside the + # conditional branch, so everything will break down if xgettext + # is missing. Therefore this conditionaled check needs to come + # only after the standard (non-conditional) macros. + AC_CHECK_HEADERS([locale.h libintl.h], [], [HAVE_I18N="no"]) + AC_SEARCH_LIBS(gettext, intl, [], [HAVE_I18N="no"]) +fi + + +AC_SUBST(HAVE_I18N) +if test "$HAVE_I18N" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_I18N, 1, [whether I18N is available]) +fi +AM_CONDITIONAL(USE_I18N, [test "$HAVE_I18N" = "yes"]) + + + + +###------------------------------------------------------------------------- +# +# GCC version (check for usability) +# + +AC_MSG_CHECKING(if symbol visibility is supported) +case `basename $CC` in + gcc*) + gccversion=`$CC --version | { read x1 x2 x3; echo $x3; }` + case $gccversion in + 0.* | 1.* | 2.* | 3.*) + visibility_supported="no (needs gcc >=4.0, you have $gccversion)" + ;; + *) + visibility_supported="yes" + AC_DEFINE(GCC_WITH_VISIBILITY_ATTRIBUTE, 1, [visibility]) + visibility_cflags="-fvisibility=hidden" + ;; + esac + ;; + *) + visibility_supported="no (needs gcc >=4.0, you use $CC)" + ;; +esac + +# -fvisibility is at least not available on MinGW/gcc-3.4.4 (will +# give an "unrecognized cmdline option"). Also, unfortunately I +# don't know an easy way to ask the compiler here. Maybe +# http://autoconf-archive.cryp.to/ax_cflags_gcc_option.html +case "$OS_TYPE" in + windows) + visibility_supported="no (not yet on MinGW/Windows)" + visibility_cflags="" + ;; + *) + ;; +esac + + +AC_MSG_RESULT(${visibility_supported}) +AC_SUBST(visibility_cflags) + + + +###------------------------------------------------------------------------- +# +# check for release +# +AC_MSG_CHECKING(whether this is an official release) +AC_ARG_ENABLE(release, + [ --enable-release make this an official release (default=no)], + [ case "${enableval}" in + yes) enable_release="yes";; + no) enable_release="no";; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-release);; + esac + ], + enable_release="no") + +if test "$enable_release" = "yes"; then + STRIPALL="-s" +else + STRIPALL="" +fi +AC_SUBST(STRIPALL) +AC_MSG_RESULT($enable_release) + + + +###------------------------------------------------------------------------- +# +# docpath +# +AC_MSG_CHECKING(docpath) +AC_ARG_WITH(docpath, [ --with-docpath=DIR where to store the apidoc], + [docpath="$withval"], + [docpath="${HOME}/apidoc"]) +AC_SUBST(docpath) +AC_MSG_RESULT($docpath) + + +###------------------------------------------------------------------------- +# +# check for doc type +# +AC_MSG_CHECKING(if full docu should be created) +AC_ARG_ENABLE(full-doc, + [ --enable-full-doc enable creating full apidoc (default=no)], + [ case "${enableval}" in + yes) enable_fulldoc="yes";; + no) enable_fulldoc="no";; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-full-doc);; + esac + ], + enable_fulldoc="no") + +if test "$enable_fulldoc" = "yes"; then + DOXYGEN_INPUT="listdoc.h src" + DOXYGEN_DEFINE="" + DOXYGEN_FILE_PATTERNS="*.h *.hpp *.c *.cpp" + DOXYGEN_EXCLUDE_PATTERNS="" +else + DOXYGEN_DEFINE="DOXYGEN_HIDE" + DOXYGEN_INPUT="listdoc.h aqdiagram" + DOXYGEN_FILE_PATTERNS="*.h *.hpp" + DOXYGEN_EXCLUDE_PATTERNS="*_p.h" +fi +AC_SUBST(DOXYGEN_INPUT) +AC_SUBST(DOXYGEN_DEFINE) +AC_SUBST(DOXYGEN_FILE_PATTERNS) +AC_SUBST(DOXYGEN_EXCLUDE_PATTERNS) +AC_MSG_RESULT($enable_fulldoc) + + + +###------------------------------------------------------------------------- +# +# search for tag files +# +AC_MSG_CHECKING(doxygen tag files) +DOXYGEN_TAGFILES="" +DOXYGEN_TAGFILEPATHS="" +if test -d "${docpath}"; then + tagfiles="`cd ${docpath} && ls *.tag`" + if test -n "${tagfiles}"; then + # remove own package from list + tagfiles="`echo ${tagfiles} | ${SED} -e s/${PACKAGE}.tag//`" + + # add every remaining tag file + for ff in ${tagfiles}; do + DOXYGEN_TAGFILES="${DOXYGEN_TAGFILES} ${docpath}/${ff}=${docpath}/`basename -s .tag ${ff}`" + done + fi +fi +if test -z "${DOXYGEN_TAGFILES}"; then + AC_MSG_RESULT(none) +else + AC_MSG_RESULT(found) +fi +AC_SUBST(DOXYGEN_TAGFILES) + + + +###------------------------------------------------------------------------- +# +# check whether test code should be enabled +# + +AC_MSG_CHECKING(whether to enable test code) +AC_ARG_ENABLE(testcode, + [ --enable-testcode allow compiling of test code (default=no)], + enable_testcode="$enableval", + enable_testcode="no") +AC_MSG_RESULT($enable_testcode) + +if test "$enable_testcode" != "no"; then + AC_DEFINE(AQDIAGRAM_ENABLE_TESTCODE, 1, [whether to enable test code]) +fi + + + +###------------------------------------------------------------------------- +# +# Debug arguments for compilation +# +ACX_COMPILE_WARN() + + + +###------------------------------------------------------------------------- +# +# Substitute vars +# +AS_SCRUB_INCLUDE(all_includes) +AC_SUBST(all_includes) +AC_SUBST(all_libraries) +AS_SCRUB_INCLUDE(aqdg_includes) +AC_SUBST(aqdg_includes) +AC_SUBST(aqdg_internal_libs) +AC_SUBST(aqdg_libs) +AC_SUBST(aqdg_pkgdatadir) +AC_SUBST(aqdg_plugindir) +AC_SUBST(aqdg_sys_is_windows) + + + +###------------------------------------------------------------------------- +# +# Output files +# + +AC_CONFIG_FILES([Makefile + m4/Makefile + src/Makefile + src/lib/Makefile + src/lib/aqdiagram/Makefile + src/lib/aqdiagram/draw/Makefile + src/lib/aqdiagram/graph/Makefile + ]) +AC_OUTPUT + + + +###------------------------------------------------------------------------- +# +# Summary +# + +echo +echo +echo "Summary" +echo "----------------------------------------------------" +echo "AqDiagram : $AQDG_VERSION_FULL_STRING" +echo "Local Installation Mode : $enable_local_install" +echo "Cfg Search Folder : $aqdiagram_cfg_searchdir" +echo "Data Search Folder : $aqdiagram_data_searchdir" +echo "Locale Search Folder : $aqdiagram_locale_searchdir" +echo "Symbol Visibility : $visibility_supported" +echo + +echo "----------------------------------------------------" +echo "You can now run \"make\" (or gmake on FreeBSD) to compile." + diff --git a/src/0BUILD b/src/0BUILD new file mode 100644 index 0000000..944afcb --- /dev/null +++ b/src/0BUILD @@ -0,0 +1,11 @@ + + + + + + + lib + + + + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..176b813 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS=lib + +typefiles: + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d typefiles; \ + done + +typedefs: + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d typedefs; \ + done diff --git a/src/lib/0BUILD b/src/lib/0BUILD new file mode 100644 index 0000000..5341151 --- /dev/null +++ b/src/lib/0BUILD @@ -0,0 +1,11 @@ + + + + + + + aqdiagram + + + + diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 0000000..183a61f --- /dev/null +++ b/src/lib/Makefile.am @@ -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 diff --git a/src/lib/aqdiagram/0BUILD b/src/lib/aqdiagram/0BUILD new file mode 100644 index 0000000..6f5029e --- /dev/null +++ b/src/lib/aqdiagram/0BUILD @@ -0,0 +1,79 @@ + + + + + + + + + + $(gwenhywfar_cflags) + -I$(topsrcdir)/src/lib + -I$(topbuilddir)/src/lib + -I$(topbuilddir) + -I$(topsrcdir) + -I$(srcdir) + + + + --include=$(builddir) + --include=$(srcdir) + --include=$(builddir)/../types + --include=$(topsrcdir)/src/lib/typemaker2/c + --include=$(topbuilddir)/src/lib/typemaker2/c + + + + $(visibility_cflags) + + + + --api=AQDG_API + + + + + aqdiagram.h + aqdg_api.h + + + + + aqdiagram.c + + + + + + + + + + + + aqdg_draw + aqdg_graph + + + + + $(gwenhywfar_libs) + $(cairo_libs) + $(zlib_libs) + + + + + + draw + graph + + + + + + diff --git a/src/lib/aqdiagram/Makefile.am b/src/lib/aqdiagram/Makefile.am new file mode 100644 index 0000000..ea89516 --- /dev/null +++ b/src/lib/aqdiagram/Makefile.am @@ -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 + + diff --git a/src/lib/aqdiagram/aqdg_api.h b/src/lib/aqdiagram/aqdg_api.h new file mode 100644 index 0000000..2235b84 --- /dev/null +++ b/src/lib/aqdiagram/aqdg_api.h @@ -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 + diff --git a/src/lib/aqdiagram/aqdiagram.c b/src/lib/aqdiagram/aqdiagram.c new file mode 100644 index 0000000..a834c6b --- /dev/null +++ b/src/lib/aqdiagram/aqdiagram.c @@ -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 +#endif + + +#include "./aqdiagram.h" + + +#include +#include +#include + + + + + +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; +} + + + diff --git a/src/lib/aqdiagram/aqdiagram.h b/src/lib/aqdiagram/aqdiagram.h new file mode 100644 index 0000000..9aff274 --- /dev/null +++ b/src/lib/aqdiagram/aqdiagram.h @@ -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 + +#include + +#include + + +#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 + diff --git a/src/lib/aqdiagram/draw/.gitignore b/src/lib/aqdiagram/draw/.gitignore new file mode 100644 index 0000000..81c03ef --- /dev/null +++ b/src/lib/aqdiagram/draw/.gitignore @@ -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 + diff --git a/src/lib/aqdiagram/draw/0BUILD b/src/lib/aqdiagram/draw/0BUILD new file mode 100644 index 0000000..afdee29 --- /dev/null +++ b/src/lib/aqdiagram/draw/0BUILD @@ -0,0 +1,105 @@ + + + + + + + + + + $(gwenhywfar_cflags) + $(cairo_cflags) + -I$(topsrcdir)/src/lib + -I$(topbuilddir)/src/lib + -I$(topbuilddir) + -I$(topsrcdir) + -I$(srcdir) + + + + --include=$(builddir) + --include=$(srcdir) + --include=$(builddir)/../types + --include=$(topsrcdir)/src/lib/typemaker2/c + --include=$(topbuilddir)/src/lib/typemaker2/c + + + + $(visibility_cflags) + + + + --api=AQDG_API + + + + + context.xml + font.xml + pen.xml + + + + context.c + font.c + pen.c + + + + context.h + font.h + pen.h + + + + + context_p.h + font_p.h + pen_p.h + + + + + $(local/built_headers_pub) + + + + $(local/built_headers_priv) + + + + + context_cairo.h + + + + context_cairo_p.h + + + + + $(local/typefiles) + $(local/sources) + + + + + + + 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 + + + + + + + + + + + + + + diff --git a/src/lib/aqdiagram/draw/Makefile.am b/src/lib/aqdiagram/draw/Makefile.am new file mode 100644 index 0000000..75d25f6 --- /dev/null +++ b/src/lib/aqdiagram/draw/Makefile.am @@ -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) + + diff --git a/src/lib/aqdiagram/draw/README b/src/lib/aqdiagram/draw/README new file mode 100644 index 0000000..2f2ff58 --- /dev/null +++ b/src/lib/aqdiagram/draw/README @@ -0,0 +1 @@ +Previous af_graphics diff --git a/src/lib/aqdiagram/draw/context.xml b/src/lib/aqdiagram/draw/context.xml new file mode 100644 index 0000000..0e42225 --- /dev/null +++ b/src/lib/aqdiagram/draw/context.xml @@ -0,0 +1,286 @@ + + + + + + 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. + + + AQDG_DRAW_CONTEXT + AQDG_Draw_Context + context + + + with_list1 + with_list2 + with_inherit + with_refcount + nodup + nocopy + + + +
aqdiagram/aqdg_api.h
+
+ +
+ + + + + + + + + + + + + + + none + + + italic + + + + + + none + + + bold + + + + + + draw vertically + + + draw horizontally + + + + + + no dash + + + Dash format 1 + + + Dash format 2 + + + Dash format 3 + + + Dash format 4 + + + Dash format 5 + + + Dash format 6 + + + Dash format 7 + + + Dash format 8 + + + + + + + + + + + 0 + 0 + volatile with_getbymember + public + + + + NULL + NULL + public + + + + + + + + + Creates a pen from the given info. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + Foreground colour used for drawing + + + + + + + + Release the given pen. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + + + + + Draws a line from xStart/yStart to xEnd/yEnd using the given pen. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + Pen to be used. + + + + + + + + + + Draws a non-filled rectangle. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + Pen to be used. + + + + + + + + + + Draws a filled rectangle. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + Pen to be used. + + + + + + + + + + Creates a font from the given info. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + + + + + + + + Releases the given font. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + + + + + Draws the given text at the given position using the given font and pen. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + Pen to be used. + + + Font to be used. + + + + + + + + + + Query the width used for the given text using the given font. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + + + + + + Query the height used for the given text using the given font. + + public + GWEN_ERROR_NOT_IMPLEMENTED + int + + + + + + + + Call this when your are finished drawing. + + public + 0 + int + + + + + +
+ +
+ + + + + diff --git a/src/lib/aqdiagram/draw/context_cairo.c b/src/lib/aqdiagram/draw/context_cairo.c new file mode 100644 index 0000000..8b860cd --- /dev/null +++ b/src/lib/aqdiagram/draw/context_cairo.c @@ -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 +#endif + + +#include "context_cairo_p.h" + +#include + + + +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; +} + + + + + + diff --git a/src/lib/aqdiagram/draw/context_cairo.h b/src/lib/aqdiagram/draw/context_cairo.h new file mode 100644 index 0000000..efca044 --- /dev/null +++ b/src/lib/aqdiagram/draw/context_cairo.h @@ -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 + +#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 + + diff --git a/src/lib/aqdiagram/draw/context_cairo_p.h b/src/lib/aqdiagram/draw/context_cairo_p.h new file mode 100644 index 0000000..eab717b --- /dev/null +++ b/src/lib/aqdiagram/draw/context_cairo_p.h @@ -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 + +#include +#include +#include + + +#include +#include +#include + + + + +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 + + diff --git a/src/lib/aqdiagram/draw/font.xml b/src/lib/aqdiagram/draw/font.xml new file mode 100644 index 0000000..62ca34c --- /dev/null +++ b/src/lib/aqdiagram/draw/font.xml @@ -0,0 +1,78 @@ + + + + + + This class contains information about a font. This class is to be used by implemnentations only. + + + AQDG_DRAW_FONT + AQDG_Draw_Font + font + + + with_list1 + with_list2 + with_inherit + with_refcount + + + +
aqdiagram/draw/context.h
+ +
+ +
+ + + + + + + + + + + + + + 0 + 0 + volatile with_getbymember + public + + + + NULL + NULL + public + + + + 12 + 12 + public + + + + AQDG_Slant_None + AQDG_Slant_None + public + + + + AQDG_Weight_None + AQDG_Weight_None + public + + + + +
+ +
+ + + + + diff --git a/src/lib/aqdiagram/draw/pen.xml b/src/lib/aqdiagram/draw/pen.xml new file mode 100644 index 0000000..8087387 --- /dev/null +++ b/src/lib/aqdiagram/draw/pen.xml @@ -0,0 +1,72 @@ + + + + + + This class contains information about a pen. This class is to be used by implemnentations only. + + + AQDG_DRAW_PEN + AQDG_Draw_Pen + pen + + + with_list1 + with_list2 + with_inherit + with_refcount + + + +
aqdiagram/draw/context.h
+ +
+ +
+ + + + + + + + + + + + + + 0 + 0 + volatile with_getbymember + public + + + + 0x00000000 + 0x00000000 + public + + + + 1 + 1 + public + + + + AQDG_Dash_None + AQDG_Dash_None + public + + + + +
+ +
+ + + + + diff --git a/src/lib/aqdiagram/graph/.gitignore b/src/lib/aqdiagram/graph/.gitignore new file mode 100644 index 0000000..6af7bd5 --- /dev/null +++ b/src/lib/aqdiagram/graph/.gitignore @@ -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 + diff --git a/src/lib/aqdiagram/graph/0BUILD b/src/lib/aqdiagram/graph/0BUILD new file mode 100644 index 0000000..5cff903 --- /dev/null +++ b/src/lib/aqdiagram/graph/0BUILD @@ -0,0 +1,140 @@ + + + + + + + + + + $(gwenhywfar_cflags) + -I$(topsrcdir)/src/lib + -I$(topbuilddir)/src/lib + -I$(topbuilddir) + -I$(topsrcdir) + -I$(srcdir) + + + + --include=$(builddir) + --include=$(srcdir) + --include=$(builddir)/../types + --include=$(topsrcdir)/src/lib/typemaker2/c + --include=$(topbuilddir)/src/lib/typemaker2/c + + + + $(visibility_cflags) + + + + --api=AQDG_API + + + + + datapair.xml + dataset.xml + tick.xml + subgraph.xml + settings_pen.xml + settings_font.xml + settings.xml + + + + datapair.c + dataset.c + tick.c + subgraph.c + settings_pen.c + settings_font.c + settings.c + + + + datapair.h + dataset.h + tick.h + subgraph.h + settings_pen.h + settings_font.h + settings.h + + + + + datapair_p.h + dataset_p.h + tick_p.h + subgraph_p.h + settings_pen_p.h + settings_font_p.h + settings_p.h + + + + + + $(local/built_headers_pub) + + + + $(local/built_headers_priv) + + + + + graph.h + + + + + graph_p.h + g_draw_data.h + g_draw_xticks.h + g_draw_yticks.h + g_config.h + g_layout.h + + + + + $(local/typefiles) + graph.c + g_draw_data.c + g_draw_xticks.c + g_draw_yticks.c + g_config.c + g_layout.c + + + + + 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 + + + + + dataset_fns.c dataset_fns.h + tick_fns.c tick_fns.h + + + + + + + + + + + + + + diff --git a/src/lib/aqdiagram/graph/Makefile.am b/src/lib/aqdiagram/graph/Makefile.am new file mode 100644 index 0000000..8d0f2cf --- /dev/null +++ b/src/lib/aqdiagram/graph/Makefile.am @@ -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 + + diff --git a/src/lib/aqdiagram/graph/datapair.xml b/src/lib/aqdiagram/graph/datapair.xml new file mode 100644 index 0000000..8b7f9fe --- /dev/null +++ b/src/lib/aqdiagram/graph/datapair.xml @@ -0,0 +1,71 @@ + + + + + + This class describes data axis. + + + AQDG_GRAPH_DATAPAIR + AQDG_Graph_DataPair + datapair + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
+ +
+ + + + + 0.0 + 0.0 + public + sortbymember + + + + 0.0 + 0.0 + public + sortbymember + + + + 0 + 0 + public + + + + NULL + NULL + public + own + const dup + const + + + + 0 + 0 + with_flags + public + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/dataset.xml b/src/lib/aqdiagram/graph/dataset.xml new file mode 100644 index 0000000..e869a4e --- /dev/null +++ b/src/lib/aqdiagram/graph/dataset.xml @@ -0,0 +1,195 @@ + + + + + + + + AQDG_GRAPH_DATASET + AQDG_Graph_DataSet + dataset + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
aqdiagram/graph/datapair.h
+
aqdiagram/graph/tick.h
+
aqdiagram/graph/subgraph.h
+ +
dataset_fns.h
+
dataset_fns.c
+
+ +
+ + + + + + + integer type + + + + floating point type (double precision) + + + + date type + + + + + + + + + + + NULL + NULL + public + own + const dup + const + + + + NULL + NULL + public + own + const dup + const + + + + NULL + AQDG_Graph_DataPair_List_new() + public + own + nodup + none + + + + NULL + AQDG_Graph_SubGraph_List_new() + public + own + nodup + none + + + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0.0 + 0.0 + public + + + + 0.0 + 0.0 + public + + + + NULL + NULL + public + own + const dup + const + + + + NULL + AQDG_Graph_Tick_List_new() + public + own + nodup + none + + + + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0.0 + 0.0 + public + + + + 0.0 + 0.0 + public + + + + NULL + NULL + public + own + const dup + const + + + + NULL + AQDG_Graph_Tick_List_new() + public + own + nodup + none + + + + + + 0 + 0 + with_flags + public + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/dataset_fns.c b/src/lib/aqdiagram/graph/dataset_fns.c new file mode 100644 index 0000000..5e93202 --- /dev/null +++ b/src/lib/aqdiagram/graph/dataset_fns.c @@ -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 (vmaxVal) + 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 (vmaxVal) + 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 (cntdataPairList) { + 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 (dist1) { + *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 (dist1) { + *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; + } + } + } +} + + + + diff --git a/src/lib/aqdiagram/graph/dataset_fns.h b/src/lib/aqdiagram/graph/dataset_fns.h new file mode 100644 index 0000000..910e6b5 --- /dev/null +++ b/src/lib/aqdiagram/graph/dataset_fns.h @@ -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 + + diff --git a/src/lib/aqdiagram/graph/g_config.c b/src/lib/aqdiagram/graph/g_config.c new file mode 100644 index 0000000..476ff58 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_config.c @@ -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 +#endif + +#include "aqdiagram/graph/g_config.h" +#include "graph_p.h" + +#include + + + +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; +} + + + diff --git a/src/lib/aqdiagram/graph/g_config.h b/src/lib/aqdiagram/graph/g_config.h new file mode 100644 index 0000000..930c4ae --- /dev/null +++ b/src/lib/aqdiagram/graph/g_config.h @@ -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 + + +#endif + diff --git a/src/lib/aqdiagram/graph/g_draw_data.c b/src/lib/aqdiagram/graph/g_draw_data.c new file mode 100644 index 0000000..ed4993a --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_data.c @@ -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 +#endif + +#include "aqdiagram/graph/g_draw_data.h" +#include "aqdiagram/graph/dataset_fns.h" +#include "graph_p.h" + +#include + + + + + +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 (vXmaxValX) + vX=maxValX; + + if (vYmaxValY) + 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 (vXmaxValX) + vX=maxValX; + + if (vYmaxValY) + vY=maxValY; + + x=gr->graphOriginX + (vX * gr->graphFactorX); + y=gr->graphOriginY - (vY * gr->graphFactorY); + + /* draw the bar */ + if ((x-(barWidth/2))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 (vXmaxValX) + vX=maxValX; + + if (vYmaxValY) + 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); + } + + } +} + + + diff --git a/src/lib/aqdiagram/graph/g_draw_data.h b/src/lib/aqdiagram/graph/g_draw_data.h new file mode 100644 index 0000000..5e27848 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_data.h @@ -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 + + +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 + diff --git a/src/lib/aqdiagram/graph/g_draw_xticks.c b/src/lib/aqdiagram/graph/g_draw_xticks.c new file mode 100644 index 0000000..5719e68 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_xticks.c @@ -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 +#endif + +#include "aqdiagram/graph/g_draw_data.h" +#include "graph_p.h" + +#include + + + + +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; leveldrawContext, 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; jgraphAreaPosX; + m2=x+(i/2)-gr->graphAreaPosX; + + for (j=m1; jdrawContext, 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 */ +} + diff --git a/src/lib/aqdiagram/graph/g_draw_xticks.h b/src/lib/aqdiagram/graph/g_draw_xticks.h new file mode 100644 index 0000000..300b4f0 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_xticks.h @@ -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 + + +void AQDG_Graph_DrawXTicks(AQDG_GRAPH *gr); + + + +#endif + diff --git a/src/lib/aqdiagram/graph/g_draw_yticks.c b/src/lib/aqdiagram/graph/g_draw_yticks.c new file mode 100644 index 0000000..0d50a44 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_yticks.c @@ -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 +#endif + +#include "aqdiagram/graph/g_draw_data.h" +#include "graph_p.h" + +#include + + + +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; leveldrawContext, 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; jgraphAreaPosY; + m2=y+(i/2)-gr->graphAreaPosY; + + for (j=m1; jdrawContext, 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 */ +} + + + diff --git a/src/lib/aqdiagram/graph/g_draw_yticks.h b/src/lib/aqdiagram/graph/g_draw_yticks.h new file mode 100644 index 0000000..c7fcf56 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_draw_yticks.h @@ -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 + + +void AQDG_Graph_DrawYTicks(AQDG_GRAPH *gr); + + + +#endif + diff --git a/src/lib/aqdiagram/graph/g_layout.c b/src/lib/aqdiagram/graph/g_layout.c new file mode 100644 index 0000000..d9a406e --- /dev/null +++ b/src/lib/aqdiagram/graph/g_layout.c @@ -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 +#endif + +#include "aqdiagram/graph/g_layout.h" +#include "aqdiagram/graph/tick_fns.h" +#include "graph_p.h" + +#include + + + +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->graphOriginXgraphAreaPosX) { + /* 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->graphOriginYgraphAreaPosY) { + /* 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); +} + + + + diff --git a/src/lib/aqdiagram/graph/g_layout.h b/src/lib/aqdiagram/graph/g_layout.h new file mode 100644 index 0000000..675ae06 --- /dev/null +++ b/src/lib/aqdiagram/graph/g_layout.h @@ -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 + + +void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr); + + + +#endif + diff --git a/src/lib/aqdiagram/graph/graph.c b/src/lib/aqdiagram/graph/graph.c new file mode 100644 index 0000000..c1ffd2b --- /dev/null +++ b/src/lib/aqdiagram/graph/graph.c @@ -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 +#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 + + +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; +} + + + + + + + + diff --git a/src/lib/aqdiagram/graph/graph.h b/src/lib/aqdiagram/graph/graph.h new file mode 100644 index 0000000..9578a67 --- /dev/null +++ b/src/lib/aqdiagram/graph/graph.h @@ -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 +#include +#include +#include +#include + +#include + + + +#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 + + + diff --git a/src/lib/aqdiagram/graph/graph_p.h b/src/lib/aqdiagram/graph/graph_p.h new file mode 100644 index 0000000..e38848a --- /dev/null +++ b/src/lib/aqdiagram/graph/graph_p.h @@ -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 + + +#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 + + + diff --git a/src/lib/aqdiagram/graph/settings.xml b/src/lib/aqdiagram/graph/settings.xml new file mode 100644 index 0000000..6c06479 --- /dev/null +++ b/src/lib/aqdiagram/graph/settings.xml @@ -0,0 +1,259 @@ + + + + + + This class describes data axis. + + + AQDG_GRAPH_SETTINGS + AQDG_Graph_Settings + settings + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
aqdiagram/draw/context.h
+ +
aqdiagram/graph/graph.h
+
aqdiagram/graph/settings_pen.h
+
aqdiagram/graph/settings_font.h
+ +
+ + + + + + + $(api) void $(struct_prefix)_SetDefaults($(struct_type) *st); + + + + + + 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); + } + + + + + + + + +
+ + + + + + + + + + + + + 0 + 0 + public + with_getbymember + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + public + own + assign + + + + 0 + 0 + with_flags + public + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/settings_font.xml b/src/lib/aqdiagram/graph/settings_font.xml new file mode 100644 index 0000000..808817b --- /dev/null +++ b/src/lib/aqdiagram/graph/settings_font.xml @@ -0,0 +1,79 @@ + + + + + + This class describes data axis. + + + AQDG_GRAPH_SETTINGS_FONT + AQDG_Graph_SettingsFont + settings_font + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
+ +
+ + + + + + + + + + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + + + + 0 + 0 + with_flags + public + + + + + 0 + 0 + public + volatile with_getbymember + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/settings_pen.xml b/src/lib/aqdiagram/graph/settings_pen.xml new file mode 100644 index 0000000..3956be2 --- /dev/null +++ b/src/lib/aqdiagram/graph/settings_pen.xml @@ -0,0 +1,86 @@ + + + + + + This class describes data axis. + + + AQDG_GRAPH_SETTINGS_PEN + AQDG_Graph_SettingsPen + settings_pen + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
+ +
+ + + + + + + + + + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 1 + 1 + public + + + + + 0 + 0 + public + + + + + + + 0 + 0 + with_flags + public + + + + + 0 + 0 + public + volatile with_getbymember + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/subgraph.xml b/src/lib/aqdiagram/graph/subgraph.xml new file mode 100644 index 0000000..50c48e1 --- /dev/null +++ b/src/lib/aqdiagram/graph/subgraph.xml @@ -0,0 +1,89 @@ + + + + + + This class describes a sub graph. + + + AQDG_GRAPH_SUBGRAPH + AQDG_Graph_SubGraph + subgraph + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+
+ +
+ + + + + NULL + NULL + public + own + const dup + const + + + + 0 + 0 + public + with_getbymember + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + 0 + 0 + public + + + + + 0 + 0 + public + volatile + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/tick.xml b/src/lib/aqdiagram/graph/tick.xml new file mode 100644 index 0000000..81520c5 --- /dev/null +++ b/src/lib/aqdiagram/graph/tick.xml @@ -0,0 +1,71 @@ + + + + + + This class describes data axis. + + + AQDG_GRAPH_TICK + AQDG_Graph_Tick + tick + + + with_db + with_xml + with_list1 + with_list2 + with_refcount + + + +
aqdiagram/aqdg_api.h
+ +
aqdiagram/graph/dataset.h
+
aqdiagram/graph/tick_fns.h
+
tick_fns.c
+ +
gwenhywfar/gwendate.h
+
gwenhywfar/i18n.h
+
+ +
+ + + + + NULL + NULL + public + own + const dup + const + + + + 0.0 + 0.0 + public + sortbymember + + + + 0 + 0 + public + + + + 0 + 0 + with_flags + public + + + + + +
+ +
+ diff --git a/src/lib/aqdiagram/graph/tick_fns.c b/src/lib/aqdiagram/graph/tick_fns.c new file mode 100644 index 0000000..997279f --- /dev/null +++ b/src/lib/aqdiagram/graph/tick_fns.c @@ -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=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->levellevel) + p_rv=-1; + else + p_rv=1; + } + else if (p_a->valuevalue) + 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; + } +} + + + + + + diff --git a/src/lib/aqdiagram/graph/tick_fns.h b/src/lib/aqdiagram/graph/tick_fns.h new file mode 100644 index 0000000..35c8e57 --- /dev/null +++ b/src/lib/aqdiagram/graph/tick_fns.h @@ -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 + + diff --git a/src/lib/aqdiagram/libtest.c b/src/lib/aqdiagram/libtest.c new file mode 100644 index 0000000..f74a474 --- /dev/null +++ b/src/lib/aqdiagram/libtest.c @@ -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 +#endif + +#include +#include +#include +#include + + + + +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; +} + + +