[cairo-commit] roadster/src Makefile.am, 1.16, 1.17 animator.c, 1.4, 1.5 databasewindow.c, 1.6, NONE databasewindow.h, 1.3, NONE datasetwindow.c, 1.6, NONE datasetwindow.h, 1.2, NONE db.c, 1.22, 1.23 gpsclient.c, 1.9, 1.10 gui.c, 1.9, 1.10 history.c, 1.2, 1.3 import_tiger.c, 1.16, 1.17 layers.c, 1.14, 1.15 main.c, 1.21, 1.22 mainwindow.c, 1.37, 1.38 map.c, 1.40, 1.41 map.h, 1.17, 1.18 map_draw_cairo.c, 1.18, 1.19 map_draw_gdk.c, 1.14, 1.15 point.c, 1.4, 1.5 pointstring.c, 1.5, 1.6 prefs.c, 1.2, 1.3 road.c, 1.3, 1.4 scenemanager.c, 1.10, 1.11 search_road.c, 1.19, 1.20 searchwindow.c, 1.18, 1.19 tooltip.c, 1.3, 1.4 util.c, 1.6, 1.7

Ian McIntosh commit at pdx.freedesktop.org
Mon Aug 29 08:23:17 EST 2005


Committed by: ian

Update of /cvs/cairo/roadster/src
In directory gabe:/tmp/cvs-serv9792/src

Modified Files:
	Makefile.am animator.c db.c gpsclient.c gui.c history.c 
	import_tiger.c layers.c main.c mainwindow.c map.c map.h 
	map_draw_cairo.c map_draw_gdk.c point.c pointstring.c prefs.c 
	road.c scenemanager.c search_road.c searchwindow.c tooltip.c 
	util.c 
Removed Files:
	databasewindow.c databasewindow.h datasetwindow.c 
	datasetwindow.h 
Log Message:
        data/roadster.glade: UI cleanup.  Moved many items into a 'Debug' menu.
        src/gpsclient.c: Update to newest gpsd lib.
        src/db.c: Format coordinates using g_ascii_dtostr to avoid i18n.
        src/mainwindow.c: Add GTK About dialog.
        src/map.c: Back to GDK rendering as default (not fast enough without hardware 
accel.).  Use g_ascii_dtostr.  Add hack to turn circular rivers into lakes.
        src/map_draw_cairo.c: Update to Cairo 1.0.  Add hack to round text rotation 
angles down to better utilize font cache (which isn't in 1.0 yet).
        src/pointstring.c:
        src/point.c: Add debugging function.
        src/search_road.c: Move function to util.c
        src/searchwindow.c: Remove unused variables.
        src/util.c: Added util_split_words_onto_two_lines(), currently unused.


Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/roadster/src/Makefile.am,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- Makefile.am	23 Mar 2005 09:21:49 -0000	1.16
+++ Makefile.am	28 Aug 2005 22:23:14 -0000	1.17
@@ -29,7 +29,6 @@
 	import_tiger.c\
 	importwindow.c\
 	util.c\
-	datasetwindow.c\
 	welcomewindow.c\
 	gpsclient.c\
 	location.c\
@@ -39,7 +38,6 @@
 	search_location.c\
 	search.c\
 	scenemanager.c\
-	databasewindow.c\
 	point.c\
 	pointstring.c\
 	track.c\

Index: animator.c
===================================================================
RCS file: /cvs/cairo/roadster/src/animator.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- animator.c	1 Apr 2005 09:53:49 -0000	1.4
+++ animator.c	28 Aug 2005 22:23:14 -0000	1.5
@@ -40,13 +40,13 @@
 {
 	g_assert(fAnimationTimeInSeconds > 0.0);
 
-        animator_t* pNew = g_new0(animator_t, 1);
-
-        pNew->m_pTimer = g_timer_new();
-        pNew->m_eAnimationType = eAnimationType;
-        pNew->m_fAnimationTimeInSeconds = fAnimationTimeInSeconds;
-
-        return pNew;
+	animator_t* pNew = g_new0(animator_t, 1);
+	
+	pNew->m_pTimer = g_timer_new();
+	pNew->m_eAnimationType = eAnimationType;
+	pNew->m_fAnimationTimeInSeconds = fAnimationTimeInSeconds;
+	
+	return pNew;
 }
 
 void animator_destroy(animator_t* pAnimator)
@@ -60,17 +60,17 @@
 
 gboolean animator_is_done(animator_t* pAnimator)
 {
-        g_assert(pAnimator != NULL);
+	g_assert(pAnimator != NULL);
 
-        gdouble fElapsedSeconds = g_timer_elapsed(pAnimator->m_pTimer, NULL);
-        return (fElapsedSeconds >= pAnimator->m_fAnimationTimeInSeconds);
+	gdouble fElapsedSeconds = g_timer_elapsed(pAnimator->m_pTimer, NULL);
+	return (fElapsedSeconds >= pAnimator->m_fAnimationTimeInSeconds);
 }
 
 gdouble animator_get_time_percent(animator_t* pAnimator)
 {
-        g_assert(pAnimator != NULL);
+	g_assert(pAnimator != NULL);
 
-        gdouble fElapsedSeconds = g_timer_elapsed(pAnimator->m_pTimer, NULL);
+	gdouble fElapsedSeconds = g_timer_elapsed(pAnimator->m_pTimer, NULL);
 
 	// Cap at 1.0
 	if(fElapsedSeconds >= pAnimator->m_fAnimationTimeInSeconds) {
@@ -82,7 +82,7 @@
 // returns a floating point 0.0 to 1.0
 gdouble animator_get_progress(animator_t* pAnimator)
 {
-        g_assert(pAnimator != NULL);
+	g_assert(pAnimator != NULL);
 
 	gdouble fTimePercent = animator_get_time_percent(pAnimator);
  

--- databasewindow.c DELETED ---

--- databasewindow.h DELETED ---

--- datasetwindow.c DELETED ---

--- datasetwindow.h DELETED ---

Index: db.c
===================================================================
RCS file: /cvs/cairo/roadster/src/db.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- db.c	23 Apr 2005 18:13:39 -0000	1.22
+++ db.c	28 Aug 2005 22:23:14 -0000	1.23
@@ -292,8 +292,10 @@
 		mappoint_t* pPoint = g_ptr_array_index(pPointsArray, i);
 
 		gchar azNewest[40];
-		if(nCount > 0) g_snprintf(azNewest, 40, ",%f %f", pPoint->m_fLatitude, pPoint->m_fLongitude);
-		else g_snprintf(azNewest, 40, "%f %f", pPoint->m_fLatitude, pPoint->m_fLongitude);
+
+		gchar azCoord1[20], azCoord2[20];
+		if(nCount > 0) g_snprintf(azNewest, 40, ",%s %s", g_ascii_dtostr(azCoord1, 20, pPoint->m_fLatitude), g_ascii_dtostr(azCoord2, 20, pPoint->m_fLongitude));
+		else g_snprintf(azNewest, 40, "%s %s", g_ascii_dtostr(azCoord1, 20, pPoint->m_fLatitude), g_ascii_dtostr(azCoord2, 20, pPoint->m_fLongitude));
 
 		g_strlcat(azCoordinateList, azNewest, COORD_LIST_MAX);
 		nCount++;
@@ -503,11 +505,14 @@
 	gint nByteOrder = *data++;	// first byte tells us the byte order
 	g_assert(nByteOrder == 1);
 
-	gint nGeometryType = *((gint32*)data)++;
+	gint nGeometryType = *((gint32*)data);
+	data += sizeof(gint32);
 	g_assert(nGeometryType == WKB_POINT);
 
-	pPoint->m_fLatitude = *((double*)data)++;
-	pPoint->m_fLongitude = *((double*)data)++;
+	pPoint->m_fLatitude = *((double*)data);
+	data += sizeof(double);
+	pPoint->m_fLongitude = *((double*)data);
+	data += sizeof(double);
 }
 
 void db_parse_wkb_linestring(const gint8* data, GPtrArray* pPointsArray, gboolean (*callback_alloc_point)(mappoint_t**))
@@ -517,17 +522,21 @@
 	gint nByteOrder = *data++;	// first byte tells us the byte order
 	g_assert(nByteOrder == 1);
 
-	gint nGeometryType = *((gint32*)data)++;
+	gint nGeometryType = *((gint32*)data);
+	data += sizeof(gint32);
 	g_assert(nGeometryType == WKB_LINESTRING);
 
-	gint nNumPoints = *((gint32*)data)++;	// NOTE for later: this field doesn't exist for type POINT
+	gint nNumPoints = *((gint32*)data);	// NOTE for later: this field doesn't exist for type POINT
+	data += sizeof(gint32);
 
 	while(nNumPoints > 0) {
 		mappoint_t* pPoint = NULL;
 		if(!callback_alloc_point(&pPoint)) return;
 
-		pPoint->m_fLatitude = *((double*)data)++;
-		pPoint->m_fLongitude = *((double*)data)++;
+		pPoint->m_fLatitude = *((double*)data);
+		data += sizeof(double);
+		pPoint->m_fLongitude = *((double*)data);
+		data += sizeof(double);
 
 		g_ptr_array_add(pPointsArray, pPoint);
 

Index: gpsclient.c
===================================================================
RCS file: /cvs/cairo/roadster/src/gpsclient.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- gpsclient.c	28 Mar 2005 18:49:50 -0000	1.9
+++ gpsclient.c	28 Aug 2005 22:23:14 -0000	1.10
@@ -22,7 +22,7 @@
  */
 
 #include <gtk/gtk.h>
-#include <gps.h>	// gpslib
+#include <gps.h>
 #include "main.h"
 #include "gpsclient.h"
 
@@ -41,13 +41,6 @@
 	gpsclient_connect();
 }
 
-// static void gpsclient_callback_raw_data(char* p)
-// {
-//         // g_print("raw: %s\n", p);
-// }
-
-// void gpsclient_debug_print(void);
-
 static void gpsclient_connect(void)
 {
 	// don't do anything if already connected
@@ -111,8 +104,8 @@
 			if(d->status != STATUS_NO_FIX) {
 				// a GPS device is present and working!
 				l->m_eStatus = GPS_STATUS_LIVE;
-				l->m_ptPosition.m_fLatitude = d->latitude;
-				l->m_ptPosition.m_fLongitude= d->longitude;
+				l->m_ptPosition.m_fLatitude = d->fix.latitude;
+				l->m_ptPosition.m_fLongitude= d->fix.longitude;
 				if(d->pdop < PDOP_EXCELLENT) {
 					l->m_fSignalQuality = GPS_SIGNALQUALITY_5_EXCELLENT;
 				}
@@ -130,8 +123,8 @@
 				}
 
 				// Set speed
-				l->m_fSpeedInKilometersPerHour = (d->speed * KNOTS_TO_KPH);
-				l->m_fSpeedInMilesPerHour = (d->speed * KNOTS_TO_MPH);
+				l->m_fSpeedInKilometersPerHour = (d->fix.speed * KNOTS_TO_KPH);
+				l->m_fSpeedInMilesPerHour = (d->fix.speed * KNOTS_TO_MPH);
 
 				// Dampen Noise when not moving fast enough for trustworthy data
 				if(l->m_fSignalQuality <= GPS_SIGNALQUALITY_2_POOR &&

Index: gui.c
===================================================================
RCS file: /cvs/cairo/roadster/src/gui.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- gui.c	23 Apr 2005 18:13:39 -0000	1.9
+++ gui.c	28 Aug 2005 22:23:14 -0000	1.10
@@ -34,7 +34,6 @@
 #include "mainwindow.h"
 #include "gotowindow.h"
 #include "importwindow.h"
-#include "datasetwindow.h"
 #include "welcomewindow.h"
 #include "searchwindow.h"
 
@@ -48,7 +47,7 @@
 	searchwindow_init(pGladeXML);
 	gotowindow_init(pGladeXML);
 	importwindow_init(pGladeXML);
-	datasetwindow_init(pGladeXML);
+	//datasetwindow_init(pGladeXML);
 	welcomewindow_init(pGladeXML);
 }
 

Index: history.c
===================================================================
RCS file: /cvs/cairo/roadster/src/history.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- history.c	28 Mar 2005 18:49:50 -0000	1.2
+++ history.c	28 Aug 2005 22:23:14 -0000	1.3
@@ -49,22 +49,24 @@
 	g_assert(pHistory != NULL);
 	g_assert(pPoint != NULL);
 
+	// If user has clicked BACK a few times, we won't be at the last index in the array...
 	if(pHistory->m_nCurrentIndex < (pHistory->m_MapViewArray->len - 1)) {
-		// clear out everything after currentindex in the array!
+		// ...so clear out everything after where we are
 		g_array_remove_range(pHistory->m_MapViewArray, pHistory->m_nCurrentIndex + 1, (pHistory->m_MapViewArray->len - pHistory->m_nCurrentIndex) - 1);
 
-		pHistory->m_nTotalItems = (pHistory->m_nCurrentIndex + 1);
+		pHistory->m_nTotalItems = (pHistory->m_nCurrentIndex + 1);	// +1 to change it from an index to a count, it's NOT for the new item we're adding
 	}
 
 	// Move to next one
 	pHistory->m_nCurrentIndex++;
 
+	// Grow array if necessary
 	if(pHistory->m_nCurrentIndex >= pHistory->m_MapViewArray->len) {
 		// XXX: is this doing a realloc every time?  ouch. :)
 		g_array_set_size(pHistory->m_MapViewArray, pHistory->m_MapViewArray->len + 1);
 	}
 
-	// Get pointer to it
+	// Get pointer to new current index
 	mapview_t* pNew = &g_array_index(pHistory->m_MapViewArray, mapview_t, pHistory->m_nCurrentIndex);
 	g_return_if_fail(pNew != NULL);
 
@@ -73,6 +75,8 @@
 	pNew->m_nZoomLevel = nZoomLevel;
 
 	pHistory->m_nTotalItems++;
+
+	g_assert(pHistory->m_nCurrentIndex < pHistory->m_nTotalItems);
 }
 
 gboolean history_can_go_forward(history_t* pHistory)
@@ -110,7 +114,7 @@
 	g_assert(pHistory->m_nCurrentIndex < pHistory->m_nTotalItems);
 
 	mapview_t* pCurrent = &g_array_index(pHistory->m_MapViewArray, mapview_t, pHistory->m_nCurrentIndex);
-	
+
 	memcpy(pReturnPoint, &(pCurrent->m_MapPoint), sizeof(mappoint_t));
 	*pnReturnZoomLevel  = pCurrent->m_nZoomLevel;
 }

Index: import_tiger.c
===================================================================
RCS file: /cvs/cairo/roadster/src/import_tiger.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- import_tiger.c	28 Mar 2005 18:49:50 -0000	1.16
+++ import_tiger.c	28 Aug 2005 22:23:14 -0000	1.17
@@ -769,6 +769,27 @@
 	}
 	g_ptr_array_add(pTempPointsArray, &pRecordRT1->m_PointB);
 
+	//
+	// Change rivers into lakes if they are circular (why doesn't this work here?)
+	//
+//     if(pRecordRT1->m_nRecordType == LAYER_RIVER) {
+//         if(((gint)(pRecordRT1->m_PointA.m_fLongitude * 1000.0)) == ((gint)(pRecordRT1->m_PointB.m_fLongitude * 1000.0)) &&
+//            ((gint)(pRecordRT1->m_PointA.m_fLatitude * 1000.0)) == ((gint)(pRecordRT1->m_PointB.m_fLatitude * 1000.0)))
+//         {
+//             if(pRecordRT1->m_PointA.m_fLongitude != pRecordRT1->m_PointB.m_fLongitude) {
+//                 g_print("OOPS: %20.20f != %20.20f\n", pRecordRT1->m_PointA.m_fLongitude, pRecordRT1->m_PointB.m_fLongitude);
+//             }
+//             if(pRecordRT1->m_PointA.m_fLatitude != pRecordRT1->m_PointB.m_fLatitude) {
+//                 g_print("OOPS: %20.20f != %20.20f\n", pRecordRT1->m_PointA.m_fLatitude, pRecordRT1->m_PointB.m_fLatitude);
+//             }
+//             g_print("converting circular river to lake: %s\n", pRecordRT1->m_achName);
+//             pRecordRT1->m_nRecordType = LAYER_LAKE;
+//         }
+//         else {
+// //          g_print("NOT converting river: %s (%f != %f)(%f != %f)\n", pRecordRT1->m_achName, pRecordRT1->m_PointA.m_fLongitude, pRecordRT1->m_PointB.m_fLongitude, pRecordRT1->m_PointA.m_fLatitude, pRecordRT1->m_PointB.m_fLatitude);
+//         }
+//     }
+
 	// use RT1's FIPS code to lookup related RTc record, which contains a CityID
 	gint nCityLeftID=0;
 	gint nCityRightID=0;

Index: layers.c
===================================================================
RCS file: /cvs/cairo/roadster/src/layers.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- layers.c	28 Mar 2005 18:49:50 -0000	1.14
+++ layers.c	28 Aug 2005 22:23:14 -0000	1.15
@@ -77,7 +77,6 @@
 	LIBXML_TEST_VERSION
 
 	layers_load_from_file();
-
 }
 
 void
