[mapguide-commits] r1064 - in trunk/MgDev: Common/Foundation/System Common/MapGuideCommon/Services Common/MapGuideCommon/System Common/PlatformBase/Services Common/Stylization Server/src/Common/Manager Server/src/Services/Kml Server/src/Services/Mapping Server/src/Services/Resource Server/src/Services/Tile UnitTest/WebTier/MapAgent/MapAgentForms Web/src/HttpHandler Web/src/mapviewerjava Web/src/mapviewernet Web/src/mapviewerphp Web/src/viewerfiles

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Jan 19 19:49:26 EST 2007


Author: trevorwekel
Date: 2007-01-19 19:49:25 -0500 (Fri, 19 Jan 2007)
New Revision: 1064

Added:
   trunk/MgDev/Common/Stylization/complex_polygon_gd.cpp
   trunk/MgDev/Common/Stylization/complex_polygon_gd.h
   trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/gettileimageform2.html
Modified:
   trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.cpp
   trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.h
   trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.cpp
   trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.h
   trunk/MgDev/Common/MapGuideCommon/Services/Site.cpp
   trunk/MgDev/Common/MapGuideCommon/Services/Site.h
   trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp
   trunk/MgDev/Common/MapGuideCommon/Services/TileService.h
   trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
   trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
   trunk/MgDev/Common/MapGuideCommon/System/UserInformation.cpp
   trunk/MgDev/Common/PlatformBase/Services/ResourceService.cpp
   trunk/MgDev/Common/PlatformBase/Services/ResourceService.h
   trunk/MgDev/Common/PlatformBase/Services/ServiceRegistry.cpp
   trunk/MgDev/Common/Stylization/GDRenderer.cpp
   trunk/MgDev/Common/Stylization/GDRenderer.h
   trunk/MgDev/Common/Stylization/LabelRendererLocal.cpp
   trunk/MgDev/Common/Stylization/Makefile.am
   trunk/MgDev/Common/Stylization/Stylization.vcproj
   trunk/MgDev/Server/src/Common/Manager/LogManager.cpp
   trunk/MgDev/Server/src/Common/Manager/LogManager.h
   trunk/MgDev/Server/src/Common/Manager/PermissionManager.cpp
   trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
   trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.cpp
   trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.h
   trunk/MgDev/Server/src/Services/Resource/RepositoryManager.h
   trunk/MgDev/Server/src/Services/Resource/ResourceDefinitionManager.h
   trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp
   trunk/MgDev/Server/src/Services/Resource/ServerResourceService.h
   trunk/MgDev/Server/src/Services/Resource/SessionRepositoryManager.h
   trunk/MgDev/Server/src/Services/Resource/SystemRepositoryManager.h
   trunk/MgDev/Server/src/Services/Tile/OpGetTile.cpp
   trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
   trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
   trunk/MgDev/Server/src/Services/Tile/TileCache.cpp
   trunk/MgDev/Server/src/Services/Tile/TileCache.h
   trunk/MgDev/Server/src/Services/Tile/TileOperationFactory.cpp
   trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/tileserviceapi.html
   trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.cpp
   trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.h
   trunk/MgDev/Web/src/HttpHandler/HttpRequestResponseHandler.cpp
   trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp
   trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h
   trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp
   trunk/MgDev/Web/src/mapviewernet/mapframe.aspx
   trunk/MgDev/Web/src/mapviewerphp/mapframe.php
   trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ
Log:
MapGuide RFC 11 - Stateless Http GETTILEIMAGE request
Initial submission

Modified: trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.cpp
===================================================================
--- trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -379,3 +379,12 @@
 {
     m_curPtrWrite = m_curPtrRead = m_buffer;
 }
+
+//////////////////////////////////////////////////////////////////
+///<summary>
+/// Rewind to start of buffer
+///</summary>
+void MgMemoryStreamHelper::Rewind()
+{
+    m_curPtrRead = m_buffer;
+}

Modified: trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.h
===================================================================
--- trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Foundation/System/MemoryStreamHelper.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -155,6 +155,12 @@
     ///
     void Clear();
 
+    //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Resets reading to start of buffer
+    ///
+    void Rewind();
+
     protected:
 
     void Dispose();

Modified: trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -105,7 +105,38 @@
     return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
 }
 
+/////////////////////////////////////////////////////////////////
+/// \brief
+/// Returns the specified base map tile for the given map.  If a cached tile
+/// image exists it will return it, otherwise the tile is rendered and added
+/// to the cache.
+MgByteReader* MgProxyTileService::GetTile(
+    MgResourceIdentifier* mapDefinition,
+    CREFSTRING baseMapLayerGroupName,
+    INT32 tileColumn,
+    INT32 tileRow,
+    INT32 scaleIndex)
+{
+    MgCommand cmd;
+    cmd.ExecuteCommand(m_connProp,                                      // Connection
+                        MgCommand::knObject,                            // Return type expected
+                        MgTileServiceOpId::GetTile,                     // Command Code
+                        5,                                              // No of arguments
+                        Tile_Service,                                   // Service Id
+                        2,                                              // Operation version
+                        MgCommand::knObject, mapDefinition,             // Argument#1
+                        MgCommand::knString, &baseMapLayerGroupName,    // Argument#2
+                        MgCommand::knInt32, tileColumn,                 // Argument#3
+                        MgCommand::knInt32, tileRow,                    // Argument#4
+                        MgCommand::knInt32, scaleIndex,                 // Argument#4
+                        MgCommand::knNone);                             // End of arguments
 
+    SetWarning(cmd.GetWarningObject());
+
+    return (MgByteReader*)cmd.GetReturnValue().val.m_obj;
+}
+
+
 /////////////////////////////////////////////////////////////////
 /// <summary>
 /// Adds the specified base map tile to the cache.  If a tile image already

Modified: trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ProxyTileService.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -56,6 +56,38 @@
         INT32 tileColumn,
         INT32 tileRow);
 
+    /////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Returns the specified base map tile for the given map.  If a cached tile
+    /// image exists it will return it, otherwise the tile is rendered and added
+    /// to the cache.
+    ///
+    /// \param mapDefinition
+    /// Input
+    /// Resource identifier for the map definition
+    /// \param baseMapLayerGroupName
+    /// Input
+    /// Specifies the name of the baseMapLayerGroup for which to render the tile.
+    /// \param tileColumn
+    /// Input
+    /// Specifies the column index of the tile to return.
+    /// \param tileRow
+    /// Input
+    /// Specifies the row index of the tile to return.
+    /// \param scaleIndex
+    /// Input
+    /// Scale index to render
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* GetTile(
+        MgResourceIdentifier* mapDefinition,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 tileColumn,
+        INT32 tileRow,
+        INT32 scaleIndex);
+
     //////////////////////////////////////////////////////////////////
     /// \brief
     /// Clears the entire tile cache for the given map.  Tiles for all base

Modified: trunk/MgDev/Common/MapGuideCommon/Services/Site.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/Site.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/Site.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -85,10 +85,23 @@
 {
     MG_SITE_TRY()
 
+    Open(userInformation, false);
+
+    MG_SITE_CATCH_AND_THROW(L"MgSite.Open")
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// Opens a connection to a Site Server.
+/// </summary>
+
+void MgSite::Open(MgUserInformation* userInformation, bool skipAuthenticate)
+{
+    MG_SITE_TRY()
+
     // Authenticate the user.
+    Authenticate(userInformation, NULL, NULL, false, skipAuthenticate);
 
-    Authenticate(userInformation, NULL, NULL, false);
-
     MG_SITE_CATCH_AND_THROW(L"MgSite.Open")
 }
 
@@ -103,7 +116,7 @@
 
     // Authenticate the user.
 
-    Authenticate(userInformation, siteInfo, NULL, false);
+    Authenticate(userInformation, siteInfo, NULL, false, false);
 
     MG_SITE_CATCH_AND_THROW(L"MgSite.Open")
 }
@@ -1214,9 +1227,11 @@
 }
 
 MgStringCollection* MgSite::Authenticate(MgUserInformation* userInformation,
-    MgSiteInfo* siteInfo, MgStringCollection* requiredRoles, bool returnAssignedRoles)
+    MgSiteInfo* siteInfo, MgStringCollection* requiredRoles,
+    bool returnAssignedRoles, bool skipAuthenticate)
 {
     MgCommand cmd;
+    Ptr<MgStringCollection> retval = NULL;
 
     MG_SITE_TRY()
 
@@ -1236,24 +1251,28 @@
     {
         m_connProp = siteManager->GetConnectionProperties(userInformation, 
             MgSiteInfo::Site, true);
-    }
+    }  
 
-    cmd.ExecuteCommand(m_connProp,                          // Connection
-                        MgCommand::knObject,                // Return type
-                        MgSiteOpId::Authenticate,           // Command code
-                        3,                                  // Number of arguments
-                        Site_Admin,                         // Service ID
-                        1,                                  // Operation version
-                        MgCommand::knObject, userInformation, // Argument #1
-                        MgCommand::knObject, requiredRoles, // Argument #2
-                        MgCommand::knInt8, (int)returnAssignedRoles, // Argument #3
-                        MgCommand::knNone);
+    if (!skipAuthenticate)
+    {
+        cmd.ExecuteCommand(m_connProp,                          // Connection
+                            MgCommand::knObject,                // Return type
+                            MgSiteOpId::Authenticate,           // Command code
+                            3,                                  // Number of arguments
+                            Site_Admin,                         // Service ID
+                            1,                                  // Operation version
+                            MgCommand::knObject, userInformation, // Argument #1
+                            MgCommand::knObject, requiredRoles, // Argument #2
+                            MgCommand::knInt8, (int)returnAssignedRoles, // Argument #3
+                            MgCommand::knNone);
 
-    SetWarning(cmd.GetWarningObject());
+        SetWarning(cmd.GetWarningObject());
+        retval = (MgStringCollection*) cmd.GetReturnValue().val.m_obj;
+    }
 
     MG_SITE_CATCH_AND_THROW(L"MgSite.Authenticate")
 
-    return (MgStringCollection*)cmd.GetReturnValue().val.m_obj;
+    return retval.Detach();
 }
 
 void MgSite::SetWarning(MgWarnings* warning)

Modified: trunk/MgDev/Common/MapGuideCommon/Services/Site.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/Site.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/Site.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -808,8 +808,29 @@
     ///
     MgStringCollection* Authenticate(MgUserInformation* userInformation,
         MgSiteInfo* siteInfo,
-        MgStringCollection* requiredRoles, bool returnAssignedRoles);
+        MgStringCollection* requiredRoles,
+        bool returnAssignedRoles,
+        bool skipAuthenticate = false);
 
+    ///////////////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Opens a connection to the Site Server.
+    ///
+    /// \param userInformation
+    /// User information to authenticate against
+    ///
+    /// \param skipAuthenticate
+    /// Skip authentication.  Used for internal performance speedups.
+    ///
+    /// \return
+    /// Nothing
+    ///
+    /// \exception MgNullArgumentException
+    /// \exception MgAuthenticationFailedException
+    /// \exception MgConnectionFailedException
+    ///
+    void Open(MgUserInformation* userInformation, bool skipAuthenticate);
+
  protected:
 
     //////////////////////////////////////////////

Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -499,7 +499,7 @@
         assert(NULL != userInformation.p);
         Ptr<MgSite> site = new MgSite();
 
-        site->Open(userInformation);
+        site->Open(userInformation, true);
 
         STRING target = site->RequestServer(serviceType);
 

Modified: trunk/MgDev/Common/MapGuideCommon/Services/TileService.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/TileService.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/Services/TileService.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -59,6 +59,38 @@
         INT32 tileColumn,
         INT32 tileRow) = 0;
 
