[osm-gps-map] 01/153: Imported Upstream version 0.3
Ross Gammon
ross-guest at moszumanska.debian.org
Tue May 13 19:58:55 UTC 2014
This is an automated email from the git hooks/post-receive script.
ross-guest pushed a commit to branch master
in repository osm-gps-map.
commit 53f4134256c905c57d34353b73a24a10d1c72c7b
Author: David Paleino <dapal at debian.org>
Date: Sun Dec 13 08:43:58 2009 +0100
Imported Upstream version 0.3
---
.gitignore | 32 +
AUTHORS | 3 +
ChangeLog | 18 +
Makefile.am | 38 +
NEWS | 0
README | 7 +
TODO.tasks | 6 +
autogen.sh | 159 ++++
configure.ac | 43 +
openstreetmap-gps-map.anjuta | 44 +
osmgpsmap.pc.in | 11 +
python/AUTHORS | 1 +
python/ChangeLog | 0
python/Makefile.am | 36 +
python/NEWS | 0
python/README | 23 +
python/acinclude.m4 | 66 ++
python/configure.ac | 66 ++
python/osmgpsmap.defs | 194 ++++
python/osmgpsmap.override | 198 ++++
python/osmgpsmapmodule.c | 64 ++
python/setup.py | 36 +
python/test.sh | 23 +
src/Makefile.am | 46 +
src/converter.c | 102 ++
src/converter.h | 45 +
src/main.c | 361 +++++++
src/osm-gps-map-types.h | 85 ++
src/osm-gps-map.c | 2171 ++++++++++++++++++++++++++++++++++++++++++
src/osm-gps-map.h | 103 ++
src/poi.png | Bin 0 -> 1093 bytes
31 files changed, 3981 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb87dc4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+*~
+*.in
+*.la
+*.lo
+*.o
+*.deps/
+*.libs/
+INSTALL
+Makefile
+autom4te.cache/
+compile
+config.guess
+config.h
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+osmgpsmap.pc
+python/COPYING
+python/INSTALL
+python/autom4te.cache/
+python/build/
+python/configure
+python/osmgpsmap.c
+src/Makefile
+src/openstreetmap-gps-map
+stamp-h1
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7490d31
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Marcus Bauer 2008 <marcus.bauer at gmail.com>
+John Stowers 2009 <john.stowers at gmail.com>
+Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..c9b8f0e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,18 @@
+2007-12-28 Johannes Schmid,,, <jhs at idefix>
+
+ reviewed by: <delete if not using a buddy>
+
+ * project.anjuta:
+
+2007-12-23 Johannes Schmid,,, <jhs at idefix>
+
+ reviewed by: <delete if not using a buddy>
+
+ * src/Makefile.am.tpl:
+
+2007-12-23 Johannes Schmid,,, <jhs at idefix>
+
+ reviewed by: <delete if not using a buddy>
+
+ * src/Makefile.am.tpl:
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..ebe57ee
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to produce Makefile.in
+## Created by Anjuta
+
+SUBDIRS = src
+
+openstreetmap_gps_mapdocdir = ${prefix}/doc/openstreetmap-gps-map
+openstreetmap_gps_mapdoc_DATA = \
+ README \
+ COPYING \
+ AUTHORS \
+ ChangeLog \
+ INSTALL \
+ NEWS
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = osmgpsmap.pc
+
+EXTRA_DIST = $(openstreetmap_gps_mapdoc_DATA) \
+ osmgpsmap.pc.in \
+ python/Makefile.am \
+ python/Makefile.in \
+ python/acinclude.m4 \
+ python/ChangeLog \
+ python/osmgpsmap.defs \
+ python/setup.py \
+ python/aclocal.m4 \
+ python/configure \
+ python/osmgpsmapmodule.c \
+ python/test.sh \
+ python/AUTHORS \
+ python/configure.ac \
+ python/osmgpsmap.override \
+ python/NEWS \
+ python/README
+
+release:
+ scp @PACKAGE at -@VERSION at .tar.gz john at open.grcnz.com:/srv/default/downloads/osm-gps-map/
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644
index 0000000..1adfa96
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+OSM-GPS-MAP is a Gtk mapping widget (and Python bindings) that when given
+GPS co-ordinates, draws a GPS track, and points of interest on a moving map
+display.
+
+OSM-GPS-MAP Downloads map data from a number of websites, including
+openstreetmap.org, openaerialmap.org and others and can be used to build
+desktop mapping or geolocation applications.
diff --git a/TODO.tasks b/TODO.tasks
new file mode 100644
index 0000000..d1fa282
--- /dev/null
+++ b/TODO.tasks
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<gtodo>
+ <category title="Personal" place="0"/>
+ <category title="Business" place="1"/>
+ <category title="Unfiled" place="2"/>
+</gtodo>
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..9ab346a
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,159 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+DIE=0
+
+if [ -n "$GNOME2_DIR" ]; then
+ ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS"
+ LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH"
+ PATH="$GNOME2_DIR/bin:$PATH"
+ export PATH
+ export LD_LIBRARY_PATH
+fi
+
+(test -f $srcdir/configure.ac) || {
+ echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+ echo " top-level package directory"
+ exit 1
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`autoconf' installed."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(grep "^IT_PROG_INTLTOOL" $srcdir/configure.ac >/dev/null) && {
+ (intltoolize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`intltool' installed."
+ echo "You can get it from:"
+ echo " ftp://ftp.gnome.org/pub/GNOME/"
+ DIE=1
+ }
+}
+
+(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.ac >/dev/null) && {
+ (xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`xml-i18n-toolize' installed."
+ echo "You can get it from:"
+ echo " ftp://ftp.gnome.org/pub/GNOME/"
+ DIE=1
+ }
+}
+
+(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
+ (libtool --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`libtool' installed."
+ echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+ }
+}
+
+(grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.ac >/dev/null) && {
+ (grep "sed.*POTFILES" $srcdir/configure.ac) > /dev/null || \
+ (glib-gettextize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`glib' installed."
+ echo "You can get it from: ftp://ftp.gtk.org/pub/gtk"
+ DIE=1
+ }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`automake' installed."
+ echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+ NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: Missing \`aclocal'. The version of \`automake'"
+ echo "installed doesn't appear recent enough."
+ echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+if test -z "$*"; then
+ echo "**Warning**: I am going to run \`configure' with no arguments."
+ echo "If you wish to pass any to it, please specify them on the"
+ echo \`$0\'" command line."
+ echo
+fi
+
+case $CC in
+xlc )
+ am_opt=--include-deps;;
+esac
+
+for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print`
+do
+ dr=`dirname $coin`
+ if test -f $dr/NO-AUTO-GEN; then
+ echo skipping $dr -- flagged as no auto-gen
+ else
+ echo processing $dr
+ ( cd $dr
+
+ aclocalinclude="$ACLOCAL_FLAGS"
+
+ if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then
+ echo "Creating $dr/aclocal.m4 ..."
+ test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+ echo "Running glib-gettextize... Ignore non-fatal messages."
+ echo "no" | glib-gettextize --force --copy
+ echo "Making $dr/aclocal.m4 writable ..."
+ test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+ fi
+ if grep "^IT_PROG_INTLTOOL" configure.ac >/dev/null; then
+ echo "Running intltoolize..."
+ intltoolize --copy --force --automake
+ fi
+ if grep "^AM_PROG_XML_I18N_TOOLS" configure.ac >/dev/null; then
+ echo "Running xml-i18n-toolize..."
+ xml-i18n-toolize --copy --force --automake
+ fi
+ if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
+ if test -z "$NO_LIBTOOLIZE" ; then
+ echo "Running libtoolize..."
+ libtoolize --force --copy
+ fi
+ fi
+ echo "Running aclocal $aclocalinclude ..."
+ aclocal $aclocalinclude
+ if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
+ echo "Running autoheader..."
+ autoheader
+ fi
+ echo "Running automake --gnu $am_opt ..."
+ automake --add-missing --gnu $am_opt
+ echo "Running autoconf ..."
+ autoconf
+ )
+ fi
+done
+
+conf_flags="--enable-maintainer-mode"
+
+if test x$NOCONFIGURE = x; then
+ echo Running $srcdir/configure $conf_flags "$@" ...
+ $srcdir/configure $conf_flags "$@" \
+ && echo Now type \`make\' to compile. || exit 1
+else
+ echo Skipping configure process.
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..0eb98c2
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,43 @@
+AC_INIT(osm-gps-map, 0.2)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AC_CONFIG_SRCDIR(osmgpsmap.pc.in)
+AM_CONFIG_HEADER(config.h)
+
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+AM_PROG_LIBTOOL
+
+PKG_CHECK_MODULES(OPENSTREETMAP_GPS_MAP, [gtk+-2.0 libsoup-2.4 glib-2.0 >= 2.18])
+AC_SUBST(OPENSTREETMAP_GPS_MAP_CFLAGS)
+AC_SUBST(OPENSTREETMAP_GPS_MAP_LIBS)
+
+AC_ARG_ENABLE(cairo,
+ [AC_HELP_STRING([--disable-cairo],
+ [Use Gdk instead of cairo to draw the map overlay])],
+ enable_cairo="$enableval",
+ enable_cairo="yes")
+
+if test "x$enable_cairo" = "xyes"; then
+ PKG_CHECK_MODULES(CAIRO,[cairo >= 1.8])
+ AC_DEFINE(USE_CAIRO, 1, [Define if we're using cairo])
+ OPENSTREETMAP_GPS_MAP_CFLAGS="$OPENSTREETMAP_GPS_MAP_CFLAGS $CAIRO_CFLAGS"
+ OPENSTREETMAP_GPS_MAP_LIBS="$OPENSTREETMAP_GPS_MAP_LIBS $CAIRO_LIBS"
+fi
+
+AC_OUTPUT([
+osmgpsmap.pc
+Makefile
+src/Makefile
+])
+
+echo
+echo $PACKAGE v$VERSION
+echo
+echo Prefix............... : $prefix
+echo cairo................ : $enable_cairo
diff --git a/openstreetmap-gps-map.anjuta b/openstreetmap-gps-map.anjuta
new file mode 100644
index 0000000..51ddd65
--- /dev/null
+++ b/openstreetmap-gps-map.anjuta
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<anjuta>
+ <plugin name="GBF Project Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaProjectManager"/>
+ <require group="Project"
+ attribute="Supported-Project-Types"
+ value="automake"/>
+ </plugin>
+ <plugin name="Symbol Browser"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaSymbolManager"/>
+ </plugin>
+ <plugin name="Make Build System"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaBuildable"/>
+ <require group="Build"
+ attribute="Supported-Build-Types"
+ value="make"/>
+ </plugin>
+ <plugin name="Task Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaTodo"/>
+ </plugin>
+ <plugin name="Debug Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaDebuggerManager"/>
+ </plugin>
+</anjuta>
diff --git a/osmgpsmap.pc.in b/osmgpsmap.pc.in
new file mode 100644
index 0000000..92db45c
--- /dev/null
+++ b/osmgpsmap.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE_NAME@
+Description: Moving map widget using openstreet map data
+Version: @PACKAGE_VERSION@
+Requires: gtk+-2.0 libsoup-2.4
+Libs: -L${libdir} -losmgpsmap
+Cflags: -I${includedir}/osmgpsmap
diff --git a/python/AUTHORS b/python/AUTHORS
new file mode 100644
index 0000000..c3a0b22
--- /dev/null
+++ b/python/AUTHORS
@@ -0,0 +1 @@
+John Stowers 2008 <john.stowers at gmail.com>
diff --git a/python/ChangeLog b/python/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/python/Makefile.am b/python/Makefile.am
new file mode 100644
index 0000000..20d13ff
--- /dev/null
+++ b/python/Makefile.am
@@ -0,0 +1,36 @@
+defsdir = $(datadir)/pygtk/2.0/defs
+defs_DATA = osmgpsmap.defs
+
+INCLUDES = \
+ $(OSMGPSMAP_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(PYGTK_CFLAGS) \
+ $(PYTHON_INCLUDES)
+
+pkgpythondir = $(pyexecdir)/gtk-2.0
+pkgpyexecdir = $(pyexecdir)/gtk-2.0
+
+pkgpyexec_LTLIBRARIES = osmgpsmap.la
+osmgpsmap_la_LDFLAGS = -module -avoid-version -export-symbols-regex initosmgpsmap
+osmgpsmap_la_LIBADD = $(OSMGPSMAP_LIBS) $(GTK_LIBS) $(PYGTK_LIBS)
+osmgpsmap_la_SOURCES = osmgpsmapmodule.c osmgpsmap.c
+#nodist_osmgpsmap_la_SOURCES = osmgpsmap.c
+
+CLEANFILES = osmgpsmap.c
+EXTRA_DIST = osmgpsmap.override $(defs_DATA)
+
+osmgpsmap.c: osmgpsmap.defs osmgpsmap.override
+.defs.c:
+ (cd $(srcdir)\
+ && pygtk-codegen-2.0 \
+ --register $(PYGTK_DEFSDIR)/gtk-types.defs \
+ --register $(PYGTK_DEFSDIR)/gdk-base-types.defs \
+ --override $*.override \
+ --prefix py$* $*.defs) > gen-$*.c \
+ && cp gen-$*.c $*.c \
+ && rm -f gen-$*.c
+
+update-defs:
+ $(PYGTK_H2DEF) ../src/osm-gps-map.h > osmgpsmap-new.defs
+
+
diff --git a/python/NEWS b/python/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/python/README b/python/README
new file mode 100644
index 0000000..4959c7b
--- /dev/null
+++ b/python/README
@@ -0,0 +1,23 @@
+How to Build Windows Installers
+0) Make sure that mingw32 is selected as the compiler. Create (or edit) a .cfg file for distutils (distutils.cfg)
+
+ eg: C:\Python25\Lib\distutils\distutils.cfg with this content:
+
+ [build]
+ compiler=mingw32
+
+
+1) Make sure Python is in path
+
+ $ echo $PATH
+ .:/usr/local/bin:/mingw/bin:/bin:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem:/c/Program Files/Altium Designer 6/System:/c/Program Files/TortoiseSVN/bin:/c/gtk/bin:/c/Python25
+
+2) Make sure the pygobject/pygtk headers and libs can be found
+
+ $ export PKG_CONFIG_PATH=/c/Python25/Lib/pkgconfig/
+ $ pkg-config.exe --libs pygobject-2.0
+ @FFI_LIBS@ -Lc:/Python25/lib -Lc:/gtk/lib -lgobject-2.0 -lglib-2.0 -lint
+
+3) Build the windows installer
+
+ $ python setup.py bdist_wininst
diff --git a/python/acinclude.m4 b/python/acinclude.m4
new file mode 100644
index 0000000..fe90156
--- /dev/null
+++ b/python/acinclude.m4
@@ -0,0 +1,66 @@
+## this one is commonly used with AM_PATH_PYTHONDIR ...
+dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
+dnl Check if a module containing a given symbol is visible to python.
+AC_DEFUN([AM_CHECK_PYMOD],
+[AC_REQUIRE([AM_PATH_PYTHON])
+py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
+AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
+ifelse([$2],[], [prog="
+import sys
+try:
+ import $1
+except ImportError:
+ sys.exit(1)
+except:
+ sys.exit(0)
+sys.exit(0)"], [prog="
+import $1
+$1.$2"])
+if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
+ then
+ eval "py_cv_mod_$py_mod_var=yes"
+ else
+ eval "py_cv_mod_$py_mod_var=no"
+ fi
+])
+py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
+if test "x$py_val" != xno; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], [],, [$3
+])dnl
+else
+ AC_MSG_RESULT(no)
+ ifelse([$4], [],, [$4
+])dnl
+fi
+])
+
+dnl a macro to check for ability to create python extensions
+dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_INCLUDES
+AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
+[AC_REQUIRE([AM_PATH_PYTHON])
+AC_MSG_CHECKING(for headers required to compile python extensions)
+dnl deduce PYTHON_INCLUDES
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
+if test -x "$PYTHON-config"; then
+PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null`
+else
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+if test "$py_prefix" != "$py_exec_prefix"; then
+ PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
+fi
+fi
+AC_SUBST(PYTHON_INCLUDES)
+dnl check if the headers exist:
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
+AC_TRY_CPP([#include <Python.h>],dnl
+[AC_MSG_RESULT(found)
+$1],dnl
+[AC_MSG_RESULT(not found)
+$2])
+CPPFLAGS="$save_CPPFLAGS"
+])
diff --git a/python/configure.ac b/python/configure.ac
new file mode 100644
index 0000000..385c2b5
--- /dev/null
+++ b/python/configure.ac
@@ -0,0 +1,66 @@
+AC_PREREQ(2.53)
+AC_INIT(osmgpsmap-python, 0.1)
+AC_CONFIG_SRCDIR(osmgpsmap.defs)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AM_MAINTAINER_MODE
+AC_PROG_MAKE_SET
+
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+AM_PROG_LIBTOOL
+
+AC_ARG_ENABLE(more-warnings,
+ [ --disable-more-warnings Inhibit compiler warnings],
+ set_more_warnings=no)
+
+if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+ CFLAGS="$CFLAGS \
+ -Wall -Wstrict-prototypes -Wmissing-declarations \
+ -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
+fi
+
+
+AM_PATH_PYTHON()
+AM_CHECK_PYTHON_HEADERS(,AC_MSG_ERROR([install python-devel]))
+
+PKG_CHECK_MODULES(PYGTK, [pygtk-2.0 >= 2.10.0])
+
+AC_MSG_CHECKING(for pygtk defs)
+PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
+AC_SUBST(PYGTK_DEFSDIR)
+AC_MSG_RESULT($PYGTK_DEFSDIR)
+
+AC_MSG_CHECKING(for pygtk codegen)
+PYGTK_CODEGEN="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/codegen.py"
+AC_SUBST(PYGTK_CODEGEN)
+AC_MSG_RESULT($PYGTK_CODEGEN)
+
+AC_MSG_CHECKING(for pygtk h2def)
+PYGTK_H2DEF="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/h2def.py"
+AC_SUBST(PYGTK_H2DEF)
+AC_MSG_RESULT($PYGTK_H2DEF)
+
+if test -f ../src/libosmgpsmap.la; then
+ #Because we are building against a non installed lib, the pkgconfig
+ #file cannot tell us to also include/link gtk/soup, so we must manually do it
+ PKG_CHECK_MODULES(OSMGPSMAP, [gtk+-2.0 libsoup-2.4])
+
+ #and we must link to the static lib
+ OSMGPSMAP_CFLAGS="$OSMGPSMAP_CFLAGS -I../src"
+ OSMGPSMAP_LIBS="$OSMGPSMAP_LIBS ../src/libosmgpsmap.la"
+else
+ PKG_CHECK_MODULES(OSMGPSMAP, osmgpsmap)
+fi
+
+AC_OUTPUT([Makefile])
+
+echo
+echo $PACKAGE v$VERSION
+
+echo
+echo "Now type make to compile"
+echo
+
diff --git a/python/osmgpsmap.defs b/python/osmgpsmap.defs
new file mode 100644
index 0000000..3ac06d8
--- /dev/null
+++ b/python/osmgpsmap.defs
@@ -0,0 +1,194 @@
+;; -*- scheme -*-
+; object definitions ...
+(define-object GpsMap
+ (in-module "Osm")
+ (parent "GtkDrawingArea")
+ (c-name "OsmGpsMap")
+ (gtype-id "OSM_TYPE_GPS_MAP")
+)
+
+;; Enumerations and flags ...
+
+
+;; From osm-gps-map.h
+
+(define-function osm_gps_map_get_type
+ (c-name "osm_gps_map_get_type")
+ (return-type "GType")
+)
+
+(define-method download_maps
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_download_maps")
+ (return-type "none")
+ (parameters
+ '("coord_t*" "pt1")
+ '("coord_t*" "pt2")
+ '("int" "zoom_start")
+ '("int" "zoom_end")
+ )
+)
+
+(define-method get_bbox
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_get_bbox")
+ (return-type "none")
+ (parameters
+ '("coord_t*" "pt1")
+ '("coord_t*" "pt2")
+ )
+)
+
+(define-method set_mapcenter
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_set_mapcenter")
+ (return-type "none")
+ (parameters
+ '("float" "latitude")
+ '("float" "longitude")
+ '("int" "zoom")
+ )
+)
+
+(define-method set_center
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_set_center")
+ (return-type "none")
+ (parameters
+ '("float" "latitude")
+ '("float" "longitude")
+ )
+)
+
+(define-method set_zoom
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_set_zoom")
+ (return-type "int")
+ (parameters
+ '("int" "zoom")
+ )
+)
+
+(define-method add_track
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_add_track")
+ (return-type "none")
+ (parameters
+ '("GSList*" "track")
+ )
+)
+
+(define-method clear_tracks
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_clear_tracks")
+ (return-type "none")
+)
+
+(define-method add_image
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_add_image")
+ (return-type "none")
+ (parameters
+ '("float" "latitude")
+ '("float" "longitude")
+ '("GdkPixbuf*" "image")
+ )
+)
+
+(define-method clear_images
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_clear_images")
+ (return-type "none")
+)
+
+(define-method osd_speed
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_osd_speed")
+ (return-type "none")
+ (parameters
+ '("float" "speed")
+ )
+)
+
+(define-method draw_gps
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_draw_gps")
+ (return-type "none")
+ (parameters
+ '("float" "latitude")
+ '("float" "longitude")
+ '("float" "heading")
+ )
+)
+
+(define-method clear_gps
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_clear_gps")
+ (return-type "none")
+)
+
+(define-method get_co_ordinates
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_get_co_ordinates")
+ (return-type "coord_t")
+ (parameters
+ '("int" "pixel_x")
+ '("int" "pixel_y")
+ )
+)
+
+(define-function osm_gps_map_new
+ (c-name "osm_gps_map_new")
+ (is-constructor-of "OsmGpsMap")
+ (return-type "GtkWidget*")
+ (properties
+ '("auto_center" (optional))
+ '("record_trip_history" (optional))
+ '("show_trip-history" (optional))
+ '("auto_download" (optional))
+ '("repo_uri" (optional))
+ '("proxy_uri" (optional))
+ '("tile_cache" (optional))
+ '("tile_cache_is_full_path" (optional))
+ '("zoom" (optional))
+ '("max_zoom" (optional))
+ '("min_zoom" (optional))
+ '("map_x" (optional))
+ '("map_Y" (optional))
+ )
+)
+
+(define-method screen_to_geographic
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_screen_to_geographic")
+ (return-type "none")
+ (parameters
+ '("int" "pixel_x")
+ '("int" "pixel_y")
+ '("float*" "latitude")
+ '("float*" "longitude")
+ )
+)
+
+(define-method geographic_to_screen
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_geographic_to_screen")
+ (return-type "none")
+ (parameters
+ '("float" "latitude")
+ '("float" "longitude")
+ '("int*" "pixel_x")
+ '("int*" "pixel_y")
+ )
+)
+
+(define-method scroll
+ (of-object "OsmGpsMap")
+ (c-name "osm_gps_map_scroll")
+ (return-type "none")
+ (parameters
+ '("gint" "dx")
+ '("gint" "dy")
+ )
+)
+
diff --git a/python/osmgpsmap.override b/python/osmgpsmap.override
new file mode 100644
index 0000000..c5cac87
--- /dev/null
+++ b/python/osmgpsmap.override
@@ -0,0 +1,198 @@
+%%
+headers
+#include <Python.h>
+#include "osm-gps-map.h"
+#include "pygobject.h"
+#include <stdio.h>
+%%
+modulename osmgpsmap
+%%
+import gobject.GObject as PyGObject_Type
+import gtk.DrawingArea as PyGtkDrawingArea_Type
+import gtk.gdk.Pixbuf as PyGdkPixbuf_Type
+%%
+ignore-glob
+ *_get_type
+%%
+override osm_gps_map_get_bbox noargs
+static PyObject *
+_wrap_osm_gps_map_get_bbox(PyGObject *self)
+{
+ coord_t pt1,pt2;
+
+ osm_gps_map_get_bbox(OSM_GPS_MAP(self->obj), &pt1, &pt2);
+
+ return Py_BuildValue("(dddd)", pt1.rlat, pt1.rlon, pt2.rlat, pt2.rlon);
+}
+%%
+override osm_gps_map_get_co_ordinates kwargs
+static PyObject *
+_wrap_osm_gps_map_get_co_ordinates(PyGObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "pixel_x", "pixel_y", NULL };
+ int pixel_x = -1, pixel_y = -1;
+ coord_t coord;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "|ii:GpsMap.get_co_ordinates",
+ kwlist, &pixel_x, &pixel_y))
+ return NULL;
+
+ if ( pixel_x < 0 || pixel_y < 0 ) {
+ PyErr_SetString(PyExc_ValueError, "pixel co-ordinatites must be >= 0");
+ return NULL;
+ }
+
+ coord = osm_gps_map_get_co_ordinates(OSM_GPS_MAP(self->obj), pixel_x, pixel_y);
+
+ return Py_BuildValue("(dd)", coord.rlat, coord.rlon);
+}
+%%
+override osm_gps_map_set_center
+static PyObject *
+_wrap_osm_gps_map_set_center(PyGObject *self, PyObject *args)
+{
+ double latitude, longitude;
+
+ if (PyTuple_Size(args) == 1)
+ args = PyTuple_GetItem(args, 0);
+ if (!PyArg_ParseTuple(args, "dd;OsmGpsMap.set_center takes two floats (also in a tuple)",
+ &latitude, &longitude))
+ return NULL;
+ osm_gps_map_set_center(OSM_GPS_MAP(self->obj), latitude, longitude);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override osm_gps_map_screen_to_geographic
+static PyObject *
+_wrap_osm_gps_map_screen_to_geographic(PyGObject *self, PyObject *args)
+{
+ int pixel_x, pixel_y;
+ gfloat latitude, longitude;
+
+ if (PyTuple_Size(args) == 1)
+ args = PyTuple_GetItem(args, 0);
+ if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.screen_to_geographic takes two"
+ "integers (also in a tuple)", &pixel_x, &pixel_y))
+ return NULL;
+
+ osm_gps_map_screen_to_geographic(OSM_GPS_MAP(self->obj), pixel_x, pixel_y,
+ &latitude, &longitude);
+
+ return Py_BuildValue("(ff)", latitude, longitude);
+}
+%%
+override osm_gps_map_geographic_to_screen
+static PyObject *
+_wrap_osm_gps_map_geographic_to_screen(PyGObject *self, PyObject *args)
+{
+ int pixel_x, pixel_y;
+ gfloat latitude, longitude;
+
+ if (PyTuple_Size(args) == 1)
+ args = PyTuple_GetItem(args, 0);
+ if (!PyArg_ParseTuple(args, "ff:OsmGpsMap.geographic_to_screen takes two"
+ "floats (also in a tuple)", &latitude, &longitude))
+ return NULL;
+
+ osm_gps_map_geographic_to_screen(OSM_GPS_MAP(self->obj),
+ latitude, longitude,
+ &pixel_x, &pixel_y);
+
+ return Py_BuildValue("(ii)", pixel_x, pixel_y);
+}
+%%
+override osm_gps_map_scroll
+static PyObject *
+_wrap_osm_gps_map_scroll(PyGObject *self, PyObject *args)
+{
+ int dx, dy;
+
+ if (PyTuple_Size(args) == 1)
+ args = PyTuple_GetItem(args, 0);
+ if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.scroll takes two "
+ "integers (also in a tuple)", &dx, &dy))
+ return NULL;
+
+ osm_gps_map_scroll(OSM_GPS_MAP(self->obj), dx, dy);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+%%
+override osm_gps_map_add_track kwargs
+static PyObject *
+_wrap_osm_gps_map_add_track(PyGObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "track", NULL };
+ float rlat,rlon;
+ int i, numItems;
+ PyObject *list;
+ PyObject *coords;
+ GSList *track = NULL;
+ int err = FALSE;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:GpsMap.add_track", kwlist, &PyList_Type, &list))
+ return NULL;
+
+ numItems = PyList_Size(list);
+ for(i = 0; i < numItems; i++)
+ {
+ coords = PyList_GetItem(list,i);
+ if(PyArg_ParseTuple(coords,"ff",&rlat,&rlon))
+ {
+ coord_t *c = g_new0(coord_t, 1);
+ c->rlat = rlat;
+ c->rlon = rlon;
+ track = g_slist_append(track, c);
+ }
+ else
+ {
+ err = TRUE;
+ break;
+ }
+ }
+
+ if (err)
+ {
+ if (track)
+ {
+ g_slist_foreach(track, (GFunc) g_free, NULL);
+ g_slist_free(track);
+ }
+ PyErr_SetString(PyExc_ValueError, "track cordinates must be a 2-tuple of lat,lon in radians");
+ return NULL;
+ }
+ else
+ {
+ osm_gps_map_add_track(OSM_GPS_MAP(self->obj), track);
+ }
+ Py_RETURN_NONE;
+}
+%%
+override osm_gps_map_download_maps kwargs
+static PyObject *
+_wrap_osm_gps_map_download_maps(PyGObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "lat1", "lon1", "lat2", "lon2", "zoom_start", "zoom_end", NULL };
+ int zoom_start, zoom_end;
+ coord_t pt1, pt2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "ffffii:GpsMap.download_maps",
+ kwlist, &pt1.rlat,&pt1.rlon,&pt2.rlat, &pt2.rlon,
+ &zoom_start, &zoom_end))
+ return NULL;
+
+ osm_gps_map_download_maps(OSM_GPS_MAP(self->obj), &pt1, &pt2, zoom_start, zoom_end);
+
+ Py_RETURN_NONE;
+}
+
+// vim: filetype=c
diff --git a/python/osmgpsmapmodule.c b/python/osmgpsmapmodule.c
new file mode 100644
index 0000000..c1163a3
--- /dev/null
+++ b/python/osmgpsmapmodule.c
@@ -0,0 +1,64 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * osmgpsmapmodule.
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <pygobject.h>
+#include <osm-gps-map.h>
+
+void pyosmgpsmap_register_classes(PyObject *d);
+extern PyMethodDef pyosmgpsmap_functions[];
+
+DL_EXPORT(void)
+initosmgpsmap(void)
+{
+ PyObject *m, *d;
+
+ init_pygobject();
+
+ m = Py_InitModule("osmgpsmap", pyosmgpsmap_functions);
+ d = PyModule_GetDict(m);
+
+ pyosmgpsmap_register_classes(d);
+
+ /* Add this if we ever add an enum or something to osmgpsmap. */
+#if 0
+ pyosmgpsmap_add_constants(m, "OSM_GPS_MAP_");
+#endif
+
+ /* Manually add all the Map repository strings */
+ PyModule_AddObject(m, "MAP_SOURCE_OPENSTREETMAP",
+ PyString_FromString(MAP_SOURCE_OPENSTREETMAP));
+ PyModule_AddObject(m, "MAP_SOURCE_OPENSTREETMAP_RENDERER",
+ PyString_FromString(MAP_SOURCE_OPENSTREETMAP_RENDERER));
+ PyModule_AddObject(m, "MAP_SOURCE_OPENAERIALMAP",
+ PyString_FromString(MAP_SOURCE_OPENAERIALMAP));
+ PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_HYBRID",
+ PyString_FromString(MAP_SOURCE_GOOGLE_HYBRID));
+ PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_SATTELITE",
+ PyString_FromString(MAP_SOURCE_GOOGLE_SATTELITE));
+ PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_SATTELITE_QUAD",
+ PyString_FromString(MAP_SOURCE_GOOGLE_SATTELITE_QUAD));
+ PyModule_AddObject(m, "MAP_SOURCE_MAPS_FOR_FREE",
+ PyString_FromString(MAP_SOURCE_MAPS_FOR_FREE));
+ PyModule_AddObject(m, "MAP_SOURCE_VIRTUAL_EARTH_SATTELITE",
+ PyString_FromString(MAP_SOURCE_VIRTUAL_EARTH_SATTELITE));
+
+ if (PyErr_Occurred()) {
+ Py_FatalError("can't initialize module osmgpsmap");
+ }
+}
diff --git a/python/setup.py b/python/setup.py
new file mode 100644
index 0000000..055c8e5
--- /dev/null
+++ b/python/setup.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+import os
+from distutils.core import setup, Extension
+
+def pkg_config_parse(pkg, opt):
+ conf = os.popen('pkg-config %s %s' % (opt,pkg)).read()
+ opt = opt[-2:]
+ return [x.lstrip(opt) for x in conf.split()]
+
+def get_include(pkg):
+ return pkg_config_parse(pkg,'--cflags-only-I')
+
+def get_lib_dirs(pkg):
+ return pkg_config_parse(pkg,'--libs-only-L')
+
+def get_libs(pkg):
+ return pkg_config_parse(pkg,'--libs-only-l')
+
+#print get_libs('osmgpsmap pygobject-2.0')
+#print get_libs('osmgpsmap pygobject-2.0')
+#print get_libs('osmgpsmap pygobject-2.0')
+
+_osmgpsmap = Extension(name = 'osmgpsmap',
+ sources= ['osmgpsmapmodule.c','osmgpsmap.c'],
+ include_dirs = get_include('osmgpsmap pygobject-2.0'),
+ library_dirs = get_lib_dirs('osmgpsmap pygobject-2.0'),
+ libraries = get_libs('osmgpsmap pygobject-2.0'),
+ )
+
+setup( name = "pyosmgpsmap",
+ version = "0.1",
+ description = "python interface for osmgpsmap",
+ ext_modules = [_osmgpsmap],
+ )
+
diff --git a/python/test.sh b/python/test.sh
new file mode 100755
index 0000000..d624efb
--- /dev/null
+++ b/python/test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+PYTHONPATH=`pwd`/.libs \
+ python -c \
+'import gtk.gdk
+import gobject
+import osmgpsmap
+
+gtk.gdk.threads_init()
+
+def print_tiles(map):
+ print map.get_property("tiles-queued")
+ return True
+
+a = gtk.Window()
+a.connect("destroy", lambda x: gtk.main_quit())
+m = osmgpsmap.GpsMap()
+
+a.add(m)
+a.show_all()
+
+gobject.timeout_add(500, print_tiles, m)
+
+gtk.main()'
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..18286b8
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,46 @@
+## Process this file with automake to produce Makefile.in
+
+## Created by Anjuta
+
+AM_CPPFLAGS = \
+ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
+ -DPACKAGE_DATA_DIR=\""$(datadir)"\" $(OPENSTREETMAP_GPS_MAP_CFLAGS)
+
+AM_CFLAGS =\
+ -Wall\
+ -g
+
+bin_PROGRAMS = openstreetmap-gps-map
+
+openstreetmap_gps_map_SOURCES = \
+ main.c
+
+openstreetmap_gps_map_DEPENDENCIES = \
+ libosmgpsmap.la
+
+openstreetmap_gps_map_LDFLAGS = \
+ -losmgpsmap -lgthread-2.0
+
+openstreetmap_gps_map_LDADD = $(OPENSTREETMAP_GPS_MAP_LIBS)
+
+lib_LTLIBRARIES = \
+ libosmgpsmap.la
+
+libosmgpsmap_la_SOURCES = \
+ converter.c \
+ osm-gps-map.c
+
+libosmgpsmap_la_CFLAGS = \
+ -DG_LOG_DOMAIN=\"OsmGpsMap\"
+
+libosmgpsmapincdir = $(includedir)/osmgpsmap
+libosmgpsmapinc_HEADERS = \
+ osm-gps-map.h
+
+noinst_HEADERS = \
+ converter.h \
+ osm-gps-map-types.h
+
+EXTRA_DIST = \
+ poi.png
diff --git a/src/converter.c b/src/converter.c
new file mode 100644
index 0000000..658c266
--- /dev/null
+++ b/src/converter.c
@@ -0,0 +1,102 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * converter.c
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdio.h>
+
+#include "osm-gps-map-types.h"
+#include "converter.h"
+
+
+float
+deg2rad(float deg)
+{
+ return (deg * M_PI / 180.0);
+}
+
+float
+rad2deg(float rad)
+{
+ return (rad / M_PI * 180.0);
+}
+
+
+int
+lat2pixel( int zoom,
+ float lat)
+{
+ float lat_m;
+ int pixel_y;
+
+ lat_m = atanh(sin(lat));
+
+ /* the formula is
+ *
+ * pixel_y = -(2^zoom * TILESIZE * lat_m) / 2PI + (2^zoom * TILESIZE) / 2
+ */
+ pixel_y = -(int)( (lat_m * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
+ ((1 << zoom) * (TILESIZE/2) );
+
+
+ return pixel_y;
+}
+
+
+int
+lon2pixel( int zoom,
+ float lon)
+{
+ int pixel_x;
+
+ /* the formula is
+ *
+ * pixel_x = (2^zoom * TILESIZE * lon) / 2PI + (2^zoom * TILESIZE) / 2
+ */
+ pixel_x = (int)(( lon * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
+ ( (1 << zoom) * (TILESIZE/2) );
+ return pixel_x;
+}
+
+float
+pixel2lon( float zoom,
+ int pixel_x)
+{
+ float lon;
+
+ lon = ((pixel_x - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) *2*M_PI) /
+ (TILESIZE * exp(zoom * M_LN2) );
+
+ return lon;
+}
+
+float
+pixel2lat( float zoom,
+ int pixel_y)
+{
+ float lat, lat_m;
+
+ lat_m = (-( pixel_y - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) * (2*M_PI)) /
+ (TILESIZE * exp(zoom * M_LN2));
+
+ lat = asin(tanh(lat_m));
+
+ return lat;
+}
diff --git a/src/converter.h b/src/converter.h
new file mode 100644
index 0000000..0023d9f
--- /dev/null
+++ b/src/converter.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * converter.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+float
+deg2rad(float deg);
+
+float
+rad2deg(float rad);
+
+int
+lat2pixel( int zoom,
+ float lat);
+
+int
+lon2pixel( int zoom,
+ float lon);
+
+float
+pixel2lon( float zoom,
+ int pixel_x);
+
+float
+pixel2lat( float zoom,
+ int pixel_y);
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..aa90c16
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,361 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * main.c
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "osm-gps-map.h"
+
+typedef struct {
+ const char *name;
+ const char *uri;
+} map_source_t;
+
+static const map_source_t MAP_SOURCES[] = {
+ {"OpenStreetMap", MAP_SOURCE_OPENSTREETMAP },
+ {"OpenStreetMap Renderer", MAP_SOURCE_OPENSTREETMAP_RENDERER },
+ {"OpenAerialMap", MAP_SOURCE_OPENAERIALMAP },
+ {"Google Maps", MAP_SOURCE_GOOGLE_MAPS },
+ {"Google Maps Hybrid", MAP_SOURCE_GOOGLE_HYBRID },
+ {"Google Sattelite", MAP_SOURCE_GOOGLE_SATTELITE },
+ {"Google Sattelite Quad", MAP_SOURCE_GOOGLE_SATTELITE_QUAD },
+ {"Maps For Free", MAP_SOURCE_MAPS_FOR_FREE },
+ {"Virtual Earth Sattelite", MAP_SOURCE_VIRTUAL_EARTH_SATTELITE },
+};
+
+static int map_provider = 0;
+static gboolean maps_in_temp = FALSE;
+static gboolean debug = FALSE;
+static GOptionEntry entries[] =
+{
+ { "maps-in-temp", 't', 0, G_OPTION_ARG_NONE, &maps_in_temp, "Store maps in /tmp instead of ~/Maps", NULL },
+ { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Enable debugging", NULL },
+ { "map", 'm', 0, G_OPTION_ARG_INT, &map_provider, "Map source", "N" },
+ { NULL }
+};
+
+
+static GdkPixbuf *STAR_IMAGE;
+
+typedef struct {
+ OsmGpsMap *map;
+ GtkWidget *entry;
+} timeout_cb_t;
+
+float
+deg2rad(float deg)
+{
+ return (deg * M_PI / 180.0);
+}
+
+float
+rad2deg(float rad)
+{
+ return (rad / M_PI * 180.0);
+}
+
+gboolean
+on_timeout_check_tiles_in_queue(gpointer user_data)
+{
+ gchar *msg;
+ int remaining;
+ timeout_cb_t *data = (timeout_cb_t *)user_data;
+ g_object_get(data->map, "tiles-queued", &remaining,NULL);
+
+ msg = g_strdup_printf("%d tiles queued",remaining);
+ gtk_entry_set_text(GTK_ENTRY(data->entry), msg);
+ g_free(msg);
+
+ return remaining > 0;
+}
+
+gboolean
+on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ coord_t coord;
+ OsmGpsMap *map = OSM_GPS_MAP(widget);
+
+ if ( (event->button == 1) && (event->type == GDK_2BUTTON_PRESS) )
+ {
+ g_debug("Double clicked %f %f", event->x, event->y);
+ coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
+ osm_gps_map_draw_gps (map,
+ rad2deg(coord.rlat),
+ rad2deg(coord.rlon),
+ 0);
+ }
+
+ if ( (event->button == 2) && (event->type == GDK_BUTTON_PRESS) )
+ {
+ coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
+ osm_gps_map_add_image (map,
+ rad2deg(coord.rlat),
+ rad2deg(coord.rlon),
+ STAR_IMAGE);
+ }
+ return FALSE;
+}
+
+gboolean
+on_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ float lat,lon;
+ GtkEntry *entry = GTK_ENTRY(user_data);
+ OsmGpsMap *map = OSM_GPS_MAP(widget);
+
+ g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
+ gchar *msg = g_strdup_printf("%f,%f",lat,lon);
+ gtk_entry_set_text(entry, msg);
+ g_free(msg);
+
+ return FALSE;
+}
+
+gboolean
+on_zoom_in_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+ int zoom;
+ OsmGpsMap *map = OSM_GPS_MAP(user_data);
+ g_object_get(map, "zoom", &zoom, NULL);
+ osm_gps_map_set_zoom(map, zoom+1);
+ return FALSE;
+}
+
+gboolean
+on_zoom_out_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+ int zoom;
+ OsmGpsMap *map = OSM_GPS_MAP(user_data);
+ g_object_get(map, "zoom", &zoom, NULL);
+ osm_gps_map_set_zoom(map, zoom-1);
+ return FALSE;
+}
+
+gboolean
+on_home_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+ OsmGpsMap *map = OSM_GPS_MAP(user_data);
+ osm_gps_map_set_mapcenter(map, -43.5326,172.6362,12);
+ return FALSE;
+}
+
+gboolean
+on_cache_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+ int zoom,max_zoom;
+ coord_t pt1, pt2;
+ timeout_cb_t *data;
+
+ data = (timeout_cb_t *)user_data;
+ osm_gps_map_get_bbox(data->map, &pt1, &pt2);
+ g_object_get(data->map, "zoom", &zoom, "max-zoom", &max_zoom, NULL);
+ osm_gps_map_download_maps(data->map, &pt1, &pt2, zoom, max_zoom);
+ g_timeout_add(500, on_timeout_check_tiles_in_queue, user_data);
+
+ return FALSE;
+}
+
+void
+on_close (GtkWidget *widget, gpointer user_data)
+{
+ gtk_widget_destroy(widget);
+ gtk_main_quit();
+}
+
+void
+usage (GOptionContext *context)
+{
+ int i;
+
+ puts(g_option_context_get_help(context, TRUE, NULL));
+
+ printf("Valid map sources:\n");
+ for(i=0; i<(sizeof(MAP_SOURCES)/sizeof(MAP_SOURCES[0])); i++)
+ printf("\t%d:\t%s\n",i,MAP_SOURCES[i].name);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *vbox;
+ GtkWidget *bbox;
+ GtkWidget *entry;
+ GtkWidget *window;
+ GtkWidget *zoomInbutton;
+ GtkWidget *zoomOutbutton;
+ GtkWidget *homeButton;
+ GtkWidget *cacheButton;
+ GtkWidget *map;
+ char *cachedir;
+ char *homedir;
+ GError *error = NULL;
+ GOptionContext *context;
+ timeout_cb_t *data;
+
+ g_thread_init(NULL);
+ gtk_init (&argc, &argv);
+
+ context = g_option_context_new ("- test tree model performance");
+ g_option_context_set_help_enabled(context, FALSE);
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ usage(context);
+ return 1;
+ }
+
+ if (map_provider < 0 || map_provider > (sizeof(MAP_SOURCES)/sizeof(MAP_SOURCES[0]))-1) {
+ usage(context);
+ return 2;
+ }
+
+ if (maps_in_temp)
+ homedir = g_strdup("/tmp");
+ else {
+ homedir = g_strdup(g_getenv("HOME"));
+ if (!homedir)
+ homedir = g_strdup(g_get_home_dir());
+ }
+
+ if (debug)
+ gdk_window_set_debug_updates(TRUE);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
+
+ STAR_IMAGE = gdk_pixbuf_new_from_file_at_size ("poi.png", 24,24,NULL);
+ cachedir = g_strdup_printf("%s/Maps/%s", homedir, MAP_SOURCES[map_provider].name);
+
+ g_debug("Map Cache Dir: %s", cachedir);
+ g_debug("Map Provider: %s (%d)", MAP_SOURCES[map_provider].name, map_provider);
+
+ switch(map_provider) {
+ //0: OpenStreetMap
+ //1: OpenStreetMap Renderer
+ //2: OpenAerialMap
+ //3: Google Maps
+ //4: Google Maps Hybrid
+ //5: Google Sattelite
+ //6: Google Sattelite Quad
+ //7: Maps For Free
+ //8: Virtual Earth Sattelite
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ default:
+ map = g_object_new (OSM_TYPE_GPS_MAP,
+ "repo-uri",MAP_SOURCES[map_provider].uri,
+ "tile-cache",cachedir,
+ "tile-cache-is-full-path",TRUE,
+ "proxy-uri",g_getenv("http_proxy"),
+ NULL);
+ break;
+ case 7:
+ //Max Zoom = 11
+ map = g_object_new (OSM_TYPE_GPS_MAP,
+ "repo-uri",MAP_SOURCES[map_provider].uri,
+ "tile-cache",cachedir,
+ "tile-cache-is-full-path",TRUE,
+ "proxy-uri",g_getenv("http_proxy"),
+ "max-zoom",11,
+ NULL);
+ break;
+ case 5:
+ case 6:
+ //Max Zoom = 18
+ map = g_object_new (OSM_TYPE_GPS_MAP,
+ "repo-uri",MAP_SOURCES[map_provider].uri,
+ "tile-cache",cachedir,
+ "tile-cache-is-full-path",TRUE,
+ "proxy-uri",g_getenv("http_proxy"),
+ "max-zoom",18,
+ NULL);
+ break;
+ case 8:
+ //Max Zoom = 20
+ map = g_object_new (OSM_TYPE_GPS_MAP,
+ "repo-uri",MAP_SOURCES[map_provider].uri,
+ "tile-cache",cachedir,
+ "tile-cache-is-full-path",TRUE,
+ "proxy-uri",g_getenv("http_proxy"),
+ "max-zoom",20,
+ NULL);
+ break;
+ }
+ g_free(cachedir);
+
+
+ vbox = gtk_vbox_new (FALSE, 2);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ //Add the map to the box
+ gtk_box_pack_start (GTK_BOX(vbox), map, TRUE, TRUE, 0);
+ //And add a box for the buttons
+ bbox = gtk_hbox_new (TRUE, 0);
+ gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
+ //And add the lat/long entry
+ entry = gtk_entry_new();
+ gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, TRUE, 0);
+
+ //Add buttons to the bbox
+ zoomInbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_IN);
+ g_signal_connect (G_OBJECT (zoomInbutton), "clicked",
+ G_CALLBACK (on_zoom_in_clicked_event), (gpointer) map);
+ gtk_box_pack_start (GTK_BOX(bbox), zoomInbutton, FALSE, TRUE, 0);
+
+ zoomOutbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
+ g_signal_connect (G_OBJECT (zoomOutbutton), "clicked",
+ G_CALLBACK (on_zoom_out_clicked_event), (gpointer) map);
+ gtk_box_pack_start (GTK_BOX(bbox), zoomOutbutton, FALSE, TRUE, 0);
+
+ homeButton = gtk_button_new_from_stock (GTK_STOCK_HOME);
+ g_signal_connect (G_OBJECT (homeButton), "clicked",
+ G_CALLBACK (on_home_clicked_event), (gpointer) map);
+ gtk_box_pack_start (GTK_BOX(bbox), homeButton, FALSE, TRUE, 0);
+
+ data = g_new0(timeout_cb_t, 1);
+ data->map = OSM_GPS_MAP(map);
+ data->entry = entry;
+ cacheButton = gtk_button_new_with_label ("Cache");
+ g_signal_connect (G_OBJECT (cacheButton), "clicked",
+ G_CALLBACK (on_cache_clicked_event), (gpointer) data);
+ gtk_box_pack_start (GTK_BOX(bbox), cacheButton, FALSE, TRUE, 0);
+
+ //Connect to map events
+ g_signal_connect (map, "button-press-event",
+ G_CALLBACK (on_button_press_event), (gpointer) entry);
+ g_signal_connect (map, "button-release-event",
+ G_CALLBACK (on_button_release_event), (gpointer) entry);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (on_close), (gpointer) map);
+
+ gtk_widget_show_all (window);
+
+ g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
+ gtk_main ();
+
+ g_free(homedir);
+ return 0;
+}
diff --git a/src/osm-gps-map-types.h b/src/osm-gps-map-types.h
new file mode 100644
index 0000000..bc3c415
--- /dev/null
+++ b/src/osm-gps-map-types.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map-types.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OSM_GPS_MAP_TYPES_H_
+#define _OSM_GPS_MAP_TYPES_H_
+
+#include <gdk/gdk.h>
+#include "osm-gps-map.h"
+
+#define TILESIZE 256
+#define MAX_ZOOM 20
+#define MIN_ZOOM 0
+
+#define URI_MARKER_X "#X"
+#define URI_MARKER_Y "#Y"
+#define URI_MARKER_Z "#Z"
+#define URI_MARKER_S "#S"
+#define URI_MARKER_Q "#Q"
+#define URI_MARKER_Q0 "#W"
+#define URI_MARKER_YS "#U"
+#define URI_MARKER_R "#R"
+
+#define URI_HAS_X (1 << 0)
+#define URI_HAS_Y (1 << 1)
+#define URI_HAS_Z (1 << 2)
+#define URI_HAS_S (1 << 3)
+#define URI_HAS_Q (1 << 4)
+#define URI_HAS_Q0 (1 << 5)
+#define URI_HAS_YS (1 << 6)
+#define URI_HAS_R (1 << 7)
+//....
+#define URI_FLAG_END (1 << 8)
+
+typedef struct {
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+} bbox_pixel_t;
+
+typedef struct {
+ /* The details of the tile to download */
+ char *uri;
+ char *folder;
+ char *filename;
+ OsmGpsMap *map;
+ /* whether to redraw the map when the tile arrives */
+ gboolean redraw;
+} tile_download_t;
+
+typedef struct {
+ int x;
+ int y;
+ int zoom;
+} tile_t;
+
+typedef struct {
+ coord_t pt;
+ GdkPixbuf *image;
+ int w;
+ int h;
+} image_t;
+
+#endif /* _OSM_GPS_MAP_TYPES_H_ */
diff --git a/src/osm-gps-map.c b/src/osm-gps-map.c
new file mode 100644
index 0000000..e25a33a
--- /dev/null
+++ b/src/osm-gps-map.c
@@ -0,0 +1,2171 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map.c
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <fcntl.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <libsoup/soup.h>
+
+#include "converter.h"
+#include "osm-gps-map-types.h"
+#include "osm-gps-map.h"
+
+#ifdef USE_CAIRO
+#include <cairo.h>
+#endif
+
+#define ENABLE_DEBUG 0
+
+#define EXTRA_BORDER (TILESIZE / 2)
+
+struct _OsmGpsMapPrivate
+{
+ GHashTable *tile_queue;
+ GHashTable *missing_tiles;
+ GHashTable *tile_cache;
+
+ int map_zoom;
+ int max_zoom;
+ int min_zoom;
+ gboolean map_auto_center;
+ gboolean map_auto_download;
+ int map_x;
+ int map_y;
+
+ /* Latitude and longitude of the center of the map, in radians */
+ gfloat center_rlat;
+ gfloat center_rlon;
+
+ guint max_tile_cache_size;
+ /* Incremented at each redraw */
+ guint redraw_cycle;
+ /* ID of the idle redraw operation */
+ guint idle_map_redraw;
+
+ //how we download tiles
+ SoupSession *soup_session;
+ char *proxy_uri;
+
+ //where downloaded tiles are cached
+ char *cache_dir;
+ gboolean cache_dir_is_full_path;
+
+ //contains flags indicating the various special characters
+ //the uri string contains, that will be replaced when calculating
+ //the uri to download.
+ char *repo_uri;
+ int uri_format;
+ //flag indicating if the map source is located on the google
+ gboolean the_google;
+
+ //gps tracking state
+ gboolean record_trip_history;
+ gboolean show_trip_history;
+ GSList *trip_history;
+ coord_t *gps;
+ gboolean gps_valid;
+
+ //additional images or tracks added to the map
+ GSList *tracks;
+ GSList *images;
+
+ //Used for storing the joined tiles
+ GdkPixmap *pixmap;
+ GdkGC *gc_map;
+
+ //The tile painted when one cannot be found
+ //GdkPixbuf *missing_tile;
+
+ //For tracking click and drag
+ int drag_counter;
+ int drag_mouse_dx;
+ int drag_mouse_dy;
+ int drag_start_mouse_x;
+ int drag_start_mouse_y;
+ int drag_start_map_x;
+ int drag_start_map_y;
+
+ //for customizing the redering of the gps track
+ int ui_gps_track_width;
+ int ui_gps_point_inner_radius;
+ int ui_gps_point_outer_radius;
+
+ guint is_disposed : 1;
+ guint dragging : 1;
+ guint center_coord_set : 1;
+};
+
+#define OSM_GPS_MAP_PRIVATE(o) (OSM_GPS_MAP (o)->priv)
+
+typedef struct
+{
+ GdkPixbuf *pixbuf;
+ /* We keep track of the number of the redraw cycle this tile was last used,
+ * so that osm_gps_map_purge_cache() can remove the older ones */
+ guint redraw_cycle;
+} OsmCachedTile;
+
+enum
+{
+ PROP_0,
+
+ PROP_AUTO_CENTER,
+ PROP_RECORD_TRIP_HISTORY,
+ PROP_SHOW_TRIP_HISTORY,
+ PROP_AUTO_DOWNLOAD,
+ PROP_REPO_URI,
+ PROP_PROXY_URI,
+ PROP_TILE_CACHE_DIR,
+ PROP_TILE_CACHE_DIR_IS_FULL_PATH,
+ PROP_ZOOM,
+ PROP_MAX_ZOOM,
+ PROP_MIN_ZOOM,
+ PROP_LATITUDE,
+ PROP_LONGITUDE,
+ PROP_MAP_X,
+ PROP_MAP_Y,
+ PROP_TILES_QUEUED,
+ PROP_GPS_TRACK_WIDTH,
+ PROP_GPS_POINT_R1,
+ PROP_GPS_POINT_R2
+};
+
+G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);
+
+/*
+ * Drawing function forward defintions
+ */
+static gchar *replace_string(const gchar *src, const gchar *from, const gchar *to);
+static void inspect_map_uri(OsmGpsMap *map);
+static gchar *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y);
+static void osm_gps_map_print_images (OsmGpsMap *map);
+static void osm_gps_map_draw_gps_point (OsmGpsMap *map);
+static void osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);
+static void osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
+static void osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw);
+static void osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y);
+static void osm_gps_map_fill_tiles_pixel (OsmGpsMap *map);
+static gboolean osm_gps_map_map_redraw (OsmGpsMap *map);
+static void osm_gps_map_map_redraw_idle (OsmGpsMap *map);
+
+static void
+cached_tile_free (OsmCachedTile *tile)
+{
+ g_object_unref (tile->pixbuf);
+ g_slice_free (OsmCachedTile, tile);
+}
+
+/*
+ * Description:
+ * Find and replace text within a string.
+ *
+ * Parameters:
+ * src (in) - pointer to source string
+ * from (in) - pointer to search text
+ * to (in) - pointer to replacement text
+ *
+ * Returns:
+ * Returns a pointer to dynamically-allocated memory containing string
+ * with occurences of the text pointed to by 'from' replaced by with the
+ * text pointed to by 'to'.
+ */
+static gchar *
+replace_string(const gchar *src, const gchar *from, const gchar *to)
+{
+ size_t size = strlen(src) + 1;
+ size_t fromlen = strlen(from);
+ size_t tolen = strlen(to);
+
+ /* Allocate the first chunk with enough for the original string. */
+ gchar *value = g_malloc(size);
+
+
+ /* We need to return 'value', so let's make a copy to mess around with. */
+ gchar *dst = value;
+
+ if ( value != NULL )
+ {
+ for ( ;; )
+ {
+ /* Try to find the search text. */
+ const gchar *match = g_strstr_len(src, size, from);
+ if ( match != NULL )
+ {
+ gchar *temp;
+ /* Find out how many characters to copy up to the 'match'. */
+ size_t count = match - src;
+
+
+ /* Calculate the total size the string will be after the
+ * replacement is performed. */
+ size += tolen - fromlen;
+
+ temp = g_realloc(value, size);
+ if ( temp == NULL )
+ {
+ g_free(value);
+ return NULL;
+ }
+
+ /* we'll want to return 'value' eventually, so let's point it
+ * to the memory that we are now working with.
+ * And let's not forget to point to the right location in
+ * the destination as well. */
+ dst = temp + (dst - value);
+ value = temp;
+
+ /*
+ * Copy from the source to the point where we matched. Then
+ * move the source pointer ahead by the amount we copied. And
+ * move the destination pointer ahead by the same amount.
+ */
+ g_memmove(dst, src, count);
+ src += count;
+ dst += count;
+
+ /* Now copy in the replacement text 'to' at the position of
+ * the match. Adjust the source pointer by the text we replaced.
+ * Adjust the destination pointer by the amount of replacement
+ * text. */
+ g_memmove(dst, to, tolen);
+ src += fromlen;
+ dst += tolen;
+ }
+ else
+ {
+ /*
+ * Copy any remaining part of the string. This includes the null
+ * termination character.
+ */
+ strcpy(dst, src);
+ break;
+ }
+ }
+ }
+ return value;
+}
+
+static void
+map_convert_coords_to_quadtree_string(OsmGpsMap *map, gint x, gint y, gint zoomlevel,
+ gchar *buffer, const gchar initial,
+ const gchar *const quadrant)
+{
+ gchar *ptr = buffer;
+ gint n;
+
+ if (initial)
+ *ptr++ = initial;
+
+ for(n = zoomlevel-1; n >= 0; n--)
+ {
+ gint xbit = (x >> n) & 1;
+ gint ybit = (y >> n) & 1;
+ *ptr++ = quadrant[xbit + 2 * ybit];
+ }
+
+ *ptr++ = '\0';
+}
+
+
+static void
+inspect_map_uri(OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_X))
+ priv->uri_format |= URI_HAS_X;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_Y))
+ priv->uri_format |= URI_HAS_Y;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_Z))
+ priv->uri_format |= URI_HAS_Z;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_S))
+ priv->uri_format |= URI_HAS_S;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_Q))
+ priv->uri_format |= URI_HAS_Q;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_Q0))
+ priv->uri_format |= URI_HAS_Q0;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_YS))
+ priv->uri_format |= URI_HAS_YS;
+
+ if (g_strrstr(priv->repo_uri, URI_MARKER_R))
+ priv->uri_format |= URI_HAS_R;
+
+ if (g_strrstr(priv->repo_uri, "google.com"))
+ priv->the_google = TRUE;
+
+ g_debug("URI Format: 0x%X (google: %X)", priv->uri_format, priv->the_google);
+
+}
+
+static gchar *
+replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ char *url;
+ unsigned int i;
+ char location[22];
+
+ i = 1;
+ url = g_strdup(uri);
+ while (i < URI_FLAG_END)
+ {
+ char *s;
+ char *old;
+
+ old = url;
+ switch(i & priv->uri_format)
+ {
+ case URI_HAS_X:
+ s = g_strdup_printf("%d", x);
+ url = replace_string(url, URI_MARKER_X, s);
+ //g_debug("FOUND " URI_MARKER_X);
+ break;
+ case URI_HAS_Y:
+ s = g_strdup_printf("%d", y);
+ url = replace_string(url, URI_MARKER_Y, s);
+ //g_debug("FOUND " URI_MARKER_Y);
+ break;
+ case URI_HAS_Z:
+ s = g_strdup_printf("%d", zoom);
+ url = replace_string(url, URI_MARKER_Z, s);
+ //g_debug("FOUND " URI_MARKER_Z);
+ break;
+ case URI_HAS_S:
+ s = g_strdup_printf("%d", priv->max_zoom-zoom);
+ url = replace_string(url, URI_MARKER_S, s);
+ //g_debug("FOUND " URI_MARKER_S);
+ break;
+ case URI_HAS_Q:
+ map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'t',"qrts");
+ s = g_strdup_printf("%s", location);
+ url = replace_string(url, URI_MARKER_Q, s);
+ //g_debug("FOUND " URI_MARKER_Q);
+ break;
+ case URI_HAS_Q0:
+ map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'\0', "0123");
+ s = g_strdup_printf("%s", location);
+ url = replace_string(url, URI_MARKER_Q0, s);
+ //g_debug("FOUND " URI_MARKER_Q0);
+ break;
+ case URI_HAS_YS:
+ // s = g_strdup_printf("%d", y);
+ // url = replace_string(url, URI_MARKER_YS, s);
+ g_warning("FOUND " URI_MARKER_YS " NOT IMPLEMENTED");
+ // retval = g_strdup_printf(repo->url,
+ // tilex,
+ // (1 << (MAX_ZOOM - zoom)) - tiley - 1,
+ // zoom - (MAX_ZOOM - 17));
+ break;
+ case URI_HAS_R:
+ s = g_strdup_printf("%d", g_random_int_range(0,4));
+ url = replace_string(url, URI_MARKER_R, s);
+ //g_debug("FOUND " URI_MARKER_R);
+ break;
+ default:
+ s = NULL;
+ break;
+ }
+
+ if (s) {
+ g_free(s);
+ g_free(old);
+ }
+
+ i = (i << 1);
+
+ }
+
+ return url;
+}
+
+static void
+my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer user_data)
+{
+ if (!(log_level & G_LOG_LEVEL_DEBUG) || ENABLE_DEBUG)
+ g_log_default_handler (log_domain, log_level, message, user_data);
+}
+
+/* clears the trip list and all resources */
+static void
+osm_gps_map_free_trip (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ if (priv->trip_history) {
+ g_slist_foreach(priv->trip_history, (GFunc) g_free, NULL);
+ g_slist_free(priv->trip_history);
+ priv->trip_history = NULL;
+ }
+}
+
+/* clears the tracks and all resources */
+static void
+osm_gps_map_free_tracks (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ if (priv->tracks)
+ {
+ GSList* tmp = priv->tracks;
+ while (tmp != NULL)
+ {
+ g_slist_foreach(tmp->data, (GFunc) g_free, NULL);
+ g_slist_free(tmp->data);
+ tmp = g_slist_next(tmp);
+ }
+ g_slist_free(priv->tracks);
+ priv->tracks = NULL;
+ }
+}
+
+/* free the poi image lists */
+static void
+osm_gps_map_free_images (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ if (priv->images) {
+ GSList *list;
+ for(list = priv->images; list != NULL; list = list->next)
+ {
+ image_t *im = list->data;
+ g_object_unref(im->image);
+ g_free(im);
+ }
+ g_slist_free(priv->images);
+ priv->images = NULL;
+ }
+}
+
+static void
+osm_gps_map_print_images (OsmGpsMap *map)
+{
+ GSList *list;
+ int x,y,pixel_x,pixel_y;
+ int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
+ int map_x0, map_y0;
+ OsmGpsMapPrivate *priv = map->priv;
+
+ map_x0 = priv->map_x - EXTRA_BORDER;
+ map_y0 = priv->map_y - EXTRA_BORDER;
+ for(list = priv->images; list != NULL; list = list->next)
+ {
+ image_t *im = list->data;
+
+ // pixel_x,y, offsets
+ pixel_x = lon2pixel(priv->map_zoom, im->pt.rlon);
+ pixel_y = lat2pixel(priv->map_zoom, im->pt.rlat);
+
+ g_debug("Image %dx%d @: %f,%f (%d,%d)",
+ im->w, im->h,
+ im->pt.rlat, im->pt.rlon,
+ pixel_x, pixel_y);
+
+ x = pixel_x - map_x0;
+ y = pixel_y - map_y0;
+
+ gdk_draw_pixbuf (
+ priv->pixmap,
+ priv->gc_map,
+ im->image,
+ 0,0,
+ x-(im->w/2),y-(im->h/2),
+ im->w,im->h,
+ GDK_RGB_DITHER_NONE, 0, 0);
+
+ max_x = MAX(x+im->w,max_x);
+ min_x = MIN(x-im->w,min_x);
+ max_y = MAX(y+im->h,max_y);
+ min_y = MIN(y-im->h,min_y);
+ }
+
+ gtk_widget_queue_draw_area (
+ GTK_WIDGET(map),
+ min_x + EXTRA_BORDER, min_y + EXTRA_BORDER,
+ max_x + EXTRA_BORDER, max_y + EXTRA_BORDER);
+
+}
+
+static void
+osm_gps_map_draw_gps_point (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ //incase we get called before we have got a gps point
+ if (priv->gps_valid) {
+ int map_x0, map_y0;
+ int x, y;
+ int r = priv->ui_gps_point_inner_radius;
+ int r2 = priv->ui_gps_point_outer_radius;
+ int lw = priv->ui_gps_track_width;
+ int mr = MAX(r,r2);
+
+ map_x0 = priv->map_x - EXTRA_BORDER;
+ map_y0 = priv->map_y - EXTRA_BORDER;
+ x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;
+ y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;
+#ifdef USE_CAIRO
+ cairo_t *cr;
+ cairo_pattern_t *pat;
+#else
+ GdkColor color;
+ GdkGC *marker;
+#endif
+
+#ifdef USE_CAIRO
+ cr = gdk_cairo_create(priv->pixmap);
+
+ // draw transparent area
+ if (r2 > 0) {
+ cairo_set_line_width (cr, 1.5);
+ cairo_set_source_rgba (cr, 0.75, 0.75, 0.75, 0.4);
+ cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
+ cairo_fill (cr);
+ // draw transparent area border
+ cairo_set_source_rgba (cr, 0.55, 0.55, 0.55, 0.4);
+ cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
+ cairo_stroke(cr);
+ }
+
+ // draw ball gradient
+ if (r > 0) {
+ pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x, y, r);
+ cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);
+ cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);
+ cairo_set_source (cr, pat);
+ cairo_arc (cr, x, y, r, 0, 2 * M_PI);
+ cairo_fill (cr);
+ cairo_pattern_destroy (pat);
+ // draw ball border
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_arc (cr, x, y, r, 0, 2 * M_PI);
+ cairo_stroke(cr);
+ }
+
+ cairo_destroy(cr);
+ gtk_widget_queue_draw_area (GTK_WIDGET(map),
+ x-mr,
+ y-mr,
+ mr*2,
+ mr*2);
+#else
+ marker = gdk_gc_new(priv->pixmap);
+ color.red = 5000;
+ color.green = 5000;
+ color.blue = 55000;
+ gdk_gc_set_rgb_fg_color(marker, &color);
+ gdk_gc_set_line_attributes(marker, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ if (r2 > 0) {
+ gdk_draw_arc (priv->pixmap,
+ marker,
+ FALSE, //filled
+ x-r2, y-r2, // x,y
+ r2*2,r2*2, // width, height
+ 0, 360*64); // start-end angle 64th, from 3h, anti clockwise
+ }
+ if (r > 0) {
+ gdk_draw_arc (priv->pixmap,
+ marker,
+ TRUE, //filled
+ x-r, y-r, // x,y
+ r*2,r*2, // width, height
+ 0, 360*64); // start-end angle 64th, from 3h, anti clockwise
+ }
+
+ g_object_unref(marker);
+ gtk_widget_queue_draw_area (GTK_WIDGET(map),
+ x-(mr+lw),
+ y-(mr+lw),
+ (mr*2)+lw+lw,
+ (mr*2)+lw+lw);
+#endif
+ }
+}
+
+static void
+osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);
+
+ /* draw pixbuf onto pixmap */
+ gdk_draw_pixbuf (priv->pixmap,
+ priv->gc_map,
+ pixbuf,
+ 0,0,
+ offset_x,offset_y,
+ TILESIZE,TILESIZE,
+ GDK_RGB_DITHER_NONE, 0, 0);
+}
+
+static void
+osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ int fd;
+ tile_download_t *dl = (tile_download_t *)user_data;
+ OsmGpsMap *map = OSM_GPS_MAP(dl->map);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ if (g_mkdir_with_parents(dl->folder,0700) == 0)
+ {
+ fd = open(dl->filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd != -1)
+ {
+ write (fd, msg->response_body->data, msg->response_body->length);
+ g_debug("Wrote %lld bytes to %s", msg->response_body->length, dl->filename);
+ close (fd);
+
+ if (dl->redraw)
+ {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
+
+ /* Store the tile into the cache */
+ if (G_LIKELY (pixbuf))
+ {
+ OsmCachedTile *tile = g_slice_new (OsmCachedTile);
+ tile->pixbuf = pixbuf;
+ tile->redraw_cycle = priv->redraw_cycle;
+ /* if the tile is already in the cache (it could be one
+ * rendered from another zoom level), it will be
+ * overwritten */
+ g_hash_table_insert (priv->tile_cache, dl->filename, tile);
+ /* NULL-ify dl->filename so that it won't be freed, as
+ * we are using it as a key in the hash table */
+ dl->filename = NULL;
+ }
+ osm_gps_map_map_redraw_idle (map);
+ }
+ }
+ }
+ else
+ {
+ g_warning("Error creating tile download directory: %s", dl->folder);
+ }
+
+ g_hash_table_remove(priv->tile_queue, dl->uri);
+
+ g_free(dl->uri);
+ g_free(dl->folder);
+ g_free(dl->filename);
+ g_free(dl);
+ }
+ else
+ {
+ g_warning("Error downloading tile: %d - %s", msg->status_code, msg->reason_phrase);
+ if (msg->status_code == SOUP_STATUS_NOT_FOUND)
+ {
+ g_hash_table_insert(priv->missing_tiles, dl->uri, NULL);
+ g_hash_table_remove(priv->tile_queue, dl->uri);
+ }
+ else if (msg->status_code == SOUP_STATUS_CANCELLED)
+ {
+ ;//application exiting
+ }
+ else
+ {
+ soup_session_requeue_message(session, msg);
+ return;
+ }
+ }
+
+
+}
+
+static void
+osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw)
+{
+ SoupMessage *msg;
+ OsmGpsMapPrivate *priv = map->priv;
+ tile_download_t *dl = g_new0(tile_download_t,1);
+
+ //calculate the uri to download
+ dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
+
+ //check the tile has not already been queued for download,
+ //or has been attempted, and its missing
+ if (g_hash_table_lookup_extended(priv->tile_queue, dl->uri, NULL, NULL) ||
+ g_hash_table_lookup_extended(priv->missing_tiles, dl->uri, NULL, NULL) )
+ {
+ g_debug("Tile already downloading (or missing)");
+ g_free(dl->uri);
+ g_free(dl);
+ } else {
+ dl->folder = g_strdup_printf("%s/%d/%d/",priv->cache_dir, zoom, x);
+ dl->filename = g_strdup_printf("%s/%d/%d/%d.png",priv->cache_dir, zoom, x, y);
+ dl->map = map;
+ dl->redraw = redraw;
+
+ g_debug("Download tile: %d,%d z:%d\n\t%s --> %s", x, y, zoom, dl->uri, dl->filename);
+
+ msg = soup_message_new (SOUP_METHOD_GET, dl->uri);
+ if (msg) {
+ if (priv->the_google) {
+ //Set maps.google.com as the referrer
+ g_debug("Setting Google Referrer");
+ soup_message_headers_append(msg->request_headers, "Referer", "http://maps.google.com/");
+ //For google satelite also set the appropriate cookie value
+ if (priv->uri_format & URI_HAS_Q) {
+ const char *cookie = g_getenv("GOOGLE_COOKIE");
+ if (cookie) {
+ g_debug("Adding Google Cookie");
+ soup_message_headers_append(msg->request_headers, "Cookie", cookie);
+ }
+ }
+ }
+
+ g_hash_table_insert (priv->tile_queue, dl->uri, msg);
+ soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);
+ } else {
+ g_warning("Could not create soup message");
+ g_free(dl->uri);
+ g_free(dl->folder);
+ g_free(dl->filename);
+ g_free(dl);
+ }
+ }
+}
+
+static GdkPixbuf *
+osm_gps_map_load_cached_tile (OsmGpsMap *map, int zoom, int x, int y)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ gchar *filename;
+ GdkPixbuf *pixbuf;
+ OsmCachedTile *tile;
+
+ filename = g_strdup_printf("%s/%u/%u/%u.png",
+ priv->cache_dir,
+ zoom, x, y);
+
+ tile = g_hash_table_lookup (priv->tile_cache, filename);
+ if (tile)
+ {
+ g_free (filename);
+ }
+ else
+ {
+ pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+ if (pixbuf)
+ {
+ tile = g_slice_new (OsmCachedTile);
+ tile->pixbuf = pixbuf;
+ g_hash_table_insert (priv->tile_cache, filename, tile);
+ }
+ }
+
+ /* set/update the redraw_cycle timestamp on the tile */
+ if (tile)
+ {
+ tile->redraw_cycle = priv->redraw_cycle;
+ pixbuf = g_object_ref (tile->pixbuf);
+ }
+
+ return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_find_bigger_tile (OsmGpsMap *map, int zoom, int x, int y,
+ int *zoom_found)
+{
+ GdkPixbuf *pixbuf;
+ int next_zoom, next_x, next_y;
+
+ if (zoom == 0) return NULL;
+ next_zoom = zoom - 1;
+ next_x = x / 2;
+ next_y = y / 2;
+ pixbuf = osm_gps_map_load_cached_tile (map, next_zoom, next_x, next_y);
+ if (pixbuf)
+ *zoom_found = next_zoom;
+ else
+ pixbuf = osm_gps_map_find_bigger_tile (map, next_zoom, next_x, next_y,
+ zoom_found);
+ return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_render_missing_tile_upscaled (OsmGpsMap *map, int zoom,
+ int x, int y)
+{
+ GdkPixbuf *pixbuf, *big, *area;
+ int zoom_big, zoom_diff, area_size, area_x, area_y;
+ int modulo;
+
+ big = osm_gps_map_find_bigger_tile (map, zoom, x, y, &zoom_big);
+ if (!big) return NULL;
+
+ g_debug ("Found bigger tile (zoom = %d, wanted = %d)", zoom_big, zoom);
+
+ /* get a Pixbuf for the area to magnify */
+ zoom_diff = zoom - zoom_big;
+ area_size = TILESIZE >> zoom_diff;
+ modulo = 1 << zoom_diff;
+ area_x = (x % modulo) * area_size;
+ area_y = (y % modulo) * area_size;
+ area = gdk_pixbuf_new_subpixbuf (big, area_x, area_y,
+ area_size, area_size);
+ g_object_unref (big);
+ pixbuf = gdk_pixbuf_scale_simple (area, TILESIZE, TILESIZE,
+ GDK_INTERP_NEAREST);
+ g_object_unref (area);
+ return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_render_missing_tile (OsmGpsMap *map, int zoom, int x, int y)
+{
+ /* maybe TODO: render from downscaled tiles, if the following fails */
+ return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);
+}
+
+static void
+osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ gchar *filename;
+ GdkPixbuf *pixbuf;
+
+ g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);
+
+ filename = g_strdup_printf("%s/%u/%u/%u.png",
+ priv->cache_dir,
+ zoom, x, y);
+
+ pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+ if(pixbuf)
+ {
+ g_debug("Found tile %s", filename);
+ osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);
+ g_object_unref (pixbuf);
+ }
+ else
+ {
+ if (priv->map_auto_download)
+ osm_gps_map_download_tile(map, zoom, x, y, TRUE);
+
+ /* try to render the tile by scaling cached tiles from other zoom
+ * levels */
+ pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);
+ if (pixbuf)
+ {
+ gdk_draw_pixbuf (priv->pixmap,
+ priv->gc_map,
+ pixbuf,
+ 0,0,
+ offset_x,offset_y,
+ TILESIZE,TILESIZE,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ g_object_unref (pixbuf);
+ }
+ else
+ {
+ //prevent some artifacts when drawing not yet loaded areas.
+ gdk_draw_rectangle (priv->pixmap,
+ GTK_WIDGET(map)->style->white_gc,
+ TRUE, offset_x, offset_y, TILESIZE, TILESIZE);
+ }
+ }
+ g_free(filename);
+}
+
+static void
+osm_gps_map_fill_tiles_pixel (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ int i,j, width, height, tile_x0, tile_y0, tiles_nx, tiles_ny;
+ int offset_xn = 0;
+ int offset_yn = 0;
+ int offset_x;
+ int offset_y;
+
+ g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);
+
+ offset_x = - priv->map_x % TILESIZE;
+ offset_y = - priv->map_y % TILESIZE;
+ if (offset_x > 0) offset_x -= TILESIZE;
+ if (offset_y > 0) offset_y -= TILESIZE;
+
+ offset_xn = offset_x + EXTRA_BORDER;
+ offset_yn = offset_y + EXTRA_BORDER;
+
+ width = GTK_WIDGET(map)->allocation.width;
+ height = GTK_WIDGET(map)->allocation.height;
+
+ tiles_nx = (width - offset_x) / TILESIZE + 1;
+ tiles_ny = (height - offset_y) / TILESIZE + 1;
+
+ tile_x0 = floor((float)priv->map_x / (float)TILESIZE);
+ tile_y0 = floor((float)priv->map_y / (float)TILESIZE);
+
+ //TODO: implement wrap around
+ for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
+ {
+ for (j=tile_y0; j<(tile_y0+tiles_ny); j++)
+ {
+ if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
+ {
+ gdk_draw_rectangle (priv->pixmap,
+ GTK_WIDGET(map)->style->white_gc,
+ TRUE,
+ offset_xn, offset_yn,
+ TILESIZE,TILESIZE);
+ }
+ else
+ {
+ osm_gps_map_load_tile(map,
+ priv->map_zoom,
+ i,j,
+ offset_xn,offset_yn);
+ }
+ offset_yn += TILESIZE;
+ }
+ offset_xn += TILESIZE;
+ offset_yn = offset_y + EXTRA_BORDER;
+ }
+}
+
+static void
+osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ GSList *list;
+ int x,y;
+ int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
+ int lw = priv->ui_gps_track_width;
+ int map_x0, map_y0;
+#ifdef USE_CAIRO
+ cairo_t *cr;
+#else
+ int last_x = 0, last_y = 0;
+ GdkColor color;
+ GdkGC *gc;
+#endif
+
+#ifdef USE_CAIRO
+ cr = gdk_cairo_create(priv->pixmap);
+ cairo_set_line_width (cr, lw);
+ cairo_set_source_rgba (cr, 60000.0/65535.0, 0.0, 0.0, 0.6);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+#else
+ gc = gdk_gc_new(priv->pixmap);
+ color.green = 0;
+ color.blue = 0;
+ color.red = 60000;
+ gdk_gc_set_rgb_fg_color(gc, &color);
+ gdk_gc_set_line_attributes(gc, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+#endif
+
+ map_x0 = priv->map_x - EXTRA_BORDER;
+ map_y0 = priv->map_y - EXTRA_BORDER;
+ for(list = trackpoint_list; list != NULL; list = list->next)
+ {
+ coord_t *tp = list->data;
+
+ x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
+ y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
+
+ // first time through loop
+ if (list == trackpoint_list) {
+#ifdef USE_CAIRO
+ cairo_move_to(cr, x, y);
+#else
+ last_x = x;
+ last_y = y;
+#endif
+ }
+
+#ifdef USE_CAIRO
+ cairo_line_to(cr, x, y);
+#else
+ gdk_draw_line (priv->pixmap, gc, x, y, last_x, last_y);
+ last_x = x;
+ last_y = y;
+#endif
+
+ max_x = MAX(x,max_x);
+ min_x = MIN(x,min_x);
+ max_y = MAX(y,max_y);
+ min_y = MIN(y,min_y);
+ }
+
+ gtk_widget_queue_draw_area (
+ GTK_WIDGET(map),
+ min_x - lw,
+ min_y - lw,
+ max_x + (lw * 2),
+ max_y + (lw * 2));
+
+#ifdef USE_CAIRO
+ cairo_stroke(cr);
+ cairo_destroy(cr);
+#else
+ g_object_unref(gc);
+#endif
+}
+
+/* Prints the gps trip history, and any other tracks */
+static void
+osm_gps_map_print_tracks (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (priv->show_trip_history)
+ osm_gps_map_print_track (map, priv->trip_history);
+ if (priv->tracks)
+ {
+ g_debug("TRACK");
+ GSList* tmp = priv->tracks;
+ while (tmp != NULL)
+ {
+ osm_gps_map_print_track (map, tmp->data);
+ tmp = g_slist_next(tmp);
+ }
+ }
+}
+
+static void
+osm_gps_map_purge_cache (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+ GHashTableIter iter;
+ OsmCachedTile *tile;
+
+ if (g_hash_table_size (priv->tile_cache) < priv->max_tile_cache_size)
+ return;
+
+ /* run through the cache, and remove the tiles which have not been used
+ * during the last redraw operation */
+ g_hash_table_iter_init (&iter, priv->tile_cache);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer)&tile))
+ {
+ if (tile->redraw_cycle != priv->redraw_cycle)
+ g_hash_table_iter_remove (&iter);
+ }
+}
+
+static gboolean
+osm_gps_map_map_redraw (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ priv->idle_map_redraw = 0;
+
+ /* the motion_notify handler uses priv->pixmap to redraw the area; if we
+ * change it while we are dragging, we will end up showing it in the wrong
+ * place. This could be fixed by carefully recompute the coordinates, but
+ * for now it's easier just to disable redrawing the map while dragging */
+ if (priv->dragging)
+ return FALSE;
+
+ priv->redraw_cycle++;
+
+ /* draw white background to initialise pixmap */
+ gdk_draw_rectangle (
+ priv->pixmap,
+ GTK_WIDGET(map)->style->white_gc,
+ TRUE,
+ 0, 0,
+ GTK_WIDGET(map)->allocation.width + EXTRA_BORDER * 2,
+ GTK_WIDGET(map)->allocation.height + EXTRA_BORDER * 2);
+
+ osm_gps_map_fill_tiles_pixel(map);
+
+ osm_gps_map_print_tracks(map);
+ osm_gps_map_draw_gps_point(map);
+ osm_gps_map_print_images(map);
+
+ //osm_gps_map_osd_speed(map, 1.5);
+ osm_gps_map_purge_cache(map);
+ gtk_widget_queue_draw (GTK_WIDGET (map));
+
+ return FALSE;
+}
+
+static void
+osm_gps_map_map_redraw_idle (OsmGpsMap *map)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (priv->idle_map_redraw == 0)
+ priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);
+}
+
+static void
+osm_gps_map_init (OsmGpsMap *object)
+{
+ OsmGpsMapPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
+ object->priv = priv;
+
+ priv->pixmap = NULL;
+
+ priv->trip_history = NULL;
+ priv->gps = g_new0(coord_t, 1);
+ priv->gps_valid = FALSE;
+
+ priv->tracks = NULL;
+ priv->images = NULL;
+
+ priv->drag_counter = 0;
+ priv->drag_mouse_dx = 0;
+ priv->drag_mouse_dy = 0;
+ priv->drag_start_mouse_x = 0;
+ priv->drag_start_mouse_y = 0;
+
+ priv->uri_format = 0;
+ priv->the_google = FALSE;
+
+ //Change naumber of concurrent connections option?
+ priv->soup_session = soup_session_async_new_with_options(
+ SOUP_SESSION_USER_AGENT,
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11",
+ NULL);
+
+ //Hash table which maps tile d/l URIs to SoupMessage requests
+ priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);
+
+ //Some mapping providers (Google) have varying degrees of tiles at multiple
+ //zoom levels
+ priv->missing_tiles = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* memory cache for most recently used tiles */
+ priv->tile_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify)cached_tile_free);
+ priv->max_tile_cache_size = 20;
+
+ gtk_widget_add_events (GTK_WIDGET (object),
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+ GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
+
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
+}
+
+static GObject *
+osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
+{
+ GObject *object;
+ OsmGpsMapPrivate *priv;
+
+ //Always chain up to the parent constructor
+ object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
+ priv = OSM_GPS_MAP_PRIVATE(object);
+
+ if (!priv->cache_dir_is_full_path) {
+ char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
+
+ if (priv->cache_dir) {
+ char *old = priv->cache_dir;
+ //the new cachedir is the given cache dir + the md5 of the repo_uri
+ priv->cache_dir = g_strdup_printf("%s/%s", old, md5);
+ g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir);
+ g_free(old);
+ } else {
+ //the new cachedir is the current dir + the md5 of the repo_uri
+ priv->cache_dir = g_strdup(md5);
+ }
+
+ g_free(md5);
+ }
+
+ return object;
+}
+
+static void
+osm_gps_map_dispose (GObject *object)
+{
+ OsmGpsMap *map = OSM_GPS_MAP(object);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (priv->is_disposed)
+ return;
+
+ priv->is_disposed = TRUE;
+
+ soup_session_abort(priv->soup_session);
+ g_object_unref(priv->soup_session);
+
+ g_hash_table_destroy(priv->tile_queue);
+ g_hash_table_destroy(priv->missing_tiles);
+ g_hash_table_destroy(priv->tile_cache);
+
+ osm_gps_map_free_images(map);
+
+ if(priv->pixmap)
+ g_object_unref (priv->pixmap);
+
+ if(priv->gc_map)
+ g_object_unref(priv->gc_map);
+
+ if (priv->idle_map_redraw != 0)
+ g_source_remove (priv->idle_map_redraw);
+
+ G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
+}
+
+static void
+osm_gps_map_finalize (GObject *object)
+{
+ OsmGpsMap *map = OSM_GPS_MAP(object);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ g_free(priv->cache_dir);
+ g_free(priv->repo_uri);
+
+ osm_gps_map_free_trip(map);
+ osm_gps_map_free_tracks(map);
+
+ G_OBJECT_CLASS (osm_gps_map_parent_class)->finalize (object);
+}
+
+static void
+osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ g_return_if_fail (OSM_IS_GPS_MAP (object));
+ OsmGpsMap *map = OSM_GPS_MAP(object);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ switch (prop_id)
+ {
+ case PROP_AUTO_CENTER:
+ priv->map_auto_center = g_value_get_boolean (value);
+ break;
+ case PROP_RECORD_TRIP_HISTORY:
+ priv->record_trip_history = g_value_get_boolean (value);
+ break;
+ case PROP_SHOW_TRIP_HISTORY:
+ priv->show_trip_history = g_value_get_boolean (value);
+ break;
+ case PROP_AUTO_DOWNLOAD:
+ priv->map_auto_download = g_value_get_boolean (value);
+ break;
+ case PROP_REPO_URI:
+ priv->repo_uri = g_value_dup_string (value);
+ inspect_map_uri(map);
+ break;
+ case PROP_PROXY_URI:
+ if ( g_value_get_string(value) ) {
+ GValue val = {0};
+
+ priv->proxy_uri = g_value_dup_string (value);
+ g_debug("Setting proxy server: %s", priv->proxy_uri);
+
+ SoupURI* uri = soup_uri_new(priv->proxy_uri);
+ g_value_init(&val, SOUP_TYPE_URI);
+ g_value_take_boxed(&val, uri);
+
+ g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
+ } else
+ priv->proxy_uri = NULL;
+
+ break;
+ case PROP_TILE_CACHE_DIR:
+ priv->cache_dir = g_value_dup_string (value);
+ break;
+ case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
+ priv->cache_dir_is_full_path = g_value_get_boolean (value);
+ break;
+ case PROP_ZOOM:
+ priv->map_zoom = g_value_get_int (value);
+ break;
+ case PROP_MAX_ZOOM:
+ priv->max_zoom = g_value_get_int (value);
+ break;
+ case PROP_MIN_ZOOM:
+ priv->min_zoom = g_value_get_int (value);
+ break;
+ case PROP_MAP_X:
+ priv->map_x = g_value_get_int (value);
+ priv->center_coord_set = FALSE;
+ break;
+ case PROP_MAP_Y:
+ priv->map_y = g_value_get_int (value);
+ priv->center_coord_set = FALSE;
+ break;
+ case PROP_GPS_TRACK_WIDTH:
+ priv->ui_gps_track_width = g_value_get_int (value);
+ break;
+ case PROP_GPS_POINT_R1:
+ priv->ui_gps_point_inner_radius = g_value_get_int (value);
+ break;
+ case PROP_GPS_POINT_R2:
+ priv->ui_gps_point_outer_radius = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ g_return_if_fail (OSM_IS_GPS_MAP (object));
+ float lat,lon;
+ OsmGpsMap *map = OSM_GPS_MAP(object);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ switch (prop_id)
+ {
+ case PROP_AUTO_CENTER:
+ g_value_set_boolean(value, priv->map_auto_center);
+ break;
+ case PROP_RECORD_TRIP_HISTORY:
+ g_value_set_boolean(value, priv->record_trip_history);
+ break;
+ case PROP_SHOW_TRIP_HISTORY:
+ g_value_set_boolean(value, priv->show_trip_history);
+ break;
+ case PROP_AUTO_DOWNLOAD:
+ g_value_set_boolean(value, priv->map_auto_download);
+ break;
+ case PROP_REPO_URI:
+ g_value_set_string(value, priv->repo_uri);
+ break;
+ case PROP_PROXY_URI:
+ g_value_set_string(value, priv->proxy_uri);
+ break;
+ case PROP_TILE_CACHE_DIR:
+ g_value_set_string(value, priv->cache_dir);
+ break;
+ case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
+ g_value_set_boolean(value, priv->cache_dir_is_full_path);
+ break;
+ case PROP_ZOOM:
+ g_value_set_int(value, priv->map_zoom);
+ break;
+ case PROP_MAX_ZOOM:
+ g_value_set_int(value, priv->max_zoom);
+ break;
+ case PROP_MIN_ZOOM:
+ g_value_set_int(value, priv->min_zoom);
+ break;
+ case PROP_LATITUDE:
+ lat = pixel2lat(priv->map_zoom,
+ priv->map_y + (GTK_WIDGET(map)->allocation.height / 2));
+ g_value_set_float(value, rad2deg(lat));
+ break;
+ case PROP_LONGITUDE:
+ lon = pixel2lon(priv->map_zoom,
+ priv->map_x + (GTK_WIDGET(map)->allocation.width / 2));
+ g_value_set_float(value, rad2deg(lon));
+ break;
+ case PROP_MAP_X:
+ g_value_set_int(value, priv->map_x);
+ break;
+ case PROP_MAP_Y:
+ g_value_set_int(value, priv->map_y);
+ break;
+ case PROP_TILES_QUEUED:
+ g_value_set_int(value, g_hash_table_size(priv->tile_queue));
+ break;
+ case PROP_GPS_TRACK_WIDTH:
+ g_value_set_int(value, priv->ui_gps_track_width);
+ break;
+ case PROP_GPS_POINT_R1:
+ g_value_set_int(value, priv->ui_gps_point_inner_radius);
+ break;
+ case PROP_GPS_POINT_R2:
+ g_value_set_int(value, priv->ui_gps_point_outer_radius);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+_osm_gps_map_scroll (GtkWidget *widget, GdkEventScroll *event)
+{
+ OsmGpsMap *map = OSM_GPS_MAP(widget);
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (event->direction == GDK_SCROLL_UP)
+ {
+ osm_gps_map_set_zoom(map, priv->map_zoom+1);
+ }
+ else
+ {
+ osm_gps_map_set_zoom(map, priv->map_zoom-1);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+ priv->drag_counter = 0;
+ priv->drag_start_mouse_x = (int) event->x;
+ priv->drag_start_mouse_y = (int) event->y;
+ priv->drag_start_map_x = priv->map_x;
+ priv->drag_start_map_y = priv->map_y;
+
+ return FALSE;
+}
+
+static gboolean
+osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+ OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+ if (priv->dragging)
+ {
+ priv->dragging = FALSE;
+
+ priv->map_x = priv->drag_start_map_x;
+ priv->map_y = priv->drag_start_map_y;
+
+ priv->map_x += (priv->drag_start_mouse_x - (int) event->x);
+ priv->map_y += (priv->drag_start_mouse_y - (int) event->y);
+
+ priv->center_coord_set = FALSE;
+
+ osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
+ }
+
+ priv->drag_mouse_dx = 0;
+ priv->drag_mouse_dy = 0;
+ priv->drag_counter = 0;
+
+ return FALSE;
+}
+
+static gboolean
+osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion *event)
+{
+ int x, y;
+ GdkModifierType state;
+ OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+ if (event->is_hint)
+ gdk_window_get_pointer (event->window, &x, &y, &state);
+ else
+ {
+ x = event->x;
+ y = event->y;
+ state = event->state;
+ }
+
+ // are we being dragged
+ if (!(state & GDK_BUTTON1_MASK))
+ return FALSE;
+
+ priv->drag_counter++;
+
+ // we havent dragged more than 6 pixels
+ if (priv->drag_counter < 6)
+ return FALSE;
+
+ priv->dragging = TRUE;
+
+ if (priv->map_auto_center)
+ g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
+
+ priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
+ priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
+
+ gdk_draw_drawable (
+ widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ priv->pixmap,
+ 0,0,
+ priv->drag_mouse_dx - EXTRA_BORDER, priv->drag_mouse_dy - EXTRA_BORDER,
+ -1,-1);
+
+ //Paint white outside of the map if dragging. Its less
+ //ugly than painting the corrupted map
+ if(priv->drag_mouse_dx>EXTRA_BORDER) {
+ gdk_draw_rectangle (
+ widget->window,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ priv->drag_mouse_dx - EXTRA_BORDER,
+ widget->allocation.height);
+ }
+ else if (-priv->drag_mouse_dx > EXTRA_BORDER)
+ {
+ gdk_draw_rectangle (
+ widget->window,
+ widget->style->white_gc,
+ TRUE,
+ priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,
+ -priv->drag_mouse_dx - EXTRA_BORDER,
+ widget->allocation.height);
+ }
+
+ if (priv->drag_mouse_dy>EXTRA_BORDER) {
+ gdk_draw_rectangle (
+ widget->window,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ priv->drag_mouse_dy - EXTRA_BORDER);
+ }
+ else if (-priv->drag_mouse_dy > EXTRA_BORDER)
+ {
+ gdk_draw_rectangle (
+ widget->window,
+ widget->style->white_gc,
+ TRUE,
+ 0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,
+ widget->allocation.width,
+ -priv->drag_mouse_dy - EXTRA_BORDER);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
+{
+ OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+ /* create pixmap */
+ if (priv->pixmap)
+ g_object_unref (priv->pixmap);
+
+ priv->pixmap = gdk_pixmap_new (
+ widget->window,
+ widget->allocation.width + EXTRA_BORDER * 2,
+ widget->allocation.height + EXTRA_BORDER * 2,
+ -1);
+
+ /* and gc, used for clipping (I think......) */
+ if(priv->gc_map)
+ g_object_unref(priv->gc_map);
+
+ priv->gc_map = gdk_gc_new(priv->pixmap);
+
+ osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
+
+ return FALSE;
+}
+
+static gboolean
+osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+ OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+ gdk_draw_drawable (
+ widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ priv->pixmap,
+ event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+static void
+osm_gps_map_class_init (OsmGpsMapClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate));
+
+ object_class->dispose = osm_gps_map_dispose;
+ object_class->finalize = osm_gps_map_finalize;
+ object_class->constructor = osm_gps_map_constructor;
+ object_class->set_property = osm_gps_map_set_property;
+ object_class->get_property = osm_gps_map_get_property;
+
+ widget_class->expose_event = osm_gps_map_expose;
+ widget_class->configure_event = osm_gps_map_configure;
+ widget_class->button_press_event = osm_gps_map_button_press;
+ widget_class->button_release_event = osm_gps_map_button_release;
+ widget_class->motion_notify_event = osm_gps_map_motion_notify;
+ widget_class->scroll_event = _osm_gps_map_scroll;
+
+ g_object_class_install_property (object_class,
+ PROP_AUTO_CENTER,
+ g_param_spec_boolean ("auto-center",
+ "auto center",
+ "map auto center",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_RECORD_TRIP_HISTORY,
+ g_param_spec_boolean ("record-trip-history",
+ "record trip history",
+ "should all gps points be recorded in a trip history",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_SHOW_TRIP_HISTORY,
+ g_param_spec_boolean ("show-trip-history",
+ "show trip history",
+ "should the recorded trip history be shown on the map",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_AUTO_DOWNLOAD,
+ g_param_spec_boolean ("auto-download",
+ "auto download",
+ "map auto download",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_REPO_URI,
+ g_param_spec_string ("repo-uri",
+ "repo uri",
+ "osm repo uri",
+ "http://tile.openstreetmap.org/#Z/#X/#Y.png",
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_PROXY_URI,
+ g_param_spec_string ("proxy-uri",
+ "proxy uri",
+ "http proxy uri on NULL",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_TILE_CACHE_DIR,
+ g_param_spec_string ("tile-cache",
+ "tile cache",
+ "osm local tile cache dir",
+ "/tmp/Maps",
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_TILE_CACHE_DIR_IS_FULL_PATH,
+ g_param_spec_boolean ("tile-cache-is-full-path",
+ "tile cache is full path",
+ "if true, the path passed to tile-cache is interpreted as the full cache path",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_ZOOM,
+ g_param_spec_int ("zoom",
+ "zoom",
+ "zoom level",
+ MIN_ZOOM, /* minimum property value */
+ MAX_ZOOM, /* maximum property value */
+ 3,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_MAX_ZOOM,
+ g_param_spec_int ("max-zoom",
+ "max zoom",
+ "maximum zoom level",
+ MIN_ZOOM, /* minimum property value */
+ MAX_ZOOM, /* maximum property value */
+ 17,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_MIN_ZOOM,
+ g_param_spec_int ("min-zoom",
+ "min zoom",
+ "minimum zoom level",
+ MIN_ZOOM, /* minimum property value */
+ MAX_ZOOM, /* maximum property value */
+ 1,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_LATITUDE,
+ g_param_spec_float ("latitude",
+ "latitude",
+ "latitude in degrees",
+ -90.0, /* minimum property value */
+ 90.0, /* maximum property value */
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_LONGITUDE,
+ g_param_spec_float ("longitude",
+ "longitude",
+ "longitude in degrees",
+ -180.0, /* minimum property value */
+ 180.0, /* maximum property value */
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_MAP_X,
+ g_param_spec_int ("map-x",
+ "map-x",
+ "initial map x location",
+ G_MININT, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 890,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_MAP_Y,
+ g_param_spec_int ("map-y",
+ "map-y",
+ "initial map y location",
+ G_MININT, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 515,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_TILES_QUEUED,
+ g_param_spec_int ("tiles-queued",
+ "tiles-queued",
+ "number of tiles currently waiting to download",
+ G_MININT, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_GPS_TRACK_WIDTH,
+ g_param_spec_int ("gps-track-width",
+ "gps-track-width",
+ "width of the lines drawn for the gps track",
+ 1, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 4,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_GPS_POINT_R1,
+ g_param_spec_int ("gps-track-point-radius",
+ "gps-track-point-radius",
+ "radius of the gps point inner circle",
+ 0, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 5,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_GPS_POINT_R2,
+ g_param_spec_int ("gps-track-highlight-radius",
+ "gps-track-highlight-radius",
+ "radius of the gps point highlight circle",
+ 0, /* minimum property value */
+ G_MAXINT, /* maximum property value */
+ 20,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+}
+
+void
+osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)
+{
+ int i,j,zoom,num_tiles;
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (pt1 && pt2)
+ {
+ gchar *filename;
+ num_tiles = 0;
+ zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom);
+ g_debug("Download maps: z:%d->%d",zoom_start, zoom_end);
+
+ for(zoom=zoom_start; zoom<=zoom_end; zoom++)
+ {
+ int x1,y1,x2,y2;
+
+ x1 = (int)floor((float)lon2pixel(zoom, pt1->rlon) / (float)TILESIZE);
+ y1 = (int)floor((float)lat2pixel(zoom, pt1->rlat) / (float)TILESIZE);
+
+ x2 = (int)floor((float)lon2pixel(zoom, pt2->rlon) / (float)TILESIZE);
+ y2 = (int)floor((float)lat2pixel(zoom, pt2->rlat) / (float)TILESIZE);
+
+ // loop x1-x2
+ for(i=x1; i<=x2; i++)
+ {
+ // loop y1 - y2
+ for(j=y1; j<=y2; j++)
+ {
+ // x = i, y = j
+ filename = g_strdup_printf("%s/%u/%u/%u.png", priv->cache_dir, zoom, i, j);
+ if (!g_file_test(filename, G_FILE_TEST_EXISTS))
+ {
+ osm_gps_map_download_tile(map, zoom, i, j, FALSE);
+ num_tiles++;
+ }
+ g_free(filename);
+ }
+ }
+ g_debug("DL @Z:%d = %d tiles",zoom,num_tiles);
+ }
+ }
+}
+
+void
+osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2)
+{
+ OsmGpsMapPrivate *priv = map->priv;
+
+ if (pt1 && pt2) {
+ pt1->rlat = pixel2lat(priv->map_zoom, priv->map_y);
+ pt1->rlon = pixel2lon(priv->map_zoom, priv->map_x);
+ pt2->rlat = pixel2lat(priv->map_zoom, priv->map_y + GTK_WIDGET(map)->allocation.height);
+ pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + GTK_WIDGET(map)->allocation.width);
+
+ g_debug("BBOX: %f %f %f %f", pt1->rlat, pt1->rlon, pt2->rlat, pt2->rlon);
+ }
+}
+
+void
+osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom)
+{
+ osm_gps_map_set_center (map, latitude, longitude);
+ osm_gps_map_set_zoom (map, zoom);
+}
+
+void
+osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
+{
+ int pixel_x, pixel_y;
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ priv->center_rlat = deg2rad(latitude);
+ priv->center_rlon = deg2rad(longitude);
+ priv->center_coord_set = TRUE;
+
+ // pixel_x,y, offsets
+ pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
+ pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
+
+ priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
+ priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
+
+ osm_gps_map_map_redraw_idle(map);
+}
+
+int
+osm_gps_map_set_zoom (OsmGpsMap *map, int zoom)
+{
+ int zoom_old;
+ double factor;
+ int width_center, height_center;
+ OsmGpsMapPrivate *priv;
+
+ g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
+ priv = map->priv;
+
+ if (zoom != priv->map_zoom)
+ {
+ width_center = GTK_WIDGET(map)->allocation.width / 2;
+ height_center = GTK_WIDGET(map)->allocation.height / 2;
+
+ zoom_old = priv->map_zoom;
+ //constrain zoom min_zoom -> max_zoom
+ priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);
+
+ if (priv->center_coord_set)
+ {
+ priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
+ priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
+ }
+ else
+ {
+ factor = exp(priv->map_zoom * M_LN2)/exp(zoom_old * M_LN2);
+ priv->map_x = ((priv->map_x + width_center) * factor) - width_center;
+ priv->map_y = ((priv->map_y + height_center) * factor) - height_center;
+ }
+
+ g_debug("Zoom changed from %d to %d factor:%f x:%d",
+ zoom_old, priv->map_zoom, factor, priv->map_x);
+
+ osm_gps_map_map_redraw_idle(map);
+ }
+ return priv->map_zoom;
+}
+
+void
+osm_gps_map_add_track (OsmGpsMap *map, GSList *track)
+{
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ if (track) {
+ priv->tracks = g_slist_append(priv->tracks, track);
+ osm_gps_map_map_redraw_idle(map);
+ }
+}
+
+void
+osm_gps_map_clear_tracks (OsmGpsMap *map)
+{
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+ osm_gps_map_free_tracks(map);
+ osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
+{
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+ if (image) {
+ OsmGpsMapPrivate *priv = map->priv;
+ image_t *im;
+
+ //cache w/h for speed, and add image to list
+ im = g_new0(image_t,1);
+ im->w = gdk_pixbuf_get_width(image);
+ im->h = gdk_pixbuf_get_width(image);
+ im->pt.rlat = deg2rad(latitude);
+ im->pt.rlon = deg2rad(longitude);
+
+ g_object_ref(image);
+ im->image = image;
+
+ priv->images = g_slist_append(priv->images, im);
+
+ osm_gps_map_map_redraw_idle(map);
+ }
+}
+
+void
+osm_gps_map_clear_images (OsmGpsMap *map)
+{
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+ osm_gps_map_free_images(map);
+ osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_osd_speed (OsmGpsMap *map, float speed)
+{
+ OsmGpsMapPrivate *priv;
+
+ PangoContext *context = NULL;
+ PangoLayout *layout = NULL;
+ PangoFontDescription *desc = NULL;
+
+ GdkColor color;
+ GdkGC *gc;
+
+ gchar *buffer;
+ //static int x = 10, y = 10;
+ static int width = 0, height = 0;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ buffer = g_strdup_printf("%.0f", speed);
+
+ /* pango initialisation */
+ context = gtk_widget_get_pango_context (GTK_WIDGET(map));
+ layout = pango_layout_new (context);
+ desc = pango_font_description_new();
+
+ pango_font_description_set_size (desc, 40 * PANGO_SCALE);
+ pango_layout_set_font_description (layout, desc);
+ pango_layout_set_text (layout, buffer, strlen(buffer));
+
+ gc = gdk_gc_new (GTK_WIDGET(map)->window);
+
+ color.red = (0 > 50) ? 0xffff : 0;
+ color.green = 0;
+ color.blue = 0;
+
+ gdk_gc_set_rgb_fg_color (gc, &color);
+
+ /* faster / less flicker alternative:*/
+ gdk_draw_drawable (
+ GTK_WIDGET(map)->window,
+ GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(map)],
+ priv->pixmap,
+ 0,0,
+ 0,0,
+ width+10,width+10);
+
+ gdk_draw_layout(GTK_WIDGET(map)->window,
+ gc,
+ 0, 0,
+ layout);
+
+ /* set width and height */
+ pango_layout_get_pixel_size(layout, &width, &height);
+
+ g_free(buffer);
+ pango_font_description_free (desc);
+ g_object_unref (layout);
+ g_object_unref (gc);
+}
+
+void
+osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
+{
+ int pixel_x, pixel_y;
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ priv->gps->rlat = deg2rad(latitude);
+ priv->gps->rlon = deg2rad(longitude);
+ priv->gps_valid = TRUE;
+
+ // pixel_x,y, offsets
+ pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
+ pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat);
+
+ //If trip marker add to list of gps points.
+ if (priv->record_trip_history) {
+ coord_t *tp = g_new0(coord_t,1);
+ tp->rlat = priv->gps->rlat;
+ tp->rlon = priv->gps->rlon;
+ priv->trip_history = g_slist_append(priv->trip_history, tp);
+ }
+
+ // dont draw anything if we are dragging
+ if (priv->dragging) {
+ g_debug("Dragging");
+ return;
+ }
+
+ //Automatically center the map if the track approaches the edge
+ if(priv->map_auto_center) {
+ int x = pixel_x - priv->map_x;
+ int y = pixel_y - priv->map_y;
+ int width = GTK_WIDGET(map)->allocation.width;
+ int height = GTK_WIDGET(map)->allocation.height;
+ if( x < (width/2 - width/8) || x > (width/2 + width/8) ||
+ y < (height/2 - height/8) || y > (height/2 + height/8)) {
+
+ priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
+ priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
+ priv->center_coord_set = FALSE;
+ }
+ }
+
+ // this redraws the map (including the gps track, and adjusts the
+ // map center if it was changed
+ osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_clear_gps (OsmGpsMap *map)
+{
+ osm_gps_map_free_trip(map);
+ osm_gps_map_map_redraw_idle(map);
+}
+
+coord_t
+osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y)
+{
+ coord_t coord;
+ OsmGpsMapPrivate *priv = map->priv;
+
+ coord.rlat = pixel2lat(priv->map_zoom, priv->map_y + pixel_y);
+ coord.rlon = pixel2lon(priv->map_zoom, priv->map_x + pixel_x);
+ return coord;
+}
+
+GtkWidget *
+osm_gps_map_new (void)
+{
+ return g_object_new (OSM_TYPE_GPS_MAP, NULL);
+}
+
+void
+osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y,
+ gfloat *latitude, gfloat *longitude)
+{
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ if (latitude)
+ *latitude = rad2deg(pixel2lat(priv->map_zoom, priv->map_y + pixel_y));
+ if (longitude)
+ *longitude = rad2deg(pixel2lon(priv->map_zoom, priv->map_x + pixel_x));
+}
+
+void
+osm_gps_map_geographic_to_screen (OsmGpsMap *map,
+ gfloat latitude, gfloat longitude,
+ gint *pixel_x, gint *pixel_y)
+{
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ if (pixel_x)
+ *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) - priv->map_x;
+ if (pixel_y)
+ *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) - priv->map_y;
+}
+
+void
+osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy)
+{
+ OsmGpsMapPrivate *priv;
+
+ g_return_if_fail (OSM_IS_GPS_MAP (map));
+ priv = map->priv;
+
+ priv->center_coord_set = FALSE;
+ priv->map_x += dx;
+ priv->map_y += dy;
+
+ osm_gps_map_map_redraw_idle (map);
+}
+
diff --git a/src/osm-gps-map.h b/src/osm-gps-map.h
new file mode 100644
index 0000000..1069976
--- /dev/null
+++ b/src/osm-gps-map.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OSM_GPS_MAP_H_
+#define _OSM_GPS_MAP_H_
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+#define OSM_TYPE_GPS_MAP (osm_gps_map_get_type ())
+#define OSM_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP, OsmGpsMap))
+#define OSM_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
+#define OSM_IS_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP))
+#define OSM_IS_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP))
+#define OSM_GPS_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
+
+typedef struct _OsmGpsMapClass OsmGpsMapClass;
+typedef struct _OsmGpsMap OsmGpsMap;
+typedef struct _OsmGpsMapPrivate OsmGpsMapPrivate;
+
+struct _OsmGpsMapClass
+{
+ GtkDrawingAreaClass parent_class;
+};
+
+struct _OsmGpsMap
+{
+ GtkDrawingArea parent_instance;
+ OsmGpsMapPrivate *priv;
+};
+
+typedef struct {
+ float rlat;
+ float rlon;
+} coord_t;
+
+//http://www.internettablettalk.com/forums/showthread.php?t=5209
+//https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c
+//http://www.ponies.me.uk/maps/GoogleTileUtils.java
+//http://www.mgmaps.com/cache/MapTileCacher.perl
+#define MAP_SOURCE_OPENSTREETMAP "http://tile.openstreetmap.org/#Z/#X/#Y.png"
+#define MAP_SOURCE_OPENSTREETMAP_RENDERER "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png"
+#define MAP_SOURCE_OPENAERIALMAP "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/#Z/#X/#Y.jpg"
+#define MAP_SOURCE_GOOGLE_MAPS "http://mt#R.google.com/mt?x=#X&y=#Y&zoom=#S"
+//No longer working
+//#define MAP_SOURCE_GOOGLE_HYBRID "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S"
+#define MAP_SOURCE_GOOGLE_HYBRID "http://mt#R.google.com/mt?x=#X&y=#Y&zoom=#S"
+#define MAP_SOURCE_GOOGLE_SATTELITE "http://khm#R.google.com/kh?n=404&v=32&x=#X&y=#Y&z=#Z"
+#define MAP_SOURCE_GOOGLE_SATTELITE_QUAD "http://khm#R.google.com/kh?n=404&v=3&t=#Q"
+#define MAP_SOURCE_MAPS_FOR_FREE "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg"
+#define MAP_SOURCE_VIRTUAL_EARTH_SATTELITE "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50"
+
+GType osm_gps_map_get_type (void) G_GNUC_CONST;
+void osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end);
+void osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2);
+void osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom);
+void osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude);
+int osm_gps_map_set_zoom (OsmGpsMap *map, int zoom);
+void osm_gps_map_add_track (OsmGpsMap *map, GSList *track);
+void osm_gps_map_clear_tracks (OsmGpsMap *map);
+void osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image);
+void osm_gps_map_clear_images (OsmGpsMap *map);
+void osm_gps_map_osd_speed (OsmGpsMap *map, float speed);
+void osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading);
+void osm_gps_map_clear_gps (OsmGpsMap *map);
+coord_t osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y);
+GtkWidget * osm_gps_map_new(void);
+void osm_gps_map_screen_to_geographic (OsmGpsMap *map,
+ gint pixel_x, gint pixel_y,
+ gfloat *latitude, gfloat *longitude);
+void osm_gps_map_geographic_to_screen (OsmGpsMap *map,
+ gfloat latitude, gfloat longitude,
+ gint *pixel_x, gint *pixel_y);
+void osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy);
+
+G_END_DECLS
+
+#endif /* _OSM_GPS_MAP_H_ */
diff --git a/src/poi.png b/src/poi.png
new file mode 100644
index 0000000..4ab54c9
Binary files /dev/null and b/src/poi.png differ
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osm-gps-map.git
More information about the Pkg-grass-devel
mailing list