pax_global_header00006660000000000000000000000064126234517330014520gustar00rootroot0000000000000052 comment=c1983d823b6b01aefb9d4af728e3cac4d32466ef osm-gps-map-1.1.0/000077500000000000000000000000001262345173300136575ustar00rootroot00000000000000osm-gps-map-1.1.0/.gitignore000066400000000000000000000006261262345173300156530ustar00rootroot00000000000000*~ *.in *.la *.lo *.o *.deps/ *.libs/ *.tar.gz *.stamp *.bak INSTALL Makefile aclocal.m4 autom4te.cache/ compile config.guess config.h config.log config.status config.sub configure depcomp install-sh libtool ltmain.sh missing osmgpsmap-1.0.pc python/autom4te.cache/ python/build/ python/configure python/osmgpsmap.c src/Makefile src/mapviewer stamp-h1 ChangeLog .project .cproject .autotools .pydevproject osm-gps-map-1.1.0/AUTHORS000066400000000000000000000002071262345173300147260ustar00rootroot00000000000000Marcus Bauer 2008 John Stowers 2009 Everaldo Canuto 2009 osm-gps-map-1.1.0/COPYING000066400000000000000000000355031262345173300147200ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. osm-gps-map-1.1.0/Makefile.am000066400000000000000000000026011262345173300157120ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in SUBDIRS = src examples docs AM_DISTCHECK_CONFIGURE_FLAGS = \ --enable-gtk-doc ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} doc_DATA = \ README \ COPYING \ AUTHORS \ ChangeLog \ NEWS pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = osmgpsmap-1.0.pc DISTCLEANFILES = gtk-doc.make # ChangeLog generation from nautils distclean-local: if test "$(srcdir)" = "."; then :; else \ rm -f ChangeLog; \ fi ChangeLog: $(AM_V_GEN)if test -d "$(srcdir)/.git"; then \ (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.7.3.. --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \ && mv -f $@.tmp $@ \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ (test -f $@ || echo git-log is required to generate this file >> $@)); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ echo A git checkout and git-log is required to generate this file >> $@); \ fi release: dist scp @PACKAGE@-@VERSION@.tar.gz root@greenbirdsystems.com:/var/www/johnstowers.co.nz/files/osm-gps-map/ .PHONY: ChangeLog osm-gps-map-1.1.0/NEWS000066400000000000000000000143121262345173300143570ustar00rootroot00000000000000Changes in 1.1.0 ====================== * Add polygon support Samuel Cowen * Add osm_gps_map_zoom_fit_bbox Martijn Goedhart * Fix leaks oman Lebedev * Remove Yahoo (API break) Quentin Glidic * Build fixes Quentin Glidic * Fix image rotation Christoph Gysin Changes in 1.0.2 ====================== * Fix build with new giscanner * Build fixes guillomovitch * Fix open-street-maps Andrew Gee Changes in 1.0.1 ====================== * Build fixes Changes in 1.0.0 ====================== * Gtk3 support (serge.noiraud@laposte.net) * Remove deprecated functionality * Add z-order property to map items * Fix Google Changes in 0.7.4 ====================== * Fix Google Changes in 0.7.3 ====================== * When using the mouse scroll wheel to zoom in, centre on the mouse pointer (as recommended by the HIG) * Doc updates * Bug fixes * Treat 403 errors as missing tiles * Bail if user queues too many tiles to download (DOS) * Limit retries of tile download on unspecified errors * Enforce gtk+-2.14 minimum * Fix Google Changes in 0.7.2 ====================== * Make osm_gps_map_point_{copy,free} public * Fix build against older gtk and pygtk/pygobject versions (Maemo) * Doc updates * Bug fixes Changes in 0.7.1 ====================== * Don't install mapviewer binary * Bug fixes * Doc updates Changes in 0.7.0 ====================== * Map auto center threshold is now adjustable via the auto-center-threshold property. * Build fixes * Provide a notify signal for tiles-queued and zoom * Improvements to changing source and tile-cache after map is constructed * Drawing of the gps marker can now be completely controlled by applications by implementing the draw_gps_point vfunc * GPS marker visibility can also be controlled using the show-gps-point property * GObject introspection support * Documentation using gtk-doc * Gtk-3.0 compatible (builds with -DGSEAL_ENABLE) * Massive improvements to the Image and Track functions and additional API cleanup. This release is not ABI compatible, however it is API compatible. All users are advised to update to the new API. A summary of these changes, and a porting guide follow; * Replace coord_t -> OsmGpsMapPoint * osm_gps_map_add_image -> osm_gps_map_image_add and now returns a OsmGpsMapImage * type that should be used when removing or modifying images * osm_gps_map_remove_image -> osm_gps_map_image_remove and now accepts this returned OsmGpsMapImage * pointer * osm_gps_map_clear_images -> osm_gps_map_image_remove_all * Track management is now done using the OsmGpsMapTrack object. This is a wrapper around a GSList of OsmGpsMapPoints. You should keep a copy of this object around. You can add single points to the track by calling osm_gps_map_track_add_point, and the map will update accordingly. You can change the visual appearance of the track via this object properties. * osm_gps_map_add_track -> osm_gps_map_track_add * osm_gps_map_replace_track. Modify the OsmGpsMapTrack object instead * osm_gps_map_clear_tracks -> osm_gps_map_track_remove_all * The gps functions are now just convenience wrappers around an internal OsmGpsMapTrack object * osm_gps_map_draw_gps -> osm_gps_map_gps_add * osm_gps_map_clear_gps -> osm_gps_map_gps_clear * osm_gps_map_screen_to_geographic -> osm_gps_map_convert_screen_to_geographic * osm_gps_map_geographic_to_screen -> osm_gps_map_convert_geographic_to_screen * osm_gps_map_get_co_ordinates -> osm_gps_map_get_event_location * osm_gps_map_set_mapcenter -> osm_gps_map_set_center_and_zoom Changes in 0.6.0 ====================== * Support libsoup-2.2 and libsoup-2.4 * Add a Add a OsmGpsMapLayer interface and a default OSD using the interface. OsdGpsMapOsd is one implementation of this interface which draws one or all of; scale, map center coords, zoom control, dpade control, center crosshair. Much of the drawing code was from Till Harbaum. * Make the drag limit a gobject property Changes in 0.5.0 ====================== * Note: Many of the improvements this release was based on code from Till Harbaum * GDK drawing is not supported anymore, you must have cairo installed * Use automake silent rules * Add keyboard navigation support to map widget * Draw GPS heading in position indicator * Allow disabling of tile cache * You can now change the map source at runtime * Redraw and performance improvements * Update python bindings * Build and run correctly on Windows * Add OPENCYCLEMAP and OSM_PUBLIC_TRANSPORT * A new "changed" signal. Connect to this to monitor when the map zoom/scroll or center changes. * Add osm_gps_map_source_is_valid Changes in 0.4.0 ====================== * Map can now be constructed by passing a MAP_SOURCE ID instead of the map repo uri * Fix iter safety when purging the tile cache * Fix for segfault when adding images to the map * Remove map repo uris from public API. They should now be retrieved using osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source) * Add osm_gps_map_get_scale * Implement a blank map source that just draws grey tiles * Demo application now stores maps in XDG_CACHE_DIR * Fix build and crashes on windows * Add getters for name and zoom * Add a more complete python example * Add ability to purge the cache Changes in 0.3.0 ====================== * A new major contributor, Alberto Mardegan, worked on many of the new features of this release. Thanks a lot Alberto! * Draw map tracks with Cairo by default. * Interpolate between zoom levels while waiting for a tile to download. * Stop using GET_PRIVATE, and cache priv* for performance. * Keep an extra border of images offscreen for smoother scrolling at the edges of the map. * Keep the last N tiles in memory to improve render performance (previously they were loaded from disk) * Add some new api; osm_gps_set_center, osm_gps_map_scroll. osm-gps-map-1.1.0/README000066400000000000000000000005321262345173300145370ustar00rootroot00000000000000osm-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. osm-gps-map-1.1.0/autogen.sh000077500000000000000000000010571262345173300156630ustar00rootroot00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. srcdir=`dirname $0` test -z "$srcdir" && srcdir=. PKG_NAME="osm-gps-map" #REQUIRED_M4MACROS=introspection.m4 (test -f $srcdir/configure.ac) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" echo " top-level $PKG_NAME directory" exit 1 } which gnome-autogen.sh || { echo "You need to install gnome-common from the GNOME SVN" exit 1 } REQUIRED_AUTOMAKE_VERSION=1.11 USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh --enable-gtk-doc "$@" osm-gps-map-1.1.0/configure.ac000066400000000000000000000035141262345173300161500ustar00rootroot00000000000000AC_PREREQ([2.63]) AC_INIT([osm-gps-map], [1.1.0], [http://github.com/nzjrs/osm-gps-map/issues], [osm-gps-map]) AM_INIT_AUTOMAKE([1.11 foreign subdir-objects parallel-tests]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([src/osm-gps-map.h]) AC_CONFIG_MACRO_DIR([m4]) AM_PROG_CC_C_O AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL AM_SILENT_RULES([yes]) # Library dependencies PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16]) PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= 3.0]) PKG_CHECK_MODULES(CAIRO, [cairo >= 1.8]) PKG_CHECK_MODULES(SOUP24, [libsoup-2.4]) # The mapviewer demo also calls g_thread_init, so it needs to link against # libgthread-2.0. PKG_CHECK_MODULES(GTHREAD, [gthread-2.0]) AC_CHECK_FUNCS(gdk_event_get_scroll_deltas) AC_MSG_CHECKING([for Win32]) case "$host" in *-*-mingw*) os_win32=yes ;; *) os_win32=no ;; esac AC_MSG_RESULT([$os_win32]) AM_CONDITIONAL(OS_WIN32, [test $os_win32 = yes]) # Before making a release, the LT_VERSION_INFO string should be modified. # The string is of the form C:R:A. # - If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # - If binary compatibility has been broken (eg removed or changed interfaces) # change to C+1:0:0 # - If the interface is the same as the previous version, change to C:R+1:A LT_VERSION_INFO=1:0:0 AC_SUBST(LT_VERSION_INFO) GOBJECT_INTROSPECTION_REQS=0.10.0 GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_REQS]) GTK_DOC_CHECK([1.12]) GNOME_COMPILE_WARNINGS([maximum]) AC_OUTPUT([ osmgpsmap-1.0.pc Makefile src/Makefile docs/Makefile examples/Makefile docs/reference/Makefile docs/reference/version.xml ]) echo echo $PACKAGE v$VERSION echo echo Prefix............... : $prefix echo Introspection support : ${found_introspection} echo gtk-doc documentation : ${enable_gtk_doc} echo osm-gps-map-1.1.0/docs/000077500000000000000000000000001262345173300146075ustar00rootroot00000000000000osm-gps-map-1.1.0/docs/Makefile.am000066400000000000000000000000241262345173300166370ustar00rootroot00000000000000SUBDIRS = reference osm-gps-map-1.1.0/docs/reference/000077500000000000000000000000001262345173300165455ustar00rootroot00000000000000osm-gps-map-1.1.0/docs/reference/Makefile.am000066400000000000000000000061361262345173300206070ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libosmgpsmap # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=../../src # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space=osm_gps_map_ # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Add the builddir to the HTML path so that version.xml is found MKHTML_OPTIONS=--path="$(abs_builddir)" # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/src/*.h CFILE_GLOB=$(top_srcdir)/src/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES= \ converter.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files=version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir) \ $(GLIB_CFLAGS) \ $(GTK_CFLAGS) \ $(CAIRO_CFLAGS) \ $(SOUP24_CFLAGS) GTKDOC_LIBS=$(top_builddir)/src/libosmgpsmap-1.0.la \ $(GLIB_LIBS) \ $(GTK_LIBS) \ $(CAIRO_LIBS) \ $(SOUP24_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += version.xml.in # disable gtkdoc-check, I hate it #if ENABLE_GTK_DOC #TESTS_ENVIRONMENT = cd $(srcdir) && #TESTS = $(GTKDOC_CHECK) #endif osm-gps-map-1.1.0/docs/reference/libosmgpsmap-docs.xml000066400000000000000000000025511262345173300227150ustar00rootroot00000000000000 ]> OsmGpsMap Reference Manual API Reference Deprecated API Index of all symbols Index of deprecated symbols Annotation glossary osm-gps-map-1.1.0/docs/reference/libosmgpsmap-overrides.txt000066400000000000000000000000001262345173300237710ustar00rootroot00000000000000osm-gps-map-1.1.0/docs/reference/libosmgpsmap-sections.txt000066400000000000000000000052101262345173300236260ustar00rootroot00000000000000
osm-gps-map OsmGpsMap OsmGpsMap OsmGpsMapClass OSM_GPS_MAP_INVALID OSM_GPS_MAP_CACHE_DISABLED OSM_GPS_MAP_CACHE_AUTO OSM_GPS_MAP_CACHE_FRIENDLY osm_gps_map_get_default_cache_directory OsmGpsMapSource_t osm_gps_map_source_get_friendly_name osm_gps_map_source_get_repo_uri osm_gps_map_source_get_image_format osm_gps_map_source_get_min_zoom osm_gps_map_source_get_max_zoom osm_gps_map_source_is_valid osm_gps_map_new osm_gps_map_download_maps osm_gps_map_download_cancel_all osm_gps_map_get_bbox osm_gps_map_set_center osm_gps_map_set_center_and_zoom osm_gps_map_set_zoom osm_gps_map_zoom_in osm_gps_map_zoom_out osm_gps_map_scroll osm_gps_map_get_scale OsmGpsMapKey_t osm_gps_map_set_keyboard_shortcut osm_gps_map_get_event_location osm_gps_map_convert_geographic_to_screen osm_gps_map_convert_screen_to_geographic osm_gps_map_gps_add osm_gps_map_gps_clear osm_gps_map_gps_get_track osm_gps_map_track_add osm_gps_map_track_remove osm_gps_map_track_remove_all osm_gps_map_image_add osm_gps_map_image_add_with_alignment osm_gps_map_image_remove osm_gps_map_image_remove_all osm_gps_map_layer_add osm_gps_map_layer_remove osm_gps_map_layer_remove_all
osm-gps-map-deprecated OsmGpsMap Deprecated osm_gps_map_draw_gps osm_gps_map_clear_gps osm_gps_map_add_track osm_gps_map_replace_track osm_gps_map_clear_tracks osm_gps_map_add_image osm_gps_map_add_image_with_alignment osm_gps_map_remove_image osm_gps_map_clear_images osm_gps_map_add_layer osm_gps_map_get_co_ordinates osm_gps_map_screen_to_geographic osm_gps_map_geographic_to_screen osm_gps_map_set_mapcenter
osm-gps-map-layer OsmGpsMapLayer OsmGpsMapLayer OsmGpsMapLayerClass osm_gps_map_layer_render osm_gps_map_layer_draw osm_gps_map_layer_busy osm_gps_map_layer_button_press OsmGpsMapOsd OsmGpsMapOsdClass osm_gps_map_osd_new
osm-gps-map-image OsmGpsMapImage OsmGpsMapImage OsmGpsMapImageClass osm_gps_map_image_draw osm_gps_map_image_get_point osm_gps_map_image_get_type osm_gps_map_image_new
osm-gps-map-point OsmGpsMapPoint OsmGpsMapPoint osm_gps_map_point_get_degrees osm_gps_map_point_get_radians osm_gps_map_point_new_degrees osm_gps_map_point_new_radians osm_gps_map_point_set_degrees osm_gps_map_point_set_radians osm_gps_map_point_copy osm_gps_map_point_free
osm-gps-map-track OsmGpsMapTrack OsmGpsMapTrack OsmGpsMapTrackClass osm_gps_map_track_add_point osm_gps_map_track_get_color osm_gps_map_track_get_points osm_gps_map_track_new
osm-gps-map-1.1.0/docs/reference/libosmgpsmap.types000066400000000000000000000002321262345173300223250ustar00rootroot00000000000000osm_gps_map_get_type osm_gps_map_layer_get_type osm_gps_map_osd_get_type osm_gps_map_image_get_type osm_gps_map_track_get_type osm_gps_map_point_get_type osm-gps-map-1.1.0/docs/reference/version.xml.in000066400000000000000000000000251262345173300213560ustar00rootroot00000000000000@AC_PACKAGE_VERSION@ osm-gps-map-1.1.0/examples/000077500000000000000000000000001262345173300154755ustar00rootroot00000000000000osm-gps-map-1.1.0/examples/.gitignore000066400000000000000000000000121262345173300174560ustar00rootroot00000000000000mapviewer osm-gps-map-1.1.0/examples/Makefile.am000066400000000000000000000030231262345173300175270ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in OSMGPSMAP_CFLAGS = \ $(GLIB_CFLAGS) \ $(GTK_CFLAGS) \ $(CAIRO_CFLAGS) \ $(SOUP24_CFLAGS) OSMGPSMAP_LIBS = \ $(GLIB_LIBS) \ $(GTK_LIBS) \ $(CAIRO_LIBS) \ $(SOUP24_LIBS) ## Demo Application noinst_PROGRAMS = mapviewer polygon editable_track mapviewer_SOURCES = \ mapviewer.c mapviewer_CFLAGS = \ -I$(top_srcdir)/src \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) \ $(OSMGPSMAP_CFLAGS) \ $(GTHREAD_CFLAGS) mapviewer_LDADD = \ $(OSMGPSMAP_LIBS) \ $(GTHREAD_LIBS) \ $(top_builddir)/src/libosmgpsmap-1.0.la polygon_SOURCES = \ polygon.c polygon_CFLAGS = \ -I$(top_srcdir)/src \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) \ $(OSMGPSMAP_CFLAGS) \ $(GTHREAD_CFLAGS) polygon_LDADD = \ $(OSMGPSMAP_LIBS) \ $(GTHREAD_LIBS) \ $(top_builddir)/src/libosmgpsmap-1.0.la editable_track_SOURCES = \ editable_track.c editable_track_CFLAGS = \ -I$(top_srcdir)/src \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) \ $(OSMGPSMAP_CFLAGS) \ $(GTHREAD_CFLAGS) editable_track_LDADD = \ $(OSMGPSMAP_LIBS) \ $(GTHREAD_LIBS) \ $(top_builddir)/src/libosmgpsmap-1.0.la ## Misc EXTRA_DIST = poi.png mapviewer.ui mapviewer.js README osm-gps-map-1.1.0/examples/README000066400000000000000000000014201262345173300163520ustar00rootroot00000000000000osm-gps-map example applications * ./mapviewer C based demo app with many options. See '--help' for a list. Note, this must be executed from the examples directory so it can find the mapviewer.ui file. * ./polygon This example demonstrates editable polygons. Vertex points can be dragged. Clicking mid-points divides the line and creates another vertex. * ./mapviewer.py Python version of the C demo app, with examples showing how to do custom layers. * ./mapviewer.js Javascript example using seed + gobject-introspection. If running uninstalled, you probbably need to tell GObject introspection where to find the bindings. Do the following from the example directory # export LD_LIBRARY_PATH=../src/.libs/ # export GI_TYPELIB_PATH=../src/ osm-gps-map-1.1.0/examples/editable_track.c000066400000000000000000000016421262345173300206010ustar00rootroot00000000000000#include #include "osm-gps-map.h" int main (int argc, char *argv[]) { OsmGpsMap *map; GtkWidget *window; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Window"); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); map = g_object_new (OSM_TYPE_GPS_MAP, NULL); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(map)); OsmGpsMapTrack* track = osm_gps_map_track_new(); OsmGpsMapPoint* p1, *p2; p1 = osm_gps_map_point_new_radians(1.25663706, -0.488692191); p2 = osm_gps_map_point_new_radians(1.06465084, -0.750491578); osm_gps_map_track_add_point(track, p1); osm_gps_map_track_add_point(track, p2); g_object_set(track, "editable", TRUE, NULL); osm_gps_map_track_add(map, track); gtk_widget_show (GTK_WIDGET(map)); gtk_widget_show (window); gtk_main (); return 0; } osm-gps-map-1.1.0/examples/env.sh000077500000000000000000000002011262345173300166150ustar00rootroot00000000000000#!/bin/sh export LD_LIBRARY_PATH=../src/.libs/ export GI_TYPELIB_PATH=$GI_TYPELIB_PATH:../src/ export PYTHONPATH=../python/ $1 osm-gps-map-1.1.0/examples/mapviewer.c000066400000000000000000000351371262345173300176510ustar00rootroot00000000000000/* -*- 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 * * This 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; version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include #include #include #include #include #include "osm-gps-map.h" static OsmGpsMapSource_t opt_map_provider = OSM_GPS_MAP_SOURCE_OPENSTREETMAP; static gboolean opt_friendly_cache = FALSE; static gboolean opt_no_cache = FALSE; static gboolean opt_debug = FALSE; static char *opt_cache_base_dir = NULL; static gboolean opt_editable_tracks = FALSE; static GOptionEntry entries[] = { { "friendly-cache", 'f', 0, G_OPTION_ARG_NONE, &opt_friendly_cache, "Store maps using friendly cache style (source name)", NULL }, { "no-cache", 'n', 0, G_OPTION_ARG_NONE, &opt_no_cache, "Disable cache", NULL }, { "cache-basedir", 'b', 0, G_OPTION_ARG_FILENAME, &opt_cache_base_dir, "Cache basedir", NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &opt_debug, "Enable debugging", NULL }, { "map", 'm', 0, G_OPTION_ARG_INT, &opt_map_provider, "Map source", "N" }, { "editable-tracks", 'e', 0, G_OPTION_ARG_NONE, &opt_editable_tracks, "Make the tracks editable", NULL }, { NULL } }; static GdkPixbuf *g_star_image = NULL; static OsmGpsMapImage *g_last_image = NULL; static gboolean on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { OsmGpsMapPoint coord; float lat, lon; OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapTrack *othertrack = OSM_GPS_MAP_TRACK(user_data); int left_button = (event->button == 1) && (event->state == 0); int middle_button = (event->button == 2) || ((event->button == 1) && (event->state & GDK_SHIFT_MASK)); int right_button = (event->button == 3) || ((event->button == 1) && (event->state & GDK_CONTROL_MASK)); osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, &coord); osm_gps_map_point_get_degrees(&coord, &lat, &lon); if (event->type == GDK_3BUTTON_PRESS) { if (middle_button) { if (g_last_image) osm_gps_map_image_remove (map, g_last_image); } if (right_button) { osm_gps_map_track_remove(map, othertrack); } } else if (event->type == GDK_2BUTTON_PRESS) { if (left_button) { osm_gps_map_gps_add (map, lat, lon, g_random_double_range(0,360)); } if (middle_button) { g_last_image = osm_gps_map_image_add (map, lat, lon, g_star_image); } if (right_button) { osm_gps_map_track_add_point(othertrack, &coord); } } return FALSE; } static 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("Map Centre: lattitude %f longitude %f",lat,lon); gtk_entry_set_text(entry, msg); g_free(msg); return FALSE; } static 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; } static 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; } static gboolean on_home_clicked_event (GtkWidget *widget, gpointer user_data) { OsmGpsMap *map = OSM_GPS_MAP(user_data); osm_gps_map_set_center_and_zoom(map, -43.5326,172.6362,12); return FALSE; } static gboolean on_cache_clicked_event (GtkWidget *widget, gpointer user_data) { OsmGpsMap *map = OSM_GPS_MAP(user_data); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { int zoom,max_zoom; OsmGpsMapPoint pt1, pt2; osm_gps_map_get_bbox(map, &pt1, &pt2); g_object_get(map, "zoom", &zoom, "max-zoom", &max_zoom, NULL); osm_gps_map_download_maps(map, &pt1, &pt2, zoom, max_zoom); } else { osm_gps_map_download_cancel_all(map); } return FALSE; } static void on_tiles_queued_changed (OsmGpsMap *image, GParamSpec *pspec, gpointer user_data) { gchar *s; int tiles; GtkLabel *label = GTK_LABEL(user_data); g_object_get(image, "tiles-queued", &tiles, NULL); s = g_strdup_printf("%d", tiles); gtk_label_set_text(label, s); g_free(s); } static void on_gps_alpha_changed (GtkAdjustment *adjustment, gpointer user_data) { OsmGpsMap *map = OSM_GPS_MAP(user_data); OsmGpsMapTrack *track = osm_gps_map_gps_get_track (map); float f = gtk_adjustment_get_value(adjustment); g_object_set (track, "alpha", f, NULL);} static void on_gps_width_changed (GtkAdjustment *adjustment, gpointer user_data) { OsmGpsMap *map = OSM_GPS_MAP(user_data); OsmGpsMapTrack *track = osm_gps_map_gps_get_track (map); float f = gtk_adjustment_get_value(adjustment); g_object_set (track, "line-width", f, NULL); } static void on_star_align_changed (GtkAdjustment *adjustment, gpointer user_data) { const char *propname = user_data; float f = gtk_adjustment_get_value(adjustment); if (g_last_image) g_object_set (g_last_image, propname, f, NULL); } #if GTK_CHECK_VERSION(3,4,0) static void on_gps_color_changed (GtkColorChooser *widget, gpointer user_data) { GdkRGBA c; OsmGpsMapTrack *track = OSM_GPS_MAP_TRACK(user_data); gtk_color_chooser_get_rgba (widget, &c); osm_gps_map_track_set_color(track, &c); } #else static void on_gps_color_changed (GtkColorButton *widget, gpointer user_data) { GdkRGBA c; OsmGpsMapTrack *track = OSM_GPS_MAP_TRACK(user_data); gtk_color_button_get_rgba (widget, &c); osm_gps_map_track_set_color(track, &c); } #endif static void on_close (GtkWidget *widget, gpointer user_data) { gtk_widget_destroy(widget); gtk_main_quit(); } static void usage (GOptionContext *context) { int i; puts(g_option_context_get_help(context, TRUE, NULL)); printf("Valid map sources:\n"); for(i=OSM_GPS_MAP_SOURCE_NULL; i <= OSM_GPS_MAP_SOURCE_LAST; i++) { const char *name = osm_gps_map_source_get_friendly_name(i); const char *uri = osm_gps_map_source_get_repo_uri(i); if (uri != NULL) printf("\t%d:\t%s\n",i,name); } } int main (int argc, char **argv) { GtkBuilder *builder; GtkWidget *widget; GtkAccelGroup *ag; OsmGpsMap *map; OsmGpsMapLayer *osd; OsmGpsMapTrack *rightclicktrack; const char *repo_uri; char *cachedir, *cachebasedir; GError *error = NULL; GOptionContext *context; gtk_init (&argc, &argv); context = g_option_context_new ("- Map browser"); 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; } /* Only use the repo_uri to check if the user has supplied a valid map source ID */ repo_uri = osm_gps_map_source_get_repo_uri(opt_map_provider); if ( repo_uri == NULL ) { usage(context); return 2; } cachebasedir = osm_gps_map_get_default_cache_directory(); if (opt_cache_base_dir && g_file_test(opt_cache_base_dir, G_FILE_TEST_IS_DIR)) { cachedir = g_strdup(OSM_GPS_MAP_CACHE_AUTO); cachebasedir = g_strdup(opt_cache_base_dir); } else if (opt_friendly_cache) { cachedir = g_strdup(OSM_GPS_MAP_CACHE_FRIENDLY); } else if (opt_no_cache) { cachedir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED); } else { cachedir = g_strdup(OSM_GPS_MAP_CACHE_AUTO); } if (opt_debug) gdk_window_set_debug_updates(TRUE); g_debug("Map Cache Dir: %s", cachedir); g_debug("Map Provider: %s (%d)", osm_gps_map_source_get_friendly_name(opt_map_provider), opt_map_provider); map = g_object_new (OSM_TYPE_GPS_MAP, "map-source",opt_map_provider, "tile-cache",cachedir, "tile-cache-base", cachebasedir, "proxy-uri",g_getenv("http_proxy"), NULL); osd = g_object_new (OSM_TYPE_GPS_MAP_OSD, "show-scale",TRUE, "show-coordinates",TRUE, "show-crosshair",TRUE, "show-dpad",TRUE, "show-zoom",TRUE, "show-gps-in-dpad",TRUE, "show-gps-in-zoom",FALSE, "dpad-radius", 30, NULL); osm_gps_map_layer_add(OSM_GPS_MAP(map), osd); g_object_unref(G_OBJECT(osd)); //Add a second track for right clicks rightclicktrack = osm_gps_map_track_new(); if(opt_editable_tracks) g_object_set(rightclicktrack, "editable", TRUE, NULL); osm_gps_map_track_add(OSM_GPS_MAP(map), rightclicktrack); g_free(cachedir); g_free(cachebasedir); //Enable keyboard navigation osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_FULLSCREEN, GDK_KEY_F11); osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_UP, GDK_KEY_Up); osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_DOWN, GDK_KEY_Down); osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_LEFT, GDK_KEY_Left); osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_RIGHT, GDK_KEY_Right); //Build the UI g_star_image = gdk_pixbuf_new_from_file_at_size ("poi.png", 24,24,NULL); builder = gtk_builder_new(); gtk_builder_add_from_file (builder, "mapviewer.ui", &error); if (error) g_error ("ERROR: %s\n", error->message); gtk_box_pack_start ( GTK_BOX(gtk_builder_get_object(builder, "map_box")), GTK_WIDGET(map), TRUE, TRUE, 0); //Init values float lw,a; GdkRGBA c; OsmGpsMapTrack *gpstrack = osm_gps_map_gps_get_track (map); g_object_get (gpstrack, "line-width", &lw, "alpha", &a, NULL); osm_gps_map_track_get_color(gpstrack, &c); gtk_adjustment_set_value ( GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gps_width_adjustment")), lw); gtk_adjustment_set_value ( GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gps_alpha_adjustment")), a); gtk_adjustment_set_value ( GTK_ADJUSTMENT(gtk_builder_get_object(builder, "star_xalign_adjustment")), 0.5); gtk_adjustment_set_value ( GTK_ADJUSTMENT(gtk_builder_get_object(builder, "star_yalign_adjustment")), 0.5); #if GTK_CHECK_VERSION(3,4,0) gtk_color_chooser_set_rgba ( GTK_COLOR_CHOOSER(gtk_builder_get_object(builder, "gps_colorbutton")), &c); #else gtk_color_button_set_rgba ( GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "gps_colorbutton")), &c); #endif //Connect to signals g_signal_connect ( gtk_builder_get_object(builder, "gps_colorbutton"), "color-set", G_CALLBACK (on_gps_color_changed), (gpointer) gpstrack); g_signal_connect ( gtk_builder_get_object(builder, "zoom_in_button"), "clicked", G_CALLBACK (on_zoom_in_clicked_event), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "zoom_out_button"), "clicked", G_CALLBACK (on_zoom_out_clicked_event), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "home_button"), "clicked", G_CALLBACK (on_home_clicked_event), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "cache_button"), "clicked", G_CALLBACK (on_cache_clicked_event), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "gps_alpha_adjustment"), "value-changed", G_CALLBACK (on_gps_alpha_changed), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "gps_width_adjustment"), "value-changed", G_CALLBACK (on_gps_width_changed), (gpointer) map); g_signal_connect ( gtk_builder_get_object(builder, "star_xalign_adjustment"), "value-changed", G_CALLBACK (on_star_align_changed), (gpointer) "x-align"); g_signal_connect ( gtk_builder_get_object(builder, "star_yalign_adjustment"), "value-changed", G_CALLBACK (on_star_align_changed), (gpointer) "y-align"); g_signal_connect (G_OBJECT (map), "button-press-event", G_CALLBACK (on_button_press_event), (gpointer) rightclicktrack); g_signal_connect (G_OBJECT (map), "button-release-event", G_CALLBACK (on_button_release_event), (gpointer) gtk_builder_get_object(builder, "text_entry")); g_signal_connect (G_OBJECT (map), "notify::tiles-queued", G_CALLBACK (on_tiles_queued_changed), (gpointer) gtk_builder_get_object(builder, "cache_label")); widget = GTK_WIDGET(gtk_builder_get_object(builder, "window1")); g_signal_connect (widget, "destroy", G_CALLBACK (on_close), (gpointer) map); //Setup accelerators. ag = gtk_accel_group_new(); gtk_accel_group_connect(ag, GDK_KEY_w, GDK_CONTROL_MASK, GTK_ACCEL_MASK, g_cclosure_new(gtk_main_quit, NULL, NULL)); gtk_accel_group_connect(ag, GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_MASK, g_cclosure_new(gtk_main_quit, NULL, NULL)); gtk_window_add_accel_group(GTK_WINDOW(widget), ag); gtk_widget_show_all (widget); g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL); gtk_main (); return 0; } osm-gps-map-1.1.0/examples/mapviewer.js000077500000000000000000000012551262345173300200400ustar00rootroot00000000000000#!/usr/bin/seed // You probbably need to tell GObject introspection where to find the bindings // export LD_LIBRARY_PATH=../src/.libs/ // export GI_TYPELIB_PATH=../src/ const Gtk = imports.gi.Gtk; const Osm = imports.gi.OsmGpsMap; Gtk.init(0, null); var win = new Gtk.Window({ type: Gtk.WindowType.TOPLEVEL }); win.set_border_width(10); win.set_default_size(400,400); // ARRRGGGHHHHH GNOME if (0) // GJS makes me do this win.connect("delete-event", Gtk.main_quit); else // Seed makes me do this win.signal.delete_event.connect(Gtk.main_quit); var map = new Osm.OsmGpsMap() var osd = new Osm.Osd() map.layer_add(osd) win.add(map); win.show_all(); Gtk.main(); osm-gps-map-1.1.0/examples/mapviewer.py000077500000000000000000000227571262345173300200660ustar00rootroot00000000000000#!/usr/bin/python """ Copyright (C) Hadley Rich 2008 based on main.c - with thanks to John Stowers This 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; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . """ import sys import os.path import random from math import pi from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GObject GObject.threads_init() Gdk.threads_init() from gi.repository import OsmGpsMap as osmgpsmap print "using library: %s (version %s)" % (osmgpsmap.__file__, osmgpsmap._version) assert osmgpsmap._version == "1.0" class DummyMapNoGpsPoint(osmgpsmap.Map): def do_draw_gps_point(self, drawable): pass GObject.type_register(DummyMapNoGpsPoint) class DummyLayer(GObject.GObject, osmgpsmap.MapLayer): def __init__(self): GObject.GObject.__init__(self) def do_draw(self, gpsmap, gdkdrawable): pass def do_render(self, gpsmap): pass def do_busy(self): return False def do_button_press(self, gpsmap, gdkeventbutton): return False GObject.type_register(DummyLayer) class UI(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL) self.set_default_size(500, 500) self.connect('destroy', lambda x: Gtk.main_quit()) self.set_title('OpenStreetMap GPS Mapper') self.vbox = Gtk.VBox(False, 0) self.add(self.vbox) if 0: self.osm = DummyMapNoGpsPoint() else: self.osm = osmgpsmap.Map() self.osm.layer_add( osmgpsmap.MapOsd( show_dpad=True, show_zoom=True, show_crosshair=True) ) self.osm.layer_add( DummyLayer() ) self.last_image = None self.osm.connect('button_press_event', self.on_button_press) self.osm.connect('button_release_event', self.on_button_release) #connect keyboard shortcuts self.osm.set_keyboard_shortcut(osmgpsmap.MapKey_t.FULLSCREEN, Gdk.keyval_from_name("F11")) self.osm.set_keyboard_shortcut(osmgpsmap.MapKey_t.UP, Gdk.keyval_from_name("Up")) self.osm.set_keyboard_shortcut(osmgpsmap.MapKey_t.DOWN, Gdk.keyval_from_name("Down")) self.osm.set_keyboard_shortcut(osmgpsmap.MapKey_t.LEFT, Gdk.keyval_from_name("Left")) self.osm.set_keyboard_shortcut(osmgpsmap.MapKey_t.RIGHT, Gdk.keyval_from_name("Right")) #connect to tooltip self.osm.props.has_tooltip = True self.osm.connect("query-tooltip", self.on_query_tooltip) self.latlon_entry = Gtk.Entry() zoom_in_button = Gtk.Button(stock=Gtk.STOCK_ZOOM_IN) zoom_in_button.connect('clicked', self.zoom_in_clicked) zoom_out_button = Gtk.Button(stock=Gtk.STOCK_ZOOM_OUT) zoom_out_button.connect('clicked', self.zoom_out_clicked) home_button = Gtk.Button(stock=Gtk.STOCK_HOME) home_button.connect('clicked', self.home_clicked) cache_button = Gtk.Button('Cache') cache_button.connect('clicked', self.cache_clicked) self.vbox.pack_start(self.osm, True, True, 0) hbox = Gtk.HBox(False, 0) hbox.pack_start(zoom_in_button, False, True, 0) hbox.pack_start(zoom_out_button, False, True, 0) hbox.pack_start(home_button, False, True, 0) hbox.pack_start(cache_button, False, True, 0) #add ability to test custom map URIs ex = Gtk.Expander(label="Map Repository URI") ex.props.use_markup = True vb = Gtk.VBox() self.repouri_entry = Gtk.Entry() self.repouri_entry.set_text(self.osm.props.repo_uri) self.image_format_entry = Gtk.Entry() self.image_format_entry.set_text(self.osm.props.image_format) lbl = Gtk.Label( """ Enter an repository URL to fetch map tiles from in the box below. Special metacharacters may be included in this url Metacharacters: \t#X\tMax X location \t#Y\tMax Y location \t#Z\tMap zoom (0 = min zoom, fully zoomed out) \t#S\tInverse zoom (max-zoom - #Z) \t#Q\tQuadtree encoded tile (qrts) \t#W\tQuadtree encoded tile (1234) \t#U\tEncoding not implemeted \t#R\tRandom integer, 0-4""") lbl.props.xalign = 0 lbl.props.use_markup = True lbl.props.wrap = True ex.add(vb) vb.pack_start(lbl, False, True, 0) hb = Gtk.HBox() hb.pack_start(Gtk.Label("URI: "), False, True, 0) hb.pack_start(self.repouri_entry, True, True, 0) vb.pack_start(hb, False, True, 0) hb = Gtk.HBox() hb.pack_start(Gtk.Label("Image Format: "), False, True, 0) hb.pack_start(self.image_format_entry, True, True, 0) vb.pack_start(hb, False, True, 0) gobtn = Gtk.Button("Load Map URI") gobtn.connect("clicked", self.load_map_clicked) vb.pack_start(gobtn, False, True, 0) self.show_tooltips = False cb = Gtk.CheckButton("Show Location in Tooltips") cb.props.active = self.show_tooltips cb.connect("toggled", self.on_show_tooltips_toggled) self.vbox.pack_end(cb, False, True, 0) cb = Gtk.CheckButton("Disable Cache") cb.props.active = False cb.connect("toggled", self.disable_cache_toggled) self.vbox.pack_end(cb, False, True, 0) self.vbox.pack_end(ex, False, True, 0) self.vbox.pack_end(self.latlon_entry, False, True, 0) self.vbox.pack_end(hbox, False, True, 0) GObject.timeout_add(500, self.print_tiles) def disable_cache_toggled(self, btn): if btn.props.active: self.osm.props.tile_cache = osmgpsmap.MAP_CACHE_DISABLED else: self.osm.props.tile_cache = osmgpsmap.MAP_CACHE_AUTO def on_show_tooltips_toggled(self, btn): self.show_tooltips = btn.props.active def load_map_clicked(self, button): uri = self.repouri_entry.get_text() format = self.image_format_entry.get_text() if uri and format: if self.osm: #remove old map self.vbox.remove(self.osm) try: self.osm = osmgpsmap.Map( repo_uri=uri, image_format=format ) except Exception, e: print "ERROR:", e self.osm = osm.Map() self.vbox.pack_start(self.osm, True, True, 0) self.osm.connect('button_release_event', self.map_clicked) self.osm.show() def print_tiles(self): if self.osm.props.tiles_queued != 0: print self.osm.props.tiles_queued, 'tiles queued' return True def zoom_in_clicked(self, button): self.osm.set_zoom(self.osm.props.zoom + 1) def zoom_out_clicked(self, button): self.osm.set_zoom(self.osm.props.zoom - 1) def home_clicked(self, button): self.osm.set_center_and_zoom(-44.39, 171.25, 12) def on_query_tooltip(self, widget, x, y, keyboard_tip, tooltip, data=None): if keyboard_tip: return False if self.show_tooltips: p = osmgpsmap.point_new_degrees(0.0, 0.0) self.osm.convert_screen_to_geographic(x, y, p) lat,lon = p.get_degrees() tooltip.set_markup("%+.4f, %+.4f" % (lat, lon )) return True return False def cache_clicked(self, button): bbox = self.osm.get_bbox() self.osm.download_maps( *bbox, zoom_start=self.osm.props.zoom, zoom_end=self.osm.props.max_zoom ) def on_button_release(self, osm, event): self.latlon_entry.set_text( 'Map Centre: latitude %s longitude %s' % ( self.osm.props.latitude, self.osm.props.longitude ) ) def on_button_press(self, osm, event): state = event.get_state() lat,lon = self.osm.get_event_location(event).get_degrees() left = event.button == 1 and state == 0 middle = event.button == 2 or (event.button == 1 and state & Gdk.ModifierType.SHIFT_MASK) right = event.button == 3 or (event.button == 1 and state & Gdk.ModifierType.CONTROL_MASK) #work around binding bug with invalid variable name GDK_2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS") GDK_3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS") if event.type == GDK_3BUTTON_PRESS: if middle: if self.last_image is not None: self.osm.image_remove(self.last_image) self.last_image = None elif event.type == GDK_2BUTTON_PRESS: if left: self.osm.gps_add(lat, lon, heading=random.random()*360) if middle: pb = GdkPixbuf.Pixbuf.new_from_file_at_size ("poi.png", 24,24) self.last_image = self.osm.image_add(lat,lon,pb) if right: pass if __name__ == "__main__": u = UI() u.show_all() if os.name == "nt": Gdk.threads_enter() Gtk.main() if os.name == "nt": Gdk.threads_leave() osm-gps-map-1.1.0/examples/mapviewer.ui000066400000000000000000000544461262345173300200500ustar00rootroot00000000000000 1 0.10000000000000001 0.10000000000000001 10 0.5 0.5 False 400 400 True False 4 4 4 4 True False 4 True False True True 0 True False True gtk-zoom-in True True True False True True True 0 gtk-zoom-out True True True False True True True 1 gtk-home True True True False True True True 2 Cache True True True False True True 3 False False 1 True False 4 True True • True True 0 True False 1 0 5 False True 1 False False 2 True True True False 4 True False True False 4 True False 0 Color False True 0 True True True False #000000000000 True True 1 False False 0 True False 4 True False 0 Alpha False True 0 True True gps_alpha_adjustment False 0 False True True 1 False False 1 True False 4 True False 0 Width False True 0 True True gps_width_adjustment False 0 False True True 1 False False 2 True False GPS Track Appearance False False 3 True True True False 4 True False True False 4 True False 0 X Offset False True 0 True True star_xalign_adjustment False 0 False True True 1 False False 0 True False 4 True False 0 Y Offset False True 0 True True star_yalign_adjustment False 0 False True True 1 False False 1 True False Star Image Appearance False False 4 1 0.5 0.10000000000000001 0.10000000000000001 1 0.5 0.10000000000000001 0.10000000000000001 osm-gps-map-1.1.0/examples/poi.png000066400000000000000000000021051262345173300167700ustar00rootroot00000000000000‰PNG  IHDRàw=øsBIT|dˆ pHYs¸¸¤ûfKtEXtSoftwarewww.inkscape.org›î<ÂIDATH‰­–ïO[UÇ¿ç¶÷¶Ú®‡Òûc°1ÂXgb|á ›Æ 'èb¢{s‰Ä½€ÁÔ?Àh‹ ‹1QÇ–€1J²Å-Æ€¾×à%5ƒ­2Xec8`´¥÷Þ¶÷<¾¸½])ënòä>99çó=Ïsï¡X;7,6?Ì|"‚€"Ÿþ>Iðz½Ãç†Å–b×(^ÀçŽÖïìÝUQÙpzÓúû$æñèÅÇÐÔth×™!éঠøüìõ׋;VëNæv{?ÚT·gÿ)QÜ@  iϳŸJ6Eàû‹%í.WKƒ—A¤Àjõ 5®'>,FÀü  .ÏÓïI’ D2Œ) RÑÜÜ3|ÖÒ©Ètym sÝ=I*´žúû$Ë£ht:YÀé¬ñÛ·v”–VyDó¶j›½¶Êl¶‚H €s= ΤÓw 'îðhìÞr2›O¥¢³r":»–ˆÏ®Å‰®b’}W2²ï©‡m¶@‰(VCJ³°\#RA$ƒHç*8—sL¦ÉYK§ã¸}kvab"Þašù[û+PÚ|¾vc–<°š}3–?–+®dÄõw8üO¬·gåòè×4aš¿EK--Ǫ­ý³Õë Ú£u Æ0føjLÉDcø2¦§æV{O-ýö;NÑF¤×¦¢‚ùê~l}©Û-bvÇ0à hš’—},š¹×Õµüm(DƒDZ×E‹‹t­ÌÁžK¥>?üÊñ'u‘û;gÌ(°š¡œ&º±râÝ¥o¦¦1@DSÛty…nØíl254~äÈA0g`ÉÌîÕlèÅÖýHä¶ÜùÎÝ‘ëa Ñõ\憃¶ºJ‘ n¾‹^å”óD¶cróo´«É¤ w—ðe>¼ ë½[¶ZÎ×ç:ß×£H ¼œ[^{ÕÔ\ˆUPàómç24í>Ðès#M3j’FeÛ[ˆUðS!Še»‰´ NOU D<'=}eeÌW´€d±ôÊY‘ùù›ÊØØÜôÂBj¥­ÍÖX__â R3Ô/ YÜš– ãßÅHòÒ¥™ðЙØÏ‘~ðëùóËϼ}ÌÜu¨Õ´ÛëevΧåŒ1+Å×ÁòÒŸ&>µ©«{ӟدÕÕá mœ¹ólu:ñfÏIÓ/ãblrRL?PØ—ÏÛ 0:"¶ŸýÊz%d£ŽØþ·Žêjt~ð¾é·:„“èé6K^à~˜ë €J ùãÿ--"v ?ÈÍIEND®B`‚osm-gps-map-1.1.0/examples/polygon.c000066400000000000000000000022131262345173300173260ustar00rootroot00000000000000#include #include "osm-gps-map.h" int main (int argc, char *argv[]) { OsmGpsMap *map; OsmGpsMapPolygon* poly; GtkWidget *window; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Window"); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); map = g_object_new (OSM_TYPE_GPS_MAP, NULL); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(map)); poly = osm_gps_map_polygon_new(); OsmGpsMapTrack* polytrack = osm_gps_map_track_new(); OsmGpsMapPoint* p1, *p2, *p3; p1 = osm_gps_map_point_new_radians(1.25663706, -0.488692191); p2 = osm_gps_map_point_new_radians(1.06465084, -0.750491578); p3 = osm_gps_map_point_new_radians(1.064650849, -0.191986218); osm_gps_map_track_add_point(polytrack, p1); osm_gps_map_track_add_point(polytrack, p2); osm_gps_map_track_add_point(polytrack, p3); g_object_set(poly, "track", polytrack, NULL); g_object_set(poly, "editable", TRUE, NULL); osm_gps_map_polygon_add(map, poly); gtk_widget_show (GTK_WIDGET(map)); gtk_widget_show (window); gtk_main (); return 0; } osm-gps-map-1.1.0/m4/000077500000000000000000000000001262345173300141775ustar00rootroot00000000000000osm-gps-map-1.1.0/m4/.gitignore000066400000000000000000000000061262345173300161630ustar00rootroot00000000000000l*.m4 osm-gps-map-1.1.0/m4/gtk-doc.m4000066400000000000000000000063121262345173300157730ustar00rootroot00000000000000dnl -*- mode: autoconf -*- # serial 2 dnl Usage: dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) AC_DEFUN([GTK_DOC_CHECK], [ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"]) AC_MSG_CHECKING([for gtk-doc]) PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no]) AC_MSG_RESULT($have_gtk_doc) if test "$have_gtk_doc" = "no"; then AC_MSG_WARN([ You will not be able to create source packages with 'make dist' because $gtk_doc_requires is not found.]) fi dnl check for tools we added during development dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that dnl may not be writable by the user. Currently, automake requires that the dnl test name must end in '.test'. dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638 AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test]) AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check]) AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) dnl for overriding the documentation installation directory AC_ARG_WITH([html-dir], AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, [with_html_dir='${datadir}/gtk-doc/html']) HTML_DIR="$with_html_dir" AC_SUBST([HTML_DIR]) dnl enable/disable documentation building AC_ARG_ENABLE([gtk-doc], AS_HELP_STRING([--enable-gtk-doc], [use gtk-doc to build documentation [[default=no]]]),, [enable_gtk_doc=no]) AC_MSG_CHECKING([whether to build gtk-doc documentation]) AC_MSG_RESULT($enable_gtk_doc) if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then AC_MSG_ERROR([ You must have $gtk_doc_requires installed to build documentation for $PACKAGE_NAME. Please install gtk-doc or disable building the documentation by adding '--disable-gtk-doc' to '[$]0'.]) fi dnl don't check for glib if we build glib if test "x$PACKAGE_NAME" != "xglib"; then dnl don't fail if someone does not have glib PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) fi dnl enable/disable output formats AC_ARG_ENABLE([gtk-doc-html], AS_HELP_STRING([--enable-gtk-doc-html], [build documentation in html format [[default=yes]]]),, [enable_gtk_doc_html=yes]) AC_ARG_ENABLE([gtk-doc-pdf], AS_HELP_STRING([--enable-gtk-doc-pdf], [build documentation in pdf format [[default=no]]]),, [enable_gtk_doc_pdf=no]) if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi AC_SUBST([AM_DEFAULT_VERBOSITY]) AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes]) AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) ]) osm-gps-map-1.1.0/m4/introspection.m4000066400000000000000000000066141262345173300173500ustar00rootroot00000000000000dnl -*- mode: autoconf -*- dnl Copyright 2009 Johan Dahlin dnl dnl This file is free software; the author(s) gives unlimited dnl permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl # serial 1 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], [ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([LT_INIT],[$0])dnl setup libtool first dnl enable/disable introspection m4_if([$2], [require], [dnl enable_introspection=yes ],[dnl AC_ARG_ENABLE(introspection, AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], [Enable introspection for this build]),, [enable_introspection=auto]) ])dnl AC_MSG_CHECKING([for gobject-introspection]) dnl presence/version checking AS_CASE([$enable_introspection], [no], [dnl found_introspection="no (disabled, use --enable-introspection to enable)" ],dnl [yes],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0],, AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) ],dnl [auto],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) ],dnl [dnl AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) ])dnl AC_MSG_RESULT([$found_introspection]) INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi AC_SUBST(INTROSPECTION_SCANNER) AC_SUBST(INTROSPECTION_COMPILER) AC_SUBST(INTROSPECTION_GENERATE) AC_SUBST(INTROSPECTION_GIRDIR) AC_SUBST(INTROSPECTION_TYPELIBDIR) AC_SUBST(INTROSPECTION_CFLAGS) AC_SUBST(INTROSPECTION_LIBS) AC_SUBST(INTROSPECTION_MAKEFILE) AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") ]) dnl Usage: dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) ]) dnl Usage: dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ]) osm-gps-map-1.1.0/osmgpsmap-1.0.pc.in000066400000000000000000000004431262345173300171130ustar00rootroot00000000000000prefix=@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+-3.0 libsoup-2.4 Libs: -L${libdir} -losmgpsmap-1.0 Cflags: -I${includedir}/osmgpsmap-1.0 osm-gps-map-1.1.0/src/000077500000000000000000000000001262345173300144465ustar00rootroot00000000000000osm-gps-map-1.1.0/src/.gitignore000066400000000000000000000000501262345173300164310ustar00rootroot00000000000000OsmGpsMap-1.0.gir OsmGpsMap-1.0.typelib osm-gps-map-1.1.0/src/Makefile.am000066400000000000000000000052071262345173300165060ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in lib_LTLIBRARIES = libosmgpsmap-1.0.la OSMGPSMAP_CFLAGS = \ $(GLIB_CFLAGS) \ $(GTK_CFLAGS) \ $(CAIRO_CFLAGS) \ $(SOUP24_CFLAGS) OSMGPSMAP_LIBS = \ $(GLIB_LIBS) \ $(GTK_LIBS) \ $(CAIRO_LIBS) \ $(SOUP24_LIBS) ## Shared library libosmgpsmap_1_0_la_CFLAGS = \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) \ $(OSMGPSMAP_CFLAGS) \ -DG_LOG_DOMAIN=\"OsmGpsMap\" if OS_WIN32 no_undefined = -no-undefined endif libosmgpsmap_1_0_la_LDFLAGS = \ -version-info $(LT_VERSION_INFO) \ $(no_undefined) libosmgpsmap_1_0_la_LIBADD = \ $(OSMGPSMAP_LIBS) \ -lm sources_private_h = \ converter.h \ osd-utils.h \ private.h sources_public_h = \ osm-gps-map.h \ osm-gps-map-osd.h \ osm-gps-map-layer.h \ osm-gps-map-track.h \ osm-gps-map-polygon.h \ osm-gps-map-point.h \ osm-gps-map-image.h \ osm-gps-map-source.h \ osm-gps-map-widget.h \ osm-gps-map-compat.h sources_c = \ converter.c \ osd-utils.c \ osm-gps-map-osd.c \ osm-gps-map-layer.c \ osm-gps-map-track.c \ osm-gps-map-polygon.c \ osm-gps-map-point.c \ osm-gps-map-image.c \ osm-gps-map-source.c \ osm-gps-map-widget.c \ osm-gps-map-compat.c libosmgpsmap_1_0_la_SOURCES = \ $(sources_public_h) \ $(sources_private_h) \ $(sources_c) libosmgpsmapincdir = $(includedir)/osmgpsmap-1.0 libosmgpsmapinc_HEADERS = $(sources_public_h) ## Misc CLEANFILES = ## GObject Introspection Support -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = INTROSPECTION_SCANNER_ARGS = $(INTROSPECTION_FLAGS) --add-include-path=$(srcdir) --add-include-path=$(builddir) --warn-all INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) --includedir=$(builddir) if HAVE_INTROSPECTION introspection_sources = $(sources_c) $(sources_public_h) OsmGpsMap-1.0.gir: libosmgpsmap-1.0.la OsmGpsMap_1_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 OsmGpsMap_1_0_gir_CFLAGS = $(OSMGPSMAP_CFLAGS) -I$(srcdir) -I$(builddir) OsmGpsMap_1_0_gir_LIBS = libosmgpsmap-1.0.la OsmGpsMap_1_0_gir_FILES = $(introspection_sources) OsmGpsMap_1_0_gir_SCANNERFLAGS = --identifier-prefix=OsmGps --c-include "osm-gps-map.h" INTROSPECTION_GIRS += OsmGpsMap-1.0.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) typelibdir = $(libdir)/girepository-1.0 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelib_DATA) endif osm-gps-map-1.1.0/src/converter.c000066400000000000000000000062121262345173300166220ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) Marcus Bauer 2008 * Copyright (C) 2013 John Stowers * Copyright (C) 2014 Martijn Goedhart * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include #include #include #include "private.h" #include "converter.h" /* * The (i)logb(x) function is equal to `floor(log(x) / log(2))` or * `floor(log2(x))`, but probably faster and also accepts negative values. * But this is only true when FLT_RADIX equals 2, which is on allmost all * machine. */ #if FLT_RADIX == 2 #define LOG2(x) (ilogb(x)) #else #define LOG2(x) ((int)floor(log2(abs(x)))) #endif 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 * * some more notes * http://manialabs.wordpress.com/2013/01/26/converting-latitude-and-longitude-to-map-tile-in-mercator-projection/ * * 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; } int latlon2zoom(int pix_height, int pix_width, float lat1, float lat2, float lon1, float lon2) { float lat1_m = atanh(sin(lat1)); float lat2_m = atanh(sin(lat2)); int zoom_lon = LOG2((double)(2 * pix_width * M_PI) / (TILESIZE * (lon2 - lon1))); int zoom_lat = LOG2((double)(2 * pix_height * M_PI) / (TILESIZE * (lat2_m - lat1_m))); return MIN(zoom_lon, zoom_lat); } osm-gps-map-1.1.0/src/converter.h000066400000000000000000000025471262345173300166360ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) Marcus Bauer 2008 * Copyright (C) John Stowers 2013 * * Contributions by * Everaldo Canuto 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ 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); int latlon2zoom(int pix_height, int pix_width, float lat1, float lat2, float lon1, float lon2); osm-gps-map-1.1.0/src/osd-utils.c000066400000000000000000000250451262345173300165430ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include #include #include #include #include #include "osd-utils.h" #define DEBUG_DRAWING 0 /* these can be overwritten with versions that support localization */ #define OSD_COORDINATES_CHR_N "N" #define OSD_COORDINATES_CHR_S "S" #define OSD_COORDINATES_CHR_E "E" #define OSD_COORDINATES_CHR_W "W" static void debug_bbox(cairo_t *cr, gint x, gint y, gint w, gint h) { #if DEBUG_DRAWING osd_draw_bbox(cr, x, y, w, h); #endif } /* this is the classic geocaching notation */ char * osd_latitude_str(float latitude) { char *c = OSD_COORDINATES_CHR_N; float integral, fractional; if(isnan(latitude)) return NULL; if(latitude < 0) { latitude = fabs(latitude); c = OSD_COORDINATES_CHR_S; } fractional = modff(latitude, &integral); return g_strdup_printf("%s %02d° %06.3f'", c, (int)integral, fractional*60.0); } char * osd_longitude_str(float longitude) { char *c = OSD_COORDINATES_CHR_E; float integral, fractional; if(isnan(longitude)) return NULL; if(longitude < 0) { longitude = fabs(longitude); c = OSD_COORDINATES_CHR_W; } fractional = modff(longitude, &integral); return g_strdup_printf("%s %03d° %06.3f'", c, (int)integral, fractional*60.0); } /* render a string at the given screen position */ int osd_render_centered_text(cairo_t *cr, int y, int width, int font_size, char *text) { if(!text) return y; char *p = g_malloc(strlen(text)+4); // space for "...\n" strcpy(p, text); cairo_text_extents_t extents; memset(&extents, 0, sizeof(cairo_text_extents_t)); cairo_text_extents (cr, p, &extents); g_assert(extents.width != 0.0); /* check if text needs to be truncated */ int trunc_at = strlen(text); while(extents.width > width) { /* cut off all utf8 multibyte remains so the actual */ /* truncation only deals with one byte */ while((p[trunc_at-1] & 0xc0) == 0x80) { trunc_at--; g_assert(trunc_at > 0); } trunc_at--; g_assert(trunc_at > 0); strcpy(p+trunc_at, "..."); cairo_text_extents (cr, p, &extents); } cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_set_line_width (cr, font_size/6); cairo_move_to (cr, (width - extents.width)/2, y - extents.y_bearing); cairo_text_path (cr, p); cairo_stroke (cr); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_move_to (cr, (width - extents.width)/2, y - extents.y_bearing); cairo_show_text (cr, p); g_free(p); /* skip + 1/5 line */ return y + 6*font_size/5; } void osd_render_crosshair_shape(cairo_t *cr, int w, int h, int r, int tick) { cairo_arc (cr, w/2, h/2, r, 0, 2*M_PI); cairo_move_to (cr, w/2 - r, h/2); cairo_rel_line_to (cr, -tick, 0); cairo_move_to (cr, w/2 + r, h/2); cairo_rel_line_to (cr, tick, 0); cairo_move_to (cr, w/2, h/2 - r); cairo_rel_line_to (cr, 0, -tick); cairo_move_to (cr, w/2, h/2 + r); cairo_rel_line_to (cr, 0, tick); cairo_stroke (cr); } void osd_shape_shadow(cairo_t *cr) { cairo_set_source_rgba (cr, 0, 0, 0, 0.2); cairo_fill (cr); cairo_stroke (cr); } void osd_shape(cairo_t *cr, GdkRGBA *bg, GdkRGBA *fg) { gdk_cairo_set_source_rgba(cr, bg); cairo_fill_preserve (cr); gdk_cairo_set_source_rgba(cr, fg); cairo_set_line_width (cr, 1); cairo_stroke (cr); } void osd_draw_bbox(cairo_t *cr, gint x, gint y, gint w, gint h) { cairo_move_to (cr, x, y); cairo_rel_line_to (cr, w, 0); cairo_rel_line_to (cr, 0, h); cairo_rel_line_to (cr, -w, 0); cairo_rel_line_to (cr, 0, -h); cairo_set_source_rgba (cr, 1, 0, 0, 0.5); // cairo_fill (cr); cairo_stroke (cr); } /* create the cairo shape used for the zoom buttons */ static void osd_zoom_shape(cairo_t *cr, gint x, gint y, gint w, gint h) { gint r = h/2; /* radius of curved ends of zoom pad */ x += r; cairo_move_to (cr, x, y); cairo_rel_line_to (cr, w-2*r, 0); cairo_arc (cr, x+w-2*r, y+r, r, -M_PI/2, M_PI/2); cairo_rel_line_to (cr, -(w-2*r), 0); cairo_arc (cr, x, y+r, r, M_PI/2, -M_PI/2); } static void osd_zoom_labels(cairo_t *cr, gint x, gint y, gint w, gint h) { gint r = h/2; /* radius of curved ends of zoom pad */ gint l = h/3; /* length of lines that draw -/+ */ x += r; cairo_move_to (cr, x-l, y+r); cairo_rel_line_to (cr, 2*l, 0); cairo_move_to (cr, x+w-2*r, y+r-l); cairo_rel_line_to (cr, 0, 2*l); cairo_move_to (cr, x+w-l-2*r, y+r); cairo_rel_line_to (cr, 2*l, 0); } void osd_render_zoom(cairo_t *cr, gint x, gint y, gint w, gint h, gint gps, gint shadow, GdkRGBA *bg, GdkRGBA *fg) { /* add the width of the GPS widget */ w += gps; if (shadow) { osd_zoom_shape(cr, x+shadow, y+shadow, w, h); osd_shape_shadow(cr); } osd_zoom_shape(cr, x, y, w, h); osd_shape(cr, bg, fg); osd_zoom_labels(cr, x, y, w, h); osd_shape(cr, bg, fg); debug_bbox(cr, x, y, w, h); } static void osd_dpad_shape(cairo_t *cr, gint x, gint y, gint r) { cairo_arc (cr, x+r, y+r, r, 0, 2 * M_PI); } static void osd_dpad_labels(cairo_t *cr, gint x, gint y, gint r) { /* move reference to dpad center */ x += r; y += r; double D_TIP = 4*r/5; /* distance of arrow tip from dpad center */ double D_LEN = r/4; /* length of arrow */ double D_WID = D_LEN; /* width of arrow */ /* left arrow/triangle */ cairo_move_to (cr, x + (-D_TIP+D_LEN), y + (-D_WID)); cairo_rel_line_to (cr, -D_LEN, D_WID); cairo_rel_line_to (cr, +D_LEN, D_WID); /* right arrow/triangle */ cairo_move_to (cr, x + (+D_TIP-D_LEN), y + (-D_WID)); cairo_rel_line_to (cr, +D_LEN, D_WID); cairo_rel_line_to (cr, -D_LEN, D_WID); /* top arrow/triangle */ cairo_move_to (cr, x + (-D_WID), y + (-D_TIP+D_LEN)); cairo_rel_line_to (cr, D_WID, -D_LEN); cairo_rel_line_to (cr, D_WID, +D_LEN); /* bottom arrow/triangle */ cairo_move_to (cr, x + (-D_WID), y + (+D_TIP-D_LEN)); cairo_rel_line_to (cr, D_WID, +D_LEN); cairo_rel_line_to (cr, D_WID, -D_LEN); } void osd_render_dpad(cairo_t *cr, gint x, gint y, gint r, gint gps, gint shadow, GdkRGBA *bg, GdkRGBA *fg) { if (shadow) { osd_dpad_shape(cr, x+shadow, y+shadow, r); osd_shape_shadow(cr); } osd_dpad_shape(cr, x, y, r); osd_shape(cr, bg, fg); osd_dpad_labels(cr, x, y, r); osd_shape(cr, bg, fg); debug_bbox(cr, x, y, 2*r, 2*r); } gboolean osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad) { return( pow(cx - x, 2) + pow(cy - y, 2) < rad * rad); } OsdControlPress_t osd_check_dpad(gint x, gint y, gint r, gboolean has_gps) { /* within entire dpad circle */ if( osm_gps_map_in_circle(x, y, r, r, r)) { /* convert into position relative to dpads centre */ x -= r; y -= r; if (has_gps) if( osm_gps_map_in_circle(x, y, 0, 0, r/3)) return OSD_GPS; if( y < 0 && abs(x) < abs(y)) return OSD_UP; if( y > 0 && abs(x) < abs(y)) return OSD_DOWN; if( x < 0 && abs(y) < abs(x)) return OSD_LEFT; if( x > 0 && abs(y) < abs(x)) return OSD_RIGHT; } return OSD_NONE; } OsdControlPress_t osd_check_zoom(gint x, gint y, guint w, guint h, guint gps_w) { //osd_zoom_shape(cairo_t *cr, gint x, gint y, gint w, gint h) { //gint r = h/2; /* radius of curved ends of zoom pad */ // //x += r; // //cairo_move_to (cr, x, y); //cairo_rel_line_to (cr, w-2*r, 0); //cairo_arc (cr, x+w-2*r, y+r, r, -M_PI/2, M_PI/2); //cairo_rel_line_to (cr, -(w-2*r), 0); //cairo_arc (cr, x, y+r, r, M_PI/2, -M_PI/2); /* within entire zoom area */ if( x > 0 && x < w && y > 0 && y < h) { gint r = h/2; /* radius of curved ends of zoom pad */ /* within circle around (-) label */ if( osm_gps_map_in_circle(x, y, r, r, r)) return OSD_OUT; /* within circle around (+) label */ if( osm_gps_map_in_circle(x, y, w-r, r, r)) return OSD_IN; //#if Z_GPS == 1 // /* within square around center */ // if( x > Z_CENTER - Z_RAD && x < Z_CENTER + Z_RAD) // return OSD_GPS; //#endif // // /* between center of (-) button and center of entire zoom control area */ // if(x > OSD_LEFT && x < D_RAD) // return OSD_OUT; // // /* between center of (+) button and center of entire zoom control area */ // if(x < OSD_RIGHT && x > D_RAD) // return OSD_IN; } return OSD_NONE; } /* draw a satellite receiver dish */ void osd_render_gps(cairo_t *cr, gint x, gint y, gint w, GdkRGBA *bg, GdkRGBA *fg) { gint ox = x; gint oy = y; /* these define the gps widget shape */ double GPS_V0 = 1.5*w/7.0; double GPS_V1 = 1.5*w/10.0; double GPS_V2 = 1.5*w/5.0; /* move reference to bounding box center */ x += (2*w/5); y += (2*w/3); cairo_move_to (cr, x-GPS_V0, y+GPS_V0); cairo_rel_line_to (cr, +GPS_V0, -GPS_V0); cairo_rel_line_to (cr, +GPS_V0, +GPS_V0); cairo_close_path (cr); cairo_move_to (cr, x+GPS_V1-GPS_V2, y-2*GPS_V2); cairo_curve_to (cr, x-GPS_V2, y, x+GPS_V1, y+GPS_V1, x+GPS_V1+GPS_V2, y); cairo_close_path (cr); x += GPS_V1; cairo_move_to (cr, x, y-GPS_V2); cairo_rel_line_to (cr, +GPS_V1, -GPS_V1); osd_shape(cr, bg, fg); debug_bbox(cr, ox, oy, w, w); } osm-gps-map-1.1.0/src/osd-utils.h000066400000000000000000000041661262345173300165510ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) Marcus Bauer 2008 * Copyright (C) John Stowers 2013 * * Contributions by * Everaldo Canuto 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef __OSD_UTILS_H__ #define __OSD_UTILS_H__ #include #include typedef enum { OSD_NONE, OSD_UP, OSD_DOWN, OSD_LEFT, OSD_RIGHT, OSD_GPS, OSD_OUT, OSD_IN } OsdControlPress_t; char *osd_latitude_str(float latitude); char *osd_longitude_str(float longitude); int osd_render_centered_text(cairo_t *cr, int y, int width, int font_size, char *text); void osd_render_crosshair_shape(cairo_t *cr, int w, int h, int r, int tick); void osd_shape_shadow(cairo_t *cr); void osd_shape(cairo_t *cr, GdkRGBA *bg, GdkRGBA *fg); void osd_render_zoom(cairo_t *cr, gint x, gint y, gint w, gint h, gint gps, gint shadow, GdkRGBA *bg, GdkRGBA *fg); void osd_render_dpad(cairo_t *cr, gint x, gint y, gint r, gint gps, gint shadow, GdkRGBA *bg, GdkRGBA *fg); void osd_draw_bbox(cairo_t *cr, gint x, gint y, gint w, gint h); gboolean osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad); OsdControlPress_t osd_check_dpad(gint x, gint y, gint r, gboolean has_gps); OsdControlPress_t osd_check_zoom(gint x, gint y, guint w, guint h, guint gps_w); void osd_render_gps(cairo_t *cr, gint x, gint y, gint r, GdkRGBA *bg, GdkRGBA *fg); #endif /* __OSD_UTILS_H__ */ osm-gps-map-1.1.0/src/osm-gps-map-compat.c000066400000000000000000000015561262345173300202420ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include "converter.h" #include "osm-gps-map-compat.h" osm-gps-map-1.1.0/src/osm-gps-map-compat.h000066400000000000000000000017231262345173300202430ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_COMPAT_H #define _OSM_GPS_MAP_COMPAT_H #include "osm-gps-map-widget.h" G_BEGIN_DECLS G_END_DECLS #endif /* _OSM_GPS_MAP_COMPAT_H */ osm-gps-map-1.1.0/src/osm-gps-map-image.c000066400000000000000000000236671262345173300200500ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ /** * SECTION:osm-gps-map-image * @short_description: An image shown on the map * @stability: Stable * @include: osm-gps-map.h * * #OsmGpsMapImage represents an image (a #GdkPixbuf) shown on the map * (osm_gps_map_image_add()) at a specific location (a #OsmGpsMapPoint). **/ #include #include #include "converter.h" #include "osm-gps-map-track.h" #include "osm-gps-map-image.h" G_DEFINE_TYPE (OsmGpsMapImage, osm_gps_map_image, G_TYPE_OBJECT) enum { PROP_0, PROP_PIXBUF, PROP_X_ALIGN, PROP_Y_ALIGN, PROP_POINT, PROP_Z_ORDER, PROP_ROTATION }; struct _OsmGpsMapImagePrivate { OsmGpsMapPoint *pt; GdkPixbuf *pixbuf; int w; int h; gfloat xalign; gfloat yalign; int zorder; float rotation; }; static void osm_gps_map_image_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv; switch (property_id) { case PROP_PIXBUF: g_value_set_object (value, priv->pixbuf); break; case PROP_X_ALIGN: g_value_set_float (value, priv->xalign); break; case PROP_Y_ALIGN: g_value_set_float (value, priv->yalign); break; case PROP_POINT: g_value_set_boxed (value, priv->pt); break; case PROP_Z_ORDER: g_value_set_int (value, priv->zorder); break; case PROP_ROTATION: g_value_set_float(value, priv->rotation); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_image_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv; switch (property_id) { case PROP_PIXBUF: if (priv->pixbuf) g_object_unref (priv->pixbuf); priv->pixbuf = g_value_dup_object (value); priv->w = gdk_pixbuf_get_width(priv->pixbuf); priv->h = gdk_pixbuf_get_height(priv->pixbuf); break; case PROP_X_ALIGN: priv->xalign = g_value_get_float (value); break; case PROP_Y_ALIGN: priv->yalign = g_value_get_float (value); break; case PROP_POINT: priv->pt = g_value_dup_boxed (value); break; case PROP_Z_ORDER: priv->zorder = g_value_get_int (value); break; case PROP_ROTATION: priv->rotation = g_value_get_float(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_image_dispose (GObject *object) { OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv; if (priv->pixbuf) g_object_unref (priv->pixbuf); G_OBJECT_CLASS (osm_gps_map_image_parent_class)->dispose (object); } static void osm_gps_map_image_finalize (GObject *object) { G_OBJECT_CLASS (osm_gps_map_image_parent_class)->finalize (object); } static void osm_gps_map_image_class_init (OsmGpsMapImageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (OsmGpsMapImagePrivate)); object_class->get_property = osm_gps_map_image_get_property; object_class->set_property = osm_gps_map_image_set_property; object_class->dispose = osm_gps_map_image_dispose; object_class->finalize = osm_gps_map_image_finalize; g_object_class_install_property (object_class, PROP_PIXBUF, g_param_spec_object ("pixbuf", "pixbuf", "the pixbuf for this image", GDK_TYPE_PIXBUF, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_X_ALIGN, g_param_spec_float ("x-align", "x-align", "image x-alignment", 0.0, /* minimum property value */ 1.0, /* maximum property value */ 0.5, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_Y_ALIGN, g_param_spec_float ("y-align", "y-align", "image y-alignment", 0.0, /* minimum property value */ 1.0, /* maximum property value */ 0.5, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_POINT, g_param_spec_boxed ("point", "point", "location point", OSM_TYPE_GPS_MAP_POINT, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_Z_ORDER, g_param_spec_int ("z-order", "z-order", "image z-order", -100, /* minimum property value */ 100, /* maximum property value */ 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_ROTATION, g_param_spec_float ("rotation", "rotation", "image rotation", -180.0, /* minimum property value */ 180.0, /* maximum property value */ 0.0f, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); } static void osm_gps_map_image_init (OsmGpsMapImage *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImagePrivate); } OsmGpsMapImage * osm_gps_map_image_new (void) { return g_object_new (OSM_TYPE_GPS_MAP_IMAGE, NULL); } void osm_gps_map_image_draw (OsmGpsMapImage *object, cairo_t *cr, GdkRectangle *rect) { OsmGpsMapImagePrivate *priv; int xoffset, yoffset; gdouble x,y; g_return_if_fail (OSM_IS_GPS_MAP_IMAGE (object)); priv = OSM_GPS_MAP_IMAGE(object)->priv; xoffset = priv->xalign * priv->w; yoffset = priv->yalign * priv->h; x = rect->x - xoffset; y = rect->y - yoffset; cairo_translate(cr, x+(priv->w/2), y+(priv->h/2)); cairo_rotate(cr, deg2rad(priv->rotation)); cairo_translate(cr, -(x+(priv->w/2)), -(y+(priv->h/2))); gdk_cairo_set_source_pixbuf (cr, priv->pixbuf, x, y); cairo_paint (cr); cairo_translate(cr, x+(priv->w/2), y+(priv->h/2)); cairo_rotate(cr, -deg2rad(priv->rotation)); cairo_translate(cr, -(x+(priv->w/2)), -(y+(priv->h/2))); rect->width = priv->w; rect->height = priv->h; } const OsmGpsMapPoint * osm_gps_map_image_get_point(OsmGpsMapImage *object) { g_return_val_if_fail (OSM_IS_GPS_MAP_IMAGE (object), NULL); return object->priv->pt; } gint osm_gps_map_image_get_zorder(OsmGpsMapImage *object) { g_return_val_if_fail (OSM_IS_GPS_MAP_IMAGE (object), 0); return object->priv->zorder; } float osm_gps_map_image_get_rotation(OsmGpsMapImage* object) { return object->priv->rotation; } void osm_gps_map_image_set_rotation(OsmGpsMapImage* object, float rot) { object->priv->rotation = rot; } osm-gps-map-1.1.0/src/osm-gps-map-image.h000066400000000000000000000046551262345173300200510ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_IMAGE_H #define _OSM_GPS_MAP_IMAGE_H #include #include #include #include "osm-gps-map-point.h" G_BEGIN_DECLS #define OSM_TYPE_GPS_MAP_IMAGE osm_gps_map_image_get_type() #define OSM_GPS_MAP_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImage)) #define OSM_GPS_MAP_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImageClass)) #define OSM_IS_GPS_MAP_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_IMAGE)) #define OSM_IS_GPS_MAP_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_IMAGE)) #define OSM_GPS_MAP_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImageClass)) typedef struct _OsmGpsMapImage OsmGpsMapImage; typedef struct _OsmGpsMapImageClass OsmGpsMapImageClass; typedef struct _OsmGpsMapImagePrivate OsmGpsMapImagePrivate; struct _OsmGpsMapImage { GObject parent; OsmGpsMapImagePrivate *priv; }; struct _OsmGpsMapImageClass { GObjectClass parent_class; }; GType osm_gps_map_image_get_type (void) G_GNUC_CONST; OsmGpsMapImage *osm_gps_map_image_new (void); void osm_gps_map_image_draw (OsmGpsMapImage *object, cairo_t *cr, GdkRectangle *rect); const OsmGpsMapPoint *osm_gps_map_image_get_point(OsmGpsMapImage *object); gint osm_gps_map_image_get_zorder(OsmGpsMapImage *object); float osm_gps_map_image_get_rotation(OsmGpsMapImage* object); void osm_gps_map_image_set_rotation(OsmGpsMapImage* object, float rot); G_END_DECLS #endif /* _OSM_GPS_MAP_IMAGE_H */ osm-gps-map-1.1.0/src/osm-gps-map-layer.c000066400000000000000000000041701262345173300200660ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ /** * SECTION:osm-gps-map-layer * @short_description: An interface for layers to be drawn on the map * @stability: Stable * @include: osm-gps-map.h * * #OsmGpsMapLayer is an interface implemented by objects that wish * to draw on top of the map respond to button press events. The most * common implementation of this interface is #OsmGpsMapOsd **/ #include "osm-gps-map-layer.h" GType osm_gps_map_layer_get_type() { static GType object_type = 0; if (!object_type) { static const GTypeInfo object_info = { sizeof(OsmGpsMapLayerIface), NULL, /* base init */ NULL, /* base finalize */ }; object_type = g_type_register_static(G_TYPE_INTERFACE, "OsmGpsMapLayer", &object_info, 0); } return object_type; } void osm_gps_map_layer_render (OsmGpsMapLayer *self, OsmGpsMap *map) { OSM_GPS_MAP_LAYER_GET_INTERFACE (self)->render (self, map); } void osm_gps_map_layer_draw (OsmGpsMapLayer *self, OsmGpsMap *map, cairo_t *cr) { OSM_GPS_MAP_LAYER_GET_INTERFACE (self)->draw (self, map, cr); } gboolean osm_gps_map_layer_busy (OsmGpsMapLayer *self) { return OSM_GPS_MAP_LAYER_GET_INTERFACE (self)->busy (self); } gboolean osm_gps_map_layer_button_press (OsmGpsMapLayer *self, OsmGpsMap *map, GdkEventButton *event) { return OSM_GPS_MAP_LAYER_GET_INTERFACE (self)->button_press (self, map, event); } osm-gps-map-1.1.0/src/osm-gps-map-layer.h000066400000000000000000000050551262345173300200760ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 cino=t0,(0: */ /* * Copyright (C) Marcus Bauer 2008 * Copyright (C) John Stowers 2013 * Copyright (C) Till Harbaum 2009 * * Contributions by * Everaldo Canuto 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_LAYER_H_ #define _OSM_GPS_MAP_LAYER_H_ #include #include #include #include G_BEGIN_DECLS #define OSM_TYPE_GPS_MAP_LAYER (osm_gps_map_layer_get_type ()) #define OSM_GPS_MAP_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_LAYER, OsmGpsMapLayer)) #define OSM_GPS_MAP_IS_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_LAYER)) #define OSM_GPS_MAP_LAYER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), OSM_TYPE_GPS_MAP_LAYER, OsmGpsMapLayerIface)) typedef struct _OsmGpsMapLayer OsmGpsMapLayer; /* dummy object */ typedef struct _OsmGpsMapLayerIface OsmGpsMapLayerIface; #include "osm-gps-map-widget.h" struct _OsmGpsMapLayerIface { GTypeInterface parent; void (*render) (OsmGpsMapLayer *self, OsmGpsMap *map); void (*draw) (OsmGpsMapLayer *self, OsmGpsMap *map, cairo_t *cr); gboolean (*busy) (OsmGpsMapLayer *self); gboolean (*button_press) (OsmGpsMapLayer *self, OsmGpsMap *map, GdkEventButton *event); }; GType osm_gps_map_layer_get_type (void); void osm_gps_map_layer_render (OsmGpsMapLayer *self, OsmGpsMap *map); void osm_gps_map_layer_draw (OsmGpsMapLayer *self, OsmGpsMap *map, cairo_t *cr); gboolean osm_gps_map_layer_busy (OsmGpsMapLayer *self); gboolean osm_gps_map_layer_button_press (OsmGpsMapLayer *self, OsmGpsMap *map, GdkEventButton *event); G_END_DECLS #endif /* _OSM_GPS_MAP_LAYER_H_ */ osm-gps-map-1.1.0/src/osm-gps-map-osd.c000066400000000000000000000760371262345173300175520ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include #include #include "osd-utils.h" #include "private.h" #include "osm-gps-map-layer.h" #include "osm-gps-map-osd.h" static void osm_gps_map_osd_interface_init (OsmGpsMapLayerIface *iface); G_DEFINE_TYPE_WITH_CODE (OsmGpsMapOsd, osm_gps_map_osd, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (OSM_TYPE_GPS_MAP_LAYER, osm_gps_map_osd_interface_init)); enum { PROP_0, PROP_OSD_X, PROP_OSD_Y, PROP_DPAD_RADIUS, PROP_SHOW_SCALE, PROP_SHOW_COORDINATES, PROP_SHOW_CROSSHAIR, PROP_SHOW_DPAD, PROP_SHOW_ZOOM, PROP_SHOW_GPS_IN_DPAD, PROP_SHOW_GPS_IN_ZOOM }; typedef struct _OsdScale { cairo_surface_t *surface; int zoom; float lat; } OsdScale_t; typedef struct _OsdCoordinates { cairo_surface_t *surface; float lat, lon; } OsdCoordinates_t; typedef struct _OsdCorosshair { cairo_surface_t *surface; gboolean rendered; } OsdCrosshair_t; typedef struct _OsdControls { cairo_surface_t *surface; gboolean rendered; gint gps_enabled; } OsdControls_t; struct _OsmGpsMapOsdPrivate { OsdScale_t *scale; OsdCoordinates_t *coordinates; OsdCrosshair_t *crosshair; OsdControls_t *controls; guint osd_w; guint osd_h; guint osd_shadow; guint osd_pad; guint zoom_w; guint zoom_h; /* properties */ gint osd_x; gint osd_y; guint dpad_radius; gboolean show_scale; gboolean show_coordinates; gboolean show_crosshair; gboolean show_dpad; gboolean show_zoom; gboolean show_gps_in_dpad; gboolean show_gps_in_zoom; }; static void osm_gps_map_osd_render (OsmGpsMapLayer *osd, OsmGpsMap *map); static void osm_gps_map_osd_draw (OsmGpsMapLayer *osd, OsmGpsMap *map, cairo_t *cr); static gboolean osm_gps_map_osd_busy (OsmGpsMapLayer *osd); static gboolean osm_gps_map_osd_button_press (OsmGpsMapLayer *osd, OsmGpsMap *map, GdkEventButton *event); static void scale_render (OsmGpsMapOsd *self, OsmGpsMap *map); static void scale_draw (OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr); static void coordinates_render (OsmGpsMapOsd *self, OsmGpsMap *map); static void coordinates_draw (OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr); static void crosshair_render (OsmGpsMapOsd *self, OsmGpsMap *map); static void crosshair_draw (OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr); static void controls_render (OsmGpsMapOsd *self, OsmGpsMap *map); static void controls_draw (OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr); #define OSD_MAX_SHADOW (4) #define OSD_SCALE_FONT_SIZE (12.0) #define OSD_SCALE_W (10*OSD_SCALE_FONT_SIZE) #define OSD_SCALE_H (5*OSD_SCALE_FONT_SIZE/2) #define OSD_SCALE_H2 (OSD_SCALE_H/2) #define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3) #define OSD_SCALE_M (OSD_SCALE_H2 - OSD_SCALE_TICK) #define OSD_SCALE_I (OSD_SCALE_H2 + OSD_SCALE_TICK) #define OSD_SCALE_FD (OSD_SCALE_FONT_SIZE/4) #define OSD_COORDINATES_FONT_SIZE (12.0) #define OSD_COORDINATES_OFFSET (OSD_COORDINATES_FONT_SIZE/6) #define OSD_COORDINATES_W (8*OSD_COORDINATES_FONT_SIZE+2*OSD_COORDINATES_OFFSET) #define OSD_COORDINATES_H (2*OSD_COORDINATES_FONT_SIZE+2*OSD_COORDINATES_OFFSET+OSD_COORDINATES_FONT_SIZE/4) #define OSD_CROSSHAIR_RADIUS 10 #define OSD_CROSSHAIR_TICK (OSD_CROSSHAIR_RADIUS/2) #define OSD_CROSSHAIR_BORDER (OSD_CROSSHAIR_TICK + OSD_CROSSHAIR_RADIUS/4) #define OSD_CROSSHAIR_W ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) #define OSD_CROSSHAIR_H ((OSD_CROSSHAIR_RADIUS+OSD_CROSSHAIR_BORDER)*2) static void osm_gps_map_osd_interface_init (OsmGpsMapLayerIface *iface) { iface->render = osm_gps_map_osd_render; iface->draw = osm_gps_map_osd_draw; iface->busy = osm_gps_map_osd_busy; iface->button_press = osm_gps_map_osd_button_press; } static void osm_gps_map_osd_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_OSD_X: g_value_set_int (value, OSM_GPS_MAP_OSD (object)->priv->osd_x); break; case PROP_OSD_Y: g_value_set_int (value, OSM_GPS_MAP_OSD (object)->priv->osd_y); break; case PROP_DPAD_RADIUS: g_value_set_uint (value, OSM_GPS_MAP_OSD (object)->priv->dpad_radius); break; case PROP_SHOW_SCALE: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_scale); break; case PROP_SHOW_COORDINATES: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_coordinates); break; case PROP_SHOW_CROSSHAIR: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_crosshair); break; case PROP_SHOW_DPAD: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_dpad); break; case PROP_SHOW_ZOOM: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_zoom); break; case PROP_SHOW_GPS_IN_DPAD: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_gps_in_dpad); break; case PROP_SHOW_GPS_IN_ZOOM: g_value_set_boolean (value, OSM_GPS_MAP_OSD (object)->priv->show_gps_in_zoom); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_osd_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_OSD_X: OSM_GPS_MAP_OSD (object)->priv->osd_x = g_value_get_int (value); break; case PROP_OSD_Y: OSM_GPS_MAP_OSD (object)->priv->osd_y = g_value_get_int (value); break; case PROP_DPAD_RADIUS: OSM_GPS_MAP_OSD (object)->priv->dpad_radius = g_value_get_uint (value); break; case PROP_SHOW_SCALE: OSM_GPS_MAP_OSD (object)->priv->show_scale = g_value_get_boolean (value); break; case PROP_SHOW_COORDINATES: OSM_GPS_MAP_OSD (object)->priv->show_coordinates = g_value_get_boolean (value); break; case PROP_SHOW_CROSSHAIR: OSM_GPS_MAP_OSD (object)->priv->show_crosshair = g_value_get_boolean (value); break; case PROP_SHOW_DPAD: OSM_GPS_MAP_OSD (object)->priv->show_dpad = g_value_get_boolean (value); break; case PROP_SHOW_ZOOM: OSM_GPS_MAP_OSD (object)->priv->show_zoom = g_value_get_boolean (value); break; case PROP_SHOW_GPS_IN_DPAD: OSM_GPS_MAP_OSD (object)->priv->show_gps_in_dpad = g_value_get_boolean (value); break; case PROP_SHOW_GPS_IN_ZOOM: OSM_GPS_MAP_OSD (object)->priv->show_gps_in_zoom = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static GObject * osm_gps_map_osd_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties) { GObject *object; OsmGpsMapOsdPrivate *priv; /* Always chain up to the parent constructor */ object = G_OBJECT_CLASS(osm_gps_map_osd_parent_class)->constructor(gtype, n_properties, properties); priv = OSM_GPS_MAP_OSD(object)->priv; /* shadow also depends on control size */ priv->osd_shadow = MAX(priv->dpad_radius/8, OSD_MAX_SHADOW); /* distance between dpad and zoom */ priv->osd_pad = priv->dpad_radius/4; /* size of zoom pad is wrt. the dpad size */ priv->zoom_w = 2*priv->dpad_radius; priv->zoom_h = priv->dpad_radius; /* total width and height of controls incl. shadow */ priv->osd_w = 2*priv->dpad_radius + priv->osd_shadow + priv->zoom_w; priv->osd_h = 2*priv->dpad_radius + priv->osd_pad + priv->zoom_h + 2*priv->osd_shadow; priv->scale = g_new0(OsdScale_t, 1); priv->scale->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_SCALE_W, OSD_SCALE_H); priv->scale->zoom = -1; priv->scale->lat = 360.0; /* init to an invalid lat so we get re-rendered */ priv->coordinates = g_new0(OsdCoordinates_t, 1); priv->coordinates->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_COORDINATES_W, OSD_COORDINATES_H); priv->coordinates->lat = priv->coordinates->lon = OSM_GPS_MAP_INVALID; priv->crosshair = g_new0(OsdCrosshair_t, 1); priv->crosshair->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_CROSSHAIR_W, OSD_CROSSHAIR_H); priv->crosshair->rendered = FALSE; priv->controls = g_new0(OsdControls_t, 1); //FIXME: SIZE DEPENDS ON IF DPAD AND ZOOM IS THERE OR NOT priv->controls->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, priv->osd_w+2, priv->osd_h+2); priv->controls->rendered = FALSE; priv->controls->gps_enabled = -1; return object; } #define OSD_STRUCT_DESTROY(_x) \ if ((_x)) { \ if ((_x)->surface) \ cairo_surface_destroy((_x)->surface); \ g_free((_x)); \ } static void osm_gps_map_osd_finalize (GObject *object) { OsmGpsMapOsdPrivate *priv = OSM_GPS_MAP_OSD(object)->priv; OSD_STRUCT_DESTROY(priv->scale) OSD_STRUCT_DESTROY(priv->coordinates) OSD_STRUCT_DESTROY(priv->crosshair) OSD_STRUCT_DESTROY(priv->controls) G_OBJECT_CLASS (osm_gps_map_osd_parent_class)->finalize (object); } static void osm_gps_map_osd_class_init (OsmGpsMapOsdClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (OsmGpsMapOsdPrivate)); object_class->get_property = osm_gps_map_osd_get_property; object_class->set_property = osm_gps_map_osd_set_property; object_class->constructor = osm_gps_map_osd_constructor; object_class->finalize = osm_gps_map_osd_finalize; /** * OsmGpsMapOsd:osd-x: * * The osd x property. */ g_object_class_install_property (object_class, PROP_OSD_X, g_param_spec_int ("osd-x", "osd-x", "osd-x", G_MININT, G_MAXINT, 10, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:osd-y: * * The osd y property. */ g_object_class_install_property (object_class, PROP_OSD_Y, g_param_spec_int ("osd-y", "osd-y", "osd-y", G_MININT, G_MAXINT, 10, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:dpad-radius: * * The dpad radius property. */ g_object_class_install_property (object_class, PROP_DPAD_RADIUS, g_param_spec_uint ("dpad-radius", "dpad-radius", "dpad radius", 0, G_MAXUINT, 30, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-scale: * * The show scale on the map property. */ g_object_class_install_property (object_class, PROP_SHOW_SCALE, g_param_spec_boolean ("show-scale", "show-scale", "show scale on the map", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-coordinates: * * The show coordinates of map centre property. */ g_object_class_install_property (object_class, PROP_SHOW_COORDINATES, g_param_spec_boolean ("show-coordinates", "show-coordinates", "show coordinates of map centre", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-crosshair: * * The show crosshair at map centre property. */ g_object_class_install_property (object_class, PROP_SHOW_CROSSHAIR, g_param_spec_boolean ("show-crosshair", "show-crosshair", "show crosshair at map centre", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-dpad: * * The show dpad for map navigation property. */ g_object_class_install_property (object_class, PROP_SHOW_DPAD, g_param_spec_boolean ("show-dpad", "show-dpad", "show dpad for map navigation", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-zoom: * * The show zoom control for map navigation property. */ g_object_class_install_property (object_class, PROP_SHOW_ZOOM, g_param_spec_boolean ("show-zoom", "show-zoom", "show zoom control for map navigation", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-gps-in-dpad: * * The show gps indicator in middle of dpad property. */ g_object_class_install_property (object_class, PROP_SHOW_GPS_IN_DPAD, g_param_spec_boolean ("show-gps-in-dpad", "show-gps-in-dpad", "show gps indicator in middle of dpad", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapOsd:show-gps-in-zoom: * * The show gps indicator in middle of zoom control property. */ g_object_class_install_property (object_class, PROP_SHOW_GPS_IN_ZOOM, g_param_spec_boolean ("show-gps-in-zoom", "show-gps-in-zoom", "show gps indicator in middle of zoom control", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } static void osm_gps_map_osd_init (OsmGpsMapOsd *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OSM_TYPE_GPS_MAP_OSD, OsmGpsMapOsdPrivate); } static void osm_gps_map_osd_render (OsmGpsMapLayer *osd, OsmGpsMap *map) { OsmGpsMapOsd *self; OsmGpsMapOsdPrivate *priv; g_return_if_fail(OSM_IS_GPS_MAP_OSD(osd)); self = OSM_GPS_MAP_OSD(osd); priv = self->priv; if (priv->show_scale) scale_render(self, map); if (priv->show_coordinates) coordinates_render(self, map); if (priv->show_crosshair) crosshair_render(self, map); if (priv->show_zoom || priv->show_dpad) controls_render(self, map); } static void osm_gps_map_osd_draw (OsmGpsMapLayer *osd, OsmGpsMap *map, cairo_t *cr) { OsmGpsMapOsd *self; OsmGpsMapOsdPrivate *priv; GtkAllocation allocation; g_return_if_fail(OSM_IS_GPS_MAP_OSD(osd)); self = OSM_GPS_MAP_OSD(osd); priv = self->priv; gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); if (priv->show_scale) scale_draw(self, &allocation, cr); if (priv->show_coordinates) coordinates_draw(self, &allocation, cr); if (priv->show_crosshair) crosshair_draw(self, &allocation, cr); if (priv->show_zoom || priv->show_dpad) controls_draw(self, &allocation, cr); } static gboolean osm_gps_map_osd_busy (OsmGpsMapLayer *osd) { return FALSE; } static gboolean osm_gps_map_osd_button_press (OsmGpsMapLayer *osd, OsmGpsMap *map, GdkEventButton *event) { gboolean handled = FALSE; OsdControlPress_t but = OSD_NONE; OsmGpsMapOsd *self; OsmGpsMapOsdPrivate *priv; GtkAllocation allocation; g_return_val_if_fail(OSM_IS_GPS_MAP_OSD(osd), FALSE); self = OSM_GPS_MAP_OSD(osd); priv = self->priv; gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); if ((event->button == 1) && (event->type == GDK_BUTTON_PRESS)) { gint mx = event->x - priv->osd_x; gint my = event->y - priv->osd_y; if(priv->osd_x < 0) mx -= (allocation.width - priv->osd_w); if(priv->osd_y < 0) my -= (allocation.height - priv->osd_h); /* first do a rough test for the OSD area. */ /* this is just to avoid an unnecessary detailed test */ if(mx > 0 && mx < priv->osd_w && my > 0 && my < priv->osd_h) { if (priv->show_dpad) { but = osd_check_dpad(mx, my, priv->dpad_radius, priv->show_gps_in_dpad); my -= (2*priv->dpad_radius); my -= priv->osd_pad; } if (but == OSD_NONE && priv->show_zoom) but = osd_check_zoom(mx, my, priv->zoom_w, priv->zoom_h, 0 /*show gps*/); } } switch (but) { case OSD_LEFT: osm_gps_map_scroll(map, -5, 0); handled = TRUE; break; case OSD_RIGHT: osm_gps_map_scroll(map, 5, 0); handled = TRUE; break; case OSD_UP: osm_gps_map_scroll(map, 0, -5); handled = TRUE; break; case OSD_DOWN: osm_gps_map_scroll(map, 0, 5); handled = TRUE; break; case OSD_OUT: osm_gps_map_zoom_out(map); handled = TRUE; break; case OSD_IN: osm_gps_map_zoom_in(map); handled = TRUE; break; case OSD_NONE: case OSD_GPS: default: handled = FALSE; break; } return handled; } /** * osm_gps_map_osd_new: * * Creates a new instance of #OsmGpsMapOsd. * * Return value: the newly created #OsmGpsMapOsd instance */ OsmGpsMapOsd* osm_gps_map_osd_new (void) { return g_object_new (OSM_TYPE_GPS_MAP_OSD, NULL); } static void scale_render(OsmGpsMapOsd *self, OsmGpsMap *map) { OsdScale_t *scale = self->priv->scale; if(!scale->surface) return; /* this only needs to be rendered if the zoom or latitude has changed */ gint zoom; gfloat lat; g_object_get(G_OBJECT(map), "zoom", &zoom, "latitude", &lat, NULL); if(zoom == scale->zoom && lat == scale->lat) return; scale->zoom = zoom; scale->lat = lat; float m_per_pix = osm_gps_map_get_scale(map); /* first fill with transparency */ g_assert(scale->surface); cairo_t *cr = cairo_create(scale->surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0); // pink for testing: cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); /* determine the size of the scale width in meters */ float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix; /* scale this to useful values */ int exp = logf(width)*M_LOG10E; int mant = width/pow(10,exp); int width_metric = mant * pow(10,exp); char *dist_str = NULL; if(width_metric<1000) dist_str = g_strdup_printf("%u m", width_metric); else dist_str = g_strdup_printf("%u km", width_metric/1000); width_metric /= m_per_pix; /* and now the hard part: scale for useful imperial values :-( */ /* try to convert to feet, 1ft == 0.3048 m */ width /= 0.3048; float imp_scale = 0.3048; char *dist_imp_unit = "ft"; if(width >= 100) { /* 1yd == 3 feet */ width /= 3.0; imp_scale *= 3.0; dist_imp_unit = "yd"; if(width >= 1760.0) { /* 1mi == 1760 yd */ width /= 1760.0; imp_scale *= 1760.0; dist_imp_unit = "mi"; } } /* also convert this to full tens/hundreds */ exp = logf(width)*M_LOG10E; mant = width/pow(10,exp); int width_imp = mant * pow(10,exp); char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit); /* convert back to pixels */ width_imp *= imp_scale; width_imp /= m_per_pix; cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_text_extents_t extents; cairo_text_extents (cr, dist_str, &extents); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); cairo_text_path (cr, dist_str); cairo_stroke (cr); cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2+OSD_SCALE_FD + extents.height); cairo_text_path (cr, dist_str_imp); cairo_stroke (cr); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD); cairo_show_text (cr, dist_str); cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2+OSD_SCALE_FD + extents.height); cairo_show_text (cr, dist_str_imp); g_free(dist_str); g_free(dist_str_imp); /* draw white line */ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3); cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); cairo_rel_line_to (cr, width_metric, 0); cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); cairo_stroke(cr); cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); cairo_rel_line_to (cr, width_imp, 0); cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); cairo_stroke(cr); /* draw black line */ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6); cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M); cairo_rel_line_to (cr, 0, OSD_SCALE_TICK); cairo_rel_line_to (cr, width_metric, 0); cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); cairo_stroke(cr); cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I); cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK); cairo_rel_line_to (cr, width_imp, 0); cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK); cairo_stroke(cr); cairo_destroy(cr); } static void scale_draw(OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr) { OsmGpsMapOsdPrivate *priv = self->priv; OsdScale_t *scale = self->priv->scale; gint x, y; x = priv->osd_x; y = -priv->osd_y; if(x < 0) x += allocation->width - OSD_SCALE_W; if(y < 0) y += allocation->height - OSD_SCALE_H; cairo_set_source_surface(cr, scale->surface, x, y); cairo_paint(cr); } static void coordinates_render(OsmGpsMapOsd *self, OsmGpsMap *map) { OsdCoordinates_t *coordinates = self->priv->coordinates; if(!coordinates->surface) return; /* get current map position */ gfloat lat, lon; g_object_get(G_OBJECT(map), "latitude", &lat, "longitude", &lon, NULL); /* check if position has changed enough to require redraw */ if(!isnan(coordinates->lat) && !isnan(coordinates->lon)) /* 1/60000 == 1/1000 minute */ if((fabsf(lat - coordinates->lat) < 1/60000) && (fabsf(lon - coordinates->lon) < 1/60000)) return; coordinates->lat = lat; coordinates->lon = lon; /* first fill with transparency */ g_assert(coordinates->surface); cairo_t *cr = cairo_create(coordinates->surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.5); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, OSD_COORDINATES_FONT_SIZE); char *latitude = osd_latitude_str(lat); char *longitude = osd_longitude_str(lon); int y = OSD_COORDINATES_OFFSET; y = osd_render_centered_text(cr, y, OSD_COORDINATES_W, OSD_COORDINATES_FONT_SIZE, latitude); y = osd_render_centered_text(cr, y, OSD_COORDINATES_W, OSD_COORDINATES_FONT_SIZE, longitude); g_free(latitude); g_free(longitude); cairo_destroy(cr); } static void coordinates_draw(OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr) { OsmGpsMapOsdPrivate *priv = self->priv; OsdCoordinates_t *coordinates = self->priv->coordinates; gint x,y; x = -priv->osd_x; y = -priv->osd_y; if(x < 0) x += allocation->width - OSD_COORDINATES_W; if(y < 0) y += allocation->height - OSD_COORDINATES_H; cairo_set_source_surface(cr, coordinates->surface, x, y); cairo_paint(cr); } static void crosshair_render(OsmGpsMapOsd *self, OsmGpsMap *map) { OsdCrosshair_t *crosshair = self->priv->crosshair; if(!crosshair->surface || crosshair->rendered) return; crosshair->rendered = TRUE; /* first fill with transparency */ g_assert(crosshair->surface); cairo_t *cr = cairo_create(crosshair->surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5); cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/2); osd_render_crosshair_shape(cr, OSD_CROSSHAIR_W, OSD_CROSSHAIR_H, OSD_CROSSHAIR_RADIUS, OSD_CROSSHAIR_TICK); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); cairo_set_line_width (cr, OSD_CROSSHAIR_RADIUS/4); osd_render_crosshair_shape(cr, OSD_CROSSHAIR_W, OSD_CROSSHAIR_H, OSD_CROSSHAIR_RADIUS, OSD_CROSSHAIR_TICK); cairo_destroy(cr); } static void crosshair_draw(OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr) { OsdCrosshair_t *crosshair = self->priv->crosshair; gint x,y; x = (allocation->width - OSD_CROSSHAIR_W)/2; y = (allocation->height - OSD_CROSSHAIR_H)/2; cairo_set_source_surface(cr, crosshair->surface, x, y); cairo_paint(cr); } static void controls_render(OsmGpsMapOsd *self, OsmGpsMap *map) { GdkRGBA fg, bg; OsmGpsMapOsdPrivate *priv = self->priv; OsdControls_t *controls = self->priv->controls; if(!controls->surface || controls->rendered) return; controls->rendered = TRUE; gdk_rgba_parse (&fg, "black"); gdk_rgba_parse (&bg, "grey80"); /* first fill with transparency */ g_assert(controls->surface); cairo_t *cr = cairo_create(controls->surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); gint x = 1; gint y = 1; /* --------- draw dpad ----------- */ if (priv->show_dpad) { gint gps_w = (priv->show_gps_in_dpad ? priv->dpad_radius/2 : 0); osd_render_dpad(cr, x, y, priv->dpad_radius, gps_w, priv->osd_shadow, &bg, &fg); if (priv->show_gps_in_dpad) { gint gps_x = x+priv->dpad_radius-(gps_w/2); gint gps_y = y+priv->dpad_radius-(gps_w/2); osd_render_gps(cr, gps_x, gps_y, gps_w, &bg, &fg); } y += (2*priv->dpad_radius); y += priv->osd_pad; } /* --------- draw zoom ----------- */ if (priv->show_zoom) { gint gps_w = (priv->show_gps_in_zoom ? priv->dpad_radius/2 : 0); osd_render_zoom(cr, x, y, priv->zoom_w, priv->zoom_h, gps_w, priv->osd_shadow, &bg, &fg); if (priv->show_gps_in_zoom) { gint gps_x = x+(priv->zoom_w/2); gint gps_y = y+(priv->zoom_h/2)-(gps_w/2); osd_render_gps(cr, gps_x, gps_y, gps_w, &bg, &fg); } y += priv->zoom_h; } } static void controls_draw(OsmGpsMapOsd *self, GtkAllocation *allocation, cairo_t *cr) { OsmGpsMapOsdPrivate *priv = self->priv; OsdControls_t *controls = self->priv->controls; gint x,y; x = priv->osd_x; if(x < 0) x += allocation->width - priv->osd_w; y = priv->osd_y; if(y < 0) y += allocation->height - priv->osd_h; cairo_set_source_surface(cr, controls->surface, x, y); cairo_paint(cr); } osm-gps-map-1.1.0/src/osm-gps-map-osd.h000066400000000000000000000037621262345173300175520ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef __OSM_GPS_MAP_OSD_H__ #define __OSM_GPS_MAP_OSD_H__ #include G_BEGIN_DECLS #define OSM_TYPE_GPS_MAP_OSD (osm_gps_map_osd_get_type()) #define OSM_GPS_MAP_OSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_OSD, OsmGpsMapOsd)) #define OSM_GPS_MAP_OSD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_OSD, OsmGpsMapOsdClass)) #define OSM_IS_GPS_MAP_OSD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_OSD)) #define OSM_IS_GPS_MAP_OSD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_OSD)) #define OSM_GPS_MAP_OSD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_OSD, OsmGpsMapOsdClass)) typedef struct _OsmGpsMapOsd OsmGpsMapOsd; typedef struct _OsmGpsMapOsdClass OsmGpsMapOsdClass; typedef struct _OsmGpsMapOsdPrivate OsmGpsMapOsdPrivate; struct _OsmGpsMapOsd { GObject parent; /*< private >*/ OsmGpsMapOsdPrivate *priv; }; struct _OsmGpsMapOsdClass { GObjectClass parent_class; /* vtable */ }; GType osm_gps_map_osd_get_type (void); OsmGpsMapOsd* osm_gps_map_osd_new (void); G_END_DECLS #endif /* __OSM_GPS_MAP_OSD_H__ */ osm-gps-map-1.1.0/src/osm-gps-map-point.c000066400000000000000000000061701262345173300201050ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ /** * SECTION:osm-gps-map-point * @short_description: A geographic location (latitude, longitude) * @stability: Stable * @include: osm-gps-map.h * * #OsmGpsMapPoint describes a geographic location (latitude, longitude). * Helper functions exist to create such a point from either radian co-ordinates * (osm_gps_map_point_new_radians()) or degrees (osm_gps_map_new_degrees()). **/ #include "converter.h" #include "osm-gps-map-point.h" GType osm_gps_map_point_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static (g_intern_static_string ("OsmGpsMapPoint"), (GBoxedCopyFunc)osm_gps_map_point_copy, (GBoxedFreeFunc)osm_gps_map_point_free); return our_type; } OsmGpsMapPoint * osm_gps_map_point_new_degrees(float lat, float lon) { OsmGpsMapPoint *p = g_new0(OsmGpsMapPoint, 1); p->rlat = deg2rad(lat); p->rlon = deg2rad(lon); return p; } OsmGpsMapPoint * osm_gps_map_point_new_radians(float rlat, float rlon) { OsmGpsMapPoint *p = g_new0(OsmGpsMapPoint, 1); p->rlat = rlat; p->rlon = rlon; return p; } /** * osm_gps_map_point_get_degrees: * @point: The point ( latitude and longitude in radian ) * @lat: (out): latitude in degrees * @lon: (out): longitude in degrees * * Returns the lagitude and longitude in degrees. * of the current window, i.e the top left and bottom right corners. **/ void osm_gps_map_point_get_degrees(OsmGpsMapPoint *point, float *lat, float *lon) { *lat = rad2deg(point->rlat); *lon = rad2deg(point->rlon); } void osm_gps_map_point_get_radians(OsmGpsMapPoint *point, float *rlat, float *rlon) { *rlat = point->rlat; *rlon = point->rlon; } void osm_gps_map_point_set_degrees(OsmGpsMapPoint *point, float lat, float lon) { point->rlat = deg2rad(lat); point->rlon = deg2rad(lon); } void osm_gps_map_point_set_radians(OsmGpsMapPoint *point, float rlat, float rlon) { point->rlat = rlat; point->rlon = rlon; } /** * osm_gps_map_point_copy: * * Since: 0.7.2 */ OsmGpsMapPoint * osm_gps_map_point_copy (const OsmGpsMapPoint *point) { OsmGpsMapPoint *result = g_new (OsmGpsMapPoint, 1); *result = *point; return result; } /** * osm_gps_map_point_free: * * Since: 0.7.2 */ void osm_gps_map_point_free (OsmGpsMapPoint *point) { g_free(point); } osm-gps-map-1.1.0/src/osm-gps-map-point.h000066400000000000000000000036541262345173300201160ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_POINT_H #define _OSM_GPS_MAP_POINT_H #include #include G_BEGIN_DECLS #define OSM_TYPE_GPS_MAP_POINT osm_gps_map_point_get_type() typedef struct _OsmGpsMapPoint OsmGpsMapPoint; struct _OsmGpsMapPoint { /* radians */ float rlat; float rlon; }; GType osm_gps_map_point_get_type (void) G_GNUC_CONST; OsmGpsMapPoint * osm_gps_map_point_new_degrees (float lat, float lon); OsmGpsMapPoint * osm_gps_map_point_new_radians (float rlat, float rlon); void osm_gps_map_point_get_degrees (OsmGpsMapPoint *point, float *lat, float *lon); void osm_gps_map_point_get_radians (OsmGpsMapPoint *point, float *rlat, float *rlon); void osm_gps_map_point_set_degrees (OsmGpsMapPoint *point, float lat, float lon); void osm_gps_map_point_set_radians (OsmGpsMapPoint *point, float rlat, float rlon); void osm_gps_map_point_free (OsmGpsMapPoint *point); OsmGpsMapPoint * osm_gps_map_point_copy (const OsmGpsMapPoint *point); G_END_DECLS #endif /* _OSM_GPS_MAP_POINT_H */ osm-gps-map-1.1.0/src/osm-gps-map-polygon.c000066400000000000000000000140761262345173300204470ustar00rootroot00000000000000/* * Copyright (C) 2013 Samuel Cowen * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include #include "converter.h" #include "osm-gps-map-polygon.h" G_DEFINE_TYPE (OsmGpsMapPolygon, osm_gps_map_polygon, G_TYPE_OBJECT) enum { PROP_0, PROP_VISIBLE, PROP_TRACK, PROP_SHADED, PROP_EDITABLE }; struct _OsmGpsMapPolygonPrivate { OsmGpsMapTrack* track; gboolean visible; gboolean editable; gboolean shaded; }; #define DEFAULT_R (60000) #define DEFAULT_G (0) #define DEFAULT_B (0) #define DEFAULT_A (0.6) static void osm_gps_map_polygon_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { OsmGpsMapPolygonPrivate *priv = OSM_GPS_MAP_POLYGON(object)->priv; switch (property_id) { case PROP_VISIBLE: g_value_set_boolean(value, priv->visible); break; case PROP_TRACK: g_value_set_pointer(value, priv->track); break; case PROP_SHADED: g_value_set_boolean(value, priv->shaded); break; case PROP_EDITABLE: g_value_set_boolean(value, priv->editable); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_polygon_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { OsmGpsMapPolygonPrivate *priv = OSM_GPS_MAP_POLYGON(object)->priv; switch (property_id) { case PROP_VISIBLE: priv->visible = g_value_get_boolean (value); break; case PROP_TRACK: priv->track = g_value_get_pointer (value); break; case PROP_SHADED: priv->shaded = g_value_get_boolean(value); break; case PROP_EDITABLE: priv->editable = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_polygon_dispose (GObject *object) { g_return_if_fail (OSM_IS_GPS_MAP_POLYGON (object)); OsmGpsMapPolygon* poly = OSM_GPS_MAP_POLYGON(object); g_object_unref(poly->priv->track); G_OBJECT_CLASS (osm_gps_map_polygon_parent_class)->dispose (object); } static void osm_gps_map_polygon_finalize (GObject *object) { G_OBJECT_CLASS (osm_gps_map_polygon_parent_class)->finalize (object); } static void osm_gps_map_polygon_class_init (OsmGpsMapPolygonClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (OsmGpsMapPolygonPrivate)); object_class->get_property = osm_gps_map_polygon_get_property; object_class->set_property = osm_gps_map_polygon_set_property; object_class->dispose = osm_gps_map_polygon_dispose; object_class->finalize = osm_gps_map_polygon_finalize; g_object_class_install_property (object_class, PROP_VISIBLE, g_param_spec_boolean ("visible", "visible", "should this poly be visible", TRUE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_TRACK, g_param_spec_pointer ("track", "track", "list of points for the polygon", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_EDITABLE, g_param_spec_boolean ("editable", "editable", "should this polygon be editable", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_SHADED, g_param_spec_boolean ("shaded", "shaded", "should this polygon be shaded", TRUE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); } static void osm_gps_map_polygon_init (OsmGpsMapPolygon *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE((self), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonPrivate); self->priv->track = osm_gps_map_track_new(); } OsmGpsMapTrack* osm_gps_map_polygon_get_track(OsmGpsMapPolygon* poly) { return poly->priv->track; } OsmGpsMapPolygon * osm_gps_map_polygon_new (void) { return g_object_new (OSM_TYPE_GPS_MAP_POLYGON, "track", osm_gps_map_track_new(), NULL); } #ifdef __cplusplus } #endif osm-gps-map-1.1.0/src/osm-gps-map-polygon.h000066400000000000000000000041551262345173300204510ustar00rootroot00000000000000/* * Copyright (C) 2013 Samuel Cowen * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_POLYGON_H #define _OSM_GPS_MAP_POLYGON_H #include #include #include G_BEGIN_DECLS #include "osm-gps-map-track.h" #define OSM_TYPE_GPS_MAP_POLYGON osm_gps_map_polygon_get_type() #define OSM_GPS_MAP_POLYGON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygon)) #define OSM_GPS_MAP_POLYGON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonClass)) #define OSM_IS_GPS_MAP_POLYGON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_POLYGON)) #define OSM_IS_GPS_MAP_POLYGON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_POLYGON)) #define OSM_GPS_MAP_POLYGON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_POLYGON, OsmGpsMapPolygonClass)) typedef struct _OsmGpsMapPolygon OsmGpsMapPolygon; typedef struct _OsmGpsMapPolygonClass OsmGpsMapPolygonClass; typedef struct _OsmGpsMapPolygonPrivate OsmGpsMapPolygonPrivate; struct _OsmGpsMapPolygon { GObject parent; OsmGpsMapPolygonPrivate *priv; }; struct _OsmGpsMapPolygonClass { GObjectClass parent_class; }; GType osm_gps_map_polygon_get_type (void) G_GNUC_CONST; OsmGpsMapPolygon* osm_gps_map_polygon_new (void); OsmGpsMapTrack* osm_gps_map_polygon_get_track(OsmGpsMapPolygon* poly); G_END_DECLS #endif /* _OSM_GPS_MAP_POLYGON_H */ osm-gps-map-1.1.0/src/osm-gps-map-source.c000066400000000000000000000154031262345173300202530ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #include "private.h" #include "osm-gps-map-source.h" const char* osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source) { switch(source) { case OSM_GPS_MAP_SOURCE_NULL: return "None"; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: return "OpenStreetMap I"; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: return "OpenStreetMap II"; case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: return "OpenAerialMap"; case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP: return "OpenCycleMap"; case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT: return "Public Transport"; case OSM_GPS_MAP_SOURCE_OSMC_TRAILS: return "OSMC Trails"; case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: return "Maps-For-Free"; case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: return "Google Maps"; case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: return "Google Satellite"; case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: return "Google Hybrid"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: return "Virtual Earth"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: return "Virtual Earth Satellite"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: return "Virtual Earth Hybrid"; case OSM_GPS_MAP_SOURCE_LAST: default: return NULL; } return NULL; } //http://www.internettablettalk.com/forums/showthread.php?t=5209 //https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c?root=maemo-mapper&view=markup //http://www.ponies.me.uk/maps/GoogleTileUtils.java //http://www.mgmaps.com/cache/MapTileCacher.perl const char* osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source) { switch(source) { case OSM_GPS_MAP_SOURCE_NULL: return "none://"; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: return OSM_REPO_URI; case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: /* OpenAerialMap is down, offline till furthur notice http://openaerialmap.org/pipermail/talk_openaerialmap.org/2008-December/000055.html */ return NULL; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: /* The Tile@Home serverhas been shut down. */ // return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png"; return NULL; case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP: // return "http://c.andy.sandbox.cloudmade.com/tiles/cycle/#Z/#X/#Y.png"; return "http://b.tile.opencyclemap.org/cycle/#Z/#X/#Y.png"; case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT: return "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z/#X/#Y.png"; case OSM_GPS_MAP_SOURCE_OSMC_TRAILS: // Appears to be shut down return NULL; case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg"; case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: return "http://mt#R.google.com/vt/lyrs=m&hl=en&x=#X&s=&y=#Y&z=#Z"; case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: return "http://mt#R.google.com/vt/lyrs=y&hl=en&x=#X&s=&y=#Y&z=#Z"; case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: return "http://mt#R.google.com/vt/lyrs=s&hl=en&x=#X&s=&y=#Y&z=#Z"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: return "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50"; case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: return "http://a#R.ortho.tiles.virtualearth.net/tiles/h#W.jpeg?g=50"; case OSM_GPS_MAP_SOURCE_LAST: default: return NULL; } return NULL; } const char * osm_gps_map_source_get_image_format(OsmGpsMapSource_t source) { switch(source) { case OSM_GPS_MAP_SOURCE_NULL: case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP: case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT: case OSM_GPS_MAP_SOURCE_OSMC_TRAILS: return "png"; case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: return "jpg"; case OSM_GPS_MAP_SOURCE_LAST: default: return "bin"; } return "bin"; } int osm_gps_map_source_get_min_zoom(OsmGpsMapSource_t source) { return 1; } int osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source) { switch(source) { case OSM_GPS_MAP_SOURCE_NULL: return 18; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP: case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT: return OSM_MAX_ZOOM; case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: return 17; case OSM_GPS_MAP_SOURCE_OSMC_TRAILS: return 15; case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: return 11; case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: return 18; case OSM_GPS_MAP_SOURCE_LAST: default: return 17; } return 17; } gboolean osm_gps_map_source_is_valid(OsmGpsMapSource_t source) { return osm_gps_map_source_get_repo_uri(source) != NULL; } osm-gps-map-1.1.0/src/osm-gps-map-source.h000066400000000000000000000040361262345173300202600ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_SOURCE_H_ #define _OSM_GPS_MAP_SOURCE_H_ #include G_BEGIN_DECLS typedef enum { OSM_GPS_MAP_SOURCE_NULL, OSM_GPS_MAP_SOURCE_OPENSTREETMAP, OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER, OSM_GPS_MAP_SOURCE_OPENAERIALMAP, OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE, OSM_GPS_MAP_SOURCE_OPENCYCLEMAP, OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT, OSM_GPS_MAP_SOURCE_GOOGLE_STREET, OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE, OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID, OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET, OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE, OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID, OSM_GPS_MAP_SOURCE_OSMC_TRAILS, OSM_GPS_MAP_SOURCE_LAST } OsmGpsMapSource_t; const char* osm_gps_map_source_get_friendly_name (OsmGpsMapSource_t source); const char* osm_gps_map_source_get_repo_uri (OsmGpsMapSource_t source); const char* osm_gps_map_source_get_image_format (OsmGpsMapSource_t source); int osm_gps_map_source_get_min_zoom (OsmGpsMapSource_t source); int osm_gps_map_source_get_max_zoom (OsmGpsMapSource_t source); gboolean osm_gps_map_source_is_valid (OsmGpsMapSource_t source); G_END_DECLS #endif /* _OSM_GPS_MAP_SOURCE_H_ */ osm-gps-map-1.1.0/src/osm-gps-map-track.c000066400000000000000000000317031262345173300200600ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ /** * SECTION:osm-gps-map-track * @short_description: A list of GPS points * @stability: Stable * @include: osm-gps-map.h * * #OsmGpsMapTrack stores multiple #OsmGpsMapPoint objects, i.e. a track, and * describes how such a track should be drawn on the map * (see osm_gps_map_track_add()), including its colour, width, etc. **/ #include #include #include "converter.h" #include "osm-gps-map-track.h" G_DEFINE_TYPE (OsmGpsMapTrack, osm_gps_map_track, G_TYPE_OBJECT) enum { PROP_0, PROP_VISIBLE, PROP_TRACK, PROP_LINE_WIDTH, PROP_ALPHA, PROP_COLOR, PROP_EDITABLE }; enum { POINT_ADDED, POINT_CHANGED, POINT_INSERTED, POINT_REMOVED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0,}; struct _OsmGpsMapTrackPrivate { GSList *track; gboolean visible; gfloat linewidth; gfloat alpha; GdkRGBA color; gboolean editable; }; #define DEFAULT_R (0.6) #define DEFAULT_G (0) #define DEFAULT_B (0) #define DEFAULT_A (0.6) static void osm_gps_map_track_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv; switch (property_id) { case PROP_VISIBLE: g_value_set_boolean(value, priv->visible); break; case PROP_TRACK: g_value_set_pointer(value, priv->track); break; case PROP_LINE_WIDTH: g_value_set_float(value, priv->linewidth); break; case PROP_ALPHA: g_value_set_float(value, priv->alpha); break; case PROP_COLOR: g_value_set_boxed(value, &priv->color); break; case PROP_EDITABLE: g_value_set_boolean(value, priv->editable); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_track_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv; switch (property_id) { case PROP_VISIBLE: priv->visible = g_value_get_boolean (value); break; case PROP_TRACK: priv->track = g_value_get_pointer (value); break; case PROP_LINE_WIDTH: priv->linewidth = g_value_get_float (value); break; case PROP_ALPHA: priv->alpha = g_value_get_float (value); break; case PROP_COLOR: { GdkRGBA *c = g_value_get_boxed (value); priv->color.red = c->red; priv->color.green = c->green; priv->color.blue = c->blue; printf("\n%f %f %f\n", c->red, c->green, c->blue); fflush(stdout); } break; case PROP_EDITABLE: priv->editable = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void osm_gps_map_track_dispose (GObject *object) { g_return_if_fail (OSM_IS_GPS_MAP_TRACK (object)); OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv; if (priv->track) { g_slist_foreach(priv->track, (GFunc) g_free, NULL); g_slist_free(priv->track); priv->track = NULL; } G_OBJECT_CLASS (osm_gps_map_track_parent_class)->dispose (object); } static void osm_gps_map_track_finalize (GObject *object) { G_OBJECT_CLASS (osm_gps_map_track_parent_class)->finalize (object); } static void osm_gps_map_track_class_init (OsmGpsMapTrackClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (OsmGpsMapTrackPrivate)); object_class->get_property = osm_gps_map_track_get_property; object_class->set_property = osm_gps_map_track_set_property; object_class->dispose = osm_gps_map_track_dispose; object_class->finalize = osm_gps_map_track_finalize; g_object_class_install_property (object_class, PROP_VISIBLE, g_param_spec_boolean ("visible", "visible", "should this track be visible", TRUE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_TRACK, g_param_spec_pointer ("track", "track", "list of points for the track", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_LINE_WIDTH, g_param_spec_float ("line-width", "line-width", "width of the lines drawn for the track", 0.0, /* minimum property value */ 100.0, /* maximum property value */ 4.0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_ALPHA, g_param_spec_float ("alpha", "alpha", "alpha transparency of the track", 0.0, /* minimum property value */ 1.0, /* maximum property value */ DEFAULT_A, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_COLOR, g_param_spec_boxed ("color", "color", "color of the track", GDK_TYPE_RGBA, G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_EDITABLE, g_param_spec_boolean ("editable", "editable", "should this track be editable", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); /** * OsmGpsMapTrack::point-added: * @self: A #OsmGpsMapTrack * * The point-added signal. */ signals [POINT_ADDED] = g_signal_new ("point-added", OSM_TYPE_GPS_MAP_TRACK, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, OSM_TYPE_GPS_MAP_POINT); signals [POINT_CHANGED] = g_signal_new ("point-changed", OSM_TYPE_GPS_MAP_TRACK, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 1, G_TYPE_INT); signals [POINT_INSERTED] = g_signal_new ("point-inserted", OSM_TYPE_GPS_MAP_TRACK, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); signals [POINT_REMOVED] = g_signal_new ("point-removed", OSM_TYPE_GPS_MAP_TRACK, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); } static void osm_gps_map_track_init (OsmGpsMapTrack *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE((self), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackPrivate); self->priv->color.red = DEFAULT_R; self->priv->color.green = DEFAULT_G; self->priv->color.blue = DEFAULT_B; } void osm_gps_map_track_add_point (OsmGpsMapTrack *track, const OsmGpsMapPoint *point) { g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track)); OsmGpsMapTrackPrivate *priv = track->priv; OsmGpsMapPoint *p = g_boxed_copy (OSM_TYPE_GPS_MAP_POINT, point); priv->track = g_slist_append (priv->track, p); g_signal_emit (track, signals[POINT_ADDED], 0, p); } void osm_gps_map_track_remove_point(OsmGpsMapTrack* track, int pos) { OsmGpsMapTrackPrivate *priv = track->priv; gpointer pgl = g_slist_nth_data(priv->track, pos); priv->track = g_slist_remove(priv->track, pgl); g_signal_emit(track, signals[POINT_REMOVED], 0, pos); } int osm_gps_map_track_n_points(OsmGpsMapTrack* track) { return g_slist_length(track->priv->track); } void osm_gps_map_track_insert_point(OsmGpsMapTrack* track, OsmGpsMapPoint* np, int pos) { OsmGpsMapTrackPrivate* priv = track->priv; priv->track = g_slist_insert(priv->track, np, pos); g_signal_emit(track, signals[POINT_INSERTED], 0, pos); } OsmGpsMapPoint* osm_gps_map_track_get_point(OsmGpsMapTrack* track, int pos) { OsmGpsMapTrackPrivate* priv = track->priv; return g_slist_nth_data(priv->track, pos); } GSList * osm_gps_map_track_get_points (OsmGpsMapTrack *track) { g_return_val_if_fail (OSM_IS_GPS_MAP_TRACK (track), NULL); return track->priv->track; } void osm_gps_map_track_set_color (OsmGpsMapTrack *track, GdkRGBA *color) { g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track)); track->priv->color.red = color->red; track->priv->color.green = color->green; track->priv->color.blue = color->blue; } void osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkRGBA *color) { g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track)); color->red = track->priv->color.red; color->green = track->priv->color.green; color->blue = track->priv->color.blue; } double osm_gps_map_track_get_length(OsmGpsMapTrack* track) { GSList* points = track->priv->track; double ret = 0; OsmGpsMapPoint* point_a = NULL; OsmGpsMapPoint* point_b = NULL; while(points) { point_a = point_b; point_b = points->data; if(point_a) { ret += acos(sin(point_a->rlat)*sin(point_b->rlat) + cos(point_a->rlat)*cos(point_b->rlat)*cos(point_b->rlon-point_a->rlon)) * 6371109; //the mean raduis of earth } points = points->next; } return ret; } OsmGpsMapTrack * osm_gps_map_track_new (void) { return g_object_new (OSM_TYPE_GPS_MAP_TRACK, NULL); } osm-gps-map-1.1.0/src/osm-gps-map-track.h000066400000000000000000000070211262345173300200610ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_TRACK_H #define _OSM_GPS_MAP_TRACK_H #include #include #include #include "osm-gps-map-point.h" G_BEGIN_DECLS #define OSM_TYPE_GPS_MAP_TRACK osm_gps_map_track_get_type() #define OSM_GPS_MAP_TRACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrack)) #define OSM_GPS_MAP_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackClass)) #define OSM_IS_GPS_MAP_TRACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_TRACK)) #define OSM_IS_GPS_MAP_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_TRACK)) #define OSM_GPS_MAP_TRACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackClass)) typedef struct _OsmGpsMapTrack OsmGpsMapTrack; typedef struct _OsmGpsMapTrackClass OsmGpsMapTrackClass; typedef struct _OsmGpsMapTrackPrivate OsmGpsMapTrackPrivate; struct _OsmGpsMapTrack { GObject parent; OsmGpsMapTrackPrivate *priv; }; struct _OsmGpsMapTrackClass { GObjectClass parent_class; }; /** * osm_gps_map_track_get_type: * * Return value: (element-type GType): The type of the track * * Since: 0.7.0 **/ GType osm_gps_map_track_get_type (void) G_GNUC_CONST; OsmGpsMapTrack * osm_gps_map_track_new (void); /** * osm_gps_map_track_add_point: * track (in,out): a #OsmGpsMapTrack * @point (in): point to add * * Since: 0.7.0 **/ void osm_gps_map_track_add_point (OsmGpsMapTrack *track, const OsmGpsMapPoint *point); /** * osm_gps_map_track_get_points: * @track (in): a #OsmGpsMapTrack * * Returns: (element-type OsmGpsMapPoint) (transfer full): list of #OsmGpsMapPoint * * Since: 0.7.0 **/ GSList * osm_gps_map_track_get_points (OsmGpsMapTrack *track); void osm_gps_map_track_set_color (OsmGpsMapTrack *track, GdkRGBA *color); void osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkRGBA *color); /** * osm_gps_map_track_remove_point: * @track (in): a #OsmGpsMapTrack * @pos: Position of the point to remove * **/ void osm_gps_map_track_remove_point(OsmGpsMapTrack* track, int pos); /** * **/ int osm_gps_map_track_n_points(OsmGpsMapTrack* track); void osm_gps_map_track_insert_point(OsmGpsMapTrack* track, OsmGpsMapPoint* np, int pos); OsmGpsMapPoint* osm_gps_map_track_get_point(OsmGpsMapTrack* track, int pos); /** * osm_gps_map_track_get_length: * @track (in): a #OsmGpsMapTrack * * Returns: the length of the track in meters. **/ double osm_gps_map_track_get_length(OsmGpsMapTrack* track); G_END_DECLS #endif /* _OSM_GPS_MAP_TRACK_H */ osm-gps-map-1.1.0/src/osm-gps-map-widget.c000066400000000000000000003533101262345173300202400ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * Copyright (C) Marcus Bauer 2008 * Copyright (C) John Stowers 2009 * Copyright (C) Till Harbaum 2009 * * Contributions by * Everaldo Canuto 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ /** * SECTION:osm-gps-map * @short_description: The map display widget * @stability: Stable * @include: osm-gps-map.h * * #OsmGpsMap is a widget for displaying a map, optionally overlaid with a * track(s) of GPS co-ordinates, images, points of interest or on screen display * controls. #OsmGpsMap downloads (and caches for offline use) map data from a * number of websites, including * OpenStreetMap * * * Showing a map * * int main (int argc, char **argv) * { * g_thread_init(NULL); * gtk_init (&argc, &argv); * * GtkWidget *map = osm_gps_map_new (); * GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL); * gtk_container_add (GTK_CONTAINER(w), map); * gtk_widget_show_all (w); * * gtk_main (); * return 0; * } * * * * #OsmGpsMap allows great flexibility in customizing how the map tiles are * cached, see #OsmGpsMap:tile-cache-base and #OsmGpsMap:tile-cache for more * information. * * A number of different map sources are supported, see #OsmGpsMapSource_t. The * default source, %OSM_GPS_MAP_SOURCE_OPENSTREETMAP always works. Other sources, * particular those from proprietary providers may work occasionally, and then * cease to work. To check if a source is supported for the given version of * this library, call osm_gps_map_source_is_valid(). * * * Map with custom source and cache dir * * int main (int argc, char **argv) * { * g_thread_init(NULL); * gtk_init (&argc, &argv); * OsmGpsMapSource_t source = OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE; * * if ( !osm_gps_map_source_is_valid(source) ) * return 1; * * GtkWidget *map = g_object_new (OSM_TYPE_GPS_MAP, * "map-source", source, * "tile-cache", "/tmp/", * NULL); * GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL); * gtk_container_add (GTK_CONTAINER(w), map); * gtk_widget_show_all (w); * * gtk_main (); * return 0; * } * * * * Finally, if you wish to use a custom map source not supported by #OsmGpsMap, * such as a custom map created with * CloudMade * then you can also pass a specially formatted string to #OsmGpsMap:repo-uri. * * * Map using custom CloudMade map and on screen display * * int main (int argc, char **argv) * { * g_thread_init(NULL); * gtk_init (&argc, &argv); * const gchar *cloudmate = "http://a.tile.cloudmade.com/YOUR_API_KEY/1/256/#Z/#X/#Y.png"; * * GtkWidget *map = g_object_new (OSM_TYPE_GPS_MAP, * "repo-uri", cloudmate, * NULL); * OsmGpsMapOsd *osd = osm_gps_map_osd_new (); * GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL); * osm_gps_map_layer_add (OSM_GPS_MAP(map), OSM_GPS_MAP_LAYER(osd)); * gtk_container_add (GTK_CONTAINER(w), map); * gtk_widget_show_all (w); * * gtk_main (); * return 0; * } * * **/ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "converter.h" #include "private.h" #include "osm-gps-map-source.h" #include "osm-gps-map-widget.h" #include "osm-gps-map-compat.h" #define ENABLE_DEBUG (0) #define EXTRA_BORDER (0) #define OSM_GPS_MAP_SCROLL_STEP (10) #define USER_AGENT "libosmgpsmap/1.0" #define DOWNLOAD_RETRIES 3 #define MAX_DOWNLOAD_TILES 10000 #define DOT_RADIUS 4.0 struct _OsmGpsMapPrivate { GHashTable *tile_queue; GHashTable *missing_tiles; GHashTable *tile_cache; int map_zoom; int max_zoom; int min_zoom; int tile_zoom_offset; int map_x; int map_y; /* Controls auto centering the map when a new GPS position arrives */ gfloat map_auto_center_threshold; /* 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 *tile_dir; char *tile_base_dir; char *cache_dir; //contains flags indicating the various special characters //the uri string contains, that will be replaced when calculating //the uri to download. OsmGpsMapSource_t map_source; char *repo_uri; char *image_format; int uri_format; //gps tracking state GSList *trip_history; float gps_heading; OsmGpsMapPoint *gps; OsmGpsMapTrack *gps_track; gboolean gps_track_used; //additional images or tracks added to the map GSList *tracks; GSList *images; GSList *polygons; //Used for storing the joined tiles cairo_surface_t *pixmap; //The tile painted when one cannot be found GdkPixbuf *null_tile; //A list of OsmGpsMapLayer* layers, such as the OSD GSList *layers; //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; int drag_limit; guint drag_expose_source; /* Properties for dragging a point with right mouse button. */ OsmGpsMapPoint* drag_point; OsmGpsMapTrack* drag_track; /* for customizing the redering of the gps track */ int ui_gps_point_inner_radius; int ui_gps_point_outer_radius; /* For storing keybindings */ guint keybindings[OSM_GPS_MAP_KEY_MAX]; /* flags controlling which features are enabled */ guint keybindings_enabled : 1; guint map_auto_download_enabled : 1; guint map_auto_center_enabled : 1; guint trip_history_record_enabled : 1; guint trip_history_show_enabled : 1; guint gps_point_enabled : 1; /* state flags */ guint is_disposed : 1; guint is_constructed : 1; guint is_dragging : 1; guint is_button_down : 1; guint is_fullscreen : 1; guint is_google : 1; guint is_dragging_point : 1; }; 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; 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; int ttl; } OsmTileDownload; 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_BASE_DIR, PROP_TILE_ZOOM_OFFSET, 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, PROP_MAP_SOURCE, PROP_IMAGE_FORMAT, PROP_DRAG_LIMIT, PROP_AUTO_CENTER_THRESHOLD, PROP_SHOW_GPS_POINT }; 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 gchar *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int 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 GdkPixbuf* osm_gps_map_render_tile_upscaled (OsmGpsMap *map, GdkPixbuf *tile, int tile_zoom, int zoom, int x, int y); 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(OsmGpsMapPrivate *priv) { priv->uri_format = 0; priv->is_google = FALSE; 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->is_google = TRUE; g_debug("URI Format: 0x%X (google: %X)", priv->uri_format, priv->is_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 = NULL; 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); break; case URI_HAS_Y: s = g_strdup_printf("%d", y); url = replace_string(url, URI_MARKER_Y, s); break; case URI_HAS_Z: s = g_strdup_printf("%d", zoom); url = replace_string(url, URI_MARKER_Z, s); break; case URI_HAS_S: s = g_strdup_printf("%d", priv->max_zoom-zoom); url = replace_string(url, URI_MARKER_S, 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); 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); 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); } static float osm_gps_map_get_scale_at_point(int zoom, float rlat, float rlon) { /* world at zoom 1 == 512 pixels */ return cos(rlat) * M_PI * OSM_EQ_RADIUS / (1<<(7+zoom)); } static GSList * gslist_remove_one_gobject(GSList **list, GObject *gobj) { GSList *data = g_slist_find(*list, gobj); if (data) { g_object_unref(gobj); *list = g_slist_delete_link(*list, data); } return data; } static void gslist_of_gobjects_free(GSList **list) { if (list) { g_slist_foreach(*list, (GFunc) g_object_unref, NULL); g_slist_free(*list); *list = NULL; } } static void gslist_of_data_free (GSList **list) { if (list) { g_slist_foreach(*list, (GFunc) g_free, NULL); g_slist_free(*list); *list = NULL; } } static void draw_white_rectangle(cairo_t *cr, double x, double y, double width, double height) { cairo_save (cr); cairo_set_source_rgb (cr, 1, 1, 1); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); cairo_restore (cr); } static void osm_gps_map_print_images (OsmGpsMap *map, cairo_t *cr) { GSList *list; 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) { GdkRectangle loc; OsmGpsMapImage *im = OSM_GPS_MAP_IMAGE(list->data); const OsmGpsMapPoint *pt = osm_gps_map_image_get_point(im); /* pixel_x,y, offsets */ loc.x = lon2pixel(priv->map_zoom, pt->rlon) - map_x0; loc.y = lat2pixel(priv->map_zoom, pt->rlat) - map_y0; osm_gps_map_image_draw ( im, cr, &loc); max_x = MAX(loc.x + loc.width, max_x); min_x = MIN(loc.x - loc.width, min_x); max_y = MAX(loc.y + loc.height, max_y); min_y = MIN(loc.y - loc.height, 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, cairo_t *cr) { OsmGpsMapPrivate *priv = map->priv; int map_x0, map_y0; int x, y; int r, r2, mr; r = priv->ui_gps_point_inner_radius; r2 = priv->ui_gps_point_outer_radius; mr = MAX(3*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; /* 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) { cairo_pattern_t *pat; /* draw direction arrow */ if(!isnan(priv->gps_heading)) { cairo_move_to (cr, x-r*cos(priv->gps_heading), y-r*sin(priv->gps_heading)); cairo_line_to (cr, x+3*r*sin(priv->gps_heading), y-3*r*cos(priv->gps_heading)); cairo_line_to (cr, x+r*cos(priv->gps_heading), y+r*sin(priv->gps_heading)); cairo_close_path (cr); cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.5); cairo_fill_preserve (cr); cairo_set_line_width (cr, 1.0); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); cairo_stroke(cr); } 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); } gtk_widget_queue_draw_area (GTK_WIDGET(map), x-mr, y-mr, mr*2, mr*2); } static void osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, cairo_t *cr, int offset_x, int offset_y, int tile_zoom, int target_x, int target_y) { OsmGpsMapPrivate *priv = map->priv; int target_zoom = priv->map_zoom; if (tile_zoom == target_zoom) { g_debug("Blit @ %d,%d", offset_x,offset_y); /* draw pixbuf */ gdk_cairo_set_source_pixbuf (cr, pixbuf, offset_x, offset_y); cairo_paint (cr); } else { /* get an upscaled version of the pixbuf */ GdkPixbuf *pixmap_scaled = osm_gps_map_render_tile_upscaled ( map, pixbuf, tile_zoom, target_zoom, target_x, target_y); osm_gps_map_blit_tile (map, pixmap_scaled, cr, offset_x, offset_y, target_zoom, target_x, target_y); g_object_unref (pixmap_scaled); } } #define MSG_RESPONSE_BODY(a) ((a)->response_body->data) #define MSG_RESPONSE_LEN(a) ((a)->response_body->length) #define MSG_RESPONSE_LEN_FORMAT "%"G_GOFFSET_FORMAT static void osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data) { FILE *file; OsmTileDownload *dl = (OsmTileDownload *)user_data; OsmGpsMap *map = OSM_GPS_MAP(dl->map); OsmGpsMapPrivate *priv = map->priv; gboolean file_saved = FALSE; if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { /* save tile into cachedir if one has been specified */ if (priv->cache_dir) { if (g_mkdir_with_parents(dl->folder,0700) == 0) { file = g_fopen(dl->filename, "wb"); if (file != NULL) { fwrite (MSG_RESPONSE_BODY(msg), 1, MSG_RESPONSE_LEN(msg), file); file_saved = TRUE; g_debug("Wrote "MSG_RESPONSE_LEN_FORMAT" bytes to %s", MSG_RESPONSE_LEN(msg), dl->filename); fclose (file); } } else { g_warning("Error creating tile download directory: %s", dl->folder); } } if (dl->redraw) { GdkPixbuf *pixbuf = NULL; /* if the file was actually stored on disk, we can simply */ /* load and decode it from that file */ if (priv->cache_dir) { if (file_saved) { pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL); } } else { GdkPixbufLoader *loader; char *extension = strrchr (dl->filename, '.'); /* parse file directly from memory */ if (extension) { loader = gdk_pixbuf_loader_new_with_type (extension+1, NULL); if (!gdk_pixbuf_loader_write (loader, (unsigned char*)MSG_RESPONSE_BODY(msg), MSG_RESPONSE_LEN(msg), NULL)) { g_warning("Error: Decoding of image failed"); } gdk_pixbuf_loader_close(loader, NULL); pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); /* give up loader but keep the pixbuf */ g_object_ref(pixbuf); g_object_unref(loader); } else { g_warning("Error: Unable to determine image file format"); } } /* 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); } g_hash_table_remove(priv->tile_queue, dl->uri); g_object_notify(G_OBJECT(map), "tiles-queued"); g_free(dl->folder); g_free(dl->filename); g_free(dl); } else { if ((msg->status_code == SOUP_STATUS_NOT_FOUND) || (msg->status_code == SOUP_STATUS_FORBIDDEN)) { g_hash_table_insert(priv->missing_tiles, dl->uri, NULL); g_hash_table_remove(priv->tile_queue, dl->uri); g_object_notify(G_OBJECT(map), "tiles-queued"); } else if (msg->status_code == SOUP_STATUS_CANCELLED) { /* called as application exit or after osm_gps_map_download_cancel_all */ g_hash_table_remove(priv->tile_queue, dl->uri); g_object_notify(G_OBJECT(map), "tiles-queued"); } else { g_warning("Error downloading tile: %d - %s", msg->status_code, msg->reason_phrase); dl->ttl--; if (dl->ttl) { soup_session_requeue_message(session, msg); return; } g_hash_table_remove(priv->tile_queue, dl->uri); g_object_notify(G_OBJECT(map), "tiles-queued"); } } } static void osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw) { SoupMessage *msg; OsmGpsMapPrivate *priv = map->priv; OsmTileDownload *dl = g_new0(OsmTileDownload,1); // set retries dl->ttl = DOWNLOAD_RETRIES; //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%c%d%c%d%c", priv->cache_dir, G_DIR_SEPARATOR, zoom, G_DIR_SEPARATOR, x, G_DIR_SEPARATOR); dl->filename = g_strdup_printf("%s%c%d%c%d%c%d.%s", priv->cache_dir, G_DIR_SEPARATOR, zoom, G_DIR_SEPARATOR, x, G_DIR_SEPARATOR, y, priv->image_format); 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->is_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); g_object_notify (G_OBJECT (map), "tiles-queued"); /* the soup session unrefs the message when the download finishes */ 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 = NULL; OsmCachedTile *tile; filename = g_strdup_printf("%s%c%d%c%d%c%d.%s", priv->cache_dir, G_DIR_SEPARATOR, zoom, G_DIR_SEPARATOR, x, G_DIR_SEPARATOR, y, priv->image_format); 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); } else { g_free (filename); } } /* 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; int zoom_big; 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); pixbuf = osm_gps_map_render_tile_upscaled (map, big, zoom_big, zoom, x, y); g_object_unref (big); return pixbuf; } static GdkPixbuf* osm_gps_map_render_tile_upscaled (OsmGpsMap *map, GdkPixbuf *big, int zoom_big, int zoom, int x, int y) { GdkPixbuf *pixbuf, *area; int area_size, area_x, area_y; int modulo; int zoom_diff; /* get a Pixbuf for the area to magnify */ zoom_diff = zoom - zoom_big; g_debug ("Upscaling by %d levels into tile %d,%d", zoom_diff, x, y); 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); 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, cairo_t *cr, int zoom, int x, int y, int offset_x, int offset_y) { OsmGpsMapPrivate *priv = map->priv; gchar *filename; GdkPixbuf *pixbuf; int zoom_offset = priv->tile_zoom_offset; int target_x, target_y; g_debug("Load virtual tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom); if (zoom > MIN_ZOOM) { zoom -= zoom_offset; x >>= zoom_offset; y >>= zoom_offset; } target_x = x; target_y = y; g_debug("Load actual tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom); if (priv->map_source == OSM_GPS_MAP_SOURCE_NULL) { osm_gps_map_blit_tile(map, priv->null_tile, cr, offset_x, offset_y, priv->map_zoom, target_x, target_y); return; } filename = g_strdup_printf("%s%c%d%c%d%c%d.%s", priv->cache_dir, G_DIR_SEPARATOR, zoom, G_DIR_SEPARATOR, x, G_DIR_SEPARATOR, y, priv->image_format); /* try to get file from internal cache first */ if(!(pixbuf = osm_gps_map_load_cached_tile(map, 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, cr, offset_x, offset_y, zoom, target_x, target_y); g_object_unref (pixbuf); } else { if (priv->map_auto_download_enabled) { 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) { osm_gps_map_blit_tile(map, pixbuf, cr, offset_x, offset_y, zoom, target_x, target_y); g_object_unref (pixbuf); } else { /* prevent some artifacts when drawing not yet loaded areas. */ g_warning ("Error getting missing tile"); /* FIXME: is this a warning? */ draw_white_rectangle (cr, offset_x, offset_y, TILESIZE, TILESIZE); } } g_free(filename); } static void osm_gps_map_fill_tiles_pixel (OsmGpsMap *map, cairo_t *cr) { OsmGpsMapPrivate *priv = map->priv; GtkAllocation allocation; int i,j, 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); gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); 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; tiles_nx = (allocation.width - offset_x) / TILESIZE + 1; tiles_ny = (allocation.height - offset_y) / TILESIZE + 1; tile_x0 = floor((float)priv->map_x / (float)TILESIZE); tile_y0 = floor((float)priv->map_y / (float)TILESIZE); 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)) { /* draw white in areas outside map (i.e. when zoomed right out) */ draw_white_rectangle (cr, offset_xn, offset_yn, TILESIZE, TILESIZE); } else { osm_gps_map_load_tile(map, cr, priv->map_zoom, i,j, offset_xn - EXTRA_BORDER,offset_yn - EXTRA_BORDER); } offset_yn += TILESIZE; } offset_xn += TILESIZE; offset_yn = offset_y + EXTRA_BORDER; } } static void osm_gps_map_print_track (OsmGpsMap *map, OsmGpsMapTrack *track, cairo_t *cr) { OsmGpsMapPrivate *priv = map->priv; GSList *pt,*points; int x,y; int min_x = 0,min_y = 0,max_x = 0,max_y = 0; gfloat lw, alpha; int map_x0, map_y0; GdkRGBA color; g_object_get (track, "track", &points, "line-width", &lw, "alpha", &alpha, NULL); osm_gps_map_track_get_color(track, &color); if (points == NULL) return; gboolean path_editable = FALSE; g_object_get(track, "editable", &path_editable, NULL); cairo_set_line_width (cr, lw); cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); map_x0 = priv->map_x - EXTRA_BORDER; map_y0 = priv->map_y - EXTRA_BORDER; int last_x = 0, last_y = 0; for(pt = points; pt != NULL; pt = pt->next) { OsmGpsMapPoint *tp = pt->data; x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0; y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0; /* first time through loop */ if (pt == points) cairo_move_to(cr, x, y); cairo_line_to(cr, x, y); cairo_stroke(cr); if(path_editable) { cairo_arc (cr, x, y, DOT_RADIUS, 0.0, 2 * M_PI); cairo_stroke(cr); if(pt != points) { cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75); cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI); cairo_stroke(cr); cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha); } } cairo_move_to(cr, x, y); max_x = MAX(x,max_x); min_x = MIN(x,min_x); max_y = MAX(y,max_y); min_y = MIN(y,min_y); last_x = x; last_y = y; } gtk_widget_queue_draw_area ( GTK_WIDGET(map), min_x - lw, min_y - lw, max_x + (lw * 2), max_y + (lw * 2)); cairo_stroke(cr); } /* Prints the gps trip history, and any other tracks */ static void osm_gps_map_print_tracks (OsmGpsMap *map, cairo_t *cr) { GSList *tmp; OsmGpsMapPrivate *priv = map->priv; if (priv->trip_history_show_enabled) { osm_gps_map_print_track (map, priv->gps_track, cr); } if (priv->tracks) { tmp = priv->tracks; while (tmp != NULL) { osm_gps_map_print_track (map, OSM_GPS_MAP_TRACK(tmp->data), cr); tmp = g_slist_next(tmp); } } } static void osm_gps_map_print_polygon (OsmGpsMap *map, OsmGpsMapPolygon *poly, cairo_t *cr) { OsmGpsMapPrivate *priv = map->priv; GSList *pt,*points; int x,y; int min_x = 0,min_y = 0,max_x = 0,max_y = 0; gfloat lw, alpha; int map_x0, map_y0; GdkRGBA color; OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly); if(!track) return; g_object_get (track, "track", &points, "line-width", &lw, "alpha", &alpha, NULL); osm_gps_map_track_get_color(track, &color); if (points == NULL) return; gboolean path_editable = FALSE; gboolean poly_shaded = FALSE; g_object_get(poly, "editable", &path_editable, NULL); g_object_get(poly, "shaded", &poly_shaded, NULL); cairo_set_line_width (cr, lw); cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); map_x0 = priv->map_x - EXTRA_BORDER; map_y0 = priv->map_y - EXTRA_BORDER; int first_x = 0, first_y = 0; for(pt = points; pt != NULL; pt = pt->next) { OsmGpsMapPoint *tp = pt->data; x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0; y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0; /* first time through loop */ if (pt == points) { cairo_move_to(cr, x, y); first_x = x; first_y = y; } cairo_line_to(cr, x, y); } //close off polygon cairo_line_to(cr, first_x, first_y); if(poly_shaded) cairo_fill(cr); else cairo_stroke(cr); if(path_editable) { int last_x = 0, last_y = 0; for(pt = points; pt != NULL; pt = pt->next) { OsmGpsMapPoint *tp = pt->data; x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0; y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0; cairo_arc (cr, x, y, DOT_RADIUS, 0.0, 2 * M_PI); cairo_stroke(cr); if(pt != points) { cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75); cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI); cairo_stroke(cr); cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha); } last_x = x; last_y = y; } x = first_x; y = first_y; cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha*0.75); cairo_arc(cr, (last_x + x)/2.0, (last_y+y)/2.0, DOT_RADIUS, 0.0, 2*M_PI); cairo_stroke(cr); cairo_set_source_rgba (cr, color.red, color.green, color.blue, alpha); } gtk_widget_queue_draw_area ( GTK_WIDGET(map), min_x - lw, min_y - lw, max_x + (lw * 2), max_y + (lw * 2)); } static void osm_gps_map_print_polygons (OsmGpsMap *map, cairo_t* cr) { GSList *tmp; OsmGpsMapPrivate *priv = map->priv; if (priv->polygons) { tmp = priv->polygons; while (tmp != NULL) { osm_gps_map_print_polygon (map, OSM_GPS_MAP_POLYGON(tmp->data), cr); tmp = g_slist_next(tmp); } } } static gboolean osm_gps_map_purge_cache_check(gpointer key, gpointer value, gpointer user) { return (((OsmCachedTile*)value)->redraw_cycle != ((OsmGpsMapPrivate*)user)->redraw_cycle); } static void osm_gps_map_purge_cache (OsmGpsMap *map) { OsmGpsMapPrivate *priv = map->priv; 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_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv); } gboolean osm_gps_map_map_redraw (OsmGpsMap *map) { cairo_t *cr; int w, h; OsmGpsMapPrivate *priv = map->priv; GtkWidget *widget = GTK_WIDGET(map); priv->idle_map_redraw = 0; /* dont't redraw if we have not been shown yet */ if (!priv->pixmap) return FALSE; /* don't redraw the entire map while the OSD is doing */ /* some animation or the like. This is to keep the animation */ /* fluid */ if (priv->layers) { GSList *list; for(list = priv->layers; list != NULL; list = list->next) { OsmGpsMapLayer *layer = list->data; if (osm_gps_map_layer_busy(layer)) return FALSE; } } /* the motion_notify handler uses priv->surface 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->is_dragging) return FALSE; /* paint to the backing surface */ cr = cairo_create (priv->pixmap); /* undo all offsets that may have happened when dragging */ priv->drag_mouse_dx = 0; priv->drag_mouse_dy = 0; priv->redraw_cycle++; /* clear white background */ w = gtk_widget_get_allocated_width (widget); h = gtk_widget_get_allocated_width (widget); draw_white_rectangle(cr, 0, 0, w + EXTRA_BORDER * 2, h + EXTRA_BORDER * 2); osm_gps_map_fill_tiles_pixel(map, cr); osm_gps_map_print_tracks(map, cr); osm_gps_map_print_polygons(map, cr); osm_gps_map_print_images(map, cr); /* draw the gps point using the appropriate virtual private method */ if (priv->gps_track_used && priv->gps_point_enabled) { OsmGpsMapClass *klass = OSM_GPS_MAP_GET_CLASS(map); if (klass->draw_gps_point) klass->draw_gps_point (map, cr); } if (priv->layers) { GSList *list; for(list = priv->layers; list != NULL; list = list->next) { OsmGpsMapLayer *layer = list->data; osm_gps_map_layer_render (layer, map); } } osm_gps_map_purge_cache(map); gtk_widget_queue_draw (GTK_WIDGET (map)); cairo_destroy (cr); return FALSE; } 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); } /* call this to update center_rlat and center_rlon after * changin map_x or map_y */ static void center_coord_update(OsmGpsMap *map) { GtkWidget *widget = GTK_WIDGET(map); OsmGpsMapPrivate *priv = map->priv; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); gint pixel_x = priv->map_x + allocation.width/2; gint pixel_y = priv->map_y + allocation.height/2; priv->center_rlon = pixel2lon(priv->map_zoom, pixel_x); priv->center_rlat = pixel2lat(priv->map_zoom, pixel_y); g_signal_emit_by_name(widget, "changed"); } /* Automatically center the map if the current point, i.e the most recent * gps point, approaches the edge, and map_auto_center is set. Does not * request the map be redrawn */ static void maybe_autocenter_map (OsmGpsMap *map) { OsmGpsMapPrivate *priv; GtkAllocation allocation; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); if(priv->map_auto_center_enabled) { int pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon); int pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat); int x = pixel_x - priv->map_x; int y = pixel_y - priv->map_y; int width = allocation.width; int height = 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 - allocation.width/2; priv->map_y = pixel_y - allocation.height/2; center_coord_update(map); } } } static gboolean on_window_key_press(GtkWidget *widget, GdkEventKey *event, OsmGpsMapPrivate *priv) { int i; int step; gboolean handled; GtkAllocation allocation; OsmGpsMap *map = OSM_GPS_MAP(widget); /* if no keybindings are set, let the app handle them... */ if (!priv->keybindings_enabled) return FALSE; handled = FALSE; gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); step = allocation.width/OSM_GPS_MAP_SCROLL_STEP; /* the map handles some keys on its own */ for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) { /* not the key we have a binding for */ if (map->priv->keybindings[i] != event->keyval) continue; switch(i) { case OSM_GPS_MAP_KEY_FULLSCREEN: { GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget)); if(!priv->is_fullscreen) gtk_window_fullscreen(GTK_WINDOW(toplevel)); else gtk_window_unfullscreen(GTK_WINDOW(toplevel)); priv->is_fullscreen = !priv->is_fullscreen; handled = TRUE; } break; case OSM_GPS_MAP_KEY_ZOOMIN: osm_gps_map_zoom_in(map); handled = TRUE; break; case OSM_GPS_MAP_KEY_ZOOMOUT: osm_gps_map_zoom_out(map); handled = TRUE; break; case OSM_GPS_MAP_KEY_UP: priv->map_y -= step; center_coord_update(map); osm_gps_map_map_redraw_idle(map); handled = TRUE; break; case OSM_GPS_MAP_KEY_DOWN: priv->map_y += step; center_coord_update(map); osm_gps_map_map_redraw_idle(map); handled = TRUE; break; case OSM_GPS_MAP_KEY_LEFT: priv->map_x -= step; center_coord_update(map); osm_gps_map_map_redraw_idle(map); handled = TRUE; break; case OSM_GPS_MAP_KEY_RIGHT: priv->map_x += step; center_coord_update(map); osm_gps_map_map_redraw_idle(map); handled = TRUE; break; default: break; } } return handled; } static void on_gps_point_added (OsmGpsMapTrack *track, OsmGpsMapPoint *point, OsmGpsMap *map) { osm_gps_map_map_redraw_idle (map); maybe_autocenter_map (map); } static void on_track_changed (OsmGpsMapTrack *track, GParamSpec *pspec, OsmGpsMap *map) { osm_gps_map_map_redraw_idle (map); } static void osm_gps_map_init (OsmGpsMap *object) { int i; 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 = osm_gps_map_point_new_radians(0.0, 0.0); priv->gps_track_used = FALSE; priv->gps_heading = OSM_GPS_MAP_INVALID; priv->gps_track = osm_gps_map_track_new(); g_signal_connect(priv->gps_track, "point-added", G_CALLBACK(on_gps_point_added), object); g_signal_connect(priv->gps_track, "notify", G_CALLBACK(on_track_changed), object); priv->tracks = NULL; priv->images = NULL; priv->layers = 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->is_google = FALSE; priv->map_source = -1; priv->keybindings_enabled = FALSE; for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) priv->keybindings[i] = 0; /* set the user agent */ priv->soup_session = soup_session_async_new_with_options(SOUP_SESSION_USER_AGENT, USER_AGENT, NULL); /* Hash table which maps tile d/l URIs to SoupMessage requests, the hashtable must free the key, the soup session unrefs the message */ priv->tile_queue = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); //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_SCROLL_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); #ifdef HAVE_GDK_EVENT_GET_SCROLL_DELTAS gtk_widget_add_events (GTK_WIDGET (object), GDK_SMOOTH_SCROLL_MASK) #endif gtk_widget_set_can_focus (GTK_WIDGET (object), TRUE); g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL); /* setup signal handlers */ g_signal_connect(object, "key_press_event", G_CALLBACK(on_window_key_press), priv); } static char* osm_gps_map_get_cache_base_dir(OsmGpsMapPrivate *priv) { if (priv->tile_base_dir) return g_strdup(priv->tile_base_dir); return osm_gps_map_get_default_cache_directory(); } static void osm_gps_map_setup(OsmGpsMap *map) { const char *uri; OsmGpsMapPrivate *priv = map->priv; /* user can specify a map source ID, or a repo URI as the map source */ uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL); if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) { g_debug("Using null source"); priv->map_source = OSM_GPS_MAP_SOURCE_NULL; priv->null_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 256, 256); gdk_pixbuf_fill(priv->null_tile, 0xcccccc00); } else if (priv->map_source >= 0) { /* check if the source given is valid */ uri = osm_gps_map_source_get_repo_uri(priv->map_source); if (uri) { g_debug("Setting map source from ID"); g_free(priv->repo_uri); priv->repo_uri = g_strdup(uri); g_free(priv->image_format); priv->image_format = g_strdup( osm_gps_map_source_get_image_format(priv->map_source)); priv->max_zoom = osm_gps_map_source_get_max_zoom(priv->map_source); priv->min_zoom = osm_gps_map_source_get_min_zoom(priv->map_source); } } /* parse the source uri */ inspect_map_uri(priv); /* setup the tile cache */ if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) { g_free(priv->cache_dir); priv->cache_dir = NULL; } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) { char *base = osm_gps_map_get_cache_base_dir(priv); char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1); g_free(priv->cache_dir); priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5); g_free(base); g_free(md5); } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) { char *base = osm_gps_map_get_cache_base_dir(priv); const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source); g_free(priv->cache_dir); priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname); g_free(base); } else { /* the simple case is handled in g_object_set(PROP_TILE_CACHE_DIR) */ } g_debug("Cache dir: %s", priv->cache_dir); /* check if we are being called for a second (or more) time in the lifetime of the object, and if so, do some extra cleanup */ if ( priv->is_constructed ) { g_debug("Setup called again in map lifetime"); /* flush the ram cache */ g_hash_table_remove_all(priv->tile_cache); /* adjust zoom if necessary */ if(priv->map_zoom > priv->max_zoom) osm_gps_map_set_zoom(map, priv->max_zoom); if(priv->map_zoom < priv->min_zoom) osm_gps_map_set_zoom(map, priv->min_zoom); osm_gps_map_map_redraw_idle(map); } } static GObject * osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties) { GObject *object; OsmGpsMap *map; /* always chain up to the parent constructor */ object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties); map = OSM_GPS_MAP(object); osm_gps_map_setup(map); map->priv->is_constructed = TRUE; 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_object_unref(priv->gps_track); g_hash_table_destroy(priv->tile_queue); g_hash_table_destroy(priv->missing_tiles); g_hash_table_destroy(priv->tile_cache); /* images and layers contain GObjects which need unreffing, so free here */ gslist_of_gobjects_free(&priv->images); gslist_of_gobjects_free(&priv->layers); gslist_of_gobjects_free(&priv->tracks); if(priv->pixmap) cairo_surface_destroy (priv->pixmap); if (priv->null_tile) g_object_unref (priv->null_tile); if (priv->idle_map_redraw != 0) g_source_remove (priv->idle_map_redraw); if (priv->drag_expose_source != 0) g_source_remove (priv->drag_expose_source); g_free(priv->gps); 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; if (priv->tile_dir) g_free(priv->tile_dir); g_free(priv->tile_base_dir); if (priv->cache_dir) g_free(priv->cache_dir); g_free(priv->repo_uri); g_free(priv->proxy_uri); g_free(priv->image_format); /* trip and tracks contain simple non GObject types, so free them here */ gslist_of_data_free(&priv->trip_history); 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_enabled = g_value_get_boolean (value); break; case PROP_RECORD_TRIP_HISTORY: priv->trip_history_record_enabled = g_value_get_boolean (value); break; case PROP_SHOW_TRIP_HISTORY: priv->trip_history_show_enabled = g_value_get_boolean (value); break; case PROP_AUTO_DOWNLOAD: priv->map_auto_download_enabled = g_value_get_boolean (value); break; case PROP_REPO_URI: g_free(priv->repo_uri); priv->repo_uri = g_value_dup_string (value); break; case PROP_PROXY_URI: if ( g_value_get_string(value) ) { g_free(priv->proxy_uri); priv->proxy_uri = g_value_dup_string (value); g_debug("Setting proxy server: %s", priv->proxy_uri); GValue val = {0}; 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 { g_free(priv->proxy_uri); priv->proxy_uri = NULL; } break; case PROP_TILE_CACHE_DIR: if ( g_value_get_string(value) ) { g_free(priv->tile_dir); priv->tile_dir = g_value_dup_string (value); if ((g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0) || (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0) || (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0)) { /* this case is handled by osm_gps_map_setup */ } else { if (priv->cache_dir) g_free(priv->cache_dir); priv->cache_dir = g_strdup(priv->tile_dir); g_debug("Cache dir: %s", priv->cache_dir); } } else { if (priv->tile_dir) g_free(priv->tile_dir); priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED); } break; case PROP_TILE_CACHE_BASE_DIR: g_free(priv->tile_base_dir); priv->tile_base_dir = g_value_dup_string (value); break; case PROP_TILE_ZOOM_OFFSET: priv->tile_zoom_offset = g_value_get_int (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); center_coord_update(map); break; case PROP_MAP_Y: priv->map_y = g_value_get_int (value); center_coord_update(map); break; case PROP_GPS_TRACK_WIDTH: g_object_set (priv->gps_track, "line-width", g_value_get_float (value), NULL); 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; case PROP_MAP_SOURCE: { gint old = priv->map_source; priv->map_source = g_value_get_int (value); if(old >= OSM_GPS_MAP_SOURCE_NULL && priv->map_source != old && priv->map_source >= OSM_GPS_MAP_SOURCE_NULL && priv->map_source <= OSM_GPS_MAP_SOURCE_LAST) { if (!priv->is_constructed) g_critical("Map source setup called twice"); /* we now have to switch the entire map */ osm_gps_map_setup(map); } } break; case PROP_IMAGE_FORMAT: g_free(priv->image_format); priv->image_format = g_value_dup_string (value); break; case PROP_DRAG_LIMIT: priv->drag_limit = g_value_get_int (value); break; case PROP_AUTO_CENTER_THRESHOLD: priv->map_auto_center_threshold = g_value_get_float (value); break; case PROP_SHOW_GPS_POINT: priv->gps_point_enabled = g_value_get_boolean (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)); 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_enabled); break; case PROP_RECORD_TRIP_HISTORY: g_value_set_boolean(value, priv->trip_history_record_enabled); break; case PROP_SHOW_TRIP_HISTORY: g_value_set_boolean(value, priv->trip_history_show_enabled); break; case PROP_AUTO_DOWNLOAD: g_value_set_boolean(value, priv->map_auto_download_enabled); 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_BASE_DIR: g_value_set_string(value, priv->tile_base_dir); break; case PROP_TILE_ZOOM_OFFSET: g_value_set_int(value, priv->tile_zoom_offset); 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: g_value_set_float(value, rad2deg(priv->center_rlat)); break; case PROP_LONGITUDE: g_value_set_float(value, rad2deg(priv->center_rlon)); 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: { gfloat f; g_object_get (priv->gps_track, "line-width", &f, NULL); g_value_set_float (value, f); } 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; case PROP_MAP_SOURCE: g_value_set_int(value, priv->map_source); break; case PROP_IMAGE_FORMAT: g_value_set_string(value, priv->image_format); break; case PROP_DRAG_LIMIT: g_value_set_int(value, priv->drag_limit); break; case PROP_AUTO_CENTER_THRESHOLD: g_value_set_float(value, priv->map_auto_center_threshold); break; case PROP_SHOW_GPS_POINT: g_value_set_boolean(value, priv->gps_point_enabled); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static gboolean osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll *event) { OsmGpsMap *map; OsmGpsMapPoint *pt; float lat, lon, c_lat, c_lon; map = OSM_GPS_MAP(widget); pt = osm_gps_map_point_new_degrees(0.0,0.0); /* arguably we could use get_event_location here, but I'm not convinced it is forward compatible to cast between GdkEventScroll and GtkEventButton */ osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, pt); osm_gps_map_point_get_degrees (pt, &lat, &lon); c_lat = rad2deg(map->priv->center_rlat); c_lon = rad2deg(map->priv->center_rlon); if ((event->direction == GDK_SCROLL_UP) && (map->priv->map_zoom < map->priv->max_zoom)) { lat = c_lat + ((lat - c_lat)/2.0); lon = c_lon + ((lon - c_lon)/2.0); osm_gps_map_set_center_and_zoom(map, lat, lon, map->priv->map_zoom+1); } else if ((event->direction == GDK_SCROLL_DOWN) && (map->priv->map_zoom > map->priv->min_zoom)) { lat = c_lat + ((c_lat - lat)*1.0); lon = c_lon + ((c_lon - lon)*1.0); osm_gps_map_set_center_and_zoom(map, lat, lon, map->priv->map_zoom-1); } osm_gps_map_point_free (pt); return FALSE; } static gboolean osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event) { OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapPrivate *priv = map->priv; if (priv->layers) { GSList *list; for(list = priv->layers; list != NULL; list = list->next) { OsmGpsMapLayer *layer = list->data; if (osm_gps_map_layer_button_press(layer, map, event)) return FALSE; } } if(event->button == 1) { GSList* tracks = priv->tracks; while(tracks) { OsmGpsMapTrack* track = tracks->data; gboolean path_editable = FALSE; g_object_get(track, "editable", &path_editable, NULL); if(path_editable) { GSList* points = osm_gps_map_track_get_points(track); int ctr = 0; int last_x = 0; int last_y = 0; while(points) { //if the mouse has gone down on a point, start dragging it int cx, cy; OsmGpsMapPoint* point = (OsmGpsMapPoint*)points->data; osm_gps_map_convert_geographic_to_screen(map, point, &cx, &cy); float dist_sqrd = (event->x - cx) * (event->x-cx) + (event->y-cy) * (event->y-cy); if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1))) { priv->is_button_down = TRUE; priv->drag_point = point; priv->drag_track = track; priv->is_dragging_point = TRUE; osm_gps_map_map_redraw(map); return FALSE; } //add a new point if a 'breaker' has been clicked if(ctr != 0) { int ptx = (last_x+cx)/2.0; int pty = (last_y+cy)/2.0; dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty); if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1))) { OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint)); osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint); osm_gps_map_track_insert_point(track, newpoint, ctr); osm_gps_map_map_redraw(map); return FALSE; } } last_x = cx; last_y = cy; points = points->next; ctr++; } } tracks = tracks->next; } GSList* polys = priv->polygons; while(polys) { OsmGpsMapPolygon* poly = polys->data; gboolean path_editable = FALSE; OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly); g_object_get(poly, "editable", &path_editable, NULL); if(path_editable) { GSList* points = osm_gps_map_track_get_points(track); int ctr = 0; int last_x = 0; int last_y = 0; int first_x = 0; int first_y = 0; while(points) { //if the mouse has gone down on a point, start dragging it int cx, cy; OsmGpsMapPoint* point = (OsmGpsMapPoint*)points->data; osm_gps_map_convert_geographic_to_screen(map, point, &cx, &cy); float dist_sqrd = (event->x - cx) * (event->x-cx) + (event->y-cy) * (event->y-cy); if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1))) { priv->is_button_down = TRUE; priv->drag_point = point; priv->drag_track = track; priv->is_dragging_point = TRUE; osm_gps_map_map_redraw(map); return FALSE; } //add a new point if a 'breaker' has been clicked if(ctr != 0) { int ptx = (last_x+cx)/2.0; int pty = (last_y+cy)/2.0; dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty); if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1))) { OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint)); osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint); osm_gps_map_track_insert_point(track, newpoint, ctr); osm_gps_map_map_redraw(map); return FALSE; } } else { first_x = cx; first_y = cy; } last_x = cx; last_y = cy; points = points->next; ctr++; } int ptx = (last_x+first_x)/2.0; int pty = (last_y+first_y)/2.0; float dist_sqrd = (event->x - ptx) * (event->x-ptx) + (event->y-pty) * (event->y-pty); if(dist_sqrd <= ((DOT_RADIUS + 1) * (DOT_RADIUS + 1))) { OsmGpsMapPoint* newpoint = malloc(sizeof(OsmGpsMapPoint)); osm_gps_map_convert_screen_to_geographic(map, ptx, pty, newpoint); osm_gps_map_track_insert_point(track, newpoint, ctr); osm_gps_map_map_redraw(map); return FALSE; } } polys = polys->next; } } priv->is_button_down = TRUE; 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) { OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapPrivate *priv = map->priv; if(!priv->is_button_down) return FALSE; if (priv->is_dragging) { priv->is_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); center_coord_update(map); osm_gps_map_map_redraw_idle(map); } if( priv->is_dragging_point) { priv->is_dragging_point = FALSE; osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, priv->drag_point); g_signal_emit_by_name(priv->drag_track, "point-changed"); } priv->drag_counter = -1; priv->is_button_down = FALSE; return FALSE; } static gboolean osm_gps_map_idle_expose (GtkWidget *widget) { OsmGpsMapPrivate *priv = OSM_GPS_MAP(widget)->priv; priv->drag_expose_source = 0; gtk_widget_queue_draw (widget); return FALSE; } static gboolean osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion *event) { GdkModifierType state; OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapPrivate *priv = map->priv; gint x, y; GdkDeviceManager* manager = gdk_display_get_device_manager( gdk_display_get_default() ); GdkDevice* pointer = gdk_device_manager_get_client_pointer( manager); if(!priv->is_button_down) return FALSE; if(priv->is_dragging_point) { osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, priv->drag_point); osm_gps_map_map_redraw_idle(map); return FALSE; } if (event->is_hint) // gdk_window_get_pointer (event->window, &x, &y, &state); gdk_window_get_device_position( event->window, pointer, &x, &y, &state); else { x = event->x; y = event->y; state = event->state; } // are we being dragged if (!(state & GDK_BUTTON1_MASK)) return FALSE; if (priv->drag_counter < 0) return FALSE; /* not yet dragged far enough? */ if(!priv->drag_counter && ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) + (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) < priv->drag_limit*priv->drag_limit)) return FALSE; priv->drag_counter++; priv->is_dragging = TRUE; if (priv->map_auto_center_enabled) 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; /* instead of redrawing directly just add an idle function */ if (!priv->drag_expose_source) priv->drag_expose_source = g_idle_add ((GSourceFunc)osm_gps_map_idle_expose, widget); return FALSE; } static gboolean osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event) { int w,h; GdkWindow *window; OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapPrivate *priv = map->priv; if (priv->pixmap) cairo_surface_destroy (priv->pixmap); w = gtk_widget_get_allocated_width (widget); h = gtk_widget_get_allocated_height (widget); window = gtk_widget_get_window(widget); priv->pixmap = gdk_window_create_similar_surface ( window, CAIRO_CONTENT_COLOR, w + EXTRA_BORDER * 2, h + EXTRA_BORDER * 2); // pixel_x,y, offsets gint pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon); gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat); priv->map_x = pixel_x - w/2; priv->map_y = pixel_y - h/2; osm_gps_map_map_redraw(OSM_GPS_MAP(widget)); g_signal_emit_by_name(widget, "changed"); return FALSE; } static gboolean osm_gps_map_draw (GtkWidget *widget, cairo_t *cr) { OsmGpsMap *map = OSM_GPS_MAP(widget); OsmGpsMapPrivate *priv = map->priv; if (!priv->drag_mouse_dx && !priv->drag_mouse_dy) { cairo_set_source_surface (cr, priv->pixmap, 0, 0); } else { cairo_set_source_surface (cr, priv->pixmap, priv->drag_mouse_dx - EXTRA_BORDER, priv->drag_mouse_dy - EXTRA_BORDER); } cairo_paint (cr); if (priv->layers) { GSList *list; for(list = priv->layers; list != NULL; list = list->next) { OsmGpsMapLayer *layer = list->data; osm_gps_map_layer_draw(layer, map, cr); } } return FALSE; } static void osm_gps_map_class_init (OsmGpsMapClass *klass) { GObjectClass* object_class; GtkWidgetClass *widget_class; g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate)); object_class = G_OBJECT_CLASS (klass); 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 = GTK_WIDGET_CLASS (klass); widget_class->draw = osm_gps_map_draw; 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_event; //widget_class->get_preferred_width = osm_gps_map_get_preferred_width; //widget_class->get_preferred_height = osm_gps_map_get_preferred_height; /* default implementation of draw_gps_point */ klass->draw_gps_point = osm_gps_map_draw_gps_point; 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_AUTO_CENTER_THRESHOLD, g_param_spec_float ("auto-center-threshold", "auto center threshold", "the amount of the window the gps point must move before auto centering", 0.0, /* minimum property value */ 1.0, /* maximum property value */ 0.25, 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)); /** * OsmGpsMap:show-gps-point: * * Controls whether the current gps point is shown on the map. Note that * for derived classes that implement the draw_gps_point vfunc, if this * property is %FALSE **/ g_object_class_install_property (object_class, PROP_SHOW_GPS_POINT, g_param_spec_boolean ("show-gps-point", "show gps point", "should the current gps point 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)); /** * OsmGpsMap:repo-uri: * * A URI string which defines the location and format to fetch tiles * for the map. The string is of the format * "http://tile.openstreetmap.org/#Z/#X/#Y.png". Characters * that begin with # are treated as tokens and replaced according to * the following rules; * * * * * \#X - X-tile, slippy map format * * * * * \#Y - Y-tile, slippy map format, mercator projection * * * * * \#Z - Zoom level, where min_zoom >= zoom <= max_zoom * * * * * \#S - Zoom level, where -max_zoom >= (zoom-max_zoom) <= min_zoom * * * * * \#Q - Quad tree format, set of "qrts" * * * * * \#Q0 - Quad tree format, set of "0123" * * * * * \#YS - Not Implemented * * * * * \#R - Random integer in range [0,4] * * * * * * * If you do not wish to use the default map tiles (provided by OpenStreeMap) * it is recommened that you use one of the predefined map sources, and thus * you should construct the map by setting #OsmGpsMap:map-source and not * #OsmGpsMap:repo-uri. The #OsmGpsMap:repo-uri property is primarily * designed for applications that wish complete control of tile repository * management, or wish to use #OsmGpsMap with a tile repository it does not * explicitly support. * * **/ g_object_class_install_property (object_class, PROP_REPO_URI, g_param_spec_string ("repo-uri", "repo uri", "Map source tile repository uri", OSM_REPO_URI, 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 or NULL", NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); /** * OsmGpsMap:tile-cache: * * Either a full path or one of the special format URIs * #OSM_GPS_MAP_CACHE_DISABLED, #OSM_GPS_MAP_CACHE_AUTO, * #OSM_GPS_MAP_CACHE_FRIENDLY. Also see #OsmGpsMap:tile-cache-base for a * full understanding. * * #OSM_GPS_MAP_CACHE_DISABLED disables the on disk tile cache (so all tiles * are fetched from the network. #OSM_GPS_MAP_CACHE_AUTO causes the tile * cache to be /tile-cache-base/md5(repo-uri), where md5 is the md5sum * of #OsmGpsMap:repo-uri. #OSM_GPS_MAP_CACHE_FRIENDLY * causes the tile cache to be /tile-cache-base/friendlyname(repo-uri). * * Any other string is interpreted as a local path, i.e. /path/to/cache **/ g_object_class_install_property (object_class, PROP_TILE_CACHE_DIR, g_param_spec_string ("tile-cache", "tile cache", "Tile cache dir", OSM_GPS_MAP_CACHE_AUTO, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); /** * OsmGpsMap:tile-cache-base: * * The base directory of the tile cache when you have constructed * the map with #OsmGpsMap:tile-cache set to #OSM_GPS_MAP_CACHE_AUTO or * #OSM_GPS_MAP_CACHE_FRIENDLY * * The string is interpreted as a local path, i.e. /path/to/cache. If NULL * is supplied, map tiles are cached starting in the users cache directory, * (as outlined in the * * XDG Base Directory Specification). To get the * base directory where map tiles will be cached call * osm_gps_map_get_default_cache_directory() * **/ g_object_class_install_property (object_class, PROP_TILE_CACHE_BASE_DIR, g_param_spec_string ("tile-cache-base", "tile cache-base", "Base directory to which friendly and auto paths are appended", NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); /** * OsmGpsMap:zoom: * * The map zoom level. Connect to ::notify::zoom if you want to be informed * when this changes. **/ g_object_class_install_property (object_class, PROP_ZOOM, g_param_spec_int ("zoom", "zoom", "Map 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_TILE_ZOOM_OFFSET, g_param_spec_int ("tile-zoom-offset", "tile zoom-offset", "Number of zoom-levels to upsample tiles", MIN_TILE_ZOOM_OFFSET, /* minimum propery value */ MAX_TILE_ZOOM_OFFSET, /* maximum propery value */ 0, 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 */ OSM_MAX_ZOOM, 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 */ OSM_MIN_ZOOM, 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)); /** * OsmGpsMap:tiles-queued: * * The number of tiles currently waiting to download. Connect to * ::notify::tiles-queued if you want to be informed when this changes **/ g_object_class_install_property (object_class, PROP_TILES_QUEUED, g_param_spec_int ("tiles-queued", "tiles-queued", "The 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_float ("gps-track-width", "gps-track-width", "The width of the lines drawn for the gps track", 1.0, /* minimum property value */ 100.0, /* maximum property value */ 4.0, 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", "The 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", "The 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)); /** * OsmGpsMap:map-source: * * A #OsmGpsMapSource_t representing the tile repository to use * * * * If you do not wish to use the default map tiles (provided by OpenStreeMap) * it is recommened that you set this property at construction, instead * of setting #OsmGpsMap:repo-uri. * * **/ g_object_class_install_property (object_class, PROP_MAP_SOURCE, g_param_spec_int ("map-source", "map source", "The map source ID", -1, /* minimum property value */ G_MAXINT, /* maximum property value */ -1, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_IMAGE_FORMAT, g_param_spec_string ("image-format", "image format", "The map source tile repository image format (jpg, png)", OSM_IMAGE_FORMAT, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_DRAG_LIMIT, g_param_spec_int ("drag-limit", "drag limit", "The number of pixels the user has to move the pointer in order to start dragging", 0, /* minimum property value */ G_MAXINT, /* maximum property value */ 10, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); /** * OsmGpsMap::changed: * * The #OsmGpsMap::changed signal is emitted any time the map zoom or map center * is chaged (such as by dragging or zooming). * * * * If you are only interested in the map zoom, then you can simply connect * to ::notify::zoom * * **/ g_signal_new ("changed", OSM_TYPE_GPS_MAP, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } /** * osm_gps_map_download_maps: * * Downloads all tiles over the supplied zoom range in the rectangular * region specified by pt1 (north west corner) to pt2 (south east corner) * **/ void osm_gps_map_download_maps (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2, int zoom_start, int zoom_end) { OsmGpsMapPrivate *priv = map->priv; if (pt1 && pt2) { gchar *filename; int i,j,zoom; int num_tiles = 0; zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom); zoom_start = CLAMP(zoom_start, priv->min_zoom, priv->max_zoom); 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); /* check for insane ranges */ if ( (x2-x1) * (y2-y1) > MAX_DOWNLOAD_TILES ) { g_warning("Aborting download of zoom level %d and up, because " "number of tiles would exceed %d", zoom, MAX_DOWNLOAD_TILES); break; } /* 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%c%d%c%d%c%d.%s", priv->cache_dir, G_DIR_SEPARATOR, zoom, G_DIR_SEPARATOR, i, G_DIR_SEPARATOR, j, priv->image_format); 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); } } } static void cancel_message (char *key, SoupMessage *value, SoupSession *user_data) { soup_session_cancel_message (user_data, value, SOUP_STATUS_CANCELLED); } /** * osm_gps_map_download_cancel_all: * * Cancels all tiles currently being downloaded. Typically used if you wish to * cacel a large number of tiles queued using osm_gps_map_download_maps() * * Since: 0.7.0 **/ void osm_gps_map_download_cancel_all (OsmGpsMap *map) { OsmGpsMapPrivate *priv = map->priv; g_hash_table_foreach (priv->tile_queue, (GHFunc)cancel_message, priv->soup_session); } /** * osm_gps_map_get_bbox: * @pt1: (out): point to be filled with the top left location * @pt2: (out): point to be filled with the bottom right location * * Returns the geographic locations of the bounding box describing the contents * of the current window, i.e the top left and bottom right corners. **/ void osm_gps_map_get_bbox (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2) { GtkAllocation allocation; OsmGpsMapPrivate *priv = map->priv; if (pt1 && pt2) { gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); 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 + allocation.height); pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + allocation.width); } } /** * osm_gps_map_zoom_fit_bbox: * Zoom and center the map so that both points fit inside the window. **/ void osm_gps_map_zoom_fit_bbox (OsmGpsMap *map, float latitude1, float latitude2, float longitude1, float longitude2) { GtkAllocation allocation; int zoom; gtk_widget_get_allocation (GTK_WIDGET (map), &allocation); zoom = latlon2zoom (allocation.height, allocation.width, deg2rad(latitude1), deg2rad(latitude2), deg2rad(longitude1), deg2rad(longitude2)); osm_gps_map_set_center (map, (latitude1 + latitude2) / 2, (longitude1 + longitude2) / 2); osm_gps_map_set_zoom (map, zoom); } /** * osm_gps_map_set_center_and_zoom: * * Since: 0.7.0 **/ void osm_gps_map_set_center_and_zoom (OsmGpsMap *map, float latitude, float longitude, int zoom) { osm_gps_map_set_center (map, latitude, longitude); osm_gps_map_set_zoom (map, zoom); } /** * osm_gps_map_set_center: * **/ void osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude) { int pixel_x, pixel_y; OsmGpsMapPrivate *priv; GtkAllocation allocation; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); g_object_set(G_OBJECT(map), "auto-center", FALSE, NULL); priv->center_rlat = deg2rad(latitude); priv->center_rlon = deg2rad(longitude); pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon); pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat); priv->map_x = pixel_x - allocation.width/2; priv->map_y = pixel_y - allocation.height/2; osm_gps_map_map_redraw_idle(map); g_signal_emit_by_name(map, "changed"); } /** * osm_gps_map_set_zoom_offset: * **/ void osm_gps_map_set_zoom_offset (OsmGpsMap *map, int zoom_offset) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_GPS_MAP (map)); priv = map->priv; if (zoom_offset != priv->tile_zoom_offset) { priv->tile_zoom_offset = zoom_offset; osm_gps_map_map_redraw_idle (map); } } /** * osm_gps_map_set_zoom: * **/ int osm_gps_map_set_zoom (OsmGpsMap *map, int zoom) { int width_center, height_center; OsmGpsMapPrivate *priv; GtkAllocation allocation; g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0); priv = map->priv; if (zoom != priv->map_zoom) { gtk_widget_get_allocation(GTK_WIDGET(map), &allocation); width_center = allocation.width / 2; height_center = allocation.height / 2; /* update zoom but constrain [min_zoom..max_zoom] */ priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom); priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center; priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center; osm_gps_map_map_redraw_idle(map); g_signal_emit_by_name(map, "changed"); g_object_notify(G_OBJECT(map), "zoom"); } return priv->map_zoom; } /** * osm_gps_map_zoom_in: * **/ int osm_gps_map_zoom_in (OsmGpsMap *map) { g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0); return osm_gps_map_set_zoom(map, map->priv->map_zoom+1); } /** * osm_gps_map_zoom_out: * **/ int osm_gps_map_zoom_out (OsmGpsMap *map) { g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0); return osm_gps_map_set_zoom(map, map->priv->map_zoom-1); } /** * osm_gps_map_new: * * Returns a new #OsmGpsMap object, defaults to showing data from * OpenStreetMap * * See the properties description for more information about construction * parameters than could be passed to g_object_new() * * Returns: a newly created #OsmGpsMap object. **/ GtkWidget * osm_gps_map_new (void) { return g_object_new (OSM_TYPE_GPS_MAP, NULL); } /** * osm_gps_map_scroll: * @map: * @dx: * @dy: * * Scrolls the map by @dx, @dy pixels (positive north, east) * **/ 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->map_x += dx; priv->map_y += dy; center_coord_update(map); osm_gps_map_map_redraw_idle (map); } /** * osm_gps_map_get_scale: * @map: * * Returns: the scale of the map at the center, in meters/pixel. * **/ float osm_gps_map_get_scale (OsmGpsMap *map) { OsmGpsMapPrivate *priv; g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_GPS_MAP_INVALID); priv = map->priv; return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon); } /** * osm_gps_map_get_default_cache_directory: * * Returns: the default cache directory for the library, that is the base * directory to which the full cache path is appended. If * #OsmGpsMap:tile-cache-base is omitted from the constructor then this value * is used. * **/ gchar * osm_gps_map_get_default_cache_directory (void) { return g_build_filename( g_get_user_cache_dir(), "osmgpsmap", NULL); } /** * osm_gps_map_set_keyboard_shortcut: * @key: a #OsmGpsMapKey_t * @keyval: * * Associates a keyboard shortcut with the supplied @keyval * (as returned by #gdk_keyval_from_name or simiar). The action given in @key * will be triggered when the corresponding @keyval is pressed. By default * no keyboard shortcuts are associated. * **/ void osm_gps_map_set_keyboard_shortcut (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval) { g_return_if_fail (OSM_IS_GPS_MAP (map)); g_return_if_fail(key < OSM_GPS_MAP_KEY_MAX); map->priv->keybindings[key] = keyval; map->priv->keybindings_enabled = TRUE; } /** * osm_gps_map_track_add: * * Since: 0.7.0 **/ void osm_gps_map_track_add (OsmGpsMap *map, OsmGpsMapTrack *track) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; g_object_ref(track); g_signal_connect(track, "point-added", G_CALLBACK(on_gps_point_added), map); g_signal_connect(track, "notify", G_CALLBACK(on_track_changed), map); priv->tracks = g_slist_append(priv->tracks, track); osm_gps_map_map_redraw_idle(map); } /** * osm_gps_map_track_remove_all: * * Since: 0.7.0 **/ void osm_gps_map_track_remove_all (OsmGpsMap *map) { g_return_if_fail (OSM_IS_GPS_MAP (map)); gslist_of_gobjects_free(&map->priv->tracks); osm_gps_map_map_redraw_idle(map); } /** * osm_gps_map_track_remove: * * Since: 0.7.0 **/ gboolean osm_gps_map_track_remove (OsmGpsMap *map, OsmGpsMapTrack *track) { GSList *data; g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE); g_return_val_if_fail (track != NULL, FALSE); data = gslist_remove_one_gobject (&map->priv->tracks, G_OBJECT(track)); osm_gps_map_map_redraw_idle(map); return data != NULL; } void osm_gps_map_polygon_add (OsmGpsMap *map, OsmGpsMapPolygon *poly) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; g_object_ref(poly); OsmGpsMapTrack* track = osm_gps_map_polygon_get_track(poly); g_signal_connect(track, "point-added", G_CALLBACK(on_gps_point_added), map); g_signal_connect(track, "notify", G_CALLBACK(on_track_changed), map); priv->polygons = g_slist_append(priv->polygons, poly); osm_gps_map_map_redraw_idle(map); } void osm_gps_map_polygon_remove_all(OsmGpsMap *map) { g_return_if_fail (OSM_IS_GPS_MAP (map)); gslist_of_gobjects_free(&map->priv->polygons); osm_gps_map_map_redraw_idle(map); } gboolean osm_gps_map_polygon_remove(OsmGpsMap *map, OsmGpsMapPolygon *poly) { GSList *data; g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE); g_return_val_if_fail (poly != NULL, FALSE); data = gslist_remove_one_gobject (&map->priv->polygons, G_OBJECT(poly)); osm_gps_map_map_redraw_idle(map); return data != NULL; } /** * osm_gps_map_gps_clear: * * Since: 0.7.0 **/ void osm_gps_map_gps_clear (OsmGpsMap *map) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; g_object_unref(priv->gps_track); priv->gps_track = osm_gps_map_track_new(); g_signal_connect(priv->gps_track, "point-added", G_CALLBACK(on_gps_point_added), map); g_signal_connect(priv->gps_track, "notify", G_CALLBACK(on_track_changed), map); osm_gps_map_map_redraw_idle(map); } /** * osm_gps_map_gps_get_track: * * Returns: (transfer none): The #OsmGpsMapTrack of the internal GPS track, * i.e. that which is modified when calling osm_gps_map_gps_add(). You must * not free this. * Since: 0.7.0 **/ OsmGpsMapTrack * osm_gps_map_gps_get_track (OsmGpsMap *map) { g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL); return map->priv->gps_track; } /** * osm_gps_map_gps_add: * @latitude: degrees * @longitude: degrees * @heading: degrees or #OSM_GPS_MAP_INVALID to disable showing heading * * Since: 0.7.0 **/ void osm_gps_map_gps_add (OsmGpsMap *map, float latitude, float longitude, float heading) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; /* update the current point */ priv->gps->rlat = deg2rad(latitude); priv->gps->rlon = deg2rad(longitude); priv->gps_track_used = TRUE; priv->gps_heading = deg2rad(heading); /* If trip marker add to list of gps points */ if (priv->trip_history_record_enabled) { OsmGpsMapPoint point; osm_gps_map_point_set_degrees (&point, latitude, longitude); /* this will cause a redraw to be scheduled */ osm_gps_map_track_add_point (priv->gps_track, &point); } else { osm_gps_map_map_redraw_idle (map); maybe_autocenter_map (map); } } /** * osm_gps_map_image_add: * * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf * Since: 0.7.0 **/ OsmGpsMapImage * osm_gps_map_image_add (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image) { return osm_gps_map_image_add_with_alignment_z (map, latitude, longitude, image, 0.5, 0.5, 0); } /** * osm_gps_map_image_add_z: * * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf * Since: 0.7.4 **/ OsmGpsMapImage * osm_gps_map_image_add_z (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, gint zorder) { return osm_gps_map_image_add_with_alignment_z (map, latitude, longitude, image, 0.5, 0.5, zorder); } static void on_image_changed (OsmGpsMapImage *image, GParamSpec *pspec, OsmGpsMap *map) { osm_gps_map_map_redraw_idle (map); } /** * osm_gps_map_image_add_with_alignment: * * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf * Since: 0.7.0 **/ OsmGpsMapImage * osm_gps_map_image_add_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign) { return osm_gps_map_image_add_with_alignment_z (map, latitude, longitude, image, xalign, yalign, 0); } static gint osm_gps_map_image_z_compare(gconstpointer item1, gconstpointer item2) { gint z1 = osm_gps_map_image_get_zorder(OSM_GPS_MAP_IMAGE(item1)); gint z2 = osm_gps_map_image_get_zorder(OSM_GPS_MAP_IMAGE(item2)); return(z1 - z2 + 1); } /** * osm_gps_map_image_add_with_alignment_z: * * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf * Since: 0.7.4 **/ OsmGpsMapImage * osm_gps_map_image_add_with_alignment_z (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign, gint zorder) { OsmGpsMapImage *im; OsmGpsMapPoint pt; g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL); pt.rlat = deg2rad(latitude); pt.rlon = deg2rad(longitude); im = g_object_new (OSM_TYPE_GPS_MAP_IMAGE, "pixbuf", image, "x-align", xalign, "y-align", yalign, "point", &pt, "z-order", zorder, NULL); g_signal_connect(im, "notify", G_CALLBACK(on_image_changed), map); map->priv->images = g_slist_insert_sorted(map->priv->images, im, (GCompareFunc) osm_gps_map_image_z_compare); osm_gps_map_map_redraw_idle(map); g_object_ref(im); return im; } /** * osm_gps_map_image_remove: * * Since: 0.7.0 **/ gboolean osm_gps_map_image_remove (OsmGpsMap *map, OsmGpsMapImage *image) { GSList *data; g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE); g_return_val_if_fail (image != NULL, FALSE); data = gslist_remove_one_gobject (&map->priv->images, G_OBJECT(image)); osm_gps_map_map_redraw_idle(map); return data != NULL; } /** * osm_gps_map_image_remove_all: * * Since: 0.7.0 **/ void osm_gps_map_image_remove_all (OsmGpsMap *map) { g_return_if_fail (OSM_IS_GPS_MAP (map)); gslist_of_gobjects_free(&map->priv->images); osm_gps_map_map_redraw_idle(map); } /** * osm_gps_map_layer_add: * @layer: a #OsmGpsMapLayer object * * Since: 0.7.0 **/ void osm_gps_map_layer_add (OsmGpsMap *map, OsmGpsMapLayer *layer) { g_return_if_fail (OSM_IS_GPS_MAP (map)); g_return_if_fail (OSM_GPS_MAP_IS_LAYER (layer)); g_object_ref(G_OBJECT(layer)); map->priv->layers = g_slist_append(map->priv->layers, layer); } /** * osm_gps_map_layer_remove: * @layer: a #OsmGpsMapLayer object * * Since: 0.7.0 **/ gboolean osm_gps_map_layer_remove (OsmGpsMap *map, OsmGpsMapLayer *layer) { GSList *data; g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE); g_return_val_if_fail (layer != NULL, FALSE); data = gslist_remove_one_gobject (&map->priv->layers, G_OBJECT(layer)); osm_gps_map_map_redraw_idle(map); return data != NULL; } /** * osm_gps_map_layer_remove_all: * * Since: 0.7.0 **/ void osm_gps_map_layer_remove_all (OsmGpsMap *map) { g_return_if_fail (OSM_IS_GPS_MAP (map)); gslist_of_gobjects_free(&map->priv->layers); osm_gps_map_map_redraw_idle(map); } /** * osm_gps_map_convert_screen_to_geographic: * @map: * @pixel_x: pixel location on map, x axis * @pixel_y: pixel location on map, y axis * @pt: (out): location * * Convert the given pixel location on the map into corresponding * location on the globe * * Since: 0.7.0 **/ void osm_gps_map_convert_screen_to_geographic(OsmGpsMap *map, gint pixel_x, gint pixel_y, OsmGpsMapPoint *pt) { OsmGpsMapPrivate *priv; int map_x0, map_y0; g_return_if_fail (OSM_IS_GPS_MAP (map)); g_return_if_fail (pt); priv = map->priv; map_x0 = priv->map_x - EXTRA_BORDER; map_y0 = priv->map_y - EXTRA_BORDER; pt->rlat = pixel2lat(priv->map_zoom, map_y0 + pixel_y); pt->rlon = pixel2lon(priv->map_zoom, map_x0 + pixel_x); } /** * osm_gps_map_convert_geographic_to_screen: * @map: * @pt: location * @pixel_x: (out): pixel location on map, x axis * @pixel_y: (out): pixel location on map, y axis * * Convert the given location on the globe to the corresponding * pixel locations on the map. * * Since: 0.7.0 **/ void osm_gps_map_convert_geographic_to_screen(OsmGpsMap *map, OsmGpsMapPoint *pt, gint *pixel_x, gint *pixel_y) { OsmGpsMapPrivate *priv; int map_x0, map_y0; g_return_if_fail (OSM_IS_GPS_MAP (map)); g_return_if_fail (pt); priv = map->priv; map_x0 = priv->map_x - EXTRA_BORDER; map_y0 = priv->map_y - EXTRA_BORDER; if (pixel_x) *pixel_x = lon2pixel(priv->map_zoom, pt->rlon) - map_x0 + priv->drag_mouse_dx; if (pixel_y) *pixel_y = lat2pixel(priv->map_zoom, pt->rlat) - map_y0 + priv->drag_mouse_dy; } /** * osm_gps_map_get_event_location: * @map: * @event: A #GtkEventButton that occured on the map * * A convenience function for getting the geographic location of events, * such as mouse clicks, on the map * * Returns: (transfer full): The point on the globe corresponding to the click * Since: 0.7.0 **/ OsmGpsMapPoint * osm_gps_map_get_event_location (OsmGpsMap *map, GdkEventButton *event) { OsmGpsMapPoint *p = osm_gps_map_point_new_degrees(0.0,0.0); osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, p); return p; } osm-gps-map-1.1.0/src/osm-gps-map-widget.h000066400000000000000000000145761262345173300202550ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * Copyright (C) Marcus Bauer 2008 * Copyright (C) Till Harbaum 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_WIDGET_H_ #define _OSM_GPS_MAP_WIDGET_H_ #include #include #include #include #include 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; #include "osm-gps-map-layer.h" #include "osm-gps-map-point.h" #include "osm-gps-map-track.h" #include "osm-gps-map-polygon.h" #include "osm-gps-map-image.h" struct _OsmGpsMapClass { GtkDrawingAreaClass parent_class; void (*draw_gps_point) (OsmGpsMap *map, cairo_t *cr); }; struct _OsmGpsMap { GtkDrawingArea parent_instance; OsmGpsMapPrivate *priv; }; typedef enum { OSM_GPS_MAP_KEY_FULLSCREEN, OSM_GPS_MAP_KEY_ZOOMIN, OSM_GPS_MAP_KEY_ZOOMOUT, OSM_GPS_MAP_KEY_UP, OSM_GPS_MAP_KEY_DOWN, OSM_GPS_MAP_KEY_LEFT, OSM_GPS_MAP_KEY_RIGHT, OSM_GPS_MAP_KEY_MAX } OsmGpsMapKey_t; #define OSM_GPS_MAP_INVALID (0.0/0.0) #define OSM_GPS_MAP_CACHE_DISABLED "none://" #define OSM_GPS_MAP_CACHE_AUTO "auto://" #define OSM_GPS_MAP_CACHE_FRIENDLY "friendly://" GType osm_gps_map_get_type (void) G_GNUC_CONST; GtkWidget* osm_gps_map_new (void); gchar* osm_gps_map_get_default_cache_directory (void); void osm_gps_map_download_maps (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2, int zoom_start, int zoom_end); void osm_gps_map_download_cancel_all (OsmGpsMap *map); void osm_gps_map_get_bbox (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2); void osm_gps_map_zoom_fit_bbox (OsmGpsMap *map, float latitude1, float latitude2, float longitude1, float longitude2); void osm_gps_map_set_center_and_zoom (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_set_zoom_offset (OsmGpsMap *map, int zoom_offset); int osm_gps_map_zoom_in (OsmGpsMap *map); int osm_gps_map_zoom_out (OsmGpsMap *map); void osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy); float osm_gps_map_get_scale (OsmGpsMap *map); void osm_gps_map_set_keyboard_shortcut (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval); void osm_gps_map_track_add (OsmGpsMap *map, OsmGpsMapTrack *track); void osm_gps_map_track_remove_all (OsmGpsMap *map); gboolean osm_gps_map_track_remove (OsmGpsMap *map, OsmGpsMapTrack *track); void osm_gps_map_polygon_add (OsmGpsMap *map, OsmGpsMapPolygon *poly); void osm_gps_map_polygon_remove_all (OsmGpsMap *map); gboolean osm_gps_map_polygon_remove (OsmGpsMap *map, OsmGpsMapPolygon *poly); void osm_gps_map_gps_add (OsmGpsMap *map, float latitude, float longitude, float heading); void osm_gps_map_gps_clear (OsmGpsMap *map); OsmGpsMapTrack *osm_gps_map_gps_get_track (OsmGpsMap *map); OsmGpsMapImage *osm_gps_map_image_add (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image); OsmGpsMapImage *osm_gps_map_image_add_z (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, gint zorder); OsmGpsMapImage *osm_gps_map_image_add_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign); OsmGpsMapImage *osm_gps_map_image_add_with_alignment_z (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign, gint zorder); gboolean osm_gps_map_image_remove (OsmGpsMap *map, OsmGpsMapImage *image); void osm_gps_map_image_remove_all (OsmGpsMap *map); void osm_gps_map_layer_add (OsmGpsMap *map, OsmGpsMapLayer *layer); gboolean osm_gps_map_layer_remove (OsmGpsMap *map, OsmGpsMapLayer *layer); void osm_gps_map_layer_remove_all (OsmGpsMap *map); void osm_gps_map_convert_screen_to_geographic(OsmGpsMap *map, gint pixel_x, gint pixel_y, OsmGpsMapPoint *pt); void osm_gps_map_convert_geographic_to_screen(OsmGpsMap *map, OsmGpsMapPoint *pt, gint *pixel_x, gint *pixel_y); OsmGpsMapPoint *osm_gps_map_get_event_location (OsmGpsMap *map, GdkEventButton *event); gboolean osm_gps_map_map_redraw (OsmGpsMap *map); void osm_gps_map_map_redraw_idle (OsmGpsMap *map); G_END_DECLS #endif /* _OSM_GPS_MAP_WIDGET_H_ */ osm-gps-map-1.1.0/src/osm-gps-map.h000066400000000000000000000021771262345173300167660ustar00rootroot00000000000000/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ /* vim:set et sw=4 ts=4 */ /* * Copyright (C) 2013 John Stowers * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _OSM_GPS_MAP_H_ #define _OSM_GPS_MAP_H_ #include #include #include #include #include #include #include #include #endif /* _OSM_GPS_MAP_H_ */ osm-gps-map-1.1.0/src/private.h000066400000000000000000000035271262345173300163000ustar00rootroot00000000000000/* * Copyright (C) Marcus Bauer 2008 * Copyright (C) John Stowers 2013 * * Contributions by * Everaldo Canuto 2009 * * This program 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU 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 . */ #ifndef _PRIVATE_H_ #define _PRIVATE_H_ #include #include #include #include "osm-gps-map-widget.h" #define TILESIZE 256 #define MAX_ZOOM 20 #define MIN_ZOOM 0 #define MAX_TILE_ZOOM_OFFSET 10 #define MIN_TILE_ZOOM_OFFSET 0 #define OSM_REPO_URI "http://tile.openstreetmap.org/#Z/#X/#Y.png" #define OSM_MIN_ZOOM 1 #define OSM_MAX_ZOOM 18 #define OSM_IMAGE_FORMAT "png" #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) /* equatorial radius in meters */ #define OSM_EQ_RADIUS (6378137.0) #endif /* _PRIVATE_H_ */ osm-gps-map-1.1.0/uncrustify.cfg000066400000000000000000001434631262345173300165660ustar00rootroot00000000000000# Uncrustify 0.52 # # General options # # The type of line endings newlines = lf # auto/lf/crlf/cr # The original size of tabs in the input input_tab_size = 4 # number # The size of tabs in the output (only used if align_with_tabs=true) output_tab_size = 4 # number # The ascii value of the string escape char, usually 92 (\) or 94 (^). (Pawn) string_escape_char = 92 # number # Alternate string escape char for Pawn. Only works right before the quote char. string_escape_char2 = 0 # number # # Indenting # # The number of columns to indent per level. # Usually 2, 3, 4, or 8. indent_columns = 4 # number # How to use tabs when indenting code # 0=spaces only # 1=indent with tabs, align with spaces # 2=indent and align with tabs indent_with_tabs = 0 # number # Whether to indent strings broken by '\' so that they line up indent_align_string = false # false/true # The number of spaces to indent multi-line XML strings. # Requires indent_align_string=True indent_xml_string = 0 # number # Spaces to indent '{' from level indent_brace = 0 # number # Whether braces are indented to the body level indent_braces = false # false/true # Disabled indenting function braces if indent_braces is true indent_braces_no_func = false # false/true # Indent based on the size of the brace parent, ie 'if' => 3 spaces, 'for' => 4 spaces, etc. indent_brace_parent = false # false/true # Whether the 'namespace' body is indented indent_namespace = false # false/true # Whether the 'extern "C"' body is indented indent_extern = false # false/true # Whether the 'class' body is indented indent_class = false # false/true # Whether to indent the stuff after a leading class colon indent_class_colon = false # false/true # False=treat 'else\nif' as 'else if' for indenting purposes # True=indent the 'if' one level indent_else_if = false # false/true # Amount to indent variable declarations after a open brace. neg=relative, pos=absolute indent_var_def_blk = 0 # number # True: indent continued function call parameters one indent level # False: align parameters under the open paren indent_func_call_param = false # false/true # Same as indent_func_call_param, but for function defs indent_func_def_param = false # false/true # Same as indent_func_call_param, but for function protos indent_func_proto_param = false # false/true # Same as indent_func_call_param, but for class declarations indent_func_class_param = false # false/true # Same as indent_func_call_param, but for class variable constructors indent_func_ctor_var_param = false # false/true # Same as indent_func_call_param, but for templates indent_template_param = false # false/true # Double the indent for indent_func_xxx_param options indent_func_param_double = false # false/true # Indentation column for standalone 'const' function decl/proto qualifier indent_func_const = 0 # number # Indentation column for standalone 'throw' function decl/proto qualifier indent_func_throw = 0 # number # The number of spaces to indent a continued '->' or '.' # Usually set to 0, 1, or indent_columns. indent_member = 0 # number # Spaces to indent single line ('//') comments on lines before code indent_sing_line_comments = 0 # number # If set, will indent trailing single line ('//') comments relative # to the code instead of trying to keep the same absolute column indent_relative_single_line_comments = false # false/true # Spaces to indent 'case' from 'switch' # Usually 0 or indent_columns. indent_switch_case = 4 # number # Spaces to shift the 'case' line, without affecting any other lines # Usually 0. indent_case_shift = 0 # number # Spaces to indent '{' from 'case'. # By default, the brace will appear under the 'c' in case. # Usually set to 0 or indent_columns. indent_case_brace = 0 # number # Whether to indent comments found in first column indent_col1_comment = false # false/true # How to indent goto labels # >0 : absolute column where 1 is the leftmost column # <=0 : subtract from brace indent indent_label = 1 # number # Same as indent_label, but for access specifiers that are followed by a colon indent_access_spec = 1 # number # Indent the code after an access specifier by one level. # If set, this option forces 'indent_access_spec=0' indent_access_spec_body = false # false/true # If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended) indent_paren_nl = false # false/true # Controls the indent of a close paren after a newline. # 0: Indent to body level # 1: Align under the open paren # 2: Indent to the brace level indent_paren_close = 0 # number # Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren indent_comma_paren = false # false/true # Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren indent_bool_paren = false # false/true # If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended) indent_square_nl = false # false/true # Don't change the relative indent of ESQL/C 'EXEC SQL' bodies indent_preserve_sql = false # false/true # Align continued statements at the '='. Default=True # If FALSE or the '=' is followed by a newline, the next line is indent one tab. indent_align_assign = true # false/true # # Spacing options # # Add or remove space around arithmetic operator '+', '-', '/', '*', etc sp_arith = ignore # ignore/add/remove/force # Add or remove space around assignment operator '=', '+=', etc sp_assign = ignore # ignore/add/remove/force # Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. sp_before_assign = ignore # ignore/add/remove/force # Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. sp_after_assign = ignore # ignore/add/remove/force # Add or remove space around assignment '=' in enum sp_enum_assign = ignore # ignore/add/remove/force # Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. sp_enum_before_assign = ignore # ignore/add/remove/force # Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. sp_enum_after_assign = ignore # ignore/add/remove/force # Add or remove space around boolean operators '&&' and '||' sp_bool = ignore # ignore/add/remove/force # Add or remove space around compare operator '<', '>', '==', etc sp_compare = ignore # ignore/add/remove/force # Add or remove space inside '(' and ')' sp_inside_paren = ignore # ignore/add/remove/force # Add or remove space between nested parens sp_paren_paren = ignore # ignore/add/remove/force # Whether to balance spaces inside nested parens sp_balance_nested_parens = false # false/true # Add or remove space between ')' and '{' sp_paren_brace = ignore # ignore/add/remove/force # Add or remove space before pointer star '*' sp_before_ptr_star = ignore # ignore/add/remove/force # Add or remove space before pointer star '*' that isn't followed by a variable name # If set to 'ignore', sp_before_ptr_star is used instead. sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force # Add or remove space between pointer stars '*' sp_between_ptr_star = ignore # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a word. sp_after_ptr_star = ignore # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by a func proto/def. sp_after_ptr_star_func = ignore # ignore/add/remove/force # Add or remove space before a pointer star '*', if followed by a func proto/def. sp_before_ptr_star_func = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&' sp_before_byref = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&' that isn't followed by a variable name # If set to 'ignore', sp_before_byref is used instead. sp_before_unnamed_byref = ignore # ignore/add/remove/force # Add or remove space after reference sign '&', if followed by a word. sp_after_byref = ignore # ignore/add/remove/force # Add or remove space after a reference sign '&', if followed by a func proto/def. sp_after_byref_func = ignore # ignore/add/remove/force # Add or remove space before a reference sign '&', if followed by a func proto/def. sp_before_byref_func = ignore # ignore/add/remove/force # Add or remove space between type and word sp_after_type = force # ignore/add/remove/force # Add or remove space in 'template <' vs 'template<'. # If set to ignore, sp_before_angle is used. sp_template_angle = ignore # ignore/add/remove/force # Add or remove space before '<>' sp_before_angle = ignore # ignore/add/remove/force # Add or remove space inside '<' and '>' sp_inside_angle = ignore # ignore/add/remove/force # Add or remove space after '<>' sp_after_angle = ignore # ignore/add/remove/force # Add or remove space between '<>' and '(' as found in 'new List();' sp_angle_paren = ignore # ignore/add/remove/force # Add or remove space between '<>' and a word as in 'List m;' sp_angle_word = ignore # ignore/add/remove/force # Add or remove space before '(' of 'if', 'for', 'switch', and 'while' sp_before_sparen = force # ignore/add/remove/force # Add or remove space inside if-condition '(' and ')' sp_inside_sparen = ignore # ignore/add/remove/force # Add or remove space before if-condition ')'. Overrides sp_inside_sparen. sp_inside_sparen_close = ignore # ignore/add/remove/force # Add or remove space after ')' of 'if', 'for', 'switch', and 'while' sp_after_sparen = ignore # ignore/add/remove/force # Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while' sp_sparen_brace = ignore # ignore/add/remove/force # Add or remove space between 'invariant' and '(' in the D language. sp_invariant_paren = ignore # ignore/add/remove/force # Add or remove space after the ')' in 'invariant (C) c' in the D language. sp_after_invariant_paren = ignore # ignore/add/remove/force # Add or remove space before empty statement ';' on 'if', 'for' and 'while' sp_special_semi = ignore # ignore/add/remove/force # Add or remove space before ';' sp_before_semi = ignore # ignore/add/remove/force # Add or remove space before ';' in non-empty 'for' statements sp_before_semi_for = ignore # ignore/add/remove/force # Add or remove space before a semicolon of an empty part of a for statment. sp_before_semi_for_empty = ignore # ignore/add/remove/force # Add or remove space after the final semicolon of an empty part of a for statment: for ( ; ; ). sp_after_semi_for_empty = ignore # ignore/add/remove/force # Add or remove space before '[' (except '[]') sp_before_square = ignore # ignore/add/remove/force # Add or remove space before '[]' sp_before_squares = ignore # ignore/add/remove/force # Add or remove space inside '[' and ']' sp_inside_square = ignore # ignore/add/remove/force # Add or remove space after ',' sp_after_comma = ignore # ignore/add/remove/force # Add or remove space before ',' sp_before_comma = remove # ignore/add/remove/force # Add or remove space after class ':' sp_after_class_colon = ignore # ignore/add/remove/force # Add or remove space before class ':' sp_before_class_colon = ignore # ignore/add/remove/force # Add or remove space before case ':' sp_before_case_colon = remove # ignore/add/remove/force # Add or remove space between 'operator' and operator sign sp_after_operator = ignore # ignore/add/remove/force # Add or remove space between the operator symbol and the open paren, as in 'operator ++(' sp_after_operator_sym = ignore # ignore/add/remove/force # Add or remove space after C/D cast, ie 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a' sp_after_cast = ignore # ignore/add/remove/force # Add or remove spaces inside cast parens sp_inside_paren_cast = ignore # ignore/add/remove/force # Add or remove space between the type and open paren in a C++ cast, ie 'int(exp)' vs 'int (exp)' sp_cpp_cast_paren = ignore # ignore/add/remove/force # Add or remove space between 'sizeof' and '(' sp_sizeof_paren = ignore # ignore/add/remove/force # Add or remove space after the tag keyword (Pawn) sp_after_tag = ignore # ignore/add/remove/force # Add or remove space inside enum '{' and '}' sp_inside_braces_enum = ignore # ignore/add/remove/force # Add or remove space inside struct/union '{' and '}' sp_inside_braces_struct = ignore # ignore/add/remove/force # Add or remove space inside '{' and '}' sp_inside_braces = ignore # ignore/add/remove/force # Add or remove space inside '{}' sp_inside_braces_empty = ignore # ignore/add/remove/force # Add or remove space between return type and function name # A minimum of 1 is forced except for pointer return types. sp_type_func = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function declaration sp_func_proto_paren = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function definition sp_func_def_paren = ignore # ignore/add/remove/force # Add or remove space inside empty function '()' sp_inside_fparens = ignore # ignore/add/remove/force # Add or remove space inside function '(' and ')' sp_inside_fparen = ignore # ignore/add/remove/force # Add or remove space between ']' and '(' when part of a function call. sp_square_fparen = ignore # ignore/add/remove/force # Add or remove space between ')' and '{' of function sp_fparen_brace = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function calls sp_func_call_paren = ignore # ignore/add/remove/force # Add or remove space between the user function name and '(' on function calls # You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. sp_func_call_user_paren = ignore # ignore/add/remove/force # Add or remove space between a constructor/destructor and the open paren sp_func_class_paren = ignore # ignore/add/remove/force # Add or remove space between 'return' and '(' sp_return_paren = ignore # ignore/add/remove/force # Add or remove space between '__attribute__' and '(' sp_attribute_paren = ignore # ignore/add/remove/force # Add or remove space between 'defined' and '(' in '#if defined (FOO)' sp_defined_paren = ignore # ignore/add/remove/force # Add or remove space between 'throw' and '(' in 'throw (something)' sp_throw_paren = ignore # ignore/add/remove/force # Add or remove space between macro and value sp_macro = ignore # ignore/add/remove/force # Add or remove space between macro function ')' and value sp_macro_func = ignore # ignore/add/remove/force # Add or remove space between 'else' and '{' if on the same line sp_else_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'else' if on the same line sp_brace_else = force # ignore/add/remove/force # Add or remove space between '}' and the name of a typedef on the same line sp_brace_typedef = ignore # ignore/add/remove/force # Add or remove space between 'catch' and '{' if on the same line sp_catch_brace = ignore # ignore/add/remove/force # Add or remove space between '}' and 'catch' if on the same line sp_brace_catch = ignore # ignore/add/remove/force # Add or remove space between 'finally' and '{' if on the same line sp_finally_brace = ignore # ignore/add/remove/force # Add or remove space between '}' and 'finally' if on the same line sp_brace_finally = ignore # ignore/add/remove/force # Add or remove space between 'try' and '{' if on the same line sp_try_brace = ignore # ignore/add/remove/force # Add or remove space between get/set and '{' if on the same line sp_getset_brace = ignore # ignore/add/remove/force # Add or remove space before the '::' operator sp_before_dc = ignore # ignore/add/remove/force # Add or remove space after the '::' operator sp_after_dc = ignore # ignore/add/remove/force # Add or remove around the D named array initializer ':' operator sp_d_array_colon = ignore # ignore/add/remove/force # Add or remove space after the '!' (not) operator. sp_not = remove # ignore/add/remove/force # Add or remove space after the '~' (invert) operator. sp_inv = remove # ignore/add/remove/force # Add or remove space after the '&' (address-of) operator. # This does not affect the spacing after a '&' that is part of a type. sp_addr = remove # ignore/add/remove/force # Add or remove space around the '.' or '->' operators sp_member = remove # ignore/add/remove/force # Add or remove space after the '*' (dereference) operator. # This does not affect the spacing after a '*' that is part of a type. sp_deref = remove # ignore/add/remove/force # Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7' sp_sign = remove # ignore/add/remove/force # Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;' sp_incdec = remove # ignore/add/remove/force # Add or remove space before a backslash-newline at the end of a line sp_before_nl_cont = add # ignore/add/remove/force # Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;' sp_after_oc_scope = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '-(int) f:(int) x;' vs '-(int) f: (int) x;' sp_after_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '-(int) f: (int) x;' vs '-(int) f : (int) x;' sp_before_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the colon in message specs # '[object setValue:1];' vs '[object setValue: 1];' sp_after_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space before the colon in message specs # '[object setValue:1];' vs '[object setValue :1];' sp_before_send_oc_colon = ignore # ignore/add/remove/force # Add or remove space after the (type) in message specs # '-(int) f: (int) x;' vs '-(int) f: (int)x;' sp_after_oc_type = ignore # ignore/add/remove/force # Add or remove space around the ':' in 'b ? t : f' sp_cond_colon = ignore # ignore/add/remove/force # Add or remove space around the '?' in 'b ? t : f' sp_cond_question = ignore # ignore/add/remove/force # Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. sp_case_label = ignore # ignore/add/remove/force # Control the space around the D '..' operator. sp_range = ignore # ignore/add/remove/force # Control the space after the opening of a C++ comment '// A' vs '//A' sp_cmt_cpp_start = ignore # ignore/add/remove/force # # Code alignment (not left column spaces/tabs) # # Whether to keep non-indenting tabs align_keep_tabs = false # false/true # Whether to use tabs for alinging align_with_tabs = false # false/true # Whether to bump out to the next tab when aligning align_on_tabstop = false # false/true # Whether to left-align numbers align_number_left = false # false/true # Align variable definitions in prototypes and functions align_func_params = false # false/true # Align parameters in single-line functions that have the same name. # The function names must already be aligned with each other. align_same_func_call_params = false # false/true # The span for aligning variable definitions (0=don't align) align_var_def_span = 0 # number # How to align the star in variable definitions. # 0=Part of the type 'void * foo;' # 1=Part of the variable 'void *foo;' # 2=Dangling 'void *foo;' align_var_def_star_style = 0 # number # How to align the '&' in variable definitions. # 0=Part of the type # 1=Part of the variable # 2=Dangling align_var_def_amp_style = 0 # number # The threshold for aligning variable definitions (0=no limit) align_var_def_thresh = 0 # number # The gap for aligning variable definitions align_var_def_gap = 0 # number # Whether to align the colon in struct bit fields align_var_def_colon = false # false/true # Whether to align inline struct/enum/union variable definitions align_var_def_inline = false # false/true # The span for aligning on '=' in assignments (0=don't align) align_assign_span = 0 # number # The threshold for aligning on '=' in assignments (0=no limit) align_assign_thresh = 0 # number # The span for aligning on '=' in enums (0=don't align) align_enum_equ_span = 0 # number # The threshold for aligning on '=' in enums (0=no limit) align_enum_equ_thresh = 0 # number # The span for aligning struct/union (0=don't align) align_var_struct_span = 0 # number # The threshold for aligning struct/union member definitions (0=no limit) align_var_struct_thresh = 0 # number # The gap for aligning struct/union member definitions align_var_struct_gap = 0 # number # The span for aligning struct initializer values (0=don't align) align_struct_init_span = 0 # number # The minimum space between the type and the synonym of a typedef align_typedef_gap = 0 # number # The span for aligning single-line typedefs (0=don't align) align_typedef_span = 0 # number # How to align typedef'd functions with other typedefs # 0: Don't mix them at all # 1: align the open paren with the types # 2: align the function type name with the other type names align_typedef_func = 0 # number # Controls the positioning of the '*' in typedefs. Just try it. # 0: Align on typdef type, ignore '*' # 1: The '*' is part of type name: typedef int *pint; # 2: The '*' is part of the type, but dangling: typedef int *pint; align_typedef_star_style = 0 # number # Controls the positioning of the '&' in typedefs. Just try it. # 0: Align on typdef type, ignore '&' # 1: The '&' is part of type name: typedef int &pint; # 2: The '&' is part of the type, but dangling: typedef int &pint; align_typedef_amp_style = 0 # number # The span for aligning comments that end lines (0=don't align) align_right_cmt_span = 0 # number # If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment align_right_cmt_mix = false # false/true # If a trailing comment is more than this number of columns away from the text it follows, # it will qualify for being aligned. align_right_cmt_gap = 0 # number # The span for aligning function prototypes (0=don't align) align_func_proto_span = 0 # number # Minimum gap between the return type and the function name. align_func_proto_gap = 0 # number # Align function protos on the 'operator' keyword instead of what follows align_on_operator = false # false/true # Whether to mix aligning prototype and variable declarations. # If true, align_var_def_XXX options are used instead of align_func_proto_XXX options. align_mix_var_proto = false # false/true # Align single-line functions with function prototypes, uses align_func_proto_span align_single_line_func = false # false/true # Aligning the open brace of single-line functions. # Requires align_single_line_func=true, uses align_func_proto_span align_single_line_brace = false # false/true # Gap for align_single_line_brace. align_single_line_brace_gap = 0 # number # The span for aligning ObjC msg spec (0=don't align) align_oc_msg_spec_span = 0 # number # Whether to align macros wrapped with a backslash and a newline. # This will not work right if the macro contains a multi-line comment. align_nl_cont = false # false/true # The minimum space between label and value of a preprocessor define align_pp_define_gap = 0 # number # The span for aligning on '#define' bodies (0=don't align) align_pp_define_span = 0 # number # Align lines that start with '<<' with previous '<<'. Default=true align_left_shift = true # false/true # # Newline adding and removing options # # Whether to collapse empty blocks between '{' and '}' nl_collapse_empty_body = false # false/true # Don't split one-line braced assignments - 'foo_t f = { 1, 2 };' nl_assign_leave_one_liners = false # false/true # Don't split one-line braced statements inside a class xx { } body nl_class_leave_one_liners = false # false/true # Don't split one-line enums: 'enum foo { BAR = 15 };' nl_enum_leave_one_liners = false # false/true # Don't split one-line get or set functions nl_getset_leave_one_liners = false # false/true # Don't split one-line function definitions - 'int foo() { return 0; }' nl_func_leave_one_liners = false # false/true # Don't split one-line if/else statements - 'if(a) b++;' nl_if_leave_one_liners = false # false/true # Add or remove newlines at the start of the file nl_start_of_file = ignore # ignore/add/remove/force # The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force' nl_start_of_file_min = 0 # number # Add or remove newline at the end of the file nl_end_of_file = ignore # ignore/add/remove/force # The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force') nl_end_of_file_min = 0 # number # Add or remove newline between '=' and '{' nl_assign_brace = ignore # ignore/add/remove/force # Add or remove newline between '=' and '[' (D only) nl_assign_square = ignore # ignore/add/remove/force # Add or remove newline after '= [' (D only). Will also affect the newline before the ']' nl_after_square_assign = ignore # ignore/add/remove/force # The number of newlines after a block of variable definitions nl_func_var_def_blk = 0 # number # Add or remove newline between a function call's ')' and '{', as in: # list_for_each(item, &list) { } nl_fcall_brace = ignore # ignore/add/remove/force # Add or remove newline between 'enum' and '{' nl_enum_brace = ignore # ignore/add/remove/force # Add or remove newline between 'struct and '{' nl_struct_brace = ignore # ignore/add/remove/force # Add or remove newline between 'union' and '{' nl_union_brace = ignore # ignore/add/remove/force # Add or remove newline between 'if' and '{' nl_if_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'else' nl_brace_else = remove # ignore/add/remove/force # Add or remove newline between 'else if' and '{' # If set to ignore, nl_if_brace is used instead nl_elseif_brace = remove # ignore/add/remove/force # Add or remove newline between 'else' and '{' nl_else_brace = remove # ignore/add/remove/force # Add or remove newline between 'else' and 'if' nl_else_if = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'finally' nl_brace_finally = ignore # ignore/add/remove/force # Add or remove newline between 'finally' and '{' nl_finally_brace = ignore # ignore/add/remove/force # Add or remove newline between 'try' and '{' nl_try_brace = ignore # ignore/add/remove/force # Add or remove newline between get/set and '{' nl_getset_brace = ignore # ignore/add/remove/force # Add or remove newline between 'for' and '{' nl_for_brace = add # ignore/add/remove/force # Add or remove newline between 'catch' and '{' nl_catch_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'catch' nl_brace_catch = ignore # ignore/add/remove/force # Add or remove newline between 'while' and '{' nl_while_brace = ignore # ignore/add/remove/force # Add or remove newline between 'do' and '{' nl_do_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'while' of 'do' statement nl_brace_while = ignore # ignore/add/remove/force # Add or remove newline between 'switch' and '{' nl_switch_brace = add # ignore/add/remove/force # Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. # Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace. nl_multi_line_cond = false # false/true # Force a newline in a define after the macro name for multi-line defines. nl_multi_line_define = false # false/true # Whether to put a newline before 'case' statement nl_before_case = false # false/true # Add or remove newline between ')' and 'throw' nl_before_throw = ignore # ignore/add/remove/force # Whether to put a newline after 'case' statement nl_after_case = false # false/true # Newline between namespace and { nl_namespace_brace = ignore # ignore/add/remove/force # Add or remove newline between 'template<>' and whatever follows. nl_template_class = ignore # ignore/add/remove/force # Add or remove newline between 'class' and '{' nl_class_brace = ignore # ignore/add/remove/force # Add or remove newline after each ',' in the constructor member initialization nl_class_init_args = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in definition nl_func_type_name = ignore # ignore/add/remove/force # Add or remove newline between function scope and name in a definition # Controls the newline after '::' in 'void A::f() { }' nl_func_scope_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a prototype nl_func_proto_type_name = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' nl_func_paren = ignore # ignore/add/remove/force # Add or remove newline after '(' in a function declaration nl_func_decl_start = ignore # ignore/add/remove/force # Add or remove newline after each ',' in a function declaration nl_func_decl_args = ignore # ignore/add/remove/force # Add or remove newline before the ')' in a function declaration nl_func_decl_end = ignore # ignore/add/remove/force # Add or remove newline between function signature and '{' nl_fdef_brace = ignore # ignore/add/remove/force # Whether to put a newline after 'return' statement nl_after_return = false # false/true # Add or remove a newline between the return keyword and return expression. nl_return_expr = ignore # ignore/add/remove/force # Whether to put a newline after semicolons, except in 'for' statements nl_after_semicolon = false # false/true # Whether to put a newline after brace open. # This also adds a newline before the matching brace close. nl_after_brace_open = false # false/true # If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is # placed between the open brace and a trailing single-line comment. nl_after_brace_open_cmt = false # false/true # Whether to put a newline after a virtual brace open. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open = false # false/true # Whether to put a newline after a brace close. # Does not apply if followed by a necessary ';'. nl_after_brace_close = false # false/true # Whether to alter newlines in '#define' macros nl_define_macro = false # false/true # Whether to not put blanks after '#ifxx', '#elxx', or before '#endif' nl_squeeze_ifdef = false # false/true # Add or remove newline before 'if' nl_before_if = ignore # ignore/add/remove/force # Add or remove newline after 'if' nl_after_if = ignore # ignore/add/remove/force # Add or remove newline before 'for' nl_before_for = ignore # ignore/add/remove/force # Add or remove newline after 'for' nl_after_for = ignore # ignore/add/remove/force # Add or remove newline before 'while' nl_before_while = ignore # ignore/add/remove/force # Add or remove newline after 'while' nl_after_while = ignore # ignore/add/remove/force # Add or remove newline before 'switch' nl_before_switch = ignore # ignore/add/remove/force # Add or remove newline after 'switch' nl_after_switch = ignore # ignore/add/remove/force # Add or remove newline before 'do' nl_before_do = ignore # ignore/add/remove/force # Add or remove newline after 'do' nl_after_do = ignore # ignore/add/remove/force # Whether to double-space commented-entries in struct/enum nl_ds_struct_enum_cmt = false # false/true # Whether to double-space before the close brace of a struct/union/enum nl_ds_struct_enum_close_brace = false # false/true # Add or remove a newline around a class colon. # Related to pos_class_colon, nl_class_init_args, and pos_comma. nl_class_colon = ignore # ignore/add/remove/force # Change simple unbraced if statements into a one-liner # 'if(b)\n i++;' => 'if(b) i++;' nl_create_if_one_liner = false # false/true # Change simple unbraced for statements into a one-liner # 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);' nl_create_for_one_liner = false # false/true # Change simple unbraced while statements into a one-liner # 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' nl_create_while_one_liner = false # false/true # # Positioning options # # The position of arithmetic operators in wrapped expressions pos_arith = ignore # ignore/lead/trail # The position of assignment in wrapped expressions pos_assign = ignore # ignore/lead/trail # The position of boolean operators in wrapped expressions pos_bool = ignore # ignore/lead/trail # The position of the comma in wrapped expressions pos_comma = ignore # ignore/lead/trail # The position of the comma in the constructor initialization list pos_class_comma = ignore # ignore/lead/trail # The position of colons between constructor and member initialization pos_class_colon = ignore # ignore/lead/trail # # Line Splitting options # # Try to limit code width to N number of columns code_width = 0 # number # Whether to fully split long 'for' statements at semi-colons ls_for_split_full = false # false/true # Whether to fully split long function protos/calls at commas ls_func_split_full = false # false/true # # Blank line options # # The maximum consecutive newlines nl_max = 0 # number # The number of newlines after a function prototype, if followed by another function prototype nl_after_func_proto = 0 # number # The number of newlines after a function prototype, if not followed by another function prototype nl_after_func_proto_group = 0 # number # The number of newlines after '}' of a multi-line function body nl_after_func_body = 0 # number # The number of newlines after '}' of a single line function body nl_after_func_body_one_liner = 0 # number # The minimum number of newlines before a multi-line comment. # Doesn't apply if after a brace open or another multi-line comment. nl_before_block_comment = 0 # number # The minimum number of newlines before a single-line C comment. # Doesn't apply if after a brace open or other single-line C comments. nl_before_c_comment = 0 # number # The minimum number of newlines before a CPP comment. # Doesn't apply if after a brace open or other CPP comments. nl_before_cpp_comment = 0 # number # Whether to force a newline after a mulit-line comment. nl_after_multiline_comment = false # false/true # The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. # Will not change the newline count if after a brace open. # 0 = No change. nl_before_access_spec = 0 # number # The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. # 0 = No change. nl_after_access_spec = 0 # number # The number of newlines between a function def and the function comment. # 0 = No change. nl_comment_func_def = 0 # number # The number of newlines after a try-catch-finally block that isn't followed by a brace close. # 0 = No change. nl_after_try_catch_finally = 0 # number # The number of newlines before and after a property, indexer or event decl. # 0 = No change. nl_around_cs_property = 0 # number # The number of newlines between the get/set/add/remove handlers in C#. # 0 = No change. nl_between_get_set = 0 # number # Whether to remove blank lines after '{' eat_blanks_after_open_brace = false # false/true # Whether to remove blank lines before '}' eat_blanks_before_close_brace = false # false/true # # Code modifying options (non-whitespace) # # Add or remove braces on single-line 'do' statement mod_full_brace_do = ignore # ignore/add/remove/force # Add or remove braces on single-line 'for' statement mod_full_brace_for = ignore # ignore/add/remove/force # Add or remove braces on single-line function defintions. (Pawn) mod_full_brace_function = ignore # ignore/add/remove/force # Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. mod_full_brace_if = ignore # ignore/add/remove/force # Don't remove braces around statements that span N newlines mod_full_brace_nl = 0 # number # Add or remove braces on single-line 'while' statement mod_full_brace_while = ignore # ignore/add/remove/force # Add or remove unnecessary paren on 'return' statement mod_paren_on_return = ignore # ignore/add/remove/force # Whether to change optional semicolons to real semicolons mod_pawn_semicolon = false # false/true # Add parens on 'while' and 'if' statement around bools mod_full_paren_if_bool = false # false/true # Whether to remove superfluous semicolons mod_remove_extra_semicolon = false # false/true # If a function body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_function_closebrace_comment = 0 # number # If a switch body exceeds the specified number of newlines and doesn't have a comment after # the close brace, a comment will be added. mod_add_long_switch_closebrace_comment = 0 # number # If TRUE, will sort consecutive single-line 'import' statements [Java, D] mod_sort_import = false # false/true # If TRUE, will sort consecutive single-line 'using' statements [C#] mod_sort_using = false # false/true # If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] # This is generally a bad idea, as it may break your code. mod_sort_include = false # false/true # If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace. mod_move_case_break = false # false/true # If TRUE, it will remove a void 'return;' that appears as the last statement in a function. mod_remove_empty_return = false # false/true # # Comment modifications # # Try to wrap comments at cmt_width columns cmt_width = 0 # number # If false, disable all multi-line comment changes, including cmt_width and leading chars. # Default is true. cmt_indent_multi = true # false/true # Whether to group c-comments that look like they are in a block cmt_c_group = true # false/true # Whether to put an empty '/*' on the first line of the combined c-comment cmt_c_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined c-comment cmt_c_nl_end = false # false/true # Whether to group cpp-comments that look like they are in a block cmt_cpp_group = true # false/true # Whether to put an empty '/*' on the first line of the combined cpp-comment cmt_cpp_nl_start = false # false/true # Whether to put a newline before the closing '*/' of the combined cpp-comment cmt_cpp_nl_end = false # false/true # Whether to change cpp-comments into c-comments cmt_cpp_to_c = true # false/true # Whether to put a star on subsequent comment lines cmt_star_cont = true # false/true # The number of spaces to insert at the start of subsequent comment lines cmt_sp_before_star_cont = 0 # number # The number of spaces to insert after the star on subsequent comment lines cmt_sp_after_star_cont = 0 # number # For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of # the comment are the same length. Default=True cmt_multi_check_last = true # false/true # The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. # Will substitue $(filename) with the current file's name. cmt_insert_file_header = "" # string # The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. # Will substitue $(filename) with the current file's name. cmt_insert_file_footer = "" # string # The filename that contains text to insert before a function implementation if the function isn't preceeded with a C/C++ comment. # Will substitue $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. # Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... } cmt_insert_func_header = "" # string # The filename that contains text to insert before a class if the class isn't preceeded with a C/C++ comment. # Will substitue $(class) with the class name. cmt_insert_class_header = "" # string # If a preprocessor is encountered when stepping backwards from a function name, then # this option decides whether the comment should be inserted. # Affects cmt_insert_func_header and cmt_insert_class_header. cmt_insert_before_preproc = false # false/true # # Preprocessor options # # Control indent of preprocessors inside #if blocks at brace level 0 pp_indent = ignore # ignore/add/remove/force # Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false) pp_indent_at_level = false # false/true # If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1. pp_indent_count = 1 # number # Add or remove space after # based on pp_level of #if blocks pp_space = ignore # ignore/add/remove/force # Sets the number of spaces added with pp_space pp_space_count = 0 # number # The indent for #region and #endregion in C# and '#pragma region' in C/C++ pp_indent_region = 0 # number # Whether to indent the code between #region and #endregion pp_region_indent_code = false # false/true # If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level pp_indent_if = 0 # number # Control whether to indent the code between #if, #else and #endif when not at file-level pp_if_indent_code = false # false/true # Whether to indent '#define' at the brace level (true) or from column 1 (false) pp_define_at_level = false # false/true # You can force a token to be a type with the 'type' option. # Example: # type myfoo1 myfoo2 # # You can create custom macro-based indentation using macro-open, # macro-else and macro-close. # Example: # macro-open BEGIN_TEMPLATE_MESSAGE_MAP # macro-open BEGIN_MESSAGE_MAP # macro-close END_MESSAGE_MAP # # You can assign any keyword to any type with the set option. # set func_call_user _ N_