@@ -362,4 +361,3 @@
 {
 	printf("color: %3.2f, %3.2f, %3.2f, %3.2f\n", color->m_fRed, color->m_fGreen, color->m_fBlue, color->m_fAlpha);
 }
-

Index: main.c
===================================================================
RCS file: /cvs/cairo/roadster/src/main.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- main.c	23 Apr 2005 18:13:39 -0000	1.21
+++ main.c	28 Aug 2005 22:23:14 -0000	1.22
@@ -79,6 +79,7 @@
 	prefs_read();
 
 	g_print("Running %s\n", g_thread_supported() ? "multi-threaded" : "single-threaded");
+
 	gui_run();
 	main_deinit();
 
@@ -141,7 +142,7 @@
 	g_print("creating database tables\n");
 	db_create_tables();
 
-	// Load sets from DB
+	// Load location sets from DB.  This is "coffee shops", "ATMs", etc.
 	locationset_load_locationsets();
 
 	g_print("initializing gui\n");
@@ -154,7 +155,7 @@
 
 static void main_deinit(void)
 {
-	g_print("deinitializating database\n");
+	g_print("deinitializing database\n");
 	db_deinit();
 	// others?
 

Index: mainwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/mainwindow.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- mainwindow.c	23 Apr 2005 18:13:39 -0000	1.37
+++ mainwindow.c	28 Aug 2005 22:23:14 -0000	1.38
@@ -37,11 +37,9 @@
 #include "map.h"
 #include "layers.h"
 #include "importwindow.h"
-#include "datasetwindow.h"
 #include "welcomewindow.h"
 #include "locationset.h"
 #include "gpsclient.h"
-#include "databasewindow.h"
 #include "mainwindow.h"
 #include "glyph.h"
 #include "animator.h"
@@ -59,6 +57,7 @@
 #define PROGRAM_NAME			"Roadster"
 #define PROGRAM_COPYRIGHT		"Copyright (c) 2005 Ian McIntosh"
 #define PROGRAM_DESCRIPTION		"Mapping for everyone!"
+#define WEBSITE_URL				"http://linuxadvocate.org/projects/roadster"
 
 // how long after stopping various movements should we redraw in high-quality mode
 #define DRAW_PRETTY_SCROLL_TIMEOUT_MS	(110)	// NOTE: should be longer than the SCROLL_TIMEOUT_MS below!!
@@ -71,7 +70,7 @@
 #define BORDER_SCROLL_CLICK_TARGET_SIZE	(20)		// the size of the click target (distance from edge of map view) to begin scrolling
 
 #define SLIDE_TIMEOUT_MS		(50)	// time between frames (in MS) for smooth-sliding (on double click?)
-#define	SLIDE_TIME_IN_SECONDS		(0.7)	// how long the whole slide should take, in seconds
+#define	SLIDE_TIME_IN_SECONDS		(0.4)	// how long the whole slide should take, in seconds
 #define	SLIDE_TIME_IN_SECONDS_AUTO	(0.8)	// time for sliding to search results, etc.
 
 // Layerlist columns
@@ -690,6 +689,20 @@
 	gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.m_pDrawingArea)->window, g_Tools[eTool].m_Cursor.m_pGdkCursor);
 }
 
+void callback_url_clicked(GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+	g_print("opening URL: %s\n", link);
+	util_open_uri(link);
+}
+
+void callback_email_clicked(GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+	gchar* pszURI = g_strdup_printf("mailto:%s", link);
+	util_open_uri(pszURI);
+	g_free(pszURI);
+
+}
+
 void mainwindow_on_aboutmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
 #if(GLIB_CHECK_VERSION(2,6,0))
@@ -699,13 +712,39 @@
                  NULL
          };
 
-         gtk_show_about_dialog(g_MainWindow.m_pWindow,
-			       "authors", ppAuthors,
+         const gchar *ppArtists[] = {
+				"Stephen DesRoches <stephen at silverorange.com>",
+                 NULL
+         };
+
+		 GdkPixbuf* pIconPixbuf;
+		 gchar* pszPath;
+
+		 pszPath = g_strdup_printf(PACKAGE_SOURCE_DIR"/data/%s", "roadster-logo.png");
+		 pIconPixbuf = gdk_pixbuf_new_from_file(pszPath, NULL);
+		 g_free(pszPath);
+
+		 if(pIconPixbuf == NULL) {
+			 pszPath = g_strdup_printf(PACKAGE_DATA_DIR"/data/%s", "roadster-logo.png");
+			 pIconPixbuf = gdk_pixbuf_new_from_file(pszPath, NULL);
+			 g_free(pszPath);
+		 }
+
+         gtk_about_dialog_set_url_hook(callback_url_clicked, NULL, NULL);
+         gtk_about_dialog_set_email_hook(callback_email_clicked, NULL, NULL);
+		 gtk_show_about_dialog(g_MainWindow.m_pWindow,
+				   "authors", ppAuthors,
+			       "artists", ppArtists,
 			       "comments", PROGRAM_DESCRIPTION,
 			       "copyright", PROGRAM_COPYRIGHT,
 			       "name", PROGRAM_NAME,
+				    "website", WEBSITE_URL,
+				   "website-label", "Visit the Roadster Website",
 			       "version", VERSION,
+				   "logo", pIconPixbuf,
 			       NULL);
+
+		 if(pIconPixbuf) g_object_unref(pIconPixbuf);
 #endif
 }
 

Index: map.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- map.c	26 May 2005 20:05:36 -0000	1.40
+++ map.c	28 Aug 2005 22:23:14 -0000	1.41
@@ -22,7 +22,7 @@
  */
 
 #include <gdk/gdkx.h>
-#include <cairo.h>
+//#include <cairo.h>
 #include <gtk/gtk.h>
 #include <math.h>
 
@@ -63,6 +63,9 @@
 
 #define MIN_ZOOMLEVEL_FOR_LOCATIONS	(6)
 
+#define ENABLE_RIVER_TO_LAKE_LOADTIME_HACK	// change circular rivers to lakes when loading from disk
+//#define ENABLE_SCENEMANAGER_DEBUG_TEST
+
 /* Prototypes */
 
 // data loading
@@ -254,30 +257,30 @@
 	map_data_load_tiles(pMap, &(pRenderMetrics->m_rWorldBoundingBox));
 	TIMER_END(loadtimer, "--- END ALL DB LOAD");
 
-	gint nRenderMode = RENDERMODE_FAST; //RENDERMODE_PRETTY; //;
-
-	nRenderMode = RENDERMODE_PRETTY;
+	gint nRenderMode = RENDERMODE_FAST; // RENDERMODE_PRETTY
 