+    /////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Returns the specified base map tile for the given map.  If a cached tile
+    /// image exists it will return it, otherwise the tile is rendered and added
+    /// to the cache.
+    ///
+    /// \param mapDefinition
+    /// Input
+    /// Resource identifier for the map definition
+    /// \param baseMapLayerGroupName
+    /// Input
+    /// Specifies the name of the baseMapLayerGroup for which to render the tile.
+    /// \param tileColumn
+    /// Input
+    /// Specifies the column index of the tile to return.
+    /// \param tileRow
+    /// Input
+    /// Specifies the row index of the tile to return.
+    /// \param scaleIndex
+    /// Input
+    /// Scale index to render.  Most detailed scale is index 0.
+    ///
+    /// \return
+    /// A byte reader containing the rendered tile image.
+    ///
+    virtual MgByteReader* GetTile(
+        MgResourceIdentifier* mapDefinition,
+        CREFSTRING baseMapLayerGroupName,
+        INT32 tileColumn,
+        INT32 tileRow,
+        INT32 scaleIndex) = 0;
+
     //////////////////////////////////////////////////////////////////
     /// \brief
     /// Clears the entire tile cache for the given map.  Tiles for all base

Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -308,6 +308,10 @@
 const STRING MgConfigProperties::TileServicePropertiesSection                               = L"TileServiceProperties";
 const STRING MgConfigProperties::TileServicePropertyTileCachePath                           = L"TileCachePath";
 const STRING MgConfigProperties::DefaultTileServicePropertyTileCachePath                    = L"Repositories/TileCache/";
+const STRING MgConfigProperties::TileServicePropertyTiledMapCacheSize                       = L"TiledMapCacheSize";
+const INT32  MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize                = 10;
+const STRING MgConfigProperties::TileServicePropertyRenderOnly                              = L"RenderOnly";
+const bool   MgConfigProperties::DefaultTileServicePropertyRenderOnly                       = false;
 
 // ******************************************************************
 // Access Log Properties
@@ -537,6 +541,8 @@
 const MgConfigValidationInfo MgConfigProperties::sm_cviTileServiceProperties[] =
 {
     { MgConfigProperties::TileServicePropertyTileCachePath                          , MgPropertyType::String    , MG_CONFIG_MIN_PATH_LENGTH             , MG_CONFIG_MAX_PATH_LENGTH             , MG_CONFIG_PATH_RESERVED_CHARACTERS        },
+    { MgConfigProperties::TileServicePropertyTiledMapCacheSize                      , MgPropertyType::Int32     , MG_CONFIG_MIN_CACHE_SIZE              , MG_CONFIG_MAX_CACHE_SIZE              , L""                                       },
+    { MgConfigProperties::TileServicePropertyRenderOnly                             , MgPropertyType::Boolean   , 0                                     , 1                                     , L""                                       },
     { L""                                                                           , 0                         , 0.0                                   , 0.0                                   , L""                                       }
 };
 

Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -396,6 +396,13 @@
     static const STRING TileServicePropertyTileCachePath;               /// value("TileCachePath")
     static const STRING DefaultTileServicePropertyTileCachePath;        /// value("Repositories/TileCache/")
 
+    /// Sets the limit on the number of cached MgMap objects used for tile generation
+    static const STRING TileServicePropertyTiledMapCacheSize;           /// value("TiledMapCacheSize")
+    static const INT32 DefaultTileServicePropertyTiledMapCacheSize;     /// value(10)
+    static const STRING TileServicePropertyRenderOnly;                  /// value("RenderOnly")
+    static const bool DefaultTileServicePropertyRenderOnly;             /// value(true)
+
+
     //////////////////////////////////////////////////////////////////
     /// \brief
     /// The remaining properties are log properties.  For each type of log, there is a "Parameters" property.

Modified: trunk/MgDev/Common/MapGuideCommon/System/UserInformation.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/UserInformation.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/MapGuideCommon/System/UserInformation.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -343,9 +343,19 @@
 
     if (!m_username.empty() || !m_password.empty())
     {
+        //TODO:  Add a general configuration parameter for user info encryption
+        if (1)
+        {
         MgCryptographyManager cryptoManager;
 
         credentials = cryptoManager.EncryptCredentials(m_username, m_password);
+        }
+        else
+        {
+            credentials = m_username;
+            credentials.append(L"\t");
+            credentials.append(m_password);
+        }
     }
 
     Ptr<MgStreamHelper> helper = stream->GetStreamHelper();
@@ -385,6 +395,9 @@
     }
     else
     {
+        //TODO:  Add a general configuration parameter for user info encryption
+        if (1)
+        {
         MG_CRYPTOGRAPHY_TRY()
 
         MgCryptographyUtil cryptoUtil;
@@ -397,5 +410,12 @@
         MgUtil::MultiByteToWideChar(password, m_password);
 
         MG_CRYPTOGRAPHY_CATCH_AND_THROW(L"MgUserInformation.Deserialize")
+        }
+        else
+        {
+            STRING::size_type sep = credentials.find(L"\t");
+            m_username = credentials.substr(0, sep);
+            m_password = credentials.substr(sep+1);
+        }
     }
 }

Modified: trunk/MgDev/Common/PlatformBase/Services/ResourceService.cpp
===================================================================
--- trunk/MgDev/Common/PlatformBase/Services/ResourceService.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/PlatformBase/Services/ResourceService.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -192,7 +192,12 @@
     throw new MgNotImplementedException(L"MgResourceService.ResourceExists", __LINE__, __WFILE__, NULL, L"", NULL);
 }
 
+bool MgResourceService::HasPermission(MgResourceIdentifier* resource, CREFSTRING permission)
+{
+    throw new MgNotImplementedException(L"MgResourceService.HasPermission", __LINE__, __WFILE__, NULL, L"", NULL);
+}
 
+
 //////////////////////////////////////////////////////////////////
 /// \brief
 /// Enumerates the unmanaged data

Modified: trunk/MgDev/Common/PlatformBase/Services/ResourceService.h
===================================================================
--- trunk/MgDev/Common/PlatformBase/Services/ResourceService.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/PlatformBase/Services/ResourceService.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -1721,6 +1721,20 @@
 INTERNAL_API:
 
     //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Returns if permission has been granted for a resource
+    /// permission named data for the specified resource.
+    ///
+    /// \param resource
+    /// Resource identifier describing the resource.
+    /// \param permission
+    /// Requested permission for the resource.  See MgResourcePermission.
+    ///
+    /// \return
+    /// True if user has requested permission.
+    virtual bool HasPermission(MgResourceIdentifier* resource, CREFSTRING permission);
+
+    //////////////////////////////////////////////////////////////////
     /// Enumerations
     enum OperationId
     {

Modified: trunk/MgDev/Common/PlatformBase/Services/ServiceRegistry.cpp
===================================================================
--- trunk/MgDev/Common/PlatformBase/Services/ServiceRegistry.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/PlatformBase/Services/ServiceRegistry.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -65,7 +65,7 @@
 
 MgService* MgServiceRegistry::CreateService(INT16 serviceType, ServerConnectionType connType)
 {
-    ServiceRegistry registry = m_serviceCreators[connType];
+    ServiceRegistry& registry = m_serviceCreators[connType];
     const ServiceCreatorFunc& func = registry[serviceType];
     if (NULL == func)
     {
@@ -177,3 +177,4 @@
     return true;
 }
 
+

Modified: trunk/MgDev/Common/Stylization/GDRenderer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/GDRenderer.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/GDRenderer.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -60,6 +60,7 @@
 #include "RSDWFInputStream.h"
 #include "LabelRenderer.h"
 #include "LabelRendererLocal.h"
+#include "complex_polygon_gd.h"
 
 #include "SymbolTrans.h"
 
@@ -159,6 +160,8 @@
         m_labeler = new LabelRenderer(this);
     else
         m_labeler = new LabelRendererLocal(this, tileExtentOffset);
+
+    m_polyrasterizer = new complex_polygon_gd();
 }
 
 
@@ -173,6 +176,8 @@
         delete [] m_wtPointBuffer;
 
     delete m_labeler;
+
+    delete m_polyrasterizer;
 }
 
 
@@ -430,18 +435,9 @@
             gdImageSetTile((gdImagePtr)m_imout, fillpat);
         }
 
