[mapguide-commits] r9182 - sandbox/jng/utfgrid/Common/Renderers

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon May 1 08:51:03 PDT 2017


Author: jng
Date: 2017-05-01 08:51:03 -0700 (Mon, 01 May 2017)
New Revision: 9182

Added:
   sandbox/jng/utfgrid/Common/Renderers/MapUTFGrid.h
   sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
   sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
   sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h
Modified:
   sandbox/jng/utfgrid/Common/Renderers/Makefile.am
   sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj
   sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj.filters
   sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
   sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h
Log:
Initial implementation of UTFGridRenderer
 - Add maputfgrid.h from mapserver, as it already implements the low-level AGG pixel format primitive (utfpix32) for UTFGrid rendering
 - Add agg_utfgrid_context. This is like agg_context, but uses agg template specializations for the above utfpix32 and eliminates AGG rendering stuff relating to alpha masking and font management.
 - Copy the bulk of the Marker/Polygon/Polyline (and any required support code) from the AGGRenderer, except instead of using agg_context, it uses the agg_utfgrid_context.
 - Add skeleton UTFGridContent which is focused on the actual assembly of the UTFGrid tile. This class is analogous to KmlContent (wrt KmlRenderer).

Modified: sandbox/jng/utfgrid/Common/Renderers/Makefile.am
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/Makefile.am	2017-04-27 12:44:20 UTC (rev 9181)
+++ sandbox/jng/utfgrid/Common/Renderers/Makefile.am	2017-05-01 15:51:03 UTC (rev 9182)
@@ -41,6 +41,8 @@
   RenderUtil.cpp \
   RS_ByteData.cpp \
   SymbolTrans.cpp \
+  UTFGridRenderer.cpp \
+  UTFGridContent.cpp \
   W2DRewriter.cpp \
   complex_polygon_gd.cpp
 
@@ -48,6 +50,7 @@
   AGGRenderer.h \
   AGGImageIO.h \
   agg_context.h \
+  agg_utfgrid_context.h \
   agg_mg_overloads.h \
   AGGW2DRewriter.h \
   AGGFillPatterns.h \
@@ -66,6 +69,7 @@
   KmlIconStyle.h \
   KmlRenderer.h \
   MapQuantization.h \
+  MapUTFGrid.h \
   ObservationMesh.h \
   Renderers.h \
   RenderUtil.h \
@@ -74,6 +78,8 @@
   RSDWFOutputStream.h \
   stdafx.h \
   SymbolTrans.h \
+  UTFGridRenderer.h \
+  UTFGridContent.h \
   W2DRewriter.h \
   whip_fill_library.h \
   whip_hatch_library.h \