-#ifdef SCENEMANAGER_DEBUG_TEST
-        GdkRectangle rect = {200,200,100,100};
-        scenemanager_claim_rectangle(pMap->m_pSceneManager, &rect);
+#ifdef ENABLE_SCENEMANAGER_DEBUG_TEST
+	GdkRectangle rect = {200,200,100,100};
+	scenemanager_claim_rectangle(pMap->m_pSceneManager, &rect);
 #endif
 
 	if(nRenderMode == RENDERMODE_FAST) {
 		// 
 		if(nDrawFlags & DRAWFLAG_GEOMETRY) {
 			map_draw_gdk(pMap, pRenderMetrics, pMap->m_pPixmap, DRAWFLAG_GEOMETRY);
+			//g_print("geometry\n");
 		}
 		// Always draw labels with Cairo
 		if(nDrawFlags & DRAWFLAG_LABELS) {
 			map_draw_cairo(pMap, pRenderMetrics, pMap->m_pPixmap, DRAWFLAG_LABELS);
+			//g_print("text\n");
 		}
 	}
 	else {	// nRenderMode == RENDERMODE_PRETTY
 		map_draw_cairo(pMap, pRenderMetrics, pMap->m_pPixmap, nDrawFlags);
 	}
 
-#ifdef SCENEMANAGER_DEBUG_TEST
+#ifdef ENABLE_SCENEMANAGER_DEBUG_TEST
         gdk_draw_rectangle(pMap->m_pPixmap, pMap->m_pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->m_pTargetWidget)],
                            FALSE, 200,200, 100, 100);
 #endif
@@ -518,9 +521,14 @@
 	gdouble fLatStart = (gdouble)nLatStart / TILE_SHIFT;
 	gdouble fLonStart = (gdouble)nLonStart / TILE_SHIFT;
 
-//	g_print("%f < %f\n", fLatStart, pRect->m_A.m_fLatitude);
-	g_assert(fLatStart <= pRect->m_A.m_fLatitude);
-        g_assert(fLonStart <= pRect->m_A.m_fLongitude);
+	if(fLatStart > pRect->m_A.m_fLatitude) {
+		g_print("fLatStart %f > pRect->m_A.m_fLatitude %f\n", fLatStart, pRect->m_A.m_fLatitude);
+		g_assert(fLatStart <= pRect->m_A.m_fLatitude);
+	}
+	if(fLonStart > pRect->m_A.m_fLongitude) {
+		g_print("fLonStart %f > pRect->m_A.m_fLongitude %f!!\n", fLonStart, pRect->m_A.m_fLongitude);
+		g_assert_not_reached();
+	}
 
 	gint nLat,nLon;
 	for(nLat = 0 ; nLat < nLatNumTiles ; nLat++) {
@@ -551,6 +559,7 @@
 	TIMER_BEGIN(mytimer, "BEGIN Geometry LOAD");
 
 	// generate SQL
+	gchar azCoord1[20], azCoord2[20], azCoord3[20], azCoord4[20], azCoord5[20], azCoord6[20], azCoord7[20], azCoord8[20];
 	gchar* pszSQL;
 	pszSQL = g_strdup_printf(
 		"SELECT Road.ID, Road.TypeID, AsBinary(Road.Coordinates), RoadName.Name, RoadName.SuffixID, AddressLeftStart, AddressLeftEnd, AddressRightStart, AddressRightEnd"
@@ -559,13 +568,20 @@
 		" WHERE"
 		//" TypeID IN (%s) AND"
                 //" MBRIntersects(@wkb, Coordinates)"
-		" MBRIntersects(GeomFromText('Polygon((%f %f,%f %f,%f %f,%f %f,%f %f))'), Coordinates)"
-		,pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude, 	// upper left
-		pRect->m_A.m_fLatitude, pRect->m_B.m_fLongitude, 	// upper right
-		pRect->m_B.m_fLatitude, pRect->m_B.m_fLongitude, 	// bottom right
-		pRect->m_B.m_fLatitude, pRect->m_A.m_fLongitude, 	// bottom left
-		pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude		// upper left again
-		);
+		" MBRIntersects(GeomFromText('Polygon((%s %s,%s %s,%s %s,%s %s,%s %s))'), Coordinates)"
+		,
+		g_ascii_dtostr(azCoord1, 20, pRect->m_A.m_fLatitude), g_ascii_dtostr(azCoord2, 20, pRect->m_A.m_fLongitude), 
+		g_ascii_dtostr(azCoord3, 20, pRect->m_A.m_fLatitude), g_ascii_dtostr(azCoord4, 20, pRect->m_B.m_fLongitude), 
+		g_ascii_dtostr(azCoord5, 20, pRect->m_B.m_fLatitude), g_ascii_dtostr(azCoord6, 20, pRect->m_B.m_fLongitude), 
+		g_ascii_dtostr(azCoord7, 20, pRect->m_B.m_fLatitude), g_ascii_dtostr(azCoord8, 20, pRect->m_A.m_fLongitude), 
+		azCoord1, azCoord2);
+
+//         pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude,    // upper left
+//         pRect->m_A.m_fLatitude, pRect->m_B.m_fLongitude,    // upper right
+//         pRect->m_B.m_fLatitude, pRect->m_B.m_fLongitude,    // bottom right
+//         pRect->m_B.m_fLatitude, pRect->m_A.m_fLongitude,    // bottom left
+//         pRect->m_A.m_fLatitude, pRect->m_A.m_fLongitude     // upper left again
+//         );
 	//g_print("sql: %s\n", pszSQL);
 
 	db_query(pszSQL, &pResultSet);
@@ -625,6 +641,17 @@
 
 			pNewRoad->m_pszName = g_strdup(azFullName);
 
+#ifdef ENABLE_RIVER_TO_LAKE_LOADTIME_HACK
+			if(nTypeID == LAYER_RIVER) {
+				mappoint_t* pPointA = g_ptr_array_index(pNewRoad->m_pPointsArray, 0);
+				mappoint_t* pPointB = g_ptr_array_index(pNewRoad->m_pPointsArray, pNewRoad->m_pPointsArray->len-1);
+
+				if(pPointA->m_fLatitude == pPointB->m_fLatitude && pPointA->m_fLongitude == pPointB->m_fLongitude) {
+					nTypeID = LAYER_LAKE;
+				}
+			}
+#endif
+
 			// Add this item to layer's list of pointstrings
 			g_ptr_array_add(pMap->m_apLayerData[nTypeID]->m_pRoadsArray, pNewRoad);
 		} // end while loop on rows
@@ -825,7 +852,7 @@
 	gint i;
 	for(i=NUM_ELEMS(layerdraworder)-1 ; i>=0 ; i--) {
 		if(layerdraworder[i].eSubLayerRenderType != SUBLAYER_RENDERTYPE_LINES) continue;
-		
+
 		gint nLayer = layerdraworder[i].nLayer;
 
 		// use width from whichever layer it's wider in
@@ -835,7 +862,7 @@
 #define EXTRA_CLICKABLE_ROAD_IN_PIXELS	(3)
 
 		// make thin roads a little easier to hit
-	       // fLineWidth = max(fLineWidth, MIN_ROAD_HIT_TARGET_WIDTH);
+		// fLineWidth = max(fLineWidth, MIN_ROAD_HIT_TARGET_WIDTH);
 
 		// XXX: hack, map_pixels should really take a floating point instead.
 		gdouble fMaxDistance = map_pixels_to_degrees(pMap, 1, pMap->m_uZoomLevel) * ((fLineWidth/2) + EXTRA_CLICKABLE_ROAD_IN_PIXELS);  // half width on each side
@@ -843,6 +870,7 @@
 		if(map_hit_test_layer_roads(pMap->m_apLayerData[nLayer]->m_pRoadsArray, fMaxDistance, pMapPoint, ppReturnStruct)) {
 			return TRUE;
 		}
+		// otherwise try next layer...
 	}
 	return FALSE;
 }
@@ -883,7 +911,7 @@
 				pHitStruct->m_eHitType = MAP_HITTYPE_ROAD;
 
 				if(pRoad->m_pszName[0] == '\0') {
-					pHitStruct->m_pszText = g_strdup("<i>unnamed road</i>");
+					pHitStruct->m_pszText = g_strdup("<i>unnamed</i>");
 				}
 				else {
 					ESide eSide = map_side_test_line(pPoint1, pPoint2, &pointClosest, pHitPoint);

Index: map.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- map.h	23 Apr 2005 18:13:39 -0000	1.17
+++ map.h	28 Aug 2005 22:23:14 -0000	1.18
@@ -225,7 +225,7 @@
 //	void (*pFunc)(map_t*, cairo_t*, rendermetrics_t*, GPtrArray*, sublayerstyle_t*, textlabelstyle_t*);
 } draworder_t;
 
-#define MAX_LOCATIONSELETION_URLS	(5)
+#define MAX_LOCATIONSELECTION_URLS	(5)
 
 typedef struct {
 	gint m_nLocationID;
@@ -242,14 +242,14 @@
 	struct {
 		screenrect_t m_Rect;
 		gchar* m_pszURL;
-	} m_aURLs[MAX_LOCATIONSELETION_URLS];
+	} m_aURLs[MAX_LOCATIONSELECTION_URLS];
 } locationselection_t;
 
 // Draw flags
 #define DRAWFLAG_LABELS 	(1)
 #define DRAWFLAG_GEOMETRY	(2)
-
 // next is 4 :)
+
 #define DRAWFLAG_ALL 		(1|2)
 
 #define NUM_SUBLAYER_TO_DRAW (24)
@@ -258,7 +258,6 @@
 void map_init(void);
 gboolean map_new(map_t** ppMap, GtkWidget* pTargetWidget);
 
-
 // Gets and Sets
 guint16 map_get_zoomlevel(map_t* pMap);
 guint32 map_get_zoomlevel_scale(map_t* pMap);
@@ -267,7 +266,6 @@
 
 void map_set_redraw_needed(map_t* pMap, gboolean bNeeded);
 gboolean map_get_redraw_needed(map_t* pMap);
-
 guint32 map_get_scale(map_t* pMap);
 
 void map_set_centerpoint(map_t* pMap, const mappoint_t* pPoint);
@@ -279,6 +277,9 @@
 gdouble map_distance_in_units_to_degrees(map_t* pMap, gdouble fDistance, gint nDistanceUnit);
 double map_get_distance_in_meters(mappoint_t* pA, mappoint_t* pB);
 double map_pixels_to_degrees(map_t* pMap, gint16 nPixels, guint16 uZoomLevel);
+double map_degrees_to_pixels(map_t* pMap, gdouble fDegrees, guint16 uZoomLevel);
+gboolean map_points_equal(mappoint_t* p1, mappoint_t* p2);
+gdouble map_get_distance_in_pixels(map_t* pMap, mappoint_t* p1, mappoint_t* p2);
 
 // remove this!
 void map_center_on_windowpoint(map_t* pMap, guint16 uX, guint16 uY);
@@ -288,12 +289,6 @@
 //void map_draw_thread_begin(map_t* pMap, GtkWidget* pTargetWidget);
 
 void map_draw(map_t* pMap, gint nDrawFlags);
-double map_degrees_to_pixels(map_t* pMap, gdouble fDegrees, guint16 uZoomLevel);
-
-gboolean map_points_equal(mappoint_t* p1, mappoint_t* p2);
-
-gdouble map_get_distance_in_pixels(map_t* pMap, mappoint_t* p1, mappoint_t* p2);
-
 void map_add_track(map_t* pMap, gint hTrack);
 
 gboolean map_hit_test(map_t* pMap, mappoint_t* pMapPoint, maphit_t** ppReturnStruct);

Index: map_draw_cairo.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_cairo.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- map_draw_cairo.c	26 May 2005 20:05:36 -0000	1.18
+++ map_draw_cairo.c	28 Aug 2005 22:23:14 -0000	1.19
@@ -23,16 +23,15 @@
 
 //#define ENABLE_TIMING
 
-#define LABEL_LIMIT_TO_ROAD
-
-#define RENDERING_THREAD_YIELD	// do nothing
+#define ENABLE_ROUND_DOWN_TEXT_ANGLES			// draw all text at multiples of X radians to be more cache-friendly
+#define 	ROUND_DOWN_TEXT_ANGLE	(100.0)		// 10.0 to keep one decimal place or 100.0 to keep two
+#define ENABLE_LABEL_LIMIT_TO_ROAD				// don't draw labels if they would be longer than the road
+#define ENABLE_HACK_AROUND_CAIRO_LINE_CAP_BUG	// enable to ensure roads have rounded caps if the style dictates
 
 #define	ACCEPTABLE_LINE_LABEL_OVERDRAW_IN_PIXELS_SQUARED (38*38)
 
