[mapguide-commits] r4544 - trunk/MgDev/Common/Renderers

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Jan 21 13:09:07 EST 2010


Author: stevedang
Date: 2010-01-21 13:09:05 -0500 (Thu, 21 Jan 2010)
New Revision: 4544

Modified:
   trunk/MgDev/Common/Renderers/AGGRenderer.cpp
   trunk/MgDev/Common/Renderers/Renderers.vcproj
   trunk/MgDev/Common/Renderers/agg_context.h
Log:
Fix #1249: Map with 50 base text layers consumes much Memory.

Submitted on behalf of Walt. Traian and I have reviewed the changes. With this fix, the MG Server performance has been remarkably improved.

Modified: trunk/MgDev/Common/Renderers/AGGRenderer.cpp
===================================================================
--- trunk/MgDev/Common/Renderers/AGGRenderer.cpp	2010-01-21 17:23:16 UTC (rev 4543)
+++ trunk/MgDev/Common/Renderers/AGGRenderer.cpp	2010-01-21 18:09:05 UTC (rev 4544)
@@ -1457,12 +1457,19 @@
     if (NULL == font)
         return;
 
-    // Don't draw the text if height > 16384 pixels, since memory usage when
-    // evaluating the glyphs will get too large.  16394 pixels should be
-    // more than enough (e.g. this allows 13" high text on a 1200dpi device).
+    // Don't draw the text if height > 16384 pixels, since performance will be
+    // poor.  16394 pixels should be more than enough (e.g. this allows 13" high
+    // text on a 1200dpi device).
     if (height > 16384.0)
         return;
 
+    // For the best performance we want to cache images of glyphs as much as
+    // possible.  But when the font height gets large the memory size of the
+    // cached images starts to become an issue, especially if many different
+    // glyphs get cached.  So when height > 1024 switch to caching glyph outlines,
+    // since memory use is then independent of height (at least for scalable fonts).
+    agg::glyph_rendering glyph_type = (height > 1024.0)? agg::glyph_ren_outline : agg::glyph_ren_agg_gray8;
+
     bool font_changed = false;
     if (cxt->last_font != font)
     {
@@ -1473,24 +1480,36 @@
         DWFCore::DWFString::EncodeUTF8(font->m_filename.c_str(), lenf * sizeof(wchar_t), futf8, lenbytesf);
 
         // load the font
-        bool res = cxt->feng.load_font(futf8, 0, agg::glyph_ren_agg_gray8);
+        bool res = cxt->feng.load_font(futf8, 0, glyph_type);
         cxt->feng.char_map(FT_ENCODING_UNICODE);
 
         if (!res)
             return;
 
         cxt->last_font = font;
+        cxt->last_glyph_type = glyph_type;
         font_changed = true;
     }
+    else if (cxt->last_glyph_type != glyph_type)
+    {
+        // reload the font using the new glyph caching type - since the
+        // font was previously loaded this call is fast
+        bool res = cxt->feng.load_font(cxt->feng.name(), 0, glyph_type);
+//      cxt->feng.char_map(FT_ENCODING_UNICODE); // this should not be necessary
 
+        if (!res)
+            return;
+
+        cxt->last_glyph_type = glyph_type;
+//      font_changed = true; // this should not be necessary
+    }
+
     if (font_changed || cxt->last_font_height != height)
     {
         cxt->feng.height(height);
         cxt->last_font_height = height;
     }
 
-//  double width = cxt->feng.width();
-
     agg::trans_affine mtx;
     mtx *= agg::trans_affine_rotation(angleRad);
 //  mtx *= agg::trans_affine_skewing(-0.4, 0);
@@ -1516,18 +1535,43 @@
 #endif
 
     unsigned int* p = text;
