├── .gitignore ├── INSTALL ├── LICENSE ├── Makefile ├── README.md ├── arch └── PKGBUILD ├── build-lua51.lhelper ├── build-lua54.lhelper ├── build-luajit.lhelper ├── contour.lua ├── debian ├── build.sh └── control ├── doc ├── Makefile ├── conf.py ├── contour.rst ├── graphics-categories-example.png ├── graphics-example-1.png ├── graphics-example-ibars.png ├── graphics-example-yellow-area.png ├── graphics.rst └── index.rst ├── examples ├── contour-plots.lua ├── histo.lua ├── integral-anim.lua ├── plot-simple.lua ├── vonkoch-anim.lua └── vonkoch.lua ├── graph-toolkit-scm-1.rockspec ├── init.lua ├── meson.build ├── meson_options.txt ├── scripts └── exports.sh ├── src ├── Makefile ├── agg-parse-trans.cpp ├── agg-parse-trans.h ├── agg-pixfmt-config.h ├── agg_font_freetype.cpp ├── agg_font_freetype.h ├── agg_pixfmt_rgb24_lcd.h ├── agg_platform_support_win32.cpp ├── agg_platform_support_x11.cpp ├── agg_win32_bmp.cpp ├── bitmap-plot.cpp ├── bitmap-plot.h ├── canvas-window-cpp.h ├── canvas-window.cpp ├── canvas.h ├── canvas_svg.cpp ├── canvas_svg.h ├── categories.h ├── colors.cpp ├── colors.h ├── defs.h ├── draw_svg.cpp ├── draw_svg.h ├── factor_labels.h ├── fonts.cpp ├── fonts.h ├── fonts_search_win32.cpp ├── fonts_search_x11.cpp ├── gamma.cpp ├── gs-types.c ├── gs-types.h ├── image_write.h ├── image_write_win32.cpp ├── image_write_x11.cpp ├── list.h ├── lua-compat.c ├── lua-compat.h ├── lua-cpp-utils.h ├── lua-defs.h ├── lua-draw.cpp ├── lua-draw.h ├── lua-graph-priv.h ├── lua-graph.cpp ├── lua-graph.h ├── lua-plot-cpp.h ├── lua-plot.cpp ├── lua-plot.h ├── lua-properties.c ├── lua-properties.h ├── lua-text.cpp ├── lua-text.h ├── lua-utils.c ├── lua-utils.h ├── makeconfig ├── markers.cpp ├── markers.h ├── meson.build ├── my_conv_simple_marker.h ├── path.h ├── pixel_fmt.h ├── platform_support_ext.h ├── plot-auto.cpp ├── plot-auto.h ├── plot.cpp ├── plot.h ├── printf_check.cpp ├── printf_check.h ├── pthreadpp.h ├── rect.h ├── rendering_buffer_utils.h ├── resource-manager.h ├── sg_marker.h ├── sg_object.h ├── shared_vector.h ├── split-parser.h ├── str.c ├── str.h ├── strpp.h ├── text-shape.h ├── text.cpp ├── text.h ├── text_label.h ├── trans.h ├── tree.h ├── units.cpp ├── units.h ├── utils.cpp ├── utils.h ├── window-cpp.h ├── window.cpp ├── window.h ├── window_hooks.h ├── window_registry.cpp └── window_registry.h └── subprojects └── libagg.wrap /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.dll 4 | .deps 5 | debian_build 6 | *.deb 7 | 8 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Lua Graphics Toolkit 2 | ==================== 3 | 4 | Installation instructions 5 | ------------------------- 6 | 7 | You can compile the Lua Graphics Toolkit on linux by installing the appropriate development packages. The libraries you will need and their package's name for 8 | debian based systems are: 9 | 10 | - Anti-Grain geometry library, libagg-dev package 11 | - Freetype library, libfreetype6-dev package 12 | - A Lua 5.1 library, either: 13 | * LuaJIT, libluajit-5.1-dev package 14 | * Lua 5.1, lua5.1 package 15 | 16 | To choose if you want to use Lua 5.1 or LuaJIT you should edit the file 17 | src/makeconfig and set the "LUA" variable to either lua5.1 or luajit. 18 | 19 | Once the packages above are installed you should be able to compile simply by typing: 20 | 21 | > make 22 | 23 | Then you can install the module on your system by using: 24 | 25 | > make install 26 | 27 | or, as an alternative, you can build a debian package using 28 | 29 | > make debian 30 | 31 | On Debian based system like Debian itself, Ubuntu or Linux Mint the 32 | recommended way to use the graphics toolkit is to build and install the 33 | debian package. 34 | The installation of the debian package ensure that all the require files 35 | are installed in the appropriate directories. 36 | 37 | The Lua's package will be named "graph" and can be called from luajit or 38 | lua using: 39 | 40 | > require("graph") 41 | 42 | Windows Installation Instructions 43 | --------------------------------- 44 | 45 | The Lua Graphics Toolkit can be installed on Windows using the mingw toolchain. To succeed you will need to compile before all the required libraries, edit the Makefile to add the 46 | path where the libraries are located. 47 | 48 | We strongly reccomend of using binary package on Windows. 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile 3 | # 4 | # Copyright (C) 2014-2024 Francesco Abbate 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or (at 9 | # your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, but 12 | # WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | # 20 | 21 | include src/makeconfig 22 | 23 | VERSION = 1.1 24 | 25 | PREFIX = /usr 26 | DEST_DIR = 27 | 28 | ifeq ($(strip $(DEST_DIR)), ) 29 | DEST_PREFIX = $(PREFIX) 30 | else 31 | DEST_PREFIX = $(DEST_DIR)/$(PREFIX) 32 | endif 33 | 34 | GRAPH_LUA_SRC = init.lua contour.lua 35 | 36 | LUA_PATH = $(DEST_PREFIX)/share/lua/$(LUA_VERSION) 37 | LUA_DLLPATH = $(DEST_PREFIX)/lib/lua/$(LUA_VERSION) 38 | 39 | all: 40 | $(MAKE) -C src 41 | 42 | clean: 43 | $(MAKE) -C src clean 44 | 45 | install: 46 | $(MAKE) -C src 47 | mkdir -p $(LUA_PATH)/graph 48 | mkdir -p $(LUA_DLLPATH) 49 | cp src/graphcore.so $(LUA_DLLPATH)/graphcore.so 50 | cp $(GRAPH_LUA_SRC) $(LUA_PATH)/graph 51 | 52 | .PHONY: clean all install 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Lua Graphics Toolkit 2 | ==================== 3 | 4 | The Lua Graphics Toolkit is a Lua module designed for crafting plots and graphics 5 | animations through an easy-to-use Lua interface. 6 | This module is compatible with both Windows and Linux as a standard Lua module. 7 | Although it can function on macOS, it requires an X Window server. 8 | 9 | To ensure high-quality rendering, the module employs the AntiGrain Geometry library. 10 | This allows for exceptional rendering quality via anti-aliasing and subpixel resolution. 11 | 12 | It supports Lua versions 5.1, 5.4, and LuaJIT 2.0 or 2.1. 13 | 14 | All functions are thoroughly documented in the 15 | [user manual](http://franko.github.io/graph-toolkit/), 16 | and several [examples](https://github.com/franko/graph-toolkit/tree/master/examples) 17 | are available in the git repository. 18 | 19 | The toolkit offers a straightforward interface for plotting functions. 20 | However, users can also access detailed control options. These include customizing 21 | graphical elements such as colors, positions, and the rendering pipeline. 22 | Additionally, the module natively supports Bezier curves, thanks to the AGG library. 23 | 24 | Further customization is available for axes, allowing for unique labels and even 25 | layered label systems. 26 | 27 | Plot legends are also a feature, although with certain restrictions. Currently, 28 | legends cannot be placed *inside* the plot area. 29 | 30 | Animations 31 | ---------- 32 | 33 | The module facilitates the creation of animations through a layered mechanism 34 | and several methods for adding and clearing elements from the current layer. 35 | 36 | To craft an animation, elements are added to the plot. To generate a new frame, 37 | the current layer is cleared using the `plot:clear()` method, allowing the 38 | addition of new elements for the next frame. 39 | The "sync" property can be set to "false" to accumulate changes, which can 40 | then be applied with `plot:flush()` to refresh the window. 41 | 42 | Multiple layers can be used effectively in animations. One layer can hold 43 | static graphical elements, while another layer can be dedicated to dynamic 44 | elements, creating a more complex animation. 45 | 46 | Building 47 | -------- 48 | 49 | The graphics module can be built either using the Meson build system or using GNU make. 50 | 51 | To build the following development packages are required: 52 | 53 | - the freetype2 library 54 | - the corresponding Lua or LuaJIT development package 55 | 56 | The AGG library is also required but, when using Meson, it will be automatically 57 | downloaded and built so the corresponding development package is not needed. 58 | When using the Makefile instead it is required to install the AGG library 59 | development package. 60 | 61 | To build using Meson use the commands: 62 | 63 | ```sh 64 | # The following command setup the build. 65 | # Use the lua option to choose between: lua5.1, lua5.4 and luajit 66 | # Meson will accept the following general options: 67 | # - --prefix= 68 | # - --buildtype= 69 | meson setup -Dlua=lua5.4 build 70 | 71 | # The following command will actually compile the library 72 | meson compile -C .build 73 | 74 | # Do the following to install. Meson accept a --destdir option to 75 | # specify a destination directory for packaging. 76 | meson install -C .build 77 | ``` 78 | 79 | To build using GNU Makefile please edit src/makeconfig to choose 80 | the Lua version to use or LuaJIT and the prefix directory, then 81 | use the commands: 82 | 83 | ```sh 84 | make 85 | make DESTDIR= install 86 | ``` 87 | 88 | 89 | History 90 | ------- 91 | 92 | The Lua Graphics Module was previously part of GSL Shell where it is still used. By looking at GSL Shell you can find more example of its utilisation. 93 | 94 | -------------------------------------------------------------------------------- /arch/PKGBUILD: -------------------------------------------------------------------------------- 1 | pkgname=graph-toolkit-git 2 | _pkgname=graph-toolkit 3 | pkgver=20150322 4 | pkgrel=1 5 | pkgdesc="Lua graph-toolkit" 6 | arch=('i686' 'x86_64') 7 | license=('BSD Licence') 8 | depends=('gsl' 'agg' 'lua51-bitop') 9 | makedepends=('git' 'libxft' 'freetype2' 'pkg-config') 10 | url="https://github.com/franko/graph-toolkit" 11 | source=('graph-toolkit::git+git://github.com/franko/graph-toolkit.git') 12 | md5sums=('SKIP') 13 | 14 | 15 | prepare() { 16 | cd "$srcdir/" 17 | } 18 | 19 | build() { 20 | cd "$srcdir/$_pkgname" 21 | make || return 1 22 | } 23 | 24 | package() { 25 | cd "$srcdir/$_pkgname" 26 | make DEST_DIR="$pkgdir" arch 27 | } 28 | -------------------------------------------------------------------------------- /build-lua51.lhelper: -------------------------------------------------------------------------------- 1 | CC="${CC:-gcc}" 2 | CXX="${CXX:-g++}" 3 | 4 | BUILD_TYPE="Release" 5 | 6 | packages=("freetype2 -pic" "lua -commands -pic 5.1.5-2") 7 | 8 | -------------------------------------------------------------------------------- /build-lua54.lhelper: -------------------------------------------------------------------------------- 1 | CC="${CC:-gcc}" 2 | CXX="${CXX:-g++}" 3 | 4 | BUILD_TYPE="Release" 5 | 6 | packages=("freetype2 -pic" "lua -app -pic 5.4.4") 7 | 8 | -------------------------------------------------------------------------------- /build-luajit.lhelper: -------------------------------------------------------------------------------- 1 | CC="${CC:-gcc}" 2 | CXX="${CXX:-g++}" 3 | 4 | BUILD_TYPE="Release" 5 | 6 | packages=("freetype2 -pic" "luajit -pic 2.1.0-beta3.1") 7 | 8 | -------------------------------------------------------------------------------- /debian/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LGT_ISIZE_A=(`du -s debian_build`) 4 | LGT_ISIZE=${LGT_ISIZE_A[0]} 5 | 6 | LGT_ARCH=`dpkg-architecture -qDEB_HOST_ARCH` 7 | 8 | VERSION=$1 9 | LGT_LUA=$2 10 | 11 | echo "Using Lua: $LGT_LUA" 12 | 13 | mkdir debian_build/DEBIAN 14 | 15 | cat debian/control | sed "s/LGT_VERSION/$VERSION/;s/LGT_INSTALLED_SIZE/$LGT_ISIZE/;s/LGT_ARCH/$LGT_ARCH/;s/LGT_LUA/$LGT_LUA/" - > debian_build/DEBIAN/control 16 | 17 | chown root.root -R debian_build 18 | chmod a-w -R debian_build 19 | chmod 0755 debian_build/DEBIAN 20 | 21 | dpkg-deb -b debian_build "lua-graph-toolkit_$VERSION-1_${LGT_ARCH}.deb" 22 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Package: lua-graph-toolkit 2 | Maintainer: Francesco Abbate 3 | Version: LGT_VERSION 4 | Architecture: LGT_ARCH 5 | Installed-Size: LGT_INSTALLED_SIZE 6 | Depends: libc6 (>= 2.7-1), libx11-6, LGT_LUA 7 | Section: x11 8 | Priority: optional 9 | Description: Lua Graphics Toolkit 10 | The Lua Graphics Toolkit is a LuaJIT2 module to create graphical 11 | windows for plots or animations. 12 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LuaGraphicsToolkit.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LuaGraphicsToolkit.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/LuaGraphicsToolkit" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/LuaGraphicsToolkit" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /doc/contour.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: lua 2 | 3 | .. include:: 4 | 5 | .. currentmodule:: graph 6 | 7 | Contour Plots 8 | ============= 9 | 10 | Overview 11 | -------- 12 | 13 | GSL shell offers a contour plot function to draw contour curves of bidimensional functions. The current algorithm works correctly only for continuous functions and it may give bad results if the function has discontinuities. 14 | 15 | Here is an example of its utilization to plot the function :math:`f(x,y) = x^2 - y^2`:: 16 | 17 | contour.plot(|x,y| x^2 - y^2, -8, -8, 8, 8) 18 | 19 | .. figure:: contour-plot-hyper.png 20 | 21 | .. module:: contour 22 | 23 | .. function:: plot(f, xmin, ymin, xmax, ymax[, options]) 24 | 25 | Plot a contour plot of the function ``f`` in the rectangle delimited by (xmin, ymin), (xmax, ymax) and return the plot itself. 26 | 27 | The ``options`` argument is an optional table that can contain the following fields: 28 | 29 | * ``gridx``, number of subdivision along x 30 | * ``gridy``, number of subdivision along y 31 | * ``levels``, number of contour levels or a list of the level values in monotonic order. 32 | * ``colormap`` a function that returns a color for the contour region. The argument of the function will be a number between 0 and 1. 33 | * ``show``, specify if the plot should be shown. By default it is ``true``. 34 | 35 | .. function:: polar_plot(f, R[, options]]) 36 | 37 | Plot a contour plot of the function ``f(x, y)`` over the circular domain of radius ``R`` and centered at the origin. The ``options`` table accepts the same fields as the function :func:`contour`. 38 | 39 | Example:: 40 | 41 | use 'math' 42 | 43 | p = contour.polar_plot(|x,y| cos(x)+cos(y)+0.1*x+0.3*y, 8) 44 | p.title = 'cos(x) + cos(y) + 0.1*x + 0.3*y' 45 | 46 | .. figure:: polar-contour-example-cos-cos.png 47 | -------------------------------------------------------------------------------- /doc/graphics-categories-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/franko/graph-toolkit/9957c6e23ba6001400333669fa8c79395d5bf6f6/doc/graphics-categories-example.png -------------------------------------------------------------------------------- /doc/graphics-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/franko/graph-toolkit/9957c6e23ba6001400333669fa8c79395d5bf6f6/doc/graphics-example-1.png -------------------------------------------------------------------------------- /doc/graphics-example-ibars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/franko/graph-toolkit/9957c6e23ba6001400333669fa8c79395d5bf6f6/doc/graphics-example-ibars.png -------------------------------------------------------------------------------- /doc/graphics-example-yellow-area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/franko/graph-toolkit/9957c6e23ba6001400333669fa8c79395d5bf6f6/doc/graphics-example-yellow-area.png -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to Lua Graphics Toolkit's documentation! 2 | ================================================ 3 | 4 | The Lua Graphics Toolkit is a Lua module for creating plots and graphical 5 | animations using a simple Lua interface. 6 | 7 | The module does implement the core functions in C and C++ using 8 | the Lua's C API. A second layer of functions are implemented in Lua. 9 | 10 | Currently only LuaJIT2 is officially supported but nothing prevent to use 11 | the library with the standad Lua implementation (PUC-Rio). 12 | 13 | Contents: 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | graphics.rst 19 | contour.rst 20 | 21 | 22 | Indices and tables 23 | ================== 24 | 25 | * :ref:`genindex` 26 | * :ref:`modindex` 27 | * :ref:`search` 28 | 29 | -------------------------------------------------------------------------------- /examples/contour-plots.lua: -------------------------------------------------------------------------------- 1 | local contour = require "graph.contour" 2 | 3 | local sin, cos, pi = math.sin, math.cos, math.pi 4 | 5 | local function fsincos(sx,sy) 6 | return function(x,y) 7 | return cos(x)+cos(y) + sx*x + sy*y 8 | end 9 | end 10 | 11 | local f = fsincos(0.1, 0.3) 12 | local p1 = contour.plot(f, -2*pi, -2*pi, 6*pi, 6*pi, {gridx=120, gridy=120, levels= 12, show= false}) 13 | p1.title = "f(x,y) = cos(x) + cos(y) + 0.1x + 0.3y" 14 | p1:show() 15 | 16 | 17 | local N, R, zmax = 5, 1.2, 1.2 18 | local ls = {} 19 | for k = 1, 2*N + 1 do ls[k] = zmax * (k-N-1)/N end 20 | local p = contour.polar_plot(function(x,y) return y^2 - x^2*(x+1) end, R, {levels= ls}) 21 | p.title = "f(x,y) = y^2 - x^2*(x+1)" 22 | 23 | 24 | contour.plot(function(x,y) return x*(sin(x) + cos(y)) + 0.3*y + 0.1*x end, -2*pi, -2*pi, 6*pi, 6*pi, {gridx=120, gridy=120, levels= 9}) 25 | -------------------------------------------------------------------------------- /examples/histo.lua: -------------------------------------------------------------------------------- 1 | local graph = require "graph" 2 | 3 | local function histo() 4 | local pi = math.pi 5 | local N = 800 6 | local function f(x) return 1/math.sqrt(2*pi) * math.exp(-x^2/2) end 7 | local p = graph.plot("Simulated Gaussian Distribution") 8 | local i = 0 9 | local x1, x2, n_sample = -3, 3, 25 10 | local function f_sample() 11 | if i <= n_sample then 12 | local x = x1 + (x2 - x1) * i / n_sample 13 | i = i + 1 14 | local y = f(x) * N 15 | return x, y / N + 2*(math.random() - 0.5) * math.sqrt(y) / N 16 | end 17 | end 18 | local b = graph.ibars(f_sample) 19 | p:add(b, "darkgreen") 20 | p:addline(b, graph.rgba(0, 0, 0, 150)) 21 | p:addline(graph.fxline(f, -4, 4), "red") 22 | p.xtitle, p.ytitle = "x", "Frequency" 23 | p:show() 24 | return p 25 | end 26 | 27 | histo() 28 | -------------------------------------------------------------------------------- /examples/integral-anim.lua: -------------------------------------------------------------------------------- 1 | local graph = require "graph" 2 | 3 | local pi, cos, exp = math.pi, math.cos, math.exp 4 | 5 | local function integral_fill() 6 | local function f(x) return exp(-0.1*x) * cos(x) end 7 | local p = graph.plot "y = f(x)" 8 | local x0, x1 = 0, 10*pi 9 | local cc = graph.fxline(f, x0, x1) 10 | p.sync = false 11 | p:limits(0, -1, 10*pi, 1) 12 | p:pushlayer() 13 | p:show() 14 | local N = 256 15 | local yellow = graph.rgba(255,255,0,155) 16 | for k= 2, N do 17 | local x = x0 + k * (x1-x0) / N 18 | local ca = graph.fxline(f, x0, x, k) 19 | ca:line_to(x, 0); ca:line_to(0, 0); ca:close() 20 | p:clear() 21 | p:add(ca, yellow) 22 | p:addline(cc) 23 | p:flush() 24 | end 25 | end 26 | 27 | integral_fill() 28 | -------------------------------------------------------------------------------- /examples/plot-simple.lua: -------------------------------------------------------------------------------- 1 | local graph = require "graph" 2 | 3 | local function f(x) return math.sin(x) * x^2 end 4 | local p = graph.fxplot(f, 0, 25) 5 | p.xtitle = "x axis" 6 | p.title = "y = sin(x) * x^2" 7 | -------------------------------------------------------------------------------- /examples/vonkoch-anim.lua: -------------------------------------------------------------------------------- 1 | local graph = require "graph" 2 | 3 | local pi, sqrt3_2 = math.pi, math.sqrt(3)/2 4 | 5 | local sx = {2, 1, -1, -2, -1, 1} 6 | local sy = {0, 1, 1, 0, -1, -1} 7 | 8 | for k=1, 6 do 9 | sx[k] = 0.5 * sx[k] 10 | sy[k] = sqrt3_2 * sy[k] 11 | end 12 | 13 | local function vonkoch_alpha(n, alpha) 14 | local sh = {1, -2, 1} 15 | local a, x, y = 0, 0, 0 16 | local w = {} 17 | for i = 1, n+1 do w[i] = 0 end 18 | local s = 1 / (3^n) 19 | local line = graph.path(x, y) 20 | while w[n+1] == 0 do 21 | local x1, y1 = x + (s/3) * sx[a+1], y + (s/3) * sy[a+1] 22 | local ap = (a + 1) % 6 23 | local x2e, y2e = x1 + (s/3) * sx[ap+1], y1 + (s/3) * sy[ap+1] 24 | local x2b, y2b = x + (s/2) * sx[a +1], y + (s/2) * sy[a +1] 25 | local x3, y3 = x + (2*s/3) * sx[a+1], y + (2*s/3) * sy[a+1] 26 | line:line_to(x1, y1) 27 | line:line_to(x2b * (1-alpha) + x2e * alpha, y2b * (1-alpha) + y2e * alpha) 28 | line:line_to(x3, y3) 29 | x, y = x + s * sx[a+1], y + s * sy[a+1] 30 | line:line_to(x, y) 31 | for k = 1, n+1 do 32 | w[k] = (w[k] + 1) % 4 33 | if w[k] ~= 0 then 34 | a = (a + sh[w[k]]) % 6 35 | break 36 | end 37 | end 38 | end 39 | return line 40 | end 41 | 42 | -- Create an empty plot (canvas). Since it is created as a "canvas" we 43 | -- have to explicitily set the limits and perform the flush operation. 44 | local p = graph.canvas("Von Koch's curve") 45 | p:limits(-0.15, -1, 1.15, 0.3) 46 | p.units = false 47 | p:show() 48 | 49 | -- Create the inner solid triangle 50 | local t = graph.path() 51 | t:move_to(0,0) 52 | t:line_to(1,0) 53 | t:line_to(0.5,-sqrt3_2) 54 | t:close() 55 | 56 | -- Defines two colors for the outline and the filling. 57 | local c = graph.webcolor(1) 58 | local cfill = graph.rgba(0,0,180,50) 59 | 60 | -- Add the inner triangle to the plot and push a new graphical layer. 61 | -- In this way the triangle will remain whel p:clear() will be called. 62 | p:add(t, cfill) 63 | p:pushlayer() 64 | 65 | for n = 0, 4 do 66 | for alpha = 0, 1.0, 0.01 do 67 | p:clear() -- clear the plot 68 | 69 | -- Create the Von Koch's curve segment 70 | local v = vonkoch_alpha(n, alpha) 71 | 72 | -- Add the segment three times but rotated and translated with 73 | -- a solid fill. 74 | p:add(v, cfill) 75 | p:add(v, cfill, {}, {{"translate", x=1, y=0}, {"rotate", angle=-2*pi/3}}) 76 | p:add(v, cfill, {}, {{"translate", x=0.5, y=-sqrt3_2}, {"rotate", angle=-2*2*pi/3}}) 77 | 78 | -- Add the same lines that before but only to make the outlines. 79 | p:addline(v, c) 80 | p:addline(v, c, {}, {{"translate", x=1, y=0}, {"rotate", angle=-2*pi/3}}) 81 | p:addline(v, c, {}, {{"translate", x=0.5, y=-sqrt3_2}, {"rotate", angle=-2*2*pi/3}}) 82 | 83 | -- Flush the plot so that the windows is actually updated on the screeen. 84 | p:flush() 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /examples/vonkoch.lua: -------------------------------------------------------------------------------- 1 | local graph = require "graph" 2 | 3 | local function vonkoch(n) 4 | local pi, sqrt3_2 = math.pi, math.sqrt(3)/2 5 | 6 | local sx = {2, 1, -1, -2, -1, 1} 7 | local sy = {0, 1, 1, 0, -1, -1} 8 | local sh = {1, -2, 1} 9 | local a, x, y = 0, 0, 0 10 | local w = {} 11 | for i = 1, n+1 do w[i] = 0 end 12 | 13 | local s = 1 / (3^n) 14 | for k=1, 6 do 15 | sx[k] = s * 0.5 * sx[k] 16 | sy[k] = s * sqrt3_2 * sy[k] 17 | end 18 | 19 | local first = true 20 | 21 | local function vk() 22 | if first then first = false; return x, y end 23 | if w[n+1] == 0 then 24 | x, y = x + sx[a+1], y + sy[a+1] 25 | for k = 1, n+1 do 26 | w[k] = (w[k] + 1) % 4 27 | if w[k] ~= 0 then 28 | a = (a + sh[w[k]]) % 6 29 | break 30 | end 31 | end 32 | return x, y 33 | end 34 | end 35 | 36 | local pl = graph.plot() 37 | 38 | local t = graph.path() 39 | t:move_to(0,0) 40 | t:line_to(1,0) 41 | t:line_to(0.5,-sqrt3_2) 42 | t:close() 43 | 44 | local v = graph.ipath(vk) 45 | local c = graph.rgba(0,0,180,50) 46 | pl:add(v, c) 47 | pl:add(v, c, {}, {{"translate", x=1, y=0}, {"rotate", angle=-2*pi/3}}) 48 | pl:add(v, c, {}, {{"translate", x=0.5, y=-sqrt3_2}, 49 | {"rotate", angle=-2*2*pi/3}}) 50 | pl:add(t, c) 51 | 52 | c = graph.rgb(0,0,180) 53 | 54 | pl:addline(v, c) 55 | pl:addline(v, c, {}, {{"translate", x=1, y=0}, {"rotate", angle=-2*pi/3}}) 56 | pl:addline(v, c, {}, {{"translate", x=0.5, y=-sqrt3_2}, 57 | {"rotate", angle=-2*2*pi/3}}) 58 | 59 | pl:show() 60 | return pl 61 | end 62 | 63 | vonkoch(4) 64 | -------------------------------------------------------------------------------- /graph-toolkit-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "graph-toolkit" 2 | version = "scm-1" 3 | source = { 4 | dir = "graph-toolkit-master", 5 | url = "https://github.com/franko/graph-toolkit/archive/master.zip", 6 | } 7 | description = { 8 | summary = "Lua Graphics Toolkit", 9 | detailed = [[ 10 | The Lua Graphics Toolkit is a Lua module for creating plots and graphical 11 | animations using a simple Lua interface. The module implements the core 12 | functions in C and C++ using Lua's C API. A second layer of functions are 13 | implemented in Lua. 14 | ]], 15 | homepage = "http://franko.github.io/graph-toolkit/", 16 | license = "GPL-3" 17 | } 18 | dependencies = { 19 | "lua >= 5.1" 20 | } 21 | external_dependencies = { 22 | AGG = { 23 | header = "agg2/agg_basics.h" 24 | }, 25 | FREETYPE = { 26 | header = "freetype2/ft2build.h", 27 | library = "freetype" 28 | }, 29 | platforms = { 30 | unix = { 31 | X11 = { 32 | header = "X11/Xlib.h", 33 | library = "X11" 34 | } 35 | }, 36 | macosx = { 37 | X11 = { 38 | header = "X11/Xlib.h", 39 | library = "X11" 40 | } 41 | } 42 | } 43 | } 44 | build = { 45 | type = "make", 46 | build_variables = { 47 | CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR)", 48 | CXXFLAGS = "$(CXXFLAGS) -I$(LUA_INCDIR)", 49 | }, 50 | install_variables = { 51 | PREFIX = "$(PREFIX)", 52 | LUA_PATH = "$(LUADIR)", 53 | LUA_DLLPATH = "$(LIBDIR)" 54 | }, 55 | copy_directories = { "doc" }, 56 | } 57 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('graph-toolkit', ['c', 'cpp'], version : '1.1', default_options : ['c_std=gnu11', 'cpp_std=c++14']) 2 | 3 | cc = meson.get_compiler('c') 4 | 5 | lua_name = get_option('lua') 6 | 7 | # Luajit should use lua/5.1 directory, in addition to luajit-2.0 or luajit-2.1 8 | lua_modules_dir = (lua_name == 'lua5.4' ? 'lua/5.4' : 'lua/5.1') 9 | 10 | lua_dep = dependency(lua_name) 11 | freetype_dep = dependency('freetype2') 12 | thread_dep = dependency('threads') 13 | 14 | libagg_project = subproject('libagg') 15 | libagg_dep = libagg_project.get_variable('libagg_dep') 16 | 17 | libm = cc.find_library('m', required: false) 18 | libdl = cc.find_library('dl', required: false) 19 | 20 | graph_toolkit_deps = [ libagg_dep, freetype_dep, lua_dep, thread_dep, libm, libdl ] 21 | 22 | if host_machine.system() != 'windows' 23 | graph_toolkit_deps += dependency('x11') 24 | endif 25 | 26 | graph_toolkit_c_args = [ ] 27 | 28 | subdir('src') 29 | 30 | install_data('init.lua', rename : 'graph.lua', install_dir : 'share' / lua_modules_dir) 31 | install_data('contour.lua', install_dir : 'share' / lua_modules_dir / 'graph') 32 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('gamma-correction', type : 'boolean', value : true, description: 'Enable gamma correction') 2 | option('subpixel-lcd', type : 'boolean', value : true, description: 'Enable subpixel LCD rendering') 3 | option('lua', type : 'combo', choices : [ 'lua5.1', 'lua5.4', 'luajit' ], value : 'lua5.1', description: 'Which Lua implementation to use') 4 | 5 | -------------------------------------------------------------------------------- /scripts/exports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Print exported symbols for a DLL on Windows 3 | # from: https://nullprogram.com/blog/2021/05/31/ 4 | set -e 5 | printf 'LIBRARY %s\nEXPORTS\n' "$1" 6 | objdump -p "$1" | awk '/^$/{t=0} {if(t)print$NF} /^\[O/{t=1}' 7 | 8 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile 3 | # 4 | # Copyright (C) 2014-2024 Francesco Abbate 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or (at 9 | # your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, but 12 | # WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | # 20 | 21 | include makeconfig 22 | 23 | AR = ar rcu 24 | RANLIB = ranlib 25 | 26 | ifneq (,$(findstring Windows,$(OS))) 27 | HOST_SYS= Windows 28 | else 29 | HOST_SYS:= $(shell uname -s) 30 | ifneq (,$(findstring CYGWIN,$(TARGET_SYS))) 31 | HOST_SYS= Windows 32 | endif 33 | endif 34 | 35 | CFLAGS += -fvisibility=hidden 36 | CXXFLAGS += -fvisibility=hidden 37 | ifeq ($(strip $(DEBUG)), yes) 38 | CFLAGS += -g -Wall 39 | CXXFLAGS += -g -Wall 40 | DEFS += -LIBGRAPH_DEBUG 41 | else 42 | CFLAGS += -O2 -fomit-frame-pointer -ffast-math -Wall 43 | CXXFLAGS += -O2 -fno-exceptions -ffast-math -fno-rtti -Wall 44 | endif 45 | 46 | PTHREAD_DEFS += -D_REENTRANT 47 | CPP_SUP_LIBS = -lsupc++ 48 | 49 | ifeq ($(strip $(DISABLE_GAMMA_CORR)), yes) 50 | DEFS += -DDISABLE_GAMMA_CORR 51 | endif 52 | 53 | ifeq ($(strip $(DISABLE_SUBPIXEL_LCD)), yes) 54 | DEFS += -DDISABLE_SUBPIXEL_AA 55 | endif 56 | 57 | # GWH (for OS X): pkg-config will include "-Wl,-rpath,/opt/local/lib" in AGG_LIBS. 58 | # If you don't include that, the code won't run unless you first do: 59 | # export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib 60 | 61 | AGG_INCLUDES = $(shell pkg-config libagg --cflags) 62 | AGG_LIBS = $(shell pkg-config libagg --libs) 63 | 64 | FREETYPE_INCLUDES = $(shell pkg-config freetype2 --cflags) 65 | FREETYPE_LIBS = $(shell pkg-config freetype2 --libs) 66 | 67 | LUA_INCLUDES = $(shell pkg-config --cflags $(LUA)) 68 | LUA_LIBS = $(shell pkg-config --libs $(LUA)) 69 | 70 | PTHREAD_DEFS += -pthread 71 | PTHREAD_LIBS = -lpthread 72 | 73 | INCLUDES += $(LUA_INCLUDES) $(FREETYPE_INCLUDES) $(AGG_INCLUDES) 74 | LIBS += $(FREETYPE_LIBS) $(AGG_LIBS) $(LUA_LIBS) $(PTHREAD_LIBS) $(CPP_SUP_LIBS) 75 | DEFS += $(PTHREAD_DEFS) 76 | 77 | ifeq ($(strip $(LUA)),lua5.4) 78 | INCLUDES += -DGRAPH_TK_USE_LUA54 79 | endif 80 | 81 | ifeq ($(HOST_SYS),Windows) 82 | DYNCC = $(CC) 83 | DYNCXX = $(CXX) 84 | DLLINK = $(CC) -shared 85 | LDFLAGS += -fvisibility=hidden 86 | LIBS += -lgdi32 87 | 88 | DISPLAY_SUFFIX = win32 89 | LIBGRAPH_SO = graphcore.dll 90 | else 91 | X11_INCLUDES = $(shell pkg-config x11 --cflags) 92 | X11_LIBS = $(shell pkg-config x11 --libs) 93 | 94 | INCLUDES += $(X11_INCLUDES) 95 | LIBS += $(X11_LIBS) 96 | 97 | DYNCC = $(CC) -fPIC 98 | DYNCXX = $(CXX) -fPIC 99 | DLLINK = $(CC) -shared 100 | LDFLAGS += -fvisibility=hidden 101 | 102 | ifeq ($(HOST_SYS),Linux) 103 | # See: https://stackoverflow.com/questions/2222162/how-to-apply-fvisibility-option-to-symbols-in-static-libraries 104 | # The following flag is to consider hidden all the symbols defined in static libraries we use 105 | # to link the shared library. 106 | LDFLAGS += -Wl,--exclude-libs,ALL 107 | endif 108 | 109 | ifeq ($(HOST_SYS),Darwin) 110 | LDFLAGS += -Wl,-E 111 | endif 112 | 113 | DISPLAY_SUFFIX = x11 114 | LIBGRAPH_SO = graphcore.so 115 | endif 116 | 117 | LIBGRAPH_A = libgraphcore.a 118 | 119 | ifeq ($(HOST_SYS),Windows) 120 | PLATFORM_SRC_FILES = agg_platform_support_win32.cpp agg_win32_bmp.cpp 121 | else 122 | ifeq ($(HOST_SYS),Darwin) 123 | DEFS += -DDARWIN_MACOSX 124 | endif 125 | PLATFORM_SRC_FILES = agg_platform_support_x11.cpp 126 | endif 127 | 128 | PLOT_CSRC_FILES = str.c gs-types.c lua-utils.c lua-properties.c lua-compat.c 129 | PLOT_CPPSRC_FILES = gamma.cpp printf_check.cpp utils.cpp \ 130 | window_registry.cpp fonts_search_$(DISPLAY_SUFFIX).cpp \ 131 | $(PLATFORM_SRC_FILES) image_write_$(DISPLAY_SUFFIX).cpp \ 132 | fonts.cpp agg_font_freetype.cpp plot.cpp plot-auto.cpp units.cpp \ 133 | colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp\ 134 | lua-text.cpp text.cpp agg-parse-trans.cpp lua-plot.cpp \ 135 | bitmap-plot.cpp lua-graph.cpp canvas-window.cpp window.cpp 136 | PLOT_OBJ_FILES := $(PLOT_CSRC_FILES:%.c=%.o) $(PLOT_CPPSRC_FILES:%.cpp=%.o) 137 | 138 | DEP_FILES := $(PLOT_CPPSRC_FILES:%.cpp=.deps/%.P) $(PLOT_CSRC_FILES:%.c=.deps/%.P) 139 | 140 | DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) 141 | 142 | ifeq ($(strip $(BUILD)), dynamic) 143 | COMPILE = $(DYNCC) $(CFLAGS) $(DEFS) $(INCLUDES) 144 | CXXCOMPILE = $(DYNCXX) $(CXXFLAGS) $(DEFS) $(INCLUDES) 145 | 146 | TARGETS = $(LIBGRAPH_SO) 147 | else 148 | COMPILE = $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) 149 | CXXCOMPILE = $(CXX) $(CXXFLAGS) $(DEFS) $(INCLUDES) 150 | 151 | TARGETS = $(LIBGRAPH_A) 152 | endif 153 | 154 | all: $(TARGETS) 155 | 156 | $(LIBGRAPH_SO): $(PLOT_OBJ_FILES) 157 | $(DLLINK) $(LDFLAGS) $(PLOT_OBJ_FILES) -o $@ $(LIBS) 158 | strip --strip-unneeded $@ 159 | 160 | $(LIBGRAPH_A): $(PLOT_OBJ_FILES) 161 | @echo Archive $@ 162 | @$(AR) $@ $? 163 | @$(RANLIB) $@ 164 | 165 | clean: 166 | rm -fr *.o *.a *.so *.dll $(TARGETS) 167 | 168 | %.o: %.cpp 169 | @echo Compiling $< 170 | @$(CXXCOMPILE) -Wp,-MMD,.deps/$(*F).pp -c $< 171 | @-cp .deps/$(*F).pp .deps/$(*F).P; \ 172 | tr ' ' '\012' < .deps/$(*F).pp \ 173 | | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ 174 | >> .deps/$(*F).P; \ 175 | rm .deps/$(*F).pp 176 | 177 | %.o: %.c 178 | @echo Compiling $< 179 | @$(COMPILE) -Wp,-MMD,.deps/$(*F).pp -c $< 180 | @-cp .deps/$(*F).pp .deps/$(*F).P; \ 181 | tr ' ' '\012' < .deps/$(*F).pp \ 182 | | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ 183 | >> .deps/$(*F).P; \ 184 | rm .deps/$(*F).pp 185 | 186 | .PHONY: clean all 187 | 188 | -include $(DEP_FILES) 189 | -------------------------------------------------------------------------------- /src/agg-parse-trans.h: -------------------------------------------------------------------------------- 1 | #ifndef AGG_PARSE_TRANS_H 2 | #define AGG_PARSE_TRANS_H 3 | 4 | extern "C" { 5 | #include "lua.h" 6 | } 7 | 8 | #include "lua-cpp-utils.h" 9 | #include "sg_object.h" 10 | #include "agg_color_rgba.h" 11 | 12 | extern sg_object* parse_graph_args (lua_State *L, agg::rgba8& color, 13 | gslshell::ret_status& st, int layer_index); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/agg-pixfmt-config.h: -------------------------------------------------------------------------------- 1 | #ifndef AGG_PIXFMT_CONFIG_H 2 | #define AGG_PIXFMT_CONFIG_H 3 | 4 | #include "platform/agg_platform_support.h" 5 | #include "agg_gamma_lut.h" 6 | #include "agg_pixfmt_rgb24_lcd.h" 7 | 8 | namespace gslshell 9 | { 10 | typedef agg::gamma_lut gamma_type; 11 | 12 | const agg::pix_format_e pixel_format = agg::pix_format_rgb24; 13 | const bool flip_y = true; 14 | 15 | extern agg::pix_format_e sys_pixel_format; 16 | extern unsigned sys_bpp; 17 | 18 | extern gamma_type gamma; 19 | extern agg::lcd_distribution_lut subpixel_lut; 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/agg_font_freetype.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------- 2 | // Anti-Grain Geometry - Version 2.4 3 | // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 | // 5 | // Permission to copy, use, modify, sell and distribute this software 6 | // is granted provided this copyright notice appears in all copies. 7 | // This software is provided "as is" without express or implied 8 | // warranty, and with no claim as to its suitability for any purpose. 9 | // 10 | //---------------------------------------------------------------------------- 11 | // Contact: mcseem@antigrain.com 12 | // mcseemagg@yahoo.com 13 | // http://www.antigrain.com 14 | //---------------------------------------------------------------------------- 15 | // 16 | // See implementation agg_font_freetype.cpp 17 | // 18 | //---------------------------------------------------------------------------- 19 | 20 | #ifndef AGG_FONT_FREETYPE_INCLUDED 21 | #define AGG_FONT_FREETYPE_INCLUDED 22 | 23 | #include 24 | #include FT_FREETYPE_H 25 | 26 | 27 | #include "agg_scanline_storage_aa.h" 28 | #include "agg_scanline_storage_bin.h" 29 | #include "agg_scanline_u.h" 30 | #include "agg_scanline_bin.h" 31 | #include "agg_path_storage_integer.h" 32 | #include "agg_rasterizer_scanline_aa.h" 33 | #include "agg_conv_curve.h" 34 | #include "agg_font_cache_manager.h" 35 | #include "agg_trans_affine.h" 36 | 37 | namespace agg 38 | { 39 | 40 | 41 | //-----------------------------------------------font_engine_freetype_base 42 | class font_engine_freetype_base 43 | { 44 | public: 45 | //-------------------------------------------------------------------- 46 | typedef serialized_scanlines_adaptor_aa gray8_adaptor_type; 47 | typedef serialized_scanlines_adaptor_bin mono_adaptor_type; 48 | typedef scanline_storage_aa8 scanlines_aa_type; 49 | typedef scanline_storage_bin scanlines_bin_type; 50 | 51 | //-------------------------------------------------------------------- 52 | ~font_engine_freetype_base(); 53 | font_engine_freetype_base(bool flag32, unsigned max_faces = 32); 54 | 55 | // Set font parameters 56 | //-------------------------------------------------------------------- 57 | void resolution(unsigned dpi); 58 | bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, 59 | const char* font_mem = 0, const long font_mem_size = 0); 60 | bool attach(const char* file_name); 61 | bool char_map(FT_Encoding map); 62 | bool height(double h); 63 | bool width(double w); 64 | void hinting(bool h); 65 | void flip_y(bool f); 66 | void transform(const trans_affine& affine); 67 | 68 | // Set Gamma 69 | //-------------------------------------------------------------------- 70 | template void gamma(const GammaF& f) 71 | { 72 | m_rasterizer.gamma(f); 73 | } 74 | 75 | // Accessors 76 | //-------------------------------------------------------------------- 77 | int last_error() const { 78 | return m_last_error; 79 | } 80 | unsigned resolution() const { 81 | return m_resolution; 82 | } 83 | const char* name() const { 84 | return m_name; 85 | } 86 | unsigned num_faces() const; 87 | FT_Encoding char_map() const { 88 | return m_char_map; 89 | } 90 | double height() const { 91 | return double(m_height) / 64.0; 92 | } 93 | double width() const { 94 | return double(m_width) / 64.0; 95 | } 96 | double ascender() const; 97 | double descender() const; 98 | bool hinting() const { 99 | return m_hinting; 100 | } 101 | bool flip_y() const { 102 | return m_flip_y; 103 | } 104 | 105 | 106 | // Interface mandatory to implement for font_cache_manager 107 | //-------------------------------------------------------------------- 108 | const char* font_signature() const { 109 | return m_signature; 110 | } 111 | int change_stamp() const { 112 | return m_change_stamp; 113 | } 114 | 115 | bool prepare_glyph(unsigned glyph_code); 116 | unsigned glyph_index() const { 117 | return m_glyph_index; 118 | } 119 | unsigned data_size() const { 120 | return m_data_size; 121 | } 122 | glyph_data_type data_type() const { 123 | return m_data_type; 124 | } 125 | const rect_i& bounds() const { 126 | return m_bounds; 127 | } 128 | double advance_x() const { 129 | return m_advance_x; 130 | } 131 | double advance_y() const { 132 | return m_advance_y; 133 | } 134 | void write_glyph_to(int8u* data) const; 135 | bool add_kerning(unsigned first, unsigned second, 136 | double* x, double* y); 137 | 138 | private: 139 | font_engine_freetype_base(const font_engine_freetype_base&); 140 | const font_engine_freetype_base& operator = (const font_engine_freetype_base&); 141 | 142 | void update_char_size(); 143 | void update_signature(); 144 | int find_face(const char* face_name) const; 145 | 146 | bool m_flag32; 147 | int m_change_stamp; 148 | int m_last_error; 149 | char* m_name; 150 | unsigned m_name_len; 151 | unsigned m_face_index; 152 | FT_Encoding m_char_map; 153 | char* m_signature; 154 | unsigned m_height; 155 | unsigned m_width; 156 | bool m_hinting; 157 | bool m_flip_y; 158 | bool m_library_initialized; 159 | FT_Library m_library; // handle to library 160 | FT_Face* m_faces; // A pool of font faces 161 | char** m_face_names; 162 | unsigned m_num_faces; 163 | unsigned m_max_faces; 164 | FT_Face m_cur_face; // handle to the current face object 165 | int m_resolution; 166 | glyph_rendering m_glyph_rendering; 167 | unsigned m_glyph_index; 168 | unsigned m_data_size; 169 | glyph_data_type m_data_type; 170 | rect_i m_bounds; 171 | double m_advance_x; 172 | double m_advance_y; 173 | trans_affine m_affine; 174 | 175 | path_storage_integer m_path16; 176 | path_storage_integer m_path32; 177 | conv_curve > m_curves16; 178 | conv_curve > m_curves32; 179 | scanline_u8 m_scanline_aa; 180 | scanline_bin m_scanline_bin; 181 | scanlines_aa_type m_scanlines_aa; 182 | scanlines_bin_type m_scanlines_bin; 183 | rasterizer_scanline_aa<> m_rasterizer; 184 | }; 185 | 186 | 187 | 188 | 189 | //------------------------------------------------font_engine_freetype_int16 190 | // This class uses values of type int16 (10.6 format) for the vector cache. 191 | // The vector cache is compact, but when rendering glyphs of height 192 | // more that 200 there integer overflow can occur. 193 | // 194 | class font_engine_freetype_int16 : public font_engine_freetype_base 195 | { 196 | public: 197 | typedef serialized_integer_path_adaptor path_adaptor_type; 198 | typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; 199 | typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; 200 | typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; 201 | typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; 202 | 203 | font_engine_freetype_int16(unsigned max_faces = 32) : 204 | font_engine_freetype_base(false, max_faces) {} 205 | }; 206 | 207 | //------------------------------------------------font_engine_freetype_int32 208 | // This class uses values of type int32 (26.6 format) for the vector cache. 209 | // The vector cache is twice larger than in font_engine_freetype_int16, 210 | // but it allows you to render glyphs of very large sizes. 211 | // 212 | class font_engine_freetype_int32 : public font_engine_freetype_base 213 | { 214 | public: 215 | typedef serialized_integer_path_adaptor path_adaptor_type; 216 | typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; 217 | typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; 218 | typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; 219 | typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; 220 | 221 | font_engine_freetype_int32(unsigned max_faces = 32) : 222 | font_engine_freetype_base(true, max_faces) {} 223 | }; 224 | 225 | 226 | } 227 | 228 | #endif 229 | -------------------------------------------------------------------------------- /src/agg_pixfmt_rgb24_lcd.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------- 2 | // Anti-Grain Geometry (AGG) - Version 2.5 3 | // A high quality rendering engine for C++ 4 | // Copyright (C) 2002-2006 Maxim Shemanarev 5 | // Contact: mcseem@antigrain.com 6 | // mcseemagg@yahoo.com 7 | // http://antigrain.com 8 | // 9 | // AGG is free software; you can redistribute it and/or 10 | // modify it under the terms of the GNU General Public License 11 | // as published by the Free Software Foundation; either version 2 12 | // of the License, or (at your option) any later version. 13 | // 14 | // AGG is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with AGG; if not, write to the Free Software 21 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 22 | // MA 02110-1301, USA. 23 | //---------------------------------------------------------------------------- 24 | 25 | // Modified for GSL Shell by Francesco Abbate, 2012. 26 | 27 | #ifndef AGG_PIXFMT_RGB24_LCD_INCLUDED 28 | #define AGG_PIXFMT_RGB24_LCD_INCLUDED 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "agg_basics.h" 35 | #include "agg_color_rgba.h" 36 | #include "agg_rendering_buffer.h" 37 | 38 | namespace agg 39 | { 40 | 41 | 42 | //=====================================================lcd_distribution_lut 43 | class lcd_distribution_lut 44 | { 45 | public: 46 | lcd_distribution_lut(double prim, double second, double tert) 47 | { 48 | double norm = 1.0 / (prim + second*2 + tert*2); 49 | prim *= norm; 50 | second *= norm; 51 | tert *= norm; 52 | for(unsigned i = 0; i < 256; i++) 53 | { 54 | unsigned b = (i << 8); 55 | unsigned s = round(second * b); 56 | unsigned t = round(tert * b); 57 | unsigned p = b - (2*s + 2*t); 58 | 59 | m_data[3*i + 1] = s; /* secondary */ 60 | m_data[3*i + 2] = t; /* tertiary */ 61 | m_data[3*i ] = p; /* primary */ 62 | } 63 | } 64 | 65 | unsigned convolution(const int8u* covers, int i0, int i_min, int i_max) const 66 | { 67 | unsigned sum = 0; 68 | int k_min = (i0 >= i_min + 2 ? -2 : i_min - i0); 69 | int k_max = (i0 <= i_max - 2 ? 2 : i_max - i0); 70 | for (int k = k_min; k <= k_max; k++) 71 | { 72 | /* select the primary, secondary or tertiary channel */ 73 | int channel = abs(k) % 3; 74 | int8u c = covers[i0 + k]; 75 | sum += m_data[3*c + channel]; 76 | } 77 | 78 | return (sum + 128) >> 8; 79 | } 80 | 81 | private: 82 | unsigned short m_data[256*3]; 83 | }; 84 | 85 | 86 | 87 | 88 | 89 | //========================================================pixfmt_rgb24_lcd 90 | class pixfmt_rgb24_lcd 91 | { 92 | public: 93 | typedef rgba8 color_type; 94 | typedef rendering_buffer::row_data row_data; 95 | typedef color_type::value_type value_type; 96 | typedef color_type::calc_type calc_type; 97 | 98 | //-------------------------------------------------------------------- 99 | pixfmt_rgb24_lcd(rendering_buffer& rb, const lcd_distribution_lut& lut) 100 | : m_rbuf(&rb), m_lut(&lut) 101 | { 102 | } 103 | 104 | //-------------------------------------------------------------------- 105 | unsigned width() const { 106 | return m_rbuf->width() * 3; 107 | } 108 | unsigned height() const { 109 | return m_rbuf->height(); 110 | } 111 | 112 | 113 | // This method should never be called when using the scanline_u8. 114 | // The use of scanline_p8 should be avoided because if does not works 115 | // properly for rendering fonts because single hspan are split in many 116 | // hline/hspan elements and pixel whitening happens. 117 | void blend_hline(int x, int y, unsigned len, 118 | const color_type& c, int8u cover) 119 | { } 120 | 121 | void copy_hline(int x, int y, unsigned len, const color_type& c) 122 | { 123 | int xr = x - (x % 3); 124 | int8u* p = m_rbuf->row_ptr(y) + xr; 125 | for (int ilen = len; ilen > 0; p += 3, ilen -= 3) 126 | { 127 | p[0] = c.r; 128 | p[1] = c.g; 129 | p[2] = c.b; 130 | } 131 | } 132 | 133 | //-------------------------------------------------------------------- 134 | void blend_solid_hspan(int x, int y, 135 | unsigned len, 136 | const color_type& c, 137 | const int8u* covers) 138 | { 139 | unsigned rowlen = width(); 140 | int cx = (x - 2 >= 0 ? -2 : -x); 141 | int cx_max = (len + 2 <= rowlen ? len + 1 : rowlen - 1); 142 | 143 | int i = (x + cx) % 3; 144 | 145 | int8u rgb[3] = { c.r, c.g, c.b }; 146 | int8u* p = m_rbuf->row_ptr(y) + (x + cx); 147 | 148 | for (/* */; cx <= cx_max; cx++) 149 | { 150 | unsigned c_conv = m_lut->convolution(covers, cx, 0, len - 1); 151 | unsigned alpha = (c_conv + 1) * (c.a + 1); 152 | unsigned dst_col = rgb[i], src_col = (*p); 153 | *p = (int8u)((((dst_col - src_col) * alpha) + (src_col << 16)) >> 16); 154 | 155 | p ++; 156 | i = (i + 1) % 3; 157 | } 158 | } 159 | 160 | private: 161 | rendering_buffer* m_rbuf; 162 | const lcd_distribution_lut* m_lut; 163 | }; 164 | 165 | template 166 | class pixfmt_rgb24_lcd_gamma 167 | { 168 | public: 169 | typedef rgba8 color_type; 170 | typedef rendering_buffer::row_data row_data; 171 | typedef color_type::value_type value_type; 172 | typedef color_type::calc_type calc_type; 173 | 174 | //-------------------------------------------------------------------- 175 | pixfmt_rgb24_lcd_gamma(rendering_buffer& rb, const lcd_distribution_lut& lut, const Gamma& gamma) 176 | : m_rbuf(&rb), m_lut(&lut), m_gamma(gamma) 177 | { 178 | } 179 | 180 | //-------------------------------------------------------------------- 181 | unsigned width() const { 182 | return m_rbuf->width() * 3; 183 | } 184 | unsigned height() const { 185 | return m_rbuf->height(); 186 | } 187 | 188 | 189 | // This method should never be called when using the scanline_u8. 190 | // The use of scanline_p8 should be avoided because if does not works 191 | // properly for rendering fonts because single hspan are split in many 192 | // hline/hspan elements and pixel whitening happens. 193 | void blend_hline(int x, int y, unsigned len, 194 | const color_type& c, int8u cover) 195 | { } 196 | 197 | void copy_hline(int x, int y, unsigned len, const color_type& c) 198 | { 199 | int xr = x - (x % 3); 200 | int8u* p = m_rbuf->row_ptr(y) + xr; 201 | for (int ilen = len; ilen > 0; p += 3, ilen -= 3) 202 | { 203 | p[0] = c.r; 204 | p[1] = c.g; 205 | p[2] = c.b; 206 | } 207 | } 208 | 209 | //-------------------------------------------------------------------- 210 | void blend_solid_hspan(int x, int y, 211 | unsigned len, 212 | const color_type& c, 213 | const int8u* covers) 214 | { 215 | unsigned rowlen = width(); 216 | int cx = (x - 2 >= 0 ? -2 : -x); 217 | int cx_max = (len + 2 <= rowlen ? len + 1 : rowlen - 1); 218 | 219 | int i = (x + cx) % 3; 220 | 221 | int8u rgb[3] = { c.r, c.g, c.b }; 222 | int8u* p = m_rbuf->row_ptr(y) + (x + cx); 223 | 224 | for (/* */; cx <= cx_max; cx++) 225 | { 226 | unsigned c_conv = m_lut->convolution(covers, cx, 0, len - 1); 227 | unsigned alpha = (c_conv + 1) * (c.a + 1); 228 | unsigned dst_col = m_gamma.dir(rgb[i]), src_col = m_gamma.dir(*p); 229 | *p = m_gamma.inv((((dst_col - src_col) * alpha) + (src_col << 16)) >> 16); 230 | 231 | p ++; 232 | i = (i + 1) % 3; 233 | } 234 | } 235 | 236 | private: 237 | rendering_buffer* m_rbuf; 238 | const lcd_distribution_lut* m_lut; 239 | const Gamma& m_gamma; 240 | }; 241 | 242 | 243 | } 244 | 245 | #endif 246 | 247 | -------------------------------------------------------------------------------- /src/bitmap-plot.cpp: -------------------------------------------------------------------------------- 1 | 2 | extern "C" { 3 | #include "lua.h" 4 | #include "lauxlib.h" 5 | } 6 | 7 | #include "bitmap-plot.h" 8 | #include "lua-compat.h" 9 | #include "lua-cpp-utils.h" 10 | #include "lua-plot-cpp.h" 11 | #include "gs-types.h" 12 | #include "canvas.h" 13 | #include "colors.h" 14 | #include "pixel_fmt.h" 15 | #include "agg-pixfmt-config.h" 16 | #include "platform_support_ext.h" 17 | #include "image_write.h" 18 | 19 | void 20 | bitmap_save_image_cpp (sg_plot *p, const char *fn, unsigned w, unsigned h, 21 | gslshell::ret_status& st) 22 | { 23 | agg::rendering_buffer rbuf_tmp; 24 | unsigned row_size = w * (LIBGRAPH_BPP / 8); 25 | unsigned buf_size = h * row_size; 26 | 27 | unsigned char* buffer = new(std::nothrow) unsigned char[buf_size]; 28 | if (!buffer) 29 | { 30 | st.error("cannot allocate memory", "plot save"); 31 | return; 32 | } 33 | 34 | rbuf_tmp.attach(buffer, w, h, gslshell::flip_y ? row_size : -row_size); 35 | 36 | canvas can(rbuf_tmp, w, h, colors::white); 37 | agg::trans_affine mtx(w, 0.0, 0.0, h, 0.0, 0.0); 38 | 39 | agg::rect_base r = rect_of_slot_matrix(mtx); 40 | can.clear_box(r); 41 | 42 | p->draw(can, mtx, NULL); 43 | 44 | bool success = save_image_file (rbuf_tmp, fn, gslshell::pixel_format); 45 | 46 | if (! success) 47 | st.error("cannot save image file", "plot save"); 48 | 49 | delete [] buffer; 50 | } 51 | 52 | int 53 | bitmap_save_image (lua_State *L) 54 | { 55 | sg_plot *p = object_check(L, 1, GS_PLOT); 56 | const char *fn = luaL_checkstring (L, 2); 57 | int w = luaL_optint (L, 3, 480), h = luaL_optint (L, 4, 480); 58 | 59 | if (w <= 0 || w > 1024 * 8) 60 | luaL_error (L, "width out of range"); 61 | 62 | if (h <= 0 || h > 1024 * 8) 63 | luaL_error (L, "height out of range"); 64 | 65 | gslshell::ret_status st; 66 | bitmap_save_image_cpp (p, fn, w, h, st); 67 | if (st.error_msg()) 68 | return luaL_error (L, "%s in %s", st.error_msg(), st.context()); 69 | 70 | return 0; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/bitmap-plot.h: -------------------------------------------------------------------------------- 1 | #ifndef BITMAP_PLOT_H 2 | #define BITMAP_PLOT_H 3 | 4 | extern "C" { 5 | 6 | #include "lua.h" 7 | 8 | extern int bitmap_save_image (lua_State *L); 9 | 10 | } 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/canvas-window-cpp.h: -------------------------------------------------------------------------------- 1 | #ifndef CANVAS_WINDOW_CPP_H 2 | #define CANVAS_WINDOW_CPP_H 3 | 4 | #include 5 | #include 6 | 7 | #include "agg-pixfmt-config.h" 8 | #include "platform_support_ext.h" 9 | #include "agg_trans_affine.h" 10 | #include "agg_color_rgba.h" 11 | 12 | extern "C" { 13 | #include "lua.h" 14 | #include "lauxlib.h" 15 | } 16 | 17 | #include "defs.h" 18 | #include "canvas.h" 19 | #include "utils.h" 20 | 21 | class canvas_window : public platform_support_ext { 22 | protected: 23 | canvas *m_canvas; 24 | agg::rgba8 m_bgcolor; 25 | 26 | agg::trans_affine m_matrix; 27 | 28 | pthread_t m_thread; 29 | 30 | public: 31 | 32 | struct thread_info { 33 | lua_State *L; 34 | canvas_window *win; 35 | int window_id; 36 | 37 | thread_info (lua_State *L, canvas_window *win) : L(L), win(win) {}; 38 | }; 39 | 40 | enum win_status_e { not_ready, running, error, closed }; 41 | 42 | enum win_status_e status; 43 | 44 | canvas_window(agg::rgba8 bgcol): 45 | platform_support_ext(gslshell::pixel_format, true), 46 | m_canvas(NULL), m_bgcolor(bgcol), m_matrix(), status(not_ready) 47 | { }; 48 | 49 | virtual ~canvas_window() 50 | { 51 | if (m_canvas) 52 | delete m_canvas; 53 | }; 54 | 55 | virtual void on_init(); 56 | virtual void on_resize(int sx, int sy); 57 | 58 | void shutdown_close(bool send_close_request); 59 | 60 | bool start_new_thread (std::unique_ptr& inf); 61 | 62 | void scale (agg::trans_affine& m) { 63 | trans_affine_compose (m, m_matrix); 64 | }; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/canvas-window.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* canvas-window.cpp 3 | * 4 | * Copyright (C) 2009, 2010 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include "defs.h" 22 | #include "canvas-window-cpp.h" 23 | #include "resource-manager.h" 24 | #include "agg-parse-trans.h" 25 | #include "lua-cpp-utils.h" 26 | #include "lua-utils.h" 27 | #include "window_registry.h" 28 | #include "lua-draw.h" 29 | #include "gs-types.h" 30 | #include "colors.h" 31 | #include "canvas.h" 32 | #include "trans.h" 33 | 34 | __BEGIN_DECLS 35 | 36 | static void * canvas_thread_function (void *_win); 37 | 38 | __END_DECLS 39 | 40 | void 41 | canvas_window::on_resize(int sx, int sy) 42 | { 43 | if (m_canvas) 44 | delete m_canvas; 45 | 46 | m_canvas = new(std::nothrow) canvas(rbuf_window(), sx, sy, m_bgcolor); 47 | 48 | m_matrix.sx = sx; 49 | m_matrix.sy = sy; 50 | } 51 | 52 | void 53 | canvas_window::on_init() 54 | { 55 | this->on_resize(width(), height()); 56 | } 57 | 58 | bool canvas_window::start_new_thread (std::unique_ptr& inf) 59 | { 60 | if (status != not_ready && status != closed) 61 | return false; 62 | 63 | pthread_attr_t attr[1]; 64 | 65 | pthread_attr_init (attr); 66 | pthread_attr_setdetachstate (attr, PTHREAD_CREATE_JOINABLE); 67 | 68 | void *user_data = (void *) inf.get(); 69 | if (pthread_create(&m_thread, attr, canvas_thread_function, user_data)) 70 | { 71 | this->status = canvas_window::error; 72 | pthread_attr_destroy (attr); 73 | return false; 74 | } 75 | else 76 | { 77 | inf.release(); 78 | pthread_attr_destroy (attr); 79 | } 80 | 81 | return true; 82 | } 83 | 84 | void * 85 | canvas_thread_function (void *_inf) 86 | { 87 | typedef canvas_window::thread_info thread_info; 88 | 89 | std::unique_ptr inf((thread_info *) _inf); 90 | platform_support_ext::prepare(); 91 | canvas_window *win = inf->win; 92 | 93 | win->caption("GSL shell plot"); 94 | if (win->init(480, 480, agg::window_resize)) 95 | { 96 | win->status = canvas_window::running; 97 | int ec = win->run(); 98 | win->status = (ec == 0 ? canvas_window::closed : canvas_window::error); 99 | } 100 | else 101 | { 102 | win->status = canvas_window::error; 103 | } 104 | 105 | win->unlock(); 106 | 107 | return NULL; 108 | } 109 | 110 | void 111 | canvas_window::shutdown_close(bool send_close_request) 112 | { 113 | lock(); 114 | if (status == canvas_window::running) 115 | { 116 | if (send_close_request) { 117 | close_request(); 118 | } 119 | unlock(); 120 | 121 | pthread_join(m_thread, NULL); 122 | } 123 | else 124 | { 125 | unlock(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/canvas.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_CANVAS_H 2 | #define AGGPLOT_CANVAS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "pixel_fmt.h" 9 | #include "sg_object.h" 10 | 11 | #include "agg_basics.h" 12 | #include "agg_rendering_buffer.h" 13 | #include "agg_rasterizer_scanline_aa.h" 14 | #include "agg_scanline_u.h" 15 | #include "agg_renderer_scanline.h" 16 | #include "agg_trans_viewport.h" 17 | #include "agg_conv_stroke.h" 18 | 19 | template 20 | class renderer_gray_aa 21 | { 22 | public: 23 | renderer_gray_aa(agg::rendering_buffer& ren_buf, agg::rgba8 bg_color): 24 | m_pixbuf(ren_buf), m_ren_base(m_pixbuf), m_ren_solid(m_ren_base), 25 | m_bgcol(bg_color) 26 | { } 27 | 28 | typedef Pixel pixfmt_type; 29 | 30 | agg::renderer_base& renderer_base() { 31 | return m_ren_base; 32 | } 33 | 34 | double width() const { 35 | return m_pixbuf.width(); 36 | }; 37 | double height() const { 38 | return m_pixbuf.height(); 39 | }; 40 | 41 | template 42 | static void add_path(Rasterizer& ras, VertexSource& vs) 43 | { 44 | ras.add_path(vs); 45 | } 46 | 47 | void color(agg::rgba8 c) { 48 | m_ren_solid.color(c); 49 | } 50 | 51 | void clear(agg::rgba8 c) { 52 | m_ren_base.clear(c); 53 | } 54 | 55 | void clear_box(const agg::rect_base& r) 56 | { 57 | for (int y = r.y1; y < r.y2; y++) 58 | m_ren_base.copy_hline (r.x1, y, r.x2, m_bgcol); 59 | } 60 | 61 | void clip_box(const agg::rect_base& clip) 62 | { 63 | m_ren_base.clip_box_naked(clip.x1, clip.y1, clip.x2, clip.y2); 64 | } 65 | 66 | void reset_clipping() { 67 | m_ren_base.reset_clipping(true); 68 | } 69 | 70 | template 71 | void render_scanlines(Rasterizer& ras, Scanline& sl) 72 | { 73 | agg::render_scanlines(ras, sl, m_ren_solid); 74 | } 75 | private: 76 | Pixel m_pixbuf; 77 | agg::renderer_base m_ren_base; 78 | agg::renderer_scanline_aa_solid > m_ren_solid; 79 | agg::rgba8 m_bgcol; 80 | }; 81 | 82 | template 83 | class renderer_subpixel_aa 84 | { 85 | enum { subpixel_scale = 3 }; 86 | 87 | struct subpixel_scale_trans 88 | { 89 | void transform(double* x, double* y) const { 90 | *x = subpixel_scale * (*x); 91 | } 92 | }; 93 | 94 | public: 95 | renderer_subpixel_aa(agg::rendering_buffer& ren_buf, agg::rgba8 bg_color): 96 | m_pixbuf(ren_buf), m_ren_base(m_pixbuf), m_ren_solid(m_ren_base), 97 | m_bgcol(bg_color) 98 | { } 99 | 100 | typedef Pixel pixfmt_type; 101 | 102 | agg::renderer_base& renderer_base() { 103 | return m_ren_base; 104 | } 105 | 106 | double width() const { 107 | return m_pixbuf.width() / subpixel_scale; 108 | }; 109 | double height() const { 110 | return m_pixbuf.height(); 111 | }; 112 | 113 | void clear(agg::rgba8 c) { 114 | m_ren_base.clear(c); 115 | } 116 | 117 | void clear_box(const agg::rect_base& r) 118 | { 119 | int x1 = subpixel_scale * r.x1, x2 = subpixel_scale * r.x2; 120 | for (int y = r.y1; y < r.y2; y++) 121 | m_ren_base.copy_hline (x1, y, x2, m_bgcol); 122 | } 123 | 124 | void clip_box(const agg::rect_base& clip) 125 | { 126 | int x1 = subpixel_scale * clip.x1, x2 = subpixel_scale * clip.x2; 127 | m_ren_base.clip_box_naked(x1, clip.y1, x2, clip.y2); 128 | } 129 | 130 | void reset_clipping() { 131 | m_ren_base.reset_clipping(true); 132 | } 133 | 134 | template 135 | static void add_path(Rasterizer& ras, VertexSource& vs) 136 | { 137 | subpixel_scale_trans tr; 138 | agg::conv_transform scaled_vs(vs, tr); 139 | ras.add_path(scaled_vs); 140 | } 141 | 142 | void color(agg::rgba8 c) { 143 | m_ren_solid.color(c); 144 | } 145 | 146 | template 147 | void render_scanlines(Rasterizer& ras, Scanline& sl) 148 | { 149 | agg::render_scanlines(ras, sl, m_ren_solid); 150 | } 151 | 152 | private: 153 | pixfmt_type m_pixbuf; 154 | agg::renderer_base m_ren_base; 155 | agg::renderer_scanline_aa_solid > m_ren_solid; 156 | agg::rgba8 m_bgcol; 157 | }; 158 | 159 | template 160 | class canvas_gen : public Renderer { 161 | 162 | typedef typename Renderer::pixfmt_type pixfmt_type; 163 | 164 | enum { line_width = 120 }; 165 | 166 | agg::rasterizer_scanline_aa<> ras; 167 | agg::scanline_u8 sl; 168 | 169 | public: 170 | canvas_gen(agg::rendering_buffer& ren_buf, double width, double height, 171 | agg::rgba8 bgcol): 172 | Renderer(ren_buf, bgcol), ras(), sl() 173 | { } 174 | 175 | void draw(sg_object& vs, agg::rgba8 c) 176 | { 177 | this->add_path(this->ras, vs); 178 | this->color(c); 179 | this->render_scanlines(this->ras, this->sl); 180 | } 181 | 182 | void draw_outline(sg_object& vs, agg::rgba8 c) 183 | { 184 | agg::conv_stroke line(vs); 185 | line.width(line_width / 100.0); 186 | line.line_cap(agg::round_cap); 187 | this->add_path(this->ras, line); 188 | this->color(c); 189 | this->render_scanlines(this->ras, this->sl); 190 | } 191 | }; 192 | 193 | struct virtual_canvas { 194 | virtual void draw(sg_object& vs, agg::rgba8 c) = 0; 195 | virtual void draw_outline(sg_object& vs, agg::rgba8 c) = 0; 196 | 197 | virtual void clip_box(const agg::rect_base& clip) = 0; 198 | virtual void reset_clipping() = 0; 199 | 200 | virtual ~virtual_canvas() { } 201 | }; 202 | 203 | #ifdef DISABLE_SUBPIXEL_AA 204 | typedef canvas_gen > canvas; 205 | #else 206 | typedef canvas_gen > canvas; 207 | #endif 208 | 209 | #endif 210 | -------------------------------------------------------------------------------- /src/canvas_svg.cpp: -------------------------------------------------------------------------------- 1 | #include "canvas_svg.h" 2 | 3 | const double canvas_svg::default_stroke_width = 1.0; 4 | 5 | template <> 6 | void canvas_svg::draw(sg_object& vs, agg::rgba8 c) 7 | { 8 | int id = m_current_id ++; 9 | str s = vs.write_svg(id, c, m_height); 10 | canvas_svg::writeln(m_output, s, " "); 11 | } 12 | 13 | template <> 14 | void canvas_svg::draw_outline(sg_object& vs, agg::rgba8 c) 15 | { 16 | int id = m_current_id ++; 17 | str path; 18 | svg_property_list* ls = vs.svg_path(path, m_height); 19 | str s = svg_stroke_path(path, canvas_svg::default_stroke_width, id, c, ls); 20 | svg_property_list::free(ls); 21 | canvas_svg::writeln(m_output, s, " "); 22 | } 23 | -------------------------------------------------------------------------------- /src/canvas_svg.h: -------------------------------------------------------------------------------- 1 | #ifndef CANVAS_SVG_H 2 | #define CANVAS_SVG_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "defs.h" 10 | #include "strpp.h" 11 | #include "sg_object.h" 12 | #include "draw_svg.h" 13 | 14 | static const char *svg_header = \ 15 | "\n" \ 16 | "\n" \ 17 | "\n"; 23 | 24 | static const char *svg_end = "\n"; 25 | 26 | class canvas_svg { 27 | public: 28 | canvas_svg(FILE *f, double height): 29 | m_output(f), m_height(height), m_current_id(0) { } 30 | 31 | void clip_box(const agg::rect_base& clip) { } 32 | 33 | void reset_clipping() { } 34 | 35 | template 36 | void draw(VertexSource& vs, agg::rgba8 c) 37 | { 38 | str path; 39 | svg_coords_from_vs(&vs, path, m_height); 40 | str s = svg_fill_path(path, m_current_id++, c); 41 | writeln(m_output, s, " "); 42 | } 43 | 44 | template 45 | void draw_outline(VertexSource& vs, agg::rgba8 c) 46 | { 47 | str path; 48 | svg_coords_from_vs(&vs, path, m_height); 49 | str s = svg_stroke_path(path, default_stroke_width, m_current_id++, c); 50 | writeln(m_output, s, " "); 51 | } 52 | 53 | void write_header(double w, double h) { 54 | fprintf(m_output, svg_header, w, h); 55 | } 56 | void write_end() { 57 | fputs(svg_end, m_output); 58 | } 59 | 60 | void write_group_header(const char* id) { 61 | fprintf(m_output, "\n", id); 62 | } 63 | 64 | void write_group_end(const char* id) { 65 | fprintf(m_output, "\n"); 66 | } 67 | 68 | static void writeln(FILE* f, str& s, const char* indent = 0) { 69 | if (str_is_null(&s)) 70 | return; 71 | if (indent) 72 | fputs(indent, f); 73 | fprintf(f, "%s\n", s.cstr()); 74 | } 75 | 76 | static const double default_stroke_width; 77 | 78 | private: 79 | FILE *m_output; 80 | double m_height; 81 | int m_current_id; 82 | }; 83 | 84 | template <> void canvas_svg::draw(sg_object& vs, agg::rgba8 c); 85 | template <> void canvas_svg::draw_outline(sg_object& vs, agg::rgba8 c); 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/categories.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_CATEGORIES_H 2 | #define AGGPLOT_CATEGORIES_H 3 | 4 | #include "strpp.h" 5 | #include "units.h" 6 | #include "utils.h" 7 | 8 | struct category_item { 9 | double value; 10 | str text; 11 | category_item(double v, const char*t) : value(v), text(t) {} 12 | }; 13 | 14 | class category_map : public ptr_list { 15 | 16 | typedef category_item item; 17 | 18 | public: 19 | class iterator : public label_iterator { 20 | public: 21 | iterator(const category_map& cat) : m_index(0), m_cat(cat) { } 22 | 23 | virtual bool next(double& val, const char*& text) 24 | { 25 | if (m_index >= m_cat.size()) 26 | return false; 27 | 28 | item* it = m_cat[m_index]; 29 | val = it->value; 30 | text = it->text.cstr(); 31 | m_index++; 32 | return true; 33 | } 34 | 35 | private: 36 | unsigned m_index; 37 | const category_map& m_cat; 38 | }; 39 | 40 | public: 41 | void add_item(double v, const char* name) { 42 | add(new item(v, name)); 43 | } 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/colors.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "lua-cpp-utils.h" 5 | #include "colors.h" 6 | 7 | static agg::rgba8 8 | rgba8_lookup (lua_State *L, const char *color_str) 9 | { 10 | const char *p = color_str; 11 | const int a = 255; 12 | 13 | if (strcmp (p, "white") == 0) 14 | return agg::rgba8(255, 255, 255, a); 15 | 16 | int val = 180; 17 | int r = 0, g = 0, b = 0; 18 | 19 | if (strncmp (p, "light", 5) == 0) 20 | { 21 | val = 255; 22 | p += 5; 23 | } 24 | else if (strncmp (p, "dark", 4) == 0) 25 | { 26 | val = 120; 27 | p += 4; 28 | } 29 | 30 | if (strcmp (p, "red") == 0) 31 | r = val; 32 | else if (strcmp (p, "green") == 0) 33 | g = val; 34 | else if (strcmp (p, "blue") == 0) 35 | b = val; 36 | else if (strcmp (p, "cyan") == 0) 37 | g = b = val; 38 | else if (strcmp (p, "magenta") == 0) 39 | r = b = val; 40 | else if (strcmp (p, "yellow") == 0) 41 | r = g = val; 42 | else if (strcmp (p, "gray") == 0) 43 | r = g = b = val; 44 | 45 | return agg::rgba8(r, g, b, a); 46 | } 47 | 48 | agg::rgba8 49 | color_arg_lookup (lua_State *L, int index) 50 | { 51 | if (lua_isnoneornil (L, index)) 52 | return colors::cdefault; 53 | 54 | if (lua_isnumber(L, index)) 55 | { 56 | unsigned int col = (unsigned int) lua_tointeger (L, index); 57 | agg::int8u r = (col & 0xff000000) >> 24; 58 | agg::int8u g = (col & 0x00ff0000) >> 16; 59 | agg::int8u b = (col & 0x0000ff00) >> 8; 60 | agg::int8u a = (col & 0x000000ff); 61 | 62 | return agg::rgba8(r, g, b, a); 63 | } 64 | 65 | const char *cstr = lua_tostring (L, index); 66 | 67 | if (!cstr) 68 | luaL_error (L, "invalid color specification"); 69 | 70 | return rgba8_lookup (L, cstr); 71 | } 72 | 73 | agg::rgba8 colors::white(0xff, 0xff, 0xff); 74 | agg::rgba8 colors::black(0, 0, 0); 75 | 76 | agg::rgba8 colors::cdefault(180, 0, 0, 255); 77 | -------------------------------------------------------------------------------- /src/colors.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_COLORS_H 2 | #define AGGPLOT_COLORS_H 3 | 4 | extern "C" { 5 | #include "lua.h" 6 | } 7 | 8 | #include "defs.h" 9 | #include "agg_color_rgba.h" 10 | 11 | extern agg::rgba8 color_arg_lookup (lua_State *L, int index); 12 | 13 | namespace colors { 14 | 15 | extern agg::rgba8 white; 16 | extern agg::rgba8 black; 17 | 18 | extern agg::rgba8 cdefault; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/defs.h: -------------------------------------------------------------------------------- 1 | #ifndef DEFS_H 2 | #define DEFS_H 3 | 4 | #undef __BEGIN_DECLS 5 | #undef __END_DECLS 6 | #ifdef __cplusplus 7 | # define __BEGIN_DECLS extern "C" { 8 | # define __END_DECLS } 9 | #else 10 | # define __BEGIN_DECLS /* empty */ 11 | # define __END_DECLS /* empty */ 12 | #endif 13 | 14 | #if defined(_WIN32) || defined(__CYGWIN__) 15 | # define _grtk_export __declspec(dllexport) 16 | # define _grtk_import __declspec(dllimport) 17 | #elif defined(__GNUC__) && (__GNUC__ >= 4) 18 | # define _grtk_export __attribute__((__visibility__("default"))) 19 | # define _grtk_import 20 | #else 21 | # define _grtk_export 22 | # define _grtk_import 23 | #endif 24 | 25 | #ifdef GRAPH_TK_COMPILATION 26 | # define _grtk_api _grtk_export 27 | #else 28 | # define _grtk_api _grtk_import 29 | #endif 30 | 31 | #define grtk_public _grtk_api extern 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/draw_svg.cpp: -------------------------------------------------------------------------------- 1 | #include "agg_color_rgba.h" 2 | 3 | #include "draw_svg.h" 4 | 5 | const char *svg_path_property_name[] = {"stroke-dasharray", "marker-start", "marker-mid", "marker-end"}; 6 | 7 | void format_rgb(char rgbstr[], int rgbstr_size, agg::rgba8 c) 8 | { 9 | int w_size = snprintf(rgbstr, rgbstr_size, "#%02X%02X%02X", (int)c.r, (int)c.g, (int)c.b); 10 | if (w_size > rgbstr_size - 1) { 11 | // Old snprintf may omit the terminating null character if 12 | // the buffer is too small. 13 | rgbstr[rgbstr_size - 1] = 0; 14 | } 15 | } 16 | 17 | static void append_properties(str& s, svg_property_list* properties) 18 | { 19 | for (svg_property_list* p = properties; p; p = p->next()) 20 | { 21 | svg_property_item& item = p->content(); 22 | const char* name = svg_path_property_name[item.key]; 23 | s.printf_add(";%s:%s", name, item.value); 24 | } 25 | } 26 | 27 | static void property_append_alpha(str& s, const char* prop, agg::rgba8 c) 28 | { 29 | if (c.a < 255) { 30 | double alpha = (double)c.a / 255; 31 | s.printf_add(";%s:%g", prop, alpha); 32 | } 33 | } 34 | 35 | static str gen_path_element(str& content, str& style, int id) 36 | { 37 | str s = str::print("= 0) 39 | s.printf_add("id=\"path%i\" ", id); 40 | s.printf_add("style=\"%s\" />", style.cstr()); 41 | return s; 42 | } 43 | 44 | str svg_stroke_path(str& path_coords, double width, int id, agg::rgba8 c, 45 | svg_property_list* properties) 46 | { 47 | char rgbstr[8]; 48 | format_rgb(rgbstr, 8, c); 49 | 50 | str s = str::print("fill:none;stroke:%s;" 51 | "stroke-width:%g;stroke-linecap:butt;" 52 | "stroke-linejoin:miter", 53 | rgbstr, width); 54 | 55 | property_append_alpha(s, "stroke-opacity", c); 56 | append_properties(s, properties); 57 | 58 | return gen_path_element(path_coords, s, id); 59 | } 60 | 61 | str svg_marker_path(str& path_coords, double sw, int id, svg_property_list* properties) 62 | { 63 | str s = str::print("fill:none;stroke:none;stroke-width:%g", sw); 64 | append_properties(s, properties); 65 | return gen_path_element(path_coords, s, id); 66 | } 67 | 68 | str svg_fill_path(str& path_coords, int id, agg::rgba8 c, 69 | svg_property_list* properties) 70 | { 71 | char rgbstr[8]; 72 | format_rgb(rgbstr, 8, c); 73 | str s = str::print("fill:%s;stroke:none", rgbstr); 74 | property_append_alpha(s, "fill-opacity", c); 75 | append_properties(s, properties); 76 | return gen_path_element(path_coords, s, id); 77 | } 78 | -------------------------------------------------------------------------------- /src/draw_svg.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAW_SVG_H 2 | #define DRAW_SVG_H 3 | 4 | #include "agg_basics.h" 5 | #include "agg_color_rgba.h" 6 | #include "list.h" 7 | #include "strpp.h" 8 | 9 | enum svg_path_property_e { 10 | stroke_dasharray = 0, 11 | marker_start, 12 | marker_mid, 13 | marker_end, 14 | }; 15 | 16 | extern const char *svg_path_property_name[]; 17 | 18 | struct svg_property_item { 19 | enum svg_path_property_e key; 20 | const char* value; 21 | 22 | svg_property_item(enum svg_path_property_e k, const char *v) : key(k), value(v) { } 23 | }; 24 | 25 | static inline double svg_y_coord(double y, double h) { 26 | return h - y; 27 | } 28 | 29 | template 30 | static inline unsigned 31 | vertex_flip(VertexSource* vs, double* x, double* y, double h) 32 | { 33 | unsigned cmd = vs->vertex(x, y); 34 | *y = svg_y_coord(*y, h); 35 | return cmd; 36 | } 37 | 38 | typedef list svg_property_list; 39 | 40 | template 41 | void svg_coords_from_vs(VertexSource* vs, str& s, double h) 42 | { 43 | unsigned cmd; 44 | double x, y; 45 | const char * const space = " "; 46 | const char *sep = ""; 47 | 48 | vs->rewind(0); 49 | 50 | while ((cmd = vertex_flip(vs, &x, &y, h))) 51 | { 52 | if (agg::is_move_to(cmd)) { 53 | s.printf_add("%sM %g,%g", sep, x, y); 54 | } else if (agg::is_line_to(cmd)) { 55 | s.printf_add("%s%g,%g", sep, x, y); 56 | } else if (agg::is_close(cmd)) { 57 | s.printf_add("%sz", sep); 58 | } else if (agg::is_curve3(cmd)) { 59 | vertex_flip(vs, &x, &y, h); 60 | s.printf_add("%s%g,%g", sep, x, y); 61 | } else if (agg::is_curve4(cmd)) { 62 | vs->vertex(&x, &y); 63 | vertex_flip(vs, &x, &y, h); 64 | s.printf_add("%s%g,%g", sep, x, y); 65 | } 66 | sep = space; 67 | } 68 | } 69 | 70 | template 71 | void svg_curve_coords_from_vs(VertexSource* vs, str& s, double h) 72 | { 73 | unsigned cmd; 74 | double x, y; 75 | const char * const space = " "; 76 | const char *sep = ""; 77 | bool omit_line_to = false; 78 | 79 | vs->rewind(0); 80 | 81 | while ((cmd = vertex_flip(vs, &x, &y, h))) 82 | { 83 | if (agg::is_move_to(cmd)) { 84 | s.printf_add("%sM %g,%g", sep, x, y); 85 | omit_line_to = true; 86 | } else if (agg::is_line_to(cmd)) { 87 | s.printf_add("%s%s%g,%g", sep, omit_line_to ? "" : "L ", x, y); 88 | } else if (agg::is_curve4(cmd)) { 89 | double x1 = x, y1 = y; 90 | double x2, y2; 91 | vertex_flip(vs, &x2, &y2, h); 92 | vertex_flip(vs, &x, &y, h); 93 | s.printf_add("%sC %g,%g %g,%g %g,%g", sep, x1, y1, x2, y2, x, y); 94 | omit_line_to = false; 95 | } else if (agg::is_curve3(cmd)) { 96 | double x1 = x, y1 = y; 97 | vertex_flip(vs, &x, &y, h); 98 | s.printf_add("%sQ %g,%g %g,%g", sep, x1, y1, x, y); 99 | omit_line_to = false; 100 | } else if (agg::is_close(cmd)) { 101 | s.printf_add("%sz", sep); 102 | } 103 | sep = space; 104 | } 105 | } 106 | 107 | extern str svg_stroke_path(str& path_coords, double width, int id, agg::rgba8 c, svg_property_list* properties = 0); 108 | extern str svg_fill_path(str& path_coords, int id, agg::rgba8 c, svg_property_list* properties = 0); 109 | extern str svg_marker_path(str& path_coords, double sw, int id, svg_property_list* properties); 110 | extern void format_rgb(char rgbstr[], int rgbstr_size, agg::rgba8 c); 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/factor_labels.h: -------------------------------------------------------------------------------- 1 | #include "agg_array.h" 2 | #include "utils.h" 3 | #include "strpp.h" 4 | 5 | class factor_labels 6 | { 7 | public: 8 | factor_labels(double delta): m_mark_delta(delta) {} 9 | 10 | double mark(int k) const { return m_mark_index[k] * m_mark_delta; } 11 | const char *label_text(int k) const { return m_label_text[k]->cstr(); } 12 | int labels_number() const { return m_label_text.size(); } 13 | 14 | void add_mark(int index, const char *text) 15 | { 16 | m_mark_index.add(index); 17 | if (text) 18 | { 19 | str* text_str = new str(text); 20 | m_label_text.add(text_str); 21 | } 22 | } 23 | 24 | private: 25 | double m_mark_delta; 26 | agg::pod_bvector m_mark_index; 27 | ptr_list m_label_text; 28 | }; 29 | -------------------------------------------------------------------------------- /src/fonts.cpp: -------------------------------------------------------------------------------- 1 | 2 | extern "C" { 3 | #include 4 | #include 5 | } 6 | 7 | #include "fonts.h" 8 | 9 | agg::font_engine_freetype_int32 global_font_eng; 10 | agg::font_cache_manager global_font_man(global_font_eng); 11 | 12 | int initialize_fonts(lua_State* L) 13 | { 14 | const char* font_name = get_font_name(); 15 | if (!font_name) 16 | luaL_error(L, "cannot find a suitable truetype font"); 17 | agg::glyph_rendering gren = agg::glyph_ren_outline; 18 | if (!global_font_eng.load_font(font_name, 0, gren)) 19 | luaL_error(L, "cannot load truetype font: %s", font_name); 20 | global_font_eng.hinting(true); 21 | return 0; 22 | } 23 | 24 | agg::font_engine_freetype_int32& font_engine() 25 | { 26 | return global_font_eng; 27 | } 28 | 29 | agg::font_cache_manager& font_manager() 30 | { 31 | return global_font_man; 32 | } 33 | -------------------------------------------------------------------------------- /src/fonts.h: -------------------------------------------------------------------------------- 1 | #ifndef FONTS_H 2 | #define FONTS_H 3 | 4 | #include "lua.h" 5 | #include "agg_font_freetype.h" 6 | 7 | extern "C" int initialize_fonts(lua_State* L); 8 | 9 | extern const char *get_font_name(); 10 | extern const char *get_console_font_name(); 11 | 12 | extern agg::font_engine_freetype_int32& font_engine(); 13 | extern agg::font_cache_manager& font_manager(); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/fonts_search_win32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "fonts.h" 6 | 7 | const char *ttf_names[] = {"calibri.ttf", "arial.ttf", 0}; 8 | const char *console_font_names[] = {"consolas", "lucida console", "fixedsys", 0}; 9 | const char *console_font_filenames[] = {"consola.ttf", "lucon.ttf", "cvgafix.fon", 0}; 10 | 11 | const char *get_font_name() 12 | { 13 | static TCHAR pf[MAX_PATH + 32]; 14 | SHGetFolderPath(0, CSIDL_FONTS, NULL, 0, pf); 15 | unsigned len = strlen(pf); 16 | pf[len++] = '\\'; 17 | for (int k = 0; ttf_names[k]; k++) 18 | { 19 | const char* font_name = ttf_names[k]; 20 | memcpy(pf + len, font_name, (strlen(font_name) + 1) * sizeof(char)); 21 | struct _stat inf[1]; 22 | int status = _stat(pf, inf); 23 | if (status == 0) 24 | return pf; 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | const char* get_console_font_name() 31 | { 32 | static TCHAR pf[MAX_PATH + 32]; 33 | SHGetFolderPath(0, CSIDL_FONTS, NULL, 0, pf); 34 | unsigned len = strlen(pf); 35 | pf[len++] = '\\'; 36 | for (int k = 0; console_font_filenames[k]; k++) 37 | { 38 | const char* filename = console_font_filenames[k]; 39 | memcpy(pf + len, filename, (strlen(filename) + 1) * sizeof(char)); 40 | struct _stat inf[1]; 41 | int status = _stat(pf, inf); 42 | if (status == 0) 43 | return console_font_names[k]; 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/fonts_search_x11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fonts.h" 4 | 5 | #ifdef DARWIN_MACOSX 6 | const char *ttf_names[] = {"Arial.ttf", "Trebuchet MS.ttf", "Courier New.ttf", 0}; 7 | const char *ttf_system_dir[] = {"/Library/Fonts", 0}; 8 | #define CONSOLE_FONT_NAME "Monaco" 9 | #else 10 | const char *ttf_names[] = { 11 | "ubuntu-font-family/Ubuntu-R.ttf", 12 | "freefont/FreeSans.ttf", "freefont-ttf/FreeSans.ttf", "FreeSans.ttf", 13 | "ttf-dejavu/DejaVuSans.ttf", "dejavu/DejaVuSans.ttf", "DejaVuSans.ttf", 14 | "liberation/LiberationSans-Regular.ttf", 0}; 15 | const char *ttf_system_dir[] = {"/usr/share/fonts/truetype", "/usr/share/fonts", "/usr/share/fonts/TTF", 0}; 16 | #define CONSOLE_FONT_NAME "monospace" 17 | #endif 18 | 19 | const char *get_font_name() 20 | { 21 | for (int i = 0; ttf_system_dir[i]; i++) 22 | { 23 | const char* ttf_dir = ttf_system_dir[i]; 24 | unsigned len = strlen(ttf_dir); 25 | static char pf[256]; 26 | memcpy(pf, ttf_dir, len); 27 | char* base_ptr = pf + len; 28 | if (pf[len - 1] != '/') { 29 | *base_ptr = '/'; 30 | base_ptr ++; 31 | } 32 | for (int k = 0; ttf_names[k]; k++) 33 | { 34 | const char* font_name = ttf_names[k]; 35 | memcpy(base_ptr, font_name, (strlen(font_name) + 1) * sizeof(char)); 36 | struct stat inf[1]; 37 | int status = stat(pf, inf); 38 | if (status == 0) 39 | return pf; 40 | } 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | const char* get_console_font_name() 47 | { 48 | return CONSOLE_FONT_NAME; 49 | } 50 | -------------------------------------------------------------------------------- /src/gamma.cpp: -------------------------------------------------------------------------------- 1 | #include "agg-pixfmt-config.h" 2 | 3 | #ifndef DISABLE_GAMMA_CORR 4 | gslshell::gamma_type gslshell::gamma(1.5); 5 | #endif 6 | // Original values for the subpixel color filter. These are quite conservative 7 | // to avoid color fringes. 8 | // agg::lcd_distribution_lut gslshell::subpixel_lut(3./9., 2./9., 1./9.); 9 | 10 | // Slightly more agressive values with more weight to primary channel. 11 | // Some people may notice colorer fringes but fonts looks sharper. 12 | agg::lcd_distribution_lut gslshell::subpixel_lut(0.448, 0.184, 0.092); 13 | -------------------------------------------------------------------------------- /src/gs-types.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include "lua-defs.h" 7 | #include "gs-types.h" 8 | #include 9 | 10 | #define GS_WINDOW_NAME_DEF "GSL.window" 11 | #define GS_DRAW_SCALABLE_NAME_DEF NULL 12 | #define GS_DRAW_PATH_NAME_DEF "GSL.path" 13 | #define GS_DRAW_ELLIPSE_NAME_DEF "GSL.ellipse" 14 | #define GS_DRAW_DRAWABLE_NAME_DEF NULL 15 | #define GS_DRAW_TEXT_NAME_DEF "GSL.text" 16 | #define GS_DRAW_TEXTSHAPE_NAME_DEF "GSL.textshape" 17 | #define GS_DRAW_MARKER_NAME_DEF "GSL.marker" 18 | #define GS_PLOT_NAME_DEF "GSL.plot" 19 | 20 | #define MYCAT2x(a,b) a ## _ ## b 21 | #define MYCAT2(a,b) MYCAT2x(a,b) 22 | #define MYCAT3x(a,b,c) a ## _ ## b ## _ ## c 23 | #define MYCAT3(a,b,c) MYCAT3x(a,b,c) 24 | 25 | #define MY_EXPAND(NM,DESCR) {MYCAT2(GS,NM), MYCAT3(GS,NM,NAME_DEF), DESCR, GS_NO_TYPE} 26 | #define MY_EXPAND_DER(NM,DESCR,BASE) {MYCAT2(GS,NM), MYCAT3(GS,NM,NAME_DEF), DESCR, MYCAT2(GS,BASE)} 27 | 28 | const struct gs_type gs_type_table[] = { 29 | MY_EXPAND(WINDOW, "graphical window"), 30 | MY_EXPAND(DRAW_SCALABLE, "graphical object"), 31 | MY_EXPAND_DER(DRAW_PATH, "geometric line", DRAW_SCALABLE), 32 | MY_EXPAND_DER(DRAW_ELLIPSE, "geometric ellipse", DRAW_SCALABLE), 33 | MY_EXPAND(DRAW_DRAWABLE, "window graphical object"), 34 | MY_EXPAND_DER(DRAW_TEXT, "graphical text", DRAW_DRAWABLE), 35 | MY_EXPAND_DER(DRAW_TEXTSHAPE, "geometric text shape", DRAW_DRAWABLE), 36 | MY_EXPAND_DER(DRAW_MARKER, "marker point", DRAW_DRAWABLE), 37 | MY_EXPAND(PLOT, "plot"), 38 | {GS_INVALID_TYPE, NULL, NULL, GS_NO_TYPE} 39 | }; 40 | 41 | #undef MYCAT2 42 | #undef MYCAT2x 43 | #undef MYCAT3 44 | #undef MYCAT3x 45 | #undef MY_EXPAND 46 | #undef MY_EXPAND_DER 47 | 48 | const char * 49 | type_qualified_name (int typeid) 50 | { 51 | const struct gs_type *tp = &gs_type_table[typeid]; 52 | return tp->fullname; 53 | } 54 | 55 | const char * 56 | metatable_name (int typeid) 57 | { 58 | const struct gs_type *tp = &gs_type_table[typeid]; 59 | return tp->mt_name; 60 | } 61 | 62 | static const char * 63 | userdata_full_name (lua_State *L, int index) 64 | { 65 | if (lua_getmetatable(L, index)) 66 | { 67 | int j; 68 | for (j = 0; j < GS_INVALID_TYPE; j++) 69 | { 70 | const char *mt = metatable_name (j); 71 | 72 | if (mt == NULL) 73 | continue; 74 | 75 | lua_getfield(L, LUA_REGISTRYINDEX, mt); 76 | if (lua_rawequal(L, -1, -2)) 77 | { 78 | lua_pop (L, 2); 79 | return type_qualified_name (j); 80 | } 81 | lua_pop (L, 1); 82 | } 83 | } 84 | 85 | return lua_typename (L, LUA_TUSERDATA);; 86 | } 87 | 88 | const char * 89 | full_type_name (lua_State *L, int narg) 90 | { 91 | int t = lua_type (L, narg); 92 | const char *nm; 93 | 94 | #ifdef LUA_TINT 95 | assert( t != LUA_TINT ); 96 | #endif 97 | 98 | switch (t) 99 | { 100 | case LUA_TUSERDATA: 101 | nm = userdata_full_name (L, narg); 102 | break; 103 | default: 104 | nm = lua_typename (L, t); 105 | } 106 | 107 | return nm; 108 | } 109 | 110 | int 111 | gs_type_error (lua_State *L, int narg, const char *req_type) 112 | { 113 | const char *actual_type = full_type_name (L, narg); 114 | const char *msg = lua_pushfstring(L, "%s expected, got %s", 115 | req_type, actual_type); 116 | return luaL_argerror(L, narg, msg); 117 | } 118 | 119 | void * 120 | gs_new_object (size_t nbytes, lua_State *L, enum gs_type_e tp) 121 | { 122 | void* p = lua_newuserdata(L, nbytes); 123 | gs_set_metatable (L, tp); 124 | return p; 125 | } 126 | 127 | static int 128 | rec_check_type (lua_State *L, enum gs_type_e tp) 129 | { 130 | const char *mt = metatable_name (tp); 131 | const struct gs_type *t; 132 | 133 | if (mt) 134 | { 135 | lua_getfield(L, LUA_REGISTRYINDEX, mt); 136 | if (lua_rawequal(L, -1, -2)) 137 | { 138 | lua_pop (L, 1); 139 | return 1; 140 | } 141 | lua_pop (L, 1); 142 | } 143 | 144 | /* we start to search from tp because we assume that derived type are 145 | follows base type in the table. */ 146 | for (t = &gs_type_table[tp]; t->tp != GS_INVALID_TYPE; t++) 147 | { 148 | if (t->base_type == tp) 149 | { 150 | if (rec_check_type (L, t->tp)) 151 | return 1; 152 | } 153 | } 154 | 155 | return 0; 156 | } 157 | 158 | void * 159 | gs_is_userdata (lua_State *L, int index, int typeid) 160 | { 161 | INDEX_SET_ABS(L, index); 162 | 163 | void *p = lua_touserdata (L, index); 164 | 165 | if (p == NULL) 166 | return NULL; 167 | 168 | if (lua_getmetatable(L, index)) 169 | { 170 | if (rec_check_type (L, typeid)) 171 | { 172 | lua_pop (L, 1); 173 | return p; 174 | } 175 | } 176 | 177 | lua_pop (L, 1); 178 | 179 | return NULL; 180 | } 181 | 182 | void * 183 | gs_check_userdata (lua_State *L, int index, int typeid) 184 | { 185 | void *p = gs_is_userdata (L, index, typeid); 186 | 187 | if (p == NULL) 188 | gs_type_error (L, index, type_qualified_name (typeid)); 189 | 190 | return p; 191 | } 192 | 193 | void 194 | gs_set_metatable (lua_State *L, int typeid) 195 | { 196 | luaL_getmetatable (L, GS_METATABLE(typeid)); 197 | lua_setmetatable (L, -2); 198 | } 199 | 200 | int 201 | gs_type_string (lua_State *L) 202 | { 203 | const char *name = full_type_name (L, 1); 204 | lua_pushstring (L, name); 205 | return 1; 206 | } 207 | 208 | double 209 | gs_check_number (lua_State *L, int index, int check_normal) 210 | { 211 | double v; 212 | if (!lua_isnumber (L, index)) 213 | return gs_type_error (L, index, "real number"); 214 | v = lua_tonumber (L, index); 215 | if (check_normal) 216 | { 217 | if (isinf(v) || isnan(v)) 218 | return luaL_error (L, "invalid 'nan' or 'inf' number", index); 219 | } 220 | return v; 221 | } 222 | -------------------------------------------------------------------------------- /src/gs-types.h: -------------------------------------------------------------------------------- 1 | #ifndef GS_TYPES_H 2 | #define GS_TYPES_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | #include 9 | #include 10 | 11 | enum gs_type_e { 12 | GS_NO_TYPE = -1, 13 | GS_WINDOW = 0, 14 | GS_DRAW_SCALABLE, /* derived types are declared only after their base class */ 15 | GS_DRAW_PATH, 16 | GS_DRAW_ELLIPSE, 17 | GS_DRAW_DRAWABLE, 18 | GS_DRAW_TEXT, 19 | GS_DRAW_TEXTSHAPE, 20 | GS_DRAW_MARKER, 21 | GS_PLOT, 22 | GS_INVALID_TYPE, 23 | }; 24 | 25 | enum fp_check_e { 26 | FP_NO_CHECK = 0, 27 | FP_CHECK_NORMAL = 1 28 | }; 29 | 30 | struct gs_type { 31 | enum gs_type_e tp; 32 | const char * mt_name; 33 | const char * fullname; 34 | enum gs_type_e base_type; 35 | }; 36 | 37 | extern const char * full_type_name (lua_State *L, int narg); 38 | extern const char * type_qualified_name (int type_id); 39 | extern int gs_type_error (lua_State *L, int narg, const char *req_type); 40 | extern void * gs_new_object (size_t nbytes, lua_State *L, enum gs_type_e tp); 41 | extern void * gs_is_userdata (lua_State *L, int index, int type_id); 42 | extern void * gs_check_userdata (lua_State *L, int index, int type_id); 43 | extern void gs_set_metatable (lua_State *L, int type_id); 44 | extern double gs_check_number (lua_State *L, int index, int check_normal); 45 | 46 | extern const struct gs_type gs_type_table[]; 47 | 48 | #define GS_METATABLE(id) gs_type_table[(id)].mt_name 49 | 50 | extern int gs_type_string (lua_State *L); 51 | 52 | __END_DECLS 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/image_write.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_WRITE_H 2 | #define IMAGE_WRITE_H 3 | 4 | #include "platform/agg_platform_support.h" 5 | 6 | extern bool save_image_file(agg::rendering_buffer& src, const char *fn, agg::pix_format_e src_pixfmt_tag); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/image_write_win32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "image_write.h" 4 | 5 | #include "platform/agg_platform_support.h" 6 | #include "rendering_buffer_utils.h" 7 | #include "platform/win32/agg_win32_bmp.h" 8 | #include "util/agg_color_conv_rgb8.h" 9 | 10 | static inline void pixel_map_attach (agg::pixel_map& pm, agg::rendering_buffer *rbuf, 11 | bool flip_y) 12 | { 13 | int stride = pm.stride(); 14 | rbuf->attach(pm.buf(), pm.width(), pm.height(), flip_y ? stride : -stride); 15 | } 16 | 17 | bool 18 | save_image_file(agg::rendering_buffer& src, const char *fn, agg::pix_format_e src_pixfmt_tag) 19 | { 20 | unsigned slen = strlen(fn); 21 | agg::pod_array fnext(slen+5); 22 | sprintf (fnext.data(), "%s.bmp", fn); 23 | 24 | agg::pixel_map pmap; 25 | pmap.create(src.width(), src.height(), agg::org_e(24)); 26 | 27 | agg::rendering_buffer rbuf_tmp; 28 | pixel_map_attach (pmap, &rbuf_tmp, true); 29 | 30 | if (src_pixfmt_tag == agg::pix_format_bgr24) 31 | { 32 | rbuf_tmp.copy_from(src); 33 | } 34 | else if (src_pixfmt_tag == agg::pix_format_rgb24) 35 | { 36 | my_color_conv(&rbuf_tmp, &src, agg::color_conv_rgb24_to_bgr24()); 37 | } 38 | 39 | return pmap.save_as_bmp(fnext.data()); 40 | } 41 | -------------------------------------------------------------------------------- /src/image_write_x11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "image_write.h" 5 | 6 | #include "platform/agg_platform_support.h" 7 | #include "rendering_buffer_utils.h" 8 | #include "util/agg_color_conv_rgb8.h" 9 | 10 | bool 11 | save_image_file(agg::rendering_buffer& rbuf, const char *fn, agg::pix_format_e src_pixfmt_tag) 12 | { 13 | unsigned slen = strlen(fn); 14 | agg::pod_array fnext(slen+5); 15 | snprintf(fnext.data(), slen+5, "%s.ppm", fn); 16 | 17 | FILE* fd = fopen(fnext.data(), "wb"); 18 | if(fd == 0) return false; 19 | 20 | unsigned w = rbuf.width(); 21 | unsigned h = rbuf.height(); 22 | 23 | fprintf(fd, "P6\n%d %d\n255\n", w, h); 24 | 25 | unsigned y; 26 | agg::pod_array row_buf(w * 3); 27 | unsigned char *tmp_buf = row_buf.data(); 28 | 29 | for(y = 0; y < rbuf.height(); y++) 30 | { 31 | const unsigned char* src = rbuf.row_ptr(h - 1 - y); 32 | switch(src_pixfmt_tag) 33 | { 34 | default: 35 | break; 36 | case agg::pix_format_rgb555: 37 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_rgb555_to_rgb24()); 38 | break; 39 | 40 | case agg::pix_format_rgb565: 41 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_rgb565_to_rgb24()); 42 | break; 43 | 44 | case agg::pix_format_bgr24: 45 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_bgr24_to_rgb24()); 46 | break; 47 | 48 | case agg::pix_format_rgb24: 49 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_rgb24_to_rgb24()); 50 | break; 51 | 52 | case agg::pix_format_rgba32: 53 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_rgba32_to_rgb24()); 54 | break; 55 | 56 | case agg::pix_format_argb32: 57 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_argb32_to_rgb24()); 58 | break; 59 | 60 | case agg::pix_format_bgra32: 61 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_bgra32_to_rgb24()); 62 | break; 63 | 64 | case agg::pix_format_abgr32: 65 | agg::color_conv_row(tmp_buf, src, w, agg::color_conv_abgr32_to_rgb24()); 66 | break; 67 | } 68 | fwrite(tmp_buf, 1, w * 3, fd); 69 | } 70 | 71 | fclose(fd); 72 | return true; 73 | } 74 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | #ifndef CPP_LIST_H 2 | #define CPP_LIST_H 3 | 4 | template 5 | class list { 6 | T m_content; 7 | list* m_next; 8 | 9 | public: 10 | list(const T& c, list* next = 0) : m_content(c), m_next(next) { }; 11 | list( T& c, list* next = 0) : m_content(c), m_next(next) { }; 12 | 13 | T& content() { return m_content; }; 14 | const T& content() const { return m_content; }; 15 | 16 | static list* push_back(list* head, list* n) 17 | { 18 | list* k = head; 19 | 20 | if (! k) 21 | return n; 22 | 23 | while (k->m_next) 24 | k = k->m_next; 25 | k->m_next = n; 26 | 27 | return head; 28 | } 29 | 30 | static int length(list* ls) 31 | { 32 | int n = 0; 33 | for ( ; ls; ls = ls->next()) 34 | n++; 35 | return n; 36 | } 37 | 38 | static void free(list* p) 39 | { 40 | list* n; 41 | for (/* */; p; p = n) 42 | { 43 | n = p->m_next; 44 | delete p; 45 | } 46 | } 47 | 48 | static list* pop(list* p) 49 | { 50 | list* tail = p->next(); 51 | delete p; 52 | return tail; 53 | } 54 | 55 | list* next() { return m_next; }; 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/lua-compat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "lua-compat.h" 5 | 6 | // Define a function equivalent to luaL_register with a NULL 7 | // second argument, to write in the table on top of the stack. 8 | void 9 | grtk_lua_register(lua_State *L, const luaL_Reg *regs) 10 | { 11 | #ifdef GRAPH_TK_USE_LUA54 12 | luaL_setfuncs (L, regs, 0); 13 | #else 14 | luaL_register (L, NULL, regs); 15 | #endif 16 | } 17 | 18 | unsigned int grtk_lua_rawlen(lua_State *L, int index) 19 | { 20 | /* In reality they are no equivalent because objlen may 21 | * invoke a meta-methods but we ignore this difference. */ 22 | #ifdef GRAPH_TK_USE_LUA54 23 | return lua_rawlen (L, index); 24 | #else 25 | return lua_objlen (L, index); 26 | #endif 27 | } 28 | 29 | int grtk_lua_setfenv(lua_State *L, int index) 30 | { 31 | #ifdef GRAPH_TK_USE_LUA54 32 | return lua_setiuservalue (L, index, 1); 33 | #else 34 | return lua_setfenv (L, index); 35 | #endif 36 | } 37 | 38 | int grtk_lua_getfenv(lua_State *L, int index) 39 | { 40 | #ifdef GRAPH_TK_USE_LUA54 41 | return lua_getiuservalue (L, index, 1); 42 | #else 43 | lua_getfenv (L, index); 44 | return 0; 45 | #endif 46 | } 47 | -------------------------------------------------------------------------------- /src/lua-compat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "defs.h" 4 | 5 | __BEGIN_DECLS 6 | 7 | #include 8 | 9 | extern void grtk_lua_register(lua_State *L, const luaL_Reg *regs); 10 | extern unsigned int grtk_lua_rawlen(lua_State *L, int index); 11 | extern int grtk_lua_setfenv(lua_State *L, int index); 12 | extern int grtk_lua_getfenv(lua_State *L, int index); 13 | 14 | #ifdef GRAPH_TK_USE_LUA54 15 | #define luaL_optint luaL_optinteger 16 | #endif 17 | 18 | __END_DECLS 19 | 20 | -------------------------------------------------------------------------------- /src/lua-cpp-utils.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_CPP_UTILS_H 2 | #define LUA_CPP_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "defs.h" 8 | #include "lua-defs.h" 9 | __BEGIN_DECLS 10 | #include "lua.h" 11 | __END_DECLS 12 | 13 | #include "gs-types.h" 14 | 15 | namespace gslshell { 16 | 17 | class ret_status { 18 | bool m_success; 19 | const char *m_error_msg; 20 | const char *m_context; 21 | 22 | public: 23 | ret_status() : m_success(true) {}; 24 | 25 | void success() { 26 | m_success = true; 27 | } 28 | void error(const char *msg, const char *ctx) 29 | { 30 | m_success = false; 31 | m_error_msg = msg; 32 | m_context = ctx; 33 | }; 34 | 35 | const char *error_msg() const { 36 | return (m_success ? 0 : m_error_msg); 37 | }; 38 | const char *context() const { 39 | return (m_success ? 0 : m_context); 40 | }; 41 | }; 42 | } 43 | 44 | inline void* operator new(size_t nbytes, lua_State *L, enum gs_type_e tp) 45 | { 46 | void* p = lua_newuserdata(L, nbytes); 47 | gs_set_metatable (L, tp); 48 | return p; 49 | } 50 | 51 | #ifdef GRAPH_TK_USE_LUA54 52 | inline void* operator new(size_t nbytes, lua_State *L, enum gs_type_e tp, int nuvalue) 53 | { 54 | void* p = lua_newuserdatauv(L, nbytes, nuvalue); 55 | gs_set_metatable (L, tp); 56 | return p; 57 | } 58 | #endif 59 | 60 | template 61 | T* push_new_object(lua_State *L, enum gs_type_e tp, Args&&... args) { 62 | return new(L, tp) T(std::forward(args)...); 63 | } 64 | 65 | #ifdef GRAPH_TK_USE_LUA54 66 | template 67 | T* push_new_object_uv(lua_State *L, enum gs_type_e tp, int nuvalue, Args&&... args) { 68 | return new(L, tp, nuvalue) T(std::forward(args)...); 69 | } 70 | #else 71 | template 72 | T* push_new_object_uv(lua_State *L, enum gs_type_e tp, int nuvalue, Args&&... args) { 73 | // We ignore the nuvalue argument when using Lua 5.1 because later lua_setfenv 74 | // will be used and no upvalues have to be requested when the object is created. 75 | return new(L, tp) T(std::forward(args)...); 76 | } 77 | #endif 78 | 79 | template 80 | int object_free (lua_State *L, int index, enum gs_type_e tp) 81 | { 82 | T *obj = (T *) gs_check_userdata (L, index, tp); 83 | obj->~T(); 84 | return 0; 85 | } 86 | 87 | template 88 | T* object_check (lua_State *L, int index, enum gs_type_e tp) 89 | { 90 | return (T *) gs_check_userdata (L, index, tp); 91 | } 92 | 93 | template 94 | T* object_cast (lua_State *L, int index, enum gs_type_e tp) 95 | { 96 | return (T *) gs_is_userdata (L, index, tp); 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/lua-defs.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_DEFS_H 2 | #define LUA_DEFS_H 3 | 4 | #define INDEX_SET_ABS(L, idx) \ 5 | if ((idx) < 0 && (idx) > LUA_REGISTRYINDEX) \ 6 | (idx) = lua_gettop(L) + ((idx)+1) 7 | 8 | #define INDEX_SET_ABS_2(L, idx1, idx2) { \ 9 | int _narg = lua_gettop (L); \ 10 | if ((idx1) < 0 && (idx1) > LUA_REGISTRYINDEX) \ 11 | (idx1) = _narg + ((idx1)+1); \ 12 | if ((idx2) < 0 && (idx2) > LUA_REGISTRYINDEX) \ 13 | (idx2) = _narg + ((idx2)+1); \ 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/lua-draw.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_DRAW_H 2 | #define LUA_DRAW_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | #include "lua.h" 8 | __END_DECLS 9 | 10 | #ifdef __cplusplus 11 | 12 | #include "agg_color_rgba.h" 13 | 14 | #include "sg_object.h" 15 | #include "path.h" 16 | 17 | extern int agg_text_new (lua_State *L); 18 | extern int agg_path_new (lua_State *L); 19 | 20 | extern draw::path* check_agg_path (lua_State *L, int index); 21 | 22 | #endif 23 | 24 | __BEGIN_DECLS 25 | 26 | extern void draw_register (lua_State *L); 27 | 28 | __END_DECLS 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/lua-graph-priv.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_GRAPH_PRIV_H 2 | #define LUA_GRAPH_PRIV_H 3 | 4 | #include 5 | 6 | #include "defs.h" 7 | 8 | __BEGIN_DECLS 9 | 10 | extern pthread_mutex_t agg_mutex[1]; 11 | 12 | #define AGG_LOCK() pthread_mutex_lock (agg_mutex); 13 | #define AGG_UNLOCK() pthread_mutex_unlock (agg_mutex); 14 | 15 | __END_DECLS 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /src/lua-graph.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* lua-graph.c 3 | * 4 | * Copyright (C) 2009 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | extern "C" { 22 | #include 23 | #include 24 | } 25 | 26 | #define GRAPH_TK_COMPILATION 27 | #include "lua-graph.h" 28 | #include "lua-graph-priv.h" 29 | #include "fonts.h" 30 | #include "window_registry.h" 31 | #include "lua-draw.h" 32 | #include "lua-text.h" 33 | #include "window.h" 34 | #include "lua-plot.h" 35 | #include "window_hooks.h" 36 | 37 | int 38 | stub_window_fn(lua_State *L) 39 | { 40 | return luaL_error(L, "no windows module loaded"); 41 | } 42 | 43 | struct window_hooks stub_window_hooks[1] = {{ 44 | stub_window_fn, stub_window_fn, stub_window_fn, stub_window_fn, 45 | stub_window_fn, stub_window_fn, stub_window_fn, stub_window_fn, 46 | stub_window_fn, 47 | }}; 48 | 49 | pthread_mutex_t agg_mutex[1]; 50 | 51 | struct window_hooks *app_window_hooks = stub_window_hooks; 52 | 53 | static luaL_Reg dummy_entries[] = { {NULL, NULL} }; 54 | 55 | int 56 | luaopen_graphcore(lua_State *L) 57 | { 58 | pthread_mutex_init(agg_mutex, NULL); 59 | window_registry_prepare(L); 60 | #ifdef GRAPH_TK_USE_LUA54 61 | luaL_newlib(L, dummy_entries); 62 | #else 63 | luaL_register(L, "graphcore", dummy_entries); 64 | #endif 65 | draw_register(L); 66 | text_register(L); 67 | plot_register(L); 68 | initialize_fonts(L); 69 | natwin_register(L); 70 | return 1; 71 | } 72 | -------------------------------------------------------------------------------- /src/lua-graph.h: -------------------------------------------------------------------------------- 1 | #ifndef LUA_GRAPH_H 2 | #define LUA_GRAPH_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | #include 9 | 10 | grtk_public int luaopen_graphcore (lua_State *L); 11 | 12 | __END_DECLS 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/lua-plot-cpp.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_LUA_PLOT_CPP_H 2 | #define AGGPLOT_LUA_PLOT_CPP_H 3 | 4 | #include "lua-plot.h" 5 | 6 | extern "C" { 7 | #include "lua.h" 8 | } 9 | 10 | #include "plot-auto.h" 11 | #include "resource-manager.h" 12 | 13 | typedef plot sg_plot; 14 | typedef plot_auto sg_plot_auto; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/lua-plot.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_LUA_PLOT_H 2 | #define AGGPLOT_LUA_PLOT_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | #include "lua.h" 9 | 10 | extern void plot_register (lua_State *L); 11 | 12 | extern void plot_lua_add_ref (lua_State* L, int plot_index, int ref_index); 13 | 14 | __END_DECLS 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/lua-properties.c: -------------------------------------------------------------------------------- 1 | #include "lua-properties.h" 2 | 3 | static void 4 | register_cfuncs(lua_State* L, const luaL_Reg reg_table[]) 5 | { 6 | const luaL_Reg* reg; 7 | for (reg = reg_table; reg->name; reg++) 8 | { 9 | lua_pushstring(L, reg->name); 10 | lua_pushcfunction(L, reg->func); 11 | lua_rawset(L, -3); 12 | } 13 | } 14 | 15 | static int 16 | properties_index (lua_State *L) 17 | { 18 | lua_pushvalue(L, 2); /* push the key */ 19 | lua_rawget(L, lua_upvalueindex(1)); /* lookup into methods' table (upvalue) */ 20 | if (lua_isnil(L, -1)) /* if the method does not exists */ 21 | { 22 | lua_pushvalue(L, 2); /* push the key */ 23 | lua_rawget(L, lua_upvalueindex(2)); /* lookup into getters table (upvalue) */ 24 | if (lua_isnil(L, -1)) /* if getter function does not exists */ 25 | return 1; /* return nil */ 26 | 27 | /* the getter exists: */ 28 | lua_pushvalue(L, 1); /* push the object itself (plot) */ 29 | lua_call(L, 1, 1); /* call the getter and return the result */ 30 | return 1; 31 | } 32 | 33 | /* the method exists. We return it (a function). */ 34 | return 1; 35 | } 36 | 37 | static int 38 | properties_newindex (lua_State *L) 39 | { 40 | lua_pushvalue(L, 2); /* push the key */ 41 | lua_rawget(L, lua_upvalueindex(1)); /* lookup into setters table (upvalue) */ 42 | if (!lua_isnil(L, -1)) /* if setter function does exists */ 43 | { 44 | lua_pushvalue(L, 1); /* push the object itself (plot) */ 45 | lua_pushvalue(L, 3); /* push the value for the setter */ 46 | /* call the setter function with the plot and value as arguments */ 47 | lua_call(L, 2, 0); 48 | return 0; 49 | } 50 | return 0; 51 | } 52 | 53 | /* Assume that we have on top of the stack a table and add 54 | a __index and __newindex function to access the methods and properties 55 | getters. Leave the table on top of the stack. */ 56 | void 57 | register_properties_index(lua_State* L, const luaL_Reg methods[], 58 | const luaL_Reg getters[], const luaL_Reg setters[]) 59 | { 60 | lua_pushstring(L, "__index"); 61 | lua_newtable(L); /* create a new table to hold the methods */ 62 | register_cfuncs(L, methods); /* register all the methods into the table */ 63 | lua_newtable(L); /* create a new table to hold the getters */ 64 | register_cfuncs(L, getters); /* register all the getters into the table */ 65 | /* create a closure with the methods and getters tables as upvalues */ 66 | lua_pushcclosure(L, properties_index, 2); 67 | lua_rawset(L, -3); /* bind the newly created closure to __index */ 68 | 69 | lua_pushstring(L, "__newindex"); 70 | lua_newtable(L); /* create a new table to hold the setters */ 71 | register_cfuncs(L, setters); /* register all the setters into the table */ 72 | /* create a closure with the setters' table as upvalue */ 73 | lua_pushcclosure(L, properties_newindex, 1); 74 | lua_rawset(L, -3); /* bind the newly created closure to __newindex */ 75 | } 76 | -------------------------------------------------------------------------------- /src/lua-properties.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | void register_properties_index(lua_State* L, const luaL_Reg methods[], 9 | const luaL_Reg getters[], const luaL_Reg setters[]); 10 | 11 | __END_DECLS -------------------------------------------------------------------------------- /src/lua-text.cpp: -------------------------------------------------------------------------------- 1 | 2 | extern "C" { 3 | #include 4 | #include 5 | } 6 | 7 | #include "lua-compat.h" 8 | #include "lua-text.h" 9 | #include "gs-types.h" 10 | #include "lua-properties.h" 11 | #include "lua-cpp-utils.h" 12 | 13 | #include "text.h" 14 | 15 | static int agg_text_new (lua_State *L); 16 | static int agg_text_free (lua_State *L); 17 | static int agg_text_set_point (lua_State *L); 18 | 19 | static int agg_text_angle_set (lua_State *L); 20 | static int agg_text_justif_set (lua_State *L); 21 | 22 | static int agg_text_text_get (lua_State *L); 23 | static int agg_text_angle_get (lua_State *L); 24 | 25 | static draw::text* check_agg_text (lua_State *L, int index); 26 | 27 | static const struct luaL_Reg text_functions[] = { 28 | {"text", agg_text_new}, 29 | {NULL, NULL} 30 | }; 31 | 32 | static const struct luaL_Reg text_metatable[] = { 33 | {"__gc", agg_text_free}, 34 | {NULL, NULL} 35 | }; 36 | 37 | static const struct luaL_Reg text_methods[] = { 38 | {"set", agg_text_set_point}, 39 | {"justif", agg_text_justif_set }, 40 | {NULL, NULL} 41 | }; 42 | 43 | static const struct luaL_Reg text_properties_get[] = { 44 | {"text", agg_text_text_get }, 45 | {"angle", agg_text_angle_get }, 46 | {NULL, NULL} 47 | }; 48 | 49 | static const struct luaL_Reg text_properties_set[] = { 50 | {"angle", agg_text_angle_set }, 51 | {NULL, NULL} 52 | }; 53 | 54 | draw::text * 55 | check_agg_text (lua_State *L, int index) 56 | { 57 | return (draw::text *) gs_check_userdata (L, index, GS_DRAW_TEXT); 58 | } 59 | 60 | int 61 | agg_text_new (lua_State *L) 62 | { 63 | double x = luaL_checknumber (L, 1); 64 | double y = luaL_checknumber (L, 2); 65 | const char *text = luaL_checkstring (L, 3); 66 | double size = luaL_optnumber (L, 4, 14.0); 67 | draw::text* t = new(L, GS_DRAW_TEXT) draw::text(text, size); 68 | t->set_point(x, y); 69 | return 1; 70 | } 71 | 72 | int 73 | agg_text_free (lua_State *L) 74 | { 75 | typedef draw::text text_type; 76 | text_type *t = check_agg_text (L, 1); 77 | t->~text_type(); 78 | return 0; 79 | } 80 | 81 | int 82 | agg_text_angle_set (lua_State *L) 83 | { 84 | draw::text *t = check_agg_text (L, 1); 85 | double th = luaL_checknumber (L, 2); 86 | t->angle(th); 87 | return 0; 88 | } 89 | 90 | int 91 | agg_text_angle_get (lua_State *L) 92 | { 93 | draw::text *t = check_agg_text (L, 1); 94 | lua_pushnumber (L, t->angle()); 95 | return 1; 96 | } 97 | 98 | int 99 | agg_text_text_get (lua_State *L) 100 | { 101 | draw::text *t = check_agg_text (L, 1); 102 | lua_pushstring (L, t->get_text()); 103 | return 1; 104 | } 105 | 106 | int 107 | agg_text_justif_set (lua_State *L) 108 | { 109 | draw::text *t = check_agg_text (L, 1); 110 | const char *justif = luaL_checkstring (L, 2); 111 | size_t len = strlen (justif); 112 | 113 | if (len > 0) 114 | { 115 | char ch = justif[0]; 116 | double hjf; 117 | switch (ch) 118 | { 119 | case 'l': 120 | hjf = 0.0; 121 | break; 122 | case 'c': 123 | hjf = 0.5; 124 | break; 125 | case 'r': 126 | hjf = 1.0; 127 | break; 128 | default: 129 | return luaL_error (L, "invalid text justification"); 130 | } 131 | 132 | t->hjustif(hjf); 133 | } 134 | 135 | if (len > 1) 136 | { 137 | char ch = justif[1]; 138 | double vjf; 139 | switch (ch) 140 | { 141 | case 'b': 142 | vjf = 0.0; 143 | break; 144 | case 'c': 145 | vjf = 0.5; 146 | break; 147 | case 't': 148 | vjf = 1.0; 149 | break; 150 | default: 151 | return luaL_error (L, "invalid text justification"); 152 | } 153 | 154 | t->vjustif(vjf); 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | int 161 | agg_text_set_point (lua_State *L) 162 | { 163 | draw::text *t = check_agg_text (L, 1); 164 | double x = luaL_checknumber (L, 2); 165 | double y = luaL_checknumber (L, 3); 166 | t->set_point(x, y); 167 | return 0; 168 | } 169 | 170 | void 171 | text_register (lua_State *L) 172 | { 173 | luaL_newmetatable (L, GS_METATABLE(GS_DRAW_TEXT)); 174 | register_properties_index(L, text_methods, text_properties_get, text_properties_set); 175 | grtk_lua_register (L, text_metatable); 176 | lua_pop (L, 1); 177 | 178 | grtk_lua_register (L, text_functions); 179 | } 180 | -------------------------------------------------------------------------------- /src/lua-text.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_LUA_TEXT_H 2 | #define AGGPLOT_LUA_TEXT_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | #include 9 | 10 | extern void text_register (lua_State *L); 11 | 12 | __END_DECLS 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/lua-utils.c: -------------------------------------------------------------------------------- 1 | 2 | /* lua-utils.c 3 | * 4 | * Copyright (C) 2009 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "lua-utils.h" 26 | #include "gs-types.h" 27 | 28 | lua_Number 29 | mlua_named_optnumber (lua_State *L, int index, const char *key, 30 | lua_Number default_value) 31 | { 32 | lua_Number r; 33 | lua_getfield (L, index, key); 34 | r = luaL_optnumber (L, -1, default_value); 35 | lua_pop (L, 1); 36 | return r; 37 | } 38 | 39 | const char * 40 | mlua_named_optstring (lua_State *L, int index, const char *key, 41 | const char * default_value) 42 | { 43 | const char * r; 44 | lua_getfield (L, index, key); 45 | r = luaL_optstring (L, -1, default_value); 46 | lua_pop (L, 1); 47 | return r; 48 | } 49 | 50 | lua_Number 51 | mlua_named_number (lua_State *L, int index, const char *key) 52 | { 53 | lua_Number r; 54 | lua_getfield (L, index, key); 55 | if (! lua_isnumber (L, -1)) 56 | luaL_error (L, "number expected"); 57 | r = lua_tonumber (L, -1); 58 | lua_pop (L, 1); 59 | return r; 60 | } 61 | 62 | const char * 63 | mlua_named_string (lua_State *L, int index, const char *key) 64 | { 65 | const char * r; 66 | lua_getfield (L, index, key); 67 | if (! lua_isstring (L, -1)) 68 | luaL_error (L, "string expected"); 69 | r = lua_tostring (L, -1); 70 | lua_pop (L, 1); 71 | return r; 72 | } 73 | 74 | int 75 | error_return(lua_State* L, const char* error_msg) 76 | { 77 | lua_pushstring(L, error_msg); 78 | return (-1); 79 | } 80 | 81 | int 82 | type_error_return(lua_State* L, int narg, const char* req_type) 83 | { 84 | const char *actual_type = full_type_name(L, narg); 85 | lua_pushfstring(L, "bad argument #%d (expected %s, got %s)", narg, req_type, actual_type); 86 | return (-1); 87 | } 88 | -------------------------------------------------------------------------------- /src/lua-utils.h: -------------------------------------------------------------------------------- 1 | 2 | /* lua-utils.h 3 | * 4 | * Copyright (C) 2009 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef LUA_UTILS_H 22 | #define LUA_UTILS_H 23 | 24 | #include "defs.h" 25 | 26 | __BEGIN_DECLS 27 | 28 | #include "lua.h" 29 | 30 | extern const char * mlua_named_optstring (lua_State *L, int index, 31 | const char *key, 32 | const char * default_value); 33 | 34 | extern const char * mlua_named_string (lua_State *L, int index, 35 | const char *key); 36 | 37 | extern lua_Number mlua_named_optnumber (lua_State *L, int index, 38 | const char *key, 39 | lua_Number default_value); 40 | 41 | extern lua_Number mlua_named_number (lua_State *L, int index, 42 | const char *key); 43 | 44 | 45 | extern int error_return(lua_State* L, const char* error_msg); 46 | extern int type_error_return(lua_State* L, int narg, const char* req_type); 47 | 48 | __END_DECLS 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/makeconfig: -------------------------------------------------------------------------------- 1 | # set this to "yes" if you want to disable gamma correction 2 | DISABLE_GAMMA_CORR = no 3 | 4 | # set this to "yes" if you want to disable subpixel LCD antialiasing 5 | DISABLE_SUBPIXEL_LCD = no 6 | 7 | # Can be "luajit", "lua5.4" "lua5.1" to use a specific Lua implementation. 8 | LUA = lua5.4 9 | 10 | # vill me used to decide where to install the modules under share/lua 11 | LUA_VERSION = 5.4 12 | 13 | DEBUG = no 14 | 15 | # Define if a static or shared library should be built. Can be "static" 16 | # or "dynamic" 17 | BUILD = dynamic 18 | -------------------------------------------------------------------------------- /src/markers.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "agg_path_storage.h" 5 | #include "agg_ellipse.h" 6 | 7 | #include "markers.h" 8 | #include "trans.h" 9 | #include "path.h" 10 | 11 | /* used to encode a simple path */ 12 | struct path_code { 13 | enum {closed = 0, open = 1, end = 2}; 14 | enum {scale = 32767}; 15 | short x, y; 16 | }; 17 | 18 | struct symbol_reg { 19 | const char *name; 20 | sg_object *(*builder)(); 21 | const path_code* pcode; 22 | }; 23 | 24 | static sg_object *build_circle(); 25 | static sg_object *build_path(const path_code* pcode); 26 | 27 | /* 28 | -- lua code to generate the coordinates 29 | 30 | use 'math' 31 | 32 | b = 2^15 - 1 33 | 34 | function rot(alpha, x, y) 35 | return x*cos(alpha) - y*sin(alpha), y*cos(alpha) + x*sin(alpha) 36 | end 37 | 38 | function tr(x, y) 39 | return floor(x*b+0.5), floor(y*b+0.5) 40 | end 41 | 42 | -- example for asterisk 43 | tr(rot(0, -0.08, 0.5)) 44 | tr(rot(0, 0.08, 0.5)) 45 | tr(rot(0, 0.08, -0.5)) 46 | tr(rot(0, -0.08, -0.5)) 47 | 48 | tr(rot(pi/3, -0.08, 0.5)) 49 | tr(rot(pi/3, 0.08, 0.5)) 50 | tr(rot(pi/3, 0.08, -0.5)) 51 | tr(rot(pi/3, -0.08, -0.5)) 52 | ... 53 | */ 54 | 55 | static path_code asterisk[] = { 56 | {path_code::closed, 4}, 57 | {-2621, 16384}, 58 | { 2621, 16384}, 59 | { 2621, -16384}, 60 | {-2621, -16384}, 61 | {path_code::closed, 4}, 62 | {-15499, 5922}, 63 | {-12878, 10462}, 64 | { 15499, -5922}, 65 | { 12878, -10462}, 66 | {path_code::closed, 4}, 67 | { 12878, 10462}, 68 | { 15499, 5922}, 69 | {-12878, -10462}, 70 | {-15499, -5922}, 71 | {path_code::end}, 72 | }; 73 | 74 | static path_code square[] = { 75 | {path_code::closed, 4}, 76 | {-16383, 16384}, 77 | { 16384, 16384}, 78 | { 16384, -16383}, 79 | {-16383, -16383}, 80 | {path_code::end}, 81 | }; 82 | 83 | static path_code diamond[] = { 84 | {path_code::closed, 4}, 85 | {-16383, 0}, 86 | { 0, 16384}, 87 | { 16384, 0}, 88 | { 0, -16383}, 89 | {path_code::end}, 90 | }; 91 | 92 | static path_code triangle[] = { 93 | {path_code::closed, 3}, 94 | {-18918, -10922}, 95 | { 18918, -10922}, 96 | { 0, 21845}, 97 | {path_code::end}, 98 | }; 99 | 100 | static path_code plus[] = { 101 | {path_code::closed, 4}, 102 | {-2621, 16384}, 103 | { 2621, 16384}, 104 | { 2621, -16384}, 105 | {-2621, -16384}, 106 | {path_code::closed, 4}, 107 | {-16383, 2621}, 108 | { 16384, 2621}, 109 | { 16384, -2621}, 110 | {-16383, -2621}, 111 | {path_code::end}, 112 | }; 113 | 114 | static path_code cross[] = { 115 | {path_code::closed, 4}, 116 | {-13438, 9731}, 117 | {-9731, 13438}, 118 | {13438, -9731}, 119 | {9731, -13438}, 120 | {path_code::closed, 4}, 121 | {9731, 13438}, 122 | {13438, 9731}, 123 | {-9731, -13438}, 124 | {-13438, -9731}, 125 | {path_code::end}, 126 | }; 127 | 128 | const unsigned NB_SYMBOLS = 7; 129 | static struct symbol_reg builder_table[NB_SYMBOLS+1] = { 130 | {"circle", build_circle}, 131 | {"square", NULL, square}, 132 | {"triangle", NULL, triangle}, 133 | {"diamond", NULL, diamond}, 134 | {"plus", NULL, plus}, 135 | {"cross", NULL, cross}, 136 | {"asterisk", NULL, asterisk}, 137 | {NULL, NULL} 138 | }; 139 | 140 | sg_object * 141 | build_circle() 142 | { 143 | draw::ellipse* c = new draw::ellipse(); 144 | c->self().init(0.0, 0.0, 0.5, 0.5); 145 | return c; 146 | } 147 | 148 | static inline void decode_coord(const path_code* p, double x[]) 149 | { 150 | x[0] = double(p->x) / path_code::scale; 151 | x[1] = double(p->y) / path_code::scale; 152 | } 153 | 154 | sg_object * 155 | build_path(const path_code *pcode) 156 | { 157 | draw::path* p = new draw::path(); 158 | agg::path_storage& ps = p->self(); 159 | 160 | for (const path_code* op = pcode; op->x != path_code::end; op = op + op->y + 1) 161 | { 162 | const path_code* code = op + 1; 163 | double x[2]; 164 | decode_coord(code ++, x); 165 | ps.move_to(x[0], x[1]); 166 | for (short k = 1; k < op->y; k++) 167 | { 168 | decode_coord(code ++, x); 169 | ps.line_to(x[0], x[1]); 170 | } 171 | 172 | if (op->x == path_code::closed) 173 | ps.close_polygon(); 174 | } 175 | 176 | return p; 177 | } 178 | 179 | sg_object* 180 | new_marker_symbol_raw(const char *req_name) 181 | { 182 | struct symbol_reg *reg; 183 | for (reg = builder_table; reg->name != NULL; reg++) 184 | { 185 | if (strcmp (reg->name, req_name) == 0) 186 | { 187 | if (reg->builder) 188 | return reg->builder(); 189 | else 190 | return build_path(reg->pcode); 191 | } 192 | } 193 | 194 | return builder_table[0].builder(); 195 | } 196 | 197 | sg_object* 198 | new_marker_symbol (const char *req_name) 199 | { 200 | sg_object* s = new_marker_symbol_raw(req_name); 201 | return new trans::scaling(s); 202 | } 203 | 204 | sg_object* 205 | new_marker_symbol (int n) 206 | { 207 | n = (n-1) % NB_SYMBOLS; 208 | return new_marker_symbol(builder_table[n].name); 209 | } 210 | 211 | const char* 212 | marker_lookup(int n) 213 | { 214 | n = (n-1) % NB_SYMBOLS; 215 | return builder_table[n].name; 216 | } 217 | -------------------------------------------------------------------------------- /src/markers.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_MARKERS_H 2 | #define AGGPLOT_MARKERS_H 3 | 4 | #include "sg_object.h" 5 | 6 | extern sg_object* new_marker_symbol(const char *name); 7 | extern sg_object* new_marker_symbol(int n); 8 | extern sg_object* new_marker_symbol_raw(const char *req_name); 9 | extern const char* marker_lookup(int n); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | graph_toolkit_src_files = [ 2 | 'lua-compat.c', 3 | 'str.c', 4 | 'gs-types.c', 5 | 'lua-utils.c', 6 | 'lua-properties.c', 7 | 'gamma.cpp', 8 | 'printf_check.cpp', 9 | 'utils.cpp', 10 | 'window_registry.cpp', 11 | 'fonts.cpp', 12 | 'agg_font_freetype.cpp', 13 | 'plot.cpp', 14 | 'plot-auto.cpp', 15 | 'units.cpp', 16 | 'colors.cpp', 17 | 'markers.cpp', 18 | 'draw_svg.cpp', 19 | 'canvas_svg.cpp', 20 | 'lua-draw.cpp', 21 | 'lua-text.cpp', 22 | 'text.cpp', 23 | 'agg-parse-trans.cpp', 24 | 'lua-plot.cpp', 25 | 'bitmap-plot.cpp', 26 | 'lua-graph.cpp', 27 | 'canvas-window.cpp', 28 | 'window.cpp', 29 | ] 30 | 31 | if not get_option('gamma-correction') 32 | graph_toolkit_c_args += '-DDISABLE_GAMMA_CORR' 33 | endif 34 | 35 | if not get_option('subpixel-lcd') 36 | graph_toolkit_c_args += '-DDISABLE_SUBPIXEL_AA' 37 | endif 38 | 39 | if lua_name == 'lua5.4' 40 | graph_toolkit_c_args += '-DGRAPH_TK_USE_LUA54' 41 | endif 42 | 43 | if host_machine.system() == 'windows' 44 | graph_toolkit_src_files += [ 'fonts_search_win32.cpp', 'image_write_win32.cpp' ] 45 | graph_toolkit_src_files += [ 'agg_platform_support_win32.cpp', 'agg_win32_bmp.cpp', 'agg_win32_bmp.cpp' ] 46 | else 47 | # Besides windows we support only X11 even on macOS 48 | if host_machine.system() == 'darwin' 49 | graph_toolkit_c_args += '-DDARWIN_MACOSX' 50 | endif 51 | graph_toolkit_src_files += [ 'fonts_search_x11.cpp', 'image_write_x11.cpp' ] 52 | graph_toolkit_src_files += [ 'agg_platform_support_x11.cpp' ] 53 | endif 54 | 55 | graph_toolkit_link_args = [ ] 56 | if cc.get_id() == 'gcc' 57 | graph_toolkit_link_args += ['-static-libgcc', '-static-libstdc++'] 58 | endif 59 | 60 | if host_machine.system() == 'linux' 61 | # See: https://stackoverflow.com/questions/2222162/how-to-apply-fvisibility-option-to-symbols-in-static-libraries 62 | # The following flag is to consider hidden all the symbols defined in static libraries we use 63 | # to link the shared library. 64 | graph_toolkit_link_args += [ '-Wl,--exclude-libs,ALL' ] 65 | endif 66 | 67 | libgraph = shared_library('graphcore', 68 | graph_toolkit_src_files, 69 | dependencies: graph_toolkit_deps, 70 | c_args : graph_toolkit_c_args, 71 | cpp_args : graph_toolkit_c_args, 72 | link_args : graph_toolkit_link_args, 73 | gnu_symbol_visibility : 'hidden', 74 | name_prefix : '', 75 | install_dir : 'lib' / lua_modules_dir, 76 | install : true, 77 | ) 78 | 79 | -------------------------------------------------------------------------------- /src/my_conv_simple_marker.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_CONV_SIMPLE_MARKER_H 2 | #define MY_CONV_SIMPLE_MARKER_H 3 | 4 | #include "agg_basics.h" 5 | #include "agg_trans_affine.h" 6 | 7 | using namespace agg; 8 | 9 | namespace my { 10 | //---------------------------------------------------------conv_simple_marker 11 | template 12 | class conv_simple_marker 13 | { 14 | public: 15 | conv_simple_marker(MarkerLocator& ml, MarkerShapes& ms); 16 | 17 | void rewind(unsigned path_id); 18 | unsigned vertex(double* x, double* y); 19 | 20 | private: 21 | conv_simple_marker(const conv_simple_marker&); 22 | const conv_simple_marker& 23 | operator = (const conv_simple_marker&); 24 | 25 | enum status_e 26 | { 27 | initial, 28 | markers, 29 | polygon, 30 | stop 31 | }; 32 | 33 | MarkerLocator* m_marker_locator; 34 | MarkerShapes* m_marker_shapes; 35 | status_e m_status; 36 | double m_x1, m_y1; 37 | }; 38 | 39 | 40 | //------------------------------------------------------------------------ 41 | template 42 | conv_simple_marker::conv_simple_marker(MarkerLocator& ml, MarkerShapes& ms) : 43 | m_marker_locator(&ml), 44 | m_marker_shapes(&ms), 45 | m_status(initial) 46 | { 47 | } 48 | 49 | 50 | //------------------------------------------------------------------------ 51 | template 52 | void conv_simple_marker::rewind(unsigned) 53 | { 54 | m_status = initial; 55 | } 56 | 57 | 58 | //------------------------------------------------------------------------ 59 | template 60 | unsigned conv_simple_marker::vertex(double* x, double* y) 61 | { 62 | unsigned cmd = path_cmd_move_to; 63 | 64 | while(!is_stop(cmd)) 65 | { 66 | switch(m_status) 67 | { 68 | case initial: 69 | m_marker_locator->rewind(0); 70 | m_status = markers; 71 | 72 | case markers: 73 | if(is_stop(m_marker_locator->vertex(&m_x1, &m_y1))) 74 | { 75 | cmd = path_cmd_stop; 76 | m_status = stop; 77 | break; 78 | } 79 | m_marker_shapes->rewind(0); 80 | m_status = polygon; 81 | 82 | case polygon: 83 | cmd = m_marker_shapes->vertex(x, y); 84 | if(is_stop(cmd)) 85 | { 86 | cmd = path_cmd_move_to; 87 | m_status = markers; 88 | break; 89 | } 90 | *x += m_x1; 91 | *y += m_y1; 92 | return cmd; 93 | 94 | case stop: 95 | cmd = path_cmd_stop; 96 | break; 97 | } 98 | } 99 | return cmd; 100 | } 101 | } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /src/path.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_PATH_H 2 | #define AGGPLOT_PATH_H 3 | 4 | #include "sg_object.h" 5 | 6 | #include "agg_path_storage.h" 7 | #include "agg_ellipse.h" 8 | 9 | namespace draw { 10 | 11 | typedef sg_object_gen path; 12 | typedef sg_object_gen ellipse; 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/pixel_fmt.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_PIXEL_FMT_H 2 | #define AGGPLOT_PIXEL_FMT_H 3 | 4 | #include "agg-pixfmt-config.h" 5 | 6 | #include "agg_pixfmt_rgb.h" 7 | 8 | typedef gslshell::gamma_type gamma_type; 9 | 10 | struct pixel_gamma : public agg::pixfmt_rgb24_gamma 11 | { 12 | pixel_gamma(agg::rendering_buffer& ren_buf): 13 | agg::pixfmt_rgb24_gamma(ren_buf, gslshell::gamma) 14 | { } 15 | }; 16 | 17 | struct pixel_gamma_lcd : public agg::pixfmt_rgb24_lcd_gamma 18 | { 19 | pixel_gamma_lcd(agg::rendering_buffer& ren_buf): 20 | agg::pixfmt_rgb24_lcd_gamma(ren_buf, gslshell::subpixel_lut, gslshell::gamma) 21 | { } 22 | }; 23 | 24 | struct pixel_simple : public agg::pixfmt_rgb24 25 | { 26 | pixel_simple(agg::rendering_buffer& ren_buf): 27 | agg::pixfmt_rgb24(ren_buf) 28 | { } 29 | }; 30 | 31 | struct pixel_lcd : public agg::pixfmt_rgb24_lcd 32 | { 33 | pixel_lcd(agg::rendering_buffer& ren_buf): 34 | agg::pixfmt_rgb24_lcd(ren_buf, gslshell::subpixel_lut) 35 | { } 36 | }; 37 | 38 | #ifdef DISABLE_GAMMA_CORR 39 | typedef pixel_simple pixel_type; 40 | typedef pixel_lcd pixel_lcd_type; 41 | #else 42 | typedef pixel_gamma pixel_type; 43 | typedef pixel_gamma_lcd pixel_lcd_type; 44 | #endif 45 | 46 | #define LIBGRAPH_BPP 24 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/platform_support_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_PLATFORM_SUPPORT_H 2 | #define AGGPLOT_PLATFORM_SUPPORT_H 3 | 4 | #include "agg_basics.h" 5 | #include "platform/agg_platform_support.h" 6 | #include "rendering_buffer_utils.h" 7 | 8 | class platform_support_ext : public agg::platform_support { 9 | public: 10 | platform_support_ext (agg::pix_format_e format, bool flip_y) 11 | : agg::platform_support(format, flip_y) 12 | { }; 13 | 14 | void lock(); 15 | void unlock(); 16 | 17 | bool is_mapped(); 18 | void close_request(); 19 | void update_region (const agg::rect_base& r); 20 | void do_window_update (); 21 | 22 | static void prepare(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/plot-auto.cpp: -------------------------------------------------------------------------------- 1 | #include "plot-auto.h" 2 | 3 | void plot_auto::add(sg_object* vs, agg::rgba8& color, bool outline) 4 | { 5 | item d(vs, color, outline); 6 | 7 | if (!this->fit_inside(vs)) 8 | { 9 | this->m_bbox_updated = false; 10 | this->m_need_redraw = true; 11 | this->m_enlarged_layer = true; 12 | } 13 | 14 | list *nn = new list(d); 15 | this->m_drawing_queue = list::push_back(this->m_drawing_queue, nn); 16 | 17 | RM::acquire(vs); 18 | } 19 | 20 | void plot_auto::check_bounding_box() 21 | { 22 | this->calc_bounding_box(); 23 | this->update_units(); 24 | this->m_bbox_updated = true; 25 | } 26 | 27 | void plot_auto::calc_layer_bounding_box(plot_auto::item_list* layer, 28 | opt_rect& rect) 29 | { 30 | for (unsigned j = 0; j < layer->size(); j++) 31 | { 32 | item& d = (*layer)[j]; 33 | agg::rect_base r; 34 | 35 | d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2); 36 | rect.add(r); 37 | } 38 | } 39 | 40 | void plot_auto::calc_bounding_box() 41 | { 42 | opt_rect box; 43 | 44 | unsigned n = this->nb_layers(); 45 | for (unsigned j = 0; j < n-1; j++) 46 | { 47 | box.add(this->get_layer(j)->bounding_box()); 48 | } 49 | 50 | calc_layer_bounding_box(this->get_layer(n-1), box); 51 | for (list *t = this->m_drawing_queue; t; t = t->next()) 52 | { 53 | const item& d = t->content(); 54 | agg::rect_base r; 55 | d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2); 56 | box.add(r); 57 | } 58 | 59 | this->m_rect = box; 60 | } 61 | 62 | bool plot_auto::fit_inside(sg_object* obj) const 63 | { 64 | if (!this->m_bbox_updated || !this->m_rect.is_defined()) 65 | return false; 66 | 67 | agg::rect_base r; 68 | obj->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2); 69 | 70 | const agg::rect_base& bb = this->m_rect.rect(); 71 | return bb.hit_test(r.x1, r.y1) && bb.hit_test(r.x2, r.y2); 72 | } 73 | 74 | void plot_auto::set_opt_limits(const opt_rect& r) 75 | { 76 | if (r.is_defined()) 77 | this->set_limits(r.rect()); 78 | else 79 | this->unset_limits(); 80 | } 81 | 82 | bool plot_auto::push_layer() 83 | { 84 | bool retval = this->plot::push_layer(); 85 | if (this->m_rect.is_defined()) 86 | this->parent_layer()->set_bounding_box(this->m_rect.rect()); 87 | this->m_bbox_updated = true; 88 | this->m_enlarged_layer = false; 89 | return retval; 90 | } 91 | 92 | bool plot_auto::pop_layer() 93 | { 94 | bool retval = this->plot::pop_layer(); 95 | if (this->m_enlarged_layer) 96 | this->m_bbox_updated = false; 97 | this->m_enlarged_layer = true; 98 | return retval; 99 | } 100 | 101 | void plot_auto::clear_current_layer() 102 | { 103 | this->plot::clear_current_layer(); 104 | if (this->m_enlarged_layer) 105 | { 106 | item_list* parent = this->parent_layer(); 107 | if (parent) 108 | set_opt_limits(parent->bounding_box()); 109 | else 110 | this->unset_limits(); 111 | } 112 | this->m_bbox_updated = true; 113 | this->m_enlarged_layer = false; 114 | } 115 | -------------------------------------------------------------------------------- /src/plot-auto.h: -------------------------------------------------------------------------------- 1 | 2 | /* plot-auto.h 3 | * 4 | * Copyright (C) 2009, 2010 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef AGGPLOT_PLOT_AUTO_H 22 | #define AGGPLOT_PLOT_AUTO_H 23 | 24 | #include "plot.h" 25 | #include "rect.h" 26 | 27 | #include "agg_array.h" 28 | #include "agg_basics.h" 29 | 30 | class plot_auto : public plot { 31 | public: 32 | plot_auto() : 33 | plot(true), m_bbox_updated(true), m_enlarged_layer(false) 34 | { }; 35 | 36 | virtual ~plot_auto() { }; 37 | 38 | virtual void add(sg_object* vs, agg::rgba8& color, bool outline); 39 | virtual void before_draw() 40 | { 41 | plot::before_draw(); 42 | if (!m_bbox_updated) 43 | check_bounding_box(); 44 | }; 45 | 46 | virtual bool push_layer(); 47 | virtual bool pop_layer(); 48 | virtual void clear_current_layer(); 49 | 50 | private: 51 | void calc_layer_bounding_box(item_list* layer, opt_rect& rect); 52 | void set_opt_limits(const opt_rect& r); 53 | 54 | void check_bounding_box(); 55 | void calc_bounding_box(); 56 | bool fit_inside(sg_object *obj) const; 57 | 58 | // bounding box 59 | bool m_bbox_updated; 60 | bool m_enlarged_layer; 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/printf_check.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "printf_check.h" 3 | 4 | static const char* match_plain_chars(const char *p) 5 | { 6 | for (/* */; *p; p++) { 7 | for (/* */; *p != '%'; p++) { 8 | if (*p == 0) 9 | return 0; 10 | } 11 | p ++; 12 | if (*p != '%') 13 | return p; 14 | } 15 | return 0; 16 | } 17 | 18 | static const char* match_integer(const char* p) 19 | { 20 | if (int(*p) >= int('1') && int(*p) <= int('9')) 21 | p++; 22 | while (int(*p) >= int('0') && int(*p) <= int('9')) 23 | p++; 24 | 25 | return p; 26 | } 27 | 28 | int check_printf_argument(const char *label, const char*& tail, arg_type_e& arg_type) 29 | { 30 | const char* p = match_plain_chars(label); 31 | 32 | if (!p) return 0; 33 | 34 | if (*p) 35 | { 36 | const char c = *p; 37 | if (c == '0' || c == '-' || c == '+' || c == ' ' || c == '#' || c == '\'') 38 | { 39 | p ++; 40 | if (*p == 0) goto error_exit; 41 | } 42 | } 43 | else 44 | goto error_exit; 45 | 46 | p = match_integer(p); 47 | if (*p == 0) goto error_exit; 48 | 49 | if (*p == '.') 50 | { 51 | p++; 52 | if (*p == 0) goto error_exit; 53 | p = match_integer(p); 54 | if (*p == 0) goto error_exit; 55 | } 56 | 57 | if (*p == 'l') { 58 | p++; 59 | if (*p == 0) goto error_exit; 60 | } 61 | 62 | if (*p) 63 | { 64 | const char s = *p; 65 | if (s == 'd' || s == 'i' || s == 'd' || s == 'u' || s == 'x' || s == 'X' || s == 'o') { 66 | tail = p + 1; 67 | arg_type = argument_int; 68 | return 1; 69 | } else if (s == 'f' || s == 'g' || s == 'e' || s == 'E' || s == 'G') { 70 | tail = p + 1; 71 | arg_type = argument_double; 72 | return 1; 73 | } 74 | } 75 | 76 | error_exit: 77 | return (-1); 78 | } 79 | -------------------------------------------------------------------------------- /src/printf_check.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_PRINTF_CHECK_H 2 | #define AGGPLOT_PRINTF_CHECK_H 3 | 4 | enum arg_type_e { 5 | argument_int, 6 | argument_double, 7 | }; 8 | 9 | extern int check_printf_argument(const char *label, const char*& tail, arg_type_e& arg_type); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/pthreadpp.h: -------------------------------------------------------------------------------- 1 | #ifndef CPP_PTHREADPP_H 2 | #define CPP_PTHREADPP_H 3 | 4 | #include 5 | 6 | /* Simple C++ wrapper around basic mutex/condition operations. 7 | The added value of the wrapper is more clean C++ code with automatic 8 | initialization/deallocation of resources. */ 9 | 10 | namespace pthread { 11 | 12 | class mutex { 13 | public: 14 | mutex() { pthread_mutex_init(&m_mutex, NULL); } 15 | ~mutex() { pthread_mutex_destroy(&m_mutex); } 16 | 17 | void lock() { pthread_mutex_lock(&m_mutex); } 18 | void unlock() { pthread_mutex_unlock(&m_mutex); } 19 | 20 | pthread_mutex_t* mutex_ptr() { return &m_mutex; } 21 | 22 | private: 23 | mutex(const mutex&); 24 | mutex& operator= (const mutex&); 25 | 26 | pthread_mutex_t m_mutex; 27 | }; 28 | 29 | class auto_lock { 30 | public: 31 | auto_lock(mutex& m): m_mutex(m) { m_mutex.lock(); } 32 | ~auto_lock() { m_mutex.unlock(); } 33 | private: 34 | mutex& m_mutex; 35 | }; 36 | 37 | /* Since the official documentation recommend to use pthread conditions 38 | always in pair with a mutex we let a condtion inherit from a mutex. 39 | In this way a C++ "cond" instance can perform both mutex and condition 40 | operations. */ 41 | class cond : public mutex { 42 | public: 43 | cond() { pthread_cond_init(&m_cond, NULL); } 44 | ~cond() { pthread_cond_destroy(&m_cond); } 45 | 46 | void signal() { pthread_cond_signal(&m_cond); } 47 | void wait() { pthread_cond_wait(&m_cond, mutex_ptr()); } 48 | 49 | private: 50 | pthread_cond_t m_cond; 51 | }; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/rect.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_RECT_H 2 | #define AGGPLOT_RECT_H 3 | 4 | #include 5 | #include "agg_basics.h" 6 | 7 | enum set_oper_e { rect_union, rect_intersect }; 8 | 9 | template 10 | class opt_rect { 11 | typedef agg::rect_base rect_type; 12 | 13 | bool m_defined; 14 | rect_type m_rect; 15 | 16 | public: 17 | opt_rect() : m_defined(false) {}; 18 | opt_rect(T x1, T y1, T x2, T y2) : m_defined(true), m_rect(x1, y1, x2, y2) {}; 19 | 20 | void clear() { 21 | m_defined = false; 22 | }; 23 | 24 | void set(const rect_type& r) { 25 | m_defined = true; 26 | m_rect = r; 27 | }; 28 | 29 | void set(T x1, T y1, T x2, T y2) { 30 | m_defined = true; 31 | m_rect.x1 = x1; 32 | m_rect.y1 = y1; 33 | m_rect.x2 = x2; 34 | m_rect.y2 = y2; 35 | }; 36 | 37 | bool is_defined() const { 38 | return m_defined; 39 | }; 40 | 41 | const rect_type& rect() const 42 | { 43 | assert (m_defined); 44 | return m_rect; 45 | } 46 | 47 | void operator = (const opt_rect& src) 48 | { 49 | m_defined = src.m_defined; 50 | if (m_defined) 51 | m_rect = src.m_rect; 52 | } 53 | 54 | void operator = (const rect_type& src) 55 | { 56 | m_defined = true; 57 | m_rect = src; 58 | } 59 | 60 | template 61 | void add(const rect_type& r) 62 | { 63 | if (op == rect_union) 64 | m_rect = (m_defined ? agg::unite_rectangles(m_rect, r) : r); 65 | else 66 | m_rect = (m_defined ? agg::intersect_rectangles(m_rect, r) : r); 67 | 68 | m_defined = true; 69 | } 70 | 71 | template 72 | void add(const opt_rect& optr) 73 | { 74 | if (optr.m_defined) 75 | this->add(optr.m_rect); 76 | } 77 | }; 78 | 79 | template 80 | agg::rect_base rect_of_slot_matrix (const agg::trans_affine& mtx) 81 | { 82 | T dx = T(mtx.sx + mtx.tx), dy = T(mtx.sy + mtx.ty); 83 | return agg::rect_base(T(mtx.tx), T(mtx.ty), dx, dy); 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/rendering_buffer_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_RBUF_UTILS_H 2 | #define AGGPLOT_RBUF_UTILS_H 3 | 4 | template 5 | void my_color_conv(RenBufDst* dst, const RenBufSrc* src, CopyRow copy_row_functor) 6 | { 7 | unsigned int width = src->width(); 8 | unsigned int height = src->height(); 9 | 10 | for(unsigned int y = 0; y < height; y++) 11 | { 12 | copy_row_functor(dst->row_ptr(0, y, width), src->row_ptr(y), width); 13 | } 14 | } 15 | 16 | template 17 | void rendering_buffer_get_region (RenBufDst& dst, RenBufSrc& src, agg::rect_base& r, 18 | unsigned pixel_width) 19 | { 20 | int w = r.x2 - r.x1, h = r.y2 - r.y1; 21 | for (int y = 0; y < h; y++) 22 | { 23 | unsigned char *drow = dst.row_ptr(y); 24 | unsigned char *srow = src.row_ptr(r.y1 + y); 25 | srow += r.x1 * pixel_width; 26 | memcpy (drow, srow, pixel_width * w); 27 | } 28 | } 29 | 30 | template 31 | void rendering_buffer_get_const_view (RenBufDst& view, const RenBufSrc& src, 32 | const agg::rect_base& r, unsigned pixel_width) 33 | { 34 | int x = r.x1, y = r.y1, w = r.x2 - r.x1, h = r.y2 - r.y1; 35 | const unsigned char *buf_start = src.row_ptr(y); 36 | if (src.stride() < 0) 37 | buf_start += src.stride() * (h - 1); 38 | view.attach(buf_start + pixel_width * x, w, h, src.stride()); 39 | } 40 | 41 | template 42 | void rendering_buffer_get_view (RenBufDst& view, RenBufSrc& src, 43 | const agg::rect_base& r, unsigned pixel_width) 44 | { 45 | int x = r.x1, y = r.y1, w = r.x2 - r.x1, h = r.y2 - r.y1; 46 | unsigned char *buf_start = src.row_ptr(y); 47 | if (src.stride() < 0) 48 | buf_start += src.stride() * (h - 1); 49 | view.attach(buf_start + pixel_width * x, w, h, src.stride()); 50 | } 51 | 52 | template 53 | void rendering_buffer_put_region (RenBufDst& dst, RenBufSrc& src, agg::rect_base& r, 54 | unsigned pixel_width) 55 | { 56 | int w = r.x2 - r.x1, h = r.y2 - r.y1; 57 | for (int y = 0; y < h; y++) 58 | { 59 | unsigned char *drow = dst.row_ptr(r.y1 + y); 60 | unsigned char *srow = src.row_ptr(y); 61 | drow += r.x1 * pixel_width; 62 | memcpy (drow, srow, pixel_width * w); 63 | } 64 | } 65 | 66 | template class row_accessor_ro 67 | { 68 | public: 69 | //-------------------------------------------------------------------- 70 | row_accessor_ro() : m_buf(0), m_width(0), m_height(0), m_stride(0), m_start(0) {}; 71 | 72 | row_accessor_ro(const T* buf, unsigned width, unsigned height, int stride) : 73 | m_buf(buf), m_width(width), m_height(height), m_stride(stride) 74 | { 75 | if(stride < 0) 76 | m_start = m_buf - int(height - 1) * stride; 77 | else 78 | m_start = m_buf; 79 | } 80 | 81 | void attach(const T* buf, unsigned width, unsigned height, int stride) 82 | { 83 | m_buf = m_start = buf; 84 | m_width = width; 85 | m_height = height; 86 | m_stride = stride; 87 | if(stride < 0) 88 | { 89 | m_start = m_buf - int(height - 1) * stride; 90 | } 91 | }; 92 | 93 | //-------------------------------------------------------------------- 94 | const T* buf() const { 95 | return m_buf; 96 | } 97 | unsigned width() const { 98 | return m_width; 99 | } 100 | unsigned height() const { 101 | return m_height; 102 | } 103 | int stride() const { 104 | return m_stride; 105 | } 106 | unsigned stride_abs() const 107 | { 108 | return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); 109 | } 110 | 111 | //-------------------------------------------------------------------- 112 | const T* row_ptr(int, int y, unsigned) const { 113 | return m_start + y * m_stride; 114 | } 115 | const T* row_ptr(int y) const { 116 | return m_start + y * m_stride; 117 | } 118 | 119 | private: 120 | //-------------------------------------------------------------------- 121 | const T* m_buf; // Pointer to renrdering buffer 122 | unsigned m_width; // Width in pixels 123 | unsigned m_height; // Height in pixels 124 | int m_stride; // Number of bytes per row. Can be < 0 125 | const T* m_start; // Pointer to first pixel depending on stride 126 | }; 127 | 128 | typedef row_accessor_ro rendering_buffer_ro; 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /src/resource-manager.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_RESOURCE_MANAGER_H 2 | #define AGGPLOT_RESOURCE_MANAGER_H 3 | 4 | class manage_owner { 5 | public: 6 | template 7 | static void acquire(T* p) { }; 8 | 9 | template 10 | static void dispose(T* p) { 11 | delete p; 12 | }; 13 | }; 14 | 15 | class manage_not_owner { 16 | public: 17 | template 18 | static void acquire(T* p) { }; 19 | 20 | template 21 | static void dispose(T* p) { }; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/sg_marker.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_SG_MARKER_H 2 | #define AGGPLOT_SG_MARKER_H 3 | 4 | #include "agg_conv_transform.h" 5 | #include "agg_trans_affine.h" 6 | 7 | #include "sg_object.h" 8 | #include "markers.h" 9 | #include "utils.h" 10 | 11 | typedef agg::conv_transform conv_type; 12 | 13 | namespace draw { 14 | 15 | class marker_a : public sg_adapter { 16 | 17 | public: 18 | marker_a(double x, double y, sg_object* sym, double size): 19 | sg_adapter(sym, m_trans), 20 | m_trans(size), m_symbol(sym), m_x(x), m_y(y) 21 | { 22 | // the following is needed to adjust the approximation_scale of the 23 | // symbol 24 | m_symbol->apply_transform(identity_matrix, size); 25 | } 26 | 27 | virtual void apply_transform(const agg::trans_affine& m, double as) 28 | { 29 | double *tx = &m_trans.tx, *ty = &m_trans.ty; 30 | *tx = m_x; 31 | *ty = m_y; 32 | m.transform(tx, ty); 33 | } 34 | 35 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) 36 | { 37 | *x1 = *x2 = m_x; 38 | *y1 = *y2 = m_y; 39 | } 40 | 41 | protected: 42 | agg::trans_affine_scaling m_trans; 43 | sg_object* m_symbol; 44 | double m_x, m_y; 45 | }; 46 | 47 | class marker : public marker_a { 48 | public: 49 | marker(double x, double y, sg_object* s, double sz) : marker_a(x, y, s, sz) {} 50 | ~marker() { 51 | delete m_symbol; 52 | } 53 | }; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/sg_object.h: -------------------------------------------------------------------------------- 1 | 2 | /* sg_object.h 3 | * 4 | * Copyright (C) 2009, 2010 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef AGGPLOT_SG_OBJECT_H 22 | #define AGGPLOT_SG_OBJECT_H 23 | 24 | #include "agg_trans_affine.h" 25 | #include "agg_bounding_rect.h" 26 | #include "agg_conv_transform.h" 27 | #include "agg_rendering_buffer.h" 28 | #include "agg_scanline_u.h" 29 | #include "agg_rasterizer_scanline_aa.h" 30 | 31 | #include "pixel_fmt.h" 32 | #include "draw_svg.h" 33 | #include "utils.h" 34 | #include "resource-manager.h" 35 | #include "strpp.h" 36 | 37 | struct vertex_source { 38 | virtual void rewind(unsigned path_id) = 0; 39 | virtual unsigned vertex(double* x, double* y) = 0; 40 | virtual ~vertex_source() { } 41 | }; 42 | 43 | // Scalable Graphics Object 44 | struct sg_object : public vertex_source { 45 | 46 | virtual void apply_transform(const agg::trans_affine& m, double as) = 0; 47 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) = 0; 48 | 49 | virtual bool affine_compose(agg::trans_affine& m) { 50 | return false; 51 | } 52 | 53 | virtual str write_svg(int id, agg::rgba8 c, double h) { 54 | str path; 55 | svg_property_list* ls = this->svg_path(path, h); 56 | str s = svg_fill_path(path, id, c, ls); 57 | svg_property_list::free(ls); 58 | return s; 59 | } 60 | 61 | virtual svg_property_list* svg_path(str& s, double h) { 62 | svg_coords_from_vs(this, s, h); 63 | return 0; 64 | } 65 | 66 | virtual ~sg_object() { } 67 | }; 68 | 69 | struct approx_scale { 70 | template static void approximation_scale(T& obj, double as) 71 | { 72 | obj.approximation_scale(as); 73 | } 74 | }; 75 | 76 | struct no_approx_scale { 77 | template static void approximation_scale(T& obj, double as) { } 78 | }; 79 | 80 | template 81 | class sg_object_gen : public sg_object { 82 | protected: 83 | VertexSource m_base; 84 | 85 | public: 86 | sg_object_gen(): m_base() {} 87 | 88 | template sg_object_gen(InitType& i) : m_base(i) { } 89 | 90 | template 91 | sg_object_gen(InitType1& i1, InitType2& i2) : m_base(i1, i2) { } 92 | 93 | virtual void rewind(unsigned path_id) { 94 | m_base.rewind(path_id); 95 | } 96 | virtual unsigned vertex(double* x, double* y) { 97 | return m_base.vertex(x, y); 98 | } 99 | 100 | virtual void apply_transform(const agg::trans_affine& m, double as) 101 | { 102 | ApproxManager::approximation_scale(m_base, as); 103 | } 104 | 105 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) 106 | { 107 | agg::bounding_rect_single(m_base, 0, x1, y1, x2, y2); 108 | } 109 | 110 | const VertexSource& self() const { 111 | return m_base; 112 | }; 113 | VertexSource& self() { 114 | return m_base; 115 | }; 116 | }; 117 | 118 | /* this class does create an sg_object obtained combining an an AGG 119 | transformation like conv_stroke, conv_dash or any other transform 120 | with a sg_object source. This adapter implements therefore the 121 | virtual methods from the sg_object abstract class */ 122 | template 123 | class sg_adapter : public sg_object { 124 | protected: 125 | ConvType m_output; 126 | sg_object* m_source; 127 | 128 | public: 129 | sg_adapter(sg_object* src): m_output(*src), m_source(src) { } 130 | 131 | template 132 | sg_adapter(sg_object* src, InitType& val): m_output(*src, val), m_source(src) 133 | { } 134 | 135 | virtual ~sg_adapter() { } 136 | 137 | virtual void rewind(unsigned path_id) { 138 | m_output.rewind(path_id); 139 | } 140 | virtual unsigned vertex(double* x, double* y) { 141 | return m_output.vertex(x, y); 142 | } 143 | 144 | virtual void apply_transform(const agg::trans_affine& m, double as) 145 | { 146 | ApproxManager::approximation_scale(m_output, as); 147 | this->m_source->apply_transform(m, as); 148 | } 149 | 150 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) 151 | { 152 | this->m_source->bounding_box(x1, y1, x2, y2); 153 | } 154 | 155 | const ConvType& self() const { 156 | return m_output; 157 | }; 158 | ConvType& self() { 159 | return m_output; 160 | }; 161 | }; 162 | 163 | /* This class add a scaling transformation to an object. The scaling 164 | transfomation is an affine transform that adapt to the size of the 165 | canvas where the object is drawn. */ 166 | template 167 | class sg_object_scaling : public sg_object 168 | { 169 | sg_object* m_source; 170 | agg::conv_transform m_trans; 171 | 172 | public: 173 | sg_object_scaling(sg_object* src, agg::trans_affine& mtx=identity_matrix): 174 | m_source(src), m_trans(*m_source, mtx) 175 | { 176 | ResourceManager::acquire(m_source); 177 | } 178 | 179 | virtual ~sg_object_scaling() { 180 | ResourceManager::dispose(m_source); 181 | } 182 | 183 | virtual void rewind(unsigned path_id) { 184 | m_trans.rewind(path_id); 185 | } 186 | virtual unsigned vertex(double* x, double* y) { 187 | return m_trans.vertex(x, y); 188 | } 189 | 190 | virtual void apply_transform(const agg::trans_affine& m, double as) 191 | { 192 | m_trans.transformer(m); 193 | m_source->apply_transform (m, as * m.scale()); 194 | } 195 | 196 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) 197 | { 198 | agg::bounding_rect_single (*m_source, 0, x1, y1, x2, y2); 199 | } 200 | }; 201 | 202 | template 203 | class sg_object_ref : public sg_object { 204 | public: 205 | sg_object_ref(sg_object* src) : m_source(src) 206 | { 207 | ResourceManager::acquire(this->m_source); 208 | } 209 | 210 | virtual ~sg_object_ref() { 211 | ResourceManager::dispose(this->m_source); 212 | } 213 | 214 | virtual void rewind(unsigned path_id) { 215 | this->m_source->rewind(path_id); 216 | } 217 | 218 | virtual unsigned vertex(double* x, double* y) { 219 | return this->m_source->vertex(x, y); 220 | } 221 | 222 | virtual void apply_transform(const agg::trans_affine& m, double as) { 223 | this->m_source->apply_transform(m, as); 224 | } 225 | 226 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) { 227 | this->m_source->bounding_box(x1, y1, x2, y2); 228 | } 229 | 230 | virtual str write_svg(int id, agg::rgba8 c, double h) { 231 | return this->m_source->write_svg(id, c, h); 232 | } 233 | 234 | virtual svg_property_list* svg_path(str& s, double h) { 235 | return this->m_source->svg_path(s, h); 236 | } 237 | 238 | virtual bool affine_compose(agg::trans_affine& m) { 239 | return this->m_source->affine_compose(m); 240 | } 241 | 242 | private: 243 | sg_object* m_source; 244 | }; 245 | 246 | #endif 247 | -------------------------------------------------------------------------------- /src/shared_vector.h: -------------------------------------------------------------------------------- 1 | #ifndef CPPUTILS_SHARED_VECTOR_H 2 | #define CPPUTILS_SHARED_VECTOR_H 3 | 4 | #include "pthreadpp.h" 5 | #include "agg_array.h" 6 | 7 | template 8 | class shared_vector : public agg::pod_bvector 9 | { 10 | public: 11 | shared_vector(): agg::pod_bvector() { } 12 | 13 | void lock() { m_mutex.lock(); } 14 | void unlock() { m_mutex.unlock(); } 15 | 16 | private: 17 | agg::pod_bvector m_data; 18 | pthread::mutex m_mutex; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/split-parser.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_SPLIT_PARSER_H 2 | #define AGGPLOT_SPLIT_PARSER_H 3 | 4 | #include "tree.h" 5 | 6 | enum direction_e { along_x, along_y }; 7 | 8 | template 9 | class split { 10 | 11 | typedef tree::node node_type; 12 | 13 | public: 14 | // ----------------------------------------------------string_lexer 15 | class lexer { 16 | const char *m_content; 17 | const char *m_ptr; 18 | 19 | public: 20 | lexer(const char *str) : m_content(str), m_ptr(m_content) {}; 21 | 22 | char next() 23 | { 24 | char c = *m_ptr; 25 | if (c != '\0') 26 | m_ptr++; 27 | return c; 28 | }; 29 | 30 | void push() 31 | { 32 | if (m_ptr > m_content) 33 | m_ptr--; 34 | }; 35 | 36 | bool checknext(char reqchar) 37 | { 38 | char c = *m_ptr; 39 | if (c == reqchar) 40 | { 41 | m_ptr++; 42 | return true; 43 | } 44 | return false; 45 | }; 46 | }; 47 | 48 | // ------------------------------------------------parser: exprlist 49 | static node_type* exprlist (lexer& lex, direction_e dir) 50 | { 51 | typedef tree::tree_node tree_type; 52 | 53 | tree_type *t = new tree_type(dir); 54 | 55 | while (true) 56 | { 57 | node_type* child = parse(lex); 58 | if (! child) 59 | break; 60 | t->add(child); 61 | } 62 | 63 | return t; 64 | } 65 | 66 | // ------------------------------------------------parser: parse 67 | static node_type* parse (lexer& lex) 68 | { 69 | char t = lex.next(); 70 | 71 | switch (t) 72 | { 73 | case '.': 74 | return new tree::leaf(); 75 | case 'h': 76 | return exprlist(lex, along_x); 77 | case 'v': 78 | return exprlist(lex, along_y); 79 | case '(': 80 | { 81 | node_type *nd = parse(lex); 82 | if (! lex.checknext(')')) 83 | return 0; 84 | return nd; 85 | } 86 | case ')': 87 | lex.push(); 88 | return 0; 89 | default: 90 | return 0; 91 | } 92 | 93 | return 0; 94 | } 95 | }; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/str.c: -------------------------------------------------------------------------------- 1 | 2 | /* str.c -- A C library for string manipulation 3 | * 4 | * Copyright (C) 2009-2013 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #define _GNU_SOURCE 1 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "str.h" 28 | 29 | static inline size_t 30 | str_sz_round (size_t sz) 31 | { 32 | #define MINSIZE (1 << 4) 33 | size_t res = MINSIZE; 34 | 35 | while (res < sz) 36 | { 37 | res *= 2; 38 | /* integer overflow ? */ 39 | assert (res > 0); 40 | } 41 | 42 | return res; 43 | } 44 | 45 | static inline void 46 | str_init_raw (str_ptr s, size_t len) 47 | { 48 | s->size = str_sz_round (len+1); 49 | s->heap = malloc (s->size); 50 | } 51 | 52 | void 53 | str_init (str_ptr s, int len) 54 | { 55 | if (len < 0) 56 | len = 0; 57 | 58 | str_init_raw (s, (size_t)len); 59 | s->heap[0] = 0; 60 | s->length = 0; 61 | } 62 | 63 | str_ptr 64 | str_new (void) 65 | { 66 | str_ptr s = malloc (sizeof(str_t)); 67 | str_init_raw (s, 16); 68 | s->heap[0] = 0; 69 | s->length = 0; 70 | return s; 71 | } 72 | 73 | void 74 | str_free (str_ptr s) 75 | { 76 | if (s->size > 0) 77 | free (s->heap); 78 | s->heap = 0; 79 | } 80 | 81 | static void 82 | str_init_from_c_raw (str_ptr s, const char *sf, size_t len) 83 | { 84 | str_init_raw (s, len); 85 | memcpy (s->heap, sf, len+1); 86 | s->length = len; 87 | } 88 | 89 | void 90 | str_init_from_c (str_ptr s, const char *sf) 91 | { 92 | size_t len = strlen (sf); 93 | str_init_from_c_raw (s, sf, len); 94 | } 95 | 96 | void 97 | str_init_from_str (str_ptr s, const str_t sf) 98 | { 99 | str_init_from_c_raw (s, CSTR(sf), STR_LENGTH(sf)); 100 | } 101 | 102 | void 103 | str_size_check (str_t s, size_t reqlen) 104 | { 105 | char *old_heap; 106 | 107 | if (reqlen+1 < s->size) 108 | return; 109 | 110 | old_heap = (s->size > 0 ? s->heap : NULL); 111 | str_init_raw (s, reqlen); 112 | 113 | if (old_heap) 114 | { 115 | memcpy (s->heap, old_heap, s->length+1); 116 | free (old_heap); 117 | } 118 | } 119 | 120 | void 121 | str_copy (str_t d, const str_t s) 122 | { 123 | const size_t len = s->length; 124 | str_size_check (d, len); 125 | memcpy (d->heap, s->heap, len+1); 126 | d->length = len; 127 | } 128 | 129 | void 130 | str_copy_c (str_t d, const char *s) 131 | { 132 | const size_t len = strlen (s); 133 | str_size_check (d, len); 134 | memcpy (d->heap, s, len+1); 135 | d->length = len; 136 | } 137 | 138 | void 139 | str_copy_c_substr (str_t d, const char *s, int len) 140 | { 141 | len = (len >= 0 ? len : 0); 142 | str_size_check (d, (size_t)len); 143 | memcpy (d->heap, s, (size_t)len); 144 | d->heap[len] = 0; 145 | d->length = len; 146 | } 147 | 148 | void 149 | str_append_c (str_t to, const char *from, int sep) 150 | { 151 | size_t flen = strlen (from); 152 | int use_sep = (sep != 0 && to->length > 0); 153 | size_t newlen = STR_LENGTH(to) + flen + (use_sep ? 1 : 0); 154 | int idx = STR_LENGTH(to); 155 | 156 | str_size_check (to, newlen); 157 | 158 | if (use_sep) 159 | to->heap[idx++] = sep; 160 | 161 | memcpy (to->heap + idx, from, flen+1); 162 | to->length = newlen; 163 | } 164 | 165 | void 166 | str_append (str_t to, const str_t from, int sep) 167 | { 168 | str_append_c (to, CSTR(from), sep); 169 | } 170 | 171 | void 172 | str_trunc (str_t s, int len) 173 | { 174 | if (len < 0 || (size_t)len >= STR_LENGTH(s)) 175 | return; 176 | 177 | s->heap[len] = 0; 178 | s->length = len; 179 | } 180 | 181 | void 182 | str_get_basename (str_t to, const str_t from, int dirsep) 183 | { 184 | const char * ptr = strrchr (CSTR(from), dirsep); 185 | 186 | if (ptr == NULL) 187 | str_copy_c (to, CSTR(from)); 188 | else 189 | str_copy_c (to, ptr + 1); 190 | } 191 | 192 | void 193 | str_dirname (str_t to, const str_t from, int dirsep) 194 | { 195 | const char * ptr = strrchr (CSTR(from), dirsep); 196 | 197 | if (ptr == NULL) 198 | str_copy_c (to, CSTR(from)); 199 | else 200 | str_copy_c_substr (to, CSTR(from), ptr - CSTR(from)); 201 | } 202 | 203 | int 204 | str_getline (str_t d, FILE *f) 205 | { 206 | char *res, *ptr; 207 | int szres, pending = 0; 208 | 209 | str_size_check (d, 0); 210 | str_trunc (d, 0); 211 | 212 | for (;;) 213 | { 214 | int j; 215 | 216 | ptr = d->heap + d->length; 217 | szres = d->size - d->length; 218 | 219 | res = fgets (ptr, szres, f); 220 | 221 | if (res == NULL) 222 | { 223 | if (feof (f) && pending) 224 | return 0; 225 | return (-1); 226 | } 227 | 228 | for (j = 0; j < szres; j++) 229 | { 230 | if (ptr[j] == '\n' || ptr[j] == 0) 231 | { 232 | ptr[j] = 0; 233 | d->length += j; 234 | break; 235 | } 236 | } 237 | 238 | if (j < szres - 1) 239 | break; 240 | 241 | pending = 1; 242 | 243 | str_size_check (d, 2 * d->length); 244 | } 245 | 246 | if (d->length > 0) 247 | { 248 | if (d->heap[d->length - 1] == '\015') 249 | { 250 | d->heap[d->length - 1] = 0; 251 | d->length --; 252 | } 253 | } 254 | 255 | return 0; 256 | } 257 | 258 | void 259 | str_vprintf (str_t d, const char *fmt, int append, va_list ap) 260 | { 261 | #define STR_BUFSIZE 64 262 | char buffer[STR_BUFSIZE]; 263 | char *xbuf; 264 | int xbuf_size; 265 | int ns; 266 | va_list aq; 267 | 268 | va_copy (aq, ap); 269 | 270 | ns = vsnprintf (buffer, STR_BUFSIZE, fmt, ap); 271 | 272 | if (ns >= STR_BUFSIZE) 273 | { 274 | xbuf_size = ns+1; 275 | xbuf = malloc (xbuf_size); 276 | vsnprintf (xbuf, xbuf_size, fmt, aq); 277 | } 278 | else 279 | { 280 | xbuf = buffer; 281 | xbuf_size = 0; 282 | } 283 | 284 | va_end (aq); 285 | 286 | if (append) 287 | { 288 | str_append_c (d, xbuf, 0); 289 | if (xbuf_size > 0) 290 | free (xbuf); 291 | } 292 | else 293 | { 294 | if (xbuf_size > 0) 295 | { 296 | free (d->heap); 297 | d->heap = xbuf; 298 | d->size = xbuf_size; 299 | d->length = ns; 300 | } 301 | else 302 | { 303 | str_copy_c_substr (d, xbuf, ns); 304 | } 305 | } 306 | #undef STR_BUFSIZE 307 | } 308 | 309 | void 310 | str_printf (str_t d, const char *fmt, ...) 311 | { 312 | va_list ap; 313 | va_start (ap, fmt); 314 | str_vprintf (d, fmt, 0, ap); 315 | va_end (ap); 316 | } 317 | 318 | void 319 | str_printf_add (str_t d, const char *fmt, ...) 320 | { 321 | va_list ap; 322 | va_start (ap, fmt); 323 | str_vprintf (d, fmt, 1, ap); 324 | va_end (ap); 325 | } 326 | 327 | void 328 | str_pad (str_t s, int len, char sep) 329 | { 330 | int diff = len - s->length; 331 | 332 | if (diff <= 0) 333 | return; 334 | 335 | str_size_check (s, (size_t)len-1); 336 | 337 | memmove (s->heap + diff, s->heap, (s->length + 1) * sizeof(char)); 338 | memset (s->heap, sep, diff * sizeof(char)); 339 | 340 | s->length += diff; 341 | } 342 | 343 | -------------------------------------------------------------------------------- /src/str.h: -------------------------------------------------------------------------------- 1 | 2 | /* str.h -- A C library for string manipulation 3 | * 4 | * Copyright (C) 2009-2013 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef STR_H 22 | #define STR_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "defs.h" 29 | 30 | __BEGIN_DECLS 31 | 32 | struct _str { 33 | char *heap; 34 | size_t size; 35 | size_t length; 36 | }; 37 | 38 | typedef struct _str str_t[1]; 39 | typedef struct _str *str_ptr; 40 | typedef struct _str const *const_str_ptr; 41 | 42 | #define STR_PTR_FREE(s) { \ 43 | str_free (s); \ 44 | free (s); \ 45 | (s) = NULL; \ 46 | } 47 | #define STR_LENGTH(s) ((s)->length) 48 | #define CSTR(s) ((const char *) (s)->heap) 49 | #define str_set_null(s) str_trunc(s, 0); 50 | #define str_is_null(s) ((s)->length == 0) 51 | 52 | 53 | extern str_ptr str_new (void); 54 | extern void str_init (str_ptr s, int len); 55 | extern void str_free (str_ptr s); 56 | extern void str_size_check (str_t s, size_t reqlen); 57 | extern void str_init_from_c (str_ptr s, const char *sf); 58 | extern void str_init_from_str (str_ptr s, const str_t sf); 59 | extern void str_copy (str_t d, const str_t s); 60 | extern void str_copy_c (str_t d, const char *s); 61 | extern void str_copy_c_substr (str_t d, const char *s, int len); 62 | extern void str_append_c (str_t to, const char *from, int sep); 63 | extern void str_append (str_t to, const str_t from, int sep); 64 | extern void str_trunc (str_t s, int len); 65 | extern void str_get_basename (str_t to, const str_t from, int dirsep); 66 | extern void str_dirname (str_t to, const str_t from, int dirsep); 67 | extern int str_getline (str_t d, FILE *f); 68 | extern void str_printf (str_t d, const char *fmt, ...); 69 | extern void str_printf_add (str_t d, const char *fmt, ...); 70 | extern void str_vprintf (str_t d, const char *fmt, int append, 71 | va_list ap); 72 | extern void str_pad (str_t d, int len, char sep); 73 | 74 | __END_DECLS 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/strpp.h: -------------------------------------------------------------------------------- 1 | #ifndef STRPP_H 2 | #define STRPP_H 3 | 4 | #include "str.h" 5 | 6 | class str : public _str { 7 | public: 8 | str(int sz = 64) { str_init(this, sz); } 9 | str(const char *s) { str_init_from_c(this, s); } 10 | str(const str& s) { str_init_from_str(this, &s); } 11 | 12 | ~str() { str_free(this); } 13 | 14 | const str& operator= (const str& s) 15 | { 16 | str_copy(this, &s); 17 | return *this; 18 | } 19 | 20 | const str& operator= (const char* s) 21 | { 22 | str_copy_c(this, s); 23 | return *this; 24 | } 25 | 26 | const char* cstr() const { return CSTR(this); } 27 | unsigned len() const { return this->length; } 28 | 29 | char operator [] (unsigned j) const { return (j < len() ? heap[j] : 0); } 30 | 31 | void append(const str& s, int sep = 0) { str_append(this, &s, sep); } 32 | void append(const char* s, int sep = 0) { str_append_c(this, s, sep); } 33 | 34 | void printf(const char* fmt, ...) { 35 | va_list ap; 36 | va_start (ap, fmt); 37 | str_vprintf (this, fmt, 0, ap); 38 | va_end (ap); 39 | } 40 | 41 | void printf_add(const char* fmt, ...) { 42 | va_list ap; 43 | va_start (ap, fmt); 44 | str_vprintf (this, fmt, 1, ap); 45 | va_end (ap); 46 | } 47 | 48 | static str print(const char* fmt, ...) { 49 | va_list ap; 50 | va_start (ap, fmt); 51 | str s; 52 | str_vprintf (&s, fmt, 0, ap); 53 | va_end (ap); 54 | return s; 55 | } 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/text-shape.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_TEXT_SHAPE_H 2 | #define AGGPLOT_TEXT_SHAPE_H 3 | 4 | #include "text_label.h" 5 | #include "sg_object.h" 6 | 7 | namespace draw { 8 | 9 | class text_shape : public sg_object { 10 | public: 11 | text_shape(double x, double y, const char* text, 12 | double _size = 10.0, double hjustif = 0.0, double vjustif = 0.0): 13 | m_text_label(text, round(_size)), m_x(x), m_y(y), m_font_size(_size), m_size(_size) 14 | { 15 | m_matrix.tx = m_x; 16 | m_matrix.ty = m_y; 17 | m_text_label.model_mtx(m_matrix); 18 | compute_bounding_box(); 19 | } 20 | 21 | virtual void rewind(unsigned path_id) 22 | { 23 | m_text_label.rewind(0.0, 0.0); 24 | } 25 | 26 | virtual unsigned vertex(double* x, double* y) 27 | { 28 | return m_text_label.vertex(x, y); 29 | } 30 | 31 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) 32 | { 33 | *x1 = m_bbox.x1; 34 | *y1 = m_bbox.y1; 35 | *x2 = m_bbox.x2; 36 | *y2 = m_bbox.y2; 37 | } 38 | 39 | void compute_bounding_box() 40 | { 41 | const double pad = 1.0; 42 | const double tx = m_matrix.tx, ty = m_matrix.ty; 43 | m_bbox.x1 = tx - pad; 44 | m_bbox.y1 = ty - pad; 45 | m_bbox.x2 = tx + m_text_label.get_text_width() + pad; 46 | m_bbox.y2 = ty + m_text_label.get_text_height() + pad; 47 | } 48 | 49 | virtual str write_svg(int id, agg::rgba8 c, double h) 50 | { 51 | const str& text = m_text_label.text(); 52 | double txt_size = m_size; 53 | 54 | const agg::trans_affine& m = m_matrix; 55 | 56 | double x = m.tx, y = m.ty; 57 | 58 | str s = str::print("" \ 60 | " %s" \ 61 | "", 62 | x, svg_y_coord(y, h), id, int(txt_size), id, text.cstr()); 63 | 64 | return s; 65 | } 66 | 67 | virtual void apply_transform(const agg::trans_affine& m, double as) 68 | { 69 | m_text_label.font_size(m.sx * m_font_size, round(m.sy * m_font_size)); 70 | 71 | double x = m_x, y = m_y; 72 | m.transform(&x, &y); 73 | m_matrix.tx = x; 74 | m_matrix.ty = y; 75 | 76 | m_text_label.approximation_scale(m.scale()); 77 | } 78 | 79 | private: 80 | text_label m_text_label; 81 | double m_x, m_y; 82 | double m_font_size; 83 | agg::trans_affine m_matrix; 84 | double m_size; 85 | agg::rect_base m_bbox; 86 | }; 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/text.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "agg_rendering_buffer.h" 3 | #include "agg_rasterizer_scanline_aa.h" 4 | #include "agg_pixfmt_rgb.h" 5 | #include "agg_trans_affine.h" 6 | 7 | #include "text.h" 8 | 9 | namespace draw { 10 | 11 | void 12 | text::apply_transform(const agg::trans_affine& m, double as) 13 | { 14 | double x = m_x, y = m_y; 15 | m.transform(&x, &y); 16 | m_matrix.tx = x; 17 | m_matrix.ty = round(y); 18 | } 19 | 20 | void 21 | text::bounding_box(double *x1, double *y1, double *x2, double *y2) 22 | { 23 | *x1 = *x2 = m_x; 24 | *y1 = *y2 = m_y; 25 | } 26 | 27 | str 28 | text::write_svg(int id, agg::rgba8 c, double h) 29 | { 30 | const agg::trans_affine& m = m_matrix; 31 | 32 | const double eps = 1.0e-6; 33 | str s; 34 | 35 | const str& content = m_text_label.text(); 36 | if (str_is_null(&content)) 37 | return s; 38 | 39 | str style; 40 | int hjust = lrint(m_hjustif * 2.0); 41 | if (hjust == 1) 42 | style.append(";text-anchor:middle"); 43 | else if (hjust >= 2) 44 | style.append(";text-anchor:end"); 45 | 46 | if (c.r != 0 || c.g != 0 || c.b != 0) { 47 | char rgbstr[8]; 48 | format_rgb(rgbstr, 8, c); 49 | style.printf_add(";fill:%s", rgbstr); 50 | } 51 | 52 | bool need_rotate = !is_unit_matrix(m, eps); 53 | 54 | int txt_size = text_height(); 55 | 56 | double x = 0.0, y = - m_vjustif * text_height() * 1.2; 57 | 58 | if (!need_rotate) { 59 | x = x + m.tx; 60 | y = svg_y_coord(y + m.ty, h); 61 | } else { 62 | y = -y; 63 | } 64 | 65 | const char* cont = get_text(); 66 | str txt = str::print("" \ 68 | " %s" \ 69 | "", 70 | x, y, id, txt_size, style.cstr(), 71 | id, cont); 72 | 73 | if (need_rotate) { 74 | s = str::print("%s", 75 | m.sx, m.shx, m.shy, m.sy, m.tx, svg_y_coord(m.ty, h), 76 | txt.cstr()); 77 | } else { 78 | s = txt; 79 | } 80 | 81 | return s; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/text.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_TEXT_H 2 | #define AGGPLOT_TEXT_H 3 | 4 | #include "agg_trans_affine.h" 5 | 6 | #include "sg_object.h" 7 | #include "text_label.h" 8 | 9 | namespace draw { 10 | 11 | class text : public sg_object 12 | { 13 | agg::trans_affine m_matrix; 14 | 15 | double m_x, m_y; 16 | double m_angle; 17 | 18 | double m_hjustif; 19 | double m_vjustif; 20 | 21 | text_label m_text_label; 22 | 23 | public: 24 | text(const char* text, double size = 10.0, double hjustif = 0.0, double vjustif = 0.0): 25 | m_x(0.0), m_y(0.0), m_angle(0.0), 26 | m_hjustif(hjustif), m_vjustif(vjustif), m_text_label(text, round(size)) 27 | { 28 | m_text_label.model_mtx(m_matrix); 29 | } 30 | 31 | virtual void rewind(unsigned path_id) 32 | { 33 | m_text_label.rewind(m_hjustif, m_vjustif); 34 | } 35 | 36 | virtual unsigned vertex(double* x, double* y) 37 | { 38 | return m_text_label.vertex(x, y); 39 | } 40 | 41 | void angle(double th) 42 | { 43 | double c = cos(th), s = sin(th); 44 | 45 | m_angle = th; 46 | 47 | m_matrix.sx = c; 48 | m_matrix.shx = -s; 49 | m_matrix.shy = s; 50 | m_matrix.sy = c; 51 | } 52 | 53 | double angle() const { 54 | return m_angle; 55 | }; 56 | 57 | const char * get_text() const { 58 | return m_text_label.text().cstr(); 59 | } 60 | 61 | double text_height() const { 62 | return m_text_label.get_text_height(); 63 | } 64 | 65 | void set_point(double x, double y) 66 | { 67 | m_x = x; 68 | m_y = y; 69 | 70 | m_matrix.tx = m_x; 71 | m_matrix.ty = m_y; 72 | } 73 | 74 | void hjustif(double hj) { 75 | m_hjustif = hj; 76 | } 77 | void vjustif(double vj) { 78 | m_vjustif = vj; 79 | } 80 | 81 | virtual void apply_transform(const agg::trans_affine& m, double as); 82 | virtual void bounding_box(double *x1, double *y1, double *x2, double *y2); 83 | 84 | virtual str write_svg(int id, agg::rgba8 c, double h); 85 | }; 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/text_label.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_TEXT_LABEL_H 2 | #define AGGPLOT_TEXT_LABEL_H 3 | 4 | #include "agg_trans_affine.h" 5 | #include "agg_conv_transform.h" 6 | #include "agg_conv_stroke.h" 7 | #include "agg_conv_curve.h" 8 | #include "agg_renderer_scanline.h" 9 | #include "agg_font_freetype.h" 10 | 11 | #include "fonts.h" 12 | #include "sg_object.h" 13 | 14 | struct grid_fit_y_only { 15 | static void adjust(double& x, double& y) { 16 | y = round(y); 17 | } 18 | }; 19 | 20 | typedef grid_fit_y_only grid_fit; 21 | 22 | class text_label 23 | { 24 | enum { scale_x = 100 }; 25 | 26 | typedef agg::font_engine_freetype_int32 font_engine_type; 27 | typedef agg::font_cache_manager font_manager_type; 28 | 29 | str m_text_buf; 30 | 31 | double m_width; 32 | double m_font_height; 33 | double m_font_width; 34 | 35 | unsigned m_pos; 36 | double m_x, m_y; 37 | double m_advance_x, m_advance_y; 38 | 39 | font_engine_type& m_font_eng; 40 | font_manager_type& m_font_man; 41 | 42 | const agg::trans_affine* m_model_mtx; 43 | agg::trans_affine m_text_mtx; 44 | agg::conv_curve m_text_curve; 45 | agg::conv_transform > m_text_trans; 46 | 47 | public: 48 | text_label(const char* text, double size): 49 | m_text_buf(text), m_font_height(size), m_font_width(size), 50 | m_font_eng(font_engine()), m_font_man(font_manager()), 51 | m_model_mtx(&identity_matrix), 52 | m_text_curve(m_font_man.path_adaptor()), m_text_trans(m_text_curve, m_text_mtx) 53 | { 54 | update_font_size(); 55 | m_width = get_text_width(); 56 | } 57 | 58 | void model_mtx(const agg::trans_affine& m) { 59 | m_model_mtx = &m; 60 | } 61 | 62 | void font_size(double height, double width) 63 | { 64 | m_font_height = height; 65 | m_font_width = width; 66 | } 67 | 68 | const str& text() const { 69 | return m_text_buf; 70 | } 71 | 72 | bool load_glyph() 73 | { 74 | m_x += m_advance_x; 75 | m_y += m_advance_y; 76 | 77 | if (m_pos >= m_text_buf.len()) 78 | return false; 79 | 80 | char c = m_text_buf[m_pos]; 81 | const agg::glyph_cache *glyph = m_font_man.glyph(c); 82 | m_font_man.add_kerning(&m_x, &m_y); 83 | m_font_man.init_embedded_adaptors(glyph, 0, 0); 84 | 85 | if(glyph->data_type == agg::glyph_data_outline) 86 | { 87 | agg::trans_affine& m = m_text_mtx; 88 | 89 | m.tx = m_x / scale_x; 90 | m.ty = m_y; 91 | m_model_mtx->transform(&m.tx, &m.ty); 92 | 93 | if (fabs(m.sx * m.sy) > fabs(m.shx * m.shy)) 94 | grid_fit::adjust(m.tx, m.ty); 95 | else 96 | grid_fit::adjust(m.ty, m.tx); 97 | 98 | m_advance_x = glyph->advance_x; 99 | m_advance_y = glyph->advance_y; 100 | 101 | return true; 102 | } 103 | 104 | return false; 105 | } 106 | 107 | void rewind(double hjustif, double vjustif) 108 | { 109 | m_x = scale_x * (- hjustif * m_width); 110 | m_y = - 0.86 * vjustif * m_font_height; 111 | m_advance_x = 0; 112 | m_advance_y = 0; 113 | m_pos = 0; 114 | 115 | m_text_mtx = (*m_model_mtx); 116 | agg::trans_affine_scaling scale_mtx(1.0 / double(scale_x), 1.0); 117 | trans_affine_compose (m_text_mtx, scale_mtx); 118 | 119 | update_font_size(); 120 | load_glyph(); 121 | } 122 | 123 | unsigned vertex(double* x, double* y) 124 | { 125 | unsigned cmd = m_text_trans.vertex(x, y); 126 | if (agg::is_stop(cmd)) 127 | { 128 | m_pos++; 129 | if (load_glyph()) 130 | { 131 | return vertex(x, y); 132 | } 133 | return agg::path_cmd_stop; 134 | } 135 | return cmd; 136 | } 137 | 138 | void approximation_scale(double as) { 139 | m_text_curve.approximation_scale(as); 140 | } 141 | 142 | double get_text_height() const { 143 | return m_font_height; 144 | } 145 | 146 | double get_text_width() 147 | { 148 | unsigned text_length = m_text_buf.len(); 149 | double x = 0, y = 0; 150 | 151 | const char* text = m_text_buf.cstr(); 152 | for (const char* p = text; p < text + text_length; p++) 153 | { 154 | const agg::glyph_cache* glyph = m_font_man.glyph(*p); 155 | 156 | if (glyph) 157 | { 158 | m_font_man.add_kerning(&x, &y); 159 | x += glyph->advance_x; 160 | } 161 | } 162 | 163 | return x / double(scale_x); 164 | } 165 | 166 | private: 167 | void update_font_size() 168 | { 169 | m_font_eng.height(m_font_height); 170 | m_font_eng.width(m_font_width * scale_x); 171 | } 172 | }; 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /src/tree.h: -------------------------------------------------------------------------------- 1 | #ifndef CPP_TREE_H 2 | #define CPP_TREE_H 3 | 4 | #include "list.h" 5 | 6 | namespace tree { 7 | 8 | template 9 | struct node { 10 | virtual list* tree() { return 0; }; 11 | virtual list* tree(tree_data_type& data) { return 0; }; 12 | 13 | virtual base_type* content() = 0; 14 | virtual void content(const base_type& src) = 0; 15 | 16 | virtual ~node() {}; 17 | }; 18 | 19 | template 20 | class leaf : public node { 21 | base_type m_content; 22 | 23 | public: 24 | leaf() : m_content() {}; 25 | 26 | virtual base_type* content() { return &m_content; }; 27 | virtual void content(const base_type& src) { m_content = src; }; 28 | }; 29 | 30 | template 31 | class tree_node : public node { 32 | 33 | typedef node node_type; 34 | typedef list node_list; 35 | 36 | node_list *m_head; 37 | tree_data_type m_data; 38 | 39 | public: 40 | tree_node() : m_head(0), m_data() {}; 41 | 42 | template 43 | tree_node(const init_type& init_val) : m_head(0), m_data(init_val) {}; 44 | 45 | ~tree_node() 46 | { 47 | node_list *n; 48 | for (node_list *p = m_head; p; p = n) 49 | { 50 | n = p->next(); 51 | delete p->content(); 52 | delete p; 53 | } 54 | }; 55 | 56 | virtual node_list* tree() { return m_head; }; 57 | virtual node_list* tree(tree_data_type& data) 58 | { 59 | data = m_data; 60 | return m_head; 61 | }; 62 | 63 | virtual base_type* content() { return 0; }; 64 | virtual void content(const base_type& src) { }; 65 | 66 | void add(node_type* child) 67 | { 68 | node_list *t = new node_list(child); 69 | m_head = node_list::push_back(m_head, t); 70 | } 71 | }; 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/units.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* units.cpp 3 | * 4 | * Copyright (C) 2009, 2010 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "utils.h" 25 | #include "units.h" 26 | #include "printf_check.h" 27 | 28 | void units::init(double yinf, double ysup, double spacefact) 29 | { 30 | double del; 31 | 32 | if (ysup == yinf) 33 | ysup = yinf + 1.0; 34 | 35 | del = (ysup - yinf) / spacefact; 36 | 37 | order = (int) floor(log10(del)); 38 | 39 | double expf = pow(10, order); 40 | double delr = del / expf; 41 | 42 | if (5 <= delr) 43 | m_major = 5; 44 | else if (2 <= delr) 45 | m_major = 2; 46 | else 47 | m_major = 1; 48 | 49 | m_inf = (int) floor(yinf / (m_major * expf) + 1e-5); 50 | m_sup = (int) ceil (ysup / (m_major * expf) - 1e-5); 51 | 52 | nb_decimals = (order < 0 ? -order : 0); 53 | 54 | dmajor = m_major * expf; 55 | } 56 | 57 | void units::mark_label (char *lab, unsigned size, int mark) const 58 | { 59 | bool minus = (m_inf < 0); 60 | int asup = (minus ? -m_inf : m_sup); 61 | char fmt[16]; 62 | 63 | if (size < 16) 64 | return; 65 | 66 | if (nb_decimals == 0) 67 | { 68 | snprintf (lab, size, "%.0f", mark * dmajor); 69 | lab[size-1] = '\0'; 70 | } 71 | else 72 | { 73 | int dec = (nb_decimals < 10 ? nb_decimals : 9); 74 | int base = (int) floor(asup * dmajor); 75 | int space = dec + (base > 0 ? (int)log10(base): 0) + 1 \ 76 | + (minus ? 1 : 0) + 1; 77 | snprintf (fmt, 16, "%%%i.%if", space, dec); 78 | fmt[15] = '\0'; 79 | snprintf (lab, size, fmt, mark * dmajor); 80 | lab[size-1] = '\0'; 81 | } 82 | } 83 | 84 | double units::mark_scale (double x) 85 | { 86 | double xinf = m_inf * dmajor, xsup = m_sup * dmajor; 87 | return (x - xinf) / (xsup - xinf); 88 | } 89 | 90 | void units::fmt_label(char* label, unsigned size, format_e tag, const char* fmt, int mark) const 91 | { 92 | double val = mark_value(mark); 93 | switch (tag) 94 | { 95 | case format_int: 96 | { 97 | unsigned nchars = snprintf(label, size, fmt, int(val)); 98 | if (nchars >= size) 99 | label[size-1] = 0; 100 | break; 101 | } 102 | case format_float: 103 | { 104 | unsigned nchars = snprintf(label, size, fmt, val); 105 | if (nchars >= size) 106 | label[size-1] = 0; 107 | break; 108 | } 109 | default: 110 | memcpy(label, "*", 2); 111 | } 112 | } 113 | 114 | units::format_e units::parse_label_format(const char* fmt) 115 | { 116 | if (strlen(fmt) >= label_format_max_size) 117 | return format_invalid; 118 | 119 | arg_type_e arg_type; 120 | const char* tail; 121 | int n = check_printf_argument(fmt, tail, arg_type); 122 | if (n != 1) 123 | return format_invalid; 124 | else 125 | { 126 | const char* tt; 127 | arg_type_e aa; 128 | if (check_printf_argument(tail, tt, aa) != 0) 129 | return format_invalid; 130 | } 131 | 132 | return (arg_type == argument_int ? format_int : format_float); 133 | } 134 | -------------------------------------------------------------------------------- /src/units.h: -------------------------------------------------------------------------------- 1 | 2 | /* units.h 3 | * 4 | * Copyright (C) 2009, 2010 Francesco Abbate 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef AGGPLOT_UNITS_H 22 | #define AGGPLOT_UNITS_H 23 | 24 | struct label_iterator { 25 | virtual bool next(double& val, const char*& text) = 0; 26 | virtual ~label_iterator() {} 27 | }; 28 | 29 | class units { 30 | private: 31 | int m_major; 32 | int order; 33 | double dmajor; // equal to (m_major * 10^order) 34 | int m_inf, m_sup; // expressed in the base of (m_major * 10^order) 35 | int nb_decimals; 36 | 37 | void init(double min, double max, double spacefact); 38 | 39 | public: 40 | enum { label_format_max_size = 16 }; 41 | enum format_e { format_int, format_float, format_invalid }; 42 | 43 | units(): m_major(1), order(0), dmajor(1), m_inf(0), m_sup(1), nb_decimals(0) {}; 44 | units (double min, double max, double spacefact = 4.0) 45 | { 46 | init(min, max, spacefact); 47 | }; 48 | 49 | int begin() const { 50 | return m_inf; 51 | }; 52 | int end() const { 53 | return m_sup; 54 | }; 55 | 56 | void limits(int &start, int &fin, double &step) 57 | { 58 | start = m_inf; 59 | fin = m_sup; 60 | step = dmajor; 61 | }; 62 | 63 | void mark_label (char *label, unsigned size, int mark) const; 64 | void fmt_label(char* label, unsigned size, format_e tag, const char* fmt, int mark) const; 65 | double mark_value (int mark) const { 66 | return dmajor * mark; 67 | }; 68 | double mark_scale(double x); 69 | 70 | static format_e parse_label_format(const char* fmt); 71 | }; 72 | 73 | class units_iterator : public label_iterator { 74 | public: 75 | units_iterator(const units& u, units::format_e tag, const char* fmt): 76 | m_units(u), m_fmt_tag(tag), m_fmt(fmt) 77 | { 78 | m_index = u.begin(); 79 | } 80 | 81 | virtual bool next(double& val, const char*& text) 82 | { 83 | if (m_index > m_units.end()) 84 | return false; 85 | 86 | if (m_fmt) 87 | m_units.fmt_label(m_buffer, 32, m_fmt_tag, m_fmt, m_index); 88 | else 89 | m_units.mark_label(m_buffer, 32, m_index); 90 | 91 | val = m_units.mark_value(m_index); 92 | text = m_buffer; 93 | m_index ++; 94 | return true; 95 | } 96 | 97 | private: 98 | char m_buffer[32]; 99 | int m_index; 100 | const units& m_units; 101 | units::format_e m_fmt_tag; 102 | const char* m_fmt; 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | agg::trans_affine identity_matrix; 4 | 5 | /* Mnemonic: a.premultiply(b) means a * b in terms of matrix multiplication */ 6 | 7 | void 8 | trans_affine_compose (agg::trans_affine& a, const agg::trans_affine& b) 9 | { 10 | double a_tx = a.tx, a_ty = a.ty; 11 | 12 | a.premultiply(b); 13 | 14 | a.tx = b.sx * a_tx + b.shx * a_ty + b.tx; 15 | a.ty = b.shy * a_tx + b.sy * a_ty + b.ty; 16 | } 17 | 18 | agg::trans_affine affine_matrix(const agg::rect_i& r) 19 | { 20 | double w = r.x2 - r.x1, h = r.y2 - r.y1; 21 | double tx = r.x1, ty = r.y1; 22 | return agg::trans_affine(w, 0.0, 0.0, h, tx, ty); 23 | } 24 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_UTILS_H 2 | #define AGGPLOT_UTILS_H 3 | 4 | #include "agg_trans_affine.h" 5 | #include "agg_array.h" 6 | 7 | #ifdef min 8 | #undef min 9 | #endif 10 | 11 | #ifdef max 12 | #undef max 13 | #endif 14 | 15 | 16 | template 17 | T min(T a, T b) 18 | { 19 | return (a < b) ? a : b; 20 | }; 21 | 22 | template 23 | T max(T a, T b) 24 | { 25 | return (a > b) ? a : b; 26 | }; 27 | 28 | template 29 | class ptr_list { 30 | public: 31 | ~ptr_list() { 32 | clear(); 33 | } 34 | 35 | void add(T* p) { 36 | m_list.add(p); 37 | } 38 | 39 | T* operator [] (unsigned k) const { 40 | return m_list[k]; 41 | } 42 | 43 | T* at(unsigned k) const { 44 | return m_list[k]; 45 | } 46 | 47 | unsigned size() const { 48 | return m_list.size(); 49 | } 50 | 51 | void clear() 52 | { 53 | unsigned n = m_list.size(); 54 | for (unsigned k = 0; k < n; k++) 55 | delete m_list[k]; 56 | m_list.clear(); 57 | } 58 | 59 | private: 60 | agg::pod_bvector m_list; 61 | }; 62 | 63 | inline bool is_unit_matrix(const agg::trans_affine& m, double eps = 1.0e-5) 64 | { 65 | return (fabs(m.sx - 1.0) < eps && fabs(m.shx) < eps && 66 | fabs(m.shy) < eps && fabs(m.sy - 1.0) < eps); 67 | } 68 | 69 | extern void trans_affine_compose (agg::trans_affine& a, 70 | const agg::trans_affine& b); 71 | 72 | extern agg::trans_affine affine_matrix(const agg::rect_i& r); 73 | 74 | extern agg::trans_affine identity_matrix; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/window-cpp.h: -------------------------------------------------------------------------------- 1 | 2 | extern "C" { 3 | #include "lua.h" 4 | } 5 | 6 | #include "window.h" 7 | #include "lua-graph.h" 8 | #include "canvas-window-cpp.h" 9 | #include "resource-manager.h" 10 | #include "lua-plot-cpp.h" 11 | #include "lua-cpp-utils.h" 12 | #include "plot.h" 13 | #include "rect.h" 14 | #include "list.h" 15 | 16 | #include "agg_color_rgba.h" 17 | #include "agg_trans_affine.h" 18 | #include "split-parser.h" 19 | 20 | class window : public canvas_window { 21 | public: 22 | int window_id; 23 | 24 | typedef agg::trans_affine bmatrix; 25 | 26 | struct ref { 27 | typedef tree::node node; 28 | 29 | sg_plot* plot; 30 | int slot_id; 31 | 32 | plot_render_info inf; 33 | bmatrix matrix; 34 | 35 | unsigned char *layer_buf; 36 | agg::rendering_buffer layer_img; 37 | 38 | bool valid_rect; 39 | opt_rect dirty_rect; 40 | 41 | ref(sg_plot* p = 0) 42 | : plot(p), matrix(), layer_buf(0), valid_rect(true), dirty_rect() 43 | {}; 44 | 45 | ~ref() { delete[] layer_buf; } 46 | 47 | void dispose_buffer() 48 | { 49 | valid_rect = false; 50 | delete[] layer_buf; 51 | layer_buf = 0; 52 | } 53 | 54 | void save_image (agg::rendering_buffer& winbuf, agg::rect_base& r, 55 | int bpp, bool flip_y); 56 | 57 | static void compose(bmatrix& a, const bmatrix& b); 58 | static int calculate(node *t, const bmatrix& m, int id); 59 | }; 60 | 61 | private: 62 | void draw_slot_by_ref(ref& ref, bool dirty); 63 | void refresh_slot_by_ref(ref& ref, bool draw_all); 64 | void cleanup_tree_rec (lua_State *L, int window_index, ref::node* n); 65 | 66 | static ref *ref_lookup (ref::node *p, int slot_id); 67 | 68 | template 69 | void plot_apply_rec(Function& f, ref::node* n); 70 | 71 | ref::node* m_tree; 72 | 73 | public: 74 | window(agg::rgba8 bgcol= colors::white): 75 | canvas_window(bgcol), m_tree(0) 76 | { 77 | this->split("."); 78 | } 79 | 80 | ~window() { delete m_tree; } 81 | 82 | template void plot_apply(Function& f) { this->plot_apply_rec(f, m_tree); } 83 | 84 | bool split(const char *spec); 85 | int attach(sg_plot *plot, const char *spec); 86 | void draw_slot(int slot_id, bool update_req); 87 | void refresh_slot(int slot_id); 88 | void start(lua_State *L, gslshell::ret_status& st); 89 | 90 | void save_slot_image(int slot_id); 91 | void restore_slot_image(int slot_id); 92 | 93 | void draw_slot(int slot_id); 94 | 95 | virtual void on_draw(); 96 | virtual void on_resize(int sx, int sy); 97 | 98 | private: 99 | struct slot_draw_function 100 | { 101 | slot_draw_function(window* w): win(w) { } 102 | void call(window::ref* ref) { win->draw_slot_by_ref(*ref, false); } 103 | window* win; 104 | }; 105 | 106 | struct dispose_buffer_function { 107 | void call(window::ref* ref) { ref->dispose_buffer(); } 108 | }; 109 | }; 110 | -------------------------------------------------------------------------------- /src/window.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_WINDOW_H 2 | #define AGGPLOT_WINDOW_H 3 | 4 | #include 5 | 6 | #include "defs.h" 7 | 8 | __BEGIN_DECLS 9 | 10 | #include "lua.h" 11 | 12 | extern int window_slot_update (lua_State *L); 13 | extern int window_slot_refresh (lua_State *L); 14 | extern int window_save_slot_image (lua_State *L); 15 | extern int window_restore_slot_image (lua_State *L); 16 | extern int window_update (lua_State *L); 17 | extern int window_new (lua_State *L); 18 | extern int window_show (lua_State *L); 19 | extern int window_attach (lua_State *L); 20 | extern int window_close (lua_State *L); 21 | extern int window_close_wait (lua_State *L); 22 | extern int window_wait (lua_State *L); 23 | 24 | extern void natwin_register (lua_State *L); 25 | 26 | __END_DECLS 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/window_hooks.h: -------------------------------------------------------------------------------- 1 | #ifndef AGGPLOT_WINDOW_HOOKS_H 2 | #define AGGPLOT_WINDOW_HOOKS_H 3 | 4 | #include 5 | 6 | #include "defs.h" 7 | 8 | __BEGIN_DECLS 9 | 10 | #include "lua.h" 11 | 12 | struct window_hooks { 13 | int (*create)(lua_State* L); 14 | int (*show)(lua_State* L); 15 | int (*attach)(lua_State* L); 16 | int (*update)(lua_State* L); 17 | int (*refresh)(lua_State* L); 18 | int (*close)(lua_State* L); 19 | int (*wait)(lua_State* L); 20 | int (*save_image)(lua_State* L); 21 | int (*restore_image)(lua_State* L); 22 | }; 23 | 24 | extern struct window_hooks *app_window_hooks; 25 | 26 | __END_DECLS 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/window_registry.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "lua-defs.h" 3 | #include "window_registry.h" 4 | 5 | /* The "windows' references" is a Lua table whose keys are windows and whose values 6 | are tables of plots indexed by their slot id. 7 | For example: 8 | 9 | {[] = {[1] = }, [] = {[1] = , [3] = }}. 10 | 11 | The table with plots can contain holes. */ 12 | static char const * const refs_tname = "GSL.oirfs.wp"; 13 | 14 | /* A Lua table with a list of the active windows (it can contain holes). 15 | The index of each window is its "window id". */ 16 | static char const * const registry_tname = "GSL.reg.wins"; 17 | 18 | void 19 | window_registry_prepare (lua_State *L) 20 | { 21 | lua_newtable (L); 22 | lua_setfield (L, LUA_REGISTRYINDEX, registry_tname); 23 | 24 | lua_newtable (L); 25 | lua_setfield (L, LUA_REGISTRYINDEX, refs_tname); 26 | } 27 | 28 | int 29 | window_index_add(lua_State *L, int index) 30 | { 31 | INDEX_SET_ABS(L, index); 32 | 33 | lua_getfield (L, LUA_REGISTRYINDEX, registry_tname); 34 | 35 | #ifdef GRAPH_TK_USE_LUA54 36 | int n = lua_rawlen (L, -1); 37 | #else 38 | int n = lua_objlen (L, -1); 39 | #endif 40 | 41 | lua_pushvalue (L, index); 42 | lua_rawseti (L, -2, n+1); 43 | lua_pop (L, 1); 44 | 45 | return n+1; 46 | } 47 | 48 | void 49 | window_index_get (lua_State *L, int id) 50 | { 51 | lua_getfield (L, LUA_REGISTRYINDEX, registry_tname); 52 | lua_rawgeti (L, -1, id); 53 | lua_remove (L, -2); 54 | } 55 | 56 | void 57 | window_index_remove (lua_State *L, int id) 58 | { 59 | lua_getfield (L, LUA_REGISTRYINDEX, registry_tname); 60 | lua_getfield (L, LUA_REGISTRYINDEX, refs_tname); 61 | lua_rawgeti (L, -2, id); 62 | if (! lua_isnil (L, -1)) 63 | { 64 | lua_pushnil (L); 65 | lua_rawset (L, -3); 66 | lua_pop (L, 1); 67 | } 68 | else 69 | { 70 | lua_pop (L, 2); 71 | } 72 | 73 | lua_pushnil (L); 74 | lua_rawseti (L, -2, id); 75 | lua_pop (L, 1); 76 | } 77 | 78 | void 79 | window_index_apply_all (lua_State *L, lua_CFunction f) 80 | { 81 | lua_getfield (L, LUA_REGISTRYINDEX, registry_tname); 82 | 83 | lua_pushnil (L); /* first key */ 84 | while (lua_next(L, -2) != 0) 85 | { 86 | lua_pushcfunction (L, f); 87 | lua_insert (L, -2); 88 | lua_call (L, 1, 0); 89 | } 90 | 91 | lua_pop (L, 1); 92 | } 93 | 94 | int 95 | window_index_count (lua_State *L) 96 | { 97 | int count = 0; 98 | 99 | lua_getfield (L, LUA_REGISTRYINDEX, registry_tname); 100 | 101 | lua_pushnil (L); /* first key */ 102 | while (lua_next(L, -2) != 0) 103 | { 104 | lua_pop (L, 1); 105 | count ++; 106 | } 107 | 108 | lua_pop (L, 1); 109 | 110 | return count; 111 | } 112 | 113 | /* Removes the closed windows from the windows' list and from the reference 114 | table. 115 | 116 | A C function should be given in the top of the stack. The function 117 | take a window as argument and return a boolean. If it does returns 118 | true the windows will be removed. */ 119 | void 120 | window_index_remove_fun(lua_State *L) 121 | { 122 | lua_getfield(L, LUA_REGISTRYINDEX, refs_tname); 123 | lua_getfield(L, LUA_REGISTRYINDEX, registry_tname); 124 | lua_pushnil(L); 125 | while (lua_next(L, -2) != 0) { 126 | int i = lua_tointeger(L, -2); 127 | lua_pushvalue(L, -5); /* Push the C function. */ 128 | lua_pushvalue(L, -2); /* Push the Window, can be nil. */ 129 | lua_call(L, 1, 1); 130 | int remove = lua_toboolean(L, -1); 131 | lua_pop(L, 1); 132 | if (remove) { 133 | lua_pushnil(L); 134 | lua_rawset(L, -5); /* Set the reference to Window to nil. */ 135 | lua_pushnil(L); 136 | lua_rawseti(L, -3, i); /* Eliminate the window from the list. */ 137 | } else { 138 | lua_pop(L, 1); 139 | } 140 | } 141 | lua_pop(L, 3); /* Pop the reference tables, the windows list and the function. */ 142 | } 143 | 144 | void 145 | window_refs_add (lua_State *L, int index, int key_index, int value_index) 146 | { 147 | INDEX_SET_ABS_2(L, key_index, value_index); 148 | 149 | lua_getfield (L, LUA_REGISTRYINDEX, refs_tname); 150 | lua_pushvalue (L, key_index); 151 | lua_rawget (L, -2); 152 | 153 | if (lua_isnil (L, -1)) 154 | { 155 | lua_pop (L, 1); 156 | lua_newtable (L); 157 | lua_pushvalue (L, key_index); 158 | lua_pushvalue (L, -2); 159 | lua_rawset (L, -4); 160 | } 161 | 162 | lua_pushvalue (L, value_index); 163 | lua_rawseti (L, -2, index); 164 | 165 | lua_pop (L, 2); 166 | } 167 | 168 | void 169 | window_refs_remove (lua_State *L, int index, int key_index) 170 | { 171 | INDEX_SET_ABS(L, key_index); 172 | 173 | lua_getfield (L, LUA_REGISTRYINDEX, refs_tname); 174 | lua_pushvalue (L, key_index); 175 | lua_rawget (L, -2); 176 | 177 | if (! lua_isnil (L, -1)) 178 | { 179 | lua_pushnil (L); 180 | lua_rawseti (L, -2, index); 181 | } 182 | 183 | lua_pop (L, 2); 184 | } 185 | 186 | void 187 | window_refs_lookup_apply (lua_State *L, int value_index, lua_CFunction func) 188 | { 189 | INDEX_SET_ABS(L, value_index); 190 | 191 | lua_getfield (L, LUA_REGISTRYINDEX, refs_tname); 192 | lua_pushnil (L); 193 | 194 | while (lua_next (L, -2) != 0) 195 | { 196 | lua_pushnil (L); 197 | 198 | while (lua_next (L, -2) != 0) 199 | { 200 | if (lua_rawequal (L, -1, value_index)) 201 | { 202 | lua_pushcfunction (L, func); 203 | lua_pushvalue (L, -5); 204 | lua_pushvalue (L, -4); 205 | lua_call (L, 2, 0); 206 | } 207 | lua_pop (L, 1); 208 | } 209 | 210 | lua_pop (L, 1); 211 | } 212 | 213 | lua_pop (L, 1); 214 | } 215 | -------------------------------------------------------------------------------- /src/window_registry.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_REGISTRY_H 2 | #define WINDOW_REGISTRY_H 3 | 4 | #include "defs.h" 5 | 6 | __BEGIN_DECLS 7 | 8 | #include "lua.h" 9 | #include "lauxlib.h" 10 | 11 | extern void window_registry_prepare (lua_State *L); 12 | 13 | extern int window_index_add (lua_State *L, int index); 14 | extern void window_index_get (lua_State *L, int id); 15 | extern void window_index_remove (lua_State *L, int id); 16 | extern void window_index_apply_all (lua_State *L, lua_CFunction f); 17 | extern int window_index_count (lua_State *L); 18 | extern void window_index_remove_fun(lua_State *L); 19 | 20 | extern void window_refs_add (lua_State *L, int index, int key_index, 21 | int value_index); 22 | extern void window_refs_remove (lua_State *L, int index, int key_index); 23 | extern void window_refs_lookup_apply (lua_State *L, int value_index, 24 | lua_CFunction func); 25 | 26 | __END_DECLS 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /subprojects/libagg.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory = libagg 3 | url = https://github.com/franko/agg 4 | revision = v2.4-lhelper5 5 | --------------------------------------------------------------------------------