-#define HACK_AROUND_CAIRO_LINE_CAP_BUG	// enable to ensure roads have rounded caps if the style dictates
-
 #define ROAD_FONT	"Bitstream Vera Sans"
-#define AREA_FONT	"Bitstream Vera Sans" // "Bitstream Charter"
+#define AREA_FONT	"Bitstream Vera Sans"
 
 #include <gdk/gdkx.h>
 #include <cairo.h>
@@ -72,18 +71,27 @@
 
 // static void map_draw_cairo_crosshair(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics);
 
-void cairo_underline_text(cairo_t* pCairo, gdouble fLabelWidth)
+void map_draw_text_underline(cairo_t* pCairo, gdouble fLabelWidth)
 {
 #define UNDERLINE_RELIEF	(2.0)
 
+	cairo_set_line_width(pCairo, 1.0);
+
 	cairo_rel_move_to(pCairo, 2, UNDERLINE_RELIEF);
 	cairo_rel_line_to(pCairo, fLabelWidth, 0.0);
-	cairo_set_line_width(pCairo, 1.0);
 	cairo_stroke(pCairo);
+
 	// undo moves for underline
 	cairo_rel_move_to(pCairo, -(fLabelWidth+2), -UNDERLINE_RELIEF);
 }
 
+void map_draw_cairo_set_rgba(cairo_t* pCairo, color_t* pColor)
+{
+	cairo_set_source_rgba(pCairo, pColor->m_fRed, pColor->m_fGreen, pColor->m_fBlue, pColor->m_fAlpha);
+}
+
+
+
 void map_draw_cairo(map_t* pMap, rendermetrics_t* pRenderMetrics, GdkPixmap* pPixmap, gint nDrawFlags)
 {
 	// 1. Set draw target to X Drawable
@@ -183,7 +191,7 @@
 }
 
 //
-// Draw a whole layer of line strings
+// Draw a whole layer of line labels
 //
 void map_draw_cairo_layer_road_labels(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pRoadsArray, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle)
 {
@@ -194,7 +202,7 @@
 	gdouble fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
 	if(fFontSize == 0) return;
 
-	gchar* pszFontFamily = ROAD_FONT;
+	gchar* pszFontFamily = ROAD_FONT;	// XXX: remove hardcoded font
 
 	// set font for whole layer
 	cairo_save(pCairo);
@@ -218,7 +226,7 @@
 	gdouble fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
 	if(fFontSize == 0) return;
 
-	gchar* pszFontFamily = AREA_FONT;
+	gchar* pszFontFamily = AREA_FONT;	// XXX: remove hardcoded font
 
 	// set font for whole layer
 	cairo_save(pCairo);
@@ -237,6 +245,9 @@
 	cairo_restore(pCairo);
 }
 
+//
+// Draw a whole layer of lines
+//
 void map_draw_cairo_layer_roads(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pRoadsArray, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle)
 {
 	mappoint_t* pPoint;
@@ -246,18 +257,15 @@
 
 	gdouble fLineWidth = pSubLayerStyle->m_afLineWidths[pRenderMetrics->m_nZoomLevel-1];
 	if(fLineWidth <= 0.0) return;	// Don't draw invisible lines
-	if(pSubLayerStyle->m_clrColor.m_fAlpha == 0.0) return;	// invisible?
+	if(pSubLayerStyle->m_clrColor.m_fAlpha == 0.0) return;
 
 	cairo_save(pCairo);
 
 	// Raise the tolerance way up for thin lines
 	gint nCapStyle = pSubLayerStyle->m_nCapStyle;
-	
-	// XXX: HACK
-//	nCapStyle = CAIRO_LINE_CAP_SQUARE;
 
 	gdouble fTolerance;
-	if(fLineWidth > 12.0) {	// huge line, low tolerance
+	if(fLineWidth >= 12.0) {	// huge line, low tolerance
 		fTolerance = 0.40;
 	}
 	else if(fLineWidth >= 6.0) {	// medium line, medium tolerance
@@ -266,7 +274,7 @@
 	else {
 		if(nCapStyle == CAIRO_LINE_CAP_ROUND) {
 			//g_print("forcing round->square cap style\n");
-			nCapStyle = CAIRO_LINE_CAP_SQUARE;
+			//nCapStyle = CAIRO_LINE_CAP_SQUARE;
 		}
 
 		if(fLineWidth >= 3.0) {
@@ -278,17 +286,13 @@
 	}
 	cairo_set_tolerance(pCairo, fTolerance);
 	cairo_set_line_join(pCairo, pSubLayerStyle->m_nJoinStyle);
-	cairo_set_line_cap(pCairo, nCapStyle);	/* CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_CAP */
+	cairo_set_line_cap(pCairo, nCapStyle);
 	if(g_aDashStyles[pSubLayerStyle->m_nDashStyle].m_nDashCount > 1) {
 		cairo_set_dash(pCairo, g_aDashStyles[pSubLayerStyle->m_nDashStyle].m_pafDashList, g_aDashStyles[pSubLayerStyle->m_nDashStyle].m_nDashCount, 0.0);
 	}
 
 	// Set layer attributes	
-	cairo_set_source_rgba(pCairo, 
-			      pSubLayerStyle->m_clrColor.m_fRed, 
-			      pSubLayerStyle->m_clrColor.m_fGreen, 
-			      pSubLayerStyle->m_clrColor.m_fBlue,
-			      pSubLayerStyle->m_clrColor.m_fAlpha);
+	map_draw_cairo_set_rgba(pCairo, &(pSubLayerStyle->m_clrColor));
 	cairo_set_line_width(pCairo, fLineWidth);
 
 	for(iString=0 ; iString<pRoadsArray->len ; iString++) {
@@ -305,13 +309,13 @@
 				pPoint = g_ptr_array_index(pRoad->m_pPointsArray, iPoint);//~ g_print("  point (%.05f,%.05f)\n", ScaleX(pPoint->m_fLongitude), ScaleY(pPoint->m_fLatitude));
 				cairo_line_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
 			}
-#ifdef HACK_AROUND_CAIRO_LINE_CAP_BUG
+#ifdef ENABLE_HACK_AROUND_CAIRO_LINE_CAP_BUG
 			cairo_stroke(pCairo);	// this is wrong place for it (see below)
 #endif
    		}
 	}
 
-#ifndef HACK_AROUND_CAIRO_LINE_CAP_BUG
+#ifndef ENABLE_HACK_AROUND_CAIRO_LINE_CAP_BUG
 	// this is correct place to stroke, but we can't do this until Cairo fixes this bug:
 	// http://cairographics.org/samples/xxx_multi_segment_caps.html
 	cairo_stroke(pCairo);
@@ -328,13 +332,9 @@
 	gdouble fLineWidth = pSubLayerStyle->m_afLineWidths[pRenderMetrics->m_nZoomLevel-1];
 	if(fLineWidth == 0.0) return;	// Don't both drawing with line width 0
 	if(pSubLayerStyle->m_clrColor.m_fAlpha == 0.0) return;	// invisible?
-	
+
 	// Set layer attributes	
-	cairo_set_source_rgba (pCairo, 
-			       pSubLayerStyle->m_clrColor.m_fRed,
-			       pSubLayerStyle->m_clrColor.m_fGreen,
-			       pSubLayerStyle->m_clrColor.m_fBlue,
-			       pSubLayerStyle->m_clrColor.m_fAlpha);
+	map_draw_cairo_set_rgba(pCairo, &(pSubLayerStyle->m_clrColor));
 	cairo_set_line_width(pCairo, fLineWidth);
 	cairo_set_fill_rule(pCairo, CAIRO_FILL_RULE_EVEN_ODD);
 
@@ -344,8 +344,6 @@
 
 	gint iString;
 	for(iString=0 ; iString<pRoadsArray->len ; iString++) {
-		RENDERING_THREAD_YIELD;
-
 		pRoad = g_ptr_array_index(pRoadsArray, iString);
 
 		if(pRoad->m_pPointsArray->len >= 3) {
@@ -360,45 +358,18 @@
 				pPoint = g_ptr_array_index(pRoad->m_pPointsArray, iPoint);				
 				cairo_line_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
 			}
-			//cairo_close_path(pCairo);
 		}
 		else {
-//			g_print("pPointString->m_pPointsArray->len = %d\n", pPointString->m_pPointsArray->len);
+//			g_print("OOPS!  A linestring with <3 points (%d)\n", pPointString->m_pPointsArray->len);
 		}
-
-		// TODO: this is debugging of polygons.
-//         cairo_save(pCairo);
-//         cairo_set_source_rgb(pCairo, 1,0,0);
-//
-//         if(pPointString->m_pPointsArray->len >= 3) {
-//             gdouble fRadius = 2;
-//             // start at index 1 (0 was used above)
-//             for(iPoint=0 ; iPoint<pPointString->m_pPointsArray->len ; iPoint++) {
-//                 pPoint = g_ptr_array_index(pPointString->m_pPointsArray, iPoint);
-//                 cairo_move_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
-//
-//                 color_t clr;
-//                 util_random_color(&clr);
-//                 cairo_set_source_rgb(pCairo, clr.m_fRed, clr.m_fGreen, clr.m_fBlue);
-//
-//                 gchar buf[20];
-//                 g_snprintf(buf, 20, "%d", iPoint);
-//     //~ //              cairo_select_font(pCairo, "Monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-//                 cairo_text_path(pCairo, buf);
-//
-//                 cairo_arc(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude), fRadius, 0, 360.0  * (M_PI/180.0));
-//                 cairo_fill(pCairo);
-//                 fRadius += 2;
-//             }
-//         }
-//         cairo_restore(pCairo);
 	}
 	cairo_fill(pCairo);
 }
 
 void map_draw_cairo_layer_points(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray)
 {
-/*	gdouble fRadius = map_degrees_to_pixels(pMap, 0.0007, map_get_zoomlevel(pMap));
+/*
+	gdouble fRadius = map_degrees_to_pixels(pMap, 0.0007, map_get_zoomlevel(pMap));
 	gboolean bAddition = FALSE;
 
 	cairo_save(pCairo);
@@ -439,6 +410,9 @@
 */
 }
 
+<<<<<<< map_draw_cairo.c
+#define ROAD_MAX_SEGMENTS 		(100)
+=======
 //void map_draw_cairo_locations(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics)
 //{
 /*
@@ -474,7 +448,6 @@
 */
 //}
 
-
 #define ROAD_MAX_SEGMENTS 100
 #define DRAW_LABEL_BUFFER_LEN	(200)
 
@@ -493,18 +466,18 @@
 //
 static void map_draw_cairo_road_label_one_segment(map_t* pMap, cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, GPtrArray* pPointsArray, gdouble fLineWidth, const gchar* pszLabel)
 {
-        // get permission to draw this label
-        if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
-        return;
-        }
+	// get permission to draw this label
+	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
+		return;
+	}
 
-        mappoint_t* pMapPoint1 = g_ptr_array_index(pPointsArray, 0);
-        mappoint_t* pMapPoint2 = g_ptr_array_index(pPointsArray, 1);
+	mappoint_t* pMapPoint1 = g_ptr_array_index(pPointsArray, 0);
+	mappoint_t* pMapPoint2 = g_ptr_array_index(pPointsArray, 1);
 
-        // swap first and second points such that the line goes left-to-right
-        if(pMapPoint2->m_fLongitude < pMapPoint1->m_fLongitude) {
-            mappoint_t* pTmp = pMapPoint1; pMapPoint1 = pMapPoint2; pMapPoint2 = pTmp;
-        }
+	// swap first and second points such that the line goes left-to-right
+	if(pMapPoint2->m_fLongitude < pMapPoint1->m_fLongitude) {
+		mappoint_t* pTmp = pMapPoint1; pMapPoint1 = pMapPoint2; pMapPoint2 = pTmp;
+	}
 
 	// find extents
 	gdouble fMaxLat = max(pMapPoint1->m_fLatitude, pMapPoint2->m_fLatitude);