-        //just a polygon, no need for a contourset
-        if (workbuffer->cntr_count() == 1)
-        {
-            gdImageFilledPolygon((gdImagePtr)m_imout, (gdPoint*)m_wtPointBuffer, workbuffer->point_count(), (fillpat)? gdTiled : gdc);
-        }
-        else //otherwise make a contour set
-        {
-            rs_gdImageMultiPolygon((gdImagePtr)m_imout,
-                workbuffer->cntrs(), workbuffer->cntr_count(),
-                (gdPoint*)m_wtPointBuffer, workbuffer->point_count(),
-                (fillpat) ? gdTiled : gdc);
-        }
+        //call the new rasterizer
+        m_polyrasterizer->FillPolygon((Point*)m_wtPointBuffer, workbuffer->point_count(), workbuffer->cntrs(), workbuffer->cntr_count(), 
+            (fillpat) ? gdTiled : gdc, (gdImagePtr)m_imout);
 
         if (fillpat)
         {

Modified: trunk/MgDev/Common/Stylization/GDRenderer.h
===================================================================
--- trunk/MgDev/Common/Stylization/GDRenderer.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/GDRenderer.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -39,6 +39,8 @@
 
 struct RS_Font;
 
+class complex_polygon_gd;
+
 class GDRenderer : public Renderer
 {
     friend class LabelRenderer;
@@ -269,6 +271,9 @@
 
     //remember id of last symbol
     RS_MarkerDef m_lastSymbol;
+
+    //polygon rasterizer
+    complex_polygon_gd* m_polyrasterizer;
 };
 
 #endif

Modified: trunk/MgDev/Common/Stylization/LabelRendererLocal.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/LabelRendererLocal.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/LabelRendererLocal.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -220,17 +220,42 @@
             double yoffset = (1.0 - ((int)(1.0/yinc))*yinc) * 0.5;
             double xoffset = (1.0 - ((int)(1.0/xinc))*xinc) * 0.5;
 
+            //parametric clip coordinates used to determine a subset of the
+            //polygon's bounding box which we will attempt to cover with
+            //periodic labels
+            double invheight = 1.0 / b.height();
+            double tilestarty = (rejectBounds.miny - b.miny) * invheight;
+            tilestarty = rs_max(0.0, tilestarty);
+            double tileendy = (rejectBounds.maxy - b.miny) * invheight;
+            tileendy = rs_min(1.0, tileendy);
+
+            double invwidth = 1.0 / b.width();
+            double tilestartx = (rejectBounds.minx - b.minx) * invwidth;
+            tilestartx = rs_max(0.0, tilestartx);
+            double tileendx = (rejectBounds.maxx - b.minx) * invwidth;
+            tileendx = rs_min(1.0, tileendx);
+
+
             double ypos = yoffset;
+
+            //move ypos up until we reach a relevant position that is likely to 
+            //draw a label that intersects the tile
+            if (tilestarty != 0.0)
+                ypos += ceil((tilestarty - ypos) / yinc) * yinc;
+
             bool offset = false;
 
-            //TODO: we should be smarter about the start and end parametric positions
-            //instead of looping from  around 0 to  around 1. If we are far zoomed in
-            //on a polygon, those loops can take quite some time to execute
-            while (ypos <= 1.0)
+            //loop to add labels 
+            while (ypos <= tileendy)
             {
                 double xpos = xoffset + ((offset) ? 0.5 * xinc : 0.0);
 
-                while (xpos <= 1.0)
+                //move to the right until we reach a relevant position that is likely to 
+                //draw a label that intersects the tile
+                if (tilestartx != 0.0)
+                    xpos += ceil((tilestartx - xpos) / xinc) * xinc;
+
+                while (xpos <= tileendx)
                 {
                     //compute mapping space position for label, based on
                     double posx = b.minx + xpos * b.width();
@@ -238,9 +263,7 @@
 
                     //rejection of labels that are far outside the current tile
                     //and also make sure the point we genrated is inside the polygon
-                    if (posx <= rejectBounds.maxx && posx >= rejectBounds.minx
-                        && posy <= rejectBounds.maxy && posy >= rejectBounds.miny
-                        && Centroid::PointInPolygon(path->points(), 2 * path->point_count(),
+                    if (Centroid::PointInPolygon(path->points(), 2 * path->point_count(),
                                 path->cntrs(), path->cntr_count(), posx, posy ))
                     {
                         RS_LabelInfo* info = &labels[0]; //assumes one label info passed in

Modified: trunk/MgDev/Common/Stylization/Makefile.am
===================================================================
--- trunk/MgDev/Common/Stylization/Makefile.am	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/Makefile.am	2007-01-20 00:49:25 UTC (rev 1064)
@@ -53,7 +53,8 @@
   LabelRendererLocal.cpp \
   SimpleOverpost.cpp \
   RS_ByteData.cpp \
-  FontManager.cpp
+  FontManager.cpp \
+  complex_polygon_gd.cpp
 
 
 noinst_HEADERS = \
@@ -120,7 +121,8 @@
   RS_Font.h \
   FontManager.h \
   SymbolVisitor.h \
-  SLDSymbols.h
+  SLDSymbols.h \
+  complex_polygon_gd.h
 
 AM_CXXFLAGS = @CXXFLAGS@ -DDWFTK_BUILD_EXPAT
 

Modified: trunk/MgDev/Common/Stylization/Stylization.vcproj
===================================================================
--- trunk/MgDev/Common/Stylization/Stylization.vcproj	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/Stylization.vcproj	2007-01-20 00:49:25 UTC (rev 1064)
@@ -41,7 +41,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\Oem\DWFTK7.1\develop\global\src;..\..\Oem\DWFTK7.1\develop\global\src\dwf;..\..\Oem\DWFTK7.1\develop\global\src\dwfemap;..\..\Oem\FDO\inc;..\..\Oem\gd\gd;..\MdfModel;..\..\Oem\gd\freetype\include"
+				AdditionalIncludeDirectories="..\..\Oem\DWFTK7.1\develop\global\src;..\..\Oem\DWFTK7.1\develop\global\src\dwf;..\..\Oem\DWFTK7.1\develop\global\src\dwfemap;..\..\Oem\FDO\inc;..\..\Oem\gd\gd;..\MdfModel;..\..\Oem\gd\freetype\include;..\..\Oem\gd\lpng;..\..\Oem\gd\zlib"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;STYLIZATION_EXPORTS;DWFTK_USE_DWFCORE_ZLIB;DWFTK_BUILD_EXPAT;DWFCORE_STATIC;DWFTK_STATIC;WHIP_STATIC_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -62,10 +62,10 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="FdoCommon.lib Fdo.lib dwfcore_wt.1.1.1.lib dwftk_wt.7.1.1.lib whiptk_wt.7.7.601.lib emaptk_wt.1.0.0.lib MgMdfModeld.lib gd.lib freetype2110_D.lib"
+				AdditionalDependencies="FdoCommon.lib Fdo.lib dwfcore_wt.1.1.1.lib dwftk_wt.7.1.1.lib whiptk_wt.7.7.601.lib emaptk_wt.1.0.0.lib MgMdfModeld.lib gd.lib freetype2110_D.lib user32.lib gdi32.lib shell32.lib libpngd.lib"
 				OutputFile="$(OutDir)/MgStylizationd.dll"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\..\Oem\DWFTK7.1\develop\global\lib\static\debug\vc8.0;..\..\Oem\FDO\lib;..\..\Oem\gd\build\win32\gd\Debug;..\..\Common\lib\debug;..\..\Oem\gd\freetype\objs"
+				AdditionalLibraryDirectories="..\..\Oem\DWFTK7.1\develop\global\lib\static\debug\vc8.0;..\..\Oem\FDO\lib;..\..\Oem\gd\build\win32\gd\Debug;..\..\Common\lib\debug;..\..\Oem\gd\freetype\objs;..\..\Oem\gd\lpng\projects\visualc8\Win32_LIB_ASM_Debug"
 				IgnoreDefaultLibraryNames="libcmtd.lib"
 				DelayLoadDLLs="Fdo.dll;FdoCommon.dll"
 				GenerateDebugInformation="true"
@@ -129,7 +129,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\Oem\DWFTK7.1\develop\global\src;..\..\Oem\DWFTK7.1\develop\global\src\dwf;..\..\Oem\DWFTK7.1\develop\global\src\dwfemap;..\..\Oem\FDO\inc;..\..\Oem\gd\gd;..\MdfModel;..\..\Oem\gd\freetype\include"
+				AdditionalIncludeDirectories="..\..\Oem\DWFTK7.1\develop\global\src;..\..\Oem\DWFTK7.1\develop\global\src\dwf;..\..\Oem\DWFTK7.1\develop\global\src\dwfemap;..\..\Oem\FDO\inc;..\..\Oem\gd\gd;..\MdfModel;..\..\Oem\gd\freetype\include;..\..\Oem\gd\lpng;..\..\Oem\gd\zlib"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;STYLIZATION_EXPORTS;DWFTK_USE_DWFCORE_ZLIB;DWFTK_BUILD_EXPAT;DWFCORE_STATIC;DWFTK_STATIC;WHIP_STATIC_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
 				ExceptionHandling="2"
 				RuntimeLibrary="2"
@@ -148,10 +148,10 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="FdoCommon.lib Fdo.lib dwfcore_wt.1.1.1.lib dwftk_wt.7.1.1.lib whiptk_wt.7.7.601.lib emaptk_wt.1.0.0.lib MgMdfModel.lib gd.lib freetype2110.lib"
+				AdditionalDependencies="FdoCommon.lib Fdo.lib dwfcore_wt.1.1.1.lib dwftk_wt.7.1.1.lib whiptk_wt.7.7.601.lib emaptk_wt.1.0.0.lib MgMdfModel.lib gd.lib freetype2110.lib shell32.lib user32.lib libpng.lib"
 				OutputFile="$(OutDir)/MgStylization.dll"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\..\Oem\DWFTK7.1\develop\global\lib\static\release\vc8.0;..\..\Oem\FDO\lib;..\..\Oem\gd\build\win32\gd\Release;..\..\Common\lib\Release;..\..\Oem\gd\freetype\objs"
+				AdditionalLibraryDirectories="..\..\Oem\DWFTK7.1\develop\global\lib\static\release\vc8.0;..\..\Oem\FDO\lib;..\..\Oem\gd\build\win32\gd\Release;..\..\Common\lib\Release;..\..\Oem\gd\freetype\objs;..\..\Oem\gd\lpng\projects\visualc8\Win32_LIB_ASM_Release"
 				IgnoreDefaultLibraryNames="libcmt.lib"
 				DelayLoadDLLs="Fdo.dll;FdoCommon.dll"
 				GenerateDebugInformation="true"
@@ -359,6 +359,32 @@
 			Name="GDRenderer"
 			>
 			<File
+				RelativePath=".\complex_polygon_gd.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\complex_polygon_gd.h"
+				>
+			</File>
+			<File
 				RelativePath=".\FontManager.cpp"
 				>
 			</File>

Added: trunk/MgDev/Common/Stylization/complex_polygon_gd.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/complex_polygon_gd.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/complex_polygon_gd.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -0,0 +1,355 @@
+
+/* Traian 1/2/2007 
+   Polygon fill routines taken from the Graphics Programming Black Book by M. Abrash.
+   
+   I (heavily) modified the code as follows:
+   * add support for polygons with multiple contours,
+   * do polygon clipping if parts of the polygon are outside of
+   the screen,
+   * Reduce number of memory allocations by reusing the same
+   buffer for egde lists
+   * function no longer returns an int
+
+   Original code description follows below.
+*/
+
+/* Color-fills an arbitrarily-shaped polygon described by VertexList.
+If the first and last points in VertexList are not the same, the path
+around the polygon is automatically closed. All vertices are offset
+by (XOffset, YOffset). Returns 1 for success, 0 if memory allocation
+failed.
+If the polygon shape is known in advance, speedier processing may be
+enabled by specifying the shape as follows: "convex" - a rubber band
+stretched around the polygon would touch every vertex in order;
+"nonconvex" - the polygon is not self-intersecting, but need not be
+convex; "complex" - the polygon may be self-intersecting, or, indeed,
+any sort of polygon at all. Complex will work for all polygons; convex
+is fastest. Undefined results will occur if convex is specified for a
+nonconvex or complex polygon.
+Define CONVEX_CODE_LINKED if the fast convex polygon filling code from
+Chapter 21 is linked in. Otherwise, convex polygons are
+handled by the complex polygon filling code.
+Nonconvex is handled as complex in this implementation. See text for a
+discussion of faster nonconvex handling
+
+Link with L23-4.C and L23-2.C in Small model.
+Tested with Borland C++ 4.02 by Jim Mischel 12/16/94.
+*/
+
+#include "stdafx.h"
+#include <stdio.h>
+#include <math.h>
+#include <malloc.h>
+#include "complex_polygon_gd.h"
+
+/* Describes a single point (used for a single vertex) */
+struct Point {
+   int X;   /* X coordinate */
+   int Y;   /* Y coordinate */
+};
+
+/* Describes the beginning and ending X coordinates of a single
+   horizontal line (used only by fast polygon fill code) */
+struct HLine {
+   int XStart; /* X coordinate of leftmost pixel in line */
+   int XEnd;   /* X coordinate of rightmost pixel in line */
+};
+/* Describes a Length-long series of horizontal lines, all assumed to
+   be on contiguous scan lines starting at YStart and proceeding
+   downward (used to describe a scan-converted polygon to the
+   low-level hardware-dependent drawing code) (used only by fast
+   polygon fill code) */
+struct HLineList {
+   int Length;                /* # of horizontal lines */
+   int YStart;                /* Y coordinate of topmost line */
+   struct HLine * HLinePtr;   /* pointer to list of horz lines */
+};
+
+#define SWAP(a,b) {temp = a; a = b; b = temp;}
+
+struct EdgeState {
+    struct EdgeState *NextEdge;
+    int X;
+    int StartY;
+    int WholePixelXMove;
+    int XDirection;
+    int ErrorTerm;
+    int ErrorTermAdjUp;
+    int ErrorTermAdjDown;
+    int Count;
+};
+
+complex_polygon_gd::complex_polygon_gd()
+{
+    m_bufEdgeState = NULL;
+    m_nBufEdgeState = 0;
+}
+complex_polygon_gd::~complex_polygon_gd()
+{
+    delete [] m_bufEdgeState;
+}
+
+
+void complex_polygon_gd::FillPolygon(Point * VertexList, int nVerts, int* Contours, int nContours, int Color, gdImagePtr target)
+{
+    struct EdgeState *EdgeTableBuffer;
+    int CurrentY;
+
+    /* It takes a minimum of 3 vertices to cause any pixels to be
+    drawn; reject polygons that are guaranteed to be invisible */
+    if (nVerts < 3)
+        return;
+
+    /* Get enough memory to store the entire edge table */
+    /* TIS -- reuse a buffer owned by the class */
+    if (m_nBufEdgeState < nVerts)
+    {
+        delete [] m_bufEdgeState;
+        m_nBufEdgeState = nVerts;
+        m_bufEdgeState = new EdgeState[m_nBufEdgeState];
+    }
+
+    EdgeTableBuffer = m_bufEdgeState;
+
+    /* Build the global edge table */
+    BuildGET(VertexList, Contours, nContours, EdgeTableBuffer, target->sy - 1);
+
+    if (m_GETPtr) /* true if polygon was not completely clipped out */
+    {
+        /* Scan down through the polygon edges, one scan line at a time,
+        so long as at least one edge remains in either the GET or AET */
+        m_AETPtr = NULL;    /* initialize the active edge table to empty */
+        CurrentY = m_GETPtr->StartY; /* start at the top polygon vertex */
+        while (((m_GETPtr != NULL) || (m_AETPtr != NULL))
+            && CurrentY != target->sy) 
+        {
+            MoveXSortedToAET(CurrentY);  /* update AET for this scan line */
+            ScanOutAET(CurrentY, Color, target); /* draw this scan line from AET */
+            AdvanceAET();                /* advance AET edges 1 scan line */
+            XSortAET();                  /* resort on X */
+            CurrentY++;                  /* advance to the next scan line */
+        }
+    }
+}
+
+/* Creates a GET in the buffer pointed to by NextFreeEdgeStruc from
+the vertex list. Edge endpoints are flipped, if necessary, to
+guarantee all edges go top to bottom. The GET is sorted primarily
+by ascending Y start coordinate, and secondarily by ascending X
+start coordinate within edges with common Y coordinates */
+void complex_polygon_gd::BuildGET(struct Point * VertexList,
+int* Contours, int nContours, struct EdgeState * NextFreeEdgeStruc, int MaxY)
+{
+    int i, StartX, StartY, EndX, EndY, DeltaY, DeltaX, Width, temp, SkipY;
+    struct EdgeState *NewEdgePtr;
+    struct EdgeState *FollowingEdge, **FollowingEdgeLink;
+    struct Point *VertexPtr;
+
+    /* Scan through the vertex list and put all non-0-height edges into
+    the GET, sorted by increasing Y start coordinate */
+    VertexPtr = VertexList;   /* point to the vertex list */
+    m_GETPtr = NULL;    /* initialize the global edge table to empty */
+    
+    int offset = 0;
+    for (int j=0; j<nContours; j++)
+    {
+        for (i = 0; i < Contours[j]; i++) {
+            /* Calculate the edge height and width */
+            StartX = VertexPtr[offset + i].X;
+            StartY = VertexPtr[offset + i].Y;
+            /* The edge runs from the current point to the previous one */
+            if (i == 0) {
+                /* Wrap back around to the end of the list */
+                EndX = VertexPtr[offset + Contours[j]-1].X;
+                EndY = VertexPtr[offset + Contours[j]-1].Y;
+            } else {
+                EndX = VertexPtr[offset + i-1].X;
+                EndY = VertexPtr[offset + i-1].Y;
+            }
+            /* Make sure the edge runs top to bottom */
+            if (StartY > EndY) {
+                SWAP(StartX, EndX);
+                SWAP(StartY, EndY);
+            }
+            /* Skip if this can't ever be an active edge (has 0 height)
+               or if the edge doesn't cross the vertical screen 
+               bounds at all */
+
+            if ((DeltaY = EndY - StartY) != 0 
+                && (EndY > 0) && (StartY <= MaxY)) {
+                /* Allocate space for this edge's info, and fill in the
+                structure */
+                NewEdgePtr = NextFreeEdgeStruc++;
+                NewEdgePtr->XDirection =   /* direction in which X moves */
+                    ((DeltaX = EndX - StartX) > 0) ? 1 : -1;
+                Width = abs(DeltaX);
+                NewEdgePtr->X = StartX;
+                
+                /* clip stuff that's before beginning of screen
+                   We can't just change StartY -- we also need to
+                   update the initial conditions for the edge
+                   rasterizer 
+                   */
+
+                /* find how many rows we have to skip */
+                SkipY = (StartY >=0) ? 0 : -StartY; 
+                StartY += SkipY;
+                NewEdgePtr->StartY = StartY;
+                NewEdgePtr->Count = DeltaY - SkipY;
+                NewEdgePtr->ErrorTermAdjDown = DeltaY;
+
+                /* set initial rasterization conditions */
+                if (DeltaX >= 0)  /* initial error term going L->R */
+                    NewEdgePtr->ErrorTerm = 0;
+                else              /* initial error term going R->L */
+                    NewEdgePtr->ErrorTerm = -DeltaY + 1;
+                if (DeltaY >= Width) {     /* Y-major edge */
+                    NewEdgePtr->WholePixelXMove = 0;
+                    NewEdgePtr->ErrorTermAdjUp = Width;
+                } else {                   /* X-major edge */
+                    NewEdgePtr->WholePixelXMove =
+                        (Width / DeltaY) * NewEdgePtr->XDirection;
+                    NewEdgePtr->ErrorTermAdjUp = Width % DeltaY;
+                }
+
+                /* update initial conditions only if we have to*/
+                if (SkipY != 0) {
+                    int XMove = (SkipY + 1) * NewEdgePtr->WholePixelXMove;
+                    int ErrorMove = NewEdgePtr->ErrorTerm + (SkipY + 1) * NewEdgePtr->ErrorTermAdjUp;
+                    int ErrorDiv = ErrorMove / NewEdgePtr->ErrorTermAdjDown;
+                    int ErrorMod = ErrorMove % NewEdgePtr->ErrorTermAdjDown;
+
+                    NewEdgePtr->X += XMove + ErrorDiv * NewEdgePtr->XDirection;
+                    StartX = NewEdgePtr->X;
+                    NewEdgePtr->ErrorTerm = ErrorMod - NewEdgePtr->ErrorTermAdjDown;
+                }
+
+                /* Link the new edge into the GET so that the edge list is
+                still sorted by Y coordinate, and by X coordinate for all
+                edges with the same Y coordinate */
+                FollowingEdgeLink = &m_GETPtr;
+                for (;;) {
+                    FollowingEdge = *FollowingEdgeLink;
+                    if ((FollowingEdge == NULL) ||
+                        (FollowingEdge->StartY > StartY) ||
+                        ((FollowingEdge->StartY == StartY) &&
+                        (FollowingEdge->X >= StartX))) {
+                            NewEdgePtr->NextEdge = FollowingEdge;
+                            *FollowingEdgeLink = NewEdgePtr;
+                            break;
+                    }
+                    FollowingEdgeLink = &FollowingEdge->NextEdge;
+                }
+            }
+        }
+
+        offset += Contours[j];
+    }
+}
+
+/* Sorts all edges currently in the active edge table into ascending
+order of current X coordinates */
+void complex_polygon_gd::XSortAET() {
+    struct EdgeState *CurrentEdge, **CurrentEdgePtr, *TempEdge;
+    int SwapOccurred;
+
+    /* Scan through the AET and swap any adjacent edges for which the
+    second edge is at a lower current X coord than the first edge.
+    Repeat until no further swapping is needed */
+    if (m_AETPtr != NULL) {
+        do {
+            SwapOccurred = 0;
+            CurrentEdgePtr = &m_AETPtr;
+            while ((CurrentEdge = *CurrentEdgePtr)->NextEdge != NULL) {
+                if (CurrentEdge->X > CurrentEdge->NextEdge->X) {
+                    /* The second edge has a lower X than the first;
+                    swap them in the AET */
+                    TempEdge = CurrentEdge->NextEdge->NextEdge;
+                    *CurrentEdgePtr = CurrentEdge->NextEdge;
+                    CurrentEdge->NextEdge->NextEdge = CurrentEdge;
+                    CurrentEdge->NextEdge = TempEdge;
+                    SwapOccurred = 1;
+                }
+                CurrentEdgePtr = &(*CurrentEdgePtr)->NextEdge;
+            }
+        } while (SwapOccurred != 0);
+    }
+}
+
+/* Advances each edge in the AET by one scan line.
+Removes edges that have been fully scanned. */
+void complex_polygon_gd::AdvanceAET() {
+    struct EdgeState *CurrentEdge, **CurrentEdgePtr;
+
+    /* Count down and remove or advance each edge in the AET */
+    CurrentEdgePtr = &m_AETPtr;
+    while ((CurrentEdge = *CurrentEdgePtr) != NULL) {
+        /* Count off one scan line for this edge */
+        if ((--(CurrentEdge->Count)) == 0) {
+            /* This edge is finished, so remove it from the AET */
+            *CurrentEdgePtr = CurrentEdge->NextEdge;
+        } else {
+            /* Advance the edge's X coordinate by minimum move */
+            CurrentEdge->X += CurrentEdge->WholePixelXMove;
+            /* Determine whether it's time for X to advance one extra */
+            if ((CurrentEdge->ErrorTerm +=
+                CurrentEdge->ErrorTermAdjUp) > 0) {
+                    CurrentEdge->X += CurrentEdge->XDirection;
+                    CurrentEdge->ErrorTerm -= CurrentEdge->ErrorTermAdjDown;
+            }
+            CurrentEdgePtr = &CurrentEdge->NextEdge;
+        }
+    }
+}
+
+/* Moves all edges that start at the specified Y coordinate from the
+GET to the AET, maintaining the X sorting of the AET. */
+void complex_polygon_gd::MoveXSortedToAET(int YToMove) {
+    struct EdgeState *AETEdge, **AETEdgePtr, *TempEdge;
+    int CurrentX;
+
+    /* The GET is Y sorted. Any edges that start at the desired Y
+    coordinate will be first in the GET, so we'll move edges from
+    the GET to AET until the first edge left in the GET is no longer
+    at the desired Y coordinate. Also, the GET is X sorted within
+    each Y coordinate, so each successive edge we add to the AET is
+    guaranteed to belong later in the AET than the one just added */
+    AETEdgePtr = &m_AETPtr;
+    while ((m_GETPtr != NULL) && (m_GETPtr->StartY == YToMove)) {
+        CurrentX = m_GETPtr->X;
+        /* Link the new edge into the AET so that the AET is still
+        sorted by X coordinate */
+        for (;;) {
+            AETEdge = *AETEdgePtr;
+            if ((AETEdge == NULL) || (AETEdge->X >= CurrentX)) {
+                TempEdge = m_GETPtr->NextEdge;
+                *AETEdgePtr = m_GETPtr;  /* link the edge into the AET */
+                m_GETPtr->NextEdge = AETEdge;
+                AETEdgePtr = &m_GETPtr->NextEdge;
+                m_GETPtr = TempEdge;   /* unlink the edge from the GET */
+                break;
+            } else {
+                AETEdgePtr = &AETEdge->NextEdge;
+            }
+        }
+    }
+}
+
+/* Fills the scan line described by the current AET at the specified Y
+coordinate in the specified color, using the odd/even fill rule */
+void complex_polygon_gd::ScanOutAET(int YToScan, int Color, gdImagePtr target) {
+    int LeftX;
+    struct EdgeState *CurrentEdge;
+
+    /* Scan through the AET, drawing line segments as each pair of edge
+    crossings is encountered. The nearest pixel on or to the right
+    of left edges is drawn, and the nearest pixel to the left of but
+    not on right edges is drawn */
+    CurrentEdge = m_AETPtr;
+    while (CurrentEdge != NULL) {
+        LeftX = CurrentEdge->X;
+        CurrentEdge = CurrentEdge->NextEdge;
+        DrawHorizontalLineSeg(YToScan, LeftX, CurrentEdge->X-1, Color, target);
+        CurrentEdge = CurrentEdge->NextEdge;
+    }
+}


Property changes on: trunk/MgDev/Common/Stylization/complex_polygon_gd.cpp
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/MgDev/Common/Stylization/complex_polygon_gd.h
===================================================================
--- trunk/MgDev/Common/Stylization/complex_polygon_gd.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Common/Stylization/complex_polygon_gd.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -0,0 +1,40 @@
+
+#ifndef complex_polygon_gd_H
+#define complex_polygon_gd_H
+
+#include "gd.h"
+
+struct EdgeState;
+struct Point;
+
+class complex_polygon_gd
+{
+public:
+    complex_polygon_gd();
+    ~complex_polygon_gd();
+
+    void FillPolygon(Point * VertexList, int nVerts, int* Contours, int nContours, int Color, gdImagePtr target);
+
+private:
+    
+    //This is what you want to implement for your own render target
+    //for all the rest of the code to work with it
+    inline void DrawHorizontalLineSeg(int Y, int StartX, int EndX, int Color, gdImagePtr target)
+    {
+        gdImageLine(target, StartX, Y, EndX, Y, Color);
+    }
+
+    void BuildGET(Point *, int* Contours, int nContours, EdgeState *, int MaxY);
+    void MoveXSortedToAET(int);
+    void ScanOutAET(int, int, gdImagePtr);
+    void AdvanceAET(void);
+    void XSortAET(void);
+
+    /* Pointers to global edge table (GET) and active edge table (AET) */
+    struct EdgeState *m_GETPtr, *m_AETPtr;
+    EdgeState* m_bufEdgeState;
+    size_t m_nBufEdgeState;
+   
+};
+
+#endif


Property changes on: trunk/MgDev/Common/Stylization/complex_polygon_gd.h
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/MgDev/Server/src/Common/Manager/LogManager.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/LogManager.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Common/Manager/LogManager.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -100,7 +100,8 @@
     m_bTraceLogEnabled(false),      // Disabled by default
     m_bTraceLogHeader(false),
     m_TraceLogFileName(MgLogManager::DefaultTraceLogFileName),
-    m_pLogThread(NULL)
+    m_pLogThread(NULL),
+    m_writeCount(0)
 {
 }
 
@@ -2060,7 +2061,10 @@
 
                 MG_LOGMANAGER_TRY()
 
-                if (false == CheckArchiveFrequency(logType, filename))
+                // This is an expensive check, only do it occasionally
+                m_writeCount++;
+                if (0 == (m_writeCount%10) &&
+                    false == CheckArchiveFrequency(logType, filename))
                 {
                     ArchiveLog(logType);
                 }

Modified: trunk/MgDev/Server/src/Common/Manager/LogManager.h
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/LogManager.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Common/Manager/LogManager.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -476,6 +476,7 @@
     ACE_Recursive_Thread_Mutex m_mutex;
     ACE_Thread_Manager m_threadManager;
     MgLogThread* m_pLogThread;
+    INT64 m_writeCount;
 
 };
 

Modified: trunk/MgDev/Server/src/Common/Manager/PermissionManager.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/PermissionManager.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Common/Manager/PermissionManager.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -20,7 +20,7 @@
 
 ACE_Recursive_Thread_Mutex MgPermissionManager::sm_mutex;
 Ptr<MgPermissionCache> MgPermissionManager::sm_permissionCache = new MgPermissionCache;
-INT32 MgPermissionManager::sm_permissionInfoCacheSize = 1000;
+INT32 MgPermissionManager::sm_permissionInfoCacheSize = 0;
 time_t MgPermissionManager::sm_cutoffTime = 0;
 
 ///----------------------------------------------------------------------------
@@ -36,14 +36,17 @@
 
     m_permissionCache = sm_permissionCache;
 
-    MgConfiguration* configuration = MgConfiguration::GetInstance();
-    assert(NULL != configuration);
+    if (sm_permissionInfoCacheSize <= 0)
+    {
+        MgConfiguration* configuration = MgConfiguration::GetInstance();
+        assert(NULL != configuration);
 
-    configuration->GetIntValue(
-        MgConfigProperties::ResourceServicePropertiesSection,
-        MgConfigProperties::ResourceServicePropertyResourcePermissionCacheSize,
-        sm_permissionInfoCacheSize,
-        MgConfigProperties::DefaultResourceServicePropertyResourcePermissionCacheSize);
+        configuration->GetIntValue(
+            MgConfigProperties::ResourceServicePropertiesSection,
+            MgConfigProperties::ResourceServicePropertyResourcePermissionCacheSize,
+            sm_permissionInfoCacheSize,
+            MgConfigProperties::DefaultResourceServicePropertyResourcePermissionCacheSize);
+    }
 }
 
 ///----------------------------------------------------------------------------

Modified: trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -467,7 +467,7 @@
             extents->GetLowerLeftCoordinate()->GetY(),
             extents->GetUpperRightCoordinate()->GetX(),
             extents->GetUpperRightCoordinate()->GetY());
-        Ptr<MgFeatureReader> featureReader = MgStylizationUtil::ExecuteFeatureQuery(m_svcFeature, rsExtent, vl, NULL, destCs, layerCs);
+        Ptr<MgFeatureReader> featureReader = MgStylizationUtil::ExecuteFeatureQuery(m_svcFeature, rsExtent, vl, NULL, destCs, layerCs, NULL);
         if (featureReader.p)
         {
             //wrap in an RS_FeatureReader
@@ -891,3 +891,5 @@
 }
 
 
+
+

Modified: trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -137,7 +137,8 @@
                                                         MdfModel::VectorLayerDefinition* vl,
                                                         const wchar_t* overrideFilter,
                                                         MgCoordinateSystem* mapCs,
-                                                        MgCoordinateSystem* layerCs)
+                                                        MgCoordinateSystem* layerCs,
+                                                        TransformCache* cache)
 {
 #ifdef _DEBUG
     long dwStart = GetTickCount();
@@ -156,20 +157,58 @@
 
     if (mapCs && layerCs)
     {
-        trans = new MgCoordinateSystemTransform(mapCs, layerCs);
+        if (NULL != cache)
+        {
+            trans = cache->GetMgTransform();
+        }
+
+        if (!trans)
+        {
+            trans = new MgCoordinateSystemTransform(mapCs, layerCs);
+            if (NULL != cache)
+            {
+                cache->SetMgTransform(trans);
+            }
+        }
     }
 
-    //bounds in mapping space
+
+
+    //start with bounds in mapping space
     Ptr<MgCoordinate> ll = new MgCoordinateXY(extent.minx, extent.miny);
     Ptr<MgCoordinate> ur = new MgCoordinateXY(extent.maxx, extent.maxy);
 
-    //if we have a valid transform, get the request extent in layer's space
-    if (trans)
+    Ptr<MgEnvelope> layerExt;
+
+    //do we have a cached extent?
+    if (NULL != cache)
     {
-        Ptr<MgEnvelope> mapExt= new MgEnvelope(ll, ur);
+        layerExt = cache->GetEnvelope();
+    }
 
-        //get corresponding bounds in layer space
-        Ptr<MgEnvelope> layerExt = trans->Transform(mapExt);
+    if (!layerExt)
+    {
+        //no cached extent
+        //if we have a valid transform, get the request extent in layer's space
+        if (trans)
+        {
+            Ptr<MgEnvelope> mapExt = new MgEnvelope(ll, ur);
+
+            //get corresponding bounds in layer space
+            layerExt = trans->Transform(mapExt);
+
+            ll = layerExt->GetLowerLeftCoordinate();
+            ur = layerExt->GetUpperRightCoordinate();
+
+            if (NULL != cache)
+            {
+                cache->SetEnvelope(layerExt);
+            }
+        }
+    }
+    else
+    {
+        //did have a cached extent, just use it.
         ll = layerExt->GetLowerLeftCoordinate();
         ur = layerExt->GetUpperRightCoordinate();
     }
@@ -410,8 +449,13 @@
     printf("\nStylizeLayers() **MAPSTART** Layers: %d\n", layers->GetCount());
     #endif
 
+    // Cache coordinate system transforms for the life of the
+    // stylization operation.
+    TransformCacheMap transformCache;
+
     for (int i = layers->GetCount()-1; i >= 0; i--)
     {
+        TransformCache* cached = NULL;
         MgCSTrans* xformer = NULL;
         MdfModel::LayerDefinition* ldf = NULL;
 
@@ -577,12 +621,29 @@
                         }
 
                         // Create coordinate system transformer
-                        srcCs = (srcwkt.empty()) ? NULL : csFactory->Create(srcwkt);
-
-                        if (srcCs.p)
+                        if (!srcwkt.empty())
                         {
-                            xformer = new MgCSTrans(srcCs, dstCs);
+                            
+                            TransformCacheMap::const_iterator iter = transformCache.find(srcwkt);
+                            if (transformCache.end() != iter) cached = (*iter).second;
+                            if (NULL != cached)
+                            {
+                                srcCs = cached->GetCoordSys();
+                                xformer = cached->GetTransform();
+                            }
+                            else 
+                            {
+                                srcCs = csFactory->Create(srcwkt);
+                                if (srcCs.p)
+                                {
+                                    xformer = new MgCSTrans(srcCs, dstCs);
+                                    cached = new TransformCache(xformer, srcCs);
+                                    transformCache[srcwkt] = cached;
+                                }
+                            }
+                            
                         }
+
                     }
                     else
                     {
@@ -664,7 +725,7 @@
                         //we are not drawing the actual geometry
                         if (maxStrokes == 0)
                         {
-                            Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs);
+                            Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs, cached);
                             if (rdr.p)
                             {
                                 //wrap the MgFeatureReader in our RSMgFeatureReader wrapper
@@ -700,7 +761,7 @@
                                     syms->Adopt(syms2->GetAt(min(i, syms2->GetCount()-1)));
                                 }
 
-                                Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs);
+                                Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs, cached);
                                 if (rdr.p)
                                 {
                                     //wrap in an RS_FeatureReader
@@ -746,7 +807,7 @@
                     }
                     else
                     {
-                        Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs);
+                        Ptr<MgFeatureReader> rdr = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, srcCs, cached);
                         if (rdr.p)
                         {
                             //wrap the MgFeatureReader in our RSMgFeatureReader wrapper
@@ -861,11 +922,26 @@
                         }
 
                         // Create coordinate system transformer
