[cairo-commit] roadster/src db.c, 1.23, 1.24 import_tiger.c, 1.17, 1.18 layers.h, 1.6, 1.7 map.c, 1.41, 1.42 map.h, 1.18, 1.19 map_draw_cairo.c, 1.19, 1.20 map_draw_gdk.c, 1.15, 1.16 scenemanager.c, 1.11, 1.12 scenemanager.h, 1.5, 1.6 util.c, 1.7, 1.8

Ian McIntosh commit at pdx.freedesktop.org
Wed Aug 31 01:37:55 PDT 2005


Committed by: ian

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

Modified Files:
	db.c import_tiger.c layers.h map.c map.h map_draw_cairo.c 
	map_draw_gdk.c scenemanager.c scenemanager.h util.c 
Log Message:
        * src/db.c: Remove incorrect 'UNIQUE' attribute on Name index in RoadName table.
        * src/scenemanager.c: Add 'on screen' as additional (optional) criteria for allowing drawing.
        * src/map_draw_cairo.c: Update to new scenemanager API.  Add new dual-line smart area labeler.
	* src/util.c: Function util_split_words_onto_two_lines() is now used.
        * data/layers.xml: Various style tweaks.  It's fun.
        * src/map.c: Style tweaks.


Index: db.c
===================================================================
RCS file: /cvs/cairo/roadster/src/db.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- db.c	28 Aug 2005 22:23:14 -0000	1.23
+++ db.c	31 Aug 2005 08:37:53 -0000	1.24
@@ -585,7 +585,7 @@
 		" Name VARCHAR(30) NOT NULL,"
 		" SuffixID INT1 UNSIGNED NOT NULL,"
 		" PRIMARY KEY (ID),"			// for joining RoadName to Road 
