[cairo-commit] roadster/src db.c, 1.12, 1.13 db.h, 1.7, 1.8 import_tiger.c, 1.11, 1.12 locationset.c, 1.5, 1.6 mainwindow.c, 1.21, 1.22 map.c, 1.19, 1.20 map_draw_cairo.c, 1.7, 1.8 scenemanager.c, 1.7, 1.8 scenemanager.h, 1.4, 1.5 search_road.c, 1.13, 1.14

Ian McIntosh commit at pdx.freedesktop.org
Wed Mar 9 22:12:05 PST 2005


Committed by: ian

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

Modified Files:
	db.c db.h import_tiger.c locationset.c mainwindow.c map.c 
	map_draw_cairo.c scenemanager.c scenemanager.h search_road.c 
Log Message:
	* src/search_road.c:
	* src/import_tiger.c:
	* src/db.c: Removed Road_RoadName joiner table.  Roads can have only one name now (we never used this feature).
	* src/db.c: Removed warning for failed inserts (really should only avoid printing warnings for duplicates on unique keys).  Removed db_parse_point() that used MySQL's text format (no replacement yet but it's not used).  Removed some dead code.
	* src/mainwindow.c: Don't draw twice on zoom in/out.
	* src/map.c: Pulled font selection up a level, so it's done once per layer.  Added a demo of the scenemanager code (a square drawn on the map that text avoids!).  Tweaked scales for the zoom levels.
	* src/map_draw_cairo.c: Added a simpler line labeler for single-segment roads (we need to profile it to see if it's worth using).  Curved text is temporarily turned off because it doesn't use the scenemanager yet.  All gfloats to gdoubles.
        * src/scenemanager.c: Added scenemanager_can_draw_rectangle().


Index: db.c
===================================================================
RCS file: /cvs/cairo/roadster/src/db.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- db.c	4 Mar 2005 02:27:29 -0000	1.12
+++ db.c	10 Mar 2005 06:12:03 -0000	1.13
@@ -55,41 +55,71 @@
 db_connection_t* g_pDB = NULL;
 
 
-gboolean db_query(const gchar* pszSQL, db_resultset_t** ppResultSet)
+/******************************************************
+** Init and deinit of database module
+******************************************************/
+
+// call once on program start-up
+void db_init()
 {
-	g_assert(pszSQL != NULL);
-	if(g_pDB == NULL) return FALSE;
+//	g_pDBMutex = g_mutex_new();
 
-	if(mysql_query(g_pDB->m_pMySQLConnection, pszSQL) != MYSQL_RESULT_SUCCESS) {
-		g_warning("db_query: %s (SQL: %s)\n", mysql_error(g_pDB->m_pMySQLConnection), pszSQL);
-		return FALSE;
+#ifdef HAVE_MYSQL_EMBED
+	gchar* pszDataDir = g_strdup_printf("%s/.roadster/data", g_get_home_dir());
+	gchar* pszSetDataDirCommand = g_strdup_printf("--datadir=%s", pszDataDir);
+
+	// Create directory if it doesn't exist
+	if(GNOME_VFS_OK != gnome_vfs_make_directory(pszDataDir, 0700)) {
+		// no big deal, probably already exists (should we check?)
 	}
 
-	// get result?
-	if(ppResultSet != NULL) {
-		*ppResultSet = (db_resultset_t*)MYSQL_GET_RESULT(g_pDB->m_pMySQLConnection);
+	gchar* apszServerOptions[] = {
+		"",	// program name -- unused
+		"--skip-innodb",	// don't bother with table types we don't use
+		"--skip-bdb",		//
+
+//                 "--query_cache_type=1",
+//                 "--query_cache_size=40MB",
+
+//		"--flush",			// seems like a good idea since users can quickly kill the app/daemon
+		pszSetDataDirCommand
+	};
+
+	// Initialize the embedded server
+	// NOTE: if not linked with libmysqld, this call will do nothing (but will succeed)
+ 	if(mysql_server_init(NUM_ELEMS(apszServerOptions), apszServerOptions, NULL) != 0) {
+		return;
 	}
-	return TRUE;
+	g_free(pszDataDir);
+	g_free(pszSetDataDirCommand);
+#endif
 }
 
-static gboolean db_insert(const gchar* pszSQL, gint* pnReturnRowsInserted)
+// call once on program shut-down
+void db_deinit()
+{
+#ifdef HAVE_MYSQL_EMBED
+	// Close embedded server if present
+	mysql_server_end();
+#endif
+}
+
+gboolean db_query(const gchar* pszSQL, db_resultset_t** ppResultSet)
 {
 	g_assert(pszSQL != NULL);
 	if(g_pDB == NULL) return FALSE;
 
-	if(mysql_query(g_pDB->m_pMySQLConnection, pszSQL) != MYSQL_RESULT_SUCCESS) {
+	gint nResult = mysql_query(g_pDB->m_pMySQLConnection, pszSQL);
+	if(nResult != MYSQL_RESULT_SUCCESS) {
 		g_warning("db_query: %s (SQL: %s)\n", mysql_error(g_pDB->m_pMySQLConnection), pszSQL);
 		return FALSE;
 	}
 
-	my_ulonglong uCount = mysql_affected_rows(g_pDB->m_pMySQLConnection);
-	if(uCount > 0) {
-		if(pnReturnRowsInserted != NULL) {
-			*pnReturnRowsInserted = uCount;
-		}
-		return TRUE;
+	// get result?
+	if(ppResultSet != NULL) {
+		*ppResultSet = (db_resultset_t*)MYSQL_GET_RESULT(g_pDB->m_pMySQLConnection);
 	}
-	return FALSE;
+	return TRUE;
 }
 
 db_row_t db_fetch_row(db_resultset_t* pResultSet)
@@ -109,9 +139,38 @@
 }
 
 /******************************************************
-** database utility functions
+** Connection creation and destruction
 ******************************************************/
 
+// initiate a new connection to server
+gboolean db_connect(const gchar* pzHost, const gchar* pzUserName, const gchar* pzPassword, const gchar* pzDatabase)
+{
+	// create a MySQL connection context
+	MYSQL *pMySQLConnection = mysql_init(NULL);
+	g_return_val_if_fail(pMySQLConnection != NULL, FALSE);
+
+	// attempt a MySQL connection
+	if(mysql_real_connect(pMySQLConnection, pzHost, pzUserName, pzPassword, pzDatabase, 0, NULL, 0) == FALSE) {
+		g_warning("mysql_real_connect failed: %s\n", mysql_error(pMySQLConnection));
+		return FALSE;
+	}
+//	db_enable_keys(); // just in case
+
+	// on success, alloc our connection struct and fill it
+	db_connection_t* pNewConnection = g_new0(db_connection_t, 1);
+	pNewConnection->m_pMySQLConnection = pMySQLConnection;
+	pNewConnection->m_pzHost = g_strdup(pzHost);
+	pNewConnection->m_pzUserName = g_strdup(pzUserName);
+	pNewConnection->m_pzPassword = g_strdup(pzPassword);
+	pNewConnection->m_pzDatabase = g_strdup(pzDatabase);
+
+	g_assert(g_pDB == NULL);
+	g_pDB = pNewConnection;
+
+	// just in case (this could mess with multi-user databases)
+	return TRUE;
+}
+
 static gboolean db_is_connected(void)
 {
 	// 'mysql_ping' will also attempt a re-connect if necessary
@@ -128,6 +187,11 @@
 	return mysql_get_host_info(g_pDB->m_pMySQLConnection);
 }
 
+
+/******************************************************
+** database utility functions
+******************************************************/
+
 // call db_free_escaped_string() on returned string
 gchar* db_make_escaped_string(const gchar* pszString)
 {
@@ -176,87 +240,30 @@
 }
 
 /******************************************************
-** Init and deinit of database module
-******************************************************/
-
-// call once on program start-up
-void db_init()
-{
-//	g_pDBMutex = g_mutex_new();
-
-#ifdef HAVE_MYSQL_EMBED
-	gchar* pszDataDir = g_strdup_printf("%s/.roadster/data", g_get_home_dir());
-	gchar* pszSetDataDirCommand = g_strdup_printf("--datadir=%s", pszDataDir);
-
-	// Create directory if it doesn't exist
-	if(GNOME_VFS_OK != gnome_vfs_make_directory(pszDataDir, 0700)) {
-		// no big deal, probably already exists (should we check?)
-	}
-
-	gchar* apszServerOptions[] = {
-		"",	// program name -- unused
-		"--skip-innodb",	// don't bother with table types we don't use
-		"--skip-bdb",		//
-//		"--flush",			// seems like a good idea since users can quickly kill the app/daemon
-		pszSetDataDirCommand
-	};
-
-	// Initialize the embedded server
-	// NOTE: if not linked with libmysqld, this call will do nothing (but will succeed)
- 	if(mysql_server_init(NUM_ELEMS(apszServerOptions), apszServerOptions, NULL) != 0) {
-		return;
-	}
-	g_free(pszDataDir);
-	g_free(pszSetDataDirCommand);
-#endif
-}
-
-// call once on program shut-down
-void db_deinit()
-{
-#ifdef HAVE_MYSQL_EMBED
-	// Close embedded server if present
-	mysql_server_end();
-#endif
-}
-
-/******************************************************
-** Connection creation and destruction
+** data inserting
 ******************************************************/
 
-// initiate a new connection to server
-gboolean db_connect(const gchar* pzHost, const gchar* pzUserName, const gchar* pzPassword, const gchar* pzDatabase)
+static gboolean db_insert(const gchar* pszSQL, gint* pnReturnRowsInserted)
 {
-	// create a MySQL connection context
-	MYSQL *pMySQLConnection = mysql_init(NULL);
-	g_return_val_if_fail(pMySQLConnection != NULL, FALSE);
+	g_assert(pszSQL != NULL);
+	if(g_pDB == NULL) return FALSE;
 
-	// attempt a MySQL connection
-	if(mysql_real_connect(pMySQLConnection, pzHost, pzUserName, pzPassword, pzDatabase, 0, NULL, 0) == FALSE) {
-		g_warning("mysql_real_connect failed: %s\n", mysql_error(pMySQLConnection));
+	if(mysql_query(g_pDB->m_pMySQLConnection, pszSQL) != MYSQL_RESULT_SUCCESS) {
+		//g_warning("db_query: %s (SQL: %s)\n", mysql_error(g_pDB->m_pMySQLConnection), pszSQL);
 		return FALSE;
 	}
-//	db_enable_keys(); // just in case
-
-	// on success, alloc our connection struct and fill it
-	db_connection_t* pNewConnection = g_new0(db_connection_t, 1);
-	pNewConnection->m_pMySQLConnection = pMySQLConnection;
-	pNewConnection->m_pzHost = g_strdup(pzHost);
-	pNewConnection->m_pzUserName = g_strdup(pzUserName);
-	pNewConnection->m_pzPassword = g_strdup(pzPassword);
-	pNewConnection->m_pzDatabase = g_strdup(pzDatabase);
 
-	g_assert(g_pDB == NULL);
-	g_pDB = pNewConnection;
-
-	// just in case (this could mess with multi-user databases)
-	return TRUE;
+	my_ulonglong uCount = mysql_affected_rows(g_pDB->m_pMySQLConnection);
+	if(uCount > 0) {
+		if(pnReturnRowsInserted != NULL) {
+			*pnReturnRowsInserted = uCount;
+		}
+		return TRUE;
+	}
+	return FALSE;
 }
 
-/******************************************************
-** data inserting
-******************************************************/
-gboolean db_insert_road(gint nLayerType, gint nAddressLeftStart, gint nAddressLeftEnd, gint nAddressRightStart, gint nAddressRightEnd, gint nCityLeftID, gint nCityRightID, const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight, GPtrArray* pPointsArray, gint* pReturnID)
+gboolean db_insert_road(gint nRoadNameID, gint nLayerType, gint nAddressLeftStart, gint nAddressLeftEnd, gint nAddressRightStart, gint nAddressRightEnd, gint nCityLeftID, gint nCityRightID, const gchar* pszZIPCodeLeft, const gchar* pszZIPCodeRight, GPtrArray* pPointsArray, gint* pReturnID)
 {
 	g_assert(pReturnID != NULL);
 	if(!db_is_connected()) return FALSE;
@@ -278,11 +285,11 @@
 
 	gchar azQuery[MAX_SQLBUFFER_LEN];
 	g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
-		"INSERT INTO %s SET TypeID=%d, Coordinates=GeometryFromText('LINESTRING(%s)')"
+		"INSERT INTO %s SET RoadNameID=%d, TypeID=%d, Coordinates=GeometryFromText('LINESTRING(%s)')"
 		", AddressLeftStart=%d, AddressLeftEnd=%d, AddressRightStart=%d, AddressRightEnd=%d"
 		", CityLeftID=%d, CityRightID=%d"
 		", ZIPCodeLeft='%s', ZIPCodeRight='%s'",
-		DB_ROADS_TABLENAME, nLayerType, azCoordinateList,
+		DB_ROADS_TABLENAME, nRoadNameID, nLayerType, azCoordinateList,
 	    nAddressLeftStart, nAddressLeftEnd, nAddressRightStart, nAddressRightEnd,
 		nCityLeftID, nCityRightID,
 		pszZIPCodeLeft, pszZIPCodeRight);
@@ -296,6 +303,10 @@
 	return TRUE;
 }
 
+/******************************************************
+**
+******************************************************/
+
 static gboolean db_roadname_get_id(const gchar* pszName, gint nSuffixID, gint* pnReturnID)
 {
 	gint nReturnID = 0;
@@ -310,6 +321,7 @@
 	db_row_t aRow;
 	db_query(pszSQL, &pResultSet);
 	g_free(pszSQL);
+
 	// get result?
 	if(pResultSet) {
 		if((aRow = db_fetch_row(pResultSet)) != NULL) {
@@ -325,9 +337,10 @@
 	return FALSE;
 }
 
-gboolean db_insert_roadname(gint nRoadID, const gchar* pszName, gint nSuffixID)
+gboolean db_insert_roadname(const gchar* pszName, gint nSuffixID, gint* pnReturnID)
 {
 	gint nRoadNameID = 0;
+
 	// Step 1. Insert into RoadName
 	if(db_roadname_get_id(pszName, nSuffixID, &nRoadNameID) == FALSE) {
 		gchar* pszSafeName = db_make_escaped_string(pszName);
@@ -339,19 +352,12 @@
 		}
 		g_free(pszSQL);
 	}
-
-	// Step 2. Insert connector into Road_RoadName
+	
 	if(nRoadNameID != 0) {
-		gchar* pszSQL = g_strdup_printf("INSERT INTO Road_RoadName SET RoadID='%d', RoadNameID='%d'",
-			nRoadID, nRoadNameID);
-		if(db_insert(pszSQL, NULL)) {
-			g_free(pszSQL);
-			return TRUE;
-		}
-		else {
-			g_free(pszSQL);
-			return FALSE;
+		if(pnReturnID != NULL) {
+			*pnReturnID = nRoadNameID;
 		}
+		return TRUE;
 	}
 	return FALSE;
 }
@@ -471,31 +477,6 @@
 	return TRUE;
 }
 
-void db_parse_point(const gchar* pszText, mappoint_t* pPoint)
-{
-	const gchar* p;
-
-	p = pszText;
-
-	if(p[0] == 'P') { //g_str_has_prefix(p, "POINT")) {
-		// format is "POINT(1.2345 -5.4321)"
-
-		p += (6); 	// move past "POINT("
-		pPoint->m_fLatitude = g_ascii_strtod(p, (gchar**)&p);
-
-		// space between coordinates
-		g_return_if_fail(*p == ' ');
-		p++;
-
-		pPoint->m_fLongitude = g_ascii_strtod(p, (gchar**)&p);
-		g_return_if_fail(*p == ')');
-		g_return_if_fail(*(p+1) == '\0');
-	}
-	else {
-		g_assert_not_reached();
-	}	
-}
-
 #define WKB_POINT                  1	// only two we care about
 #define WKB_LINESTRING             2
 
@@ -533,19 +514,26 @@
 	db_query("CREATE TABLE IF NOT EXISTS Road("
 		" ID INT4 UNSIGNED NOT NULL AUTO_INCREMENT,"
 		" TypeID INT1 UNSIGNED NOT NULL,"
+
+		" RoadNameID INT4 UNSIGNED NOT NULL,"
+
 		" AddressLeftStart INT2 UNSIGNED NOT NULL,"
 		" AddressLeftEnd INT2 UNSIGNED NOT NULL,"
 		" AddressRightStart INT2 UNSIGNED NOT NULL,"
 		" AddressRightEnd INT2 UNSIGNED NOT NULL,"
-	    " CityLeftID INT4 UNSIGNED NOT NULL,"
+		
+		" CityLeftID INT4 UNSIGNED NOT NULL,"
 		" CityRightID INT4 UNSIGNED NOT NULL,"
+		
 		" ZIPCodeLeft CHAR(6) NOT NULL,"
 		" ZIPCodeRight CHAR(6) NOT NULL,"
+
 		" Coordinates point NOT NULL,"
-		
+
 	    // lots of indexes:
 		" PRIMARY KEY (ID),"
-	    " INDEX(TypeID),"
+		" INDEX(TypeID),"
+		" INDEX(RoadNameID),"	// to get roads when we've matched a RoadName
 		" INDEX(AddressLeftStart, AddressLeftEnd),"
 		" INDEX(AddressRightStart, AddressRightEnd),"
 		" SPATIAL KEY (Coordinates));", NULL);
@@ -559,12 +547,12 @@
 		" UNIQUE KEY (Name(15), SuffixID));", NULL);
 
 	// Road_RoadName
-	db_query("CREATE TABLE IF NOT EXISTS Road_RoadName("
-		" RoadID INT4 UNSIGNED NOT NULL,"
-		" RoadNameID INT4 UNSIGNED NOT NULL,"
-		
-	    " PRIMARY KEY (RoadID, RoadNameID),"	// allows search on (RoadID,RoadName) and just (RoadID)
-		" INDEX(RoadNameID));", NULL);			// allows search the other way, going from a Name to a RoadID
+//         db_query("CREATE TABLE IF NOT EXISTS Road_RoadName("
+//                 " RoadID INT4 UNSIGNED NOT NULL,"
+//                 " RoadNameID INT4 UNSIGNED NOT NULL,"
+//
+//                 " PRIMARY KEY (RoadID, RoadNameID),"    // allows search on (RoadID,RoadName) and just (RoadID)
+//                 " INDEX(RoadNameID));", NULL);          // allows search the other way, going from a Name to a RoadID
 
 	// City
 	db_query("CREATE TABLE IF NOT EXISTS City("
@@ -573,7 +561,7 @@
 		" StateID INT4 UNSIGNED NOT NULL,"
 		" Name CHAR(60) NOT NULL,"
 		" PRIMARY KEY (ID),"
-		" INDEX (StateID),"		// for finding all cities by state (needed?)
+		" INDEX (StateID),"	// for finding all cities by state (needed?)
 		" INDEX (Name(15)));"	// only index the first X chars of name (who types more than that?) (are city names ever 60 chars anyway??  TIGER think so)
 	    ,NULL);
 
@@ -581,9 +569,9 @@
 	db_query("CREATE TABLE IF NOT EXISTS State("
 		// a unique ID for the value
 		" ID INT4 UNSIGNED NOT NULL AUTO_INCREMENT,"
-	    " Name CHAR(40) NOT NULL,"
-	    " Code CHAR(3) NOT NULL,"		//
-		" CountryID INT4 NOT NULL,"		//
+		" Name CHAR(40) NOT NULL,"
+		" Code CHAR(3) NOT NULL,"
+		" CountryID INT4 NOT NULL,"
 		" PRIMARY KEY (ID),"
 		" INDEX (Name(15)));"	// only index the first X chars of name (who types more than that?)
 	    ,NULL);
@@ -614,7 +602,7 @@
 		" AttributeNameID INT4 UNSIGNED NOT NULL,"
 		// the actual value, a text blob
 		" Value TEXT NOT NULL,"
-		" PRIMARY KEY (ID),"	// for fast deletes (needed only if POIs can have multiple values per name)
+		" PRIMARY KEY (ID),"	// for fast updates/deletes (needed only if POIs can have multiple values per name)
 		" INDEX (LocationID),"	// for searching values for a given POI
 		" FULLTEXT(Value));", NULL);
 
@@ -710,99 +698,6 @@
 	else return 0;
 }
 
-gboolean db_load_geometry(db_connection_t* pConnection, maprect_t* pRect, layer_t* pLayers, gint nNumLayers) //, geometryset_t* pGeometrySet)
-{
-	TIMER_BEGIN(mytimer, "BEGIN DB LOAD");
-
-//	g_return_val_if_fail(pGeometrySet != NULL, FALSE);
-	gint nZoomLevel = map_get_zoomlevel();
-	
-	if(!db_is_connected(pConnection)) return FALSE;
-
-	gchar* pszTable = DB_ROADS_TABLENAME; 	// use a hardcoded table name for now
-	
-	// HACKY: make a list of layer IDs "2,3,5,6"
-	gchar azLayerNumberList[200] = {0};
-	gint nActiveLayerCount = 0;
-	gint i;
-	for(i=LAYER_FIRST ; i <= LAYER_LAST ;i++) {
-		if(g_aLayers[i].m_Style.m_aSubLayers[0].m_afLineWidths[nZoomLevel-1] != 0.0 ||
-		   g_aLayers[i].m_Style.m_aSubLayers[1].m_afLineWidths[nZoomLevel-1] != 0.0)
-		{
-			gchar azLayerNumber[10];
-			if(nActiveLayerCount > 0) g_snprintf(azLayerNumber, 10, ",%d", i);
-			else g_snprintf(azLayerNumber, 10, "%d", i);
-			g_strlcat(azLayerNumberList, azLayerNumber, 200);
-			nActiveLayerCount++;
-		}
-	}
-	if(nActiveLayerCount == 0) {
-		g_print("no visible layers!\n");
-		layers_clear();
-		return TRUE;
-	}
-
-	// generate SQL
-	gchar azQuery[MAX_SQLBUFFER_LEN];
-	g_snprintf(azQuery, MAX_SQLBUFFER_LEN,
-		"SELECT ID, TypeID, AsText(Coordinates) FROM %s WHERE"
-		" TypeID IN (%s) AND" //
-		" MBRIntersects(GeomFromText('Polygon((%f %f,%f %f,%f %f,%f %f,%f %f))'), Coordinates)",
-		pszTable,
-		azLayerNumberList,
-		(nZoomLevel >= 9) ? 2 : 0,
-		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
-		);
-	TIMER_SHOW(mytimer, "after SQL generation");
-g_print("sql: %s\n", azQuery);
-	mysql_query(pConnection->m_pMySQLConnection, azQuery);
-	TIMER_SHOW(mytimer, "after query");
-
-	MYSQL_RES* pResultSet = MYSQL_GET_RESULT(pConnection->m_pMySQLConnection);
-	guint32 uRowCount = 0;
-
-	MYSQL_ROW aRow;
-	if(pResultSet) {
-		// HACK: empty out old data, since we don't know how to merge yet
-		layers_clear();
-		TIMER_SHOW(mytimer, "after clear layers");
-
-		while((aRow = mysql_fetch_row(pResultSet))) {
-			uRowCount++;
-
-			// aRow[0] is ID
-			// aRow[1] is TypeID
-			// aRow[2] is Coordinates in mysql's text format
-			//g_print("data: %s, %s, %s\n", aRow[0], aRow[1], aRow[2]);
-
-			gint nTypeID = atoi(aRow[1]);
-			if(nTypeID < LAYER_FIRST || nTypeID > LAYER_LAST) {
-				g_warning("geometry record '%s' has bad type '%s'\n", aRow[0], aRow[1]);
-				continue;
-			}
-
-			// add it to layer
-			geometryset_add_from_mysql_geometry(pLayers[nTypeID].m_pGeometrySet, aRow[2]);
-		} // end while loop on rows
-		g_print(" -- got %d rows\n", uRowCount);
-		TIMER_SHOW(mytimer, "after rows retrieved");
-
-		mysql_free_result(pResultSet);
-		TIMER_SHOW(mytimer, "after free results");
-		TIMER_END(mytimer, "END DB LOAD");
-
-		return TRUE;
-	}
-	else {
-		g_print(" no rows\n");
-		return FALSE;
-	}
-}
-
 void db_parse_pointstring(const gchar* pszText, pointstring_t* pPointString, gboolean (*callback_get_point)(mappoint_t**))
 {
 	// parse string and add points to the string
@@ -848,29 +743,5 @@
 		g_assert_not_reached();
 	}
 }
-
-GMutex* g_pDBMutex = NULL;
-
-void db_lock(void)
-{
-	g_mutex_lock(g_pDBMutex);
-}
-
-void db_unlock(void)
-{
-	g_mutex_unlock(g_pDBMutex);
-}
-
-void db_begin_thread(void)
-{
-	mysql_thread_init();
-}
-
-void db_end_thread(void)
-{
-	mysql_thread_end();
-}
-
 */
 #endif
-

Index: db.h
===================================================================
RCS file: /cvs/cairo/roadster/src/db.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- db.h	4 Mar 2005 02:27:29 -0000	1.7
+++ db.h	10 Mar 2005 06:12:03 -0000	1.8
@@ -56,7 +56,7 @@
 // utility
 gboolean db_is_empty(void);
 
-gboolean db_insert_roadname(gint nRoadID, const gchar* pszName, gint nSuffixID);
+gboolean db_insert_roadname(const gchar* pszName, gint nSuffixID, gint* pnReturnID);
 
 //~ gboolean db_create_points_db(const gchar* name);
 
@@ -87,7 +87,7 @@
 void db_disable_keys(void);
 
 gboolean db_insert_city(const gchar* pszName, gint nStateID, gint* pnReturnCityID);
-gboolean db_insert_road(gint nLayerType,
+gboolean db_insert_road(gint nRoadNameID, gint nLayerType,
 							gint nAddressLeftStart, gint nAddressLeftEnd,
 							gint nAddressRightStart, gint nAddressRightEnd,
 							gint nCityLeftID, gint nCityRightID,

Index: import_tiger.c
===================================================================
RCS file: /cvs/cairo/roadster/src/import_tiger.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- import_tiger.c	1 Mar 2005 19:48:21 -0000	1.11
+++ import_tiger.c	10 Mar 2005 06:12:03 -0000	1.12
@@ -801,8 +801,15 @@
 		gchar azZIPCodeRight[6];
 		g_snprintf(azZIPCodeRight, 6, "%05d", pRecordRT1->m_nZIPCodeRight);
 
+		gint nRoadNameID = 0;
+		if(pRecordRT1->m_achName[0] != '\0') {
+			//printf("inserting road name %s\n", pRecordRT1->m_achName);
+			db_insert_roadname(pRecordRT1->m_achName, pRecordRT1->m_nRoadNameSuffixID, &nRoadNameID);
+		}
+
 		gint nRoadID;
-		db_insert_road(pRecordRT1->m_nRecordType,
+		db_insert_road(nRoadNameID,
+			pRecordRT1->m_nRecordType,
 			pRecordRT1->m_nAddressLeftStart,
 			pRecordRT1->m_nAddressLeftEnd,
 			pRecordRT1->m_nAddressRightStart,
@@ -810,10 +817,6 @@
 			nCityLeftID, nCityRightID,
 			azZIPCodeLeft, azZIPCodeRight,
 			pTempPointsArray, &nRoadID);
-		if(pRecordRT1->m_achName[0] != '\0') {
-			//printf("inserting road name %s\n", pRecordRT1->m_achName);
-			db_insert_roadname(nRoadID, pRecordRT1->m_achName, pRecordRT1->m_nRoadNameSuffixID);
-		}
 	}
 	g_ptr_array_free(pTempPointsArray, FALSE);
 }
@@ -994,17 +997,21 @@
 
 		// insert record
 		if(pRecordRT7->m_nRecordType != LAYER_NONE) {
+			gint nRoadNameID = 0;
+			if(pRecordRT7->m_achName[0] != '\0') {
+				//g_printf("inserting area name %s\n", pRecordRT7->m_achName);
+				db_insert_roadname(pRecordRT7->m_achName, 0, &nRoadNameID);
+			}
+
 			gint nRoadID;
-			db_insert_road(pRecordRT7->m_nRecordType,
+			db_insert_road(
+				nRoadNameID,
+				pRecordRT7->m_nRecordType,
 				0,0,0,0,
 				nCityLeftID, nCityRightID,
 				pszZIPCodeLeft, pszZIPCodeRight,
 				pTempPointsArray, &nRoadID);
 
-			if(pRecordRT7->m_achName[0] != '\0') {
-				//g_printf("inserting area name %s\n", pRecordRT7->m_achName);
-				db_insert_roadname(nRoadID, pRecordRT7->m_achName, 0);
-			}
 		}
 	}
 	g_ptr_array_free(pTempPointsArray, FALSE);

Index: locationset.c
===================================================================
RCS file: /cvs/cairo/roadster/src/locationset.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- locationset.c	8 Mar 2005 18:40:50 -0000	1.5
+++ locationset.c	10 Mar 2005 06:12:03 -0000	1.6
@@ -226,7 +226,10 @@
 				location_t* pNewLocation = NULL;
 				if(location_new(&pNewLocation)) {
 					pNewLocation->m_nID = nLocationID;
-					db_parse_point(aRow[2], &pNewLocation->m_Coordinates);
+					
+					g_assert_not_reached();
+					// XXX: need to write this using MySQL WKB format
+					// db_parse_point(aRow[2], &pNewLocation->m_Coordinates);
 					g_ptr_array_add(pLocationSet->m_pLocationsArray, pNewLocation);
 				}
 			}

Index: mainwindow.c
===================================================================
RCS file: /cvs/cairo/roadster/src/mainwindow.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- mainwindow.c	8 Mar 2005 18:40:50 -0000	1.21
+++ mainwindow.c	10 Mar 2005 06:12:03 -0000	1.22
@@ -26,6 +26,7 @@
 #endif
 
 #include <gtk/gtk.h>
+#include <gtk/gtksignal.h>
 
 #include "search_road.h"
 #include "gui.h"
@@ -55,10 +56,10 @@
 #define PROGRAM_COPYRIGHT		"Copyright (c) 2005 Ian McIntosh"
 #define PROGRAM_DESCRIPTION		"Mapping for everyone!"
 
-#define DRAW_PRETTY_TIMEOUT_MS		(110)	// how long after stopping various movements should we redraw in high-quality mode
+#define DRAW_PRETTY_TIMEOUT_MS		(180)	// how long after stopping various movements should we redraw in high-quality mode
 #define SCROLL_TIMEOUT_MS		(100)	// how often (in MS) to move (SHORTER THAN ABOVE TIME)
 #define SCROLL_DISTANCE_IN_PIXELS	(100)	// how far to move every (above) MS
-#define BORDER_SCROLL_CLICK_TARGET_SIZE	(17)	// the size of the click target (distance from edge of map view) to begin scrolling
+#define BORDER_SCROLL_CLICK_TARGET_SIZE	(20)	// the size of the click target (distance from edge of map view) to begin scrolling
 
 // Layerlist columns
 #define LAYERLIST_COLUMN_ENABLED	(0)
@@ -550,23 +551,33 @@
 //
 void mainwindow_set_zoomlevel(gint nZoomLevel)
 {
+	// set zoomlevel scale but prevent it from calling handler (mainwindow_on_zoomscale_value_changed)
+        g_signal_handlers_block_by_func(g_MainWindow.m_pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
 	gtk_range_set_value(GTK_RANGE(g_MainWindow.m_pZoomScale), nZoomLevel);
+	g_signal_handlers_unblock_by_func(g_MainWindow.m_pZoomScale, mainwindow_on_zoomscale_value_changed, NULL);
 }
 
 static void zoom_in_one(void)
 {
+	// tell the map
 	map_set_zoomlevel(g_MainWindow.m_pMap, map_get_zoomlevel(g_MainWindow.m_pMap) + 1);
+	// tell the GUI
+	mainwindow_set_zoomlevel(map_get_zoomlevel(g_MainWindow.m_pMap));
 
-	gtk_range_set_value(GTK_RANGE(g_MainWindow.m_pZoomScale), map_get_zoomlevel(g_MainWindow.m_pMap));
+	// NOTE: doesn't trigger an actual redraw
 }
 
 static void zoom_out_one(void)
 {
 	map_set_zoomlevel(g_MainWindow.m_pMap, map_get_zoomlevel(g_MainWindow.m_pMap) - 1 );
+	mainwindow_set_zoomlevel(map_get_zoomlevel(g_MainWindow.m_pMap));
 
-	gtk_range_set_value(GTK_RANGE(g_MainWindow.m_pZoomScale), map_get_zoomlevel(g_MainWindow.m_pMap));
+	// NOTE: doesn't trigger an actual redraw
 }
 
+//
+//
+//
 static void gui_set_tool(EToolType eTool)
 {
 	g_MainWindow.m_eSelectedTool = eTool;
@@ -614,11 +625,13 @@
 void mainwindow_on_zoomin_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
 	zoom_in_one();
+	mainwindow_draw_map(DRAWFLAG_ALL);
 }
 
 void mainwindow_on_zoomout_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
 	zoom_out_one();
+	mainwindow_draw_map(DRAWFLAG_ALL);
 }
 
 void mainwindow_on_fullscreenmenuitem_activate(GtkMenuItem *menuitem, gpointer user_data)
@@ -785,8 +798,6 @@
 
 	gint nWidth = GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.width;
 	gint nHeight = GTK_WIDGET(g_MainWindow.m_pDrawingArea)->allocation.height;
-	
-	EDirection eScrollDirection = match_border(nX, nY, nWidth, nHeight, BORDER_SCROLL_CLICK_TARGET_SIZE);
 
 	if(g_MainWindow.m_bMouseDragging) {
 		g_MainWindow.m_bMouseDragMovement = TRUE;
@@ -814,6 +825,8 @@
 	else if(g_MainWindow.m_bScrolling) {
 		// just set the cursor the window
 
+		EDirection eScrollDirection = match_border(nX, nY, nWidth, nHeight, BORDER_SCROLL_CLICK_TARGET_SIZE);
+
 		if(g_MainWindow.m_eScrollDirection != eScrollDirection) {
 			// update cursor
 			GdkCursor* pCursor = gdk_cursor_new(g_aDirectionCursors[eScrollDirection].m_nCursor);
@@ -830,6 +843,8 @@
 		}
 	}
 	else {
+		EDirection eScrollDirection = match_border(nX, nY, nWidth, nHeight, BORDER_SCROLL_CLICK_TARGET_SIZE);
+
 		// just set cursor based on what we're hovering over
 		GdkCursor* pCursor = gdk_cursor_new(g_aDirectionCursors[eScrollDirection].m_nCursor);
 		gdk_window_set_cursor(GTK_WIDGET(g_MainWindow.m_pDrawingArea)->window, pCursor);

Index: map.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- map.c	7 Mar 2005 05:30:10 -0000	1.19
+++ map.c	10 Mar 2005 06:12:03 -0000	1.20
@@ -64,8 +64,8 @@
 	{  400000, ""},		// 3
 	{  200000, ""},		// 4
 	{  100000, ""},		// 5
-	{   50000, ""},		// 6
-	{   25000, ""}, 	// 7
+	{   40000, ""},		// 6
+	{   20000, ""}, 	// 7
 
 	{   10000, ""},		// 8
 	{    4000, ""},		// 9
@@ -182,6 +182,10 @@
 
 	gint nRenderMode = RENDERMODE_FAST;
 
+	// XXX test
+	GdkRectangle rect = {200,200,100,100};
+	scenemanager_claim_rectangle(pMap->m_pSceneManager, &rect);
+
 	if(nRenderMode == RENDERMODE_FAST) {
 		if(nDrawFlags & DRAWFLAG_GEOMETRY) {
 			map_draw_gdk(pMap, pRenderMetrics, pMap->m_pPixmap, DRAWFLAG_GEOMETRY);
@@ -193,6 +197,11 @@
 	else {	// nRenderMode == RENDERMODE_PRETTY
 		map_draw_cairo(pMap, pRenderMetrics, pMap->m_pPixmap, nDrawFlags);
 	}
+	
+	// XXX test
+	gdk_draw_rectangle(pMap->m_pPixmap, pMap->m_pTargetWidget->style->fg_gc[GTK_WIDGET_STATE(pMap->m_pTargetWidget)],
+			FALSE, 200,200, 100, 100);
+
 	gtk_widget_queue_draw(pMap->m_pTargetWidget);
 }
 
@@ -471,8 +480,8 @@
 	gchar* pszSQL = g_strdup_printf(
 		"SELECT Road.ID, Road.TypeID, AsBinary(Road.Coordinates), RoadName.Name, RoadName.SuffixID"
 		" FROM Road "
-		" LEFT JOIN Road_RoadName ON (Road.ID=Road_RoadName.RoadID)"
-		" LEFT JOIN RoadName ON (Road_RoadName.RoadNameID=RoadName.ID)"
+	//      " LEFT JOIN Road_RoadName ON (Road.ID=Road_RoadName.RoadID)"
+		" LEFT JOIN RoadName ON (Road.RoadNameID=RoadName.ID)"
 		" WHERE"
 //		" TypeID IN (%s) AND"
 		" MBRIntersects(GeomFromText('Polygon((%f %f,%f %f,%f %f,%f %f,%f %f))'), Coordinates)",
@@ -536,7 +545,7 @@
 			g_ptr_array_add(
 				pMap->m_apLayerData[nTypeID]->m_pPointStringsArray, pNewPointString);
 		} // end while loop on rows
-		// g_print("[%d rows]\n", uRowCount);
+		g_print("[%d rows]\n", uRowCount);
 		TIMER_SHOW(mytimer, "after rows retrieved");
 
 		db_free_result(pResultSet);

Index: map_draw_cairo.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_cairo.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- map_draw_cairo.c	9 Mar 2005 07:32:49 -0000	1.7
+++ map_draw_cairo.c	10 Mar 2005 06:12:03 -0000	1.8
@@ -21,6 +21,8 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+//#define ENABLE_TIMING
+
 #define RENDERING_THREAD_YIELD	// do nothing
 
 #define HACK_AROUND_CAIRO_LINE_CAP_BUG	// enable to ensure roads have rounded caps if the style dictates
@@ -152,17 +154,160 @@
 	gdouble m_fScore;
 } labelposition_t;
 
+static void map_draw_cairo_line_label_one_segment(map_t* pMap, cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, pointstring_t* pPointString, gdouble fLineWidth, const gchar* pszLabel)
+{
+//         gdouble fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+//         if(fFontSize == 0) 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(pPointString->m_pPointsArray, 0);
+	mappoint_t* pMapPoint2 = g_ptr_array_index(pPointString->m_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;
+	}
+
+	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);
+
+	// exclude and road that starts or ends outside drawable window (sacrifice a little quality for speed)
+	if(fX1 < 0 || fX2 < 0 || fY1 < 0 || fY2 < 0 || fX1 > pRenderMetrics->m_nWindowWidth || fX2 > pRenderMetrics->m_nWindowWidth || fY1 > pRenderMetrics->m_nWindowHeight || fY2 > pRenderMetrics->m_nWindowHeight) {
+		return;
+	}
+
+	gdouble fRise = fY2 - fY1;
+	gdouble fRun = fX2 - fX1;
+	gdouble fLineLengthSquared = (fRun*fRun) + (fRise*fRise);
+
+	gchar* pszFontFamily = ROAD_FONT;
+
+	cairo_save(pCairo);
+//         cairo_select_font(pCairo, pszFontFamily, CAIRO_FONT_SLANT_NORMAL,
+//                           pLabelStyle->m_abBoldAtZoomLevel[pRenderMetrics->m_nZoomLevel-1] ?
+//                           CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
+//         cairo_scale_font(pCairo, fFontSize);
+
+	// get total width of string
+	cairo_text_extents_t extents;
+	cairo_text_extents(pCairo, pszLabel, &extents);
+	cairo_font_extents_t font_extents;
+	cairo_current_font_extents(pCairo, &font_extents);
+
+	// text too big for line?
+//	if(extents.width > fLineLength) {
+	if((extents.width * extents.width) > fLineLengthSquared) {
+		cairo_restore(pCairo);
+		return;
+	}
+	gdouble fLineLength = sqrt(fLineLengthSquared);
+
+	gdouble fTotalPadding = fLineLength - extents.width;
+
+	// 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;
+
+	// 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);
+
+	// 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 * font_extents.ascent/2);
+		fDrawY -= (fPerpendicularNormalizedY * font_extents.ascent/2);
+
+		GdkPoint aBoundingPolygon[4];
+		// 0 is bottom left point
+		aBoundingPolygon[0].x = fDrawX;	
+		aBoundingPolygon[0].y = fDrawY;
+		// 1 is upper left point
+		aBoundingPolygon[1].x = fDrawX + (fPerpendicularNormalizedX * font_extents.ascent);
+		aBoundingPolygon[1].y = fDrawY + (fPerpendicularNormalizedY * font_extents.ascent);
+		// 2 is upper right point
+		aBoundingPolygon[2].x = aBoundingPolygon[1].x + (fNormalizedX * extents.width);
+		aBoundingPolygon[2].y = aBoundingPolygon[1].y + (fNormalizedY * extents.width);
+		// 2 is lower right point
+		aBoundingPolygon[3].x = fDrawX + (fNormalizedX * extents.width);
+		aBoundingPolygon[3].y = fDrawY + (fNormalizedY * extents.width);
+
+		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_move_to(pCairo, fDrawX, fDrawY);
+		cairo_set_rgb_color(pCairo, 0.0,0.0,0.0);
+		cairo_set_alpha(pCairo, 1.0);
+		cairo_rotate(pCairo, fAngleInRadians);
+
+		gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+		if(fHaloSize >= 0) {
+			cairo_save(pCairo);
+			cairo_text_path(pCairo, pszLabel);
+			cairo_set_line_width(pCairo, fHaloSize);
+			cairo_set_rgb_color(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_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);
+}
+
 static void map_draw_cairo_line_label(map_t* pMap, cairo_t *pCairo, textlabelstyle_t* pLabelStyle, rendermetrics_t* pRenderMetrics, pointstring_t* pPointString, gdouble fLineWidth, const gchar* pszLabel)
 {
 	if(pPointString->m_pPointsArray->len < 2) return;
 
-	if(pPointString->m_pPointsArray->len > ROAD_MAX_SEGMENTS) { 
+	// pass off single segments to a specialized function
+	if(pPointString->m_pPointsArray->len == 2) {
+		map_draw_cairo_line_label_one_segment(pMap, pCairo, pLabelStyle, pRenderMetrics, pPointString, fLineWidth, pszLabel);
+		return;
+	}
+
+	// XXX
+	return;
+
+	if(pPointString->m_pPointsArray->len > ROAD_MAX_SEGMENTS) {
 		g_warning("not drawing label for road '%s' with > %d segments.\n", pszLabel, ROAD_MAX_SEGMENTS);
 		return;
 	}
 
-	gfloat fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
-	if(fFontSize == 0) return;
+//         gdouble fFontSize = pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+//         if(fFontSize == 0) return;
 
 	if(!scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
 		//g_print("dup label: %s\n", pszLabel);
@@ -172,10 +317,10 @@
 	gchar* pszFontFamily = ROAD_FONT;
 
 	cairo_save(pCairo);
-	cairo_select_font(pCairo, pszFontFamily, CAIRO_FONT_SLANT_NORMAL,
-	                  pLabelStyle->m_abBoldAtZoomLevel[pRenderMetrics->m_nZoomLevel-1] ? 
-                          CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
-	cairo_scale_font(pCairo, fFontSize);
+//         cairo_select_font(pCairo, pszFontFamily, CAIRO_FONT_SLANT_NORMAL,
+//                           pLabelStyle->m_abBoldAtZoomLevel[pRenderMetrics->m_nZoomLevel-1] ?
+//                           CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
+//         cairo_scale_font(pCairo, fFontSize);
 
 	// get total width of string
 	cairo_text_extents_t extents;
@@ -521,14 +666,28 @@
 		cairo_text_extents(pCairo, pszLabel, &extents);
 
 		// is the text too big for the polygon?
-		if((extents.width > (fPolygonWidth * 1.5)) || (extents.height > (fPolygonHeight * 1.5))) {
-			cairo_restore(pCairo);
-			return;
-		}
+//                 if((extents.width > (fPolygonWidth * 1.5)) || (extents.height > (fPolygonHeight * 1.5))) {
+//                         cairo_restore(pCairo);
+//                         return;
+//                 }
 
 		fDrawX -= (extents.width / 2);
 		fDrawY += (extents.height / 2);
 
+		// check permission with scenemanager
+		GdkRectangle rcLabelOutline;
+		rcLabelOutline.x = (gint)fDrawX;
+		rcLabelOutline.width = extents.width;
+		rcLabelOutline.y = ((gint)fDrawY) - extents.height;
+		rcLabelOutline.height = extents.height;
+		if(FALSE == scenemanager_can_draw_rectangle(pMap->m_pSceneManager, &rcLabelOutline)) {
+//			g_print("not drawing %s (blocked!)\n", pszLabel);
+			cairo_restore(pCairo);
+			return;
+		}
+		// claim it!  Now no one else will text draw here.
+		scenemanager_claim_rectangle(pMap->m_pSceneManager, &rcLabelOutline);
+
 // g_print("drawing at %f,%f\n", fDrawX, fDrawY);
 
 		cairo_move_to(pCairo, fDrawX, fDrawY);
@@ -586,7 +745,7 @@
 
 void map_draw_cairo_layer_points(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray)
 {
-	gfloat 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);
@@ -789,6 +948,16 @@
 {
 	gint i;
 	gdouble fLineWidth = pSubLayerStyle->m_afLineWidths[pRenderMetrics->m_nZoomLevel-1];
+	if(fLineWidth == 0) return;
+
+	gchar* pszFontFamily = ROAD_FONT;
+
+	// set font for whole layer
+	cairo_save(pCairo);
+	cairo_select_font(pCairo, pszFontFamily, CAIRO_FONT_SLANT_NORMAL,
+		  pLabelStyle->m_abBoldAtZoomLevel[pRenderMetrics->m_nZoomLevel-1] ?
+		  CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
+	cairo_scale_font(pCairo, pLabelStyle->m_afFontSizeAtZoomLevel[pRenderMetrics->m_nZoomLevel-1]);
 
 	for(i=0 ; i<pPointStringsArray->len ; i++) {
 		RENDERING_THREAD_YIELD;
@@ -798,6 +967,7 @@
 			map_draw_cairo_line_label(pMap, pCairo, pLabelStyle, pRenderMetrics, pPointString, fLineWidth, pPointString->m_pszName);
 		}
 	}
+	cairo_restore(pCairo);
 }
 
 void map_draw_cairo_layer_polygon_labels(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pPointStringsArray, sublayerstyle_t* pSubLayerStyle, textlabelstyle_t* pLabelStyle)

Index: scenemanager.c
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- scenemanager.c	8 Mar 2005 18:40:50 -0000	1.7
+++ scenemanager.c	10 Mar 2005 06:12:03 -0000	1.8
@@ -74,6 +74,18 @@
 	return bOK;
 }
 
+gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect)
+{
+	GdkRegion* pNewRegion = gdk_region_rectangle(pRect);
+
+	// Set pNewRegion to the intersection of it and the 'taken region'
+	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion);
+	gboolean bOK = gdk_region_empty(pNewRegion);	// it's ok to draw here if the intersection is empty
+        gdk_region_destroy(pNewRegion);
+
+	return bOK;
+}
+
 void scenemanager_claim_label(scenemanager_t* pSceneManager, const gchar* pszLabel)
 {
 	g_assert(pSceneManager != NULL);

Index: scenemanager.h
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- scenemanager.h	8 Mar 2005 18:40:50 -0000	1.4
+++ scenemanager.h	10 Mar 2005 06:12:03 -0000	1.5
@@ -35,6 +35,7 @@
 
 gboolean scenemanager_can_draw_label_at(scenemanager_t* pSceneManager, const gchar* pszLabel, GdkPoint* pScreenLocation);
 gboolean scenemanager_can_draw_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints);
+gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect);
 void scenemanager_claim_label(scenemanager_t* pSceneManager, const gchar* pszLabel);
 void scenemanager_claim_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints);
 void scenemanager_claim_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect);

Index: search_road.c
===================================================================
RCS file: /cvs/cairo/roadster/src/search_road.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- search_road.c	7 Mar 2005 05:30:10 -0000	1.13
+++ search_road.c	10 Mar 2005 06:12:03 -0000	1.14
@@ -276,7 +276,9 @@
 
 	gchar* pszZIPClause;
 	if(pRoadSearch->m_pszZIPCode != NULL) {
-		pszZIPClause = g_strdup_printf(" AND (Road.ZIPCodeLeft='%s' OR Road.ZIPCodeRight='%s')", pRoadSearch->m_pszZIPCode, pRoadSearch->m_pszZIPCode);
+		gchar* pszSafeZIP = db_make_escaped_string(pRoadSearch->m_pszZIPCode);
+		pszZIPClause = g_strdup_printf(" AND (Road.ZIPCodeLeft='%s' OR Road.ZIPCodeRight='%s')", pszSafeZIP, pszSafeZIP);
+		db_free_escaped_string(pszSafeZIP);
 	}
 	else {
 		pszZIPClause = g_strdup("");
@@ -323,8 +325,7 @@
 		"SELECT Road.ID, RoadName.Name, RoadName.SuffixID, AsBinary(Road.Coordinates), Road.AddressLeftStart, Road.AddressLeftEnd, Road.AddressRightStart, Road.AddressRightEnd, CityLeft.Name, CityRight.Name"
 		", StateLeft.Code, StateRight.Code, Road.ZIPCodeLeft, Road.ZIPCodeRight"
 		" FROM RoadName"
-		" LEFT JOIN Road_RoadName ON (RoadName.ID=Road_RoadName.RoadNameID)"
- 	    " LEFT JOIN Road ON (Road_RoadName.RoadID=Road.ID%s)"					// address # clause
+		" LEFT JOIN Road ON (RoadName.ID=Road.RoadNameID%s)"					// address # clause
 		// left side
 	    " LEFT JOIN City AS CityLeft ON (Road.CityLeftID=CityLeft.ID)"
 		" LEFT JOIN State AS StateLeft ON (CityLeft.StateID=StateLeft.ID)"




More information about the cairo-commit mailing list