-    while (*p)
+    if (glyph_type == agg::glyph_ren_agg_gray8)
     {
-        const agg::glyph_cache* glyph = cxt->fman.glyph(*p++);
+        while (*p)
+        {
+            const agg::glyph_cache* glyph = cxt->fman.glyph(*p++);
+            cxt->fman.add_kerning(&x, &y);
+            cxt->fman.init_embedded_adaptors(glyph, x, y);
 
-        cxt->fman.add_kerning(&x, &y);
+            agg::render_scanlines(cxt->fman.gray8_adaptor(), cxt->fman.gray8_scanline(), ren_aa_solid);
 
-        cxt->fman.init_embedded_adaptors(glyph, x, y);
+            x += glyph->advance_x;
+            y += glyph->advance_y;
+        }
+    }
+    else
+    {
+        font_curve_type curves(cxt->fman.path_adaptor());
+        font_contour_type contour(curves);
 
-        agg::render_scanlines(cxt->fman.gray8_adaptor(), cxt->fman.gray8_scanline(), ren_aa_solid);
+        cxt->ras.filling_rule(agg::fill_non_zero);
 
-        x += glyph->advance_x;
-        y += glyph->advance_y;
+        while (*p)
+        {
+            const agg::glyph_cache* glyph = cxt->fman.glyph(*p++);
+            cxt->fman.add_kerning(&x, &y);
+            cxt->fman.init_embedded_adaptors(glyph, x, y);
+
+            cxt->ras.reset();
+            cxt->ras.add_path(contour);
+
+            agg::render_scanlines(cxt->ras, cxt->sl, ren_aa_solid);
+
+            x += glyph->advance_x;
+            y += glyph->advance_y;
+        }
+
+        cxt->ras.filling_rule(agg::fill_even_odd);
     }
 }
 
@@ -1540,9 +1584,10 @@
                                 RS_F_Point*      res,       // assumes length equals 4 points
                                 float*           offsets)   // assumes length equals length of string
 {
-    // If the supplied font height is too large AGG will run out of memory.  We'll
-    // use a reasonable font height for measuring, and then scale the result.
-    double measureHeight = rs_min(5000.0, height);
+    // If the supplied font height is too large AGG will run out of memory
+    // when it tries to cache images of the glyphs.  So restrict the height
+    // to 1024 for measuring, and then scale the result if necessary.
+    double measureHeight = rs_min(1024.0, height);
     double measureScale = height / measureHeight;
 
     // load the font
@@ -1562,6 +1607,7 @@
             return;
 
         c()->last_font = font;
+        c()->last_glyph_type = agg::glyph_ren_agg_gray8;
         font_changed = true;
     }
 
@@ -1579,8 +1625,6 @@
         c()->last_font_height = measureHeight;
     }
 
-//  double width = c()->feng.width();
-
     // Do any BIDI conversion.  If the offset array is supplied (i.e. for path
     // text) then assume the conversion was already performed on the input string.
     const RS_String* pStrToUse;

Modified: trunk/MgDev/Common/Renderers/Renderers.vcproj
===================================================================
--- trunk/MgDev/Common/Renderers/Renderers.vcproj	2010-01-21 17:23:16 UTC (rev 4543)
+++ trunk/MgDev/Common/Renderers/Renderers.vcproj	2010-01-21 18:09:05 UTC (rev 4544)
@@ -639,6 +639,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\Oem\agg-2.4\src\agg_vcgen_contour.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\Oem\agg-2.4\src\agg_vcgen_stroke.cpp"
 				>
 			</File>

Modified: trunk/MgDev/Common/Renderers/agg_context.h
===================================================================
--- trunk/MgDev/Common/Renderers/agg_context.h	2010-01-21 17:23:16 UTC (rev 4543)
+++ trunk/MgDev/Common/Renderers/agg_context.h	2010-01-21 18:09:05 UTC (rev 4544)
@@ -90,6 +90,8 @@
 // font types
 typedef agg::font_engine_freetype_int32                                 font_engine_type;
 typedef agg::font_cache_manager<font_engine_type>                       font_manager_type;
+typedef agg::conv_curve<font_manager_type::path_adaptor_type>           font_curve_type;
+typedef agg::conv_contour<font_curve_type>                              font_contour_type;
 
 // alpha mask pixel format
 typedef agg::renderer_base<agg::pixfmt_gray8>                           mg_alpha_mask_rb_type;
@@ -137,6 +139,7 @@
         feng.transform(agg::trans_affine());
         last_font_height = 0.0;
         last_font = NULL;
+        last_glyph_type = agg::glyph_ren_agg_gray8;
 
         // polygon clip buffer
         bPolyClip = false;
@@ -197,6 +200,7 @@
     double last_font_height;
     const RS_Font* last_font;
     agg::trans_affine last_font_transform;
+    agg::glyph_rendering last_glyph_type;
 };
 
 #endif



More information about the mapguide-commits mailing list