-		" UNIQUE KEY (Name(7)));", NULL);	// for searching by RoadName. 7 is enough for decent uniqueness(?)
+		" INDEX (Name(7)));", NULL);	// for searching by RoadName. 7 is enough for decent uniqueness(?)
 
 	// City
 	db_query("CREATE TABLE IF NOT EXISTS City("

Index: import_tiger.c
===================================================================
RCS file: /cvs/cairo/roadster/src/import_tiger.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- import_tiger.c	28 Aug 2005 22:23:14 -0000	1.17
+++ import_tiger.c	31 Aug 2005 08:37:53 -0000	1.18
@@ -488,6 +488,8 @@
 
 		// columns 6 to 15 is the TLID -
 		import_tiger_read_int(&pLine[6-1], TIGER_TLID_LENGTH, &pRecord->m_nTLID);
+		
+		// columns 20 to ? is the name
 		import_tiger_read_string(&pLine[20-1], TIGER_CHAIN_NAME_LEN, &pRecord->m_achName[0]);
 
 		// columns 141-145 and 146-150 are FIPS55 codes which link this road to a city
@@ -503,7 +505,6 @@
 if(achType[0] != '\0' && pRecord->m_nRoadNameSuffixID == ROAD_SUFFIX_NONE) {
 	g_print("type '%s' couldn't be looked up\n", achType);
 }
-
 		import_tiger_read_int(&pLine[135-1], 3, &pRecord->m_nCountyIDLeft);
 		import_tiger_read_int(&pLine[138-1], 3, &pRecord->m_nCountyIDRight);
 

Index: layers.h
===================================================================
RCS file: /cvs/cairo/roadster/src/layers.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- layers.h	13 Mar 2005 23:31:21 -0000	1.6
+++ layers.h	31 Aug 2005 08:37:53 -0000	1.7
@@ -29,21 +29,24 @@
 
 G_BEGIN_DECLS
 
-#define LAYER_NONE				(0)
+#define LAYER_NONE					(0)
 
 #define LAYER_MINORSTREET			(1)
 #define LAYER_MAJORSTREET			(2)
+
 #define LAYER_MINORHIGHWAY			(3)
-#define LAYER_MINORHIGHWAY_RAMP			(4)
+#define LAYER_MINORHIGHWAY_RAMP		(4)
+
 #define LAYER_MAJORHIGHWAY			(5)	// used?
-#define LAYER_MAJORHIGHWAY_RAMP			(6)	// used?
+#define LAYER_MAJORHIGHWAY_RAMP		(6)	// used?
+
 #define LAYER_RAILROAD				(7)
-#define LAYER_PARK				(8)
-#define LAYER_RIVER				(9)
-#define LAYER_LAKE				(10)
+#define LAYER_PARK					(8)
+#define LAYER_RIVER					(9)
+#define LAYER_LAKE					(10)
 #define LAYER_MISC_AREA				(11)
 
-#define NUM_LAYERS 				(11)
+#define NUM_LAYERS 					(11)
 
 #define LAYER_FIRST				(1)
 #define LAYER_LAST				(11)

Index: map.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- map.c	28 Aug 2005 22:23:14 -0000	1.41
+++ map.c	31 Aug 2005 08:37:53 -0000	1.42
@@ -39,6 +39,11 @@
 #include "location.h"
 #include "scenemanager.h"
 
+
+#define ENABLE_RIVER_TO_LAKE_LOADTIME_HACK	// change circular rivers to lakes when loading from disk
+//#define ENABLE_SCENEMANAGER_DEBUG_TEST
+
+
 #ifdef THREADED_RENDERING
 #define RENDERING_THREAD_YIELD          g_thread_yield()
 #else
@@ -63,9 +68,6 @@
 
 #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
@@ -92,6 +94,7 @@
 	{ 1600000, ""},		// 1
 	{  800000, ""},		// 2
 	{  400000, ""},		// 3
+
 	{  200000, ""},		// 4
 	{  100000, ""},		// 5
 
@@ -106,11 +109,11 @@
 
 	{LAYER_MISC_AREA, 0, SUBLAYER_RENDERTYPE_POLYGONS}, //map_draw_layer_polygons},
 
-	{LAYER_PARK, 0, SUBLAYER_RENDERTYPE_LINES}, //map_draw_layer_lines},
+//	{LAYER_PARK, 0, SUBLAYER_RENDERTYPE_LINES}, //map_draw_layer_lines},
 	{LAYER_PARK, 1, SUBLAYER_RENDERTYPE_POLYGONS}, //map_draw_layer_polygons},
 
-	{LAYER_LAKE, 0, SUBLAYER_RENDERTYPE_LINES},	// NOTE: drawing lines BELOW polygons (and ~double width) lets us avoid drawing seams on top of multi-polygon lakes
-	{LAYER_RIVER, 0, SUBLAYER_RENDERTYPE_LINES}, //map_draw_layer_lines},	// single-line rivers
+//	{LAYER_LAKE, 0, SUBLAYER_RENDERTYPE_LINES},	// NOTE: drawing lines BELOW polygons (and ~double width) lets us avoid drawing seams on top of multi-polygon lakes
+//	{LAYER_RIVER, 0, SUBLAYER_RENDERTYPE_LINES}, //map_draw_layer_lines},	// single-line rivers
 	
 	{LAYER_LAKE, 1, SUBLAYER_RENDERTYPE_POLYGONS},
 	{LAYER_RIVER, 1, SUBLAYER_RENDERTYPE_LINES}, //map_draw_layer_lines},	// single-line rivers
@@ -240,18 +243,15 @@
 {
 	g_assert(pMap != NULL);
 
-	scenemanager_clear(pMap->m_pSceneManager);
-
-	// Get render metrics
+	// Get area of world to draw and screen dimensions to draw to, etc.
 	rendermetrics_t renderMetrics = {0};
 	map_get_render_metrics(pMap, &renderMetrics);
 	rendermetrics_t* pRenderMetrics = &renderMetrics;
 
-	//g_print("drawing at %f,%f\n", pMap->m_MapCenter.m_fLatitude, pMap->m_MapCenter.m_fLongitude);
+	scenemanager_clear(pMap->m_pSceneManager);
+	scenemanager_set_screen_dimensions(pMap->m_pSceneManager, pRenderMetrics->m_nWindowWidth, pRenderMetrics->m_nWindowHeight);
 
-	//
 	// Load geometry
-	//
 	TIMER_BEGIN(loadtimer, "--- BEGIN ALL DB LOAD");
 	map_data_clear(pMap);
 	map_data_load_tiles(pMap, &(pRenderMetrics->m_rWorldBoundingBox));

Index: map.h
===================================================================
RCS file: /cvs/cairo/roadster/src/map.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- map.h	28 Aug 2005 22:23:14 -0000	1.18
+++ map.h	31 Aug 2005 08:37:53 -0000	1.19
@@ -252,7 +252,7 @@
 
 #define DRAWFLAG_ALL 		(1|2)
 
-#define NUM_SUBLAYER_TO_DRAW (24)
+#define NUM_SUBLAYER_TO_DRAW (21) //(24)
 extern draworder_t layerdraworder[NUM_SUBLAYER_TO_DRAW];	//
 
 void map_init(void);

Index: map_draw_cairo.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_cairo.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- map_draw_cairo.c	28 Aug 2005 22:23:14 -0000	1.19
+++ map_draw_cairo.c	31 Aug 2005 08:37:53 -0000	1.20
@@ -28,10 +28,13 @@
 #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	ACCEPTABLE_LINE_LABEL_OVERDRAW_IN_PIXELS_SQUARED (24*24)	// XXX: make this a run-time variable
 
-#define ROAD_FONT	"Bitstream Vera Sans"
-#define AREA_FONT	"Bitstream Vera Sans"
+#define ROAD_FONT	"Free Sans" //Bitstream Vera Sans"
+#define AREA_FONT	"Free Sans" // "Bitstream Vera Sans"
+
+#define MIN_AREA_LABEL_LINE_LENGTH	(4)
+#define MAX_AREA_LABEL_LINE_LENGTH	(8)
 
 #include <gdk/gdkx.h>
 #include <cairo.h>
@@ -62,7 +65,7 @@
 // Draw a single line/polygon/point
 static void map_draw_cairo_background(map_t* pMap, cairo_t *pCairo);
 static void map_draw_cairo_layer_points(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationsArray);
-//static void map_draw_cairo_locationset(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics, locationset_t* pLocationSet, GPtrArray* pLocationsArray);
+static void map_draw_cairo_locationset(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics, locationset_t* pLocationSet, GPtrArray* pLocationsArray);
 static void map_draw_cairo_locationselection(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics, GPtrArray* pLocationSelectionArray);
 
 // Draw a single line/polygon label
@@ -103,11 +106,7 @@
 	drawable = gdk_x11_drawable_get_xid(pPixmap);
 
 	gdk_drawable_get_size (pPixmap, &width, &height);
-	cairo_surface_t *pSurface = cairo_xlib_surface_create (dpy,
-							       drawable,
-							       visual,
-							       width,
-							       height);
+	cairo_surface_t *pSurface = cairo_xlib_surface_create (dpy, drawable, visual, width, height);
 	cairo_t* pCairo = cairo_create (pSurface);
 
 	// 2. Rendering
@@ -167,7 +166,7 @@
 		}
 	}
 