Added: sandbox/jng/utfgrid/Common/Renderers/MapUTFGrid.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/MapUTFGrid.h	                        (rev 0)
+++ sandbox/jng/utfgrid/Common/Renderers/MapUTFGrid.h	2017-05-01 15:51:03 UTC (rev 9182)
@@ -0,0 +1,249 @@
+/******************************************************************************
+* Adapted for use in MgRenderers by Jackie Ng
+*
+* $Id$
+*
+* Project:  MapServer
+* Purpose:  UTFGrid rendering functions (using AGG)
+* Author:   Francois Desjarlais
+*
+******************************************************************************
+* Copyright (c) 1996-2007 Regents of the University of Minnesota.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies of this Software or works derived from this Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*****************************************************************************/
+#ifndef _MAPUTFGRID_H_
+#define _MAPUTFGRID_H_
+
+#include "agg_renderer_base.h"
+#include "agg_rendering_buffer.h"
+
+/*
+* Using AGG templates to create UTFGrid pixel.
+*/
+
+//==================================================================utfpix32
+struct utfpix32
+{
+    typedef agg::int32u value_type;
+    typedef agg::int64u calc_type;
+    typedef agg::int64  long_type;
+
+    typedef utfpix32 self_type;
+
+    value_type v;
+
+    //--------------------------------------------------------------------
+    utfpix32() {}
+
+    //--------------------------------------------------------------------
+    utfpix32(unsigned v_) :
+        v(agg::int32u(v_)) {}
+
+    //--------------------------------------------------------------------
+    utfpix32(const self_type& c) :
+        v(c.v) {}
+
+    //--------------------------------------------------------------------
+    void clear()
+    {
+        v = 0;
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE void add(const self_type& c, unsigned cover)
+    {
+        *this = c;
+    }
+};
+
+//=================================================pixfmt_utf
+template<class ColorT, class RenBuf, unsigned Step = 1, unsigned Offset = 0>
+class pixfmt_utf
+{
+public:
+    typedef RenBuf   rbuf_type;
+    typedef typename rbuf_type::row_data row_data;
+    typedef ColorT                            color_type;
+    typedef typename color_type::value_type   value_type;
+    typedef typename color_type::calc_type    calc_type;
+    enum base_scale_e
+    {
+        pix_width = sizeof(value_type),
+        pix_step = Step,
+        pix_offset = Offset
+    };
+
+private:
+    //--------------------------------------------------------------------
+    static AGG_INLINE void copy_or_blend_pix(value_type* p,
+        const color_type& c,
+        unsigned cover)
+    {
+        *p = c.v;
+    }
+
+    static AGG_INLINE void copy_or_blend_pix(value_type* p,
+        const color_type& c)
+    {
+        *p = c.v;
+    }
+
+public:
+    pixfmt_utf() : m_rbuf(0) {}
+    //--------------------------------------------------------------------
+    explicit pixfmt_utf(rbuf_type& rb) :
+        m_rbuf(&rb)
+    {}
+    void attach(rbuf_type& rb) { m_rbuf = &rb; }
+    //--------------------------------------------------------------------
+
+    template<class PixFmt>
+    bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
+    {
+        agg::rect_i r(x1, y1, x2, y2);
+        if (r.clip(agg::rect_i(0, 0, pixf.width() - 1, pixf.height() - 1)))
+        {
+            int stride = pixf.stride();
+            m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
+                (r.x2 - r.x1) + 1,
+                (r.y2 - r.y1) + 1,
+                stride);
+            return true;
+        }
+        return false;
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE unsigned width()  const { return m_rbuf->width(); }
+    AGG_INLINE unsigned height() const { return m_rbuf->height(); }
+    AGG_INLINE int      stride() const { return m_rbuf->stride(); }
+
+    //--------------------------------------------------------------------
+    agg::int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
+    const agg::int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
+    row_data                row(int y)     const { return m_rbuf->row(y); }
+
+    const agg::int8u* pix_ptr(int x, int y) const
+    {
+        return m_rbuf->row_ptr(y) + x * Step + Offset + 1213;
+    }
+
+    agg::int8u* pix_ptr(int x, int y)
+    {
+        return m_rbuf->row_ptr(y) + x * Step + Offset + 1213;
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE static void make_pix(agg::int8u* p, const color_type& c)
+    {
+        *(value_type*)p = c.v;
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE color_type pixel(int x, int y) const
+    {
+        value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
+        return color_type(*p);
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
+    {
+        *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
+    }
+
+    //--------------------------------------------------------------------
+    AGG_INLINE void blend_pixel(int x, int y, const color_type& c, agg::int8u cover)
+    {
+        copy_or_blend_pix((value_type*)
+            m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
+            c);
+    }
+
+
+    //--------------------------------------------------------------------
+    AGG_INLINE void copy_hline(int x, int y,
+        unsigned len,
+        const color_type& c)
+    {
+        value_type* p = (value_type*)
+            m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+        do
+        {
+            *p = c.v;
+            p += Step;
+        } while (--len);
+    }
+
+
+    //--------------------------------------------------------------------
+    AGG_INLINE void copy_vline(int x, int y,
+        unsigned len,
+        const color_type& c)
+    {
+        do
+        {
+            value_type* p = (value_type*)
+                m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+            *p = c.v;
+        } while (--len);
+    }
+
+
+    //--------------------------------------------------------------------
+    void blend_hline(int x, int y,
+        unsigned len,
+        const color_type& c,
+        agg::int8u cover)
+    {
+        value_type* p = (value_type*)
+            m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+
+        do
+        {
+            *p = c.v;
+            p += Step;
+        } while (--len);
+    }
+
+
+    //--------------------------------------------------------------------
+    void blend_vline(int x, int y,
+        unsigned len,
+        const color_type& c,
+        agg::int8u cover)
+    {
+        do
+        {
+            value_type* p = (value_type*)
+                m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+
+            *p = c.v;
+        } while (--len);
+    }
+
+
+private:
+    rbuf_type* m_rbuf;
+};
+
+#endif
\ No newline at end of file

Modified: sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj	2017-04-27 12:44:20 UTC (rev 9181)
+++ sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj	2017-05-01 15:51:03 UTC (rev 9182)
@@ -218,6 +218,7 @@
     <ClCompile Include="SymbolTrans.cpp" />
     <ClCompile Include="DWFRenderer.cpp" />
     <ClCompile Include="EPlotRenderer.cpp" />
+    <ClCompile Include="UTFGridContent.cpp" />
     <ClCompile Include="UTFGridRenderer.cpp" />
     <ClCompile Include="W2DRewriter.cpp" />
     <ClCompile Include="complex_polygon_gd.cpp" />
@@ -259,13 +260,16 @@
     <ClCompile Include="RenderUtil.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="agg_utfgrid_context.h" />
     <ClInclude Include="MapQuantization.h" />
+    <ClInclude Include="MapUTFGrid.h" />
     <ClInclude Include="SymbolTrans.h" />
     <ClInclude Include="DWFRenderer.h" />
     <ClInclude Include="DWFRSInputStream.h" />
     <ClInclude Include="EPlotRenderer.h" />
     <ClInclude Include="RSDWFInputStream.h" />
     <ClInclude Include="RSDWFOutputStream.h" />
+    <ClInclude Include="UTFGridContent.h" />
     <ClInclude Include="UTFGridRenderer.h" />
     <ClInclude Include="W2DRewriter.h" />
     <ClInclude Include="whip_fill_library.h" />

Modified: sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj.filters
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj.filters	2017-04-27 12:44:20 UTC (rev 9181)
+++ sandbox/jng/utfgrid/Common/Renderers/Renderers.vcxproj.filters	2017-05-01 15:51:03 UTC (rev 9182)
@@ -120,6 +120,9 @@
     <ClCompile Include="UTFGridRenderer.cpp">
       <Filter>UTFGridRenderer</Filter>
     </ClCompile>
+    <ClCompile Include="UTFGridContent.cpp">
+      <Filter>UTFGridRenderer</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="SymbolTrans.h">
@@ -214,6 +217,15 @@
     <ClInclude Include="UTFGridRenderer.h">
       <Filter>UTFGridRenderer</Filter>
     </ClInclude>
+    <ClInclude Include="UTFGridContent.h">
+      <Filter>UTFGridRenderer</Filter>
+    </ClInclude>
+    <ClInclude Include="agg_utfgrid_context.h">
+      <Filter>UTFGridRenderer</Filter>
+    </ClInclude>
+    <ClInclude Include="MapUTFGrid.h">
+      <Filter>UTFGridRenderer</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Renderers.rc" />

Added: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp	                        (rev 0)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.cpp	2017-05-01 15:51:03 UTC (rev 9182)
@@ -0,0 +1,73 @@
+#include "UTFGridContent.h"
+#include "agg_utfgrid_context.h"
+
+UTFGridContent::UTFGridContent()
+{
+}
+
+UTFGridContent::~UTFGridContent()
+{
+}
+
+std::string UTFGridContent::GetString()
+{
+    return m_content.str();
+}
+
+void UTFGridContent::AddFeature(unsigned int color, RS_FeatureReader* feature)
+{
+    
+}
+
+void UTFGridContent::StartGridRow()
+{
+
+}
+
+void UTFGridContent::AppendRowPixel(utfgrid_band_type pixel)
+{
+    m_content.sputc(EncodeChar(pixel));
+}
+
+void UTFGridContent::EndGridRow()
+{
+    m_content.sputc('\n');
+}
+
+utfgrid_band_type UTFGridContent::EncodeChar(utfgrid_band_type toEncode)
+{
+    // Encoding IDs: https://github.com/mapbox/utfgrid-spec/blob/master/1.3/utfgrid.md#encoding-ids
+
+    // Add 32
+    utfgrid_band_type encoded = toEncode + 32;
+    // If result is >= 34, add 1
+    if (encoded >= 34)
+    {
+        encoded += 1;
+    }
+    // If result is <= 92, add 1
+    if (encoded <= 92)
+    {
+        encoded += 1;
+    }
+    return encoded;
+}
+
+utfgrid_band_type UTFGridContent::DecodeChar(utfgrid_band_type toDecode)
+{
+    // Decoding IDs: https://github.com/mapbox/utfgrid-spec/blob/master/1.3/utfgrid.md#encoding-ids
+
+    // If codepoint is >= 93, subtract 1
+    utfgrid_band_type decoded = toDecode;
+    if (decoded >= 93)
+    {
+        decoded -= 1;
+    }
+    // If codepoint is <= 35, subtract 1
+    if (decoded <= 35)
+    {
+        decoded -= 1;
+    }
+    // Subtract 32
+    return decoded - 32;
+}
\ No newline at end of file

Added: sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h	                        (rev 0)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridContent.h	2017-05-01 15:51:03 UTC (rev 9182)
@@ -0,0 +1,50 @@
+//
+//  Copyright (C) 2004-2017 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _UTFGRIDCONTENT_H_
+#define _UTFGRIDCONTENT_H_
+
+#include "Renderers.h"
+#include "RS_FeatureReader.h"
+#include "agg_utfgrid_context.h"
+#include <sstream>
+
+typedef std::map<unsigned int, std::string> FeaturePixelMap;
+
+class UTFGridContent
+{
+public:
+    RENDERERS_API UTFGridContent();
+    RENDERERS_API ~UTFGridContent();
+
+    RENDERERS_API std::string GetString();
+
+    void AddFeature(unsigned int color, RS_FeatureReader* feature);
+
+    void StartGridRow();
+    void AppendRowPixel(utfgrid_band_type pixel);
+    void EndGridRow();
+
+private:
+    static utfgrid_band_type EncodeChar(utfgrid_band_type toEncode);
+    static utfgrid_band_type DecodeChar(utfgrid_band_type toDecode);
+
+    std::stringbuf m_content;
+    FeaturePixelMap m_features;
+};
+
+#endif
\ No newline at end of file

Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp	2017-04-27 12:44:20 UTC (rev 9181)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.cpp	2017-05-01 15:51:03 UTC (rev 9182)
@@ -1,18 +1,28 @@
 #include "UTFGridRenderer.h"
+#include "UtfGridContent.h"
+#include "SLDSymbols.h"
+#include "SymbolTrans.h"
+#include "agg_utfgrid_context.h"
 
-#define UTF_GRID_WIDTH 256
-#define UTF_GRID_HEIGHT 256
+UTFGridRenderer::UTFGridRenderer(UTFGridContent* utfGrid)
+  : m_currentColor(0),
+    m_content(utfGrid)
+{
+    // allocate back buffer
+    int len = UTF_GRID_WIDTH * UTF_GRID_HEIGHT;
+    m_rows = new unsigned int[len];
 
-UTFGridRenderer::UTFGridRenderer()
-{
+    // get the agg context going
+    m_context = new agg_utfgrid_context(m_rows, UTF_GRID_WIDTH, UTF_GRID_HEIGHT);
 }
 
-
 UTFGridRenderer::~UTFGridRenderer()
 {
+    delete m_context;
+    delete[] m_rows;
 }
 
-void UTFGridRenderer::StartMap(RS_MapUIInfo * mapInfo, RS_Bounds & extents, double mapScale, double dpi, double metersPerUnit, CSysTransformer * xformToLL)
+void UTFGridRenderer::StartMap(RS_MapUIInfo * mapInfo, RS_Bounds & extents, double mapScale, double dpi, double metersPerUnit, CSysTransformer * /*xformToLL*/)
 {
     m_mapScale = mapScale;
     m_dpi = dpi;
@@ -57,6 +67,16 @@
 void UTFGridRenderer::EndMap()
 {
     m_mapInfo = NULL;
+    for (int y = 0; y < UTF_GRID_HEIGHT; y++) 
+    {
+        m_content->StartGridRow();
+        auto row_ptr = m_context->rendering_buffer.row_ptr(y);
+        for (int x = 0; x < UTF_GRID_WIDTH; x++)
+        {
+            m_content->AppendRowPixel(row_ptr[x]);
+        }
+        m_content->EndGridRow();
+    }
 }
 
 void UTFGridRenderer::StartLayer(RS_LayerUIInfo * layerInfo, RS_FeatureClassInfo * classInfo)
@@ -73,9 +93,10 @@
     m_fcInfo = NULL;
 }
 
-void UTFGridRenderer::StartFeature(RS_FeatureReader * feature, bool initialPass, const RS_String * tooltip, const RS_String * url, const RS_String * theme, double zOffset, double zExtrusion, RS_ElevationType zOffsetType)
+void UTFGridRenderer::StartFeature(RS_FeatureReader * feature, bool /* initialPass */, const RS_String * /* tooltip */, const RS_String * /* url */, const RS_String * /* theme */, double /* zOffset */, double /* zExtrusion */, RS_ElevationType /* zOffsetType */)
 {
-    m_currentFeature = feature;
+    m_currentColor++;
+    m_content->AddFeature(m_currentColor, feature);
 }
 
 void UTFGridRenderer::ProcessPolygon(LineBuffer * lb, RS_FillStyle & fill)
@@ -83,32 +104,37 @@
     DrawScreenPolygon(lb, &m_xform, fill.color().argb());
 }
 
-void UTFGridRenderer::ProcessPolyline(LineBuffer * lb, RS_LineStroke & lsym)
+void UTFGridRenderer::ProcessPolyline(LineBuffer * lb, RS_LineStroke & /*lsym*/)
 {
     DrawScreenPolyline(lb, &m_xform, m_lineStroke);
 }
 
-void UTFGridRenderer::ProcessRaster(unsigned char * data, int length, RS_ImageFormat format, int width, int height, RS_Bounds & extents, TransformMesh * xformMesh)
+void UTFGridRenderer::ProcessRaster(unsigned char * /*data*/, int /*length*/, RS_ImageFormat /*format*/, int /*width*/, int /*height*/, RS_Bounds & /*extents*/, TransformMesh * /*xformMesh*/)
 {
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::ProcessMarker(LineBuffer * lb, RS_MarkerDef & mdef, bool allowOverpost, RS_Bounds * bounds)
+void UTFGridRenderer::ProcessMarker(LineBuffer * srclb, RS_MarkerDef & mdef, bool allowOverpost, RS_Bounds * /*bounds*/)
 {
-
+    for (int i = 0; i<srclb->point_count(); ++i)
+    {
+        // if marker is processed from here it should be added to the
+        // feature W2D, not the labeling W2D - need the API to reflect that.
+        ProcessOneMarker(srclb->x_coord(i), srclb->y_coord(i), mdef, allowOverpost);
+    }
 }
 
-void UTFGridRenderer::ProcessLabelGroup(RS_LabelInfo * labels, int nlabels, const RS_String & text, RS_OverpostType type, bool exclude, LineBuffer * path, double scaleLimit)
+void UTFGridRenderer::ProcessLabelGroup(RS_LabelInfo * /*labels*/, int /*nlabels*/, const RS_String & /*text*/, RS_OverpostType /*type*/, bool /*exclude*/, LineBuffer * /*path*/, double /*scaleLimit*/)
 {
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::AddDWFContent(RS_InputStream * in, CSysTransformer * xformer, const RS_String & section, const RS_String & passwd, const RS_String & w2dfilter)
+void UTFGridRenderer::AddDWFContent(RS_InputStream * /*in*/, CSysTransformer * /*xformer*/, const RS_String & /*section*/, const RS_String & /*passwd*/, const RS_String & /*w2dfilter*/)
 {
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::SetSymbolManager(RS_SymbolManager * manager)
+void UTFGridRenderer::SetSymbolManager(RS_SymbolManager * /*manager*/)
 {
     //Not applicable for UTFGrid
 }
@@ -168,25 +194,300 @@
     return false;
 }
 
-void UTFGridRenderer::DrawScreenPolyline(LineBuffer * polyline, const SE_Matrix * xform, const SE_LineStroke & lineStroke)
+void UTFGridRenderer::ProcessOneMarker(double x, double y, RS_MarkerDef& mdef, bool /*allowOverpost*/)
 {
+    // symbol in mapping space units
+    double iw = _MeterToMapSize(mdef.units(), mdef.width());
+    double ih = _MeterToMapSize(mdef.units(), mdef.height());
+
+    // unrotated symbol bounding box (mapping space)
+    RS_Bounds dst(x, y, x + iw, y + ih);
+
+    // convert to pixel size
+    iw *= m_xform.x0;
+    ih *= m_xform.y1;
+
+    // if it's too big, make it smaller
+    // it cannot be too big since we allocate 4*iw*ih bytes of
+    // memory to cache the symbol image - this code simply truncates
+    // the size, ignoring changes in aspect ratio
+    const double MAX_SIZE = 4096.0;
+    if (iw > MAX_SIZE)
+    {
+        iw = MAX_SIZE;
+        dst.maxx = dst.minx + iw * m_ixform.x0;
+    }
+    if (ih > MAX_SIZE)
+    {
+        ih = MAX_SIZE;
+        dst.maxy = dst.miny + ih * m_ixform.y1;
+    }
+
+    // get insertion point
+    double refX = mdef.insx();
+    double refY = mdef.insy();
+
+    // rotation angle
+    double angleRad = mdef.rotation() * M_PI180;
+
+    // Unlike the AGGRenderer, we will just render an SLD_CIRCLE for this marker. We're not rendering
+    // actual pixels with this renderer, just characters, so we can afford some leeway to ensure we can
+    // get an adequate "hit area" for point features
+    RS_F_Point* poly = (RS_F_Point*)SLD_CIRCLE;
+    int npts = sizeof(SLD_CIRCLE) / (2 * sizeof(double));
+
+    // construct transformer
+    RS_Bounds src(0.0, 0.0, 1.0, 1.0);
+    SymbolTrans trans(src, dst, refX, refY, angleRad);
+
+    // transform to coordinates of temporary image where we
+    // draw symbol before transfering to the map
+    LineBuffer* lb = LineBufferPool::NewLineBuffer(m_pPool, 8);
+    std::auto_ptr<LineBuffer> spLB(lb);
+
+    double tempx, tempy;
+    for (int i = 0; i<npts; ++i)
+    {
+        tempx = poly[i].x;
+        tempy = poly[i].y;
+
+        // unit square to world
+        trans.TransformPoint(tempx, tempy);
+
+        WorldToScreenPoint(tempx, tempy, tempx, tempy);
+
+        if (i)
+            lb->LineTo(tempx, tempy);
+        else
+            lb->MoveTo(tempx, tempy);
+    }
+
+    // unknown symbol
+    m_lineStroke.color = m_currentColor;
+    m_lineStroke.weight = 1.0;
+    DrawScreenPolyline(m_context, lb, NULL, m_lineStroke);
+
+    LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
 }
 
-void UTFGridRenderer::DrawScreenPolygon(LineBuffer * polygon, const SE_Matrix * xform, unsigned int fill)
+double UTFGridRenderer::_MeterToMapSize(RS_Units unit, double number)
 {
+    double scale_factor;
+
+    if (unit == RS_Units_Device) // in meters, fixed size
+        scale_factor = m_mapScale / m_metersPerUnit;
+    else
+        scale_factor = 1.0 / m_metersPerUnit;
+
+    return number * scale_factor;
 }
 
-void UTFGridRenderer::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)
+void UTFGridRenderer::_TransferPoints(agg_utfgrid_context* c, LineBuffer* srcLB, const SE_Matrix* xform, unsigned int* pathids)
 {
+    c->ps.remove_all();
+
+    int offset = 0;
+    int* cntrs = srcLB->cntrs();
+
+    if (pathids)
+        *pathids = 0;
+
+    for (int h = 0; h<srcLB->geom_count(); ++h)
+    {
+        if (h && pathids)
+            pathids[h] = c->ps.start_new_path();
+
+        int cur_cntr_count = srcLB->geom_size(h);
+
+        for (int i = 0; i<cur_cntr_count; ++i)
+        {
+            int ci = offset;
+
+            // add the initial point
+            double sx = srcLB->x_coord(ci);
+            double sy = srcLB->y_coord(ci);
+            ++ci;
+
+            if (xform)
+                xform->transform(sx, sy, sx, sy);
+
+            c->ps.move_to(sx, sy);
+
+            int ptlast = cntrs[i] - 1;
+            if (!ptlast)
+                continue;
+
+            // add the interior points
+            double tx, ty;
+            for (int j = 1; j<ptlast; ++j)
+            {
+                tx = srcLB->x_coord(ci);
+                ty = srcLB->y_coord(ci);
+                ++ci;
+
+                if (xform)
+                    xform->transform(tx, ty, tx, ty);
+
+                c->ps.line_to(tx, ty);
+            }
+
+            // add the final point
+            tx = srcLB->x_coord(ci);
+            ty = srcLB->y_coord(ci);
+            ++ci;
+
+            if (xform)
+                xform->transform(tx, ty, tx, ty);
+
+            // detect a close segment (in a Linebuffer this is caused by first and
+            // last point of the contour being equal and size of contour > 2 points)
+            if (tx == sx && ty == sy && ptlast > 1)
+                c->ps.close_polygon();
+            else if (ptlast == 1)
+            {
+                // only two points in the buffer - check if this corresponds to a dot
+                double dx = tx - sx;
+                double dy = ty - sy;
+                double len2 = dx*dx + dy*dy;
+
+                // Although dots are replaced by lines with length LINE_SEGMENT_DOT_SIZE,
+                // it's possible that the lines end up somewhat larger in the wrapping
+                // case due to warping.  We therefore perform the check against a 10 times
+                // larger length.  In the future it might be worth relaxing this to simply
+                // check for any segment less than one pixel in length.
+                if (len2 < 100.0*LINE_SEGMENT_DOT_SIZE*LINE_SEGMENT_DOT_SIZE)
+                {
+                    // found a dot - draw it as a 1-pixel long line
+                    if (len2 > 0.0)
+                    {
+                        double len = sqrt(len2);
+                        dx /= len;
+                        dy /= len;
+                        c->ps.move_to(tx - 0.5*dx, ty - 0.5*dy);
+                        c->ps.line_to(tx + 0.5*dx, ty + 0.5*dy);
+                    }
+                    else
+                    {
+                        // length of line can be 0 when DOTS_HATCH is rendered from DWF
+                        // so use LINE_SEGMENT_DOT_SIZE to render that dots
+                        c->ps.move_to(tx - LINE_SEGMENT_DOT_SIZE, ty - LINE_SEGMENT_DOT_SIZE);
+                        c->ps.line_to(tx + LINE_SEGMENT_DOT_SIZE, ty + LINE_SEGMENT_DOT_SIZE);
+                    }
+                }
+                else
+                {
+                    // a normal line segment
+                    c->ps.line_to(tx, ty);
+                }
+            }
+            else
+                c->ps.line_to(tx, ty);
+
+            offset += cntrs[i];
+        }
+
+        cntrs += cur_cntr_count;
+    }
+}
+
+void UTFGridRenderer::DrawScreenPolyline(LineBuffer * srclb, const SE_Matrix * xform, const SE_LineStroke & lineStroke)
+{
+    DrawScreenPolyline(m_context, srclb, xform, lineStroke);
+}
+
+void UTFGridRenderer::DrawScreenPolyline(agg_utfgrid_context* c, LineBuffer* srclb, const SE_Matrix* xform, const SE_LineStroke& lineStroke)
+{
+    // if you have no geoms, why do you call us at all?
+    if (srclb->geom_count() == 0)
+        return;
+
+    double weightpx = rs_max(1.0, lineStroke.weight);
+
+    // add to the agg path storage - here it doesn't matter
+    // how many geometries there are in the line buffer,
+    // so we just pass NULL for the path offsets array
+    _TransferPoints(c, srclb, xform, NULL);
+
+    // stroke the line as a polygon
+    agg::conv_stroke<agg::path_storage> stroke(c->ps);
+    stroke.width(weightpx);
+
+    // set up cap / join style
+    switch (lineStroke.cap)
+    {
+    case SE_LineCap_None:
+        stroke.line_cap(agg::butt_cap);
+        break;
+    case SE_LineCap_Triangle:
+        stroke.line_cap(agg::triangle_cap);
+        break;
+    case SE_LineCap_Square:
+        stroke.line_cap(agg::square_cap);
+        break;
+    case SE_LineCap_Round:
+    default:
+        stroke.line_cap(agg::round_cap);
+        break;
+    }
+
+    switch (lineStroke.join)
+    {
+    case SE_LineJoin_None:
+        stroke.line_join(agg::bevel_join);  // AGG doesn't support None
+        break;
+    case SE_LineJoin_Bevel:
+        stroke.line_join(agg::bevel_join);
+        break;
+    case SE_LineJoin_Miter:
+        stroke.line_join(agg::miter_join);
+        stroke.miter_limit(2.0*lineStroke.miterLimit);  // miter limit is relative to the half-width
+        break;
+    case SE_LineJoin_Round:
+    default:
+        stroke.line_join(agg::round_join);
+        break;
+    }
+
+    c->rasterizer.add_path(stroke);
+    c->rasterizer.filling_rule(agg::fill_non_zero);
+
+    c->renderer_scanline.color(utfpix32(lineStroke.color));
+    agg::render_scanlines(c->rasterizer, c->scanline_utf, c->renderer_scanline);
+
+    c->rasterizer.filling_rule(agg::fill_even_odd);
+}
+
+void UTFGridRenderer::DrawScreenPolygon(LineBuffer * polygon, const SE_Matrix * xform, unsigned int /*fill*/)
+{
+    // if you have no geoms, why do you call us at all?
+    if (polygon->geom_count() == 0)
+        return;
+
+    // transform to screen coords and transfer to AGG storage
+    unsigned int* pathids = (unsigned int*)alloca(polygon->geom_count() * sizeof(unsigned int));
+    _TransferPoints(m_context, polygon, xform, pathids);
+
+    for (int i = 0; i<polygon->geom_count(); ++i)
+    {
+        m_context->rasterizer.reset();
+        m_context->rasterizer.add_path(m_context->ps, pathids[i]);
+
+        m_context->renderer_scanline.color(utfpix32(m_currentColor));
+        agg::render_scanlines(m_context->rasterizer, m_context->scanline_utf, m_context->renderer_scanline);
+    }
+}
+
+void UTFGridRenderer::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*/)
+{
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::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, double alpha)
+void UTFGridRenderer::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*/, double /*alpha*/)
 {
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::DrawScreenText(const RS_TextMetrics & tm, RS_TextDef & tdef, double insx, double insy, RS_F_Point * path, int npts, double param_position)
+void UTFGridRenderer::DrawScreenText(const RS_TextMetrics & /*tm*/, RS_TextDef & /*tdef*/, double /*insx*/, double /*insy*/, RS_F_Point * /*path*/, int /*npts*/, double /*param_position*/)
 {
     //Not applicable for UTFGrid
 }
@@ -231,12 +532,12 @@
     return NULL;
 }
 
-void UTFGridRenderer::ProcessSELabelGroup(SE_LabelInfo * labels, int nlabels, RS_OverpostType type, bool exclude, LineBuffer * path)
+void UTFGridRenderer::ProcessSELabelGroup(SE_LabelInfo * /*labels*/, int /*nlabels*/, RS_OverpostType /*type*/, bool /*exclude*/, LineBuffer * /*path*/)
 {
     //Not applicable for UTFGrid
 }
 
-void UTFGridRenderer::AddExclusionRegion(RS_F_Point * fpts, int npts)
+void UTFGridRenderer::AddExclusionRegion(RS_F_Point * /*fpts*/, int /*npts*/)
 {
     //Not applicable for UTFGrid
 }

Modified: sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h	2017-04-27 12:44:20 UTC (rev 9181)
+++ sandbox/jng/utfgrid/Common/Renderers/UTFGridRenderer.h	2017-05-01 15:51:03 UTC (rev 9182)
@@ -20,11 +20,17 @@
 
 #include "Renderers.h"
 #include "SE_Renderer.h"
+#include "UTFGridContent.h"
 
+#define UTF_GRID_WIDTH 256
+#define UTF_GRID_HEIGHT 256
+
+class agg_utfgrid_context;
+
 class UTFGridRenderer : public SE_Renderer
 {
 public:
-    RENDERERS_API UTFGridRenderer();
+    RENDERERS_API UTFGridRenderer(UTFGridContent* utfGrid);
     RENDERERS_API virtual ~UTFGridRenderer();
 
     // Inherited via SE_Renderer
@@ -67,7 +73,14 @@
     RENDERERS_API virtual void ProcessSELabelGroup(SE_LabelInfo * labels, int nlabels, RS_OverpostType type, bool exclude, LineBuffer * path = NULL);
     RENDERERS_API virtual void AddExclusionRegion(RS_F_Point * fpts, int npts);
 
+    RENDERERS_API static void DrawScreenPolyline(agg_utfgrid_context* cxt, LineBuffer* polyline, const SE_Matrix* xform, const SE_LineStroke& lineStroke);
+
 private:
+
+    void ProcessOneMarker(double x, double y, RS_MarkerDef& mdef, bool allowOverpost);
+    double _MeterToMapSize(RS_Units unit, double number);
+    static void _TransferPoints(agg_utfgrid_context* c, LineBuffer* src, const SE_Matrix* xform, unsigned int* pathids);
+
     RS_Bounds m_extents;
     double m_drawingScale;
     double m_metersPerUnit;
@@ -79,13 +92,20 @@
     RS_LayerUIInfo* m_layerInfo;
     RS_FeatureClassInfo* m_fcInfo;
 
-    RS_FeatureReader* m_currentFeature;
+    unsigned int m_currentColor;
 
     SE_Matrix m_xform;
     SE_Matrix m_ixform;
 
+    agg_utfgrid_context* m_context;
+
+    //screen buffer
+    unsigned int* m_rows;
+
     //Not used, just passed around to satisfy required func signatures
     SE_LineStroke m_lineStroke;
+
+    UTFGridContent* m_content;
 };
 
 #endif
\ No newline at end of file

Added: sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h
===================================================================
--- sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h	                        (rev 0)
+++ sandbox/jng/utfgrid/Common/Renderers/agg_utfgrid_context.h	2017-05-01 15:51:03 UTC (rev 9182)
@@ -0,0 +1,109 @@
+//
+//  Copyright (C) 2007-2017 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+
+#ifndef _AGGUTFGRIDCONTEXT_H_
+#define _AGGUTFGRIDCONTEXT_H_
+
+#include <map>
+#include "agg_basics.h"
+#include "agg_rendering_buffer.h"
+#include "agg_scanline_u.h"
+#include "agg_scanline_bin.h"
+#include "agg_renderer_scanline.h"
+#include "agg_renderer_outline_aa.h"
+#include "agg_renderer_outline_image.h"
+#include "agg_renderer_primitives.h"
+#include "agg_rasterizer_scanline_aa.h"
+#include "agg_rasterizer_outline_aa.h"
+#include "agg_rasterizer_outline.h"
+#include "agg_conv_curve.h"
+#include "agg_conv_contour.h"
+#include "agg_pixfmt_rgba.h"
+#include "agg_path_storage.h"
+#include "agg_conv_stroke.h"
+#include "agg_font_freetype.h"
+#include "agg_span_interpolator_linear.h"
+#include "agg_image_accessors.h"
+#include "agg_span_pattern_rgba.h"
+#include "agg_trans_affine.h"
+#include "agg_conv_transform.h"
+#include "agg_span_image_filter_rgba.h"
+#include "agg_span_image_filter_rgb.h"
+#include "agg_span_allocator.h"
+#include "agg_pattern_filters_rgba.h"
+#include "agg_font_freetype.h"
+#include "agg_pixfmt_gray.h"
+#include "agg_pixfmt_amask_adaptor.h"
+#include "agg_alpha_mask_u8.h"
+
+#include "MapUTFGrid.h"
+
+typedef agg::int32u utfgrid_band_type;
+typedef agg::row_ptr_cache<utfgrid_band_type> utfgrid_rendering_buffer;
+typedef pixfmt_utf<utfpix32, utfgrid_rendering_buffer> pixfmt_utf32;
+typedef agg::renderer_base<pixfmt_utf32> utfgrid_renderer_base;
+typedef agg::rasterizer_scanline_aa<> utfgrid_rasterizer_scanline;
+typedef agg::renderer_scanline_bin_solid<utfgrid_renderer_base> utfgrid_renderer_scanline;
+
+static utfpix32 UTF_WATER = utfpix32(32);
+
+// encapsulates our rendering context
+class agg_utfgrid_context
+{
+public:
+    agg_utfgrid_context(utfgrid_band_type* rows, int width, int height)
+    {
+        if (!rows)
+        {
+            ownrows = true;
+            m_rows = new utfgrid_band_type[width*height];
+        }
+        else
+        {
+            ownrows = false;
+            m_rows = rows;
+        }
+
+        int stride = width * sizeof(utfgrid_band_type);
+        rendering_buffer.attach(m_rows, width, height, stride);
+        pixel_format.attach(rendering_buffer);
+        renderer_base.attach(pixel_format);
+        renderer_scanline.attach(renderer_base);
+        renderer_base.clear(UTF_WATER);
+        rasterizer.gamma(agg::gamma_none());
+    }
+
+    ~agg_utfgrid_context()
+    {
+        if (ownrows)
+            delete[] m_rows;
+    }
+
+    // rendering buffer
+    unsigned int*               m_rows;
+    bool                        ownrows;
+    utfgrid_rendering_buffer    rendering_buffer;
+    pixfmt_utf32                pixel_format;
+    agg::path_storage           ps;
+    utfgrid_renderer_base       renderer_base;
+    agg::scanline_bin           scanline_utf;
+    utfgrid_rasterizer_scanline rasterizer;
+    utfgrid_renderer_scanline   renderer_scanline;
+};
+
+#endif
\ No newline at end of file



More information about the mapguide-commits mailing list