[mapguide-commits] r10256 - in branches/4.0/MgDev: Common/Renderers Common/Stylization Server/src/UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Mon Nov 2 21:32:44 PST 2026
Author: jng
Date: 2026-11-02 21:32:43 -0800 (Mon, 02 Nov 2026)
New Revision: 10256
Modified:
branches/4.0/MgDev/Common/Renderers/KmlRenderer.cpp
branches/4.0/MgDev/Common/Renderers/KmlRenderer.h
branches/4.0/MgDev/Common/Stylization/Renderer.h
branches/4.0/MgDev/Common/Stylization/StylizationEngine.cpp
branches/4.0/MgDev/Common/Stylization/StylizationEngine.h
branches/4.0/MgDev/Server/src/UnitTesting/TestKmlService.cpp
branches/4.0/MgDev/Server/src/UnitTesting/TestServiceFactory.cpp
Log:
Fix excessive KML placemarks being rendered under composite symbolization. Fixes #2488
Modified: branches/4.0/MgDev/Common/Renderers/KmlRenderer.cpp
===================================================================
--- branches/4.0/MgDev/Common/Renderers/KmlRenderer.cpp 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Common/Renderers/KmlRenderer.cpp 2026-11-03 05:32:43 UTC (rev 10256)
@@ -39,7 +39,7 @@
m_mainContent(kmlContent),
m_kmlContent(kmlContent),
m_styleContent(NULL),
- m_featureCount(0),
+ m_placemarkOpen(false),
m_mapInfo(NULL),
m_layerInfo(NULL),
m_featureClassInfo(NULL),
@@ -72,7 +72,7 @@
double /*metersPerUnit*/,
CSysTransformer* /*xformToLL*/)
{
- m_featureCount = 0;
+ m_placemarkOpen = false;
// remember the map info
m_mapInfo = mapInfo;
@@ -89,7 +89,7 @@
void KmlRenderer::StartLayer(RS_LayerUIInfo* layerInfo,
RS_FeatureClassInfo* classInfo)
{
- m_featureCount = 0;
+ m_placemarkOpen = false;
m_layerInfo = layerInfo;
m_featureClassInfo = classInfo;
ClearThemes();
@@ -100,11 +100,7 @@
void KmlRenderer::EndLayer()
{
//close the very last feature
- if (m_featureCount > 0)
- {
- //end last feature
- EndPlacemark();
- }
+ EndPlacemark();
m_kmlContent = m_mainContent;
//write out the features for each theme
@@ -128,6 +124,9 @@
void KmlRenderer::EndPlacemark()
{
+ if (!m_placemarkOpen)
+ return;
+
//a placemark has one name at most, and an empty one shows as a blank entry
//next to the real name in Google Earth, so only write it when there is one
if (!m_placemarkName.empty())
@@ -138,11 +137,12 @@
m_placemarkName.clear();
}
m_kmlContent->WriteString("</Placemark>");
+ m_placemarkOpen = false;
}
void KmlRenderer::StartFeature(RS_FeatureReader* /*feature*/,
- bool /*initialPass*/,
+ bool initialPass,
const RS_String* tooltip,
const RS_String* url,
const RS_String* theme,
@@ -150,56 +150,64 @@
double zExtrusion,
RS_ElevationType zOffsetType)
{
- if (m_featureCount > 0)
+ KmlContent* content = m_mainContent;
+ if (theme != NULL && !theme->empty())
{
- //end last feature
- EndPlacemark();
- }
- if (theme == NULL || theme->empty())
- {
- m_kmlContent = m_mainContent;
- }
- else
- {
ThemeMap::iterator iter = m_themeMap.find(*theme);
if (iter != m_themeMap.end())
{
- m_kmlContent = (*iter).second;
+ content = (*iter).second;
}
else
{
- m_kmlContent = new KmlContent();
- m_themeMap[*theme] = m_kmlContent;
+ content = new KmlContent();
+ m_themeMap[*theme] = content;
}
}
- m_placemarkName.clear();
- m_kmlContent->WriteString("<Placemark>");
- if ((tooltip != NULL && tooltip->length() > 0) ||
- (url != NULL && url->length() > 0))
+
+ //a feature is stylized once per composite type style, so this is called once
+ //per style of the same feature and only the first of those passes is the
+ //initial one. The placemark belongs to the feature, not to the style pass, so
+ //the remaining passes add to the placemark the initial pass opened. A pass
+ //that moves the feature to another theme cannot continue it, because a
+ //placemark cannot span the folders the themes are written into.
+ if (m_placemarkOpen && (initialPass || content != m_kmlContent))
{
- m_kmlContent->WriteString("<description>");
- m_kmlContent->WriteString("<![CDATA[", false);
- if (tooltip != NULL && tooltip->length() > 0)
+ EndPlacemark();
+ }
+ m_kmlContent = content;
+
+ if (!m_placemarkOpen)
+ {
+ m_placemarkName.clear();
+ m_kmlContent->WriteString("<Placemark>");
+ m_placemarkOpen = true;
+ if ((tooltip != NULL && tooltip->length() > 0) ||
+ (url != NULL && url->length() > 0))
{
- //replace line breaks
- RS_String newTT(*tooltip);
- RS_String::size_type lb = newTT.find(L"\\n");
- while (lb != RS_String::npos)
+ m_kmlContent->WriteString("<description>");
+ m_kmlContent->WriteString("<![CDATA[", false);
+ if (tooltip != NULL && tooltip->length() > 0)
{
- newTT = newTT.replace(lb, 2, L"<br/>");
- lb = newTT.find(L"\\n", lb);
+ //replace line breaks
+ RS_String newTT(*tooltip);
+ RS_String::size_type lb = newTT.find(L"\\n");
+ while (lb != RS_String::npos)
+ {
+ newTT = newTT.replace(lb, 2, L"<br/>");
+ lb = newTT.find(L"\\n", lb);
+ }
+ m_kmlContent->WriteString(newTT, false);
+ m_kmlContent->WriteString("<br/>", false);
}
- m_kmlContent->WriteString(newTT, false);
- m_kmlContent->WriteString("<br/>", false);
+ if (url != NULL && url->length() > 0)
+ {
+ m_kmlContent->WriteString(*url, false);
+ }
+ m_kmlContent->WriteString("]]>");
+ m_kmlContent->WriteString("</description>");
}
- if (url != NULL && url->length() > 0)
- {
- m_kmlContent->WriteString(*url, false);
- }
- m_kmlContent->WriteString("]]>");
- m_kmlContent->WriteString("</description>");
}
- m_featureCount++;
// Elevation / Extrusion settings
m_elevation = zExtrusion + zOffset;
@@ -507,6 +515,16 @@
}
+bool KmlRenderer::RequiresCompositeLineStyleSeparation()
+{
+ //separating a rule's line styles into one styling pass each is what the
+ //screen renderers need, but it would draw a feature more than once and so
+ //give it a placemark per pass - a placemark holds all of a rule's line
+ //styles, so they can be stylized together (ticket #2488)
+ return false;
+}
+
+
bool KmlRenderer::SupportsZ()
{
// although KmlRenderer supports elevation, it ignores Z values
Modified: branches/4.0/MgDev/Common/Renderers/KmlRenderer.h
===================================================================
--- branches/4.0/MgDev/Common/Renderers/KmlRenderer.h 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Common/Renderers/KmlRenderer.h 2026-11-03 05:32:43 UTC (rev 10256)
@@ -120,6 +120,8 @@
virtual bool RequiresLabelClipping();
+ virtual bool RequiresCompositeLineStyleSeparation();
+
virtual bool SupportsZ();
////////////////////////////////////////////////
@@ -183,7 +185,9 @@
KmlContent* m_kmlContent;
KmlContent* m_mainContent;
KmlContent* m_styleContent;
- int m_featureCount;
+ // true while a <Placemark> has been written and not yet closed. A feature's
+ // style passes share the placemark its initial pass opened.
+ bool m_placemarkOpen;
RS_MapUIInfo* m_mapInfo;
RS_LayerUIInfo* m_layerInfo;
RS_FeatureClassInfo* m_featureClassInfo;
Modified: branches/4.0/MgDev/Common/Stylization/Renderer.h
===================================================================
--- branches/4.0/MgDev/Common/Stylization/Renderer.h 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Common/Stylization/Renderer.h 2026-11-03 05:32:43 UTC (rev 10256)
@@ -76,7 +76,11 @@
///<summary>
/// Indicates the renderer should process all subsequent geometry
- /// as part of a single logical feature.
+ /// as part of a single logical feature. When a feature is stylized by
+ /// several composite type styles, this is called once per style and
+ /// initialPass is true only for the first of those calls, which is
+ /// where a renderer that groups a feature's output (the KML
+ /// placemark, for example) opens its group.
///</summary>
virtual void StartFeature(RS_FeatureReader* feature,
bool initialPass,
Modified: branches/4.0/MgDev/Common/Stylization/StylizationEngine.cpp
===================================================================
--- branches/4.0/MgDev/Common/Stylization/StylizationEngine.cpp 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Common/Stylization/StylizationEngine.cpp 2026-11-03 05:32:43 UTC (rev 10256)
@@ -166,12 +166,20 @@
}
// stylize once for each composite type style
+ bool featureStarted = false;
for (size_t i=0; i<numTypeStyles; ++i)
{
- bool initialPass = (i == 0 && instanceRenderingPass == 0 && symbolRenderingPass == 0);
- Stylize(reader, exec, lb, compTypeStyles[i], &seTip, &seUrl, NULL,
- initialPass, instanceRenderingPass, symbolRenderingPass,
- nextInstanceRenderingPass, nextSymbolRenderingPass);
+ // The initial pass is the one that opens the feature for the renderer,
+ // which is the first style whose rules match - a style whose rules match
+ // nothing never reaches the renderer at all, and the style passes that
+ // follow the initial one belong to the same feature.
+ bool initialPass = !featureStarted;
+ if (Stylize(reader, exec, lb, compTypeStyles[i], &seTip, &seUrl, NULL,
+ initialPass, instanceRenderingPass, symbolRenderingPass,
+ nextInstanceRenderingPass, nextSymbolRenderingPass))
+ {
+ featureStarted = true;
+ }
}
// free geometry when done stylizing
@@ -751,7 +759,7 @@
}
-void StylizationEngine::Stylize(RS_FeatureReader* reader,
+bool StylizationEngine::Stylize(RS_FeatureReader* reader,
FdoExpressionEngine* exec,
LineBuffer* geometry,
CompositeTypeStyle* style,
@@ -824,8 +832,9 @@
}
}
+ // no rule matches, so the renderer never hears about this feature
if (rule == NULL)
- return;
+ return false;
// we found a valid rule - send a StartFeature notification
RS_String rs_tip, rs_url;
@@ -840,7 +849,7 @@
// up with no symbols - we're done in that case.
std::vector<SE_SymbolInstance*>* symbolInstances = &rule->symbolInstances;
if (symbolInstances->size() == 0)
- return;
+ return true;
double mm2sud = m_serenderer->GetScreenUnitsPerMillimeterDevice();
double mm2suw = m_serenderer->GetScreenUnitsPerMillimeterWorld();
@@ -1103,7 +1112,7 @@
// if the clipped buffer is NULL (completely clipped) just move on to
// the next feature
if (!lbc)
- return;
+ return true;
// otherwise continue processing with the clipped buffer
lb = lbc;
@@ -1250,6 +1259,8 @@
// free clipped line buffer if the geometry was clipped
if (spClipLB.get())
LineBufferPool::FreeLineBuffer(m_pool, spClipLB.release());
+
+ return true;
}
Modified: branches/4.0/MgDev/Common/Stylization/StylizationEngine.h
===================================================================
--- branches/4.0/MgDev/Common/Stylization/StylizationEngine.h 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Common/Stylization/StylizationEngine.h 2026-11-03 05:32:43 UTC (rev 10256)
@@ -78,7 +78,9 @@
int saveHeight);
// Stylizes the current feature on the reader using the supplied composite type style.
- void Stylize(RS_FeatureReader* reader,
+ // Returns true if the renderer was given the feature - the style's rules can match
+ // nothing, in which case no StartFeature() is issued for it.
+ bool Stylize(RS_FeatureReader* reader,
FdoExpressionEngine* exec,
LineBuffer* geometry,
CompositeTypeStyle* style,
Modified: branches/4.0/MgDev/Server/src/UnitTesting/TestKmlService.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/UnitTesting/TestKmlService.cpp 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Server/src/UnitTesting/TestKmlService.cpp 2026-11-03 05:32:43 UTC (rev 10256)
@@ -484,3 +484,220 @@
REQUIRE(CountOccurrences(placemark, "<name>") == 1);
REQUIRE(placemark.find("<name><![CDATA[BlockSymbol]]></name>") != std::string::npos);
}
+
+//////////////////////////////////////////////////////////////////////////////
+// Kml renderer placemark grouping across composite style passes (ticket #2488)
+//
+// StylizationEngine::StylizeVectorLayer() stylizes a feature once per composite
+// type style, so StartFeature() is called several times for the same feature and
+// only the first of those calls is the initial pass. A placemark belongs to the
+// feature, not to the style pass, so all of a feature's style passes have to land
+// in one <Placemark> - otherwise GetFeaturesKml() reports one placemark per style.
+
+namespace
+{
+ // Everything in the KML that is not inside a <Placemark> element
+ std::string GetContentOutsidePlacemarks(const std::string& kml)
+ {
+ static const std::string startTag("<Placemark>");
+ static const std::string endTag("</Placemark>");
+
+ std::string content;
+ std::string::size_type pos = 0;
+ while (true)
+ {
+ std::string::size_type start = kml.find(startTag, pos);
+ std::string::size_type end = (start == std::string::npos)? std::string::npos : kml.find(endTag, start);
+ if (end == std::string::npos)
+ {
+ content.append(kml, pos, std::string::npos);
+ break;
+ }
+ content.append(kml, pos, start - pos);
+ pos = end + endTag.length();
+ }
+ return content;
+ }
+
+ // Renders one point feature, calling StartFeature() once per composite type
+ // style pass, in the order StylizationEngine does it. A feature whose leading
+ // styles match no rule has no call for those styles, so initialPass marks the
+ // first pass it actually reaches the renderer for.
+ //
+ // ProcessMarker() rather than ProcessPolyline() because it is the one the
+ // renderer exports: the geometry adapters reach the other Process* methods
+ // through the vtable, so only ProcessMarker() is linkable from this module
+ // when KmlRenderer lives in its own DLL (the Windows build).
+ void StylizePointFeature(KmlRenderer& renderer,
+ int stylePasses,
+ bool initialPassOnFirst,
+ double y,
+ const RS_String* theme = NULL)
+ {
+ LineBuffer lb(2);
+ lb.MoveTo(-87.70, y);
+
+ RS_MarkerDef mdef;
+
+ for (int pass = 0; pass < stylePasses; ++pass)
+ {
+ renderer.StartFeature(NULL, initialPassOnFirst && pass == 0, NULL, NULL, theme, 0.0, 0.0, RS_ElevationType_RelativeToGround);
+ renderer.ProcessMarker(&lb, mdef, true, NULL);
+ }
+ }
+
+ void StartRailLayer(KmlRenderer& renderer)
+ {
+ RS_UIGraphic graphic(NULL, 0, L"");
+ RS_LayerUIInfo layerInfo(L"Rail", L"Library://UnitTests/Layers/MultiCTS.LayerDefinition",
+ L"", true, true, false, L"", L"", true, true, 0.0, graphic);
+ RS_FeatureClassInfo classInfo(L"Rail", L"Library://UnitTests/Data/Rail.FeatureSource", L"SHPGEOM");
+ renderer.StartLayer(&layerInfo, &classInfo);
+ }
+}
+
+TEST_CASE("KmlCompositeStyleWritesOnePlacemark", "[KmlService]")
+{
+ KmlContent kmlContent;
+ RS_Bounds bounds(-87.8, 43.7, -87.6, 43.8);
+ KmlRenderer renderer(&kmlContent, bounds, 10000.0, 96.0, 1.0, 0);
+ StartRailLayer(renderer);
+
+ // one feature, stylized by three composite type styles
+ StylizePointFeature(renderer, 3, true, 43.75);
+
+ renderer.EndLayer();
+
+ std::string kml = kmlContent.GetString();
+ INFO(kml);
+ std::vector<std::string> placemarks = GetPlacemarks(kml);
+ REQUIRE(placemarks.size() == 1);
+ REQUIRE(CountOccurrences(placemarks.front(), "<Point>") == 3);
+ REQUIRE(GetContentOutsidePlacemarks(kml).find("<coordinates>") == std::string::npos);
+}
+
+TEST_CASE("KmlCompositeStyleKeepsFeaturesApart", "[KmlService]")
+{
+ KmlContent kmlContent;
+ RS_Bounds bounds(-87.8, 43.7, -87.6, 43.8);
+ KmlRenderer renderer(&kmlContent, bounds, 10000.0, 96.0, 1.0, 0);
+ StartRailLayer(renderer);
+
+ // two features, two composite type styles each
+ StylizePointFeature(renderer, 2, true, 43.75);
+ StylizePointFeature(renderer, 2, true, 43.78);
+
+ renderer.EndLayer();
+
+ std::string kml = kmlContent.GetString();
+ INFO(kml);
+ std::vector<std::string> placemarks = GetPlacemarks(kml);
+ REQUIRE(placemarks.size() == 2);
+ for (size_t i = 0; i < placemarks.size(); ++i)
+ {
+ // each feature's style passes stay in its own placemark
+ REQUIRE(CountOccurrences(placemarks[i], "<Point>") == 2);
+ }
+ REQUIRE(GetContentOutsidePlacemarks(kml).find("<coordinates>") == std::string::npos);
+}
+
+TEST_CASE("KmlCompositeStylePlacemarkDoesNotSpanThemes", "[KmlService]")
+{
+ KmlContent kmlContent;
+ RS_Bounds bounds(-87.8, 43.7, -87.6, 43.8);
+ KmlRenderer renderer(&kmlContent, bounds, 10000.0, 96.0, 1.0, 0);
+ StartRailLayer(renderer);
+
+ // a feature whose two composite type styles carry different legend labels:
+ // each theme is written into its own folder, and a placemark cannot be left
+ // open across folders, so the second theme starts a placemark of its own
+ RS_String themeA(L"Single Track");
+ RS_String themeB(L"Dual Track");
+ StylizePointFeature(renderer, 1, true, 43.75, &themeA);
+ StylizePointFeature(renderer, 1, false, 43.75, &themeB);
+
+ renderer.EndLayer();
+
+ std::string kml = kmlContent.GetString();
+ INFO(kml);
+ std::vector<std::string> placemarks = GetPlacemarks(kml);
+ REQUIRE(placemarks.size() == 2);
+ for (size_t i = 0; i < placemarks.size(); ++i)
+ {
+ REQUIRE(CountOccurrences(placemarks[i], "<Point>") == 1);
+ }
+ REQUIRE(GetContentOutsidePlacemarks(kml).find("<coordinates>") == std::string::npos);
+}
+
+TEST_CASE("GetFeaturesKmlCompositeStylePerFeature", "[KmlService]")
+{
+ try
+ {
+ Ptr<MgKmlService> m_svcKml = TestServiceFactory::CreateKmlService();
+ Ptr<MgResourceService> m_svcResource = TestServiceFactory::CreateResourceService();
+
+ Ptr<MgEnvelope> extents = new MgEnvelope(-87.764986990962839, 43.691398128787782,
+ -87.695521510899724, 43.797520000480347);
+ STRING agentUri = L"http://myserver/mapguide/mapagent/mapagent.fcgi";
+ STRING format = L"KML";
+
+ try
+ {
+ // MultiCTS.LayerDefinition carries the Rail features, the same ones
+ // Rail.LayerDefinition draws, but with three composite type styles - so
+ // each feature is stylized three times. The KML must still carry one
+ // placemark per feature, and therefore as many placemarks as the layer
+ // with a single style produces over the same features (ticket #2488).
+ Ptr<MgResourceIdentifier> compositeLdf = new MgResourceIdentifier(L"Library://UnitTests/Layers/MultiCTS.LayerDefinition");
+ Ptr<MgLayer> compositeLayer = new MgLayer(compositeLdf, m_svcResource);
+
+ Ptr<MgResourceIdentifier> lineLdf = new MgResourceIdentifier(L"Library://UnitTests/Layers/Rail.LayerDefinition");
+ Ptr<MgLayer> lineLayer = new MgLayer(lineLdf, m_svcResource);
+
+ Ptr<MgByteReader> compositeReader = m_svcKml->GetFeaturesKml(compositeLayer, extents, 796, 717, 96.0, 0, agentUri, format);
+ Ptr<MgByteReader> lineReader = m_svcKml->GetFeaturesKml(lineLayer, extents, 796, 717, 96.0, 0, agentUri, format);
+
+ // the KML mime type is not one MgByteSink::ToStringUtf8() will read
+ compositeReader->GetByteSource()->SetMimeType(L"text/xml");
+ lineReader->GetByteSource()->SetMimeType(L"text/xml");
+ std::string compositeKml = MgUtil::WideCharToMultiByte(compositeReader->ToString());
+ std::string lineKml = MgUtil::WideCharToMultiByte(lineReader->ToString());
+
+ int compositePlacemarks = CountOccurrences(compositeKml, "<Placemark>");
+ int linePlacemarks = CountOccurrences(lineKml, "<Placemark>");
+
+ INFO(compositeKml);
+ INFO(lineKml);
+ REQUIRE(linePlacemarks > 0);
+ REQUIRE(compositePlacemarks == linePlacemarks);
+ }
+ catch (MgException* e)
+ {
+ if (e->GetExceptionCode() == MgExceptionCodes::MgConnectionFailedException)
+ {
+ SAFE_RELEASE(e);
+ ACE_DEBUG((LM_INFO, ACE_TEXT("\nTestCase_GetFeaturesKmlCompositeStylePerFeature skipped because unable to connect to test server.\n")));
+
+ // We need to update the mapguide server status so that it can be used again because we have used the
+ // same exception class for servers outside the one actually executing this code.
+ MgSiteManager* siteManager = MgSiteManager::GetInstance();
+ Ptr<MgSiteInfo> siteInfo = siteManager->GetSiteInfo(0);
+ siteInfo->SetStatus(MgSiteInfo::Ok);
+ }
+ else
+ {
+ e->Raise();
+ }
+ }
+ }
+ catch(MgException* e)
+ {
+ STRING message = e->GetDetails(TestServiceFactory::TEST_LOCALE);
+ SAFE_RELEASE(e);
+ FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+ catch(...)
+ {
+ throw;
+ }
+}
Modified: branches/4.0/MgDev/Server/src/UnitTesting/TestServiceFactory.cpp
===================================================================
--- branches/4.0/MgDev/Server/src/UnitTesting/TestServiceFactory.cpp 2026-11-03 05:06:46 UTC (rev 10255)
+++ branches/4.0/MgDev/Server/src/UnitTesting/TestServiceFactory.cpp 2026-11-03 05:32:43 UTC (rev 10256)
@@ -465,6 +465,13 @@
Ptr<MgByteReader> ldfrdr3 = ldfsrc3->GetReader();
svcResource->SetResource(ldfres3, ldfrdr3, nullptr);
+ //the features of Rail.LayerDefinition, but with several composite type
+ //styles, so each feature is stylized once per style (ticket #2488)
+ Ptr<MgResourceIdentifier> ldfres4 = new MgResourceIdentifier(L"Library://UnitTests/Layers/MultiCTS.LayerDefinition");
+ Ptr<MgByteSource> ldfsrc4 = new MgByteSource(L"../UnitTestFiles/UT_MultiCTS.ldf", false);
+ Ptr<MgByteReader> ldfrdr4 = ldfsrc4->GetReader();
+ svcResource->SetResource(ldfres4, ldfrdr4, nullptr);
+
//publish the feature sources
Ptr<MgResourceIdentifier> fsres1 = new MgResourceIdentifier(L"Library://UnitTests/Data/HydrographicPolygons.FeatureSource");
Ptr<MgByteSource> fssrc1 = new MgByteSource(L"../UnitTestFiles/UT_HydrographicPolygons.fs", false);
@@ -1735,6 +1742,9 @@
Ptr<MgResourceIdentifier> ldfres3 = new MgResourceIdentifier(L"Library://UnitTests/Layers/Rail.LayerDefinition");
svcResource->DeleteResource(ldfres3);
+ Ptr<MgResourceIdentifier> ldfres4 = new MgResourceIdentifier(L"Library://UnitTests/Layers/MultiCTS.LayerDefinition");
+ svcResource->DeleteResource(ldfres4);
+
//delete the feature sources
Ptr<MgResourceIdentifier> fsres1 = new MgResourceIdentifier(L"Library://UnitTests/Data/HydrographicPolygons.FeatureSource");
svcResource->DeleteResource(fsres1);
More information about the mapguide-commits
mailing list