-//	map_draw_cairo_locations(pMap, pCairo, pRenderMetrics);
+	//map_draw_cairo_locations(pMap, pCairo, pRenderMetrics);	done with GDK
 	map_draw_cairo_locationselection(pMap, pCairo, pRenderMetrics, pMap->m_pLocationSelectionArray);
 
 	// 4. Cleanup
@@ -410,44 +409,6 @@
 */
 }
 
-<<<<<<< map_draw_cairo.c
-#define ROAD_MAX_SEGMENTS 		(100)
-=======
-//void map_draw_cairo_locations(map_t* pMap, cairo_t* pCairo, rendermetrics_t* pRenderMetrics)
-//{
-/*
-	location_t loc;
-	location_t* pLoc = &loc;
-
-	// XXX:	debug
-	pLoc->m_pszName = "2020 Massachusetts Ave., Cambridge, MA, 02140";
-	pLoc->m_Coordinates.m_fLongitude = 0;
-	pLoc->m_Coordinates.m_fLatitude = 0;
-
-	//
-	// Draw
-	//
-	cairo_save(pCairo);
-
-	gdouble fX = (gdouble)(gint)SCALE_X(pRenderMetrics, pLoc->m_Coordinates.m_fLongitude);
-	gdouble fY = (gdouble)(gint)SCALE_Y(pRenderMetrics, pLoc->m_Coordinates.m_fLatitude);
-
-#define BIP (3)
-#define BAP (1.5)
-
-	cairo_set_source_rgb(pCairo, 20/255.0, 20/255.0, 20/255.0);
-	cairo_set_line_width(pCairo, 2.5);
-	cairo_set_alpha(pCairo, 1.0);
-
-	cairo_rectangle(pCairo, fX - BIP, fY - BIP, BIP*2, BIP*2);
-	cairo_stroke(pCairo);
-
-	cairo_rectangle(pCairo, fX - BAP, fY - BAP, BAP*2, BAP*2);
-	cairo_fill(pCairo);
-	cairo_restore(pCairo);
-*/
-//}
-
 #define ROAD_MAX_SEGMENTS 100
 #define DRAW_LABEL_BUFFER_LEN	(200)
 