@@ -512,10 +485,10 @@
 	gdouble fMaxLon = max(pMapPoint1->m_fLongitude, pMapPoint2->m_fLongitude);
 	gdouble fMinLon = min(pMapPoint1->m_fLongitude, pMapPoint2->m_fLongitude);
 
-        gdouble fX1 = SCALE_X(pRenderMetrics, pMapPoint1->m_fLongitude);
-        gdouble fY1 = SCALE_Y(pRenderMetrics, pMapPoint1->m_fLatitude);
-        gdouble fX2 = SCALE_X(pRenderMetrics, pMapPoint2->m_fLongitude);
-        gdouble fY2 = SCALE_Y(pRenderMetrics, pMapPoint2->m_fLatitude);
+	gdouble fX1 = SCALE_X(pRenderMetrics, pMapPoint1->m_fLongitude);
+	gdouble fY1 = SCALE_Y(pRenderMetrics, pMapPoint1->m_fLatitude);
+	gdouble fX2 = SCALE_X(pRenderMetrics, pMapPoint2->m_fLongitude);
+	gdouble fY2 = SCALE_Y(pRenderMetrics, pMapPoint2->m_fLatitude);
 
 	// rectangle overlap test
 	if(fMaxLat < pRenderMetrics->m_rWorldBoundingBox.m_A.m_fLatitude
@@ -523,20 +496,20 @@
 	   || fMinLat > pRenderMetrics->m_rWorldBoundingBox.m_B.m_fLatitude
 	   || fMinLon > pRenderMetrics->m_rWorldBoundingBox.m_B.m_fLongitude)
 	{
-            return;
-        }
+		return;
+	}
 
-        gdouble fRise = fY2 - fY1;
-        gdouble fRun = fX2 - fX1;
-        gdouble fLineLengthSquared = (fRun*fRun) + (fRise*fRise);
+	gdouble fRise = fY2 - fY1;
+	gdouble fRun = fX2 - fX1;
+	gdouble fLineLengthSquared = (fRun*fRun) + (fRise*fRise);
 
-        gchar* pszFontFamily = ROAD_FONT;
+	gchar* pszFontFamily = ROAD_FONT;
 
-        cairo_save(pCairo);
+	cairo_save(pCairo);
 
-        // get total width of string
-        cairo_text_extents_t extents;
-        cairo_text_extents(pCairo, pszLabel, &extents);
+	// get total width of string
+	cairo_text_extents_t extents;
+	cairo_text_extents(pCairo, pszLabel, &extents);
 	gdouble fLabelWidth = extents.width;
 	gdouble fFontHeight = extents.height;
 
@@ -544,99 +517,111 @@
 //        cairo_current_font_extents(pCairo, &font_extents);
 //	gdouble fFontHeight = font_extents.ascent;
 
-        // text too big for line?       XXX: This math is not right but good enough for now ;)
-#ifdef LABEL_LIMIT_TO_ROAD
-        if((fLabelWidth * fLabelWidth) > (fLineLengthSquared + (ACCEPTABLE_LINE_LABEL_OVERDRAW_IN_PIXELS_SQUARED))) {
-            cairo_restore(pCairo);
-            return;
-        }
+	// text too big for line?       XXX: This math is not right but good enough for now ;)
+#ifdef ENABLE_LABEL_LIMIT_TO_ROAD
+	if((fLabelWidth * fLabelWidth) > (fLineLengthSquared + (ACCEPTABLE_LINE_LABEL_OVERDRAW_IN_PIXELS_SQUARED))) {
+		cairo_restore(pCairo);
+		return;
+	}
 #endif
-        gdouble fLineLength = sqrt(fLineLengthSquared);
 
-        gdouble fTotalPadding = fLineLength - fLabelWidth;
+	gdouble fLineLength = sqrt(fLineLengthSquared);	// delay expensive sqrt() until after above test
 
-        // Normalize (make length = 1.0) by dividing by line length
-        // This makes a line with length 1 from the origin (0,0)
-        gdouble fNormalizedX = fRun / fLineLength;
-        gdouble fNormalizedY = fRise / fLineLength;
+	gdouble fTotalPadding = fLineLength - fLabelWidth;
 
-        // NOTE: ***Swap the X and Y*** and normalize (make length = 1.0) by dividing by line length
-        // This makes a perpendicular line with length 1 from the origin (0,0)
-        gdouble fPerpendicularNormalizedX = fRise / fLineLength;
-        gdouble fPerpendicularNormalizedY = -(fRun / fLineLength);
+	// Normalize (make length = 1.0) by dividing by line length
+	// This makes a line with length 1 from the origin (0,0)
+	gdouble fNormalizedX = fRun / fLineLength;
+	gdouble fNormalizedY = fRise / fLineLength;
 
-        // various places to try, in order
-        gdouble afPercentagesOfPadding[] = {0.5, 0.25, 0.75, 0.0, 1.0};
-        gint i;
-        for(i=0 ; i<NUM_ELEMS(afPercentagesOfPadding) ; i++) {
-                // try the next point along the line
-                gdouble fFrontPadding = fTotalPadding * afPercentagesOfPadding[i];
-                
-                // align it on the line
-                // (front padding) |-text-| (back padding)
-                gdouble fDrawX = fX1 + (fNormalizedX * fFrontPadding);
-                gdouble fDrawY = fY1 + (fNormalizedY * fFrontPadding);
-                
-                // center text vertically by shifting down by half of height
-                fDrawX -= (fPerpendicularNormalizedX * fFontHeight/2);
-                fDrawY -= (fPerpendicularNormalizedY * fFontHeight/2);
+	// Swap the X and Y and normalize (make length = 1.0) by dividing by line length
+	// This makes a perpendicular line with length 1 from the origin (0,0)
+	gdouble fPerpendicularNormalizedX = fRise / fLineLength;
+	gdouble fPerpendicularNormalizedY = -(fRun / fLineLength);
 
-		#define B (3)	// a border around the text to keep things readable, in pixels
+	// various places to try
+	gdouble afPercentagesOfPadding[] = {0.5, 0.25, 0.75, 0.0, 1.0};
+	gint i;
+	for(i=0 ; i<NUM_ELEMS(afPercentagesOfPadding) ; i++) {
+		// try the next point along the line
+		gdouble fFrontPadding = fTotalPadding * afPercentagesOfPadding[i];
 
-                GdkPoint aBoundingPolygon[4];
-                // 0 is bottom left point
-                aBoundingPolygon[0].x = fDrawX - (fPerpendicularNormalizedX * B) - (fNormalizedX * B);
-                aBoundingPolygon[0].y = fDrawY - (fPerpendicularNormalizedX * B) - (fNormalizedX * B);
-                // 1 is upper left point
-                aBoundingPolygon[1].x = fDrawX + (fPerpendicularNormalizedX * (fFontHeight+B)) - (fNormalizedX * B); ;
-                aBoundingPolygon[1].y = fDrawY + (fPerpendicularNormalizedY * (fFontHeight+B)) - (fNormalizedY * B);;
-                // 2 is upper right point
-                aBoundingPolygon[2].x = aBoundingPolygon[1].x + (fNormalizedX * (fLabelWidth+B+B));
-                aBoundingPolygon[2].y = aBoundingPolygon[1].y + (fNormalizedY * (fLabelWidth+B+B));
-                // 3 is lower right point
-                aBoundingPolygon[3].x = fDrawX + (fNormalizedX * (fLabelWidth+B)) - (fPerpendicularNormalizedX * B);
-                aBoundingPolygon[3].y = fDrawY + (fNormalizedY * (fLabelWidth+B)) - (fPerpendicularNormalizedY * B);
-                
-                // Ask whether we can draw here
-                if(FALSE == scenemanager_can_draw_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4)) {
-                        continue;
-                }
-                
-                // do this after the padding calculation to possibly save some CPU cycles
-                gdouble fAngleInRadians = atan(fRise / fRun);
-                if(fRun < 0.0) fAngleInRadians += M_PI;
-                
-                cairo_save(pCairo);
-                cairo_set_source_rgb (pCairo, 0.0,0.0,0.0);
-                
-                gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
-                if(fHaloSize >= 0) {
-                        cairo_save(pCairo);
+		// move it "forward" along the line
+		// (front padding) |-text-| (back padding)
+		gdouble fDrawX = fX1 + (fNormalizedX * fFrontPadding);
+		gdouble fDrawY = fY1 + (fNormalizedY * fFrontPadding);
+
+		// center text "vertically" by translating "down" by half of font height
+		fDrawX -= (fPerpendicularNormalizedX * fFontHeight/2);
+		fDrawY -= (fPerpendicularNormalizedY * fFontHeight/2);
+
+		//
+		// Build a rectangle that surrounds the text to tell the scenemanager where we want to draw
+		//
+		#define B (3)	// claim an extra border around the text to keep things readable (in pixels)
+
+		GdkPoint aBoundingPolygon[4];
+		// 0 is bottom left point
+		aBoundingPolygon[0].x = fDrawX - (fPerpendicularNormalizedX * B) - (fNormalizedX * B);
+		aBoundingPolygon[0].y = fDrawY - (fPerpendicularNormalizedX * B) - (fNormalizedX * B);
+		// 1 is upper left point
+		aBoundingPolygon[1].x = fDrawX + (fPerpendicularNormalizedX * (fFontHeight+B)) - (fNormalizedX * B);
+		aBoundingPolygon[1].y = fDrawY + (fPerpendicularNormalizedY * (fFontHeight+B)) - (fNormalizedY * B);
+		// 2 is upper right point
+		aBoundingPolygon[2].x = aBoundingPolygon[1].x + (fNormalizedX * (fLabelWidth+B+B));
+		aBoundingPolygon[2].y = aBoundingPolygon[1].y + (fNormalizedY * (fLabelWidth+B+B));
+		// 3 is lower right point
+		aBoundingPolygon[3].x = fDrawX + (fNormalizedX * (fLabelWidth+B)) - (fPerpendicularNormalizedX * B);
+		aBoundingPolygon[3].y = fDrawY + (fNormalizedY * (fLabelWidth+B)) - (fPerpendicularNormalizedY * B);
+		
+		// Ask whether we can draw here
+		if(FALSE == scenemanager_can_draw_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4)) {
+			continue;
+		}
+		
+		gdouble fAngleInRadians = atan(fRise / fRun);	// delay expensive atan() until we've found a place we can draw
+
+		if(fRun < 0.0) fAngleInRadians += M_PI;			// XXX: Why do we do this?
+
+#ifdef ENABLE_ROUND_DOWN_TEXT_ANGLES
+		fAngleInRadians = floor((fAngleInRadians * ROUND_DOWN_TEXT_ANGLE) + 0.5) / ROUND_DOWN_TEXT_ANGLE;
+#endif
+
+		cairo_save(pCairo);								// XXX: do we need this?
+
+		cairo_set_source_rgb(pCairo, 0.0,0.0,0.0);		// XXX: this should be a style setting
+
+		// Draw a "halo" around text if the style calls for it
+		gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+		if(fHaloSize >= 0) {
+			// Halo = stroking the text path with a fat white line
+			cairo_save(pCairo);
 			cairo_move_to(pCairo, fDrawX, fDrawY);
 			cairo_rotate(pCairo, fAngleInRadians);
-                        cairo_text_path(pCairo, pszLabel);
-                        cairo_set_line_width(pCairo, fHaloSize);
-                        cairo_set_source_rgb(pCairo, 1.0,1.0,1.0);
-                        cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_BEVEL);
-                        //cairo_set_miter_limit(pCairo, 0.1);
-                        cairo_stroke(pCairo);
-                        cairo_restore(pCairo);
-                }
-                cairo_move_to(pCairo, fDrawX, fDrawY);
+			cairo_text_path(pCairo, pszLabel);
+			cairo_set_line_width(pCairo, fHaloSize);
+			cairo_set_source_rgb(pCairo, 1.0,1.0,1.0);	// XXX: this should be a style setting
+			cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_BEVEL);
+			//cairo_set_miter_limit(pCairo, 0.1);
+			cairo_stroke(pCairo);
+			cairo_restore(pCairo);
+		}
+		cairo_move_to(pCairo, fDrawX, fDrawY);
 		cairo_rotate(pCairo, fAngleInRadians);