-                        srcCs = (srcwkt.empty()) ? NULL : csFactory->Create(srcwkt);
-
-                        if (srcCs.p)
+                        if (!srcwkt.empty())
                         {
-                            xformer = new MgCSTrans(srcCs, dstCs);
+                            TransformCacheMap::const_iterator iter = transformCache.find(srcwkt);
+                            if (transformCache.end() != iter) cached = (*iter).second;
+                            if (NULL != cached)
+                            {
+                                srcCs = cached->GetCoordSys();
+                                xformer = cached->GetTransform();
+                            }
+                            else 
+                            {
+                                srcCs = csFactory->Create(srcwkt);
+                                if (srcCs.p)
+                                {
+                                    xformer = new MgCSTrans(srcCs, dstCs);
+                                    cached = new TransformCache(xformer, srcCs);
+                                    transformCache[srcwkt] = cached;
+                                }
+                            }
+                            
                         }
                     }
                     else
@@ -966,9 +1042,23 @@
 
                         if (!cs.empty() && cs != dstCs->ToString())
                         {
-                            //construct cs transformer if needed
-                            Ptr<MgCoordinateSystem> srcCs = csFactory->Create(cs);
-                            xformer = new MgCSTrans(srcCs, dstCs);
+                            // Create coordinate system transformer
+                            TransformCacheMap::const_iterator iter = transformCache.find(cs);
+                            if (transformCache.end() != iter) cached = (*iter).second;
+                            if (NULL != cached)
+                            {
+                                xformer = cached->GetTransform();
+                            }
+                            else 
+                            {
+                                Ptr<MgCoordinateSystem> srcCs = csFactory->Create(cs);
+                                if (srcCs.p)
+                                {
+                                    xformer = new MgCSTrans(srcCs, dstCs);
+                                    cached = new TransformCache(xformer, srcCs);
+                                    transformCache[cs] = cached;
+                                }
+                            }
                         }
                     }
 