@@ -467,7 +428,7 @@
 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)) {
+	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 		return;
 	}
 
@@ -575,7 +536,7 @@
 		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)) {
+		if(FALSE == scenemanager_can_draw_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 			continue;
 		}
 		
@@ -657,7 +618,7 @@
 
 	// 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)) {
+	if(!scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 		return;
 	}
 
@@ -959,7 +920,7 @@
 			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)) {
+			if(FALSE == scenemanager_can_draw_polygon(pMap->m_pSceneManager, aBoundingPolygon, 4, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 				bGood = FALSE;
 				break;
 			}
@@ -1142,7 +1103,7 @@
 	g_ptr_array_free(pPositionsPtrArray, FALSE);
 	*/
 }
-/*
+
 //
 // Draw a single polygon label
 //
@@ -1150,34 +1111,24 @@
 {
 	if(pPointsArray->len < 3) return;
 
-	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL)) {
+	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 		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);
+		mappoint_t* 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 += SCALE_X(pRenderMetrics, pMapPoint->m_fLongitude);
-		//fTotalY += SCALE_Y(pRenderMetrics, pMapPoint->m_fLatitude);
 	}
 
 	// rectangle overlap test
@@ -1189,74 +1140,119 @@
 	    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;
+	gdouble fAreaOriginX = SCALE_X(pRenderMetrics, fMinLon);
+	gdouble fAreaOriginY = SCALE_Y(pRenderMetrics, fMaxLat);
+//g_print("Area origin (%f,%f)\n", fAreaOriginX, fAreaOriginY);
 
-#define MIN_AREA_LABEL_LINE_LENGTH	(4)
-#define MAX_AREA_LABEL_LINE_LENGTH	(10)
+	gdouble fAreaWidth = SCALE_X(pRenderMetrics, fMaxLon) - SCALE_X(pRenderMetrics, fMinLon);
+	gdouble fAreaHeight = SCALE_Y(pRenderMetrics, fMinLat) - SCALE_Y(pRenderMetrics, fMaxLat);
+//g_print("Area size (%f,%f)\n", fAreaWidth, fAreaHeight);
 
 	gchar** aLines = util_split_words_onto_two_lines(pszLabel, MIN_AREA_LABEL_LINE_LENGTH, MAX_AREA_LABEL_LINE_LENGTH);
+	gint nLineCount = g_strv_length(aLines);	// could be one or two, unless we change above function
+	gint* anWidths = g_new0(gint, nLineCount);
 
-	cairo_save(pCairo);
+	gdouble fLabelBoxWidth = 0.0;
+	gdouble fLabelBoxHeight = 0.0;
 
-	// 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;
+	for(i=0 ; i<nLineCount ; i++) {
+		cairo_text_extents(pCairo, aLines[i], &extents);
+		anWidths[i] = extents.width;
+		fLabelBoxWidth = max(fLabelBoxWidth, (gdouble)extents.width);	// as wide as the widest line
+		fLabelBoxHeight += (gdouble)extents.height;						// total height of all lines
 	}
 
-	fDrawX -= (extents.width / 2);
-	fDrawY += (extents.height / 2);
+	gdouble fOneLineHeight = fLabelBoxHeight / nLineCount;
 
-	// 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 fHorizontalPadding = (fAreaWidth - fLabelBoxWidth);
+	gdouble fVerticalPadding = (fAreaHeight - fLabelBoxHeight);
+//g_print("padding (%f,%f)\n", fHorizontalPadding, fVerticalPadding);
+
+	// various places to try...
+	struct { gdouble fX,fY; } afPercentagesOfPadding[] = {
+		{0.50, 0.50},
+		
+		// first the close-to-center positions (.25 and .75)
+		{0.50, 0.25}, {0.50, 0.75},	// dodge up/down
+		{0.25, 0.50}, {0.75, 0.50}, // dodge left/right middle
+		{0.25, 0.25}, {0.75, 0.25}, // upper left/right
+		{0.25, 0.75}, {0.75, 0.75}, // lower left/right
+
+		// now the close-to-center positions (0.0 and 1.0)
+		{0.50, 0.00}, {0.50, 1.00},	// dodge up/down
+		{0.00, 0.50}, {1.00, 0.50}, // dodge left/right middle
+//		{0.00, 0.00}, {1.00, 0.00}, // upper left/right
+//		{0.00, 1.00}, {1.00, 1.00}, // lower left/right		
+	};
+
+	gboolean bSuccess = FALSE;
+	gint iSlot;
+	for(iSlot=0 ; iSlot<NUM_ELEMS(afPercentagesOfPadding) ; iSlot++) {
+		gdouble fDrawBoxCornerX = fAreaOriginX + (fHorizontalPadding * afPercentagesOfPadding[iSlot].fX);
+		gdouble fDrawBoxCornerY = fAreaOriginY + (fVerticalPadding * afPercentagesOfPadding[iSlot].fY);
+
+		GdkRectangle rcLabelOutline;
+		rcLabelOutline.x = (gint)(fDrawBoxCornerX);
+		rcLabelOutline.width = (gint)(fLabelBoxWidth);
+		rcLabelOutline.y = (gint)(fDrawBoxCornerY);
+		rcLabelOutline.height = (gint)(fLabelBoxHeight);
+		if(FALSE == scenemanager_can_draw_rectangle(pMap->m_pSceneManager, &rcLabelOutline, SCENEMANAGER_FLAG_FULLY_ON_SCREEN)) {
+			continue;
+		}
+
+		// passed test!  claim this label and rectangle area
+		scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
+		scenemanager_claim_rectangle(pMap->m_pSceneManager, &rcLabelOutline);
+
+		//
+		// Draw Halo for all lines, if style dictates.
+		//
+		gdouble fHaloSize = pLabelStyle->m_afHaloAtZoomLevel[pRenderMetrics->m_nZoomLevel-1];
+		if(fHaloSize >= 0) {
+			cairo_save(pCairo);
 
-	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);
+			for(i=0 ; i<nLineCount ; i++) {
+				// Get total width of string
+				cairo_move_to(pCairo, 
+							  fDrawBoxCornerX + ((fLabelBoxWidth - anWidths[i])/2), 
+							  fDrawBoxCornerY + ((i+1) * fOneLineHeight));
+				cairo_text_path(pCairo, aLines[i]);
+				cairo_stroke(pCairo);
+			}
+			cairo_restore(pCairo);
+		}
+
+		//
+		// Draw text for all lines.
+		//
+		for(i=0 ; i<nLineCount ; i++) {
+			// Get total width of string
+			cairo_move_to(pCairo, 
+						  fDrawBoxCornerX + ((fLabelBoxWidth - anWidths[i])/2), 
+						  fDrawBoxCornerY + ((i+1) * fOneLineHeight));
+			cairo_show_text(pCairo, aLines[i]);
+		}
+		break;
 	}
-	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);
-	
+		// draw it
+//		cairo_save(pCairo);
+
+//		cairo_restore(pCairo);
 	g_strfreev(aLines);
+	g_free(anWidths);
 }
-*/
 
+/*
 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)) {
+	if(FALSE == scenemanager_can_draw_label_at(pMap->m_pSceneManager, pszLabel, NULL, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 		return;
 	}
 
@@ -1319,7 +1315,7 @@
 		rcLabelOutline.width = extents.width;
 		rcLabelOutline.y = ((gint)fDrawY) - extents.height;
 		rcLabelOutline.height = extents.height;
-		if(FALSE == scenemanager_can_draw_rectangle(pMap->m_pSceneManager, &rcLabelOutline)) {
+		if(FALSE == scenemanager_can_draw_rectangle(pMap->m_pSceneManager, &rcLabelOutline, SCENEMANAGER_FLAG_PARTLY_ON_SCREEN)) {
 			cairo_restore(pCairo);
 			return;
 		}
@@ -1345,6 +1341,7 @@
 	// Tell scenemanager that we've drawn this label
 	scenemanager_claim_label(pMap->m_pSceneManager, pszLabel);
 }
+*/
 
 /*
 static void map_draw_cairo_locations(map_t* pMap, cairo_t *pCairo, rendermetrics_t* pRenderMetrics)

Index: map_draw_gdk.c
===================================================================
RCS file: /cvs/cairo/roadster/src/map_draw_gdk.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- map_draw_gdk.c	28 Aug 2005 22:23:14 -0000	1.15
+++ map_draw_gdk.c	31 Aug 2005 08:37:53 -0000	1.16
@@ -205,9 +205,9 @@
 	// XXX: Don't use round at low zoom levels
 //	gint nCapStyle = pSubLayerStyle->m_nCapStyle;
 	gint nCapStyle = GDK_CAP_ROUND;
-	if(fLineWidth < 8) {
-		nCapStyle = GDK_CAP_PROJECTING;
-	}
+	//if(fLineWidth < 8) {
+	//	nCapStyle = GDK_CAP_PROJECTING;
+	//}
 
 	gint nLineWidth = (gint)fLineWidth;
 	
@@ -250,7 +250,9 @@
 				aPoints[iPoint].y = (gint)SCALE_Y(pRenderMetrics, pPoint->m_fLatitude);
 			}
 
-			// rectangle overlap test
+			// basic rectangle overlap test
+			// XXX: not quite right. the points that make up a road may be offscreen,
+			// but a thick road should still be visible
 			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

Index: scenemanager.c
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- scenemanager.c	28 Aug 2005 22:23:14 -0000	1.11
+++ scenemanager.c	31 Aug 2005 08:37:53 -0000	1.12
@@ -34,6 +34,7 @@
 
 void scenemanager_init(void)
 {
+	
 }
 
 void scenemanager_new(scenemanager_t** ppReturn)
@@ -45,22 +46,63 @@
 	*ppReturn = pNew;
 }
 
-gboolean scenemanager_can_draw_label_at(scenemanager_t* pSceneManager, const gchar* pszLabel, GdkPoint* __unused_pScreenLocation)
+// NOTE: must be called before any scenemanager_can_draw_* calls
+void scenemanager_set_screen_dimensions(scenemanager_t* pSceneManager, gint nWindowWidth, gint nWindowHeight)
+{
+	pSceneManager->m_nWindowWidth = nWindowWidth;
+	pSceneManager->m_nWindowHeight = nWindowHeight;
+}
+
+gboolean scenemanager_can_draw_label_at(scenemanager_t* pSceneManager, const gchar* pszLabel, GdkPoint* __unused_pScreenLocation, gint nFlags)
 {
 	g_assert(pSceneManager != NULL);
 	g_assert(pszLabel != NULL);
-	
+
 	// g_assert(pScreenLocation != NULL);
 	// NOTE: ignore pScreenLocation for now
-
 	gpointer pKey, pValue;
 
 	// Can draw if it doesn't exist in table
 	return (FALSE == g_hash_table_lookup_extended(pSceneManager->m_pLabelHash, pszLabel, &pKey, &pValue));
 }
 
-gboolean scenemanager_can_draw_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints)
+gboolean scenemanager_can_draw_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints, gint nFlags)
 {
+	//
+	// 1) Enforce on-screen rules
+	//
+	if(nFlags & SCENEMANAGER_FLAG_FULLY_ON_SCREEN) {
+		// all points must be within screen box
+		gint i;
+		for(i=0 ; i<nNumPoints ; i++) {
+			GdkPoint* pPoint = &pPoints[i];
+			if(pPoint->x < 0 || pPoint->x > pSceneManager->m_nWindowWidth) return FALSE;
+			if(pPoint->y < 0 || pPoint->y > pSceneManager->m_nWindowHeight) return FALSE;
+		}
+		// else go on to test below
+	}
+	else if(nFlags & SCENEMANAGER_FLAG_PARTLY_ON_SCREEN) {
+		// one point must be withing screen box
+		gint i;
+		gboolean bFound = FALSE;
+		for(i=0 ; i<nNumPoints ; i++) {
+			GdkPoint* pPoint = &pPoints[i];
+			if(pPoint->x > 0 && pPoint->x < pSceneManager->m_nWindowWidth) {
+				bFound = TRUE;
+				break;
+			}
+			if(pPoint->y > 0 && pPoint->y < pSceneManager->m_nWindowHeight) {
+				bFound = TRUE;
+				break;
+			}
+		}
+		if(!bFound) return FALSE;
+		// else go on to test below
+	}
+
+	//
+	// 2) Enforce overlap rules
+	//
 	GdkRegion* pNewRegion = gdk_region_polygon(pPoints, nNumPoints, GDK_WINDING_RULE);
 
 	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion); // sets pNewRegion to the intersection of itself and the 'taken region'
@@ -70,8 +112,29 @@
 	return bOK;
 }
 
-gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect)
+gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect, gint nFlags)
 {
+	//
+	// 1) Enforce on-screen rules
+	//
+	if(nFlags & SCENEMANAGER_FLAG_FULLY_ON_SCREEN) {
+		// basic rect1 contains rect2 test
+		if((pRect->x) <= 0) return FALSE;
+		if((pRect->y) <= 0) return FALSE;
+		if((pRect->x + pRect->width) > pSceneManager->m_nWindowWidth) return FALSE;
+		if((pRect->y + pRect->height) > pSceneManager->m_nWindowHeight) return FALSE;
+	}
+	else if(nFlags & SCENEMANAGER_FLAG_PARTLY_ON_SCREEN) {
+		// basic rect intersect test
+		if((pRect->x + pRect->width) <= 0) return FALSE;
+		if((pRect->y + pRect->height) <= 0) return FALSE;
+		if((pRect->x) > pSceneManager->m_nWindowWidth) return FALSE;
+		if((pRect->y) > pSceneManager->m_nWindowHeight) return FALSE;
+	}
+
+	//
+	// 2) Enforce overlap rules
+	//
 	GdkRegion* pNewRegion = gdk_region_rectangle(pRect);
 
 	gdk_region_intersect(pNewRegion, pSceneManager->m_pTakenRegion); // sets pNewRegion to the intersection of itself and the 'taken region'

Index: scenemanager.h
===================================================================
RCS file: /cvs/cairo/roadster/src/scenemanager.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- scenemanager.h	10 Mar 2005 06:12:03 -0000	1.5
+++ scenemanager.h	31 Aug 2005 08:37:53 -0000	1.6
@@ -24,18 +24,28 @@
 #ifndef _SCENEMANAGER_H_
 #define _SCENEMANAGER_H_
 
+// Flags
+#define SCENEMANAGER_FLAG_NONE				(0)
+#define SCENEMANAGER_FLAG_FULLY_ON_SCREEN	(1)
+#define SCENEMANAGER_FLAG_PARTLY_ON_SCREEN	(2)
+
 typedef struct scenemanager {
 	GdkRegion* m_pTakenRegion;
 
+	gint m_nWindowWidth;
+	gint m_nWindowHeight;
+
 	GHashTable* m_pLabelHash;
 } scenemanager_t;
 
 void scenemanager_init(void);
 void scenemanager_new(scenemanager_t** ppReturn);
+void scenemanager_set_screen_dimensions(scenemanager_t* pSceneManager, gint nWindowWidth, gint nWindowHeight);
+
+gboolean scenemanager_can_draw_label_at(scenemanager_t* pSceneManager, const gchar* pszLabel, GdkPoint* pScreenLocation, gint nFlags);
+gboolean scenemanager_can_draw_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints, gint nFlags);
+gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect, gint nFlags);
 
-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: util.c
===================================================================
RCS file: /cvs/cairo/roadster/src/util.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- util.c	28 Aug 2005 22:23:14 -0000	1.7
+++ util.c	31 Aug 2005 08:37:53 -0000	1.8
@@ -78,10 +78,7 @@
 
 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
 
 	//



More information about the cairo-commit mailing list