-                cairo_show_text(pCairo, pszLabel);
-                cairo_restore(pCairo);
-                
-                // claim the space this took up and the label (so it won't be drawn twice)
-                scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
-                scenemanager_claim_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4);
-                
-                // success
-                break;
-        }
-        cairo_restore(pCairo);
+		cairo_show_text(pCairo, pszLabel);
+		cairo_restore(pCairo);
+
+		// claim the space this took up and the label (so it won't be drawn twice)
+		scenemanager_claim_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4);
+		scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
+
+		// success
+		break;
+	}
+	cairo_restore(pCairo);
 }
 
+
 //
 // Draw a label along a multi-point line
 //
@@ -659,7 +644,7 @@
 		return;
 	}
 
-	// XXX
+	// XXX: Below code is broken.  For now we can only label 2-point roads. :(
 	return;
 
 	if(pPointsArray->len > ROAD_MAX_SEGMENTS) {
@@ -670,11 +655,13 @@
 //         gdouble fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
 //         if(fFontSize == 0) return;
 
+	// Request permission to draw this label.  This prevents multiple labels too close together.
+	// NOTE: Currently no location is used, only allows one of each text string per draw
 	if(!scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
 		return;
 	}
 
-	gchar* pszFontFamily = ROAD_FONT;
+	gchar* pszFontFamily = ROAD_FONT;		// XXX: remove hardcoded font
 
 	cairo_save(pCairo);
 
@@ -842,8 +829,6 @@
 		gboolean bGood = TRUE;
 
 		for(iPoint = iStartPoint ; iPoint < iEndPoint ; iPoint++) {
-			RENDERING_THREAD_YIELD;
-
 			if(nTotalStringLength == nStringStartIndex) break;	// done
 
 			pMapPoint1 = apPoints[iPoint-1];
@@ -872,6 +857,9 @@
 			// do this after the padding calculation to possibly save some CPU cycles
 			gdouble fAngleInRadians = atan(fRise / fRun);
 			if(fRun < 0.0) fAngleInRadians += M_PI;
+#ifdef ENABLE_ROUND_DOWN_TEXT_ANGLES
+        fAngleInRadians = floor((fAngleInRadians * ROUND_DOWN_TEXT_ANGLE) + 0.5) / ROUND_DOWN_TEXT_ANGLE;
+#endif
 
 			//g_print("(fRise(%f) / fRun(%f)) = %f, atan(fRise / fRun) = %f: ", fRise, fRun, fRise / fRun, fAngleInRadians);
 			//g_print("=== NEW SEGMENT, pixel (deltaY=%f, deltaX=%f), line len=%f, (%f,%f)->(%f,%f)\n",fRise, fRun, fLineLength, pMapPoint1->m_fLatitude,pMapPoint1->m_fLongitude,pMapPoint2->m_fLatitude,pMapPoint2->m_fLongitude);
@@ -990,8 +978,6 @@
 
 		// draw it
 		for(iPoint = iStartPoint ; iPoint < iEndPoint ; iPoint++) {
-			RENDERING_THREAD_YIELD;
-
 			if(nTotalStringLength == nStringStartIndex) break;	// done
 
 			pMapPoint1 = apPoints[iPoint-1];
@@ -1014,6 +1000,9 @@
 			// do this after the padding calculation to possibly save some CPU cycles
 			gdouble fAngleInRadians = atan(fRise / fRun);
 			if(fRun < 0.0) fAngleInRadians += M_PI;
+#ifdef ENABLE_ROUND_DOWN_TEXT_ANGLES
+        fAngleInRadians = floor((fAngleInRadians * ROUND_DOWN_TEXT_ANGLE) + 0.5) / ROUND_DOWN_TEXT_ANGLE;
+#endif
 
 			//g_print("(fRise(%f) / fRun(%f)) = %f, atan(fRise / fRun) = %f: ", fRise, fRun, fRise / fRun, fAngleInRadians);
 			//g_print("=== NEW SEGMENT, pixel (deltaY=%f, deltaX=%f), line len=%f, (%f,%f)->(%f,%f)\n",fRise, fRun, fLineLength, pMapPoint1->m_fLatitude,pMapPoint1->m_fLongitude,pMapPoint2->m_fLatitude,pMapPoint2->m_fLongitude);
@@ -1153,7 +1142,7 @@
 	g_ptr_array_free(pPositionsPtrArray, FALSE);
 	*/
 }
-
+/*
 //
 // Draw a single polygon label
 //
@@ -1162,11 +1151,11 @@
 	if(pPointsArray->len < 3) return;
 
 	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
-		return;	// duplicate label or whatever other rule scenemanager uses
+		return;
 	}
 
-	gdouble fTotalX = 0.0;
-	gdouble fTotalY = 0.0;
+	//gdouble fTotalX = 0.0;
+	//gdouble fTotalY = 0.0;
 
 	gdouble fMaxLat = MIN_LATITUDE;	// init to the worst possible value so first point will override
 	gdouble fMinLat = MAX_LATITUDE;
@@ -1179,19 +1168,122 @@
 	gint i;
 	for(i=0 ; i<pPointsArray->len ; i++) {
 		pMapPoint = g_ptr_array_index(pPointsArray, i);
-		
-		// find extents
+
+		// find polygon bounding box for visibility test below
 		fMaxLat = max(pMapPoint->m_fLatitude,fMaxLat);
 		fMinLat = min(pMapPoint->m_fLatitude,fMinLat);
 		fMaxLon = max(pMapPoint->m_fLongitude,fMaxLon);
 		fMinLon = min(pMapPoint->m_fLongitude,fMinLon);
 
-		fX = SCALE_X(pRenderMetrics, pMapPoint->m_fLongitude);
-		fY = SCALE_Y(pRenderMetrics, pMapPoint->m_fLatitude);
+		// sum up Xs and Ys (we'll take an average later)
+		//fTotalX += SCALE_X(pRenderMetrics, pMapPoint->m_fLongitude);
+		//fTotalY += SCALE_Y(pRenderMetrics, pMapPoint->m_fLatitude);
+	}
+
+	// rectangle overlap test
+	if(fMaxLat < pRenderMetrics->m_rWorldBoundingBox.m_A.m_fLatitude
+	   || fMaxLon < pRenderMetrics->m_rWorldBoundingBox.m_A.m_fLongitude
+	   || fMinLat > pRenderMetrics->m_rWorldBoundingBox.m_B.m_fLatitude
+	   || fMinLon > pRenderMetrics->m_rWorldBoundingBox.m_B.m_fLongitude)
+	{
+	    return;	// not visible
+	}
+
+	gdouble fDrawX = SCALE_X(pRenderMetrics, (fMinLon + fMaxLon) / 2); 	//fMinX + fPolygonWidth/2;	//fTotalX / pPointString->m_pPointsArray->len;
+	gdouble fDrawY = SCALE_Y(pRenderMetrics, (fMinLat + fMaxLat) / 2);	//fMinY + fPolygonHeight/2; 	//fTotalY / pPointString->m_pPointsArray->len;
+
+#define MIN_AREA_LABEL_LINE_LENGTH	(4)
+#define MAX_AREA_LABEL_LINE_LENGTH	(10)
+
+	gchar** aLines = util_split_words_onto_two_lines(pszLabel, MIN_AREA_LABEL_LINE_LENGTH, MAX_AREA_LABEL_LINE_LENGTH);
+
+	cairo_save(pCairo);
+
+	// Get total width of string
+	cairo_text_extents_t extents;
+	cairo_text_extents(pCairo, aLines[0], &extents);
+	gint nWidth = extents.width;
+	gint nHeight = extents.height;
+
+	// add second line if present
+	if(aLines[1]) {
+		cairo_text_extents(pCairo, aLines[1], &extents);
+		nWidth = max(nWidth, extents.width);
+		nHeight += extents.height;
+	}
+
+	fDrawX -= (extents.width / 2);
+	fDrawY += (extents.height / 2);
+
+	// check permission with scenemanager
+	GdkRectangle rcLabelOutline;
+	rcLabelOutline.x = (gint)fDrawX;
+	rcLabelOutline.width = nWidth;
+	rcLabelOutline.y = ((gint)fDrawY) - nHeight;
+	rcLabelOutline.height = nHeight;
+	if(FALSE == scenemanager_can_draw_rectangle(pMap->m_pSceneManager, &rcLabelOutline)) {
+		cairo_restore(pCairo);
+		g_strfreev(aLines);
+		return;
+	}
+	// claim it!  Now no one else will draw text here.
+	scenemanager_claim_rectangle(pMap->m_pSceneManager, &rcLabelOutline);
+
+	gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+	if(fHaloSize >= 0) {
+		cairo_save(pCairo);
+			cairo_move_to(pCairo, fDrawX, fDrawY);
+			cairo_text_path(pCairo, pszLabel);
+			cairo_set_line_width(pCairo, fHaloSize);
+			cairo_set_source_rgb (pCairo, 1.0,1.0,1.0);
+			cairo_set_line_join(pCairo, CAIRO_LINE_JOIN_BEVEL);
+//				cairo_set_miter_limit(pCairo, 0.1);
+			cairo_stroke(pCairo);
+		cairo_restore(pCairo);
+	}
+	cairo_move_to(pCairo, fDrawX, fDrawY);
+	cairo_show_text(pCairo, pszLabel);
+	cairo_restore(pCairo);
+
+	// Tell scenemanager that we've drawn this label
+	scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
+	
+	g_strfreev(aLines);
+}
+*/
+
+void map_draw_cairo_polygon_label(map_t* pMap, cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, GPtrArray* pPointsArray, const gchar* pszLabel)
+{
+	if(pPointsArray->len < 3) return;
+
+	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
+		return;
+	}
+
+	//gdouble fTotalX = 0.0;
+	//gdouble fTotalY = 0.0;
+
+	gdouble fMaxLat = MIN_LATITUDE;	// init to the worst possible value so first point will override
+	gdouble fMinLat = MAX_LATITUDE;
+	gdouble fMaxLon = MIN_LONGITUDE;
+	gdouble fMinLon = MAX_LONGITUDE;
+
+	mappoint_t* pMapPoint;
+	gdouble fX;
+	gdouble fY;
+	gint i;
+	for(i=0 ; i<pPointsArray->len ; i++) {
+		pMapPoint = g_ptr_array_index(pPointsArray, i);
+
+		// find polygon bounding box for visibility test below
+		fMaxLat = max(pMapPoint->m_fLatitude,fMaxLat);
+		fMinLat = min(pMapPoint->m_fLatitude,fMinLat);
+		fMaxLon = max(pMapPoint->m_fLongitude,fMaxLon);
+		fMinLon = min(pMapPoint->m_fLongitude,fMinLon);
 
 		// sum up Xs and Ys (we'll take an average later)
-		fTotalX += fX;
-		fTotalY += fY;
+		//fTotalX += SCALE_X(pRenderMetrics, pMapPoint->m_fLongitude);
+		//fTotalY += SCALE_Y(pRenderMetrics, pMapPoint->m_fLatitude);
 	}
 
 	// rectangle overlap test
@@ -1234,7 +1326,6 @@
 		// claim it!  Now no one else will draw text here.
 		scenemanager_claim_rectangle(pMap->m_pSceneManager, &rcLabelOutline);
 
-
 		gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
 		if(fHaloSize >= 0) {
 			cairo_save(pCairo);
@@ -1252,7 +1343,7 @@
 	cairo_restore(pCairo);
 
 	// Tell scenemanager that we've drawn this label
-        scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
+	scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
 }
 
 /*
@@ -1281,6 +1372,8 @@
 
 static void map_draw_cairo_locationselection_outline(cairo_t *pCairo, gdouble fPointX, gdouble fPointY, const screenrect_t* pRect, screenrect_t* pCloseRect)
 {
+	cairo_save(pCairo);
+
 	gdouble fCorner = 30.0;
 	gdouble fArrowWidth = 30.0; 
 
@@ -1302,7 +1395,7 @@
 	// BEGIN drawing balloon
 
 #define	 CCPOE	(4.0)	// # pixels to move the control points past the rectangle's corner points
-			// a higher number means less curve.  (what does it stand for?  who cares, it's short)
+						// a higher number means less curve.  (what does it stand for?  Who cares?  It's short!)
 
 	// move to spot just below top left curve
 	cairo_move_to(pCairo, fBoxX, (fBoxY + fCorner));
@@ -1330,17 +1423,6 @@
 
 	// bottom line (drawing right to left)
 	if(eArrowSide == SIDE_BOTTOM) {
-#ifdef LOCATIONSELECTION_USE_CURVY_BALLOON
-		cairo_curve_to(pCairo,  
-			       (fBoxX + fBoxWidth/2) + fArrowWidth, (fBoxY + fBoxHeight), 
-			       (fBoxX + fBoxWidth/2) + fArrowWidth, (fBoxY + fBoxHeight), 
-			       fPointX, fPointY);
-
-		cairo_curve_to(pCairo,  
-			       (fBoxX + fBoxWidth/2) - 0, (fBoxY + fBoxHeight),
-			       (fBoxX + fBoxWidth/2) - 0, (fBoxY + fBoxHeight),
-			       (fBoxX + fCorner), (fBoxY + fBoxHeight));
-#else
 		// right side of arrow
 		cairo_line_to(pCairo, (fBoxX + fBoxWidth/2) + fArrowWidth, (fBoxY + fBoxHeight));
 
@@ -1352,7 +1434,6 @@
 
 		// right side of bottom left corner
 		cairo_line_to(pCairo, (fBoxX + fCorner), (fBoxY + fBoxHeight));
-#endif
 	}
 	else {
 		cairo_line_to(pCairo, (fBoxX + fCorner), (fBoxY + fBoxHeight));
@@ -1360,7 +1441,7 @@
 
 	// bottom left corner
 	cairo_curve_to(pCairo,  (fBoxX - CCPOE), (fBoxY + fBoxHeight),
-				(fBoxX), (fBoxY + fBoxHeight + CCPOE), 
+				(fBoxX), (fBoxY + fBoxHeight + CCPOE),
 				(fBoxX), (fBoxY + fBoxHeight) - fCorner);
 
 	// left line, headed up
@@ -1370,19 +1451,15 @@
 	// =======================================================================================
 
 	// fill then stroke
-	cairo_save(pCairo);
-		cairo_set_source_rgb(pCairo, 1.0, 1.0, 1.0);
-		cairo_fill(pCairo);
-	cairo_restore(pCairo);
+	cairo_set_source_rgba(pCairo, 1.0, 1.0, 1.0, 1.0);
+	cairo_fill_preserve(pCairo);
 
-//	cairo_save(pCairo);
-		cairo_set_source_rgb(pCairo, 0.0, 0.0, 0.0);
-		cairo_set_line_width(pCairo, 1.0);
-		cairo_stroke(pCairo);
-//	cairo_restore(pCairo);
+	cairo_set_source_rgb(pCairo, 0.0, 0.0, 0.0);
+	cairo_set_line_width(pCairo, 1.0);
+	cairo_stroke(pCairo);
 
 	// BEGIN [X]
-	gdouble fCloseRectRelief = 8.0;
+	gdouble fCloseRectRelief = 8.0;		// Distance from edge
 	gdouble fCloseRectWidth = 13.0;
 
 	cairo_set_line_width(pCairo, 1.0);
@@ -1400,6 +1477,7 @@
 	pCloseRect->m_B.m_nX = (gint)((fBoxX + fBoxWidth) - fCloseRectRelief);
 	pCloseRect->m_B.m_nY = (gint)fBoxY + fCloseRectRelief + fCloseRectWidth;
 
+	// draw the X itself
 	cairo_set_line_width(pCairo, 2.0);
 	cairo_move_to(pCairo, (((fBoxX + fBoxWidth) - fCloseRectRelief) - fCloseRectWidth) + 3, fBoxY + fCloseRectRelief + 3);
 	cairo_rel_line_to(pCairo, fCloseRectWidth - 6, fCloseRectWidth - 6);
@@ -1408,6 +1486,8 @@
 	cairo_rel_line_to(pCairo, (fCloseRectWidth - 6), -(fCloseRectWidth - 6));
 	cairo_stroke(pCairo);
 	// END [X]
+
+	cairo_restore(pCairo);
 }
 
 static void map_draw_cairo_locationselection(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationSelectionArray)
@@ -1452,8 +1532,8 @@
 		pLocationSelection->m_InfoBoxRect.m_B.m_nY = (gint)(fBoxY + fBoxHeight);
 
 		map_draw_cairo_locationselection_outline(pCairo, fX, fY, &(pLocationSelection->m_InfoBoxRect), &(pLocationSelection->m_InfoBoxCloseRect));
-
-		gchar* pszFontFamily = ROAD_FONT;
+/*
+		gchar* pszFontFamily = ROAD_FONT;	// XXX: remove hardcoded font
 		gint fTitleFontSize = 15.0;
 		gint fBodyFontSize = 13.0;
 
@@ -1506,7 +1586,7 @@
 				cairo_show_text(pCairo, pszLine);
 
 				if(aLines[1]) {
-					g_print("line 2\n");
+					//g_print("line 2\n");
 					// draw address, line 2
 					pszLine = aLines[1];
 
@@ -1532,8 +1612,7 @@
 //                 cairo_text_extents(pCairo, pszString, &extents);
 //                 fLabelWidth = extents.width;
 //                 fFontHeight = extents.height;
-//                 cairo_underline_text(pCairo, fLabelWidth);
-		
+//                 map_draw_text_underline(pCairo, fLabelWidth);
 
 		// draw website link
 		fTextOffsetX = fBoxX;
@@ -1544,8 +1623,8 @@
 		fFontHeight = extents.height;
 		cairo_move_to(pCairo, fTextOffsetX, fTextOffsetY);
 		cairo_set_source_rgb(pCairo, 0.1,0.1,0.4);	// remote link color
+		map_draw_text_underline(pCairo, fLabelWidth);
 		cairo_show_text(pCairo, pszString);
-		cairo_underline_text(pCairo, fLabelWidth);
 
 		screenrect_t* pRect = &(pLocationSelection->m_aURLs[pLocationSelection->m_nNumURLs].m_Rect);
 		pRect->m_A.m_nX = fTextOffsetX;
@@ -1570,19 +1649,22 @@
 
 		cairo_move_to(pCairo, fTextOffsetX, fTextOffsetY);
 		cairo_show_text(pCairo, pszString);
-		cairo_underline_text(pCairo, fLabelWidth);
+		map_draw_text_underline(pCairo, fLabelWidth);
 		
 		pRect = &(pLocationSelection->m_EditRect);
 		pRect->m_A.m_nX = fTextOffsetX;
 		pRect->m_A.m_nY = fTextOffsetY - fFontHeight;
 		pRect->m_B.m_nX = fTextOffsetX + fLabelWidth;
 		pRect->m_B.m_nY = fTextOffsetY;
+*/
 	}
 	cairo_restore(pCairo);
 }
 
 #ifdef ROADSTER_DEAD_CODE
 /*
+<<<<<<< map_draw_cairo.c
+=======
 //
 // Draw a crosshair
 //
@@ -1682,8 +1764,6 @@
 
 		gint i;
 		for(i=1 ; i<pPointString->m_pPointsArray->len ; i++) {
-			RENDERING_THREAD_YIELD;
-			
 			pPoint = g_ptr_array_index(pPointString->m_pPointsArray, i);
 			cairo_line_to(pCairo, SCALE_X(pRenderMetrics, pPoint->m_fLongitude), SCALE_Y(pRenderMetrics, pPoint->m_fLatitude));
 		}

Index: map_draw_gdk.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_gdk.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- map_draw_gdk.c	23 Apr 2005 18:13:39 -0000	1.14
+++ map_draw_gdk.c	28 Aug 2005 22:23:14 -0000	1.15
@@ -203,7 +203,7 @@
 	}
 
 	// XXX: Don't use round at low zoom levels
-	// gint nCapStyle = pSubLayerStyle->m_nCapStyle;
+//	gint nCapStyle = pSubLayerStyle->m_nCapStyle;
 	gint nCapStyle = GDK_CAP_ROUND;
 	if(fLineWidth < 8) {
 		nCapStyle = GDK_CAP_PROJECTING;

Index: point.c
===================================================================
RCS file: /cvs/cairo/roadster/src/point.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- point.c	28 Mar 2005 18:49:50 -0000	1.4
+++ point.c	28 Aug 2005 22:23:14 -0000	1.5
@@ -78,3 +78,8 @@
 #endif
 }
 
+void point_debug_print(mappoint_t* pPoint)
+{
+	g_print("pt (%f, %f)\n", pPoint->m_fLatitude, pPoint->m_fLongitude);
+}
+

Index: pointstring.c
===================================================================
RCS file: /cvs/cairo/roadster/src/pointstring.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- pointstring.c	28 Mar 2005 18:49:50 -0000	1.5
+++ pointstring.c	28 Aug 2005 22:23:14 -0000	1.6
@@ -104,3 +104,12 @@
 
 	g_ptr_array_add(pPointString->m_pPointsArray, pNewPoint);
 }
+
+void pointstring_debug_print(pointstring_t* pPointString)
+{
+	int i;
+	for(i=0 ; i<pPointString->m_pPointsArray->len ; i++) {
+		mappoint_t* pPoint = g_ptr_array_index(pPointString->m_pPointsArray, i);
+		g_print("(%f, %f)", pPoint->m_fLatitude, pPoint->m_fLongitude);
+	}
+}

Index: prefs.c
===================================================================
RCS file: /cvs/cairo/roadster/src/prefs.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- prefs.c	28 Mar 2005 18:49:50 -0000	1.2
+++ prefs.c	28 Aug 2005 22:23:14 -0000	1.3
@@ -29,13 +29,11 @@
 
 /*
 #include <glib.h>
-#include <glib.h>
 
 struct {
 	GKeyFile* m_pKeyFile;
 } g_Prefs = {0};
 
-
 #define KEYFILE_GROUP_GUI_STATE  	("state")
 #define KEYFILE_KEY_LATITUDE		("latitude")
 
@@ -49,9 +47,7 @@
 		
 	}
 
-        gchar* pszValue;
-
-	//
+	gchar* pszValue;
 	pszValue = g_key_file_get_value(g_Prefs.m_pKeyFile,
                                              KEYFILE_GROUP_GUI_STATE,
                                              KEYFILE_KEY_LATITUDE,

Index: road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/road.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- road.c	28 Mar 2005 18:49:50 -0000	1.3
+++ road.c	28 Aug 2005 22:23:14 -0000	1.4
@@ -260,4 +260,3 @@
 	}
 	return FALSE;
 }
-

Index: scenemanager.c
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- scenemanager.c	28 Mar 2005 18:49:50 -0000	1.10
+++ scenemanager.c	28 Aug 2005 22:23:14 -0000	1.11
@@ -62,11 +62,10 @@
 gboolean scenemanager_can_draw_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints)
 {
 	GdkRegion* pNewRegion = gdk_region_polygon(pPoints, nNumPoints, GDK_WINDING_RULE);
-	
-	// Set pNewRegion to the intersection of it and the 'taken region'
-	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion);
+
+	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion); // sets pNewRegion to the intersection of itself and the 'taken region'
 	gboolean bOK = gdk_region_empty(pNewRegion);	// it's ok to draw here if the intersection is empty
-        gdk_region_destroy(pNewRegion);
+	gdk_region_destroy(pNewRegion);
 
 	return bOK;
 }
@@ -75,10 +74,9 @@
 {
 	GdkRegion* pNewRegion = gdk_region_rectangle(pRect);
 
-	// Set pNewRegion to the intersection of it and the 'taken region'
-	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion);
+	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion); // sets pNewRegion to the intersection of itself and the 'taken region'
 	gboolean bOK = gdk_region_empty(pNewRegion);	// it's ok to draw here if the intersection is empty
-        gdk_region_destroy(pNewRegion);
+	gdk_region_destroy(pNewRegion);
 
 	return bOK;
 }
@@ -96,7 +94,7 @@
 	// Create a GdkRegion from the given points and union it with the 'taken region'
 	GdkRegion* pNewRegion = gdk_region_polygon(pPoints, nNumPoints, GDK_WINDING_RULE);
 	gdk_region_union(pSceneManager->m_pTakenRegion, pNewRegion);
-        gdk_region_destroy(pNewRegion);
+	gdk_region_destroy(pNewRegion);
 }
 
 void scenemanager_claim_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect)
@@ -109,11 +107,11 @@
 {
 	g_assert(pSceneManager != NULL);
 
-	// destroy and recreate hash table (better way to clear it?)
+	// destroy and recreate hash table (XXX: better way to clear it?)
 	g_hash_table_destroy(pSceneManager->m_pLabelHash);
 	pSceneManager->m_pLabelHash = g_hash_table_new(g_str_hash, g_str_equal);
 
-	// Empty the region (better way?)
+	// Empty the region (XXX: better way?)
 	gdk_region_destroy(pSceneManager->m_pTakenRegion);
 	pSceneManager->m_pTakenRegion = gdk_region_new();
 }

Index: search_road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/search_road.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- search_road.c	23 Apr 2005 18:13:39 -0000	1.19
+++ search_road.c	28 Aug 2005 22:23:14 -0000	1.20
@@ -50,25 +50,6 @@
 #define MAX_QUERY 				(4000)
 #define ROAD_MIN_LENGTH_FOR_WILDCARD_SEARCH	(3)
 
-gchar* g_strjoinv_limit(const gchar* separator, gchar** a, gint iFirst, gint iLast)
-{
-	g_assert(iFirst <= iLast);
-	g_assert(iLast < g_strv_length(a));
-
-	gchar* pszSave;
-
-	// replace first unwanted string with NULL (save old value)
-	pszSave = a[iLast+1];
-	a[iLast+1] = NULL;
-
-	// use built-in function for joining
-	gchar* pszReturn = g_strjoinv(separator, &a[iFirst]);
-
-	// restore old value
-	a[iLast+1] = pszSave;
-	return pszReturn;
-}
-
 gboolean search_address_match_zipcode(const gchar* pszWord)
 {
 	// very US-centric right now
@@ -361,7 +342,7 @@
 			// [0] Road.ID
 			// [1] RoadName.Name
 			// [2] RoadName.SuffixID
-			// [3] AsText(Road.Coordinates),
+			// [3] AsBinary(Road.Coordinates),
 			// [4] Road.AddressLeftStart,
 			// [5] Road.AddressLeftEnd
 			// [6] Road.AddressRightStart
@@ -513,7 +494,7 @@
 		const gchar* pszCityNameLeft, const gchar* pszCityNameRight,
 		const gchar* pszStateNameLeft, const gchar* pszStateNameRight,
 		const gchar* pszZIPLeft, const gchar* pszZIPRight,
-		
+
 		pointstring_t* pPointString)
 {
 	gint nRoadID = 0;

Index: searchwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/searchwindow.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- searchwindow.c	23 Apr 2005 18:13:39 -0000	1.18
+++ searchwindow.c	28 Aug 2005 22:23:14 -0000	1.19
@@ -46,14 +46,8 @@
 #define MAGIC_GTK_NO_SORT_COLUMN (-2)	// why -2?  dunno.  is there a real define for this?  dunno.
 
 struct {
-	// window
-	GtkComboBox* m_pSearchTypeComboBox;		// choose between types of searches
-
-	// search text box (on the toolbar)
-	GtkEntry* m_pSearchEntry;
-
-	// search button (on the toolbar)
-	GtkButton* m_pSearchButton;
+	GtkEntry* m_pSearchEntry;		// search text box (on the toolbar)
+	GtkButton* m_pSearchButton;		// search button (on the toolbar)
 
 	// results list (on the sidebar)
 	GtkTreeView* m_pResultsTreeView;
@@ -147,7 +141,8 @@
 
 	gdouble fDistance = map_get_distance_in_meters(&ptCenter, pPoint);
 
-	gchar* pszBuffer = g_strdup_printf("<span size='small'>%s</span>", pszText);
+	gchar* pszBuffer = g_markup_printf_escaped("<span size='small'>%s</span>", pszText);
+	//g_print("Adding: (%f,%f) (%f) %s\n", pPoint->m_fLatitude, pPoint->m_fLongitude, fDistance, pszBuffer);
 	gtk_list_store_append(g_SearchWindow.m_pResultsListStore, &iter);
 	gtk_list_store_set(g_SearchWindow.m_pResultsListStore, &iter,
 		RESULTLIST_COLUMN_NAME, pszBuffer,

Index: tooltip.c
===================================================================
RCS file: /cvs/cairo/roadster/src/tooltip.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- tooltip.c	29 Mar 2005 09:16:20 -0000	1.3
+++ tooltip.c	28 Aug 2005 22:23:14 -0000	1.4
@@ -54,7 +54,7 @@
 	pNew->m_pLabel = GTK_LABEL(gtk_label_new("testing"));
 	gtk_container_add(GTK_CONTAINER(pFrame), GTK_WIDGET(pNew->m_pLabel));
 
-	pNew->m_bEnabled = TRUE;	// XXX: note: currently no API to disable it
+	pNew->m_bEnabled = TRUE;	// XXX: currently no API to disable it
 
 	return pNew;
 }

Index: util.c
===================================================================
RCS file: /cvs/cairo/roadster/src/util.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- util.c	23 Apr 2005 18:13:39 -0000	1.6
+++ util.c	28 Aug 2005 22:23:14 -0000	1.7
@@ -40,28 +40,152 @@
 	// This is why we use g_spawn_async, which lets us mark the URI as a parameter instead
 	// of just part of the command line (it could be "; rm / -rf" or something...)
 
-	char *pszCommand = NULL;
 	GError *pError = NULL;
 
 	// if they are running gnome, use the gnome web browser
 	if (util_running_gnome() == FALSE) return;
 
-
 	gchar **argv = g_malloc0(sizeof(gchar*) * 3);
 	argv[0] = "gnome-open";
 	argv[1] = pszDangerousURI;
 	argv[2] = NULL;
 
 	if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &pError)) {
-		// XXX: error message?
+		// XXX: error message?  or make this function return boolean?
 		g_error_free(pError);
 	}
 	g_free(argv);
-	g_free(pszCommand);
 }
 
-// if glib < 2.6
+gchar* g_strjoinv_limit(const gchar* separator, gchar** a, gint iFirst, gint iLast)
+{
+	g_assert(iFirst <= iLast);
+	g_assert(iLast < g_strv_length(a));
+
+	gchar* pszSave;
+
+	// replace first unwanted string with NULL (save old value)
+	pszSave = a[iLast+1];
+	a[iLast+1] = NULL;
+
+	// use built-in function for joining (returns a newly allocated string)
+	gchar* pszReturn = g_strjoinv(separator, &a[iFirst]);
+
+	// restore old value
+	a[iLast+1] = pszSave;
+	return pszReturn;
+}
+
+gchar** util_split_words_onto_two_lines(const gchar* pszText, gint nMinLineLength, gint nMaxLineLength)
+{
+	g_assert_not_reached();	// untested
+
+#define MAX_WORDS_WE_CAN_HANDLE (6)
+
+	// NOTE: 'nMinLineLength' and 'nMaxLineLength' are loosely enforced
+
+	//
+	// Split sentence into words, count words, measure words
+	//
+	gchar** aWords = g_strsplit(pszText, " ", 0);	// " " = delimeters, 0 = no max #
+	gint nWordCount = g_strv_length(aWords);
+
+	gint* aWordLengths = g_new0(gint, nWordCount);
+	gint i;
+	for(i=0 ; i<nWordCount ; i++) {
+		aWordLengths[i] = strlen(aWords[i]);
+	}
+
+	gint nTotalLength = strlen(pszText);
+
+	//
+	// Assemble into sentences
+	//
+	gchar** aLines = g_new0(gchar*, 2);
+
+	if(nTotalLength <= nMaxLineLength || (nWordCount > MAX_WORDS_WE_CAN_HANDLE)) {
+		// done!
+		aLines[0] = g_strdup(pszText);
+	}
+	else {
+		// We could probably write a nice algorithm to handle this generically...
+		// ...but hardcoding it is easier to write and debug.
+
+		switch(nWordCount) {
+		case 1:
+			aLines[0] = g_strdup(pszText);	// no other choice
+			break;
+		case 2:
+			// Don't put little words by themselves on a line (yes, the result may be > nMaxCharsOnOneLine)
+			if((aWordLengths[0] < nMinLineLength) || (aWordLengths[1] < nMinLineLength)) {
+				aLines[0] = g_strdup(pszText);
+			}
+			else {
+				// two lines
+				aLines[0] = g_strdup(aWords[0]);
+				aLines[1] = g_strdup(aWords[1]);
+			}
+			break;
+		case 3:
+			// Definitely two lines.  Put the middle word with the shorter of the first|second.
+			if(aWordLengths[0] > aWordLengths[2]) {
+				// 1 word on first line, 2 on second
+				aLines[0] = g_strdup(aWords[0]);
+				aLines[1] = g_strjoinv_limit(" ", aWords, 1, 2);
+			}
+			else {
+				// 2 words on first line, 1 on second
+				aLines[0] = g_strjoinv_limit(" ", aWords, 0, 1);
+				aLines[1] = g_strdup(aWords[2]);
+			}
+			break;
+		case 4:
+			if((aWordLengths[0] + aWordLengths[1] + aWordLengths[2]) < aWordLengths[3]) {
+				// 3 and 1
+				aLines[0] = g_strjoinv_limit(" ", aWords, 0, 2);
+				aLines[1] = g_strdup(aWords[3]);
+			}
+			else if(aWordLengths[0] > (aWordLengths[1] + aWordLengths[2] + aWordLengths[3])) {
+				// 1 and 3
+				aLines[0] = g_strdup(aWords[0]);
+				aLines[1] = g_strjoinv_limit(" ", aWords, 1, 3);
+			}
+			else {
+				// 2 and 2
+				aLines[0] = g_strjoinv_limit(" ", aWords, 0, 1);
+				aLines[1] = g_strjoinv_limit(" ", aWords, 2, 3);
+			}
+			break;
+		case 5:
+			if((aWordLengths[0]+aWordLengths[1]) > (aWordLengths[3]+aWordLengths[4])) {
+				// 2 and 3
+				aLines[0] = g_strjoinv_limit(" ", aWords, 0, 1);
+				aLines[1] = g_strjoinv_limit(" ", aWords, 2, 4);
+			}
+			else {
+				// 3 and 2
+				aLines[0] = g_strjoinv_limit(" ", aWords, 0, 2);
+				aLines[1] = g_strjoinv_limit(" ", aWords, 3, 4);
+			}
+			break;
+		case 6:
+			aLines[0] = g_strjoinv_limit(" ", aWords, 0, 2);
+			aLines[1] = g_strjoinv_limit(" ", aWords, 3, 5);
+			break;
+		default:
+			g_assert_not_reached();
+			break;
+		}
+	}
+
+	g_strfreev(aWords);
+	g_free(aWordLengths);
+
+	return aLines;
+}
+
 #if(!GLIB_CHECK_VERSION(2,6,0))
+// if glib < 2.6 we need to provide this function ourselves
 gint g_strv_length(const gchar** a)
 {
 	gint nCount=0;
@@ -75,9 +199,7 @@
 #endif
 
 #if ROADSTER_DEAD_CODE
-#include <stdlib.h>
-#include "layers.h"		// for color_t -- move it elsewhere!
-static void util_random_color(color_t* pColor)
+void util_random_color(color_t* pColor)
 {
 	pColor->m_fRed = (random()%1000)/1000.0;
 	pColor->m_fGreen = (random()%1000)/1000.0;



More information about the cairo-commit mailing list