@@ -1021,22 +1111,25 @@
 #endif
         }
 
-        if (xformer)
-        {
-            delete xformer;
-            xformer = NULL;
-        }
-
         if (ldf)
         {
             delete ldf;
             ldf = NULL;
         }
+
     }
 
     #ifdef _DEBUG
     printf("StylizeLayers() **MAPDONE** Layers: %d  Total Time = %6.4f (s)\n\n", layers->GetCount(), (GetTickCount()-dwStart)/1000.0);
     #endif
+
+    TransformCacheMap::iterator iter = transformCache.begin();
+    while (transformCache.end() != iter)
+    {
+        delete (*iter).second;
+        (*iter).second = NULL;
+        ++iter;
+    }
 }
 
 
@@ -1626,3 +1719,46 @@
 
     return NULL;
 }
+
+
+MgStylizationUtil::TransformCache::TransformCache(MgCSTrans* transform, MgCoordinateSystem* coordinateSystem)
+: m_xform(transform)
+{
+    m_coordSys = SAFE_ADDREF((MgCoordinateSystem*)coordinateSystem);
+}
+
+MgStylizationUtil::TransformCache::~TransformCache()
+{
+    delete m_xform;
+    m_xform = NULL;
+}
+
+MgCSTrans* MgStylizationUtil::TransformCache::GetTransform()
+{
+    return m_xform;
+}
+
+MgCoordinateSystem* MgStylizationUtil::TransformCache::GetCoordSys()
+{
+    return SAFE_ADDREF((MgCoordinateSystem*) m_coordSys);
+}
+
+void MgStylizationUtil::TransformCache::SetMgTransform(MgCoordinateSystemTransform* mgTransform)
+{
+    m_transform = SAFE_ADDREF((MgCoordinateSystemTransform*) mgTransform);
+}
+
+MgCoordinateSystemTransform* MgStylizationUtil::TransformCache::GetMgTransform()
+{
+    return SAFE_ADDREF((MgCoordinateSystemTransform*) m_transform);
+}
+
+void MgStylizationUtil::TransformCache::SetEnvelope(MgEnvelope* envelope)
+{
+    m_envelope = SAFE_ADDREF((MgEnvelope*) envelope);
+}
+
+MgEnvelope* MgStylizationUtil::TransformCache::GetEnvelope()
+{
+    return SAFE_ADDREF((MgEnvelope*) m_envelope);
+}

