[mapguide-commits] r4484 - in trunk/MgDev:
Common/MapGuideCommon/MapLayer Common/MapGuideCommon/Resources
Common/MapGuideCommon/Services Common/Renderers
Common/Stylization Server/src/Services/Kml
Server/src/Services/Mapping Server/src/Services/Rendering
Server/src/Services/Tile
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Jan 6 02:59:02 EST 2010
Author: waltweltonlair
Date: 2010-01-06 02:59:00 -0500 (Wed, 06 Jan 2010)
New Revision: 4484
Modified:
trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp
trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.h
trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res
trunk/MgDev/Common/MapGuideCommon/Services/RenderingOptions.cpp
trunk/MgDev/Common/Renderers/AGGImageIO.cpp
trunk/MgDev/Common/Renderers/AGGImageIO.h
trunk/MgDev/Common/Renderers/AGGRenderer.cpp
trunk/MgDev/Common/Renderers/AGGRenderer.h
trunk/MgDev/Common/Stylization/DefaultStylizer.cpp
trunk/MgDev/Common/Stylization/DefaultStylizer.h
trunk/MgDev/Common/Stylization/RendererStyles.h
trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
trunk/MgDev/Server/src/Services/Mapping/MappingUtil.cpp
trunk/MgDev/Server/src/Services/Mapping/MappingUtil.h
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
Log:
This submission merges the RFC60 code changes into the trunk stream.
Modified: trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -19,7 +19,6 @@
#include "MdfModel.h"
#include "SAX2Parser.h"
#include <map>
-#include <vector>
using namespace std;
@@ -35,7 +34,8 @@
MgMap::MgMap()
: MgMapBase(),
m_inSave(false),
- m_unpackedLayersGroups(false)
+ m_unpackedLayersGroups(false),
+ m_colorPalette(NULL) // lazy instantiation
{
}
@@ -46,7 +46,8 @@
MgMap::MgMap(MgSiteConnection* siteConnection)
: MgMapBase(),
m_inSave(false),
- m_unpackedLayersGroups(false)
+ m_unpackedLayersGroups(false),
+ m_colorPalette(NULL) // lazy instantiation
{
if (NULL == siteConnection)
{
@@ -118,6 +119,10 @@
m_mapDefinitionId = SAFE_ADDREF(mapDefinition);
m_name = mapName;
+ // reset the colorlist from our layers (std::list dtor clears the list)
+ delete m_colorPalette;
+ m_colorPalette = NULL; // initialize to empty (lazy as its only used for 8bit color)
+
// generate a unique id for this map
MgUtil::GenerateUuid(m_objectId);
@@ -293,7 +298,7 @@
for(int i = 0; i < layers->GetCount(); i++, displayOrder += LAYER_ZORDER_INCR)
{
MapLayer* layer = (MapLayer*)layers->GetAt(i);
- //create a runtime layer from this layer and add it to the layer collection
+ //create a runtime layer from this layerDefinition and add it to the layer collection
//pull identity properties as a batch process after the layers are created
Ptr<MgResourceIdentifier> layerDefId = new MgResourceIdentifier(layer->GetLayerResourceID());
Ptr<MgLayerBase> rtLayer = new MgLayer(layerDefId, m_resourceService, false, false);
@@ -459,6 +464,10 @@
m_name = mapName;
MgMapBase::Create(mapSRS, mapExtent, mapName);
m_unpackedLayersGroups = true;
+
+ // reset the colorlist from our layers (std::list dtor clears the list)
+ delete m_colorPalette;
+ m_colorPalette = NULL; // initialize to empty (lazy as its only used for 8bit color)
}
@@ -635,6 +644,8 @@
//
MgMap::~MgMap()
{
+ // reset the colorlist from our layers (std::list dtor clears the list)
+ delete m_colorPalette;
}
@@ -1101,3 +1112,41 @@
}
}
}
+
+////////////////////////////////////////////////////////////////////////
+// RFC60 ColorPalette Accessor uses lazy instantiation as it's not used
+// for truecolor tiles. It's used for the map colors collected from the
+// stylization of the visible layers.
+ColorStringList& MgMap::GetColorPalette()
+{
+ if (m_colorPalette == NULL)
+ m_colorPalette = new ColorStringList();
+ else
+ {
+ m_colorPalette->sort();
+ m_colorPalette->unique();
+ }
+ return *m_colorPalette;
+}
+
+////////////////////////////////////////////////////////////////////////
+// RFC60 setter adds list.
+void MgMap::AddColorsToPalette(ColorStringList& newColorPalette)
+{
+ if (NULL == m_colorPalette)
+ GetColorPalette(); // lazy instantiation
+
+ if (!newColorPalette.empty())
+ {
+ ColorStringList::iterator it = newColorPalette.begin();
+ for (; it != newColorPalette.end(); it++)
+ {
+ if (*it != L"") // filter empty strings
+ {
+ // uppercase the colorcodes (FFABDEFF)
+ std::transform((*it).begin(), (*it).end(), (*it).begin(), towupper);
+ m_colorPalette->push_back(*it);
+ }
+ }
+ }
+}
Modified: trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/MapGuideCommon/MapLayer/Map.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -22,22 +22,13 @@
/// \ingroup Maps_and_Layers_Module
/// \{
-/*TSW remove
#include "Foundation.h"
#include <vector>
#include <list>
#include <map>
-#include "LayerBase.h"
-#include "LayerGroup.h"
-#include "LayerCollection.h"
-#include "LayerGroupCollection.h"
-#include "MapCollection.h"
-#include "ObjectChange.h"
-#include "ChangeList.h"
-#include "ReadOnlyLayerCollection.h"
-#include "SelectionBase.h"
-*/
+typedef std::list<const MdfModel::MdfString> ColorStringList;
+
class MgMap;
class MgSiteConnection;
template class MG_MAPGUIDE_API Ptr<MgMap>;
@@ -579,6 +570,13 @@
virtual void OnLayerParentChanged(MgLayerBase* layer, CREFSTRING parentId);
//////////////////////////////////////////////////////////////////
+ /// \brief
+ /// RFC60 ColorPalette accessors
+ ///
+ ColorStringList& GetColorPalette();
+ void AddColorsToPalette(ColorStringList& newColorPalette);
+
+ //////////////////////////////////////////////////////////////////
/// Bulk load identity properties
///
///
@@ -636,6 +634,7 @@
Ptr<MgResourceService> m_resourceService;
bool m_inSave;
bool m_unpackedLayersGroups;
+ ColorStringList* m_colorPalette;
};
/// \}
Modified: trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res 2010-01-06 07:59:00 UTC (rev 4484)
@@ -291,6 +291,7 @@
MgMissingSchema = No schema specified.
MgMissingSrs = No coordinate system specified.
MgNameNotFound = The name was not found.
+MgNoDataFromRenderer = No data from renderer.
MgPropertyValuesEmpty = The property values cannot be empty.
MgReaderIdNotFound = The reader ID was not found.
MgRepositoryAlreadyOpened = The repository is already opened by another process (e.g. If you are running the server interactively as an application from the command line, are you also running the server as a service?).
@@ -309,6 +310,7 @@
MgStringTooLong = The string is too long.
MgTagFieldNotFound = The tag contained no fields.
MgUnableToLockTileFile = Unable to lock the tile file.
+MgUnableToOpenLockFile = Unable to open the tile lock file.
MgUnableToOpenTileFile = Unable to open the tile file.
MgUnsupportedService = The site/resource services cannot be enabled/disabled.
MgUserAndGroupNotEmpty = Both the user and group are not empty.
Modified: trunk/MgDev/Common/MapGuideCommon/Services/RenderingOptions.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/RenderingOptions.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/MapGuideCommon/Services/RenderingOptions.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -35,7 +35,7 @@
/// Selection color, including filling color and boundary color
/// </param>
MgRenderingOptions::MgRenderingOptions(CREFSTRING format, INT32 behavior, MgColor* selectionColor)
-: m_format(format),
+: m_format(MgUtil::ToUpper(format)),
m_behavior(behavior)
{
m_selectionColor = SAFE_ADDREF(selectionColor);
@@ -47,7 +47,7 @@
/// Get the image format
/// </summary>
/// <returns>
-/// The string value
+/// The string value (is in upper case from CTOR)
/// </returns>
STRING MgRenderingOptions::GetImageFormat()
{
Modified: trunk/MgDev/Common/Renderers/AGGImageIO.cpp
===================================================================
--- trunk/MgDev/Common/Renderers/AGGImageIO.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Renderers/AGGImageIO.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -15,6 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+//#define _DEBUG_PNG8
#include "stdafx.h"
#include "RendererStyles.h"
#include "AGGImageIO.h"
@@ -29,9 +30,22 @@
#include "GDUtils.h"
+#include <assert.h>
+
+#ifdef _DEBUG_PNG8
+#define myassert(COND,L,F) if (!(COND)){ printf("(%d) failed assertion in %d %s", GetCurrentThreadId(), L,F); throw new exception(); }
+#else
+#define myassert(COND,L,F) (COND)
+#endif
+
#pragma warning(disable : 4611)
+enum MS_RETURN_VALUE {MS_SUCCESS, MS_FAILURE, MS_DONE};
+// in-memory switch to permit disabling colormapping at runtime
+// (could be in debug ifdefs but will be optimized away in release build anyway)
+static bool s_bUseColorMap = true;
+
struct png_write_context
{
unsigned char* buf;
@@ -653,7 +667,220 @@
}
////////////////////////////////////////////////////////////////////////////////////////
+/******************************************************************************
+ * mapgd.c 7803 2008-07-09 05:17:40Z sdlime
+ * Project: MapServer
+ * Purpose: GD rendering and other GD related functions.
+ * Author: Steve Lime and the MapServer team.
+ ******************************************************************************/
+/// copied from mapserver source tree --------> mapgd.c line 3248 - 3463, UV 25.02.2009
+ // copy src to dst using dst's palette
+ // src must be a truecolor image
+ // dst must be a paletted image
+ // method is to fine tune the caching used to lookup color values in the palette:
+ // -0 is the default method, which allocates cache memory when needed
+ // -1 is a memory conservative method, that uses very little caching but is much slower
+ // -2 is a memory hungry caching method (allocates 32MB on the heap) but is the fastest for large images
+ // see bug #2422 for some benchmark timings of these methods
+ //
+static int ImageCopyForcePaletteGD(gdImagePtr src, gdImagePtr dst, int method)
+{
+#ifdef _DEBUG_PNG8
+ long icfp = GetTickCount(); // for performance evaluation
+#endif
+ int x, y;
+ int w, h;
+ int c, r, g, b,color;
+ if(!src || !dst) return MS_FAILURE;
+ // input images have different sizes
+ if(gdImageSX(src) != gdImageSX(dst) || gdImageSY(src) != gdImageSY(dst)) return MS_FAILURE;
+ if(!gdImageTrueColor(src) || gdImageTrueColor(dst)) return MS_FAILURE; /* 24-bit to 8-bit */
+ w = gdImageSX(src);
+ h = gdImageSY(src);
+ if(method==0) {
+ /*default caching strategy*/
+ unsigned short ***cols=(unsigned short***)calloc(256,sizeof(unsigned short**));
+
+ /*pointer to cache, pointed by red component, indexed by green component*/
+ unsigned short **data=(unsigned short**)calloc(256*256,sizeof(unsigned short*));
+
+ for(r=0;r<256;r++) {
+ /*populate the cache*/
+ cols[r]=&(data[r*256]);
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ c = gdImageGetPixel(src, x, y);
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+
+ if(cols[r][g]==NULL) {
+ /*this is the first time we see this r,g couple.
+ *allocate bytes for the blue component*/
+ cols[r][g]=(unsigned short*)calloc(256,sizeof(unsigned short));
+ }
+
+ if(!cols[r][g][b]) {
+ /*this r,g,b triplet was never seen before
+ * compute its index in the palette and cache the result
+ */
+ color = gdImageColorClosest(dst, r, g, b);
+ dst->pixels[y][x] = color;
+ /*the cache data was calloc'ed to avoid initialization
+ * store 'index+1' so we are sure the test for cols[r][g][b]
+ * returns true, i.e that this color was cached*/
+ cols[r][g][b]=color+1;
+ }
+ else {
+ /*the cache data was calloc'ed to avoid initialization
+ * the cache contains 'index+1' so we must subtract
+ * 1 to get the real color index*/
+ dst->pixels[y][x] = cols[r][g][b]-1;
+ } // if
+ } // for x
+ } // for y
+ } // for r
+ for(r=0;r<256;r++)
+ for(g=0;g<256;g++)
+ if(cols[r][g]) /*only free the row if it was used*/
+ free(cols[r][g]);
+ free(data);
+ free(cols);
+ }
+ else if(method==1) {
+ /*memory conservative method, does not allocate mem on the heap*/
+ int R[10], G[10], B[10], C[10];
+ int i, color, nCache = 0, iCache =0, maxCache=10;
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ c = gdImageGetPixel(src, x, y);
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+ color = -1;
+
+ /* adding a simple cache to keep colors instead of always calling gdImageColorClosest
+ seems to reduce significantly the time passed in this function
+ spcially with large images (bug 2096)*/
+ for (i=0; i<nCache; i++)
+ {
+ if (R[i] == r)
+ {
+ if (G[i] == g && B[i] == b)
+ {
+ color = C[i];
+ break;
+ }
+ }
+ }
+
+ if (color == -1)
+ {
+ color = gdImageColorClosest(dst, r, g, b);
+ R[iCache] = r;
+ G[iCache] = g;
+ B[iCache] = b;
+ C[iCache] = color;
+ nCache++;
+ if (nCache >= maxCache)
+ nCache = maxCache;
+
+ iCache++;
+ if (iCache == maxCache)
+ iCache = 0;
+ }
+
+ gdImageSetPixel(dst, x, y, color);
+ }
+ }
+ }
+ else if(method==2) {
+ /*memory hungry method, fastest for very large images*/
+
+ /*use a cache for every possible r,g,b triplet
+ * this is usually a full 32MB (when short is 2 bytes) */
+ short *cache=(short*)calloc(16777216,sizeof(short));
+
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int index;
+ c = gdImageGetPixel(src, x, y);
+ index=c&0xFFFFFF; /*use r,g,b for the cache index, i.e. remove alpha*/
+ if(!cache[index]) {
+ r = gdTrueColorGetRed(c);
+ g = gdTrueColorGetGreen(c);
+ b = gdTrueColorGetBlue(c);
+ color = gdImageColorClosest(dst, r, g, b);
+ cache[index]=color+1;
+ dst->pixels[y][x] = color;
+ }
+ else
+ dst->pixels[y][x] = cache[index]-1;
+ }
+ }
+ free(cache);
+ }
+#ifdef _DEBUG_PNG8
+ printf("\n(%d) ########################### ImageCopyForcePaletteGD: Time:%6.4f (s)\n", GetCurrentThreadId(), (GetTickCount()-icfp)/1000.0);
+#endif
+
+ if(gdImageTrueColor(dst)) return MS_FAILURE; /* result is not 8-bit */
+ return MS_SUCCESS;
+}
+
+
////////////////////////////////////////////////////////////////////////////////////////
+// helper function to create an empty image with a palette provided in std::list<MgColor>
+// inParam: 24bit image, filename of palette file, imagesixeX, imagesizeY
+// return: 8bit image using given palette if provided ...
+static gdImagePtr CreateGdImageWithPalette(gdImagePtr img24, RS_ColorVector* baseColorPalette, int sx, int sy)
+{
+ myassert(sx > 0 && sy > 0, __LINE__, __WFILE__);
+
+ /// allow empty default parameter
+ int ncolors = baseColorPalette? baseColorPalette->size() : 0;
+
+ // create new empty palette image
+ gdImagePtr gdPPalette = gdImageCreatePalette(sx, sy);
+ myassert(gdPPalette, __LINE__, __WFILE__);
+
+ // if the palette file contains less than 256, fill the rest with colors generated
+ // by gd - those can include the base colors
+ if (ncolors < 256)
+ {
+ gdImagePtr gdPPaletteFromImg24 = gdImageCreatePaletteFromTrueColor(img24, 1, 255-ncolors);
+ myassert(gdPPaletteFromImg24, __LINE__, __WFILE__);
+
+ // copy colors from palette into new empty gdpalette
+ for (int c = 0; c < gdPPaletteFromImg24->colorsTotal; c++)
+ {
+ gdImageColorAllocate(gdPPalette,gdPPaletteFromImg24->red[c],
+ gdPPaletteFromImg24->green[c],
+ gdPPaletteFromImg24->blue[c]);
+ }
+ gdImageDestroy(gdPPaletteFromImg24);
+ }
+#ifdef _DEBUG_PNG8
+ printf("\n(%d) ########################### CreateGdImageWithPalette colors: %d\n", GetCurrentThreadId(), ncolors);
+#endif
+
+ if (baseColorPalette)
+ {
+ // add colors from the colorpalette (duplicate color entries make the used palette less than 256)
+ RS_ColorVector::iterator it;
+ for (it = baseColorPalette->begin();it != baseColorPalette->end(); it++)
+ {
+ gdImageColorAllocate(gdPPalette, (*it).red(), (*it).green(), (*it).blue());
+ }
+ }
+
+ myassert(gdImageTrueColor(gdPPalette) == 0, __LINE__, __WFILE__); // result is not a 8-bit paletted image
+ return gdPPalette; // this is an empty image with the right color palette
+}
+
+
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
@@ -662,8 +889,7 @@
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
-
-
+// create an image using the other Save method and store it at filename
bool AGGImageIO::Save(const RS_String& filename, const RS_String& format,
unsigned int* src, int src_width, int src_height,
int dst_width, int dst_height, RS_Color& bgColor)
@@ -701,9 +927,13 @@
}
+////////////////////////////////////////////////////////////////////////////////////////
+// convert imagebuffer src into the desired format using the provided baseColorPalette for 8bit
+// (the baseColorPalette is a default parameter NULL)
RS_ByteData* AGGImageIO::Save(const RS_String& format,
unsigned int* src, int src_width, int src_height,
- int dst_width, int dst_height, RS_Color& bgColor)
+ int dst_width, int dst_height, RS_Color& bgColor,
+ RS_ColorVector* baseColorPalette)
{
bool drop_alpha = bgColor.alpha() == 255;
@@ -750,76 +980,97 @@
}
else if (format == L"JPG" || format == L"GIF" || format == L"PNG8")
{
- gdImagePtr gdimg = gdImageCreateTrueColor(dst_width, dst_height);
+ // gdimg24 contains the 24bit image
+ gdImagePtr gdimg24 = gdImageCreateTrueColor(dst_width, dst_height);
- int bgc = ConvertColor(gdimg, bgColor);
+ int bgc = ConvertColor(gdimg24, bgColor);
// initialize the destination image to the bg color (temporarily turn
// off alpha blending so the fill has the supplied alpha)
- gdImageAlphaBlending(gdimg, 0);
- gdImageFilledRectangle(gdimg, 0, 0, gdImageSX(gdimg)-1, gdImageSY(gdimg)-1, bgc);
+ gdImageAlphaBlending(gdimg24, 0);
+ gdImageFilledRectangle(gdimg24, 0, 0, gdImageSX(gdimg24)-1, gdImageSY(gdimg24)-1, bgc);
// set any transparent color
if (bgColor.alpha() != 255)
- gdImageColorTransparent(gdimg, bgc);
+ gdImageColorTransparent(gdimg24, bgc);
+ // copy the src data into the gdImage
unsigned int* ptr = src;
for (int j=0; j<dst_height; j++)
{
for(int i=0; i<dst_width; i++)
{
//TODO: can be optimized
-
unsigned int c = *ptr++;
int a = c >> 24;
- int b = (c >> 16) & 0xff;
- int g = (c >> 8) & 0xff;
- int r = c & 0xff;
-
// skip any fully transparent pixels so a transparent
// background color will show through
if (a != 0)
{
- int gdc = gdImageColorAllocateAlpha(gdimg, r, g, b, a);
- gdImageSetPixel(gdimg, i, j, gdc);
+ int b = (c >> 16) & 0xff; // some simple optimization ;-)
+ int g = (c >> 8) & 0xff;
+ int r = c & 0xff;
+
+ int gdc = gdImageColorAllocateAlpha(gdimg24, r, g, b, a);
+ gdImageSetPixel(gdimg24, i, j, gdc);
}
}
}
- gdImageAlphaBlending(gdimg, 1);
+ gdImageAlphaBlending(gdimg24, 1);
// Make output image non-interlaced --- it's a little faster to compress that way.
- gdImageInterlace(gdimg, 0);
+ gdImageInterlace(gdimg24, 0);
// Make sure the alpha values get saved -- but only if required
// it is faster not to save them and makes a smaller PNG
- if (bgColor.alpha() != 255)
- gdImageSaveAlpha(gdimg, 1);
- else
- gdImageSaveAlpha(gdimg, 0);
+ gdImageSaveAlpha(gdimg24, (bgColor.alpha() != 255)? 1 : 0);
- //convert to 256 color paletted image for PNG8, GIF
- if (format == L"GIF" || format == L"PNG8")
- gdImageTrueColorToPalette(gdimg, 0, 256);
+ // convert to 256 color paletted image for PNG8, GIF
+ gdImagePtr gdImgPalette = NULL;
+ if (format == L"GIF" || format == L"PNG8")
+ {
+ /// skip color quantization if no palette given or empty
+ if (baseColorPalette && !baseColorPalette->empty() && s_bUseColorMap) // memory based switch
+ {
+ gdImgPalette = CreateGdImageWithPalette(gdimg24, baseColorPalette,
+ gdImageSX(gdimg24), gdImageSY(gdimg24));
+ myassert(gdImgPalette, __LINE__, __WFILE__);
+ // methods are described above - we use method 1 as default????? TODO what's best???
+ myassert(ImageCopyForcePaletteGD(gdimg24, gdImgPalette, 1) == MS_SUCCESS, __LINE__, __WFILE__);
+
+ // forced palette GD image now in gdimgPalette
+ }
+ else
+ {
+ gdImageTrueColorToPalette(gdimg24, 0, 256); // in place conversion
+ gdImgPalette = gdimg24;
+ }
+ }
+
//get an in-memory image stream
int size = 0;
unsigned char* data = NULL;
if (format == L"GIF") // MgImageFormats::Gif
- data = (unsigned char*)gdImageGifPtr(gdimg, &size);
+ data = (unsigned char*)gdImageGifPtr(gdImgPalette, &size);
+ else if (format == L"PNG8") // MgImageFormats::Png8
+ data = (unsigned char*)gdImagePngPtr(gdImgPalette, &size);
else if (format == L"JPG") // MgImageFormats::Jpeg
- data = (unsigned char*)gdImageJpegPtr(gdimg, &size, 75);
- else if (format == L"PNG8") // MgImageFormats::Png8
- data = (unsigned char*)gdImagePngPtr(gdimg, &size);
+ data = (unsigned char*)gdImageJpegPtr(gdimg24, &size, 75);
std::auto_ptr<RS_ByteData> byteData;
byteData.reset((NULL == data)? NULL : new RS_ByteData(data, size));
gdFree(data);
- //if we allocated a temporary image to stretch-blit, destroy it
- gdImageDestroy(gdimg);
+ if (gdimg24 == gdImgPalette)
+ gdimg24 = NULL; // reset pointer so destructor is not called twice -> exception!!!
+ else //if we allocated a temporary image to stretch-blit, destroy it
+ gdImageDestroy(gdimg24);
+ //if we allocated a paletted image, destroy it (very likely that is)
+ gdImageDestroy(gdImgPalette);
return byteData.release();
}
@@ -830,6 +1081,8 @@
return NULL;
}
+//---------------------------------------------------------------------------
+
//TODO: This routine should be rewritten to use agg to blend PNGs more accurately
void AGGImageIO::Combine(const RS_String& src1, const RS_String& src2, const RS_String& dst)
{
Modified: trunk/MgDev/Common/Renderers/AGGImageIO.h
===================================================================
--- trunk/MgDev/Common/Renderers/AGGImageIO.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Renderers/AGGImageIO.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -26,7 +26,8 @@
static RS_ByteData* Save(const RS_String& format,
unsigned int* src, int src_width, int src_height,
- int dst_width, int dst_height, RS_Color& bgColor);
+ int dst_width, int dst_height, RS_Color& bgColor,
+ RS_ColorVector* baseColorPalette = NULL);
static void Combine(const RS_String& src1, const RS_String& src2, const RS_String& dst);
Modified: trunk/MgDev/Common/Renderers/AGGRenderer.cpp
===================================================================
--- trunk/MgDev/Common/Renderers/AGGRenderer.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Renderers/AGGRenderer.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -96,6 +96,7 @@
bool AGGRenderer::s_bGeneralizeData = false;
+//////////////////////////////////////////////////////////////////////////////
// constructor that allows a backbuffer
AGGRenderer::AGGRenderer(int width,
int height,
@@ -138,6 +139,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
//default constructor
AGGRenderer::AGGRenderer(int width,
int height,
@@ -192,6 +194,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
AGGRenderer::~AGGRenderer()
{
delete m_context;
@@ -203,6 +206,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::UpdateBackBuffer(int width, int height, unsigned int* backbuffer)
{
if (m_bownbuffer)
@@ -219,6 +223,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
unsigned int* AGGRenderer::GetBackBuffer(int &width, int& height)
{
width = m_width;
@@ -227,30 +232,42 @@
}
+//////////////////////////////////////////////////////////////////////////////
+// This one writes into a file not returning a bytestream using
+// default parameters for the width and height.
void AGGRenderer::Save(const RS_String& filename, const RS_String& format)
{
Save(filename, format, m_width, m_height);
}
+//////////////////////////////////////////////////////////////////////////////
+// This one writes into a file not returning a bytestream.
void AGGRenderer::Save(const RS_String& filename, const RS_String& format, int width, int height)
{
AGGImageIO::Save(filename, format, m_rows, m_width, m_height, width, height, m_bgcolor);
}
-RS_ByteData* AGGRenderer::Save(const RS_String& format, int width, int height)
+//////////////////////////////////////////////////////////////////////////////
+// Return the rendered image passed in via the imagebuffer (m_rows) as
+// a bytestream in the given image format using the provided colorPalette
+// if given.
+RS_ByteData* AGGRenderer::Save(const RS_String& format, int width, int height,
+ RS_ColorVector* baseColorPalette)
{
- return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor);
+ return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor, baseColorPalette);
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::Combine(const RS_String& fileIn1, const RS_String& fileIn2, const RS_String& fileOut)
{
AGGImageIO::Combine(fileIn1, fileIn2, fileOut);
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::StartMap(RS_MapUIInfo* mapInfo,
RS_Bounds& extents,
double mapScale,
@@ -308,6 +325,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::EndMap()
{
// turn off selection mode so the labels draw normal
@@ -321,6 +339,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::StartLayer(RS_LayerUIInfo* legendInfo,
RS_FeatureClassInfo* classInfo)
{
@@ -330,6 +349,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::EndLayer()
{
// clear the layer/feature info
@@ -338,6 +358,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::StartFeature(RS_FeatureReader* /*feature*/,
bool /*initialPass*/,
const RS_String* /*tooltip*/,
@@ -350,6 +371,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessPolygon(LineBuffer* lb, RS_FillStyle& fill)
{
_ASSERT(NULL != lb);
@@ -494,6 +516,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessPolyline(LineBuffer* lb, RS_LineStroke& lsym)
{
_ASSERT(NULL != lb);
@@ -603,6 +626,7 @@
printf(" width = %6.4f height = %6.4f\n", ext.width(), ext.height());
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessRaster(unsigned char* data,
int length,
RS_ImageFormat format,
@@ -633,6 +657,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessMarker(LineBuffer* srclb, RS_MarkerDef& mdef, bool allowOverpost, RS_Bounds* bounds)
{
RS_MarkerDef use_mdef = mdef;
@@ -658,6 +683,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessOneMarker(double x, double y, RS_MarkerDef& mdef, bool allowOverpost, RS_Bounds* bounds)
{
RS_InputStream* symbol = NULL;
@@ -1038,6 +1064,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ProcessLabelGroup(RS_LabelInfo* labels,
int nlabels,
const RS_String& text,
@@ -1055,66 +1082,77 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetSymbolManager(RS_SymbolManager* manager)
{
m_symbolManager = manager;
}
+//////////////////////////////////////////////////////////////////////////////
RS_MapUIInfo* AGGRenderer::GetMapInfo()
{
return m_mapInfo;
}
+//////////////////////////////////////////////////////////////////////////////
RS_LayerUIInfo* AGGRenderer::GetLayerInfo()
{
return m_layerInfo;
}
+//////////////////////////////////////////////////////////////////////////////
RS_FeatureClassInfo* AGGRenderer::GetFeatureClassInfo()
{
return m_fcInfo;
}
+//////////////////////////////////////////////////////////////////////////////
double AGGRenderer::GetMapScale()
{
return m_mapScale;
}
+//////////////////////////////////////////////////////////////////////////////
double AGGRenderer::GetDrawingScale()
{
return m_drawingScale;
}
+//////////////////////////////////////////////////////////////////////////////
RS_Bounds& AGGRenderer::GetBounds()
{
return m_extents;
}
+//////////////////////////////////////////////////////////////////////////////
double AGGRenderer::GetDpi()
{
return m_dpi;
}
+//////////////////////////////////////////////////////////////////////////////
double AGGRenderer::GetMetersPerUnit()
{
return m_metersPerUnit;
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::RequiresClipping()
{
return m_bRequiresClipping;
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::RequiresLabelClipping()
{
// always the same value as RequiresClipping
@@ -1122,6 +1160,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::SupportsZ()
{
// Z values in feature geometry are ignored
@@ -1129,6 +1168,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::SupportsTooltips()
{
// set to false to disable processing of tooltips
@@ -1136,6 +1176,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::SupportsHyperlinks()
{
// set to false to disable processing of hyperlinks
@@ -1143,12 +1184,14 @@
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::UseLocalOverposting()
{
return m_bLocalOverposting;
}
+//////////////////////////////////////////////////////////////////////////////
// WARNING: caller responsible for deleting resulting line buffer
LineBuffer* AGGRenderer::ApplyLineStyle(LineBuffer* srcLB, wchar_t* lineStyle, double lineWidthPixels, double drawingScale, double dpi)
{
@@ -1338,10 +1381,9 @@
}
-//-----------------------------------------------------------------------------
+//////////////////////////////////////////////////////////////////////////////
// scale an input number in meters to a mapping
// space number given a device or mapping space unit.
-//-----------------------------------------------------------------------------
double AGGRenderer::_MeterToMapSize(RS_Units unit, double number)
{
double scale_factor;
@@ -1355,12 +1397,14 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetRenderSelectionMode(bool mode)
{
SetRenderSelectionMode(mode, 0x0000FF00);
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetRenderSelectionMode(bool mode, int rgba)
{
SE_Renderer::SetRenderSelectionMode(mode, rgba);
@@ -1382,6 +1426,7 @@
//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawString(const RS_String& s,
double x,
double y,
@@ -1398,6 +1443,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawString(agg_context* cxt,
const RS_String& s,
double x,
@@ -1649,6 +1695,9 @@
// SE_Renderer implementation
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetPolyClip(LineBuffer* polygon, double bufferWidth)
{
c()->bPolyClip = false;
@@ -1757,6 +1806,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Called when applying a line style on a feature geometry. Line styles can
// only be applied to linestring and polygon feature geometry types.
void AGGRenderer::ProcessLine(SE_ApplyContext* ctx, SE_RenderLineStyle* style)
@@ -1789,6 +1839,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Called when applying an area style on a feature geometry. Area styles can
// can only be applied to polygon feature geometry types.
void AGGRenderer::ProcessArea(SE_ApplyContext* ctx, SE_RenderAreaStyle* style)
@@ -1840,6 +1891,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::_TransferPoints(agg_context* c, LineBuffer* srcLB, const SE_Matrix* xform, unsigned int* pathids, bool isPolygon)
{
if (s_bClampPoints)
@@ -1945,6 +1997,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::_TransferPointsClamped(agg_context* c, LineBuffer* srcLB, const SE_Matrix* xform, unsigned int* pathids, bool isPolygon)
{
c->ps.remove_all();
@@ -2089,12 +2142,14 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenPolyline(LineBuffer* srclb, const SE_Matrix* xform, const SE_LineStroke& lineStroke)
{
DrawScreenPolyline(c(), srclb, xform, lineStroke);
}
+//////////////////////////////////////////////////////////////////////////////
// copied from WritePolylines, except it doesn't do to screen transform - we should refactor
void AGGRenderer::DrawScreenPolyline(agg_context* c, LineBuffer* srclb, const SE_Matrix* xform, const SE_LineStroke& lineStroke)
{
@@ -2169,12 +2224,14 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenPolygon(LineBuffer* polygon, const SE_Matrix* xform, unsigned int color)
{
DrawScreenPolygon(c(), polygon, xform, color);
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenPolygon(agg_context* c, LineBuffer* polygon, const SE_Matrix* xform, unsigned int color)
{
if ((color & 0xFF000000) == 0)
@@ -2203,18 +2260,21 @@
}
+//////////////////////////////////////////////////////////////////////////////
bool AGGRenderer::YPointsUp()
{
return true;
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::GetWorldToScreenTransform(SE_Matrix& xform)
{
xform = m_xform;
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetWorldToScreenTransform(SE_Matrix& xform)
{
m_xform = xform;
@@ -2222,18 +2282,21 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::WorldToScreenPoint(double& inx, double& iny, double& ox, double& oy)
{
m_xform.transform(inx, iny, ox, oy);
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::ScreenToWorldPoint(double& inx, double& iny, double& ox, double& oy)
{
m_ixform.transform(inx, iny, ox, oy);
}
+//////////////////////////////////////////////////////////////////////////////
// returns number of pixels per millimeter device
double AGGRenderer::GetScreenUnitsPerMillimeterDevice()
{
@@ -2241,6 +2304,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// returns number of pixels per millimeter world
double AGGRenderer::GetScreenUnitsPerMillimeterWorld()
{
@@ -2248,6 +2312,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// screen units are pixels
double AGGRenderer::GetScreenUnitsPerPixel()
{
@@ -2255,18 +2320,21 @@
}
+//////////////////////////////////////////////////////////////////////////////
RS_FontEngine* AGGRenderer::GetRSFontEngine()
{
return this;
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::AddExclusionRegion(RS_F_Point* fpts, int npts)
{
m_labeler->AddExclusionRegion(fpts, npts);
}
+//////////////////////////////////////////////////////////////////////////////
// labeling - this is the entry API for adding SE labels
// to the label mananger
void AGGRenderer::ProcessSELabelGroup(SE_LabelInfo* labels,
@@ -2284,6 +2352,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenRaster(unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
double x, double y, double w, double h, double angledeg)
@@ -2292,6 +2361,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenRaster(agg_context* cxt, unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
double x, double y, double w, double h, double angledeg)
@@ -2377,6 +2447,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenRasterTransform(agg_context* cxt, unsigned char* data, int length,
RS_ImageFormat format, int native_width, int native_height,
double x, double y, double w, double h,
@@ -2435,6 +2506,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Renders the mesh rectangle defined by the point mappings at the four supplied mesh indices
void AGGRenderer::RenderTransformMeshRectangle(mg_rendering_buffer& src, agg_context* cxt,
RS_ImageFormat format, TransformMesh* transformMesh,
@@ -2458,6 +2530,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Renders the triangle in the source image defined by the three source points into
// the triangle in the supplied context defined by the three destination points.
void AGGRenderer::RenderTransformedTriangle(mg_rendering_buffer& src, agg_context* cxt, RS_ImageFormat format,
@@ -2486,6 +2559,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Renders the source image to the destination context, using the specified
// affine transformation matrix.
void AGGRenderer::RenderWithTransform(mg_rendering_buffer& src, agg_context* cxt,
@@ -2559,6 +2633,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::DrawScreenText(const RS_TextMetrics& tm, RS_TextDef& tdef, double insx, double insy,
RS_F_Point* path, int npts, double param_position)
{
@@ -2595,6 +2670,7 @@
//////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
// Inserts the contents of a given DWF input stream into the current
// output W2D. The given coord sys transformation is applied and geometry
// will be clipped to the RS_Bounds context of the DWFRenderer.
@@ -2720,6 +2796,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::AddW2DContent(RS_InputStream* in, CSysTransformer* xformer, const RS_String& w2dfilter)
{
WT_Result result;
@@ -2761,6 +2838,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::SetActions(WT_File& file)
{
file.set_stream_open_action (agr_open);
@@ -2842,6 +2920,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// Given an array of points in W2D logical coordinates, this function:
// 1. Transforms W2D logical coords into their model space using the
// W2D file's units structure
@@ -2965,6 +3044,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// This function scales a W2D space related value from source W2D space
// to destination. Since the source W2D file can fit into a small piece
// of the destination DWF or be much larger, we need to take that scaling
@@ -2996,6 +3076,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void AGGRenderer::UpdateSymbolTrans(WT_File& /*file*/, WT_Viewport& viewport)
{
_ASSERT(m_xformer);
Modified: trunk/MgDev/Common/Renderers/AGGRenderer.h
===================================================================
--- trunk/MgDev/Common/Renderers/AGGRenderer.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Renderers/AGGRenderer.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -151,7 +151,8 @@
//
RENDERERS_API void Save(const RS_String& filename, const RS_String& format);
RENDERERS_API void Save(const RS_String& filename, const RS_String& format, int width, int height);
- RENDERERS_API RS_ByteData* Save(const RS_String& format, int width, int height);
+ RENDERERS_API RS_ByteData* Save(const RS_String& format, int width, int height,
+ RS_ColorVector* baseColorPalette = NULL);
RENDERERS_API void Combine(const RS_String& fileIn1, const RS_String& fileIn2, const RS_String& fileOut);
RENDERERS_API void SetWorldToScreenTransform(SE_Matrix& xform);
Modified: trunk/MgDev/Common/Stylization/DefaultStylizer.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/DefaultStylizer.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Stylization/DefaultStylizer.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -30,13 +30,16 @@
#include "ExpressionHelper.h"
+//////////////////////////////////////////////////////////////////////////////
DefaultStylizer::DefaultStylizer(SE_SymbolManager* sman)
{
m_pRasterAdapter = NULL;
+ m_symbolmanager = sman;
m_styleEngine = new StylizationEngine(sman, &m_lbPool);
}
+//////////////////////////////////////////////////////////////////////////////
DefaultStylizer::~DefaultStylizer()
{
// free geom adapters -- not strictly needed here but just
@@ -47,6 +50,14 @@
}
+//////////////////////////////////////////////////////////////////////////////
+SE_SymbolManager* DefaultStylizer::GetSymbolManager()
+{
+ return m_symbolmanager;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
void DefaultStylizer::StylizeVectorLayer(MdfModel::VectorLayerDefinition* layer,
Renderer* renderer,
RS_FeatureReader* features,
@@ -218,6 +229,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
int DefaultStylizer::StylizeVLHelper(MdfModel::VectorLayerDefinition* layer,
MdfModel::VectorScaleRange* scaleRange,
Renderer* renderer,
@@ -348,6 +360,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void DefaultStylizer::StylizeGridLayer(MdfModel::GridLayerDefinition* layer,
Renderer* renderer,
RS_FeatureReader* features,
@@ -411,6 +424,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void DefaultStylizer::StylizeDrawingLayer(MdfModel::DrawingLayerDefinition* layer,
Renderer* renderer,
RS_InputStream* dwfin,
@@ -430,6 +444,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
// WARNING: given pointer to the new stylizer will be destroyed
// by the stylizer (in its destructor)
void DefaultStylizer::SetGeometryAdapter(FdoGeometryType type, GeometryAdapter* stylizer)
@@ -443,6 +458,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
GeometryAdapter* DefaultStylizer::FindGeomAdapter(int geomType)
{
GeometryAdapter* adapter = m_hGeomStylizers[geomType];
@@ -492,6 +508,7 @@
}
+//////////////////////////////////////////////////////////////////////////////
void DefaultStylizer::ClearAdapters()
{
std::map<int, GeometryAdapter*>::iterator sgiter = m_hGeomStylizers.begin();
Modified: trunk/MgDev/Common/Stylization/DefaultStylizer.h
===================================================================
--- trunk/MgDev/Common/Stylization/DefaultStylizer.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Stylization/DefaultStylizer.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -25,16 +25,18 @@
class StylizationEngine;
class SE_SymbolManager;
-//-----------------------------------------------------------------------------
+//////////////////////////////////////////////////////////////////////////////
// Stylizer used for all types of layers which do not have special
// Stylizer implementation, which is currently all of them.
-//-----------------------------------------------------------------------------
+//////////////////////////////////////////////////////////////////////////////
class DefaultStylizer : public Stylizer
{
public:
STYLIZATION_API DefaultStylizer(SE_SymbolManager* sman);
STYLIZATION_API virtual ~DefaultStylizer();
+ STYLIZATION_API SE_SymbolManager* GetSymbolManager();
+
STYLIZATION_API virtual void StylizeVectorLayer(MdfModel::VectorLayerDefinition* layer,
Renderer* renderer,
RS_FeatureReader* features,
@@ -80,6 +82,9 @@
//composite stylizer
StylizationEngine* m_styleEngine;
+ // keep a handle on the symbolmanager
+ SE_SymbolManager* m_symbolmanager;
+
SE_BufferPool m_lbPool;
};
Modified: trunk/MgDev/Common/Stylization/RendererStyles.h
===================================================================
--- trunk/MgDev/Common/Stylization/RendererStyles.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Common/Stylization/RendererStyles.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -164,6 +164,7 @@
RS_OEM = 255
};
+
//////////////////////////////////////////////////////////////////////////////
class RS_Color
{
@@ -235,6 +236,11 @@
//////////////////////////////////////////////////////////////////////////////
+/// RFC60 list of colors used for color quantization
+typedef std::vector<RS_Color> RS_ColorVector;
+
+
+//////////////////////////////////////////////////////////////////////////////
class RS_LineStroke
{
public:
Modified: trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Kml/ServerKmlService.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -15,6 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+#include "RendererStyles.h"
#include "MapGuideCommon.h"
#include "ServerKmlService.h"
#include "Services/KmlDefs.h"
Modified: trunk/MgDev/Server/src/Services/Mapping/MappingUtil.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/MappingUtil.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Mapping/MappingUtil.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -17,19 +17,23 @@
#include "MappingUtil.h"
-#include "SAX2Parser.h"
+#include "AGGRenderer.h"
#include "Bounds.h"
+#include "DefaultStylizer.h"
+#include "Fdo.h"
#include "Renderer.h"
-#include "AGGRenderer.h"
+#include "SAX2Parser.h"
+#include "SEMgSymbolManager.h"
+#include "SE_StyleVisitor.h"
+#include "SLDSymbols.h"
+#include "StylizationUtil.h"
#include "Stylizer.h"
#include "SymbolVisitor.h"
-#include "SLDSymbols.h"
-#include "SE_StyleVisitor.h"
-#include "SEMgSymbolManager.h"
+#include "SymbolDefinition.h"
#include "TransformCache.h"
-#include "StylizationUtil.h"
-#include "Fdo.h"
+#include <algorithm>
+
//For logging
#include "ServerManager.h"
#include "LogManager.h"
@@ -42,6 +46,7 @@
#endif
+///////////////////////////////////////////////////////////////////////////////
MdfModel::MapDefinition* MgMappingUtil::GetMapDefinition(MgResourceService* svcResource, MgResourceIdentifier* resId)
{
//get and parse the mapdef
@@ -70,6 +75,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
RSMgFeatureReader* MgMappingUtil::ExecuteFeatureQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
MdfModel::VectorLayerDefinition* vl,
@@ -229,6 +235,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
RSMgFeatureReader* MgMappingUtil::ExecuteRasterQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
MdfModel::GridLayerDefinition* gl,
@@ -340,6 +347,9 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// This is called by the MgServerRenderingService::RenderMapInternal to
+// render the layers.
void MgMappingUtil::StylizeLayers(MgResourceService* svcResource,
MgFeatureService* svcFeature,
MgDrawingService* svcDrawing,
@@ -353,7 +363,8 @@
bool expandExtents,
bool checkRefreshFlag,
double scale,
- bool selection)
+ bool selection,
+ bool extractColors)
{
#ifdef _DEBUG
long dwStart = GetTickCount();
@@ -365,7 +376,7 @@
TransformCacheMap transformCache;
Ptr<MgStringCollection> layerIds = new MgStringCollection();
- // Get the layers' resource content in a single request
+ // Get the layers' resource content in a single request by adding them to a collection
for (int i = layers->GetCount()-1; i >= 0; i--)
{
Ptr<MgLayerBase> mapLayer = layers->GetItem(i);
@@ -391,6 +402,8 @@
Ptr<MgResourceIdentifier> mapLayerId = mapLayer->GetLayerDefinition();
layerIds->Add(mapLayerId->ToString());
}
+
+ // request the collection from resource service and add ResourceContent to the individual layers
if(layerIds->GetCount() != 0)
{
Ptr<MgStringCollection> layerContents = svcResource->GetResourceContents(layerIds, NULL);
@@ -409,6 +422,7 @@
}
}
+ // cycle over the layers and do stylization
for (int i = layers->GetCount()-1; i >= 0; i--)
{
auto_ptr<MdfModel::LayerDefinition> ldf;
@@ -425,7 +439,7 @@
MG_SERVER_MAPPING_SERVICE_TRY()
- //get layer definition
+ // get layer definition using SAX XML Parser
ldf.reset(MgLayerBase::GetLayerDefinition(mapLayer->GetLayerResourceContent()));
Ptr<MgLayerGroup> group = mapLayer->GetGroup();
@@ -459,7 +473,7 @@
MdfModel::DrawingLayerDefinition* dl = dynamic_cast<MdfModel::DrawingLayerDefinition*>(ldf.get());
MdfModel::GridLayerDefinition* gl = dynamic_cast<MdfModel::GridLayerDefinition*>(ldf.get());
- if (vl)
+ if (vl) //############################################################################ vector layer
{
#ifdef _DEBUG
long dwLayerStart = GetTickCount();
@@ -546,6 +560,7 @@
// create the reader we'll use
rsReader = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, layerCs, item);
+ // create an automatic FdoPtr around the reader
FdoPtr<FdoIFeatureReader> fdoReader = (NULL == rsReader) ? NULL : rsReader->GetInternalReader();
#ifdef _DEBUG
@@ -558,9 +573,21 @@
dr->StartLayer(&layerInfo, &fcinfo);
ds->StylizeVectorLayer(vl, dr, rsReader, xformer, scale, NULL, NULL);
dr->EndLayer();
+
+ // color extraction for RFC60 only when needed
+ if (extractColors)
+ {
+ #ifdef _DEBUG
+ printf(" StylizeLayers() //ExtractColors// -Vector- Name:%S Time:%6.4f (s)\n\n", (mapLayer->GetName()).c_str(), (GetTickCount()-dwLayerStart)/1000.0);
+ #endif
+ ExtractColors(map, scaleRange, ds);
+ #ifdef _DEBUG
+ printf(" StylizeLayers() ##ExtractColors## -Vector- Name:%S Time:%6.4f (s)\n\n", (mapLayer->GetName()).c_str(), (GetTickCount()-dwLayerStart)/1000.0);
+ #endif
+ }
}
}
- else
+ else // not scaleRange
{
#ifdef _DEBUG
printf(" StylizeLayers() **NOT Stylizing - NO SCALE RANGE** Name:%S\n", (mapLayer->GetName()).c_str());
@@ -571,7 +598,7 @@
printf(" StylizeLayers() **LAYEREND** -Vector- Name:%S Time:%6.4f (s)\n\n", (mapLayer->GetName()).c_str(), (GetTickCount()-dwLayerStart)/1000.0);
#endif
}
- else if (gl)
+ else if (gl) //############################################################################ grid layer
{
// TODO: FDO RFP - Make FdoPtr's reference counter thread-safe.
static ACE_Recursive_Thread_Mutex sg_fdoRfpMutex;
@@ -717,7 +744,7 @@
printf(" StylizeLayers() **LAYEREND** -Grid- Name:%S Time:%6.4f (s)\n\n", (mapLayer->GetName()).c_str(), (GetTickCount()-dwLayerStart)/1000.0);
#endif
}
- else if (dl) //drawing layer
+ else if (dl) //############################################################################ drawing layer
{
#ifdef _DEBUG
long dwLayerStart = GetTickCount();
@@ -779,7 +806,7 @@
#ifdef _DEBUG
printf(" StylizeLayers() **LAYEREND** -Drawing- Name:%S Time = %6.4f (s)\n\n", (mapLayer->GetName()).c_str(), (GetTickCount()-dwLayerStart)/1000.0);
#endif
- }
+ } // end layer switch
MG_SERVER_MAPPING_SERVICE_CATCH(L"MgMappingUtil.StylizeLayers");
@@ -807,7 +834,7 @@
STRING stackTrace = exception->GetStackTrace(locale);
MG_LOG_EXCEPTION_ENTRY(message.c_str(), stackTrace.c_str());
-#ifdef _DEBUG
+#if defined(_DEBUG) || defined(_DEBUG_PNG8)
STRING details = mgException->GetDetails(locale);
wstring err = L"\n %t Error during stylization of layer ";
@@ -818,8 +845,10 @@
err += L"\n";
ACE_DEBUG( (LM_DEBUG, err.c_str()) );
#endif
- }
- }
+ // TODO could throw here depending on a serverconfig setting (RFC64)
+// throw exception;
+ } // if exception
+ } // for all layers
#ifdef _DEBUG
printf("StylizeLayers() **MAPDONE** Layers:%d Total Time:%6.4f (s)\n\n", layers->GetCount(), (GetTickCount()-dwStart)/1000.0);
@@ -829,6 +858,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
// When rendering a tile, we need to compute the extent used to determine
// which features to render into it. Features in adjacent tiles, but not
// in the current tile, will potentially draw in this tile due to their
@@ -1083,6 +1113,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
// draws a given feature type style into an image
MgByteReader* MgMappingUtil::DrawFTS(MgResourceService* svcResource,
MdfModel::FeatureTypeStyle* fts,
@@ -1125,6 +1156,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
// transforms a given extent and returns the new extent in the new cs
MgEnvelope* MgMappingUtil::TransformExtent(MgEnvelope* extent, MgCoordinateSystemTransform* xform)
{
@@ -1135,6 +1167,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
// returns an MgPolygon from a given envelope
MgPolygon* MgMappingUtil::GetPolygonFromEnvelope(MgEnvelope* env)
{
@@ -1155,6 +1188,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
void MgMappingUtilExceptionTrap(FdoException* except, int line, wchar_t* file)
{
MG_TRY()
@@ -1185,7 +1219,295 @@
}
+///////////////////////////////////////////////////////////////////////////////
void MgMappingUtil::InitializeStylizerCallback()
{
SetStylizerExceptionCallback(&MgMappingUtilExceptionTrap);
}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// PURPOSE: Accessor method for the base colors defined in this Layer and
+// scaleRange. Used for RFC60.
+// RETURNS: A pointer to the list of colors of the collected colors (maybe
+// empty but not null)
+///////////////////////////////////////////////////////////////////////////////
+void MgMappingUtil::GetUsedColorsFromScaleRange(ColorStringList& usedColorList,
+ MdfModel::VectorScaleRange* scaleRange,
+ SE_SymbolManager* sman)
+{
+ // compute new color list by iterating through the featuretypecollection
+ FeatureTypeStyleCollection* pftsColl = scaleRange->GetFeatureTypeStyles();
+ int ftsccount = pftsColl->GetCount();
+ for (int j=0; j<ftsccount; ++j)
+ {
+ FeatureTypeStyle* pfts = pftsColl->GetAt(j);
+
+ // iterate through the rulecollection
+ RuleCollection* ruleColl = pfts->GetRules();
+ int rccount = ruleColl->GetCount();
+ for (int k=0; k<rccount; ++k)
+ {
+ Rule* rule = ruleColl->GetAt(k);
+
+ // get the label which will be the key in the color map
+ Label* label = rule->GetLabel();
+ if (label)
+ {
+ // add colors of txtsymbols
+ TextSymbol* txtsym = label->GetSymbol();
+ if (txtsym)
+ {
+ // create copies of all strings so we can safely delete the resulting list later
+ usedColorList.push_back(txtsym->GetForegroundColor().substr());
+ usedColorList.push_back(txtsym->GetBackgroundColor().substr());
+ }
+ }
+
+ // Do the casting to access the relevant members. This is bad style
+ // (instead of using the visitor pattern of the MdfModel) but it keeps
+ // it nice and compact and documents the structure better...
+ AreaRule* paRule = dynamic_cast<AreaRule*>(rule);
+ LineRule* plRule = dynamic_cast<LineRule*>(rule);
+ PointRule* ppRule = dynamic_cast<PointRule*>(rule);
+ CompositeRule* pcRule = dynamic_cast<CompositeRule*>(rule); // used for new stylization
+
+ // AreaRule symbolization...
+ if (paRule != NULL)
+ {
+ AreaSymbolization2D* pasym = paRule->GetSymbolization();
+ if (pasym && pasym->GetFill() != NULL)
+ {
+ // create copies of all strings so we can safely delete the resulting list later
+ usedColorList.push_back(pasym->GetFill()->GetForegroundColor().substr());
+ usedColorList.push_back(pasym->GetFill()->GetBackgroundColor().substr());
+ }
+ if (pasym && pasym->GetEdge() != NULL)
+ usedColorList.push_back(pasym->GetEdge()->GetColor().substr());
+ }
+
+ // LineRule Symbolization...
+ if (plRule != NULL)
+ {
+ LineSymbolizationCollection* plsymcol = plRule->GetSymbolizations();
+
+ // iterate through the linesymbolizations
+ int lsccount = plsymcol->GetCount();
+ for (int l=0; l < lsccount; l++)
+ {
+ LineSymbolization2D* plsym = plsymcol->GetAt(l);
+ if (plsym && plsym->GetStroke() != NULL)
+ usedColorList.push_back(plsym->GetStroke()->GetColor().substr());
+ }
+ }
+
+ // PointRule Symbolization...
+ if (ppRule != NULL)
+ {
+ PointSymbolization2D* ppsym = ppRule->GetSymbolization();
+ if (ppsym)
+ {
+ Symbol* sym = ppsym->GetSymbol();
+ MdfModel::BlockSymbol* blockSymbol = dynamic_cast<MdfModel::BlockSymbol*>(sym);
+ MdfModel::FontSymbol* fontSymbol = dynamic_cast<MdfModel::FontSymbol*>(sym);
+ MdfModel::MarkSymbol* markSymbol = dynamic_cast<MdfModel::MarkSymbol*>(sym);
+ MdfModel::TextSymbol* textSymbol = dynamic_cast<MdfModel::TextSymbol*>(sym);
+ MdfModel::W2DSymbol* w2dSymbol = dynamic_cast<MdfModel::W2DSymbol*>(sym);
+ if (blockSymbol != NULL)
+ {
+ usedColorList.push_back(blockSymbol->GetBlockColor().substr());
+ usedColorList.push_back(blockSymbol->GetLayerColor().substr());
+ }
+ if (fontSymbol != NULL)
+ {
+ usedColorList.push_back(fontSymbol->GetForegroundColor().substr());
+ }
+ if (markSymbol != NULL)
+ {
+ if (markSymbol->GetEdge() != NULL)
+ usedColorList.push_back(markSymbol->GetEdge()->GetColor().substr());
+ if (markSymbol->GetFill() != NULL)
+ {
+ usedColorList.push_back(markSymbol->GetFill()->GetForegroundColor().substr());
+ usedColorList.push_back(markSymbol->GetFill()->GetBackgroundColor().substr());
+ }
+ }
+ if (textSymbol != NULL)
+ {
+ usedColorList.push_back(textSymbol->GetForegroundColor().substr());
+ usedColorList.push_back(textSymbol->GetBackgroundColor().substr());
+ }
+ if (w2dSymbol != NULL)
+ {
+ usedColorList.push_back(w2dSymbol->GetFillColor().substr());
+ usedColorList.push_back(w2dSymbol->GetLineColor().substr());
+ usedColorList.push_back(w2dSymbol->GetTextColor().substr());
+ }
+ }
+ }
+
+ // CompositeRule Symbolization...
+ if (pcRule != NULL)
+ {
+ CompositeSymbolization* pcsym = pcRule->GetSymbolization();
+ SymbolInstanceCollection* sic = pcsym->GetSymbolCollection();
+ int nInstances = sic->GetCount();
+ for (int i=0; i<nInstances; ++i)
+ {
+ SymbolInstance* instance = sic->GetAt(i);
+ // get the symbol definition, either inlined or by reference
+ SymbolDefinition* symdef = instance->GetSymbolDefinition();
+ if (symdef) // inline
+ FindColorInSymDefHelper(usedColorList, symdef);
+ else
+ {
+ // resourceId
+ const MdfString& symref = instance->GetResourceId(); // symbol reference
+ if (sman)
+ {
+ // if we have a symbolmanager do the lookup
+ MdfModel::SymbolDefinition* symdef = sman->GetSymbolDefinition(symref.c_str());
+ FindColorInSymDefHelper(usedColorList, symdef);
+ }
+ }
+ } // for sym instances
+ } // for CompositeRule
+ } // for GetRules
+ } // for GetFeatureTypeStyles
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Extract colors from the scalerange, lookup the referenceIds, and store
+// them with the map.
+void MgMappingUtil::ExtractColors(MgMap* map, MdfModel::VectorScaleRange* scaleRange, Stylizer* stylizer)
+{
+ // add the colors from this scaleRange and vectorlayer to the map colors
+ try
+ {
+ DefaultStylizer* ds = dynamic_cast<DefaultStylizer*>(stylizer);
+ SE_SymbolManager* sman = ds? ds->GetSymbolManager() : NULL;
+ // stack based
+ ColorStringList vLayerColors;
+ // parse the scalerange
+ GetUsedColorsFromScaleRange(vLayerColors, scaleRange, sman);
+ map->AddColorsToPalette(vLayerColors);
+ }
+ catch (exception e)
+ {
+ ACE_DEBUG((LM_DEBUG, L"(%t) %w caught in MappingUtil.ExtractColors\n", e.what()));
+ throw e;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// overloaded helper for SimpleSymbolDefinition
+inline void MgMappingUtil::FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::SimpleSymbolDefinition* symdef)
+{
+ // the visitor for the graphics
+ class GraphicElementVisitorImpl : public MdfModel::IGraphicElementVisitor
+ {
+ public:
+ ColorStringList* colorList;
+ void VisitPath (Path& path)
+ {
+ colorList->push_back(path.GetLineColor().substr());
+ colorList->push_back(path.GetFillColor().substr());
+ };
+ // TODO - other visitors for VisitImage and VisitText to be added here on a needed basis
+ void VisitImage(Image& image) {};
+ void VisitText(Text& text) {};
+ } visitor;
+
+ if (symdef)
+ {
+ MdfModel::LineUsage* lineUsage = symdef->GetLineUsage();
+ if (lineUsage)
+ {
+ MdfModel::Path* path = lineUsage->GetDefaultPath();
+ if (path)
+ {
+ colorList.push_back(path->GetLineColor().substr());
+ colorList.push_back(path->GetFillColor().substr());
+ }
+ }
+
+ MdfModel::GraphicElementCollection* graphElems = symdef->GetGraphics();
+ int gInstances = graphElems->GetCount();
+ for (int i=0; i < gInstances; ++i)
+ {
+ MdfModel::GraphicElement* graphics = graphElems->GetAt(i);
+ if (graphics)
+ {
+ visitor.colorList = &colorList; // use injection to pass reference to list
+ graphics->AcceptVisitor(visitor);
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// overloaded helper for CompoundSymbolDefinition
+inline void MgMappingUtil::FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::CompoundSymbolDefinition* symdef)
+{
+ if (symdef)
+ {
+ MdfModel::SimpleSymbolCollection* simSymCol = symdef->GetSymbols();
+ int kInstances = simSymCol->GetCount();
+ for (int i=0; i<kInstances; ++i)
+ {
+ MdfModel::SimpleSymbol* simsym = simSymCol->GetAt(i);
+ if (simsym)
+ {
+ MdfModel::SimpleSymbolDefinition* simplesymdef = simsym->GetSymbolDefinition();
+ if (simplesymdef) // inline
+ FindColorInSymDefHelper(colorList, simplesymdef);
+ else
+ {
+ // TODO - resourceId
+ }
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// overloaded helper for SymbolDefinition
+inline void MgMappingUtil::FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::SymbolDefinition* symdef)
+{
+ FindColorInSymDefHelper(colorList, dynamic_cast<MdfModel::SimpleSymbolDefinition*>(symdef));
+ FindColorInSymDefHelper(colorList, dynamic_cast<MdfModel::CompoundSymbolDefinition*>(symdef));
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//-------------------------------------------------------
+// RFC60 code for colormapped tiles by UV
+//-------------------------------------------------------
+// We examine the expressions collected from xml definitions of all layers.
+// The color Palette for the renderer is a vector<RS_Color>. The map object
+// has a list from all color entries found in the most recent layer stylization.
+// TODO - currently they are interpreted as ffffffff 32 bit RGBA string values.
+// Adding expressions and other interpretations could be done here.
+void MgMappingUtil::ParseColorStrings (RS_ColorVector* tileColorPalette, MgMap* map)
+{
+ assert(tileColorPalette);
+ assert(map);
+ ColorStringList& mapColorList = map->GetColorPalette(); // sorted and uniquified
+ if (!mapColorList.empty()) // add them if they are available
+ {
+ ColorStringList::iterator it = mapColorList.begin();
+ for (; it != mapColorList.end(); it++)
+ {
+ // string color reader for 0xAARRGGBB "%10X" XML color strings
+ // this is parsed and converted using the MgColor(string) ctor which also uses rgba order
+ // but it is in argb order ergo => r=a, g=r, b=g, a=b
+ MgColor c(*it);
+ // set the RS_Color(r,g,b,a) assign the crossed over colors
+ tileColorPalette->push_back(RS_Color(c.GetGreen(), c.GetBlue(), c.GetAlpha(), c.GetRed()));
+ }
+ }
+}
Modified: trunk/MgDev/Server/src/Services/Mapping/MappingUtil.h
===================================================================
--- trunk/MgDev/Server/src/Services/Mapping/MappingUtil.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Mapping/MappingUtil.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -34,6 +34,13 @@
class MgCoordinateSystem;
class RSMgFeatureReader;
class TransformCache;
+class SE_SymbolManager;
+namespace MdfModel
+{
+ class SymbolDefinition;
+ class CompoundSymbolDefinition;
+ class SimpleSymbolDefinition;
+}
//Common stylization utility code -- used by both the mapping and rendering services
class MG_SERVER_MAPPING_API MgMappingUtil
@@ -52,9 +59,10 @@
bool expandExtents,
bool checkRefreshFlag,
double scale,
- bool selection = false);
+ bool selection = false,
+ bool extractColors = false);
- static RSMgFeatureReader * ExecuteFeatureQuery(MgFeatureService* svcFeature,
+ static RSMgFeatureReader* ExecuteFeatureQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
MdfModel::VectorLayerDefinition* vl,
const wchar_t* overrideFilter,
@@ -62,7 +70,7 @@
MgCoordinateSystem* layerCs,
TransformCache* cache);
- static RSMgFeatureReader * ExecuteRasterQuery(MgFeatureService* svcFeature,
+ static RSMgFeatureReader* ExecuteRasterQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
MdfModel::GridLayerDefinition* gl,
const wchar_t* overrideFilter,
@@ -80,6 +88,21 @@
static void InitializeStylizerCallback();
static MgPolygon* GetPolygonFromEnvelope(MgEnvelope* extent);
+
+ // RFC60 addition
+ static void ExtractColors(MgMap* map, MdfModel::VectorScaleRange* scaleRange, Stylizer* stylizer);
+ static void GetUsedColorsFromScaleRange(ColorStringList& usedColorList, MdfModel::VectorScaleRange* scaleRange, SE_SymbolManager* sman);
+
+ // helpers
+ static void FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::SymbolDefinition* symdef);
+ static void FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::CompoundSymbolDefinition* symdef);
+ static void FindColorInSymDefHelper(ColorStringList& colorList, MdfModel::SimpleSymbolDefinition* symdef);
+
+ // Parse the expressions collected from xml definitions of all layers. The map
+ // object has a list from all color entries found in the most recent layer stylization.
+ // TODO: currently they are interpreted as ffffffff 32 bit RGBA string values.
+ // The color palette passed to the renderer is a std::vector<RS_Color>
+ static void ParseColorStrings(RS_ColorVector* tileColorPalette, MgMap* map);
};
#endif
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -36,8 +36,15 @@
static const INT32 FILTER_SELECTABLE = 2;
static const INT32 FILTER_HASTOOLTIPS = 4;
+inline bool hasColorMap (STRING format)
+{
+ return format == L"PNG8" || format == L"GIF";
+}
+
IMPLEMENT_CREATE_SERVICE(MgServerRenderingService)
+
+///////////////////////////////////////////////////////////////////////////////
// used when we want to process a given number of features
bool StylizeThatMany(void* data)
{
@@ -49,6 +56,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
MgServerRenderingService::MgServerRenderingService() : MgRenderingService()
{
m_pCSFactory = new MgCoordinateSystemFactory();
@@ -111,11 +119,13 @@
}
+///////////////////////////////////////////////////////////////////////////////
MgServerRenderingService::~MgServerRenderingService()
{
}
+///////////////////////////////////////////////////////////////////////////////
MgByteReader* MgServerRenderingService::RenderTile(MgMap* map,
CREFSTRING baseMapLayerGroupName,
INT32 tileColumn,
@@ -188,6 +198,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+/// render a map using all layers from the baseGroup
MgByteReader* MgServerRenderingService::RenderTile(MgMap* map,
MgLayerGroup* baseGroup,
INT32 scaleIndex,
@@ -256,6 +268,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arg bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderDynamicOverlay(MgMap* map,
MgSelection* selection,
CREFSTRING format)
@@ -265,6 +279,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arg bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderDynamicOverlay(MgMap* map,
MgSelection* selection,
CREFSTRING format,
@@ -277,6 +293,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// called from API (first call of AjaxPgPViewerSampleApplication)
MgByteReader* MgServerRenderingService::RenderDynamicOverlay(MgMap* map,
MgSelection* selection,
MgRenderingOptions* options)
@@ -341,6 +359,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arg bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
CREFSTRING format)
@@ -350,6 +370,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arg bClip = false
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
CREFSTRING format,
@@ -359,6 +381,10 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// render complete map around center point in given scale using map's background
+// color and display sizes as default arguments to call the real rendermap method
+// default arg (bKeepSelection = true, bClip = false)
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
CREFSTRING format,
@@ -390,6 +416,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arg bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
MgEnvelope* extents,
@@ -403,6 +431,9 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// render the provided extent of the map and align aspect ratios to the provided window
+// default arg bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
MgEnvelope* extents,
@@ -497,6 +528,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default argument bKeepSelection = true
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
MgCoordinate* center,
@@ -511,6 +544,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// default arguments bClip = false
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
MgCoordinate* center,
@@ -525,6 +560,10 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// render map around center point in given scale
+// default args bKeepSelection = true, bClip = false, backgroundColor = map->backgroundColor,
+// width = map->getDisplayWidth, height = map->getDisplayHeight
MgByteReader* MgServerRenderingService::RenderMap(MgMap* map,
MgSelection* selection,
MgCoordinate* center,
@@ -581,7 +620,7 @@
}
-
+///////////////////////////////////////////////////////////////////////////////
MgFeatureInformation* MgServerRenderingService::QueryFeatures(MgMap* map,
MgStringCollection* layerNames,
MgGeometry* geometry,
@@ -593,6 +632,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
MgFeatureInformation* MgServerRenderingService::QueryFeatures(MgMap* map,
MgStringCollection* layerNames,
MgGeometry* geometry,
@@ -681,6 +721,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
MgBatchPropertyCollection* MgServerRenderingService::QueryFeatureProperties(MgMap* map,
MgStringCollection* layerNames,
MgGeometry* filterGeometry,
@@ -692,6 +733,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
MgBatchPropertyCollection* MgServerRenderingService::QueryFeatureProperties(MgMap* map,
MgStringCollection* layerNames,
MgGeometry* filterGeometry,
@@ -722,6 +764,9 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// pack options into object and forward call (select Selection AND Layers)
+// maybe keepSelection called by RenderTile
MgByteReader* MgServerRenderingService::RenderMapInternal(MgMap* map,
MgSelection* selection,
MgReadOnlyLayerCollection* roLayers,
@@ -740,6 +785,14 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// called from (indirectly):
+// RenderMap(complete), RenderMap(extent)(roLayers == NULL)
+// RenderTile (selection == NULL)
+// render the map using from the provided rolayers
+// (this is the baseGroup layers for rendering tiles)
+// render map using provided options object from before
+// this is called for tiles and for dynamic overlays
MgByteReader* MgServerRenderingService::RenderMapInternal(MgMap* map,
MgSelection* selection,
MgReadOnlyLayerCollection* roLayers,
@@ -788,14 +841,18 @@
RS_Color bgcolor(0, 0, 0, 255); //not used -- GDRenderer is already initialized to the correct bgcolor
+ STRING format = options->GetImageFormat();
+
RS_MapUIInfo mapInfo(sessionId, map->GetName(), map->GetObjectId(), srs, units, bgcolor);
// begin map stylization
dr->StartMap(&mapInfo, b, scale, map->GetDisplayDpi(), map->GetMetersPerUnit(), NULL);
+ MG_TRY()
+
// if no layer collection is supplied, then put all layers in a temporary collection
Ptr<MgReadOnlyLayerCollection> tempLayers = SAFE_ADDREF(roLayers);
- if (tempLayers == NULL)
+ if (tempLayers == NULL) // if called from renderMap not RenderTile
{
tempLayers = new MgReadOnlyLayerCollection();
Ptr<MgLayerCollection> layers = map->GetLayers();
@@ -807,13 +864,14 @@
}
INT32 behavior = options->GetBehavior();
- if (behavior & MgRenderingOptions::RenderLayers)
+ if (behavior & MgRenderingOptions::RenderLayers) // this is for tiles so observer colormaps
{
MgMappingUtil::StylizeLayers(m_svcResource, m_svcFeature, m_svcDrawing, m_pCSFactory, map,
- tempLayers, NULL, &ds, dr, dstCs, expandExtents, false, scale);
+ tempLayers, NULL, &ds, dr, dstCs, expandExtents, false, scale,
+ false, hasColorMap(format));
}
- // now we need to stylize the selection on top
+ // now we need to stylize the selection on top (this is not for tiles!)
if (selection && (behavior & MgRenderingOptions::RenderSelection))
{
Ptr<MgReadOnlyLayerCollection> selLayers = selection->GetLayers();
@@ -867,7 +925,11 @@
}
}
+ MG_CATCH(L"MgServerRenderingService.RenderMapInternal")
+
dr->EndMap();
+
+ MG_THROW() // to skip a faulty tile we need to rethrow the exception which could be thrown in StylizeLayers
/*
//-------------------------------------------------------
// draw a border around the tile - used for debugging
@@ -894,15 +956,38 @@
// get a byte representation of the image
auto_ptr<RS_ByteData> data;
- STRING imageFormat = options->GetImageFormat();
- // Both AGG and GD expect the format to be an uppercase string
- STRING format = MgUtil::ToUpper(imageFormat);
+ try
+ {
+ // call the image renderer to create the image
+ if (wcscmp(m_rendererName.c_str(), L"AGG") == 0)
+ {
+ //-------------------------------------------------------
+ /// RFC60 code to correct colormaps by UV
+ //-------------------------------------------------------
+ // we examine the expressions collected from xml definitions of all layers.
+ // the map object has a list from all color entries found in the most recent layer stylization
+ // TODO currently they are interpreted as ffffffff 32 bit RGBA string values.
+ // adding expresssions and other interpretations should be done in ParseColorStrings.
+ // the color Palette for the renderer is a vector<RS_Color>
+ if (hasColorMap(format))
+ {
+ RS_ColorVector tileColorPalette;
+ MgMappingUtil::ParseColorStrings(&tileColorPalette, map);
+// printf("<<<<<<<<<<<<<<<<<<<<< MgServerRenderingService::ColorPalette->size(): %d\n", tileColorPalette.size());
+ data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, &tileColorPalette));
+ }
+ else
+ data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, NULL));
+ }
+ else
+ data.reset(((GDRenderer*)dr)->Save(format, saveWidth, saveHeight));
+ }
+ catch (exception e)
+ {
+ ACE_DEBUG((LM_DEBUG, L"(%t) %w caught in RenderingService ColorPaletteGeneration\n", e.what()));
+ throw e;
+ }
- if (wcscmp(m_rendererName.c_str(), L"AGG") == 0)
- data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight));
- else
- data.reset(((GDRenderer*)dr)->Save(format, saveWidth, saveHeight));
-
if (NULL != data.get())
{
// put this into a byte source
@@ -919,11 +1004,14 @@
ret = bs->GetReader();
}
+ else
+ throw new MgNullReferenceException(L"MgServerRenderingService.RenderMapInternal", __LINE__, __WFILE__, NULL, L"MgNoDataFromRenderer", NULL);
return ret.Detach();
}
+///////////////////////////////////////////////////////////////////////////////
MgByteReader* MgServerRenderingService::RenderMapLegend(MgMap* map,
INT32 width,
INT32 height,
@@ -1009,6 +1097,7 @@
}
+///////////////////////////////////////////////////////////////////////////////
// A helper function that does most of the work for QueryFeatures
// and QueryFeatureProperties. Basically runs a rendering loop with
// a custom renderer supplied by the caller that accumulates selection
@@ -1367,12 +1456,14 @@
}
+///////////////////////////////////////////////////////////////////////////////
void MgServerRenderingService::SetConnectionProperties(MgConnectionProperties*)
{
// Do nothing. No connection properties are required for server-side service objects.
}
+///////////////////////////////////////////////////////////////////////////////
SE_Renderer* MgServerRenderingService::CreateRenderer(int width,
int height,
RS_Color& bgColor,
Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2010-01-06 07:59:00 UTC (rev 4484)
@@ -117,12 +117,16 @@
return found;
}
-MgByteReader* MgServerTileService::GetTile(
- MgResourceIdentifier* mapDefinition,
- CREFSTRING baseMapLayerGroupName,
- INT32 tileColumn,
- INT32 tileRow,
- INT32 scaleIndex)
+
+///////////////////////////////////////////////////////////////////////////////
+// Create tilename from mapDefinition, scaleIndex, row, and column.
+// Remove lockfile, look for the tile in the cache, if not in cache create
+// lockfile and look for map in mapcache.
+MgByteReader* MgServerTileService::GetTile(MgResourceIdentifier* mapDefinition,
+ CREFSTRING baseMapLayerGroupName,
+ INT32 tileColumn,
+ INT32 tileRow,
+ INT32 scaleIndex)
{
Ptr<MgByteReader> ret;
FILE* lockFile = NULL;
@@ -149,26 +153,9 @@
__LINE__, __WFILE__, &arguments, L"MgInvalidScaleIndex", 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(NULL != resourceService);
-
- if (!resourceService->HasPermission(mapDefinition, MgResourcePermission::ReadOnly))
- {
- 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);
- }
-
+ // get the service from our helper method
+ Ptr<MgResourceService> resourceService = GetResourceServiceForMapDef(mapDefinition,
+ L"MgServerTileService.GetTile");
// Generate tile and lock pathnames.
m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
tileColumn, tileRow, tilePathname, lockPathname, false);
@@ -194,9 +181,10 @@
// 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()
+ // that a Rewind() is not called in the middle of a Deserialize().
+ // Lockfile test and creation is in same protected scope.
{
- // Attemp to lock the tile file.
+ // Attempt to lock the tile file.
ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
// Bail out if the tile file has been locked for so long.
@@ -214,7 +202,7 @@
if (NULL != ret)
{
- break;
+ break; // tile was in tileCache .. done.
}
// Create the lock file and close it right away.
@@ -227,7 +215,7 @@
arguments.Add(lockPathname);
throw new MgFileIoException(L"MgServerTileService.GetTile",
- __LINE__, __WFILE__, &arguments, L"MgUnableToOpenTileFile", NULL);
+ __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
}
else
{
@@ -238,6 +226,10 @@
if (sm_mapCache.end() != iter)
{
cachedMap = SAFE_ADDREF((*iter).second);
+ cachedMap->Rewind();
+ Ptr<MgStream> stream = new MgStream(cachedMap);
+ map = new MgMap();
+ map->Deserialize(stream);
}
else
{
@@ -254,17 +246,8 @@
}
sm_mapCache[mapString] = SAFE_ADDREF((MgMemoryStreamHelper*)cachedMap);
}
+ } // end of mutex scope
-
- if (!map)
- {
- cachedMap->Rewind();
- Ptr<MgStream> stream = new MgStream(cachedMap);
- map = new MgMap();
- map->Deserialize(stream);
- }
- }
-
double scale = map->GetFiniteDisplayScaleAt(scaleIndex);
map->SetViewScale(scale);
@@ -286,6 +269,8 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// look for the tile in the tilecache first
MgByteReader* MgServerTileService::GetTile(MgMap* map,
CREFSTRING baseMapLayerGroupName,
INT32 tileColumn,
@@ -364,7 +349,7 @@
arguments.Add(lockPathname);
throw new MgFileIoException(L"MgServerTileService.GetTile",
- __LINE__, __WFILE__, &arguments, L"MgUnableToOpenTileFile", NULL);
+ __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
}
else
{
@@ -389,6 +374,9 @@
return ret.Detach();
}
+
+///////////////////////////////////////////////////////////////////////////////
+// render a tile and store it in the cache
MgByteReader* MgServerTileService::GetTile(CREFSTRING tilePathname, MgMap* map, INT32 scaleIndex,
CREFSTRING baseMapLayerGroupName, INT32 tileColumn, INT32 tileRow)
{
@@ -422,6 +410,9 @@
return img.Detach();
}
+
+///////////////////////////////////////////////////////////////////////////////
+// take a tile image and store it in the tilecache using lockfiles
void MgServerTileService::SetTile(MgByteReader* img,
MgMap* map,
INT32 scaleIndex,
@@ -476,7 +467,7 @@
arguments.Add(lockPathname);
throw new MgFileIoException(L"MgServerTileService.SetTile",
- __LINE__, __WFILE__, &arguments, L"MgUnableToOpenTileFile", NULL);
+ __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
}
else
{
@@ -498,6 +489,35 @@
}
+///////////////////////////////////////////////////////////////////////////////
+// accessor method for resource service
+MgResourceService* MgServerTileService::GetResourceServiceForMapDef(MgResourceIdentifier* mapDefinition,
+ CREFSTRING funcName)
+{
+ // get service manager
+ MgServiceManager* serviceMan = MgServiceManager::GetInstance();
+ assert(NULL != serviceMan);
+
+ // Get the service from service manager
+ Ptr<MgResourceService> resourceService = dynamic_cast<MgResourceService*>(
+ serviceMan->RequestService(MgServiceType::ResourceService));
+ assert(NULL != resourceService);
+
+ if (!resourceService->HasPermission(mapDefinition, MgResourcePermission::ReadOnly))
+ {
+ MG_LOG_AUTHENTICATION_ENTRY(MgResources::PermissionDenied.c_str());
+
+ MgStringCollection arguments;
+ arguments.Add(mapDefinition->ToString());
+
+ throw new MgPermissionDeniedException(
+ funcName, __LINE__, __WFILE__, &arguments, L"", NULL);
+ }
+ return resourceService.Detach();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
void MgServerTileService::ClearCache(MgMap* map)
{
MG_TRY()
@@ -513,6 +533,7 @@
MG_CATCH_AND_THROW(L"MgServerTileService.ClearCache")
}
+
///////////////////////////////////////////////////////////////////////////////
/// \brief
/// Handle the Resource Change Notification event.
@@ -571,11 +592,15 @@
return success;
}
+
+///////////////////////////////////////////////////////////////////////////////
void MgServerTileService::SetConnectionProperties(MgConnectionProperties*)
{
// 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));
@@ -612,11 +637,15 @@
}
}
+
+///////////////////////////////////////////////////////////////////////////////
INT32 MgServerTileService::GetDefaultTileSizeX()
{
return MgTileParameters::tileWidth;
}
+
+///////////////////////////////////////////////////////////////////////////////
INT32 MgServerTileService::GetDefaultTileSizeY()
{
return MgTileParameters::tileHeight;
Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.h 2010-01-06 07:35:50 UTC (rev 4483)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.h 2010-01-06 07:59:00 UTC (rev 4484)
@@ -69,6 +69,8 @@
void ClearMapCache(CREFSTRING mapName);
+ MgResourceService* GetResourceServiceForMapDef(MgResourceIdentifier* mapDefinition, CREFSTRING funcName);
+
// member data
Ptr<MgTileCache> m_tileCache;
More information about the mapguide-commits
mailing list