[mapguide-commits] r9191 - sandbox/jng/utfgrid/Common/Renderers
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue May 30 08:19:47 PDT 2017
Author: jng
Date: 2017-05-30 08:19:47 -0700 (Tue, 30 May 2017)
New Revision: 9191
Modified:
sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
Log:
Convert the utfgrid content rendering into a 2-pass process:
- 1st pass: Track the rendered "pixels" from the AGG backend and re-map them to a new replacement pixel starting from (decoded: 0, encoded: 32) that increments with each tracked pixel. This pass is to ensure that:
a. Our utf character budget is utilized to the max. We don't want to skip across any valid characters.
b. We can render keys in the order of the re-mapped "pixels". This is important as the rendered character "pixel" must resolve to the index of the "keys" array (per the UTFGrid spec). Re-mapping character pixels allows us to establish this relationship.
- 2nd pass: With the pixels re-mapped, render the utfgrid with the re-mapped pixels.
This commit also ensures any FDO string properties are escaped for JSON content rendering.
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp 2017-05-26 16:05:42 UTC (rev 9190)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp 2017-05-30 15:19:47 UTC (rev 9191)
@@ -7,7 +7,10 @@
//feature
#define DEBUG_UTFGRID
+#define EMPTY_ENCODED_CHAR 32
+
UTFGridContent::UTFGridContent()
+ : m_currentRemappedColor(0)
{
}
@@ -22,6 +25,27 @@
return mbContent;
}
+void UTFGridContent::EscapeJsonString(const std::wstring& input, std::wstring& output)
+{
+ std::wostringstream ss;
+ for (std::wstring::const_iterator iter = input.begin(); iter != input.end(); iter++)
+ {
+ switch (*iter)
+ {
+ case '\\': ss << L"\\\\"; break;
+ case '"': ss << L"\\\""; break;
+ case '/': ss << L"\\/"; break;
+ case '\b': ss << L"\\b"; break;
+ case '\f': ss << L"\\f"; break;
+ case '\n': ss << L"\\n"; break;
+ case '\r': ss << L"\\r"; break;
+ case '\t': ss << L"\\t"; break;
+ default: ss << *iter; break;
+ }
+ }
+ output.assign(ss.str());
+}
+
bool UTFGridContent::AddFeature(RS_LayerUIInfo* layer, unsigned int decodedColor, RS_FeatureReader* feature, const RS_String * tooltip, const RS_String * url)
{
static const size_t MAX_STRING = 64;
@@ -61,9 +85,22 @@
int propType = feature->GetPropertyType(propName);
if (propType == FdoDataType_String || propType == FdoDataType_DateTime)
{
- wVal.append(L"\"");
- wVal.append(propVal);
- wVal.append(L"\"");
+ if (propType == FdoDataType_String)
+ {
+ std::wstring oPropVal;
+ std::wstring iPropVal = propVal;
+ EscapeJsonString(iPropVal, oPropVal);
+
+ wVal.append(L"\"");
+ wVal.append(oPropVal);
+ wVal.append(L"\"");
+ }
+ else
+ {
+ wVal.append(L"\"");
+ wVal.append(propVal);
+ wVal.append(L"\"");
+ }
}
else
{
@@ -132,10 +169,37 @@
m_content << "," << std::endl << " \"";
}
+void UTFGridContent::BeginTracking()
+{
+ _ASSERT(m_currentRemappedColor == 0);
+ // Pre-register the "empty space" pixel
+ m_trackedEncodedColors.insert(EMPTY_ENCODED_CHAR);
+ m_remappedEncodedColors.insert(std::make_pair(EMPTY_ENCODED_CHAR, EncodeChar(m_currentRemappedColor)));
+ m_remappedEncodedColorsInv.insert(std::make_pair(m_currentRemappedColor, EMPTY_ENCODED_CHAR));
+}
+
+void UTFGridContent::TrackPixel(unsigned int pixel)
+{
+ // To maximize our utf character "budget", start from 0 again and for each rendered
+ // "pixel" we encounter, map it to our re-mapped and pre-encoded offset pixel. When it comes time to render
+ // the actual content, use the re-mapped offset pixel instead of what was rendered to the AGG backend, but
+ // retain the use of the original pixel for accessing the keys and data to be rendered out
+ if (m_trackedEncodedColors.find(pixel) == m_trackedEncodedColors.end())
+ {
+ m_currentRemappedColor++;
+ m_remappedEncodedColors.insert(std::make_pair(pixel, EncodeChar(m_currentRemappedColor)));
+ m_remappedEncodedColorsInv.insert(std::make_pair(m_currentRemappedColor, pixel));
+ m_trackedEncodedColors.insert(pixel);
+ }
+}
+
void UTFGridContent::AppendRowPixel(unsigned int pixel)
{
- m_trackedEncodedColors.insert(pixel);
- m_content << (wchar_t)pixel;
+ // This pixel should've been already re-mapped
+ _ASSERT(m_remappedEncodedColors.find(pixel) != m_remappedEncodedColors.end());
+
+ // Don't write the original pixel, write its re-mapped one
+ m_content << (wchar_t)m_remappedEncodedColors[pixel];
}
void UTFGridContent::EndGridRow()
@@ -152,20 +216,15 @@
{
m_content << "," << std::endl;
m_content << " \"keys\": [" << std::endl;
- for (ColorSet::iterator it = m_trackedEncodedColors.begin(); it != m_trackedEncodedColors.end(); it++)
+ m_content << " \"\""; //This is the "empty space" pixel
+ for (unsigned int i = 1; i <= m_currentRemappedColor; i++)
{
- if (it != m_trackedEncodedColors.begin())
- m_content << "," << std::endl;
+ //Every remapped pixel in this "ramp" should be accounted for
+ _ASSERT(m_remappedEncodedColorsInv.find(i) != m_remappedEncodedColorsInv.end());
- if (*it == 32) // This is the "empty space" pixel
- {
- m_content << " \"\"";
- }
- else
- {
- unsigned int decodedKey = DecodeChar(*it);
- m_content << " \"" << decodedKey << "\"";
- }
+ m_content << "," << std::endl;
+ unsigned int decodedKey = DecodeChar(m_remappedEncodedColorsInv[i]);
+ m_content << " \"" << decodedKey << "\"";
}
m_content << std::endl << " ]";
}
@@ -177,7 +236,7 @@
bool bFirst = true;
for (ColorSet::iterator it = m_trackedEncodedColors.begin(); it != m_trackedEncodedColors.end(); it++)
{
- if (*it == 32) // This is the "empty space" pixel
+ if (*it == EMPTY_ENCODED_CHAR) // This is the "empty space" pixel
{
continue;
}
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h 2017-05-26 16:05:42 UTC (rev 9190)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h 2017-05-30 15:19:47 UTC (rev 9191)
@@ -25,6 +25,7 @@
#include <set>
#include <sstream>
+typedef std::map<unsigned int, unsigned int> ColorReMap;
typedef std::map<unsigned int, std::string> ColorKeyMap;
typedef std::map<std::string, std::wstring> KeyFeatureMap;
typedef std::set<unsigned int> ColorSet;
@@ -41,6 +42,8 @@
void StartGrid();
void StartGridRow(bool bFirst);
+ void BeginTracking();
+ void TrackPixel(unsigned int pixel);
void AppendRowPixel(unsigned int pixel);
void EndGridRow();
void EndGrid();
@@ -52,9 +55,12 @@
static unsigned int DecodeChar(unsigned int toDecode);
private:
-
+ static void EscapeJsonString(const std::wstring& input, std::wstring& output);
+ unsigned int m_currentRemappedColor;
std::wstringstream m_content;
ColorSet m_trackedEncodedColors;
+ ColorReMap m_remappedEncodedColors;
+ ColorReMap m_remappedEncodedColorsInv;
KeyFeatureMap m_features;
ColorKeyMap m_pixels;
Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp 2017-05-26 16:05:42 UTC (rev 9190)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp 2017-05-30 15:19:47 UTC (rev 9191)
@@ -116,14 +116,31 @@
{
m_mapInfo = NULL;
+ //First pass: Track the rendered pixels
+ m_content->BeginTracking();
+
+ unsigned int bufHeight = m_context->rendering_buffer.height();
+ unsigned int bufWidth = m_context->rendering_buffer.width();
+
+ for (int y = bufHeight - 1; y >= 0; y--)
+ {
+ utfgrid_band_type* row_ptr = m_context->rendering_buffer.row_ptr(y);
+ for (int x = 0; x < bufWidth; x++)
+ {
+ m_content->TrackPixel(row_ptr[x]);
+ }
+ }
+
+ //Second pass: Render the actual grid content. The tracked pixels in the previous pass
+ //will assist in any re-mapping (as character space is at a premium)
m_content->StartGrid();
bool bFirst = true;
//Y-axis is flipped, so reverse iterate the y-axis
- for (int y = m_context->rendering_buffer.height() - 1; y >= 0; y--)
+ for (int y = bufHeight - 1; y >= 0; y--)
{
m_content->StartGridRow(bFirst);
utfgrid_band_type* row_ptr = m_context->rendering_buffer.row_ptr(y);
- for (int x = 0; x < m_context->rendering_buffer.width(); x++)
+ for (int x = 0; x < bufWidth; x++)
{
m_content->AppendRowPixel(row_ptr[x]);
}
More information about the mapguide-commits
mailing list