Modified: trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.h
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Mapping/StylizationUtil.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -32,12 +32,36 @@
 class MgStringCollection;
 class MgMap;
 class MgCoordinateSystem;
+class MgCSTrans;
 
 //Common stylization utility code -- used by both the mapping and rendering services
 class MG_SERVER_MAPPING_API MgStylizationUtil
 {
 public:
 
+    // Class to cache coordinate systems and transforms during processing.  Many layers
+    // will use the same coordinate system so this is an effective way to reduce significant overhead.
+    class TransformCache
+    {
+    public:
+        TransformCache(MgCSTrans* transform, MgCoordinateSystem* coordinateSystem);
+        virtual ~TransformCache();
+        MgCSTrans* GetTransform();
+        MgCoordinateSystem* GetCoordSys();
+        void SetMgTransform(MgCoordinateSystemTransform* mgTransform);
+        MgCoordinateSystemTransform* GetMgTransform();
+        void SetEnvelope(MgEnvelope* extent);
+        MgEnvelope* GetEnvelope();
+
+    private:
+        MgCSTrans* m_xform;
+        Ptr<MgCoordinateSystem> m_coordSys;
+        Ptr<MgCoordinateSystemTransform> m_transform;
+        Ptr<MgEnvelope> m_envelope;
+    };
+
+    typedef std::map<STRING, TransformCache*> TransformCacheMap;
+
     static void StylizeLayers(MgResourceService* svcResource,
                               MgFeatureService* svcFeature,
                               MgDrawingService* svcDrawing,
@@ -57,7 +81,8 @@
                                                  MdfModel::VectorLayerDefinition* vl,
                                                  const wchar_t* overrideFilter,
                                                  MgCoordinateSystem* mapCs,
-                                                 MgCoordinateSystem* layerCs);
+                                                 MgCoordinateSystem* layerCs,
+                                                 TransformCache* cache);
 
     static MgFeatureReader * ExecuteRasterQuery(MgFeatureService* svcFeature,
                                                 RS_Bounds& extent,

Modified: trunk/MgDev/Server/src/Services/Resource/RepositoryManager.h
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/RepositoryManager.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/RepositoryManager.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -108,6 +108,9 @@
 
     virtual bool FindResource(MgResourceIdentifier* resource);
 
+    virtual MgResourceContentManager* GetResourceContentManager() = 0;
+    virtual MgResourceHeaderManager* GetResourceHeaderManager() = 0;
+
 protected:
 
     void CreateTransaction();
@@ -115,9 +118,6 @@
     virtual void CommitTransaction();
     void AbortTransaction();
 
-    virtual MgResourceContentManager* GetResourceContentManager() = 0;
-    virtual MgResourceHeaderManager* GetResourceHeaderManager() = 0;
-
     virtual void UpdateDateModifiedResourceSet(CREFSTRING resource) {};
     virtual void UpdateChangedResourceSet(MgResourceIdentifier& resource) {};
 

Modified: trunk/MgDev/Server/src/Services/Resource/ResourceDefinitionManager.h
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/ResourceDefinitionManager.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/ResourceDefinitionManager.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -79,6 +79,11 @@
     bool FindResource(const string& mbResourcePathname);
     bool FindResource(CREFSTRING wcResourcePathname);
 
+    // Resource Permission related methods
+
+    virtual bool CheckPermission(MgResourceIdentifier& resource,
+        CREFSTRING permission, bool strict = true) = 0;
+
 protected:
 
     virtual void ValidateDocument(MgResourceIdentifier& resource,
@@ -107,10 +112,6 @@
     void DeleteDocument(XmlDocument& xmlDoc,
         XmlUpdateContext& updateContext);
 
-    // Resource Permission related methods
-
-    virtual bool CheckPermission(MgResourceIdentifier& resource,
-        CREFSTRING permission, bool strict = true) = 0;
     virtual bool CheckParentPermission(MgResourceIdentifier& resource,
         CREFSTRING permission, bool strict = true) = 0;
 

Modified: trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -2054,6 +2054,46 @@
 
 ///----------------------------------------------------------------------------
 /// <summary>
+/// Checks whether or not the current user has the specified permission on the
+/// specified resource.
+/// </summary>
+///----------------------------------------------------------------------------
+
+bool MgServerResourceService::HasPermission(MgResourceIdentifier* resource, 
+    CREFSTRING permission)
+{
+    bool retVal = false;
+
+    MG_RESOURCE_SERVICE_TRY()
+
+    MG_LOG_TRACE_ENTRY(L"MgServerResourceService::HasPermission()");
+
+    if (NULL == resource)
+    {
+        throw new MgNullArgumentException(
+            L"MgServerResourceService.HasPermission",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    auto_ptr<MgApplicationRepositoryManager> repositoryMan(
+        CreateApplicationRepositoryManager(resource));
+    MgResourceContentManager* resourceContentMan = 
+        repositoryMan->GetResourceContentManager();
+    ACE_ASSERT(NULL != resourceContentMan);
+
+    MG_RESOURCE_SERVICE_BEGIN_OPERATION(false)
+
+    retVal = resourceContentMan->CheckPermission(*resource, permission);
+
+    MG_RESOURCE_SERVICE_END_OPERATION(sm_maxOpRetries)
+
+    MG_RESOURCE_SERVICE_CATCH_AND_THROW(L"MgServerResourceService.HasPermission")
+
+    return retVal;
+}
+
+///----------------------------------------------------------------------------
+/// <summary>
 /// Performs checkpoints for all the repositories.
 /// </summary>
 ///----------------------------------------------------------------------------

Modified: trunk/MgDev/Server/src/Services/Resource/ServerResourceService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/ServerResourceService.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/ServerResourceService.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -156,6 +156,8 @@
     // Resource Permission related methods
 
     MgPermissionCache* CreatePermissionCache();
+    virtual bool HasPermission(MgResourceIdentifier* resource, 
+        CREFSTRING permission);
 
     // Other internal methods
 

Modified: trunk/MgDev/Server/src/Services/Resource/SessionRepositoryManager.h
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/SessionRepositoryManager.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/SessionRepositoryManager.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -47,11 +47,11 @@
 
         virtual MgByteReader* EnumerateRepositories();
         virtual void DeleteRepository(MgResourceIdentifier* resource);
+         virtual MgResourceHeaderManager* GetResourceHeaderManager();
 
     protected:
 
         virtual MgResourceContentManager* GetResourceContentManager();
-        virtual MgResourceHeaderManager* GetResourceHeaderManager();
 
 /// Data Members
 

Modified: trunk/MgDev/Server/src/Services/Resource/SystemRepositoryManager.h
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/SystemRepositoryManager.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Resource/SystemRepositoryManager.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -47,9 +47,10 @@
         virtual MgByteReader* GetResourceContent(
             MgResourceIdentifier* resource, CREFSTRING preProcessTags);
 
+        virtual MgResourceHeaderManager* GetResourceHeaderManager();
+
     protected:
 
-        virtual MgResourceHeaderManager* GetResourceHeaderManager();
 
 /// Data Members
 

Modified: trunk/MgDev/Server/src/Services/Tile/OpGetTile.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/OpGetTile.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/OpGetTile.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -46,7 +46,7 @@
 
     ACE_ASSERT(m_stream != NULL);
 
-    if (4 == m_packet.m_NumArguments)
+    if (4 == m_packet.m_NumArguments && m_packet.m_OperationVersion == 1 )
     {
         Ptr<MgMap> map = (MgMap*)m_stream->GetObject();
         map->SetDelayedLoadResourceService(m_resourceService);
@@ -80,6 +80,44 @@
         
         EndExecution(byteReader);
     }
+    else if (5 == m_packet.m_NumArguments && m_packet.m_OperationVersion == 2 )
+    {
+        Ptr<MgResourceIdentifier> mapDefinition = (MgResourceIdentifier*)m_stream->GetObject();
+
+        STRING baseMapLayerGroupName;
+        m_stream->GetString(baseMapLayerGroupName);
+
+        INT32 tileCol = 0;
+        m_stream->GetInt32(tileCol);
+
+        INT32 tileRow = 0;
+        m_stream->GetInt32(tileRow);
+
+        INT32 scale = 0;
+        m_stream->GetInt32(scale);
+
+        BeginExecution();
+
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"MgResourceIdentifier");
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(baseMapLayerGroupName.c_str());
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"tileCol");
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_STRING(L"tileRow");
+        MG_LOG_OPERATION_MESSAGE_ADD_SEPARATOR();
+        MG_LOG_OPERATION_MESSAGE_ADD_DOUBLE(scale);
+        MG_LOG_OPERATION_MESSAGE_PARAMETERS_END();
+
+        Validate();
+
+        Ptr<MgByteReader> byteReader =
+            m_service->GetTile(mapDefinition, baseMapLayerGroupName, tileCol, tileRow, scale);
+
+        
+        EndExecution(byteReader);
+    }
     else
     {
         MG_LOG_OPERATION_MESSAGE_PARAMETERS_START();

Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -20,8 +20,29 @@
 
 IMPLEMENT_CREATE_SERVICE(MgServerTileService)
 
+ACE_Recursive_Thread_Mutex MgServerTileService::sm_mutex;
+MgServerTileService::MapCache MgServerTileService::sm_mapCache;
+INT32 MgServerTileService::sm_mapCacheSize = -1;
+bool MgServerTileService::sm_renderOnly = false;
+
 MgServerTileService::MgServerTileService() : MgTileService()
 {
+    if (sm_mapCacheSize < 0)
+    {
+        // initialize the tile cache size
+        MgConfiguration* pConf = MgConfiguration::GetInstance();
+
+        pConf->GetIntValue(MgConfigProperties::TileServicePropertiesSection,
+            MgConfigProperties::TileServicePropertyTiledMapCacheSize,
+            sm_mapCacheSize,
+            MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize);
+
+        pConf->GetBoolValue(MgConfigProperties::TileServicePropertiesSection,
+            MgConfigProperties::TileServicePropertyRenderOnly,
+            sm_renderOnly,
+            MgConfigProperties::DefaultTileServicePropertyRenderOnly);
+    }
+
     m_tileCache = new MgTileCache();
 }
 
@@ -30,7 +51,102 @@
 {
 }
 
+MgByteReader* MgServerTileService::GetTile(
+    MgResourceIdentifier* mapDefinition,
+    CREFSTRING baseMapLayerGroupName,
+    INT32 tileColumn,
+    INT32 tileRow,
+    INT32 scaleIndex)
+{
+    Ptr<MgByteReader> ret;
 
+    MG_TRY()
+
+    if (NULL == mapDefinition || baseMapLayerGroupName.empty())
+    {
+        throw new MgNullArgumentException(
+            L"MgServerTileService.GetTile", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    MgServiceManager* serviceMan = MgServiceManager::GetInstance();
+    assert(NULL != serviceMan);
+
+    // Get the service from service manager
+    Ptr<MgResourceService> resourceService = dynamic_cast<MgResourceService*>(
+        serviceMan->RequestService(MgServiceType::ResourceService));
+    assert(resourceService != NULL);
+
+    bool bAllowed = resourceService->HasPermission(mapDefinition, MgResourcePermission::ReadOnly);
+
+    if (!bAllowed)
+    {
+        MG_LOG_AUTHENTICATION_ENTRY(MgResources::PermissionDenied.c_str());
+
+        MgStringCollection arguments;
+        arguments.Add(mapDefinition->ToString());
+
+        throw new MgPermissionDeniedException(
+            L"MgServerTileService.GetTile",
+            __LINE__, __WFILE__, &arguments, L"", NULL);
+    }
+    
+    ret = m_tileCache->Get(mapDefinition, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+
+    if (!ret)
+    {
+
+        // Attempt use a cached & serialized MgMap object
+        Ptr<MgMemoryStreamHelper> cachedMap;
+
+        STRING mapString = mapDefinition->ToString();
+
+        Ptr<MgMap> map;
+
+        // Protect the serialized MgMap cache with a mutex.  Stream reading is not
+        // thread safe so we need to deserialize the map within the mutex to ensure
+        // that a Rewind() is not called in the middle of a Deserialize()
+        {
+            ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
+            MapCache::const_iterator iter = sm_mapCache.find(mapString);
+            if (sm_mapCache.end() != iter)
+            {
+                cachedMap = SAFE_ADDREF((*iter).second);
+            }
+            else
+            {
+                map = new MgMap();
+                map->Create(resourceService, mapDefinition, mapString);
+                cachedMap = new MgMemoryStreamHelper();
+                Ptr<MgStream> stream = new MgStream(cachedMap);
+                map->Serialize(stream);
+                if (sm_mapCache.size() > sm_mapCacheSize)
+                {
+                    ClearMapCache(L"");
+                }
+                sm_mapCache[mapString] = SAFE_ADDREF((MgMemoryStreamHelper*)cachedMap);
+            }
+
+
+            if (!map)
+            {
+                cachedMap->Rewind();
+                Ptr<MgStream> stream = new MgStream(cachedMap);
+                map = new MgMap();
+                map->Deserialize(stream);
+            }
+        }
+
+        double scale = map->GetFiniteDisplayScaleAt(scaleIndex);
+        map->SetViewScale(scale);
+        ret = GetTile(map, baseMapLayerGroupName, tileColumn, tileRow);
+    }
+
+    MG_CATCH_AND_THROW(L"MgServerTileService.GetTile")
+
+    return ret.Detach();
+}
+
+
 MgByteReader* MgServerTileService::GetTile(MgMap* map,
                                            CREFSTRING baseMapLayerGroupName,
                                            INT32 tileColumn,
@@ -70,11 +186,14 @@
             ret = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow);
 
             // cache the tile
-            SetTile(ret, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+            if (!sm_renderOnly)
+            {
+                SetTile(ret, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
 
-            // rewind the reader since setting the tile advances it to the end
-            if (ret)
-                ret->Rewind();
+                // rewind the reader since setting the tile advances it to the end
+                if (ret)
+                    ret->Rewind();
+            }
         }
     }
 
@@ -123,6 +242,9 @@
     if (NULL == map)
         throw new MgNullArgumentException(L"MgServerTileService.ClearCache", __LINE__, __WFILE__, NULL, L"", NULL);
 
+    Ptr<MgResourceIdentifier> resourceId = map->GetMapDefinition();
+    ClearMapCache(resourceId->ToString());
+
     m_tileCache->Clear(map);
 
     MG_CATCH_AND_THROW(L"MgServerTileService.ClearCache")
@@ -157,6 +279,9 @@
 
             if (mapResId->IsResourceTypeOf(MgResourceType::MapDefinition))
             {
+                // clear any cached mgmap objects
+                ClearMapCache(mapResId->ToString());
+
                 // clear any tile cache associated with this map
                 m_tileCache->Clear(mapResId);
             }
@@ -170,3 +295,28 @@
 {
     // Do nothing.  No connection properties are required for Server-side service objects.
 }
+
+void MgServerTileService::ClearMapCache(CREFSTRING mapDefinition)
+{
+    ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+    MapCache::iterator iter = sm_mapCache.end();
+    if (mapDefinition.empty())
+    {
+        for (iter = sm_mapCache.begin(); iter != sm_mapCache.end(); ++iter)
+        {
+            SAFE_RELEASE((*iter).second);
+            (*iter).second = NULL;
+        }
+        sm_mapCache.clear();
+    }
+    else
+    {
+        iter = sm_mapCache.find(mapDefinition);
+        if (sm_mapCache.end() != iter)
+        {
+            SAFE_RELEASE((*iter).second);
+            (*iter).second = NULL;
+            sm_mapCache.erase(iter);
+        }
+    }
+}

Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -35,6 +35,12 @@
                                   INT32 tileColumn,
                                   INT32 tileRow);
 
+    virtual MgByteReader* GetTile(MgResourceIdentifier* mapDefinition,
+                                  CREFSTRING baseMapLayerGroupName,
+                                  INT32 tileColumn,
+                                  INT32 tileRow,
+                                  INT32 scaleIndex);
+
     virtual void SetTile(MgByteReader* img,
                          MgMap* map,
                          INT32 scaleIndex,
@@ -50,8 +56,17 @@
 
 private:
 
+    void ClearMapCache(CREFSTRING mapName);
+
     // member data
     Ptr<MgTileCache> m_tileCache;
+
+    typedef std::map<STRING, MgMemoryStreamHelper*> MapCache;
+    static MapCache sm_mapCache;
+    static ACE_Recursive_Thread_Mutex sm_mutex;
+    static INT32 sm_mapCacheSize;
+    static bool sm_renderOnly;
+
 };
 
 #endif

Modified: trunk/MgDev/Server/src/Services/Tile/TileCache.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileCache.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/TileCache.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -20,23 +20,30 @@
 
 #define PATH_LEN 512
 
+STRING MgTileCache::m_path = L"";
+
 // default constructor
 MgTileCache::MgTileCache()
 {
-    // initialize the tile cache path
-    MgConfiguration* pConf = MgConfiguration::GetInstance();
+    //TODO: It is possible to get a double write on m_path here.  We need
+    //to investigate general mutex use in this class.
+    if (m_path.empty())
+    {
+        // initialize the tile cache path
+        MgConfiguration* pConf = MgConfiguration::GetInstance();
 
-    pConf->GetStringValue(MgConfigProperties::TileServicePropertiesSection,
-                          MgConfigProperties::TileServicePropertyTileCachePath,
-                          m_path,
-                          MgConfigProperties::DefaultTileServicePropertyTileCachePath);
+        pConf->GetStringValue(MgConfigProperties::TileServicePropertiesSection,
+                              MgConfigProperties::TileServicePropertyTileCachePath,
+                              m_path,
+                              MgConfigProperties::DefaultTileServicePropertyTileCachePath);
 
-    // generate directory location for tile cache
-    MgFileUtil::AppendSlashToEndOfPath(m_path);
+        // generate directory location for tile cache
+        MgFileUtil::AppendSlashToEndOfPath(m_path);
 
-    // create directory if it is not already there
-    if (!MgFileUtil::PathnameExists(m_path))
-        MgFileUtil::CreateDirectory(m_path, false);
+        // create directory if it is not already there
+        if (!MgFileUtil::PathnameExists(m_path))
+            MgFileUtil::CreateDirectory(m_path, false);
+    }
 }
 
 
@@ -69,7 +76,35 @@
     return SAFE_ADDREF(ret.p);
 }
 
+MgByteReader* MgTileCache::Get(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group, int i, int j)
+{
+    // acquire a read lock - this blocks if a writer holds the lock
+    ACE_Read_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
 
+    Ptr<MgByteReader> ret;
+
+    if (mapDef != NULL)
+    {
+        STRING tilePath = MgTileCache::GetFullPath(mapDef, scaleIndex, group);
+
+        // generate full path to tile file using <row,column> format
+        // TODO: handle case where path is > PATH_LEN
+        wchar_t tmp[PATH_LEN] = { 0 };
+        swprintf(tmp, PATH_LEN, L"%ls/%d_%d.png", tilePath.c_str(), j, i);
+
+        MG_TRY()
+
+        Ptr<MgByteSource> bs = new MgByteSource(tmp, false);
+        bs->SetMimeType(MgMimeType::Png);
+        ret = bs->GetReader();
+
+        MG_CATCH_AND_RELEASE()
+    }
+
+    return SAFE_ADDREF(ret.p);
+}
+
+
 // caches a tile for the given map / scale index / group / i / j
 void MgTileCache::Set(MgByteReader* img, MgMap* map, int scaleIndex, CREFSTRING group, int i, int j)
 {
@@ -192,7 +227,18 @@
     return STRING(tmp);
 }
 
+// gets the full path to use with the tile cache for the given map / scale index / group
+STRING MgTileCache::GetFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group)
+{
+    STRING basePath = MgTileCache::GetBasePath(mapDef);
 
+    wchar_t tmp[PATH_LEN] = { 0 };
+    swprintf(tmp, PATH_LEN, L"%ls/%d/%ls", basePath.c_str(), scaleIndex, group.c_str());
+
+    return STRING(tmp);
+}
+
+
 STRING MgTileCache::CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group)
 {
     wchar_t tmp[PATH_LEN] = { 0 };

Modified: trunk/MgDev/Server/src/Services/Tile/TileCache.h
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileCache.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/TileCache.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -27,6 +27,7 @@
     MgTileCache();
 
     MgByteReader* Get(MgMap* map, int scaleIndex, CREFSTRING group, int i, int j);
+    MgByteReader* Get(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group, int i, int j);
     void Set(MgByteReader* img, MgMap* map, int scaleIndex, CREFSTRING group, int i, int j);
     void Clear(MgMap* map);
     void Clear(MgResourceIdentifier* resId);
@@ -41,10 +42,14 @@
     STRING GetBasePath(MgMap* map);
     STRING GetBasePath(MgResourceIdentifier* resId);
     STRING GetFullPath(MgMap* map, int scaleIndex, CREFSTRING group);
+    STRING GetFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group);
     STRING CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group);
 
+    // TODO: Investigate this mutex.  It may fail if
+    // we have more than one tile service and could reduce
+    // multi-threaded performance.  File locks would be better.
     ACE_RW_Thread_Mutex m_mutexRW;
-    STRING m_path;
+    static STRING m_path;
 };
 
 #endif

