[mapguide-internals] CSS sprited legend images - RFC

Paul Spencer pspencer at dmsolutions.ca
Tue Jan 11 08:26:19 EST 2011

I don't think legend performance is strictly an issue of legend images since the tree implementation via Jx or Fusion's use of it is also likely to cause problems when dealing with large numbers of layers.  I thought we had done some work to improve that in the latest version of Jx and Fusion but that may not be in the regular distributions yet.   Mike can say better where that stuff is in the queue.

On the sprited image thing, there are actually two pieces to legend icons on the mapserver side that are somewhat relevant.

1) fusion/Layers/MapServer/php/LegendIcon.php

this is the non-sprited case for mapserver layers, they call this php script as the src for the legend icon image.  If you take a look, you'll see that we went to some effort to cache legend icons and provide cache control headers for browsers to improve performance on *subsequent* visits - meaning that the initial load for a new client or after a change to the map file is still heavy and only improves with  reloads or with new clients connecting (getting the disk-cached copy vs having to build it).

It appears that for mapguide we use the GETLEGENDIMAGE operation.  I'm not sure what the internals of this operation do, I suspect they cache per session/mapdefinition but perhaps they cache across sessions?

2) fusion/Layers/MapServer/php/LoadScaleRanges.php

The primary purpose of this file is to build a JSON object representing the layers and scale breaks to guide the legend's behaviour as the user zooms and pans.  However, around line 164 we have added code to build a sprited image of legend icons and the associated offsets.  Of note, the output JSON includes

* a layers array that has, for each layer, a set of scale ranges and for each scale range, icon_x and icon_y offsets inside the sprited image

* an icons_url property that points to where the sprited image can be loaded from

* icons_width and icons_height properties giving the size of an individual icon.

I believe that if the result of LoadScaleRanges.php includes these things (icon_x and icon_y per style and icons_url) then Legend.js will generically just work with the sprited image.

For mapguide, there is a LoadScaleRanges.php file but it just returns something from the php session, the real work actually happens over in LoadMap.php specifically in the buildScaleRanges function.  This is where modifications would be needed to indicate support for sprited legend images by including icon_x and icon_y properties in each styleObj that gets saved.  

Also in LoadScaleRanges.php, the returned JSON could need to be modified to include the icons_url, icons_width and icons_height properties.

So I guess there would need to be some method or function in mapguide that would iterate over all the layers in a Map and over each of the scale ranges and build a sprited image and also return the offset (x and y) of each.

Note that the current design of this only supports icons that all have the same size.  If we ever needed to support different sized icons for different layers/scale ranges then it would require quite a large overall not only of the backend but also the tree code.

Also note that the generic code should work for dynamically added layers as the fallback would be to use the GETLEGENDIMAGE operation for layers that don't have the icon_x and icon_y properties.

There may also be some piece of magic required in MapGuide.js to make this work.  I can't see anything in MapServer.js that indicates this, it should just work if the correct metadata is provided in the return from LoadScaleRanges.php - but I've thought that before :)  If someone can get to the point where MapGuide's LoadScaleRanges.php returns the correct metadata and it doesn't Just Work (tm) then it shouldn't be too difficult to get it working.

I hope this helps get things in perspective.  It wasn't that hard to make it work for MapServer but the php api is a lot simpler ... mapguide was, IIRC, somewhat opaque on the whole legend icon thing.  The logic could perhaps be ported almost directly if there was a method on a layer to generate a legend icon at a given size for a given scale but that wasn't there when I worked on this.  Oh and there is also the problem of compositing the images together into a single strip.  We (ab)used mapserver's image methods for this so we didn't need to save them to disk in order to use the GD api.  Not sure where things stand with mapguide and an api for manipulating images in this way.



On 2011-01-11, at 7:23 AM, Zac Spitzer wrote:

> this post got a bit lost in discussion,
> the ajax viewer performs better because it only renders a subset of
> large legends,
> abbreviating them [ .... ] fusion tries to render them all and ends up
> DOSing the browser
> CSS sprites for the legend is sorely needed
> What's the technical requirements?
> GetLegendImageStrip
> GetLegendCSS
> Proper http cache semantics for those operations
> cached in the session repo? generated when requested,
> cache invalidated after changes to the run time map,
> but only after re-rendering and comparison of new and old
> has changes
> z
> ---------- Forwarded message ----------
> From: Jason Birch <Jason.Birch at nanaimo.ca>
> Date: Sat, Apr 4, 2009 at 9:03 AM
> Subject: [fusion-dev] RE: [mapguide-users] Fusion and Themed Layers - usability
> To: "mapguide-users at lists.osgeo.org" <mapguide-users at lists.osgeo.org>
> Cc: "fusion-dev at lists.osgeo.org" <fusion-dev at lists.osgeo.org>,
> 'MapGuide at lists.osgeo.org, Internals Mail List'
> <mapguide-internals at lists.osgeo.org>
> Heh,
> Yeah, I can see how that would be unmanageable.  I wouldn't be
> surprised if your use case strains fusion to the level that it's not
> workable for the current version or for 2.1.  I'm surprised it works
> with the AJAX viewer, but maybe the viewer has a different strategy
> for managing legend images.
> Ideally, MapGuide would support a GetLegendImageStrip operation that
> Fusion could then use with CSS sprites to reduce (in your case,
> dramatically) the number of requests to the server.  I believe that
> there may be functionality for this in MapServer layer types in Fusion
> 2.0, but I don't think there is in MapGuide.  Bob Bray put in a ticket
> for this functionality a _long_ time ago, but unfortunately I don't
> think any work has been done on it:
> http://trac.osgeo.org/mapguide/ticket/22
> I think that there is a partial measure that could be done in Fusion
> to improve the situation somewhat.  Currently, Fusion does a
> reasonable job of caching images; it only requests a new legend image
> once per scale range context switch.  However, the initial request is
> done using the exact current scale.  If the request instead used a
> fixed value within the scale range (bottom + x?) then the images could
> be better cached by the browser.  If MapGuide sent cache headers (last
> modified, based on the layer definition?) this would also help.
> Any Fusion or MapGuide devs have thoughts on this?
> Jason
> _______________________________________________
> mapguide-users mailing list
> mapguide-users at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/mapguide-users
> _______________________________________________
> fusion-dev mailing list
> fusion-dev at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/fusion-dev
> -- 
> Zac Spitzer
> Solution Architect / Director
> Ennoble Consultancy Australia
> http://www.ennoble.com.au
> http://zacster.blogspot.com
> +61 405 847 168
> _______________________________________________
> mapguide-internals mailing list
> mapguide-internals at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/mapguide-internals


   Paul Spencer
   Chief Technology Officer
   DM Solutions Group Inc

More information about the mapguide-internals mailing list