Modified: trunk/MgDev/Server/src/Services/Tile/TileOperationFactory.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileOperationFactory.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Server/src/Services/Tile/TileOperationFactory.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -65,6 +65,7 @@
         switch (operationVersion)
         {
         case 1:
+        case 2:
             handler.reset(new MgOpGetTile());
             break;
         default:

Added: trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/gettileimageform2.html
===================================================================
--- trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/gettileimageform2.html	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/gettileimageform2.html	2007-01-20 00:49:25 UTC (rev 1064)
@@ -0,0 +1,28 @@
+<html>
+    <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <script type="text/javascript" src="setactiontarget.js" >
+    </script>
+    </head>
+    <body>
+        <form name="input" action="" method="get" ID="Form1">
+            <div nowrap="true">
+            <b>Operation:</b> <input type="text" name="OPERATION" value="GETTILEIMAGE" size="50" ID="Text1">
+            <p>
+                Version: <input type="text" name="VERSION" value="2.0.0" size="10" ID="Text2">
+            <p>
+                Map name: <input type="text" name="MAPDEFINITION" value="Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition" size="100" ID="Text4">
+            <p>
+                BaseMapLayerGroup name: <input type="text" name="BASEMAPLAYERGROUPNAME" value="Base Layer Group" size="100" ID="Text5">
+            <p>
+                Tile column index: <input type="text" name="TILECOL" value="10" size="10" ID="Text6">
+                &nbsp &nbsp
+                Tile row index: <input type="text" name="TILEROW" value="10" size="10" ID="Text7">
+            <p>
+                Scale: <input type="text" name="SCALEINDEX" value="1" size="100" ID="Text5">
+            <p>
+                <input type="submit" value="Submit" onclick="SetActionTarget()"> <input type="reset">
+            </div>
+        </form>
+    </body>
+</html>


Property changes on: trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/gettileimageform2.html
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/tileserviceapi.html
===================================================================
--- trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/tileserviceapi.html	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/UnitTest/WebTier/MapAgent/MapAgentForms/tileserviceapi.html	2007-01-20 00:49:25 UTC (rev 1064)
@@ -11,6 +11,8 @@
             <LI>
                 <A href="gettileimageform.html" target="showform">GetTileImage</a></LI>
             <LI>
+                <A href="gettileimageform2.html" target="showform">GetTileImage R2</a></LI>
+            <LI>
                 <A href="cleartilecacheform.html" target="showform">ClearTileCache</a></LI>
         </UL>
         <P>&nbsp;</P>

Modified: trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -36,17 +36,56 @@
 
     Ptr<MgHttpRequestParam> params = hRequest->GetRequestParam();
 
-    // Get the map name
-    m_mapName = params->GetParameterValue(MgHttpResourceStrings::reqRenderingMapName);
+    STRING version = params->GetParameterValue(MgHttpResourceStrings::reqVersion);
 
-    // Get the baseMapLayerGroup name
-    m_baseMapLayerGroupName = params->GetParameterValue(MgHttpResourceStrings::reqRenderingBaseMapLayerGroupName);
+    size_t pos1;
 
-    // Get the tile column index and convert to integer
-    m_tileCol = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileColumn));
+    pos1 = version.find(L".");
+    if (pos1 != string::npos)
+    {
+        m_version = version.substr(0, pos1);
+    }
+    else
+    {
+        m_version = version;
+    }
 
-    // Get the tile row index and convert to integer
-    m_tileRow = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileRow));
+    if (m_version == L"1")
+    {
+        // Get the map name
+        m_mapName = params->GetParameterValue(MgHttpResourceStrings::reqRenderingMapName);
+
+        // Get the baseMapLayerGroup name
+        m_baseMapLayerGroupName = params->GetParameterValue(MgHttpResourceStrings::reqRenderingBaseMapLayerGroupName);
+
+        // Get the tile column index and convert to integer
+        m_tileCol = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileColumn));
+
+        // Get the tile row index and convert to integer
+        m_tileRow = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileRow));
+    }
+    else if (m_version == L"2")
+    {
+        // Get the map name
+        m_mapName = params->GetParameterValue(MgHttpResourceStrings::reqTileMapDefinition);
+
+        // Get the baseMapLayerGroup name
+        m_baseMapLayerGroupName = params->GetParameterValue(MgHttpResourceStrings::reqRenderingBaseMapLayerGroupName);
+
+        // Get the tile column index and convert to integer
+        m_tileCol = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileColumn));
+
+        // Get the tile row index and convert to integer
+        m_tileRow = MgUtil::StringToInt32(params->GetParameterValue(MgHttpResourceStrings::reqRenderingTileRow));
+
+        // Get the scale and convert to double
+        m_scale = MgUtil::StringToDouble(params->GetParameterValue(MgHttpResourceStrings::reqRenderingScaleIndex));
+    }
+    else
+    {
+        throw new MgInvalidOperationVersionException(
+            L"MgHttpGetTileImage.MgHttpGetTileImage", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
 }
 
 /// <summary>
@@ -75,21 +114,52 @@
             __LINE__, __WFILE__, &arguments, L"MgStringEmpty", NULL);
     }
 
-    // Get Proxy Resource Service instance
-    Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
+    if (m_version == L"1")
+    {
+        // Get Proxy Resource Service instance
+        Ptr<MgResourceService> resourceService = (MgResourceService*)CreateService(MgServiceType::ResourceService);
 
-    // Create MgMap
-    Ptr<MgMap> map = new MgMap();
-    map->Open(resourceService, m_mapName);
+        // Create MgMap
+        Ptr<MgMap> map = new MgMap();
+        map->Open(resourceService, m_mapName);
 
-    // Get Proxy Tile Service instance
-    Ptr<MgTileService> service = (MgTileService*)(CreateService(MgServiceType::TileService));
+        // Get Proxy Tile Service instance
+        Ptr<MgTileService> service = (MgTileService*)(CreateService(MgServiceType::TileService));
 
-    // Call the C++ API
-    Ptr<MgByteReader> tileImage = service->GetTile(map, m_baseMapLayerGroupName, m_tileCol, m_tileRow);
+        // Call the C++ API
+        Ptr<MgByteReader> tileImage = service->GetTile(map, m_baseMapLayerGroupName, m_tileCol, m_tileRow);
 
-    // Set the result
-    hResult->SetResultObject(tileImage, tileImage->GetMimeType());
+        // Set the result
+        hResult->SetResultObject(tileImage, tileImage->GetMimeType());
+    }
+    else
+    {
+        Ptr<MgResourceIdentifier> resId = new MgResourceIdentifier(m_mapName);
 
+        // Get Proxy Tile Service instance
+        Ptr<MgTileService> service = (MgTileService*)(CreateService(MgServiceType::TileService));
+
+        // Call the C++ API
+        Ptr<MgByteReader> tileImage = service->GetTile(resId, m_baseMapLayerGroupName, m_tileCol, m_tileRow, m_scale);
+
+        // Set the result
+        hResult->SetResultObject(tileImage, tileImage->GetMimeType());
+    }
+
     MG_HTTP_HANDLER_CATCH_AND_THROW_EX(L"MgHttpGetTileImage.Execute")
 }
+
+/// <summary>
+/// This method is responsible for checking if
+/// a valid version was given
+/// </summary>
+/// <returns>Returns nothing</returns>
+void MgHttpGetTileImage::ValidateOperationVersion()
+{
+    MG_HTTP_HANDLER_TRY()
+
+    // Operation version validation has been moved to constructor
+   
+    MG_HTTP_HANDLER_CATCH_AND_THROW(L"MgHttpGetTileImage.ValidateOperationVersion");
+}
+

Modified: trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.h
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/HttpHandler/HttpGetTileImage.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -51,11 +51,21 @@
     /// </returns>
     MgRequestClassification GetRequestClassification() { return MgHttpRequestResponseHandler::mrcViewer; }
 
+protected:
+    /// <summary>
+    /// This method is responsible for checking if
+    /// a valid version was given
+    /// </summary>
+    /// <returns>Returns nothing</returns>
+    virtual void ValidateOperationVersion();
+
 private:
     STRING  m_mapName;
     STRING  m_baseMapLayerGroupName;
     INT32   m_tileCol;
     INT32   m_tileRow;
+    STRING  m_version;
+    double  m_scale;
 };
 
 #endif  // _FS_GET_TILE_IMAGE_H

Modified: trunk/MgDev/Web/src/HttpHandler/HttpRequestResponseHandler.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpRequestResponseHandler.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/HttpHandler/HttpRequestResponseHandler.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -126,7 +126,7 @@
         m_userInfo->SetClientIp(clientIp);
     }
 
-    // And create the site connection, pushing user information into thread local storage
+    // And create the site connection
     m_siteConn = new MgSiteConnection();
     m_siteConn->Open(m_userInfo);
 

Modified: trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.cpp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -227,6 +227,7 @@
 const STRING MgHttpResourceStrings::reqRenderingTileColumn = L"TILECOL";
 const STRING MgHttpResourceStrings::reqRenderingTileRow = L"TILEROW";
 const STRING MgHttpResourceStrings::reqRenderingPersist = L"PERSIST";
+const STRING MgHttpResourceStrings::reqRenderingScaleIndex = L"SCALEINDEX";
 
 // Rendering Service Operation Requests
 const STRING MgHttpResourceStrings::opGetDynamicMapOverlayImage = L"GETDYNAMICMAPOVERLAYIMAGE";

Modified: trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h
===================================================================
--- trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/HttpHandler/HttpResourceStrings.h	2007-01-20 00:49:25 UTC (rev 1064)
@@ -165,6 +165,7 @@
     static const STRING reqRenderingTileColumn;
     static const STRING reqRenderingTileRow;
     static const STRING reqRenderingPersist;
+    static const STRING reqRenderingScaleIndex;
 
     // PREDEFINED TILE REQUEST PARAMETERS
     static const STRING reqTileMapDefinition;

Modified: trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp
===================================================================
--- trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp	2007-01-20 00:49:25 UTC (rev 1064)
@@ -149,6 +149,7 @@
         String vpath = GetSurroundVirtualPath(request);
         String vals[] = { GetRootVirtualFolder(request) + "/mapagent/mapagent.fcgi",
                     mapName,
+                    mapDefinition,
                     String.valueOf(infoWidth),
                     showLegend != 0 ? "true": "false",
                     showProperties != 0 ? "true": "false",

Modified: trunk/MgDev/Web/src/mapviewernet/mapframe.aspx
===================================================================
--- trunk/MgDev/Web/src/mapviewernet/mapframe.aspx	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/mapviewernet/mapframe.aspx	2007-01-20 00:49:25 UTC (rev 1064)
@@ -152,6 +152,7 @@
             String vpath = GetSurroundVirtualPath(Request);
             String[] vals = { GetRootVirtualFolder(Request) + "/mapagent/mapagent.fcgi",
                         mapName,
+                        mapDefinition,
                         IntToString(infoWidth),
                         showLegend != 0 ? "true": "false",
                         showProperties != 0 ? "true": "false",

Modified: trunk/MgDev/Web/src/mapviewerphp/mapframe.php
===================================================================
--- trunk/MgDev/Web/src/mapviewerphp/mapframe.php	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/mapviewerphp/mapframe.php	2007-01-20 00:49:25 UTC (rev 1064)
@@ -121,6 +121,7 @@
         printf ($templ,
                     GetRootVirtualFolder() . "/mapagent/mapagent.fcgi",
                     $mapName,
+                    $mapDefinition,
                     $infoWidth,
                     $showLegend?"true":"false",
                     $showProperties?"true":"false",

Modified: trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ
===================================================================
--- trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ	2007-01-19 19:08:41 UTC (rev 1063)
+++ trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ	2007-01-20 00:49:25 UTC (rev 1064)
@@ -254,6 +254,7 @@
 var minInfoWidth;
 var webAgent = '%s';
 var mapName = '%s';
+var mapDefinitionName = '%s';
 var infoWidth = %s;
 var isLegend = %s, legendExpanded = isLegend;
 var isProperties = %s, propExpanded = isProperties;
@@ -3065,7 +3066,7 @@
         if(cell.loaded == "1")
             return 0;
         cell.loaded = "1";
-        url = webAgent + "?OPERATION=GETTILEIMAGE&VERSION=1.0.0&SESSION=" + sessionId + "&MAPNAME=" + encodeComponent(mapName) + "&BASEMAPLAYERGROUPNAME=" + encodeComponent(baseGroups[k]) + "&TILECOL=" + tilex + "&TILEROW=" + tiley + "&SC=" + sci;
+        url = webAgent + "?OPERATION=GETTILEIMAGE&VERSION=2.0.0&SESSION=" + sessionId + "&MAPDEFINITION=" + encodeComponent(mapDefinitionName) + "&BASEMAPLAYERGROUPNAME=" + encodeComponent(baseGroups[k]) + "&TILECOL=" + tilex + "&TILEROW=" + tiley + "&SCALEINDEX=" + sci;
         tag = '<img id="' + (imgId) + '" width=' + TILECX + ' height=' + TILECY + ' border=0 vspace=0 hspace=0 src="' + url + '" style="visibility: hidden; width: 300px; height: 300px;" onload="OnTileLoaded(\'' + imgId + '\')">';
         imgId ++;
         cell.innerHTML = tag;



More information about the mapguide-commits mailing list